barkey/packages/frontend/src/components/grid/MkHeaderCell.vue
おさむのひと f9ad127aaf
feat: 新カスタム絵文字管理画面(β)の追加 (#13473)
* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* fix

* fix

* fix

* fix size

* fix register logs

* fix img autosize

* fix row selection

* support delete

* fix border rendering

* fix display:none

* tweak comments

* support choose pc file and drive file

* support directory drag-drop

* fix

* fix comment

* support context menu on data area

* fix autogen

* wip イベント整理

* イベントの整理

* refactor grid

* fix cell re-render bugs

* fix row remove

* fix comment

* fix validation

* fix utils

* list maximum

* add mimetype check

* fix

* fix number cell focus

* fix over 100 file drop

* remove log

* fix patchData

* fix performance

* fix

* support update and delete

* support remote import

* fix layout

* heightやめる

* fix performance

* add list v2 endpoint

* support pagination

* fix api call

* fix no clickable input text

* fix limit

* fix paging

* fix

* fix

* support search

* tweak logs

* tweak cell selection

* fix range select

* block delete

* add comment

* fix

* support import log

* fix dialog

* refactor

* add confirm dialog

* fix name

* fix autogen

* wip

* support image change and highlight row

* add columns

* wip

* support sort

* add role name

* add index to emoji

* refine context menu setting

* support role select

* remove unused buttons

* fix url

* fix MkRoleSelectDialog.vue

* add route

* refine remote page

* enter key search

* fix paste bugs

* fix copy/paste

* fix keyEvent

* fix copy/paste and delete

* fix comment

* fix MkRoleSelectDialog.vue and storybook scenario

* fix MkRoleSelectDialog.vue and storybook scenario

* add MkGrid.stories.impl.ts

* fix

* [wip] add custom-emojis-manager2.stories.impl.ts

* [wip] add custom-emojis-manager2.stories.impl.ts

* wip

* 課題はまだ残っているが、ひとまず完了

* fix validation and register roles

* fix upload

* optimize import

* patch from dev

* i18n

* revert excess fixes

* separate sort order component

* add SPDX

* revert excess fixes

* fix pre test

* fix bugs

* add type column

* fix types

* fix CHANGELOG.md

* fix lit

* lint

* tweak style

* refactor

* fix ci

* autogen

* Update types.ts

* CSS Module化

* fix log

* 縦スクロールを無効化

* MkStickyContainer化

* regenerate locales index.d.ts

* fix

* fix

* テスト

* ランダム値によるUI変更の抑制

* テスト

* tableタグやめる

* fix last-child css

* fix overflow css

* fix endpoint.ts

* tweak css

* 最新への追従とレイアウト微調整

* ソートキーの指定方法を他と合わせた

* fix focus

* fix layout

* v2エンドポイントのルールに対応

* 表示条件などを微調整

* fix MkDataCell.vue

* fix error code

* fix error

* add comment to MkModal.vue

* Update index.d.ts

* fix CHANGELOG.md

* fix color theme

* fix CHANGELOG.md

* fix CHANGELOG.md

* fix center

* fix: テーブルにフォーカスがあり、通常状態であるときはキーイベントの伝搬を止める

* fix: ロール選択用のダイアログにてコンディショナルロールを×ボタンで除外できなかったのを修正

* fix remote list folder

* sticky footers

* chore: fix ci error(just single line-break diff)

* fix loading

* fix like

* comma to space

* fix ci

* fix ci

* removed align-center

---------

Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
2025-01-20 11:35:37 +00:00

216 lines
5 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
ref="rootEl"
class="mk_grid_th"
:class="$style.cell"
:style="[{ maxWidth: column.width, minWidth: column.width, width: column.width }]"
data-grid-cell
:data-grid-cell-row="-1"
:data-grid-cell-col="column.index"
>
<div :class="$style.root">
<div :class="$style.left"/>
<div :class="$style.wrapper">
<div ref="contentEl" :class="$style.contentArea">
<span v-if="column.setting.icon" class="ti" :class="column.setting.icon" style="line-height: normal"/>
<span v-else>{{ text }}</span>
</div>
</div>
<div
:class="$style.right"
@mousedown="onHandleMouseDown"
@dblclick="onHandleDoubleClick"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
import { GridColumn } from '@/components/grid/column.js';
const emit = defineEmits<{
(ev: 'operation:beginWidthChange', sender: GridColumn): void;
(ev: 'operation:endWidthChange', sender: GridColumn): void;
(ev: 'operation:widthLargest', sender: GridColumn): void;
(ev: 'change:width', sender: GridColumn, width: string): void;
(ev: 'change:contentSize', sender: GridColumn, newSize: Size): void;
}>();
const props = defineProps<{
column: GridColumn,
bus: GridEventEmitter,
}>();
const { column, bus } = toRefs(props);
const rootEl = ref<InstanceType<typeof HTMLTableCellElement>>();
const contentEl = ref<InstanceType<typeof HTMLDivElement>>();
const resizing = ref<boolean>(false);
const text = computed(() => {
const result = column.value.setting.title ?? column.value.setting.bindTo;
return result.length > 0 ? result : ' ';
});
watch(column, () => {
// 中身がセットされた直後はサイズが分からないので、次のタイミングで更新する
nextTick(emitContentSizeChanged);
}, { immediate: true });
function onHandleDoubleClick(ev: MouseEvent) {
switch (ev.type) {
case 'dblclick': {
emit('operation:widthLargest', column.value);
break;
}
}
}
function onHandleMouseDown(ev: MouseEvent) {
switch (ev.type) {
case 'mousedown': {
if (!resizing.value) {
registerHandleMouseUp();
registerHandleMouseMove();
resizing.value = true;
emit('operation:beginWidthChange', column.value);
}
break;
}
}
}
function onHandleMouseMove(ev: MouseEvent) {
if (!rootEl.value) {
// 型ガード
return;
}
switch (ev.type) {
case 'mousemove': {
if (resizing.value) {
const bounds = rootEl.value.getBoundingClientRect();
const clientWidth = rootEl.value.clientWidth;
const clientRight = bounds.left + clientWidth;
const nextWidth = clientWidth + (ev.clientX - clientRight);
emit('change:width', column.value, `${nextWidth}px`);
}
break;
}
}
}
function onHandleMouseUp(ev: MouseEvent) {
switch (ev.type) {
case 'mouseup': {
if (resizing.value) {
unregisterHandleMouseUp();
unregisterHandleMouseMove();
resizing.value = false;
emit('operation:endWidthChange', column.value);
}
break;
}
}
}
function onForceRefreshContentSize() {
emitContentSizeChanged();
}
function registerHandleMouseMove() {
unregisterHandleMouseMove();
addEventListener('mousemove', onHandleMouseMove);
}
function unregisterHandleMouseMove() {
removeEventListener('mousemove', onHandleMouseMove);
}
function registerHandleMouseUp() {
unregisterHandleMouseUp();
addEventListener('mouseup', onHandleMouseUp);
}
function unregisterHandleMouseUp() {
removeEventListener('mouseup', onHandleMouseUp);
}
function emitContentSizeChanged() {
const clientWidth = contentEl.value?.clientWidth ?? 0;
const clientHeight = contentEl.value?.clientHeight ?? 0;
emit('change:contentSize', column.value, {
// バーの横幅も考慮したいので、+3px
width: clientWidth + 3 + 3,
height: clientHeight,
});
}
onMounted(() => {
bus.value.on('forceRefreshContentSize', onForceRefreshContentSize);
});
onUnmounted(() => {
bus.value.off('forceRefreshContentSize', onForceRefreshContentSize);
});
</script>
<style module lang="scss">
$handleWidth: 5px;
$cellHeight: 28px;
.cell {
cursor: pointer;
}
.root {
display: flex;
flex-direction: row;
height: $cellHeight;
max-height: $cellHeight;
min-height: $cellHeight;
.wrapper {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
justify-content: center;
}
.contentArea {
display: flex;
padding: 6px 4px;
box-sizing: border-box;
overflow: hidden;
white-space: nowrap;
text-align: center;
}
.left {
// rightのぶんだけズレるのでそれを相殺するためのネガティブマージン
margin-left: -$handleWidth;
margin-right: auto;
width: $handleWidth;
min-width: $handleWidth;
}
.right {
margin-left: auto;
// 判定を罫線の上に重ねたいのでネガティブマージンを使う
margin-right: -$handleWidth;
width: $handleWidth;
min-width: $handleWidth;
cursor: w-resize;
z-index: 1;
}
}
</style>