Optimize slug/db-safe modes on v-input, add slug interface (#548)

* Optimize slug functionality

* Add slug interface
This commit is contained in:
Rijk van Zanten
2020-05-11 12:58:07 -04:00
committed by GitHub
parent 34b71dc584
commit 62ef2bb59a
4 changed files with 76 additions and 0 deletions

View File

@@ -122,6 +122,7 @@ export default defineComponent({
const _listeners = computed(() => ({
...listeners,
input: emitValue,
keydown: processValue,
}));
const hasClick = computed(() => {
@@ -130,11 +131,48 @@ export default defineComponent({
return { _listeners, hasClick, stepUp, stepDown, input };
function processValue(event: KeyboardEvent) {
const key = event.key.toLowerCase();
const systemKeys = ['meta', 'shift', 'alt', 'backspace'];
const value = (event.target as HTMLInputElement).value;
if (props.slug === true) {
const slugSafeCharacters = 'abcdefghijklmnopqrstuvwxyz01234567890-_~ '.split('');
const isAllowed = slugSafeCharacters.includes(key) || systemKeys.includes(key);
if (isAllowed === false) {
event.preventDefault();
}
if (key === ' ' && value.endsWith(props.slugSeparator)) {
event.preventDefault();
}
}
if (props.slug === true) {
const dbSafeCharacters = 'abcdefghijklmnopqrstuvwxyz01234567890-_~ '.split('');
const isAllowed = dbSafeCharacters.includes(key) || systemKeys.includes(key);
if (isAllowed === false) {
event.preventDefault();
}
// Prevent leading number
if (value.length === 0 && '0123456789'.split('').includes(key)) {
event.preventDefault();
}
}
}
function emitValue(event: InputEvent) {
let value = (event.target as HTMLInputElement).value;
if (props.slug === true) {
const endsWithSpace = value.endsWith(' ');
value = slugify(value, { separator: props.slugSeparator });
if (endsWithSpace) value += props.slugSeparator;
}
if (props.dbSafe === true) {

View File

@@ -16,6 +16,7 @@ import InterfaceIcon from './icon';
import InterfaceManyToOne from './many-to-one';
import InterfaceOneToMany from './one-to-many';
import InterfaceHash from './hash';
import InterfaceSlug from './slug';
export const interfaces = [
InterfaceTextInput,
@@ -36,6 +37,7 @@ export const interfaces = [
InterfaceManyToOne,
InterfaceOneToMany,
InterfaceHash,
InterfaceSlug,
];
export default interfaces;

View File

@@ -0,0 +1,10 @@
import { defineInterface } from '@/interfaces/define';
import InterfaceSlug from './slug.vue';
export default defineInterface(({ i18n }) => ({
id: 'slug',
name: i18n.t('slug'),
icon: 'link',
component: InterfaceSlug,
options: [],
}));

View File

@@ -0,0 +1,26 @@
<template>
<v-input :value="value" :disabled="disabled" @input="$emit('input', $event)" slug />
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
export default defineComponent({
props: {
value: {
type: String,
default: null,
},
disabled: {
type: Boolean,
default: null,
},
},
});
</script>
<style lang="scss" scoped>
.v-input {
--v-input-font-family: var(--family-monospace);
}
</style>