feat(filter): add auto resize for filter query input
This commit is contained in:
parent
b978d344ca
commit
c162a5a457
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
|
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
modelValue,
|
modelValue,
|
||||||
@ -8,6 +9,10 @@ const {
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const filterQuery = ref('')
|
const filterQuery = ref('')
|
||||||
|
const {
|
||||||
|
textarea: filterInput,
|
||||||
|
height,
|
||||||
|
} = useAutoHeightTextarea(filterQuery)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => modelValue,
|
() => modelValue,
|
||||||
@ -88,14 +93,19 @@ function escapeHtml(unsafe: string): string {
|
|||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
v-model="filterQuery"
|
v-model="filterQuery"
|
||||||
class="input"
|
class="input"
|
||||||
|
ref="filterInput"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="filter-input-highlight" v-html="highlightedFilterQuery"></div>
|
<div
|
||||||
|
class="filter-input-highlight"
|
||||||
|
:style="{'height': height}"
|
||||||
|
v-html="highlightedFilterQuery"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.filter-input-highlight span {
|
.filter-input-highlight span {
|
||||||
&.filter-query__field {
|
&.filter-query__field {
|
||||||
color: #faf594;
|
color: #faf594;
|
||||||
}
|
}
|
||||||
@ -113,18 +123,20 @@ function escapeHtml(unsafe: string): string {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.filter-input {
|
.filter-input {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-fill-color: transparent;
|
text-fill-color: transparent;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-input-highlight {
|
.filter-input-highlight {
|
||||||
height: 2.5em;
|
height: 2.5em;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding: .5em .75em;
|
padding: .5em .75em;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -77,7 +77,7 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(['taskAdded'])
|
const emit = defineEmits(['taskAdded'])
|
||||||
|
|
||||||
const newTaskTitle = ref('')
|
const newTaskTitle = ref('')
|
||||||
const newTaskInput = useAutoHeightTextarea(newTaskTitle)
|
const {textarea: newTaskInput} = useAutoHeightTextarea(newTaskTitle)
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
@ -6,6 +6,7 @@ import {debouncedWatch, tryOnMounted, useWindowSize, type MaybeRef} from '@vueus
|
|||||||
export function useAutoHeightTextarea(value: MaybeRef<string>) {
|
export function useAutoHeightTextarea(value: MaybeRef<string>) {
|
||||||
const textarea = ref<HTMLTextAreaElement | null>(null)
|
const textarea = ref<HTMLTextAreaElement | null>(null)
|
||||||
const minHeight = ref(0)
|
const minHeight = ref(0)
|
||||||
|
const height = ref('')
|
||||||
|
|
||||||
// adapted from https://github.com/LeaVerou/stretchy/blob/47f5f065c733029acccb755cae793009645809e2/src/stretchy.js#L34
|
// adapted from https://github.com/LeaVerou/stretchy/blob/47f5f065c733029acccb755cae793009645809e2/src/stretchy.js#L34
|
||||||
function resize(textareaEl: HTMLTextAreaElement | null) {
|
function resize(textareaEl: HTMLTextAreaElement | null) {
|
||||||
@ -23,14 +24,13 @@ export function useAutoHeightTextarea(value: MaybeRef<string>) {
|
|||||||
|
|
||||||
textareaEl.style.minHeight = ''
|
textareaEl.style.minHeight = ''
|
||||||
textareaEl.style.height = '0'
|
textareaEl.style.height = '0'
|
||||||
const offset = textareaEl.offsetHeight - parseFloat(cs.paddingTop) - parseFloat(cs.paddingBottom)
|
height.value = textareaEl.scrollHeight + 'px'
|
||||||
const height = textareaEl.scrollHeight + offset + 'px'
|
|
||||||
|
|
||||||
textareaEl.style.height = height
|
textareaEl.style.height = height.value
|
||||||
|
|
||||||
// calculate min-height for the first time
|
// calculate min-height for the first time
|
||||||
if (!minHeight.value) {
|
if (!minHeight.value) {
|
||||||
minHeight.value = parseFloat(height)
|
minHeight.value = parseFloat(height.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
textareaEl.style.minHeight = minHeight.value.toString()
|
textareaEl.style.minHeight = minHeight.value.toString()
|
||||||
@ -68,5 +68,8 @@ export function useAutoHeightTextarea(value: MaybeRef<string>) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return textarea
|
return {
|
||||||
|
textarea,
|
||||||
|
height,
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user