+
diff --git a/src/lib/components/common/Select.svelte b/src/lib/components/common/Select.svelte
new file mode 100644
index 000000000..a0aaf31f1
--- /dev/null
+++ b/src/lib/components/common/Select.svelte
@@ -0,0 +1,84 @@
+
+
+
{
+ searchValue = '';
+ }}
+ selected={items.find((item) => item.value === value)}
+ onSelectedChange={(selectedItem) => {
+ value = selectedItem.value;
+ }}
+>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each filteredItems as item}
+
+ {item.label}
+
+
+
+
+ {:else}
+
+ No results found
+
+ {/each}
+
+
+
+
diff --git a/src/lib/components/icons/Check.svelte b/src/lib/components/icons/Check.svelte
new file mode 100644
index 000000000..37eb9d713
--- /dev/null
+++ b/src/lib/components/icons/Check.svelte
@@ -0,0 +1,15 @@
+
+
+
diff --git a/src/lib/components/icons/ChevronDown.svelte b/src/lib/components/icons/ChevronDown.svelte
new file mode 100644
index 000000000..16686ea3a
--- /dev/null
+++ b/src/lib/components/icons/ChevronDown.svelte
@@ -0,0 +1,15 @@
+
+
+
diff --git a/src/lib/components/icons/Search.svelte b/src/lib/components/icons/Search.svelte
new file mode 100644
index 000000000..c2dc55845
--- /dev/null
+++ b/src/lib/components/icons/Search.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/src/lib/utils/transitions/index.ts b/src/lib/utils/transitions/index.ts
new file mode 100644
index 000000000..9d919f561
--- /dev/null
+++ b/src/lib/utils/transitions/index.ts
@@ -0,0 +1,48 @@
+import { cubicOut } from 'svelte/easing';
+import type { TransitionConfig } from 'svelte/transition';
+
+type FlyAndScaleParams = {
+ y?: number;
+ start?: number;
+ duration?: number;
+};
+
+const defaultFlyAndScaleParams = { y: -8, start: 0.95, duration: 200 };
+
+export const flyAndScale = (node: Element, params?: FlyAndScaleParams): TransitionConfig => {
+ const style = getComputedStyle(node);
+ const transform = style.transform === 'none' ? '' : style.transform;
+ const withDefaults = { ...defaultFlyAndScaleParams, ...params };
+
+ const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
+ const [minA, maxA] = scaleA;
+ const [minB, maxB] = scaleB;
+
+ const percentage = (valueA - minA) / (maxA - minA);
+ const valueB = percentage * (maxB - minB) + minB;
+
+ return valueB;
+ };
+
+ const styleToString = (style: Record
): string => {
+ return Object.keys(style).reduce((str, key) => {
+ if (style[key] === undefined) return str;
+ return str + `${key}:${style[key]};`;
+ }, '');
+ };
+
+ return {
+ duration: withDefaults.duration ?? 200,
+ delay: 0,
+ css: (t) => {
+ const y = scaleConversion(t, [0, 1], [withDefaults.y, 0]);
+ const scale = scaleConversion(t, [0, 1], [withDefaults.start, 1]);
+
+ return styleToString({
+ transform: `${transform} translate3d(0, ${y}px, 0) scale(${scale})`,
+ opacity: t
+ });
+ },
+ easing: cubicOut
+ };
+};