Implemented Checkbox

pull/7319/merge
Cagatay Civici 2025-03-02 00:47:51 +03:00
parent e21ab4a480
commit 18848a9803
13 changed files with 462 additions and 4 deletions

View File

@ -22,6 +22,10 @@
"name": "Components",
"icon": "pi pi-compass",
"children": [
{
"name": "Checkbox",
"to": "/checkbox"
},
{
"name": "InputMask",
"to": "/inputmask"

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Binary checkbox is used with the <i>v-model</i> for two-way value binding and the <i>binary</i> property.</p>
</DocSectionText>
<div class="card flex justify-center">
<Checkbox v-model="checked" binary />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<Checkbox v-model="checked" binary />
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,35 @@
<template>
<DocSectionText v-bind="$attrs">
<p>When <i>disabled</i> is present, the element cannot be edited and focused.</p>
</DocSectionText>
<div class="card flex justify-center gap-2">
<Checkbox v-model="checked1" binary disabled />
<Checkbox v-model="checked2" binary disabled />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked1 = ref(false);
const checked2 = ref(true);
const code = ref(`
<template>
<div class="card flex justify-center gap-2">
<Checkbox v-model="checked1" binary disabled />
<Checkbox v-model="checked2" binary disabled />
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked1 = ref(false);
const checked2 = ref(true);
<\/script>
`);
</script>

View File

@ -0,0 +1,53 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Checkboxes can be generated using a list of values.</p>
</DocSectionText>
<div class="card flex justify-center">
<div class="flex flex-col gap-4">
<div v-for="category of categories" :key="category.key" class="flex items-center gap-2">
<Checkbox v-model="selectedCategories" :inputId="category.key" name="category" :value="category.name" />
<label :for="category.key">{{ category.name }}</label>
</div>
</div>
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const selectedCategories = ref(['Marketing']);
const categories = ref([
{ name: 'Accounting', key: 'A' },
{ name: 'Marketing', key: 'M' },
{ name: 'Production', key: 'P' },
{ name: 'Research', key: 'R' }
]);
const code = ref(`
<template>
<div class="card flex justify-center">
<div class="flex flex-col gap-4">
<div v-for="category of categories" :key="category.key" class="flex items-center gap-2">
<Checkbox v-model="selectedCategories" :inputId="category.key" name="category" :value="category.name" />
<label :for="category.key">{{ category.name }}</label>
</div>
</div>
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const selectedCategories = ref(['Marketing']);
const categories = ref([
{ name: 'Accounting', key: 'A' },
{ name: 'Marketing', key: 'M' },
{ name: 'Production', key: 'P' },
{ name: 'Research', key: 'R' }
]);
<\/script>
`);
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Specify the <i>variant</i> property as <i>filled</i> to display the component with a higher visual emphasis than the default <i>outlined</i> style.</p>
</DocSectionText>
<div class="card flex justify-center">
<Checkbox v-model="checked" binary variant="filled" />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<Checkbox v-model="checked" binary variant="filled" />
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,61 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Multiple checkboxes can be grouped together.</p>
</DocSectionText>
<div class="card flex flex-wrap justify-center gap-4">
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient1" name="pizza" value="Cheese" />
<label for="ingredient1"> Cheese </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient2" name="pizza" value="Mushroom" />
<label for="ingredient2"> Mushroom </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient3" name="pizza" value="Pepper" />
<label for="ingredient3"> Pepper </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient4" name="pizza" value="Onion" />
<label for="ingredient4"> Onion </label>
</div>
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const pizza = ref(null);
const code = ref(`
<template>
<div class="card flex flex-wrap justify-center gap-4">
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient1" name="pizza" value="Cheese" />
<label for="ingredient1"> Cheese </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient2" name="pizza" value="Mushroom" />
<label for="ingredient2"> Mushroom </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient3" name="pizza" value="Pepper" />
<label for="ingredient3"> Pepper </label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="pizza" inputId="ingredient4" name="pizza" value="Onion" />
<label for="ingredient4"> Onion </label>
</div>
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const pizza = ref(null);
<\/script>
`);
</script>

View File

@ -0,0 +1,16 @@
<template>
<DocSectionText v-bind="$attrs" />
<DocSectionCode :code="code" lang="script" />
</template>
<script>
export default {
data() {
return {
code: `
import Checkbox from '@/plex/checkbox';
`
};
}
};
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>When <i>indeterminate</i> is present, the checkbox masks the actual value visually.</p>
</DocSectionText>
<div class="card flex justify-center">
<Checkbox v-model="checked" indeterminate binary />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<Checkbox v-model="checked" indeterminate binary />
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,31 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Invalid state is displayed using the <i>invalid</i> prop to indicate a failed validation. You can use this style when integrating with form validation libraries.</p>
</DocSectionText>
<div class="card flex justify-center">
<Checkbox v-model="checked" :invalid="!checked" binary />
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
const code = ref(`
<template>
<div class="card flex justify-center">
<Checkbox v-model="checked" :invalid="!checked" binary />
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const checked = ref(false);
<\/script>
`);
</script>

View File

@ -0,0 +1,53 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Checkbox provides <i>small</i> and <i>large</i> sizes as alternatives to the base.</p>
</DocSectionText>
<div class="card flex flex-wrap justify-center gap-4">
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_small" name="size" value="Small" size="small" />
<label for="size_small" class="text-sm">Small</label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_normal" name="size" value="Normal" />
<label for="size_normal">Normal</label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_large" name="size" value="Large" size="large" />
<label for="size_large" class="text-lg">Large</label>
</div>
</div>
<DocSectionCode :code="code" />
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const size = ref(null);
const code = ref(`
<template>
<div class="card flex flex-wrap justify-center gap-4">
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_small" name="size" value="Small" size="small" />
<label for="size_small" class="text-sm">Small</label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_normal" name="size" value="Normal" />
<label for="size_normal">Normal</label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="size" inputId="size_large" name="size" value="Large" size="large" />
<label for="size_large" class="text-lg">Large</label>
</div>
</div>
</template>
<script setup>
import Checkbox from '@/plex/checkbox';
import { ref } from 'vue';
const size = ref(null);
<\/script>
`);
</script>

View File

@ -0,0 +1,69 @@
<template>
<DocComponent title="Vue Checkbox Component" header="Checkbox" description="Checkbox is an extension to standard checkbox element with theming." :componentDocs="docs" />
</template>
<script>
import BasicDoc from '@/doc/checkbox/BasicDoc.vue';
import DisabledDoc from '@/doc/checkbox/DisabledDoc.vue';
import DynamicDoc from '@/doc/checkbox/DynamicDoc.vue';
import FilledDoc from '@/doc/checkbox/FilledDoc.vue';
import GroupDoc from '@/doc/checkbox/GroupDoc.vue';
import ImportDoc from '@/doc/checkbox/ImportDoc.vue';
import IndeterminateDoc from '@/doc/checkbox/IndeterminateDoc.vue';
import InvalidDoc from '@/doc/checkbox/InvalidDoc.vue';
import SizesDoc from '@/doc/checkbox/SizesDoc.vue';
export default {
data() {
return {
docs: [
{
id: 'import',
label: 'Import',
component: ImportDoc
},
{
id: 'basic',
label: 'Basic',
component: BasicDoc
},
{
id: 'group',
label: 'Group',
component: GroupDoc
},
{
id: 'dynamic',
label: 'Dynamic',
component: DynamicDoc
},
{
id: 'indeterminate',
label: 'Indeterminate',
component: IndeterminateDoc
},
{
id: 'filled',
label: 'Filled',
component: FilledDoc
},
{
id: 'sizes',
label: 'Sizes',
component: SizesDoc
},
{
id: 'invalid',
label: 'Invalid',
component: InvalidDoc
},
{
id: 'disabled',
label: 'Disabled',
component: DisabledDoc
}
]
};
}
};
</script>

View File

@ -0,0 +1,33 @@
<template>
<Checkbox unstyled :pt="theme" />
</template>
<script setup>
import Checkbox from 'primevue/checkbox';
import { ref } from 'vue';
const theme = ref({
root: `relative inline-flex select-none w-5 h-5 align-bottom
p-small:w-4 p-small:h-4
p-large:w-6 p-large:h-6`,
input: `peer cursor-pointer disabled:cursor-default appearance-none absolute start-0 top-0 w-full h-full m-0 p-0 opacity-0 z-10
border border-transparent rounded-sm`,
box: `flex justify-center items-center rounded-sm w-5 h-5
border border-surface-300 dark:border-surface-700
bg-surface-0 dark:bg-surface-950
text-surface-700 dark:text-surface-0
peer-enabled:peer-hover:border-surface-400 dark:peer-enabled:peer-hover:border-surface-600
p-checked:border-primary p-checked:bg-primary p-checked:text-primary-contrast
transition-colors duration-200
p-invalid:border-red-400 dark:p-invalid:border-red-300
peer-focus-visible:outline peer-focus-visible:outline-1 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-primary
p-filled:bg-surface-50 dark:p-filled:bg-surface-800
p-disabled:bg-surface-200 dark:p-disabled:bg-surface-400 p-disabled:border-surface-300 dark:p-disabled:border-surface-700 p-disabled:text-surface-700 dark:p-disabled:text-surface-400
shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
p-small:w-4 p-small:h-4
p-large:w-6 p-large:h-6`,
icon: `text-sm w-[0.875rem] h-[0.875rem] transition-none
p-small:w-3 p-small:h-3
p-large:w-4 p-large:h-4`
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<div :class="cx('root')" v-bind="getPTOptions('root')" :data-p-checked="checked" :data-p-indeterminate="d_indeterminate || undefined" :data-p-disabled="disabled">
<div :class="cx('root')" v-bind="getPTOptions('root')" :data-p-checked="checked" :data-p-indeterminate="d_indeterminate || undefined" :data-p-disabled="disabled" :data-p="dataP">
<input
:id="inputId"
type="checkbox"
@ -21,16 +21,17 @@
@change="onChange"
v-bind="getPTOptions('input')"
/>
<div :class="cx('box')" v-bind="getPTOptions('box')">
<div :class="cx('box')" v-bind="getPTOptions('box')" :data-p="dataP">
<slot name="icon" :checked="checked" :indeterminate="d_indeterminate" :class="cx('icon')">
<CheckIcon v-if="checked" :class="cx('icon')" v-bind="getPTOptions('icon')" />
<MinusIcon v-else-if="d_indeterminate" :class="cx('icon')" v-bind="getPTOptions('icon')" />
<CheckIcon v-if="checked" :class="cx('icon')" v-bind="getPTOptions('icon')" :data-p="dataP" />
<MinusIcon v-else-if="d_indeterminate" :class="cx('icon')" v-bind="getPTOptions('icon')" :data-p="dataP" />
</slot>
</div>
</div>
</template>
<script>
import { cn } from '@primeuix/utils';
import { contains, equals } from '@primeuix/utils/object';
import CheckIcon from '@primevue/icons/check';
import MinusIcon from '@primevue/icons/minus';
@ -105,6 +106,15 @@ export default {
const value = this.$pcCheckboxGroup ? this.$pcCheckboxGroup.d_value : this.d_value;
return this.d_indeterminate ? false : this.binary ? value === this.trueValue : contains(this.value, value);
},
dataP() {
return cn({
invalid: this.$invalid,
checked: this.checked,
disabled: this.disabled,
filled: this.$variant === 'filled',
[this.size]: this.size
});
}
},
components: {