mirror of
https://github.com/directus/directus.git
synced 2026-01-28 05:18:13 -05:00
Optimize slug/db-safe modes on v-input, add slug interface (#548)
* Optimize slug functionality * Add slug interface
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
10
src/interfaces/slug/index.ts
Normal file
10
src/interfaces/slug/index.ts
Normal 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: [],
|
||||
}));
|
||||
26
src/interfaces/slug/slug.vue
Normal file
26
src/interfaces/slug/slug.vue
Normal 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>
|
||||
Reference in New Issue
Block a user