Skip to content

Commit

Permalink
Unbind row indexes from BSRow
Browse files Browse the repository at this point in the history
This significantly increased performance of inserting new lines, as Vue
doesn't need to dispatch changes of row index of the rows below newly
inserted row. Instead, the focus state of each row is revalidate only when
needed.
  • Loading branch information
xingrz committed Apr 6, 2024
1 parent 86e0380 commit b28d20f
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 31 deletions.
10 changes: 9 additions & 1 deletion src/components/BSMap.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div :class="$style.map" :style="style">
<BSRow v-for="({ row, id }, index) in rows" :key="id" :src="row" :row="index"
<BSRow v-for="({ row, id }, index) in rows" :key="id" :src="row" :focused="isFocused(index)"
@select="(offset, length) => handleSelect(index, offset, length)" />
</div>
</template>
Expand Down Expand Up @@ -41,6 +41,14 @@ const style = computed(() => ({
'--bs-map-cols': cols.value,
}) as CSSProperties);
function isFocused(row: number): boolean {
const { selection } = editorStore;
return (
typeof selection != 'undefined' &&
selection.row == row
);
}
function handleSelect(row: number, offset: number, length: number): void {
editorStore.selection = {
row: row,
Expand Down
5 changes: 2 additions & 3 deletions src/components/BSMap/BSCell.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<BSSelectable v-slot="{ selectable }" :row="props.row" :offset="props.offset" :length="props.src.length">
<BSSelectable v-slot="{ selectable }" :focused="props.focused">
<div :class="[selectable, $style.cell]" :title="props.src" :style="style" @click="() => emit('select')">
<BSIcon v-for="(icon, index) in (parts?.icons || [])" :key="index" :class="$style.icon" :src="icon"
@ratio="(ratio: number) => updateRatio(index, ratio)" />
Expand All @@ -23,8 +23,7 @@ import BSIcon from './BSIcon.vue';
const props = defineProps<{
src: string;
row: number;
offset: number;
focused: boolean;
}>();
const emit = defineEmits<{
Expand Down
23 changes: 18 additions & 5 deletions src/components/BSMap/BSRow.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<template>
<div :class="$style.row">
<div :class="$style.cells" :style="rowStyle">
<BSCell v-for="({ part, offset }, index) in cells" :key="index" :src="part" :row="row" :offset="offset"
@select="() => emit('select', offset, part.length)" />
<BSCell v-for="({ part, offset }, index) in cells" :key="index" :src="part"
:focused="isFocused(offset, part.length)" @select="() => emit('select', offset, part.length)" />
</div>
<div :class="$style.texts">
<BSText v-for="({ part, offset, align }, index) in texts" :key="index" :src="part" :align="align" :row="row"
:offset="offset" @select="() => emit('select', offset, part.length)" />
<BSText v-for="({ part, offset, align }, index) in texts" :key="index" :src="part" :align="align"
:focused="isFocused(offset, part.length)" @select="() => emit('select', offset, part.length)" />
</div>
</div>
</template>

<script lang="ts" setup>
import { computed, defineEmits, defineProps } from 'vue';
import { useEditorStore } from '@/stores/editor';
import splitWithOffset from '@/utils/splitWithOffset';
import styleFromParams from '@/utils/styleFromParams';
Expand All @@ -22,13 +23,15 @@ import BSText from './BSText.vue';
const props = defineProps<{
src: string;
row: number;
focused: boolean;
}>();
const emit = defineEmits<{
(e: 'select', offset: number, length: number): void;
}>();
const editorStore = useEditorStore();
const parts = computed(() => {
const [cells, ...texts] = splitWithOffset(props.src, '~~');
return { cells, texts };
Expand All @@ -41,6 +44,16 @@ const texts = computed(() => parts.value.texts
.map((part, index, { length }) => ({ ...part, align: length == 1 ? 2 : index + 1 }))
.filter(({ part }) => !!part));
function isFocused(offset: number, length: number): boolean {
const { selection } = editorStore;
return (
props.focused &&
typeof selection != 'undefined' &&
selection.offset >= offset &&
selection.offset <= offset + length
);
}
const rowStyle = computed(() => styleFromParams(parts.value.texts[4]?.part));
</script>

Expand Down
22 changes: 3 additions & 19 deletions src/components/BSMap/BSSelectable.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
<template>
<slot :selectable="{
[$style.selectable]: true,
[$style.focused]: focused,
[$style.focused]: props.focused,
}" />
</template>

<script lang="ts" setup>
import { computed, defineProps } from 'vue';
import { useEditorStore } from '@/stores/editor';
import { defineProps } from 'vue';
const props = defineProps<{
row: number;
offset: number;
length: number;
focused: boolean;
}>();
const editorStore = useEditorStore();
const focused = computed(() => {
const { selection } = editorStore;
return (
typeof selection != 'undefined' &&
selection.row == props.row &&
selection.offset >= props.offset &&
selection.offset <= props.offset + props.length
);
});
</script>

<style lang="scss" module>
Expand Down
5 changes: 2 additions & 3 deletions src/components/BSMap/BSText.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<BSSelectable v-slot="{ selectable }" :row="props.row" :offset="props.offset" :length="props.src.length">
<BSSelectable v-slot="{ selectable }" :focused="props.focused">
<div :class="[selectable, $style.text]" :data-align="align" :title="props.src" @click="() => emit('select')">
{{ props.src }}
</div>
Expand All @@ -14,8 +14,7 @@ import BSSelectable from './BSSelectable.vue';
const props = defineProps<{
src: string;
align: number;
row: number;
offset: number;
focused: boolean;
}>();
const emit = defineEmits<{
Expand Down

0 comments on commit b28d20f

Please sign in to comment.