Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
iNeoO committed Oct 10, 2024
1 parent 3fea129 commit fbe7981
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 70 deletions.
13 changes: 12 additions & 1 deletion packages/frontend-bo/src/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,23 @@ const consentCookie = useCookie("VAO_BO_consent", {
function acceptAll() {
consentCookie.value = true;
}
const options = [1, 2, 3, 4, 5, 6, 7, 8];
const values = ref([]);
</script>

<template>
<div>
<DsfrToaster />
<dsfr-multi-select />
<div style="padding-left: 5rem; padding-right: 5rem">
{{ values }}
<dsfr-multi-select
v-model="values"
:options="options"
search
select-all
/>
</div>
<div class="fr-container">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12">
Expand Down
198 changes: 181 additions & 17 deletions packages/shared/src/components/DsfrMultiSelect.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts" setup generic="T">
import { useId, ref, onMounted } from "vue";
<script lang="ts" setup generic="T extends Object">
import { useId, ref, computed } from "vue";
import { usePopper } from "../composables/usePopper";
const props = withDefaults(
defineProps<{
modelValue: T[] | string[] | number[];
modelValue: string[] | number[];
options: T[] | string[] | number[];
label?: string;
name?: string;
Expand All @@ -25,7 +25,7 @@ const props = withDefaults(
name: "",
description: "",
legend: "",
selectId: useId(),
selectId: "",
buttonLabel: "",
selectAll: false,
search: false,
Expand All @@ -35,10 +35,14 @@ const props = withDefaults(
},
);
const id = props.selectId || useId();
const host = ref<HTMLButtonElement | null>(null);
const popover = ref<null | HTMLElement>(null);
const model = defineModel();

Check warning on line 42 in packages/shared/src/components/DsfrMultiSelect.vue

View workflow job for this annotation

GitHub Actions / lint-format-test

Prop "modelValue" should define at least its type
const { hostSize, hostPosition, popoverPosition } = usePopper(host, popover);
const { hostSize, hostPosition, popoverPosition, activeTracking } =
usePopper(host);
defineSlots<{
label: () => any;
Expand All @@ -48,20 +52,35 @@ defineSlots<{
}>();
const handleClick = (event: MouseEvent) => {
const button = event.target as HTMLButtonElement;
button.getBoundingClientRect();
activeTracking.value = !isVisible.value;
isVisible.value = !isVisible.value;
};
const isVisible = ref(false);
const searchInput = ref("");
const filterdOptions = computed(() =>
props.options.filter((option) => {
if (typeof option === "object" && option !== null) {
return props.filteringKeys.some((key) =>
`${option[key]}`.includes(searchInput.value),
);
}
return `${option}`.includes(searchInput.value);
}),
);
</script>

<template>
{{ hostPosition }}
{{ hostSize }}
<div class="preview-wrapper fr-py-6v">
{{ hostPosition }}
{{ hostSize }}
<div v-for="(option, index) in filterdOptions" :key="index">
<input type="checkbox" :id="index" :value="option" v-model="model" />
<label :for="index">{{ option }}</label>
</div>
<div class="fr-select-group">
<label class="fr-label" :for="props.selectId">
<slot name="label">
{{ props.label }}
</slot>
<label class="fr-label" :for="id">
<slot name="label"> {{ props.label }} totoot </slot>
<slot name="required-tip">
<span v-if="props.required" class="required">&nbsp;*</span>
</slot>
Expand All @@ -73,7 +92,7 @@ const handleClick = (event: MouseEvent) => {
</span>
</label>
<button
:id="props.selectId"
:id="id"
ref="host"
class="fr-select fr-multi-select"
@click="handleClick"
Expand All @@ -84,14 +103,118 @@ const handleClick = (event: MouseEvent) => {
</button>
<Teleport to="body">
<div
v-if="isVisible"
ref="popover"
:style="{
left: `${popoverPosition.x}px`,
top: `${popoverPosition.y}px`,
'--left-position': `${popoverPosition.x}px`,
'--top-position': `${popoverPosition.y}px`,
'--width-host': `${hostSize.width}px`,
}"
class="fr-multi-select__popover"
>
cocucoucouc {{ popoverPosition }}
<ul v-if="props.selectAll" class="fr-btns-group">
<li>
<button class="fr-btn fr-btn--sm fr-btn--secondary">
<span class="fr-icon-check-line"></span>
Tout sélectionner
</button>
</li>
</ul>
<div v-if="props.search" class="fr-input-group">
<div class="fr-input-wrap fr-icon-search-line">
<input
class="fr-input"
placeholder="Rechercher"
:aria-describedby="`${id}-text-input-icon-messages`"
type="text"
/>
</div>
<div
:id="`${id}-text-input-icon-messages`"
class="fr-messages-group"
aria-live="assertive"
></div>
</div>
<fieldset
:id="`${id}-checkboxes`"
class="fr-fieldset"
aria-labelledby="checkboxes-legend checkboxes-messages"
>
<legend
:id="`${id}-checkboxes-legend`"
class="fr-fieldset__legend--regular fr-fieldset__legend"
>
Légende pour l’ensemble des éléments
</legend>
<div
v-for="option in filterdOptions"
:key="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${option[props.idKey]}`
: `${option}`
"
class="fr-fieldset__element"
>
<div class="fr-checkbox-group fr-checkbox-group--sm">
<input
:id="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${option[props.idKey]}`
: `${option}`
"
v-model="model"
type="checkbox"
:aria-describedby="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${id}-${option[props.idKey]}-message`
: `${id}-${option}-message`
"
:value="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${option[props.idKey]}`
: `${option}`
"
/>
<label
class="fr-label"
:for="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${id}-${option[props.idKey]}-message`
: `${id}-${option}-message`
"
>
{{
typeof option === "object" &&
props.labelKey &&
props.labelKey in option
? `${option[props.labelKey]}`
: `${option}`
}}
</label>
<div
:id="
typeof option === 'object' &&
props.idKey &&
props.idKey in option
? `${id}-${option[props.idKey]}-message`
: `${id}-${option}-message`
"
class="fr-messages-group"
aria-live="assertive"
/>
</div>
</div>
</fieldset>
</div>
</Teleport>
</div>
Expand Down Expand Up @@ -131,7 +254,48 @@ const handleClick = (event: MouseEvent) => {
}
.fr-multi-select__popover {
z-index: 20000;
position: absolute;
transform-origin: left top;
width: var(--width-host);
left: var(--left-position);
top: var(--top-position);
padding: 1rem;
margin-top: 4px;
background-image: conic-gradient(
from -33.69deg at 50% 100%,
transparent 0deg,
var(--background-overlap-grey) 0deg,
var(--background-overlap-grey) 67.38deg,
transparent 67.38deg
),
conic-gradient(
from -33.69deg at 50% 100%,
transparent 0deg,
var(--border-default-grey) 0deg,
var(--border-default-grey) 67.38deg,
transparent 67.38deg
),
linear-gradient(
90deg,
var(--border-default-grey),
var(--border-default-grey)
),
linear-gradient(
90deg,
var(--background-overlap-grey),
var(--background-overlap-grey)
);
background-position:
50% calc(100% - 0.5rem),
50% calc(100% - 0.375rem),
50% calc(100% - 0.75rem),
50% calc(100% - 0.75rem);
background-repeat: no-repeat;
background-size:
0.5rem 0.375rem,
0.5rem 0.375rem,
100% 1px,
100% calc(100% - 0.75rem);
}
</style>
Loading

0 comments on commit fbe7981

Please sign in to comment.