Files
windmill/frontend/src/lib/components/multiselect/MultiSelectWrapper.svelte
Faton Ramadani 4f0e111563 feat(frontend): event handlers (#3902)
* feat(frontend): wip

* feat(frontend): wip

* feat(frontend): wip

* feat(frontend): wip

* feat(frontend): wip

* feat(frontend): done

* feat(frontend): dark mode

* feat(frontend): fix dark mode + width issue

* feat(frontend): fix dark mode + width issue

* feat(frontend): fix layout

* feat(frontend): done

* feat(frontend): fix wording
2024-06-13 15:57:14 +02:00

98 lines
2.6 KiB
Svelte

<script lang="ts">
// @ts-ignore
import Portal from 'svelte-portal'
import { createFloatingActions } from 'svelte-floating-ui'
import { tick } from 'svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import MultiSelect from '$lib/components/multiselect/MultiSelect.svelte'
import DarkModeObserver from '../DarkModeObserver.svelte'
const [floatingRef, floatingContent] = createFloatingActions({
strategy: 'absolute',
middleware: [offset(5), flip(), shift()]
})
export let items: any[]
export let value: string[] | undefined = [] as string[]
let outerDiv: HTMLDivElement | undefined = undefined
let portalRef: HTMLDivElement | undefined = undefined
function moveOptionsToPortal() {
// Find ul element with class 'options' within the outerDiv
const ul = outerDiv?.querySelector('.options')
if (ul) {
// Move the ul element to the portal
portalRef?.appendChild(ul)
}
}
$: if (portalRef && outerDiv && items?.length > 0) {
tick().then(() => {
moveOptionsToPortal()
})
}
// bg-indigo-100 text-indigo-800 dark:bg-indigo-200 dark:text-indigo-900
let darkMode: boolean = false
let w = 0
let open: boolean = false
</script>
<DarkModeObserver bind:darkMode />
<div use:floatingRef bind:clientWidth={w}>
{#if !value || Array.isArray(value)}
<div class="border rounded-md border-gray-300 shadow-sm dark:border-gray-600 !w-full">
<MultiSelect
outerDivClass={`!text-xs`}
ulSelectedClass="overflow-auto"
bind:outerDiv
--sms-border={'none'}
--sms-min-height={'30px'}
--sms-focus-border={'none'}
--sms-selected-bg={darkMode ? '#c7d2fe' : '#e0e7ff'}
--sms-selected-text-color={darkMode ? '#312e81' : '#3730a3'}
bind:selected={value}
options={items}
on:close={() => {
open = false
}}
on:open={() => {
open = true
}}
let:option
disableRemoveAll
>
<!-- needed because portal doesn't work for mouseup event en mobile -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="w-full text-sm"
on:mouseup|stopPropagation
on:pointerdown|stopPropagation={(e) => {
let newe = new MouseEvent('mouseup')
e.target?.['parentElement']?.dispatchEvent(newe)
}}
>
{option}
</div>
</MultiSelect>
</div>
<Portal>
<div use:floatingContent class="z5000" hidden={!open}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
bind:this={portalRef}
class="multiselect"
style={`min-width: ${w}px;`}
on:click|stopPropagation
/>
</div>
</Portal>
{:else}
Value {value} is not an array
{/if}
</div>