Merge branch 'develop' into mkjs-n

This commit is contained in:
tamaina
2023-05-21 12:11:22 +00:00
36 changed files with 255 additions and 304 deletions

View File

@@ -397,6 +397,7 @@ function toStories(component: string): string {
Promise.all([
glob('src/components/global/*.vue'),
glob('src/components/Mk{A,B}*.vue'),
glob('src/components/MkDigitalClock.vue'),
glob('src/components/MkGalleryPostPreview.vue'),
glob('src/components/MkSignupServerRules.vue'),
glob('src/components/MkUserSetupDialog.vue'),

View File

@@ -16,7 +16,7 @@ import { initializeSw } from '@/scripts/initialize-sw';
export async function mainBoot() {
const { isClientUpdated } = await common(() => createApp(
new URLSearchParams(window.location.search).has('zen') ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
new URLSearchParams(window.location.search).has('zen') || (ui === 'deck' && location.pathname !== '/') ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import isChromatic from 'chromatic/isChromatic';
import MkAnalogClock from './MkAnalogClock.vue';
import isChromatic from 'chromatic';
export const Default = {
render(args) {
return {

View File

@@ -39,6 +39,7 @@
-->
<line
ref="sLine"
:class="[$style.s, { [$style.animate]: !disableSAnimate && sAnimation !== 'none', [$style.elastic]: sAnimation === 'elastic', [$style.easeOut]: sAnimation === 'easeOut' }]"
:x1="5 - (0 * (sHandLengthRatio * handsTailLength))"
:y1="5 + (1 * (sHandLengthRatio * handsTailLength))"
@@ -73,9 +74,10 @@
</template>
<script lang="ts" setup>
import { computed, onMounted, onBeforeUnmount } from 'vue';
import { computed, onMounted, onBeforeUnmount, ref } from 'vue';
import tinycolor from 'tinycolor2';
import { globalEvents } from '@/events.js';
import { defaultIdlingRenderScheduler } from '@/scripts/idle-render.js';
// https://stackoverflow.com/questions/1878907/how-can-i-find-the-difference-between-two-angles
const angleDiff = (a: number, b: number) => {
@@ -145,6 +147,7 @@ let mAngle = $ref<number>(0);
let sAngle = $ref<number>(0);
let disableSAnimate = $ref(false);
let sOneRound = false;
const sLine = ref<SVGPathElement>();
function tick() {
const now = props.now();
@@ -160,17 +163,21 @@ function tick() {
}
hAngle = Math.PI * (h % (props.twentyfour ? 24 : 12) + (m + s / 60) / 60) / (props.twentyfour ? 12 : 6);
mAngle = Math.PI * (m + s / 60) / 30;
if (sOneRound) { // 秒針が一周した際のアニメーションをよしなに処理する(これが無いと秒が59->0になったときに期待したアニメーションにならない)
if (sOneRound && sLine.value) { // 秒針が一周した際のアニメーションをよしなに処理する(これが無いと秒が59->0になったときに期待したアニメーションにならない)
sAngle = Math.PI * 60 / 30;
window.setTimeout(() => {
defaultIdlingRenderScheduler.delete(tick);
sLine.value.addEventListener('transitionend', () => {
disableSAnimate = true;
window.setTimeout(() => {
requestAnimationFrame(() => {
sAngle = 0;
window.setTimeout(() => {
requestAnimationFrame(() => {
disableSAnimate = false;
}, 100);
}, 100);
}, 700);
if (enabled) {
defaultIdlingRenderScheduler.add(tick);
}
});
});
}, { once: true });
} else {
sAngle = Math.PI * s / 30;
}
@@ -194,20 +201,13 @@ function calcColors() {
calcColors();
onMounted(() => {
const update = () => {
if (enabled) {
tick();
window.setTimeout(update, 1000);
}
};
update();
defaultIdlingRenderScheduler.add(tick);
globalEvents.on('themeChanged', calcColors);
});
onBeforeUnmount(() => {
enabled = false;
defaultIdlingRenderScheduler.delete(tick);
globalEvents.off('themeChanged', calcColors);
});
</script>

View File

@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import isChromatic from 'chromatic/isChromatic';
import MkDigitalClock from './MkDigitalClock.vue';
export const Default = {
render(args) {
return {
components: {
MkDigitalClock,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MkDigitalClock v-bind="props" />',
};
},
args: {
now: isChromatic() ? () => new Date('2023-01-01T10:10:30') : undefined,
},
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MkDigitalClock>;

View File

@@ -11,19 +11,21 @@
</template>
<script lang="ts" setup>
import { onUnmounted, ref, watch } from 'vue';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { defaultIdlingRenderScheduler } from '@/scripts/idle-render.js';
const props = withDefaults(defineProps<{
showS?: boolean;
showMs?: boolean;
offset?: number;
now?: () => Date;
}>(), {
showS: true,
showMs: false,
offset: 0 - new Date().getTimezoneOffset(),
now: () => new Date(),
});
let intervalId;
const hh = ref('');
const mm = ref('');
const ss = ref('');
@@ -39,9 +41,9 @@ watch(showColon, (v) => {
}
});
const tick = () => {
const now = new Date();
now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + props.offset));
const tick = (): void => {
const now = props.now();
now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + props.offset);
hh.value = now.getHours().toString().padStart(2, '0');
mm.value = now.getMinutes().toString().padStart(2, '0');
ss.value = now.getSeconds().toString().padStart(2, '0');
@@ -52,13 +54,12 @@ const tick = () => {
tick();
watch(() => props.showMs, () => {
if (intervalId) window.clearInterval(intervalId);
intervalId = window.setInterval(tick, props.showMs ? 10 : 1000);
}, { immediate: true });
onMounted(() => {
defaultIdlingRenderScheduler.add(tick);
});
onUnmounted(() => {
window.clearInterval(intervalId);
defaultIdlingRenderScheduler.delete(tick);
});
</script>

View File

@@ -58,7 +58,6 @@ function tick() {
if (props.mode === 'relative' || props.mode === 'detail') {
tick();
onUnmounted(() => {
window.clearTimeout(tickId);
});

View File

@@ -3,7 +3,7 @@
<MkStickyContainer>
<template #header><XHeader :actions="headerActions"/></template>
<MkSpacer :contentMax="900">
<div>
<div class="_gaps">
<div>
<MkInput v-model="host" :debounce="true" class="">
<template #prefix><i class="ti ti-search"></i></template>

View File

@@ -3,29 +3,27 @@
<MkStickyContainer>
<template #header><XHeader :actions="headerActions"/></template>
<MkSpacer :contentMax="900">
<div>
<div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.instance }}</template>
<option value="combined">{{ i18n.ts.all }}</option>
<option value="local">{{ i18n.ts.local }}</option>
<option value="remote">{{ i18n.ts.remote }}</option>
</MkSelect>
<MkInput v-model="searchHost" :debounce="true" type="search" style="margin: 0; flex: 1;" :disabled="pagination.params.origin === 'local'">
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
</div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap; padding-top: 1.2em;">
<MkInput v-model="userId" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>User ID</template>
</MkInput>
<MkInput v-model="type" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>MIME type</template>
</MkInput>
</div>
<MkFileListForAdmin :pagination="pagination" :viewMode="viewMode"/>
<div class="_gaps">
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.instance }}</template>
<option value="combined">{{ i18n.ts.all }}</option>
<option value="local">{{ i18n.ts.local }}</option>
<option value="remote">{{ i18n.ts.remote }}</option>
</MkSelect>
<MkInput v-model="searchHost" :debounce="true" type="search" style="margin: 0; flex: 1;" :disabled="pagination.params.origin === 'local'">
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
</div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkInput v-model="userId" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>User ID</template>
</MkInput>
<MkInput v-model="type" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>MIME type</template>
</MkInput>
</div>
<MkFileListForAdmin :pagination="pagination" :viewMode="viewMode"/>
</div>
</MkSpacer>
</MkStickyContainer>

View File

@@ -0,0 +1,38 @@
class IdlingRenderScheduler {
#renderers: Set<FrameRequestCallback>;
#rafId: number;
#ricId: number;
constructor() {
this.#renderers = new Set();
this.#rafId = 0;
this.#ricId = requestIdleCallback((deadline) => this.#schedule(deadline));
}
#schedule(deadline: IdleDeadline): void {
if (deadline.timeRemaining()) {
this.#rafId = requestAnimationFrame((time) => {
for (const renderer of this.#renderers) {
renderer(time);
}
});
}
this.#ricId = requestIdleCallback((arg) => this.#schedule(arg));
}
add(renderer: FrameRequestCallback): void {
this.#renderers.add(renderer);
}
delete(renderer: FrameRequestCallback): void {
this.#renderers.delete(renderer);
}
dispose(): void {
this.#renderers.clear();
cancelAnimationFrame(this.#rafId);
cancelIdleCallback(this.#ricId);
}
}
export const defaultIdlingRenderScheduler = new IdlingRenderScheduler();

View File

@@ -4,27 +4,23 @@
<div :class="$style.main">
<XStatusBars/>
<div ref="columnsEl" :class="[$style.columns, deckStore.reactiveState.columnAlign.value, { [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu">
<template v-for="ids in layout">
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-if="ids.length > 1"
:class="$style.folder"
:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
>
<DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :isStacked="true" @parentFocus="moveFocus(id, $event)"/>
</section>
<DeckColumnCore
v-else
:ref="ids[0]"
:key="ids[0]"
<div ref="columnsEl" :class="[$style.sections, deckStore.reactiveState.columnAlign.value, { [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu">
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-for="ids in layout"
:class="$style.section"
:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
>
<component
:is="columnComponents[columns.find(c => c.id === id)!.type] ?? XTlColumn"
v-for="id in ids"
:ref="id"
:key="id"
:class="$style.column"
:column="columns.find(c => c.id === ids[0])"
:isStacked="false"
:style="columns.find(c => c.id === ids[0])!.flexible ? { flex: 1, minWidth: '350px' } : { width: columns.find(c => c.id === ids[0])!.width + 'px' }"
@parentFocus="moveFocus(ids[0], $event)"
:column="columns.find(c => c.id === id)"
:isStacked="ids.length > 1"
/>
</template>
</section>
<div v-if="layout.length === 0" class="_panel" :class="$style.onboarding">
<div>{{ i18n.ts._deck.introduction }}</div>
<MkButton primary style="margin: 1em auto;" @click="addColumn">{{ i18n.ts._deck.addColumn }}</MkButton>
@@ -87,7 +83,6 @@ import { computed, defineAsyncComponent, ref, watch } from 'vue';
import { v4 as uuid } from 'uuid';
import XCommon from './_common_/common.vue';
import { deckStore, addColumn as addColumnToStore, loadDeck, getProfiles, deleteProfile as deleteProfile_ } from './deck/deck-store';
import DeckColumnCore from '@/ui/deck/column-core.vue';
import XSidebar from '@/ui/_common_/navbar.vue';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import MkButton from '@/components/MkButton.vue';
@@ -100,8 +95,31 @@ import { mainRouter } from '@/router';
import { unisonReload } from '@/scripts/unison-reload';
import { deviceKind } from '@/scripts/device-kind';
import { defaultStore } from '@/store';
import XMainColumn from '@/ui/deck/main-column.vue';
import XTlColumn from '@/ui/deck/tl-column.vue';
import XAntennaColumn from '@/ui/deck/antenna-column.vue';
import XListColumn from '@/ui/deck/list-column.vue';
import XChannelColumn from '@/ui/deck/channel-column.vue';
import XNotificationsColumn from '@/ui/deck/notifications-column.vue';
import XWidgetsColumn from '@/ui/deck/widgets-column.vue';
import XMentionsColumn from '@/ui/deck/mentions-column.vue';
import XDirectColumn from '@/ui/deck/direct-column.vue';
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
const columnComponents = {
main: XMainColumn,
widgets: XWidgetsColumn,
notifications: XNotificationsColumn,
tl: XTlColumn,
list: XListColumn,
channel: XChannelColumn,
antenna: XAntennaColumn,
mentions: XMentionsColumn,
direct: XDirectColumn,
roleTimeline: XRoleTimelineColumn,
};
mainRouter.navHook = (path, flag): boolean => {
if (flag === 'forcePage') return false;
const noMainColumn = !deckStore.state.columns.some(x => x.type === 'main');
@@ -187,11 +205,8 @@ window.addEventListener('wheel', (ev) => {
columnsEl.scrollLeft += ev.deltaY;
}
});
loadDeck();
function moveFocus(id: string, direction: 'up' | 'down' | 'left' | 'right') {
// TODO??
}
loadDeck();
function changeProfile(ev: MouseEvent) {
const items = ref([{
@@ -286,18 +301,18 @@ async function deleteProfile() {
flex-direction: column;
}
.columns {
.sections {
flex: 1;
display: flex;
overflow-x: auto;
overflow-y: clip;
&.center {
> .column:first-of-type {
> .section:first-of-type {
margin-left: auto;
}
> .column:last-of-type {
> .section:last-of-type {
margin-right: auto;
}
}
@@ -307,7 +322,9 @@ async function deleteProfile() {
}
}
.column {
.section {
display: flex;
flex-direction: column;
scroll-snap-align: start;
flex-shrink: 0;
border-right: solid var(--deckDividerThickness) var(--deckDivider);
@@ -315,14 +332,8 @@ async function deleteProfile() {
&:first-of-type {
border-left: solid var(--deckDividerThickness) var(--deckDivider);
}
}
.folder {
composes: column;
display: flex;
flex-direction: column;
> *:not(:last-of-type) {
> .column:not(:last-of-type) {
border-bottom: solid var(--deckDividerThickness) var(--deckDivider);
}
}

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-antenna"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-device-tv"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@@ -29,7 +29,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View File

@@ -1,38 +0,0 @@
<template>
<!-- TODO: リファクタの余地がありそう -->
<div v-if="!column">たぶん見えちゃいけないやつ</div>
<XMainColumn v-else-if="column.type === 'main'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XWidgetsColumn v-else-if="column.type === 'widgets'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XNotificationsColumn v-else-if="column.type === 'notifications'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XTlColumn v-else-if="column.type === 'tl'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XListColumn v-else-if="column.type === 'list'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XChannelColumn v-else-if="column.type === 'channel'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XAntennaColumn v-else-if="column.type === 'antenna'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XMentionsColumn v-else-if="column.type === 'mentions'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XDirectColumn v-else-if="column.type === 'direct'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XRoleTimelineColumn v-else-if="column.type === 'roleTimeline'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
</template>
<script lang="ts" setup>
import { } from 'vue';
import XMainColumn from './main-column.vue';
import XTlColumn from './tl-column.vue';
import XAntennaColumn from './antenna-column.vue';
import XListColumn from './list-column.vue';
import XChannelColumn from './channel-column.vue';
import XNotificationsColumn from './notifications-column.vue';
import XWidgetsColumn from './widgets-column.vue';
import XMentionsColumn from './mentions-column.vue';
import XDirectColumn from './direct-column.vue';
import XRoleTimelineColumn from './role-timeline-column.vue';
import { Column } from './deck-store';
defineProps<{
column?: Column;
isStacked: boolean;
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
</script>

View File

@@ -1,7 +1,5 @@
<template>
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-hotkey="keymap"
<div
:class="[$style.root, { [$style.paged]: isMainColumn, [$style.naked]: naked, [$style.active]: active, [$style.isStacked]: isStacked, [$style.draghover]: draghover, [$style.dragging]: dragging, [$style.dropready]: dropready }]"
@dragover.prevent.stop="onDragover"
@dragleave="onDragleave"
@@ -22,10 +20,10 @@
<span :class="$style.title"><slot name="header"></slot></span>
<button v-tooltip="i18n.ts.settings" :class="$style.menu" class="_button" @click.stop="showSettingsMenu"><i class="ti ti-dots"></i></button>
</header>
<div v-show="active" ref="body" :class="$style.body">
<div v-if="active" ref="body" :class="$style.body">
<slot></slot>
</div>
</section>
</div>
</template>
<script lang="ts" setup>
@@ -49,12 +47,7 @@ const props = withDefaults(defineProps<{
naked: false,
});
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
(ev: 'change-active-state', v: boolean): void;
}>();
let body = $shallowRef<HTMLDivElement>();
let body = $shallowRef<HTMLDivElement | null>();
let dragging = $ref(false);
watch($$(dragging), v => os.deckGlobalEvents.emit(v ? 'column.dragStart' : 'column.dragEnd'));
@@ -64,14 +57,6 @@ let dropready = $ref(false);
const isMainColumn = $computed(() => props.column.type === 'main');
const active = $computed(() => props.column.active !== false);
watch($$(active), v => emit('change-active-state', v));
const keymap = $computed(() => ({
'shift+up': () => emit('parent-focus', 'up'),
'shift+down': () => emit('parent-focus', 'down'),
'shift+left': () => emit('parent-focus', 'left'),
'shift+right': () => emit('parent-focus', 'right'),
}));
onMounted(() => {
os.deckGlobalEvents.on('column.dragStart', onOtherDragStart);
@@ -190,10 +175,12 @@ function onContextmenu(ev: MouseEvent) {
}
function goTop() {
body.scrollTo({
top: 0,
behavior: 'smooth',
});
if (body) {
body.scrollTo({
top: 0,
behavior: 'smooth',
});
}
}
function onDragstart(ev) {

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-mail" style="margin-right: 8px;"></i>{{ column.name }}</template>
<MkNotes :pagination="pagination"/>
@@ -18,7 +18,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
const pagination = {

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-list"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View File

@@ -1,5 +1,5 @@
<template>
<XColumn v-if="deckStore.state.alwaysShowMainColumn || mainRouter.currentRoute.value.name !== 'index'" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn v-if="deckStore.state.alwaysShowMainColumn || mainRouter.currentRoute.value.name !== 'index'" :column="column" :isStacked="isStacked">
<template #header>
<template v-if="pageMetadata?.value">
<i :class="pageMetadata?.value.icon"></i>
@@ -26,7 +26,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-at" style="margin-right: 8px;"></i>{{ column.name }}</template>
<MkNotes :pagination="pagination"/>
@@ -18,7 +18,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
const pagination = {

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" :menu="menu" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked" :menu="menu">
<template #header><i class="ti ti-bell" style="margin-right: 8px;"></i>{{ column.name }}</template>
<XNotifications :includeTypes="column.includingTypes"/>
@@ -20,7 +20,6 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
function func() {

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-badge"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i v-if="column.tl === 'home'" class="ti ti-home"></i>
<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i>
@@ -36,7 +36,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let disabled = $ref(false);

View File

@@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :naked="true" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :naked="true" :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-apps" style="margin-right: 8px;"></i>{{ column.name }}</template>
<div :class="$style.root">
@@ -22,7 +22,6 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let edit = $ref(false);