mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
create clipboard component and update fields
This commit is contained in:
parent
0eb512fea8
commit
aec0c8d966
4 changed files with 117 additions and 81 deletions
File diff suppressed because one or more lines are too long
97
vuejs/client/src/components/Forms/Feature/Clipboard.vue
Normal file
97
vuejs/client/src/components/Forms/Feature/Clipboard.vue
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<script setup>
|
||||
import { defineProps } from "vue";
|
||||
import { contentIndex } from "@utils/tabindex.js";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Forms/Feature/Clipboard.vue
|
||||
@description This component can be add to some fields to allow to copy the value of the field.
|
||||
Additionnal clipboardClass and copyClass can be added to fit the parent container.
|
||||
@example
|
||||
{
|
||||
id: 'test-input',
|
||||
isClipboard: true,
|
||||
valueToCopy: 'yes',
|
||||
clipboadClass: 'mx-2',
|
||||
copyClass: 'mt-2',
|
||||
}
|
||||
@param {id} [id=uuidv4()] - Unique id
|
||||
@param {isClipboard} [isClipboard=false] - Display a clipboard button to copy a value
|
||||
@param {valueToCopy} [valueToCopy=""] - The value to copy
|
||||
@param {clipboadClass} [clipboadClass=""] - Additional class for the clipboard container. Useful to fit the component in a specific container.
|
||||
@param {copyClass} [copyClass=""] - The class of the copy message. Useful to fit the component in a specific container.
|
||||
*/
|
||||
|
||||
const { text, copy, copied, isSupported } = useClipboard({ legacy: true });
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
isClipboard: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
valueToCopy: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
clipboardClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
copyClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="props.isClipboard"
|
||||
:class="['input-clipboard-container', props.clipboardClass]"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
:class="['input-clipboard-button', copied ? 'copied' : 'not-copied']"
|
||||
:tabindex="contentIndex"
|
||||
@click.prevent="copy(valueToCopy)"
|
||||
:aria-describedby="`${props.id}-clipboard-text`"
|
||||
>
|
||||
<span :id="`${props.id}-clipboard-text`" class="sr-only">
|
||||
{{ $t("inp_input_clipboard_desc") }}
|
||||
</span>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="input-clipboard-svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z"
|
||||
></path>
|
||||
</svg>
|
||||
<div
|
||||
v-if="copied"
|
||||
role="alert"
|
||||
:class="['input-clipboard-copy', props.copyClass]"
|
||||
>
|
||||
{{ $t("inp_input_clipboard_copied") }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -7,12 +7,13 @@ import {
|
|||
defineProps,
|
||||
onUnmounted,
|
||||
} from "vue";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
import { contentIndex } from "@utils/tabindex.js";
|
||||
import Container from "@components/Widget/Container.vue";
|
||||
import Header from "@components/Forms/Header/Field.vue";
|
||||
import ErrorField from "@components/Forms/Error/Field.vue";
|
||||
import Clipboard from "@components/Forms/Feature/Clipboard.vue";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import "@assets/script/editor/ace.js";
|
||||
import "@assets/script/editor/theme-dracula.js";
|
||||
import "@assets/script/editor/theme-dawn.js";
|
||||
|
|
@ -44,7 +45,7 @@ import "@assets/script/editor/theme-dawn.js";
|
|||
@param {string} [pattern=""]
|
||||
@param {boolean} [disabled=false]
|
||||
@param {boolean} [required=false]
|
||||
@param {boolean} [clipboard=false] - allow to copy the input value
|
||||
@param {boolean} [isClipboard=true] - allow to copy the input value
|
||||
@param {boolean} [hideLabel=false]
|
||||
@param {string} [containerClass=""]
|
||||
@param {string} [editorClass=""]
|
||||
|
|
@ -52,8 +53,6 @@ import "@assets/script/editor/theme-dawn.js";
|
|||
@param {string|number} [tabId=contentIndex] - The tabindex of the field, by default it is the contentIndex
|
||||
*/
|
||||
|
||||
const { text, copy, copied, isSupported } = useClipboard({ legacy: true });
|
||||
|
||||
const props = defineProps({
|
||||
// id && value && method
|
||||
id: {
|
||||
|
|
@ -92,7 +91,7 @@ const props = defineProps({
|
|||
required: false,
|
||||
defaut: "",
|
||||
},
|
||||
clipboard: {
|
||||
isClipboard: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
|
|
@ -135,7 +134,6 @@ const props = defineProps({
|
|||
const editor = reactive({
|
||||
value: props.value,
|
||||
showInp: false,
|
||||
isClipAllow: false,
|
||||
isValid: computed(() => {
|
||||
if (props.required && !editor.value) return false;
|
||||
if (props.pattern) {
|
||||
|
|
@ -331,38 +329,12 @@ onUnmounted(() => {
|
|||
:aria-description="$t('inp_editor_desc')"
|
||||
:id="props.id"
|
||||
></div>
|
||||
<div v-if="props.clipboard" class="input-clipboard-container editor">
|
||||
<button
|
||||
type="button"
|
||||
:class="['input-clipboard-button', copied ? 'copied' : 'not-copied']"
|
||||
:tabindex="contentIndex"
|
||||
@click.prevent="copy(editor.value)"
|
||||
:aria-describedby="`${props.id}-clipboard-text`"
|
||||
>
|
||||
<span :id="`${props.id}-clipboard-text`" class="sr-only"
|
||||
>{{ $t("inp_input_clipboard_desc") }}
|
||||
</span>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="input-clipboard-svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z"
|
||||
></path>
|
||||
</svg>
|
||||
<div v-if="copied" role="alert" class="editor input-clipboard-copy">
|
||||
{{ $t("inp_input_clipboard_copied") }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<Clipboard
|
||||
:isClipboard="props.isClipboard"
|
||||
:clipboardClass="'editor'"
|
||||
:copyClass="'editor'"
|
||||
:valueToCopy="editor.value"
|
||||
/>
|
||||
</div>
|
||||
<ErrorField :isValid="editor.isValid" :isValue="!!editor.value" />
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import { contentIndex } from "@utils/tabindex.js";
|
|||
import Container from "@components/Widget/Container.vue";
|
||||
import Header from "@components/Forms/Header/Field.vue";
|
||||
import ErrorField from "@components/Forms/Error/Field.vue";
|
||||
import Clipboard from "@components/Forms/Feature/Clipboard.vue";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
|
||||
/**
|
||||
@name Forms/Field/Input.vue
|
||||
|
|
@ -45,7 +45,7 @@ import { useClipboard } from "@vueuse/core";
|
|||
@param {boolean} [required=false]
|
||||
@param {string} [placeholder=""]
|
||||
@param {string} [pattern="(?.*)"]
|
||||
@param {boolean} [clipboard=false] - allow to copy the input value
|
||||
@param {boolean} [isClipboard=true] - allow to copy the input value
|
||||
@param {boolean} [readonly=false] - allow to read only the input value
|
||||
@param {boolean} [hideLabel=false]
|
||||
@param {string} [containerClass=""]
|
||||
|
|
@ -54,8 +54,6 @@ import { useClipboard } from "@vueuse/core";
|
|||
@param {string|number} [tabId=contentIndex] - The tabindex of the field, by default it is the contentIndex
|
||||
*/
|
||||
|
||||
const { text, copy, copied, isSupported } = useClipboard({ legacy: true });
|
||||
|
||||
const props = defineProps({
|
||||
// id && value && method
|
||||
id: {
|
||||
|
|
@ -101,7 +99,7 @@ const props = defineProps({
|
|||
type: String,
|
||||
required: false,
|
||||
},
|
||||
clipboard: {
|
||||
isClipboard: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
|
|
@ -150,7 +148,6 @@ const inputEl = ref(null);
|
|||
const inp = reactive({
|
||||
value: props.value,
|
||||
showInp: false,
|
||||
isClipAllow: false,
|
||||
isValid: true,
|
||||
});
|
||||
|
||||
|
|
@ -212,42 +209,12 @@ onMounted(() => {
|
|||
: props.type
|
||||
"
|
||||
/>
|
||||
<div
|
||||
v-if="props.clipboard"
|
||||
:class="[props.type === 'password' ? 'pw-input' : 'no-pw-input']"
|
||||
class="input-clipboard-container"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
:class="['input-clipboard-button', copied ? 'copied' : 'not-copied']"
|
||||
:tabindex="contentIndex"
|
||||
@click.prevent="copy(inp.value)"
|
||||
:aria-describedby="`${props.id}-clipboard-text`"
|
||||
>
|
||||
<span :id="`${props.id}-clipboard-text`" class="sr-only"
|
||||
>{{ $t("inp_input_clipboard_desc") }}
|
||||
</span>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="input-clipboard-svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z"
|
||||
></path>
|
||||
</svg>
|
||||
<div v-if="copied" role="alert" class="input input-clipboard-copy">
|
||||
{{ $t("inp_input_clipboard_copied") }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<Clipboard
|
||||
:isClipboard="props.isClipboard"
|
||||
:valueToCopy="inp.value"
|
||||
:clipboardClass="props.type === 'password' ? 'pw-input' : 'no-pw-input'"
|
||||
:copyClass="'input'"
|
||||
/>
|
||||
|
||||
<div v-if="props.type === 'password'" class="input-pw-container">
|
||||
<button
|
||||
|
|
|
|||
Loading…
Reference in a new issue