fix display:none
This commit is contained in:
parent
b2c8548c67
commit
ad03ef03da
|
@ -50,7 +50,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineAsyncComponent, nextTick, ref, shallowRef, toRefs, watch } from 'vue';
|
import { computed, defineAsyncComponent, nextTick, onMounted, onUnmounted, ref, shallowRef, toRefs, watch } from 'vue';
|
||||||
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
|
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
|
||||||
import { useTooltip } from '@/scripts/use-tooltip.js';
|
import { useTooltip } from '@/scripts/use-tooltip.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
@ -144,6 +144,10 @@ function onInputText(ev: Event) {
|
||||||
editingValue.value = (ev.target as HTMLInputElement).value;
|
editingValue.value = (ev.target as HTMLInputElement).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onForceRefreshContentSize() {
|
||||||
|
emitContentSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
function registerOutsideMouseDown() {
|
function registerOutsideMouseDown() {
|
||||||
unregisterOutsideMouseDown();
|
unregisterOutsideMouseDown();
|
||||||
addEventListener('mousedown', onOutsideMouseDown);
|
addEventListener('mousedown', onOutsideMouseDown);
|
||||||
|
@ -223,6 +227,14 @@ useTooltip(rootEl, (showing) => {
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
bus.value.on('forceRefreshContentSize', onForceRefreshContentSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
bus.value.off('forceRefreshContentSize', onForceRefreshContentSize);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, toRefs, watch } from 'vue';
|
import { computed, nextTick, onMounted, ref, toRefs, watch } from 'vue';
|
||||||
import {
|
import {
|
||||||
CellValueChangedEvent,
|
CellValueChangedEvent,
|
||||||
ColumnSetting,
|
ColumnSetting,
|
||||||
|
@ -71,7 +71,21 @@ const emit = defineEmits<{
|
||||||
(ev: 'change:cellValue', event: CellValueChangedEvent): void;
|
(ev: 'change:cellValue', event: CellValueChangedEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* grid -> 各子コンポーネントのイベント経路を担う{@link GridEventEmitter}。
|
||||||
|
* 子コンポーネント -> gridのイベントでは原則使用せず、{@link emit}を使用する。
|
||||||
|
*/
|
||||||
const bus = new GridEventEmitter();
|
const bus = new GridEventEmitter();
|
||||||
|
/**
|
||||||
|
* テーブルコンポーネントのリサイズイベントを監視するための{@link ResizeObserver}。
|
||||||
|
* 表示切替を検知し、サイズの再計算要求を発行するために使用する(マウント時にコンテンツが表示されていない場合、初手のサイズの自動計算が正常に働かないため)
|
||||||
|
*
|
||||||
|
* {@link setTimeout}を経由している理由は、{@link onResize}の中でサイズ再計算要求→サイズ変更が発生するとループとみなされ、
|
||||||
|
* 「ResizeObserver loop completed with undelivered notifications.」という警告が発生するため(状態管理してるので実際にはループしない)
|
||||||
|
*
|
||||||
|
* @see {@link onResize}
|
||||||
|
*/
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => setTimeout(() => onResize(entries)));
|
||||||
|
|
||||||
const { gridSetting, columnSettings, data } = toRefs(props);
|
const { gridSetting, columnSettings, data } = toRefs(props);
|
||||||
|
|
||||||
|
@ -122,14 +136,44 @@ watch(columnSettings, refreshColumnsSetting);
|
||||||
watch(data, refreshData);
|
watch(data, refreshData);
|
||||||
|
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
watch(state, (value) => {
|
watch(state, (value, oldValue) => {
|
||||||
console.log(`state: ${value}`);
|
console.log(`[grid][state] ${oldValue} -> ${value}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onResize(entries: ResizeObserverEntry[]) {
|
||||||
|
if (entries.length !== 1 || entries[0].target !== rootEl.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentRect = entries[0].contentRect;
|
||||||
|
if (_DEV_) {
|
||||||
|
console.log(`[grid][resize] contentRect: ${contentRect.width}x${contentRect.height}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state.value) {
|
||||||
|
case 'hidden': {
|
||||||
|
if (contentRect.width > 0 && contentRect.height > 0) {
|
||||||
|
state.value = 'normal';
|
||||||
|
|
||||||
|
// 選択状態が狂うかもしれないので解除しておく
|
||||||
|
unSelectionRange();
|
||||||
|
bus.emit('forceRefreshContentSize');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (contentRect.width === 0 || contentRect.height === 0) {
|
||||||
|
state.value = 'hidden';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onKeyDown(ev: KeyboardEvent) {
|
function onKeyDown(ev: KeyboardEvent) {
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log('[Grid]', `ctrl: ${ev.ctrlKey}, shift: ${ev.shiftKey}, code: ${ev.code}`);
|
console.log(`[grid][key] ctrl: ${ev.ctrlKey}, shift: ${ev.shiftKey}, code: ${ev.code}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state.value) {
|
switch (state.value) {
|
||||||
|
@ -482,7 +526,7 @@ function onChangeCellValue(sender: GridCell, newValue: CellValue) {
|
||||||
function onChangeCellContentSize(sender: GridCell, contentSize: Size) {
|
function onChangeCellContentSize(sender: GridCell, contentSize: Size) {
|
||||||
cells.value[sender.address.row][sender.address.col].contentSize = contentSize;
|
cells.value[sender.address.row][sender.address.col].contentSize = contentSize;
|
||||||
if (sender.column.setting.width === 'auto') {
|
if (sender.column.setting.width === 'auto') {
|
||||||
largestCellWidth(sender.column);
|
calcLargestCellWidth(sender.column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +563,7 @@ function onHeaderCellChangeContentSize(sender: GridColumn, newSize: Size) {
|
||||||
case 'normal': {
|
case 'normal': {
|
||||||
columns.value[sender.index].contentSize = newSize;
|
columns.value[sender.index].contentSize = newSize;
|
||||||
if (sender.setting.width === 'auto') {
|
if (sender.setting.width === 'auto') {
|
||||||
largestCellWidth(sender);
|
calcLargestCellWidth(sender);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -529,13 +573,13 @@ function onHeaderCellChangeContentSize(sender: GridColumn, newSize: Size) {
|
||||||
function onHeaderCellWidthLargest(sender: GridColumn) {
|
function onHeaderCellWidthLargest(sender: GridColumn) {
|
||||||
switch (state.value) {
|
switch (state.value) {
|
||||||
case 'normal': {
|
case 'normal': {
|
||||||
largestCellWidth(sender);
|
calcLargestCellWidth(sender);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function largestCellWidth(column: GridColumn) {
|
function calcLargestCellWidth(column: GridColumn) {
|
||||||
const _cells = cells.value;
|
const _cells = cells.value;
|
||||||
const largestColumnWidth = columns.value[column.index].contentSize.width;
|
const largestColumnWidth = columns.value[column.index].contentSize.width;
|
||||||
|
|
||||||
|
@ -548,7 +592,9 @@ function largestCellWidth(column: GridColumn) {
|
||||||
)
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
console.log(`largestCellWidth: ${largestColumnWidth}, ${largestCellWidth}`);
|
if (_DEV_) {
|
||||||
|
console.log(`[grid][calc-largest] idx:${column.setting.bindTo}, col:${largestColumnWidth}, cell:${largestCellWidth}`);
|
||||||
|
}
|
||||||
|
|
||||||
column.width = `${Math.max(largestColumnWidth, largestCellWidth)}px`;
|
column.width = `${Math.max(largestColumnWidth, largestCellWidth)}px`;
|
||||||
}
|
}
|
||||||
|
@ -800,9 +846,21 @@ function unregisterMouseUp() {
|
||||||
removeEventListener('mouseup', onMouseUp);
|
removeEventListener('mouseup', onMouseUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshColumnsSetting();
|
onMounted(() => {
|
||||||
refreshData();
|
refreshColumnsSetting();
|
||||||
|
refreshData();
|
||||||
|
|
||||||
|
if (rootEl.value) {
|
||||||
|
resizeObserver.observe(rootEl.value);
|
||||||
|
|
||||||
|
// 初期表示時にコンテンツが表示されていない場合はhidden状態にしておく。
|
||||||
|
// コンテンツ表示時にresizeイベントが発生するが、そのときにhidden状態にしておかないとサイズの再計算が走らないので
|
||||||
|
const bounds = rootEl.value.getBoundingClientRect();
|
||||||
|
if (bounds.width === 0 || bounds.height === 0) {
|
||||||
|
state.value = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
|
@ -812,7 +870,6 @@ $borderRadius: var(--radius);
|
||||||
.grid {
|
.grid {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
width: fit-content;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, ref, toRefs, watch } from 'vue';
|
import { computed, nextTick, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
|
||||||
import { GridColumn, GridEventEmitter, Size } from '@/components/grid/grid.js';
|
import { GridColumn, GridEventEmitter, Size } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -51,7 +51,7 @@ const text = computed(() => {
|
||||||
|
|
||||||
watch(column, () => {
|
watch(column, () => {
|
||||||
// 中身がセットされた直後はサイズが分からないので、次のタイミングで更新する
|
// 中身がセットされた直後はサイズが分からないので、次のタイミングで更新する
|
||||||
nextTick(updateContentSize);
|
nextTick(emitContentSizeChanged);
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
function onHandleDoubleClick(ev: MouseEvent) {
|
function onHandleDoubleClick(ev: MouseEvent) {
|
||||||
|
@ -111,6 +111,10 @@ function onHandleMouseUp(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onForceRefreshContentSize() {
|
||||||
|
emitContentSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
function registerHandleMouseMove() {
|
function registerHandleMouseMove() {
|
||||||
unregisterHandleMouseMove();
|
unregisterHandleMouseMove();
|
||||||
addEventListener('mousemove', onHandleMouseMove);
|
addEventListener('mousemove', onHandleMouseMove);
|
||||||
|
@ -129,7 +133,7 @@ function unregisterHandleMouseUp() {
|
||||||
removeEventListener('mouseup', onHandleMouseUp);
|
removeEventListener('mouseup', onHandleMouseUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContentSize() {
|
function emitContentSizeChanged() {
|
||||||
const clientWidth = contentEl.value?.clientWidth ?? 0;
|
const clientWidth = contentEl.value?.clientWidth ?? 0;
|
||||||
const clientHeight = contentEl.value?.clientHeight ?? 0;
|
const clientHeight = contentEl.value?.clientHeight ?? 0;
|
||||||
emit('change:contentSize', column.value, {
|
emit('change:contentSize', column.value, {
|
||||||
|
@ -139,6 +143,14 @@ function updateContentSize() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
bus.value.on('forceRefreshContentSize', onForceRefreshContentSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
bus.value.off('forceRefreshContentSize', onForceRefreshContentSize);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
|
|
|
@ -8,7 +8,7 @@ export type GridSetting = {
|
||||||
|
|
||||||
export type DataSource = Record<string, CellValue>;
|
export type DataSource = Record<string, CellValue>;
|
||||||
|
|
||||||
export type GridState = 'normal' | 'cellSelecting' | 'cellEditing' | 'colResizing' | 'colSelecting' | 'rowSelecting'
|
export type GridState = 'normal' | 'cellSelecting' | 'cellEditing' | 'colResizing' | 'colSelecting' | 'rowSelecting' | 'hidden'
|
||||||
|
|
||||||
export type Size = {
|
export type Size = {
|
||||||
width: number;
|
width: number;
|
||||||
|
@ -47,5 +47,7 @@ export type CellValueChangedEvent = {
|
||||||
value: CellValue;
|
value: CellValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GridEventEmitter extends EventEmitter<{}> {
|
export class GridEventEmitter extends EventEmitter<{
|
||||||
|
'forceRefreshContentSize': void;
|
||||||
|
}> {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue