Files
jinshen-serial-tools/src/lib/components/ui/select/SelectContent.svelte

83 lines
2.3 KiB
Svelte

<script lang="ts">
import { Select as BitsSelect, type WithoutChildren } from 'bits-ui';
import { cubicOut } from 'svelte/easing';
type Props = WithoutChildren<BitsSelect.ContentProps> & {
items: { value: string; label: string; disabled?: boolean }[];
class?: string;
};
let { items, class: className = '', ...restProps }: Props = $props();
function selectTransition(
node: HTMLElement,
params: {
delay?: number;
duration?: number;
easing?: (t: number) => number;
y?: number;
start?: number;
} = {}
) {
const {
delay = 0,
duration = 200,
easing = cubicOut,
y = -6,
start = 0.95,
} = params;
const existingTransform = getComputedStyle(node).transform.replace(
'none',
''
);
return {
delay,
duration,
easing,
css: (t: number, u: number) => {
const translate = `translateY(${u * y}px)`;
const scale = `scale(${start + t * (1 - start)})`;
return `
opacity: ${t};
transform: ${existingTransform} ${translate} ${scale};
`;
},
};
}
</script>
<BitsSelect.Portal>
<BitsSelect.Content
forceMount
sideOffset={4}
class={`w-(--bits-select-anchor-width) min-w-(--bits-select-anchor-width) rounded-xl border-[1.5px] border-base-content/20 bg-base-100 select-none ${className}`}
{...restProps}
>
{#snippet child({ wrapperProps, props, open })}
{#if open}
<div {...wrapperProps}>
<div {...props} transition:selectTransition>
<BitsSelect.ScrollUpButton>up</BitsSelect.ScrollUpButton>
<BitsSelect.Viewport class="p-1">
{#each items as { value, label, disabled } (value)}
<BitsSelect.Item
{value}
{label}
{disabled}
class="outlined-hidden flex h-10 w-full items-center rounded-lg p-2 text-sm capitalize select-none data-disabled:opacity-50 data-highlighted:bg-gray-200"
>
{label}
</BitsSelect.Item>
{/each}
</BitsSelect.Viewport>
<BitsSelect.ScrollDownButton>down</BitsSelect.ScrollDownButton>
</div>
</div>
{/if}
{/snippet}
</BitsSelect.Content>
</BitsSelect.Portal>