tableタグやめる
This commit is contained in:
parent
1cefedb6ac
commit
20bcf4af4f
|
@ -4,11 +4,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<td
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="mk_grid_td"
|
||||
:class="$style.cell"
|
||||
:style="{ maxWidth: cellWidth, minWidth: cellWidth }"
|
||||
:tabindex="-1"
|
||||
data-grid-cell
|
||||
:data-grid-cell-row="cell.row.index"
|
||||
:data-grid-cell-col="cell.column.index"
|
||||
@keydown="onCellKeyDown"
|
||||
@dblclick.prevent="onCellDoubleClick"
|
||||
>
|
||||
|
@ -77,7 +81,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -143,7 +147,7 @@ function onCellDoubleClick(ev: MouseEvent) {
|
|||
|
||||
function onOutsideMouseDown(ev: MouseEvent) {
|
||||
const isOutside = ev.target instanceof Node && !rootEl.value?.contains(ev.target);
|
||||
if (isOutside || !equalCellAddress(cell.value.address, getCellAddress(ev.target as HTMLElement, rowSetting.value))) {
|
||||
if (isOutside || !equalCellAddress(cell.value.address, getCellAddress(ev.target as HTMLElement))) {
|
||||
endEditing(true);
|
||||
}
|
||||
}
|
||||
|
@ -352,9 +356,9 @@ $cellHeight: 28px;
|
|||
width: 100%;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
min-height: $cellHeight;
|
||||
max-height: $cellHeight;
|
||||
height: $cellHeight + 4px;
|
||||
min-height: $cellHeight - 2;
|
||||
max-height: $cellHeight - 2;
|
||||
height: $cellHeight - 2;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-family: 'Hiragino Maru Gothic Pro', "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif;
|
||||
|
|
|
@ -4,7 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<tr
|
||||
<div
|
||||
class="mk_grid_tr"
|
||||
:class="[
|
||||
$style.row,
|
||||
row.ranged ? $style.ranged : {},
|
||||
|
@ -13,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:style="[
|
||||
...(row.additionalStyles ?? []).map(it => it.style ?? {}),
|
||||
]"
|
||||
:data-grid-row="row.index"
|
||||
>
|
||||
<MkNumberCell
|
||||
v-if="setting.showNumber"
|
||||
|
@ -31,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@change:value="(sender, newValue) => emit('change:value', sender, newValue)"
|
||||
@change:contentSize="(sender, newSize) => emit('change:contentSize', sender, newSize)"
|
||||
/>
|
||||
</tr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -58,6 +60,10 @@ defineProps<{
|
|||
|
||||
<style module lang="scss">
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&.ranged {
|
||||
background-color: var(--accentedBg);
|
||||
}
|
||||
|
|
|
@ -4,14 +4,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<table
|
||||
<div
|
||||
ref="rootEl"
|
||||
:class="[$style.grid, $style.border]"
|
||||
class="mk_grid_border"
|
||||
:class="[$style.grid]"
|
||||
@mousedown.prevent="onMouseDown"
|
||||
@keydown="onKeyDown"
|
||||
@contextmenu.prevent.stop="onContextMenu"
|
||||
>
|
||||
<thead>
|
||||
<div class="mk_grid_thead">
|
||||
<MkHeaderRow
|
||||
:columns="columns"
|
||||
:gridSetting="rowSetting"
|
||||
|
@ -22,8 +23,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@change:width="onHeaderCellChangeWidth"
|
||||
@change:contentSize="onHeaderCellChangeContentSize"
|
||||
/>
|
||||
</thead>
|
||||
<tbody>
|
||||
</div>
|
||||
<div class="mk_grid_tbody">
|
||||
<MkDataRow
|
||||
v-for="row in rows"
|
||||
v-show="row.using"
|
||||
|
@ -39,8 +40,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@change:value="onChangeCellValue"
|
||||
@change:contentSize="onChangeCellContentSize"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -81,14 +82,14 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
// non-reactive
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
|
||||
const rowSetting: Required<GridRowSetting> = {
|
||||
...defaultGridRowSetting,
|
||||
...props.settings.row,
|
||||
};
|
||||
|
||||
// non-reactive
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
|
||||
const columnSettings = props.settings.cols;
|
||||
|
||||
// non-reactive
|
||||
|
@ -448,7 +449,7 @@ function onMouseDown(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
function onLeftMouseDown(ev: MouseEvent) {
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement);
|
||||
if (_DEV_) {
|
||||
console.log(`[grid][mouse-left] state:${state.value}, button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||
}
|
||||
|
@ -582,7 +583,7 @@ function onLeftMouseDown(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
function onRightMouseDown(ev: MouseEvent) {
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement);
|
||||
if (_DEV_) {
|
||||
console.log(`[grid][mouse-right] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||
}
|
||||
|
@ -607,7 +608,7 @@ function onRightMouseDown(ev: MouseEvent) {
|
|||
function onMouseMove(ev: MouseEvent) {
|
||||
ev.preventDefault();
|
||||
|
||||
const targetCellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||
const targetCellAddress = getCellAddress(ev.target as HTMLElement);
|
||||
if (equalCellAddress(previousCellAddress.value, targetCellAddress)) {
|
||||
// セルが変わるまでイベントを起こしたくない
|
||||
return;
|
||||
|
@ -718,7 +719,7 @@ function onMouseUp(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
function onContextMenu(ev: MouseEvent) {
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||
const cellAddress = getCellAddress(ev.target as HTMLElement);
|
||||
if (_DEV_) {
|
||||
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||
}
|
||||
|
@ -1270,22 +1271,22 @@ onMounted(() => {
|
|||
</script>
|
||||
|
||||
<style module lang="scss">
|
||||
.grid {
|
||||
font-size: 90%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
$borderSetting: solid 0.5px var(--divider);
|
||||
$borderRadius: var(--radius);
|
||||
|
||||
.grid {
|
||||
overflow: scroll;
|
||||
table-layout: fixed;
|
||||
user-select: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.border {
|
||||
// 配下コンポーネントを含めて一括してコントロールするため、scopedもmoduleも使用できない
|
||||
.mk_grid_border {
|
||||
border-spacing: 0;
|
||||
|
||||
thead {
|
||||
tr {
|
||||
th {
|
||||
.mk_grid_thead {
|
||||
.mk_grid_tr {
|
||||
.mk_grid_th {
|
||||
border-left: $borderSetting;
|
||||
border-top: $borderSetting;
|
||||
|
||||
|
@ -1303,9 +1304,9 @@ $borderRadius: var(--radius);
|
|||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
td, th {
|
||||
.mk_grid_tbody {
|
||||
.mk_grid_tr {
|
||||
.mk_grid_td, .mk_grid_th {
|
||||
border-left: $borderSetting;
|
||||
border-top: $borderSetting;
|
||||
|
||||
|
@ -1316,7 +1317,7 @@ $borderRadius: var(--radius);
|
|||
}
|
||||
|
||||
&.lastLine {
|
||||
td, th {
|
||||
.mk_grid_td, .mk_grid_th {
|
||||
// 一番下の行
|
||||
border-bottom: $borderSetting;
|
||||
|
||||
|
|
|
@ -4,16 +4,20 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<th
|
||||
<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"/>
|
||||
<span v-if="column.setting.icon" class="ti" :class="column.setting.icon" style="line-height: normal"/>
|
||||
<span v-else>{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@dblclick="onHandleDoubleClick"
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -161,6 +165,7 @@ onUnmounted(() => {
|
|||
|
||||
<style module lang="scss">
|
||||
$handleWidth: 5px;
|
||||
$cellHeight: 28px;
|
||||
|
||||
.cell {
|
||||
cursor: pointer;
|
||||
|
@ -169,7 +174,9 @@ $handleWidth: 5px;
|
|||
.root {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
height: $cellHeight;
|
||||
max-height: $cellHeight;
|
||||
min-height: $cellHeight;
|
||||
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
|
|
|
@ -4,7 +4,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<tr>
|
||||
<div
|
||||
class="mk_grid_tr"
|
||||
:class="$style.root"
|
||||
:data-grid-row="-1"
|
||||
>
|
||||
<MkNumberCell
|
||||
v-if="gridSetting.showNumber"
|
||||
content="#"
|
||||
|
@ -21,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@change:width="(sender, width) => emit('change:width', sender, width)"
|
||||
@change:contentSize="(sender, newSize) => emit('change:contentSize', sender, newSize)"
|
||||
/>
|
||||
</tr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -46,3 +50,11 @@ defineProps<{
|
|||
bus: GridEventEmitter,
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style module lang="scss">
|
||||
.root {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,11 +4,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<th :class="[$style.cell]" tabindex="-1">
|
||||
<div
|
||||
class="mk_grid_th"
|
||||
:class="[$style.cell]"
|
||||
:tabindex="-1"
|
||||
data-grid-cell
|
||||
:data-grid-cell-row="row?.index ?? -1"
|
||||
:data-grid-cell-col="-1"
|
||||
>
|
||||
<div :class="[$style.root]">
|
||||
{{ content }}
|
||||
</div>
|
||||
</th>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
import { isRef, Ref } from 'vue';
|
||||
import { DataSource, SizeStyle } from '@/components/grid/grid.js';
|
||||
import { CELL_ADDRESS_NONE, CellAddress, CellValue, GridCell } from '@/components/grid/cell.js';
|
||||
import { GridRow, GridRowSetting } from '@/components/grid/row.js';
|
||||
import { GridRow } from '@/components/grid/row.js';
|
||||
import { GridContext } from '@/components/grid/grid-event.js';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||
import { GridColumn, GridColumnSetting } from '@/components/grid/column.js';
|
||||
|
||||
export function isCellElement(elem: any): elem is HTMLTableCellElement {
|
||||
return elem instanceof HTMLTableCellElement;
|
||||
export function isCellElement(elem: HTMLElement): boolean {
|
||||
return elem.hasAttribute('data-grid-cell');
|
||||
}
|
||||
|
||||
export function isRowElement(elem: any): elem is HTMLTableRowElement {
|
||||
return elem instanceof HTMLTableRowElement;
|
||||
export function isRowElement(elem: HTMLElement): boolean {
|
||||
return elem.hasAttribute('data-grid-row');
|
||||
}
|
||||
|
||||
export function calcCellWidth(widthSetting: SizeStyle): string {
|
||||
|
@ -31,29 +31,43 @@ export function calcCellWidth(widthSetting: SizeStyle): string {
|
|||
}
|
||||
}
|
||||
|
||||
export function getCellAddress(elem: HTMLElement, gridSetting: GridRowSetting, parentNodeCount = 10): CellAddress {
|
||||
function getCellRowByAttribute(elem: HTMLElement): number {
|
||||
const row = elem.getAttribute('data-grid-cell-row');
|
||||
if (row === null) {
|
||||
throw new Error('data-grid-cell-row attribute not found');
|
||||
}
|
||||
return Number(row);
|
||||
}
|
||||
|
||||
function getCellColByAttribute(elem: HTMLElement): number {
|
||||
const col = elem.getAttribute('data-grid-cell-col');
|
||||
if (col === null) {
|
||||
throw new Error('data-grid-cell-col attribute not found');
|
||||
}
|
||||
return Number(col);
|
||||
}
|
||||
|
||||
export function getCellAddress(elem: HTMLElement, parentNodeCount = 10): CellAddress {
|
||||
let node = elem;
|
||||
for (let i = 0; i < parentNodeCount; i++) {
|
||||
if (isCellElement(node) && isRowElement(node.parentElement)) {
|
||||
return {
|
||||
// ヘッダ行ぶんを除く
|
||||
row: node.parentElement.rowIndex - 1,
|
||||
// 数値列ぶんを除く
|
||||
col: gridSetting.showNumber ? node.cellIndex - 1 : node.cellIndex,
|
||||
};
|
||||
}
|
||||
|
||||
if (!node.parentElement) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (isCellElement(node) && isRowElement(node.parentElement)) {
|
||||
const row = getCellRowByAttribute(node);
|
||||
const col = getCellColByAttribute(node);
|
||||
|
||||
return { row, col };
|
||||
}
|
||||
|
||||
node = node.parentElement;
|
||||
}
|
||||
|
||||
return CELL_ADDRESS_NONE;
|
||||
}
|
||||
|
||||
export function getCellElement(elem: HTMLElement, parentNodeCount = 10): HTMLTableCellElement | null {
|
||||
export function getCellElement(elem: HTMLElement, parentNodeCount = 10): HTMLElement | null {
|
||||
let node = elem;
|
||||
for (let i = 0; i < parentNodeCount; i++) {
|
||||
if (isCellElement(node)) {
|
||||
|
|
Loading…
Reference in New Issue