Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: カスタムディレクティブの型付け #298

Draft
wants to merge 1 commit into
base: taiyme
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/frontend/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,22 @@ initialize({
initLocalStorage();
queueMicrotask(() => {
Promise.all([
import('../src/components/index.js'),
import('../src/directives/index.js'),
import('../src/components/index.js'),
import('../src/widgets/index.js'),
import('../src/scripts/theme.js'),
import('../src/store.js'),
import('../src/os.js'),
]).then(([{ default: components }, { default: directives }, { default: widgets }, { applyTheme }, { defaultStore }, os]) => {
]).then(([{ default: directives }, { default: components }, { default: widgets }, { applyTheme }, { defaultStore }, os]) => {
setup((app) => {
moduleInitialized = true;
if (app[appInitialized]) {
return;
}
app[appInitialized] = true;
loadTheme(applyTheme);
components(app);
directives(app);
components(app);
widgets(app);
misskeyOS = os;
if (isChromatic()) {
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/boot/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import { computed, watch, version as vueVersion, App } from 'vue';
import { compareVersions } from 'compare-versions';
import { version, lang, updateLocale, locale, commitHash } from '@@/js/config.js';
import widgets from '@/widgets/index.js';
import directives from '@/directives/index.js';
import components from '@/components/index.js';
import widgets from '@/widgets/index.js';
import { applyTheme } from '@/scripts/theme.js';
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js';
import { updateI18n } from '@/i18n.js';
Expand Down Expand Up @@ -257,9 +257,9 @@ export async function common(createVue: () => App<Element>) {
app.config.performance = true;
}

widgets(app);
directives(app);
components(app);
widgets(app);

// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
// なぜか2回実行されることがあるため、mountするdivを1つに制限する
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkWidgets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import { v4 as uuid } from 'uuid';
import { isLink } from '@@/js/is-link.js';
import MkSelect from '@/components/MkSelect.vue';
import MkButton from '@/components/MkButton.vue';
import { widgets as widgetDefs } from '@/widgets/index.js';
import { widgetDefs } from '@/widgets/index.js';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';

Expand Down
108 changes: 54 additions & 54 deletions packages/frontend/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { App } from 'vue';
import type { App } from 'vue';

import Mfm from './global/MkMfm.js';
import MkA from './global/MkA.vue';
import MkAcct from './global/MkAcct.vue';
import MkAvatar from './global/MkAvatar.vue';
import MkEmoji from './global/MkEmoji.vue';
import MkCondensedLine from './global/MkCondensedLine.vue';
import MkCustomEmoji from './global/MkCustomEmoji.vue';
import MkUserName from './global/MkUserName.vue';
import MkEllipsis from './global/MkEllipsis.vue';
import MkTime from './global/MkTime.vue';
import MkUrl from './global/MkUrl.vue';
import I18n from './global/I18n.vue';
import RouterView from './global/RouterView.vue';
import MkLoading from './global/MkLoading.vue';
import MkError from './global/MkError.vue';
import MkAd from './global/MkAd.vue';
import MkPageHeader from './global/MkPageHeader.vue';
import MkSpacer from './global/MkSpacer.vue';
import MkFooterSpacer from './global/MkFooterSpacer.vue';
import MkStickyContainer from './global/MkStickyContainer.vue';
import MkLazy from './global/MkLazy.vue';
import TmsNoCache from './global/TmsNoCache.vue';
import I18n from '@/components/global/I18n.vue';
import RouterView from '@/components/global/RouterView.vue';
import Mfm from '@/components/global/MkMfm.js';
import MkA from '@/components/global/MkA.vue';
import MkAcct from '@/components/global/MkAcct.vue';
import MkAd from '@/components/global/MkAd.vue';
import MkAvatar from '@/components/global/MkAvatar.vue';
import MkCondensedLine from '@/components/global/MkCondensedLine.vue';
import MkCustomEmoji from '@/components/global/MkCustomEmoji.vue';
import MkEllipsis from '@/components/global/MkEllipsis.vue';
import MkEmoji from '@/components/global/MkEmoji.vue';
import MkError from '@/components/global/MkError.vue';
import MkFooterSpacer from '@/components/global/MkFooterSpacer.vue';
import MkLazy from '@/components/global/MkLazy.vue';
import MkLoading from '@/components/global/MkLoading.vue';
import MkPageHeader from '@/components/global/MkPageHeader.vue';
import MkSpacer from '@/components/global/MkSpacer.vue';
import MkStickyContainer from '@/components/global/MkStickyContainer.vue';
import MkTime from '@/components/global/MkTime.vue';
import MkUrl from '@/components/global/MkUrl.vue';
import MkUserName from '@/components/global/MkUserName.vue';
import TmsNoCache from '@/components/global/TmsNoCache.vue';

// eslint-disable-next-line import/no-default-export
export default function(app: App) {
Expand All @@ -36,29 +36,29 @@ export default function(app: App) {
}

export const components = {
I18n: I18n,
RouterView: RouterView,
Mfm: Mfm,
MkA: MkA,
MkAcct: MkAcct,
MkAvatar: MkAvatar,
MkEmoji: MkEmoji,
MkCondensedLine: MkCondensedLine,
MkCustomEmoji: MkCustomEmoji,
MkUserName: MkUserName,
MkEllipsis: MkEllipsis,
MkTime: MkTime,
MkUrl: MkUrl,
MkLoading: MkLoading,
MkError: MkError,
MkAd: MkAd,
MkPageHeader: MkPageHeader,
MkSpacer: MkSpacer,
MkFooterSpacer: MkFooterSpacer,
MkStickyContainer: MkStickyContainer,
MkLazy: MkLazy,
TmsNoCache: TmsNoCache,
};
I18n,
RouterView,
Mfm,
MkA,
MkAcct,
MkAd,
MkAvatar,
MkCondensedLine,
MkCustomEmoji,
MkEllipsis,
MkEmoji,
MkError,
MkFooterSpacer,
MkLazy,
MkLoading,
MkPageHeader,
MkSpacer,
MkStickyContainer,
MkTime,
MkUrl,
MkUserName,
TmsNoCache,
} as const;

declare module '@vue/runtime-core' {
export interface GlobalComponents {
Expand All @@ -67,22 +67,22 @@ declare module '@vue/runtime-core' {
Mfm: typeof Mfm;
MkA: typeof MkA;
MkAcct: typeof MkAcct;
MkAd: typeof MkAd;
MkAvatar: typeof MkAvatar;
MkEmoji: typeof MkEmoji;
MkCondensedLine: typeof MkCondensedLine;
MkCustomEmoji: typeof MkCustomEmoji;
MkUserName: typeof MkUserName;
MkEllipsis: typeof MkEllipsis;
MkTime: typeof MkTime;
MkUrl: typeof MkUrl;
MkLoading: typeof MkLoading;
MkEmoji: typeof MkEmoji;
MkError: typeof MkError;
MkAd: typeof MkAd;
MkFooterSpacer: typeof MkFooterSpacer;
MkLazy: typeof MkLazy;
MkLoading: typeof MkLoading;
MkPageHeader: typeof MkPageHeader;
MkSpacer: typeof MkSpacer;
MkFooterSpacer: typeof MkFooterSpacer;
MkStickyContainer: typeof MkStickyContainer;
MkLazy: typeof MkLazy;
MkTime: typeof MkTime;
MkUrl: typeof MkUrl;
MkUserName: typeof MkUserName;
TmsNoCache: typeof TmsNoCache;
}
}
18 changes: 12 additions & 6 deletions packages/frontend/src/directives/adaptive-bg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Directive } from 'vue';
import { getBgColor } from '@/scripts/tms/get-bg-color.js';
import type { ObjectDirective } from 'vue';

type VAdaptiveBg = ObjectDirective<HTMLElement, null | undefined>;

export const vAdaptiveBg = {
async mounted(src) {
const [
{ getBgColor },
] = await Promise.all([
import('@/scripts/tms/get-bg-color.js'),
]);

// eslint-disable-next-line import/no-default-export
export default {
mounted(src, binding, vn) {
const parentBg = getBgColor(src.parentElement) ?? 'transparent';

const myBg = window.getComputedStyle(src).backgroundColor;
Expand All @@ -19,4 +25,4 @@ export default {
src.style.backgroundColor = myBg;
}
},
} as Directive;
} satisfies VAdaptiveBg as VAdaptiveBg;
18 changes: 12 additions & 6 deletions packages/frontend/src/directives/adaptive-border.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Directive } from 'vue';
import { getBgColor } from '@/scripts/tms/get-bg-color.js';
import type { ObjectDirective } from 'vue';

type VAdaptiveBorder = ObjectDirective<HTMLElement, null | undefined>;

export const vAdaptiveBorder = {
async mounted(src) {
const [
{ getBgColor },
] = await Promise.all([
import('@/scripts/tms/get-bg-color.js'),
]);

// eslint-disable-next-line import/no-default-export
export default {
mounted(src, binding, vn) {
const parentBg = getBgColor(src.parentElement) ?? 'transparent';

const myBg = window.getComputedStyle(src).backgroundColor;
Expand All @@ -19,4 +25,4 @@ export default {
src.style.borderColor = myBg;
}
},
} as Directive;
} satisfies VAdaptiveBorder as VAdaptiveBorder;
17 changes: 10 additions & 7 deletions packages/frontend/src/directives/anim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Directive } from 'vue';
import type { ObjectDirective } from 'vue';

// eslint-disable-next-line import/no-default-export
export default {
beforeMount(src, binding, vn) {
type VAnim = ObjectDirective<HTMLElement, number | null | undefined>;

export const vAnim = {
async beforeMount(src) {
src.style.opacity = '0';
src.style.transform = 'scale(0.9)';
// ページネーションと相性が悪いので
// if (typeof binding.value === 'number') src.style.transitionDelay = `${binding.value * 30}ms`;
// if (typeof binding.value === 'number') {
// src.style.transitionDelay = `${binding.value * 30}ms`;
// }
src.classList.add('_zoom');
},

mounted(src, binding, vn) {
async mounted(src) {
window.setTimeout(() => {
src.style.opacity = '1';
src.style.transform = 'none';
}, 1);
},
} as Directive;
} satisfies VAnim as VAnim;
19 changes: 10 additions & 9 deletions packages/frontend/src/directives/appear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Directive } from 'vue';
import type { ObjectDirective } from 'vue';

// eslint-disable-next-line import/no-default-export
export default {
mounted(src, binding, vn) {
type VAppear = ObjectDirective<HTMLElement, (() => unknown) | null | undefined>;

export const vAppear = {
async mounted(src, binding) {
const fn = binding.value;
if (fn == null) return;

const observer = new IntersectionObserver(entries => {
if (entries.some(entry => entry.isIntersecting)) {
const observer = new IntersectionObserver((entries) => {
if (entries.some((entry) => entry.isIntersecting)) {
fn();
}
});
Expand All @@ -22,7 +23,7 @@ export default {
src._observer_ = observer;
},

unmounted(src, binding, vn) {
if (src._observer_) src._observer_.disconnect();
async unmounted(src) {
src._observer_?.disconnect();
},
} as Directive;
} satisfies VAppear as VAppear;
26 changes: 16 additions & 10 deletions packages/frontend/src/directives/click-anime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Directive } from 'vue';
import { defaultStore } from '@/store.js';
import type { ObjectDirective } from 'vue';

type VClickAnime = ObjectDirective<HTMLElement, null | undefined>;

export const vClickAnime = {
async mounted(src) {
const [
{ defaultStore },
] = await Promise.all([
import('@/store.js'),
]);

// eslint-disable-next-line import/no-default-export
export default {
mounted(el: HTMLElement, binding, vn) {
if (!defaultStore.state.animation) return;

const target = el.children[0];
const target = src.children[0];

if (target == null) return;

target.classList.add('_anime_bounce_standBy');

el.addEventListener('mousedown', () => {
src.addEventListener('mousedown', () => {
target.classList.remove('_anime_bounce');

target.classList.add('_anime_bounce_standBy');
Expand All @@ -28,14 +34,14 @@ export default {
}, { passive: true });
}, { passive: true });

el.addEventListener('click', () => {
src.addEventListener('click', () => {
target.classList.add('_anime_bounce');
target.classList.remove('_anime_bounce_ready');
}, { passive: true });

el.addEventListener('animationend', () => {
src.addEventListener('animationend', () => {
target.classList.remove('_anime_bounce');
target.classList.add('_anime_bounce_standBy');
}, { passive: true });
},
} as Directive;
} satisfies VClickAnime as VClickAnime;
Loading
Loading