Skip to content

Commit

Permalink
feat: enhance table interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed May 30, 2023
1 parent bde7963 commit 864604e
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 48 deletions.
176 changes: 129 additions & 47 deletions packages/form/src/extensions/table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,84 @@
<template #control>
<el-button @click="add()" :disabled="disabled">添加项目</el-button>
</template>
<table class="bottom schema-table" v-if="entries.length">
<tr v-for="([key], index) in entries">
<td class="key" v-if="schema.type === 'dict'">
<el-input
v-model="entries[index][0]"
:disabled="disabled"
<div class="bottom k-schema-table-container">
<table class="k-schema-table" v-if="entries.length">
<tr v-for="([key], index) in entries">
<td
v-if="schema.type === 'dict'"
class="key"
:class="{ invalid: entries.filter(e => e[0] === key).length > 1 }"
></el-input>
</td>
<td>
<el-input
v-model="entries[index][1]"
:disabled="disabled"
:type="schema.inner.type === 'number' ? 'number' : 'text'"
:max="schema.inner.meta.max"
:min="schema.inner.meta.min"
:step="schema.inner.meta.step"
></el-input>
</td>
<td class="close">
<div class="inner" :class="{ disabled }" @click.stop="del(index)">
<icon-close></icon-close>
</div>
</td>
</tr>
</table>
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
<el-input
v-model="entries[index][0]"
:disabled="disabled"
@focus="handleFocus"
@blur="handleBlur"
></el-input>
</td>
<td
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<el-input
v-model="entries[index][1]"
:disabled="disabled"
:type="schema.inner.type === 'number' ? 'number' : 'text'"
:max="schema.inner.meta.max"
:min="schema.inner.meta.min"
:step="schema.inner.meta.step"
@focus="handleFocus"
@blur="handleBlur"
></el-input>
</td>
<td class="button"
:class="{ disabled: disabled || !index }"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<div class="inner" @click.stop="up(index)">
<icon-arrow-up></icon-arrow-up>
</div>
</td>
<td class="button"
:class="{ disabled: disabled || index === entries.length - 1 }"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<div class="inner" @click.stop="down(index)">
<icon-arrow-down></icon-arrow-down>
</div>
</td>
<td class="button"
:class="{ disabled }"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<div class="inner" @click.stop="del(index)">
<icon-close></icon-close>
</div>
</td>
</tr>
</table>
<template v-for="rect in { hover, focus }">
<div
v-if="rect"
class="outline"
:style="{
top: rect.top + 'px',
left: rect.left + 'px',
width: rect.width + 'px',
height: rect.height + 'px',
}"
></div>
</template>
</div>
</schema-base>
</template>

<script lang="ts" setup>
import { PropType } from 'vue'
import { ref, PropType } from 'vue'
import { useI18n } from 'vue-i18n'
import { IconClose } from '../icons'
import { IconArrowUp, IconArrowDown, IconClose } from '../icons'
import { Schema, useEntries } from '../utils'
import SchemaBase from '../base.vue'
import zhCN from '../locales/zh-CN.yml'
Expand All @@ -57,7 +101,32 @@ defineProps({
defineEmits(['update:modelValue'])
const { entries, add, del } = useEntries()
const { entries, add, del, up, down } = useEntries()
const hover = ref<DOMRect>()
const focus = ref<DOMRect>()
function handleMouseEnter(event: MouseEvent) {
const el = event.target as HTMLElement
hover.value = el.getBoundingClientRect()
}
function handleMouseLeave(event: MouseEvent) {
hover.value = undefined
}
function handleFocus(event: MouseEvent) {
let el = event.target as HTMLElement
while (el && el.tagName !== 'TD') {
el = el.parentElement
}
if (!el) return
focus.value = el.getBoundingClientRect()
}
function handleBlur(event: MouseEvent) {
focus.value = undefined
}
const { t, setLocaleMessage } = useI18n({
messages: {
Expand All @@ -79,52 +148,65 @@ if (import.meta.hot) {

<style lang="scss">
.schema-table {
tr {
border-left: 1px solid var(--el-border-color);
border-right: 1px solid var(--el-border-color);
.k-schema-table-container {
position: relative;
.outline {
position: fixed;
box-sizing: border-box;
border: 1px solid var(--k-color-active);
pointer-events: none;
}
}
.k-schema-table {
td {
padding: 0;
border: 1px solid var(--el-border-color);
.el-input.invalid {
--el-input-border-color: var(--el-color-warning);
&.invalid {
background-color: var(--k-color-warning-fade);
}
.el-input__wrapper {
z-index: 1;
border-radius: 0;
box-shadow: none;
}
}
td {
transition: var(--color-transition);
&.disabled {
pointer-events: none;
}
&:hover {
background-color: var(--k-button-hover-bg);
}
}
td.key {
width: 30%;
}
td.close {
td.button {
width: 2rem;
color: var(--k-text-light);
&:hover {
color: var(--k-color-active);
}
.inner {
height: 2rem;
box-sizing: border-box;
border: 1px solid var(--el-border-color);
display: flex;
justify-content: center;
align-items: center;
color: var(--k-text-light);
transition: var(--color-transition);
cursor: pointer;
}
.inner.disabled {
pointer-events: none;
}
.inner:hover {
color: var(--k-text-dark);
}
.k-icon {
height: 1rem;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/form/src/icons/arrow-down.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<path fill="currentColor" d="M377.4 296.6l-168 176C204.8 477.3 198.6 480 192 480s-12.84-2.688-17.38-7.438l-168-176C-2.5 286.1-2.156 271.8 7.438 262.6c9.5-9.156 24.75-8.812 33.94 .8125L168 396.1V56.02c0-13.25 10.75-24.01 23.1-24.01S216 42.77 216 56.02v340.1l126.6-132.7c9.156-9.625 24.41-9.969 33.94-.8125C386.2 271.8 386.5 286.1 377.4 296.6z"/>
</svg>
</template>
5 changes: 5 additions & 0 deletions packages/form/src/icons/arrow-up.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<path fill="currentColor" d="M6.625 215.5l168-176C179.2 34.7 185.4 32.02 192 32.02s12.84 2.688 17.38 7.438l168 176c9.125 9.594 8.781 24.78-.8125 33.94c-9.5 9.156-24.75 8.812-33.94-.8125L216 115.9V456c0 13.25-10.75 23.1-23.1 23.1S168 469.3 168 456V115.9l-126.6 132.7C32.22 258.2 16.97 258.5 7.438 249.4C-2.156 240.2-2.5 225 6.625 215.5z"/>
</svg>
</template>
4 changes: 3 additions & 1 deletion packages/form/src/icons/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import IconArrowDown from './arrow-down.vue'
import IconArrowUp from './arrow-up.vue'
import IconClose from './close.vue'
import IconEllipsis from './ellipsis.vue'
import IconExternal from './external.vue'
import IconEyeSlash from './eye-slash.vue'
import IconEye from './eye.vue'

export { IconClose, IconEllipsis, IconExternal, IconEyeSlash, IconEye }
export { IconArrowDown, IconArrowUp, IconClose, IconEllipsis, IconExternal, IconEyeSlash, IconEye }

0 comments on commit 864604e

Please sign in to comment.