mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
start combobox component
This commit is contained in:
parent
195f292599
commit
197436c9d5
9 changed files with 583 additions and 73 deletions
|
|
@ -229,6 +229,14 @@ body {
|
|||
@apply pointer-events-none transition-transform h-4 w-4 fill-gray-600 dark:fill-gray-500;
|
||||
}
|
||||
|
||||
.select-combobox-list {
|
||||
@apply flex flex-col;
|
||||
}
|
||||
|
||||
.combobox-no-match {
|
||||
@apply text-[0.75rem] font-semibold mb-0 mt-0.5;
|
||||
}
|
||||
|
||||
.select-dropdown-container {
|
||||
@apply flex fixed h-full max-h-[200px] overflow-x-hidden overflow-y-auto flex-col w-fit mt-2;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -4,6 +4,7 @@ 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 { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Forms/Field/Checkbox.vue
|
||||
|
|
@ -29,7 +30,7 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
},
|
||||
]
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} [id=uuidv4()] - Unique id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} value
|
||||
|
|
@ -49,7 +50,8 @@ const props = defineProps({
|
|||
// id && value && method
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
columns: {
|
||||
type: [Object, Boolean],
|
||||
|
|
|
|||
463
vuejs/client/src/components/Forms/Field/Combobox.vue
Normal file
463
vuejs/client/src/components/Forms/Field/Combobox.vue
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
<script setup>
|
||||
import { ref, reactive, watch, onMounted, defineEmits, defineProps } from "vue";
|
||||
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 { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Forms/Field/Combobox.vue
|
||||
@description This component is used to create a complete combobox field input with error handling and label.
|
||||
We can be more precise by adding values that need to be selected to be valid.
|
||||
We can also add popover to display more information.
|
||||
@example
|
||||
{
|
||||
id: 'test-input',
|
||||
value: 'yes',
|
||||
values : ['yes', 'no'],
|
||||
name: 'test-input',
|
||||
disabled: false,
|
||||
required: true,
|
||||
requiredValues : ['no'], // need required to be checked
|
||||
label: 'Test select',
|
||||
inpType: "select",
|
||||
popovers : [
|
||||
{
|
||||
text: "This is a popover text",
|
||||
iconName: "info",
|
||||
iconColor: "info",
|
||||
},]
|
||||
}
|
||||
@param {string} [id=uuidv4()] - Unique id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} value
|
||||
@param {array} values
|
||||
@param {array} [popovers] - List of popovers to display more information
|
||||
@param {string} [inpType="select"] - The type of the field, useful when we have multiple fields in the same container to display the right field
|
||||
@param {boolean} [disabled=false]
|
||||
@param {boolean} [required=false]
|
||||
@param {array} [requiredValues=[]] - values that need to be selected to be valid, works only if required is true
|
||||
@param {object} [columns={"pc": "12", "tablet": "12", "mobile": "12}] - Field has a grid system. This allow to get multiple field in the same row if needed.
|
||||
@param {boolean} [hideLabel=false]
|
||||
@param {string} [containerClass=""]
|
||||
@param {string} [inpClass=""]
|
||||
@param {string} [headerClass=""]
|
||||
@param {string|number} [tabId=contentIndex] - The tabindex of the field, by default it is the contentIndex
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
// id && value && method
|
||||
id: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
columns: {
|
||||
type: [Object, Boolean],
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
values: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
inpType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "select",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
requiredValues: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
popovers: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
hideLabel: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
containerClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
headerClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
inpClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
tabId: {
|
||||
type: [String, Number],
|
||||
required: false,
|
||||
default: contentIndex,
|
||||
},
|
||||
});
|
||||
|
||||
// When mounted or when props changed, we want select to display new props values
|
||||
// When component value change itself, we want to switch to select.value
|
||||
// To avoid component to send and stick to props values (bad behavior)
|
||||
// Trick is to use select.value || props.value on template
|
||||
watch(props, (newProp, oldProp) => {
|
||||
if (newProp.value !== select.value) {
|
||||
select.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
const inp = reactive({
|
||||
value: props.value,
|
||||
isValid: false,
|
||||
});
|
||||
|
||||
const inputEl = ref();
|
||||
|
||||
const select = reactive({
|
||||
isOpen: false,
|
||||
// On mounted value is null to display props value
|
||||
// Then on new select we will switch to select.value
|
||||
// If we use select.value : props.value
|
||||
// Component will not re-render after props.value change
|
||||
value: "",
|
||||
isValid: !props.required
|
||||
? true
|
||||
: props.requiredValues.length <= 0
|
||||
? true
|
||||
: props.requiredValues.includes(props.value)
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
||||
const selectBtn = ref();
|
||||
const selectWidth = ref("");
|
||||
const selectDropdown = ref();
|
||||
|
||||
// EVENTS
|
||||
function toggleSelect() {
|
||||
select.isOpen = select.isOpen ? false : true;
|
||||
// Position dropdown relative to btn on open on fixed position
|
||||
if (select.isOpen) {
|
||||
// focus on combobox and reset value
|
||||
inp.value = "";
|
||||
inp.isValid = inputEl.value.checkValidity();
|
||||
inputEl.value.focus();
|
||||
|
||||
// setup dropdown position
|
||||
const selectBtnRect = selectBtn.value.getBoundingClientRect();
|
||||
const selectDropdownRect = selectDropdown.value.getBoundingClientRect();
|
||||
|
||||
// We need to take care of parent padding and margin that will affect dropdown position but aren't calculate in rect
|
||||
const parents = [selectBtn.value.parentElement];
|
||||
let isParent = selectBtn.value.parentElement ? true : false;
|
||||
while (isParent) {
|
||||
parents.push(parents[parents.length - 1].parentElement);
|
||||
isParent = parents[parents.length - 1].parentElement ? true : false;
|
||||
}
|
||||
|
||||
let noRectParentHeight = 0;
|
||||
for (let i = 0; i < parents.length; i++) {
|
||||
try {
|
||||
noRectParentHeight += +window
|
||||
.getComputedStyle(parents[i], null)
|
||||
.getPropertyValue("padding-top")
|
||||
.replace("px", "");
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
noRectParentHeight += +window
|
||||
.getComputedStyle(parents[i], null)
|
||||
.getPropertyValue("margin-top")
|
||||
.replace("px", "");
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// If dropdown is too close to bottom, we need to drop it up
|
||||
const canDropBeDown =
|
||||
selectBtnRect.top + selectDropdownRect.height + 20 < window.innerHeight
|
||||
? true
|
||||
: false;
|
||||
|
||||
if (canDropBeDown) {
|
||||
selectDropdown.value.style.top = `${
|
||||
window.scrollY +
|
||||
selectBtnRect.bottom +
|
||||
selectBtnRect.height * 2 -
|
||||
selectDropdownRect.height -
|
||||
noRectParentHeight +
|
||||
16
|
||||
}px`;
|
||||
}
|
||||
|
||||
if (!canDropBeDown) {
|
||||
selectDropdown.value.style.top = `${
|
||||
window.scrollY +
|
||||
selectBtnRect.top +
|
||||
selectBtnRect.height * 2 -
|
||||
selectDropdownRect.height * 2 -
|
||||
noRectParentHeight -
|
||||
24
|
||||
}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeSelect() {
|
||||
select.isOpen = false;
|
||||
}
|
||||
|
||||
function changeValue(newValue) {
|
||||
// Allow on template to switch from prop value to component own value
|
||||
// Then send the new value to parent
|
||||
select.value = newValue;
|
||||
// Check if value is required and if it is in requiredValues
|
||||
select.isValid = !props.required
|
||||
? true
|
||||
: props.requiredValues.length <= 0
|
||||
? true
|
||||
: props.requiredValues.includes(newValue)
|
||||
? true
|
||||
: false;
|
||||
closeSelect();
|
||||
return newValue;
|
||||
}
|
||||
|
||||
// Close select when clicked outside logic
|
||||
function closeOutside(e) {
|
||||
try {
|
||||
if (e.target !== selectBtn.value && e.target !== inputEl.value) {
|
||||
select.isOpen = false;
|
||||
}
|
||||
} catch (err) {
|
||||
select.isOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
function closeScroll(e) {
|
||||
if (!e.target) return;
|
||||
// Case not a DOM element (like the document itself)
|
||||
if (e.target.nodeType !== 1) return (select.isOpen = false);
|
||||
// Case DOM, check if it is the select dropdown
|
||||
if (e.target.hasAttribute("data-select-dropdown")) return;
|
||||
select.isOpen = false;
|
||||
}
|
||||
|
||||
// Close select dropdown when clicked outside element
|
||||
watch(select, () => {
|
||||
if (select.isOpen) {
|
||||
window.addEventListener("click", closeOutside);
|
||||
window.addEventListener("scroll", closeScroll, true);
|
||||
} else {
|
||||
window.removeEventListener("click", closeOutside);
|
||||
window.removeEventListener("scroll", closeScroll, true);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
selectWidth.value = `${selectBtn.value.clientWidth}px`;
|
||||
window.addEventListener("resize", () => {
|
||||
try {
|
||||
selectWidth.value = `${selectBtn.value.clientWidth}px`;
|
||||
} catch (err) {}
|
||||
});
|
||||
});
|
||||
|
||||
const emits = defineEmits(["inp"]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Container
|
||||
:containerClass="`field-container ${props.containerClass}`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Header
|
||||
:popovers="props.popovers"
|
||||
:required="props.required"
|
||||
:name="props.name"
|
||||
:label="props.label"
|
||||
:hideLabel="props.hideLabel"
|
||||
:headerClass="props.headerClass"
|
||||
/>
|
||||
|
||||
<select :name="props.name" class="hidden">
|
||||
<option
|
||||
v-for="(value, id) in props.values"
|
||||
:key="id"
|
||||
:value="value"
|
||||
@click="$emit('inp', changeValue(value))"
|
||||
:selected="
|
||||
(select.value && select.value === value) ||
|
||||
(!select.value && value === props.value)
|
||||
? true
|
||||
: false
|
||||
"
|
||||
>
|
||||
{{ value }}
|
||||
</option>
|
||||
</select>
|
||||
<!-- end default select -->
|
||||
|
||||
<!--custom-->
|
||||
<div class="relative">
|
||||
<button
|
||||
:name="`${props.name}-custom`"
|
||||
:tabindex="props.tabId"
|
||||
ref="selectBtn"
|
||||
:aria-controls="`${props.id}-custom`"
|
||||
:aria-expanded="select.isOpen ? 'true' : 'false'"
|
||||
:aria-description="$t('inp_select_dropdown_button_desc')"
|
||||
data-select-dropdown
|
||||
:disabled="props.disabled || false"
|
||||
@click.prevent="toggleSelect()"
|
||||
:class="[
|
||||
'select-btn',
|
||||
select.isValid ? 'valid' : 'invalid',
|
||||
props.inpClass,
|
||||
]"
|
||||
>
|
||||
<span :id="`${props.id}-text`" class="select-btn-name">
|
||||
{{ select.value || props.value }}
|
||||
</span>
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
role="img"
|
||||
aria-hidden="true"
|
||||
:class="[select.isOpen ? '-rotate-180' : '']"
|
||||
class="select-btn-svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"
|
||||
/>
|
||||
</svg>
|
||||
<!-- end chevron -->
|
||||
</button>
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
ref="selectDropdown"
|
||||
:style="{ width: selectWidth }"
|
||||
:id="`${props.id}-custom`"
|
||||
:class="[select.isOpen ? 'open' : 'close']"
|
||||
class="select-dropdown-container"
|
||||
:aria-hidden="select.isOpen ? 'false' : 'true'"
|
||||
:aria-expanded="select.isOpen ? 'true' : 'false'"
|
||||
:aria-description="$t('inp_select_dropdown_desc')"
|
||||
>
|
||||
<div>
|
||||
<label :class="['sr-only']" :for="`${props.id}-combobox`">
|
||||
{{ $t("inp_combobox", "inp_combobox") }}
|
||||
</label>
|
||||
<input
|
||||
:tabindex="select.isOpen ? props.tabId : '-1'"
|
||||
ref="inputEl"
|
||||
v-model="inp.value"
|
||||
@input="
|
||||
() => {
|
||||
inp.isValid = inputEl.checkValidity();
|
||||
$emit('inp', inp.value);
|
||||
}
|
||||
"
|
||||
:aria-controls="`${props.id}-list`"
|
||||
:id="`${props.id}-combobox`"
|
||||
:class="[
|
||||
'input-regular',
|
||||
inp.isValid ? 'valid' : 'invalid',
|
||||
props.inpClass,
|
||||
]"
|
||||
:placeholder="props.placeholder || ''"
|
||||
:pattern="props.pattern || '(?s).*'"
|
||||
:name="`${props.id}-combobox`"
|
||||
:value="inp.value"
|
||||
:type="'text'"
|
||||
/>
|
||||
<div
|
||||
class="select-dropdown-btn"
|
||||
v-if="!props.values.some((str) => str.includes(inp.value))"
|
||||
:aria-hidden="
|
||||
!props.values.some((str) => str.includes(inp.value))
|
||||
? 'true'
|
||||
: 'false'
|
||||
"
|
||||
role="alert"
|
||||
>
|
||||
<p class="combobox-no-match">
|
||||
{{ $t("inp_combobox_no_match", "inp_combobox_no_match") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:id="`${props.id}-list`"
|
||||
:aria-hidden="select.isOpen ? 'false' : 'true'"
|
||||
role="radiogroup"
|
||||
class="select-combobox-list"
|
||||
>
|
||||
<template v-for="(value, id) in props.values">
|
||||
<button
|
||||
v-if="value.includes(inp.value)"
|
||||
:aria-hidden="value.includes(inp.value) ? 'false' : 'true'"
|
||||
:tabindex="
|
||||
select.isOpen
|
||||
? value.includes(inp.value)
|
||||
? props.tabId
|
||||
: '-1'
|
||||
: '-1'
|
||||
"
|
||||
role="radio"
|
||||
@click.prevent="$emit('inp', changeValue(value))"
|
||||
:class="[
|
||||
id === 0 ? 'first' : '',
|
||||
id === props.values.length - 1 ? 'last' : '',
|
||||
(value === select.value && select.value === value) ||
|
||||
(!select.value && value === props.value)
|
||||
? 'active'
|
||||
: '',
|
||||
'select-dropdown-btn',
|
||||
]"
|
||||
:aria-controls="`${props.id}-text`"
|
||||
:aria-checked="
|
||||
(select.value && select.value === value) ||
|
||||
(!select.value && value === props.value)
|
||||
? 'true'
|
||||
: 'false'
|
||||
"
|
||||
>
|
||||
{{ value }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<ErrorField :isValid="select.isValid" :isValue="true" />
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end custom-->
|
||||
</Container>
|
||||
</template>
|
||||
|
|
@ -4,6 +4,7 @@ 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 { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import flatpickr from "flatpickr";
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ import "@assets/css/flatpickr.dark.css";
|
|||
},
|
||||
],
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} [id=uuidv4()] - Unique id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {array} popovers - List of popovers to display more information
|
||||
|
|
@ -57,7 +58,8 @@ const props = defineProps({
|
|||
// id && type && disabled && required && value
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ 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 { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Forms/Field/Input.vue
|
||||
|
|
@ -31,7 +32,7 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
},
|
||||
],
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} [id=uuidv4()] - Unique id
|
||||
@param {string} type - text, email, password, number, tel, url
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text. @param {string} label
|
||||
|
|
@ -56,7 +57,8 @@ const props = defineProps({
|
|||
// id && value && method
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
columns: {
|
||||
type: [Object, Boolean],
|
||||
|
|
@ -146,7 +148,6 @@ const inp = reactive({
|
|||
showInp: false,
|
||||
isClipAllow: false,
|
||||
isValid: false,
|
||||
isIndexUp: false,
|
||||
});
|
||||
|
||||
const emits = defineEmits(["inp"]);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ 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 { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Forms/Field/Select.vue
|
||||
|
|
@ -29,7 +30,7 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
iconColor: "info",
|
||||
},]
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} [id=uuidv4()] - Unique id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} value
|
||||
|
|
@ -51,7 +52,8 @@ const props = defineProps({
|
|||
// id && value && method
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: uuidv4(),
|
||||
},
|
||||
columns: {
|
||||
type: [Object, Boolean],
|
||||
|
|
@ -147,7 +149,6 @@ const select = reactive({
|
|||
: props.requiredValues.includes(props.value)
|
||||
? true
|
||||
: false,
|
||||
isIndexUp: false,
|
||||
});
|
||||
|
||||
const selectBtn = ref();
|
||||
|
|
@ -352,6 +353,7 @@ const emits = defineEmits(["inp"]);
|
|||
<div
|
||||
data-select-dropdown
|
||||
:aria-hidden="select.isOpen ? 'false' : 'true'"
|
||||
:aria-expanded="select.isOpen ? 'true' : 'false'"
|
||||
ref="selectDropdown"
|
||||
role="radiogroup"
|
||||
:style="{ width: selectWidth }"
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@
|
|||
"inp_input_error": "input is invalid",
|
||||
"inp_popover_multisite": "This setting is multisite.",
|
||||
"inp_popover_global": "This setting is global.",
|
||||
"inp_combobox": "Combobox input for relate select radio group.",
|
||||
"inp_combobox_no_match": "No match found.",
|
||||
"action_send": "send {name}",
|
||||
"action_start": "start {name}",
|
||||
"action_disable": "disable {name}",
|
||||
|
|
|
|||
|
|
@ -4,97 +4,127 @@ import Checkbox from "@components/Forms/Field/Checkbox.vue";
|
|||
import Select from "@components/Forms/Field/Select.vue";
|
||||
import Input from "@components/Forms/Field/Input.vue";
|
||||
import Datepicker from "@components/Forms/Field/Datepicker.vue";
|
||||
import Combobox from "@components/Forms/Field/Combobox.vue";
|
||||
import Button from "@components/Widget/Button.vue";
|
||||
|
||||
|
||||
const checkboxData = {
|
||||
id: 'test-checkbox',
|
||||
value: 'yes',
|
||||
name: 'test-checkbox',
|
||||
id: "test-checkbox",
|
||||
value: "yes",
|
||||
name: "test-checkbox",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: 'Test checkbox',
|
||||
tabId: '1',
|
||||
|
||||
}
|
||||
label: "Test checkbox",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const selectData = {
|
||||
id: 'test-select',
|
||||
value: 'yes',
|
||||
values: ['yes', 'no'],
|
||||
name: 'test-select',
|
||||
id: "test-select",
|
||||
value: "yes",
|
||||
values: ["yes", "no"],
|
||||
name: "test-select",
|
||||
disabled: false,
|
||||
required: false,
|
||||
requiredValues : ["no"],
|
||||
label: 'Test select',
|
||||
tabId: '1',
|
||||
}
|
||||
requiredValues: ["no"],
|
||||
label: "Test select",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const inputData = {
|
||||
id: 'test-input',
|
||||
value: 'yes',
|
||||
id: "test-input",
|
||||
value: "yes",
|
||||
type: "text",
|
||||
name: 'test-input',
|
||||
name: "test-input",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: 'Test input',
|
||||
pattern : "(test)",
|
||||
tabId: '1',
|
||||
}
|
||||
label: "Test input",
|
||||
pattern: "(test)",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const datepickerData = {
|
||||
id: 'test-datepicker',
|
||||
name: 'test-datepicker',
|
||||
id: "test-datepicker",
|
||||
name: "test-datepicker",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: 'Test datepicker',
|
||||
tabId: '1',
|
||||
}
|
||||
label: "Test datepicker",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const buttonData = {
|
||||
id: 'test-button',
|
||||
text: 'Test button',
|
||||
type: 'button',
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
|
||||
columns: {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
tabId: '1',
|
||||
}
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const buttonSVGData = {
|
||||
id: 'test-button',
|
||||
text: 'Test button',
|
||||
type: 'button',
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
|
||||
columns: {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
tabId: '1',
|
||||
iconName : "plus"
|
||||
}
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
iconName: "plus",
|
||||
};
|
||||
|
||||
const buttonOnlySVGData = {
|
||||
id: 'test-button',
|
||||
text: 'Test button',
|
||||
hideText : true,
|
||||
type: 'button',
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
hideText: true,
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
|
||||
columns: {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
tabId: '1',
|
||||
iconName : "plus"
|
||||
}
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
iconName: "plus",
|
||||
};
|
||||
|
||||
const comboboxData = {
|
||||
id: "test-combobox",
|
||||
value: "yes",
|
||||
values: ["yes", "no"],
|
||||
name: "test-combobox",
|
||||
disabled: false,
|
||||
required: false,
|
||||
requiredValues: ["no"],
|
||||
label: "Test combobox",
|
||||
tabId: "1",
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-secondary flex flex-col items-center justify-center h-full">
|
||||
<div style="width: 300px;">
|
||||
<Checkbox v-bind="checkboxData" />
|
||||
<Select v-bind="selectData" />
|
||||
<Input v-bind="inputData" />
|
||||
<Datepicker v-bind="datepickerData" />
|
||||
<Button v-bind="buttonData" />
|
||||
<Button v-bind="buttonSVGData" />
|
||||
<Button v-bind="buttonOnlySVGData" />
|
||||
</div>
|
||||
<div class="bg-secondary flex flex-col items-center justify-center h-full">
|
||||
<div style="width: 300px">
|
||||
<Checkbox v-bind="checkboxData" />
|
||||
<Select v-bind="selectData" />
|
||||
<Input v-bind="inputData" />
|
||||
<Datepicker v-bind="datepickerData" />
|
||||
<Combobox v-bind="comboboxData" />
|
||||
<Button v-bind="buttonData" />
|
||||
<Button v-bind="buttonSVGData" />
|
||||
<Button v-bind="buttonOnlySVGData" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in a new issue