From a66d90cf4aff24594e765820bf7706da46593389 Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 7 Mar 2025 14:17:03 -0500 Subject: [PATCH 1/3] added fixed position prop, enabling dropdown to expand beyond the parent element --- package.json | 7 ++- src/lib/MultiSelect.svelte | 37 ++++++++++++- src/routes/(demos)/portal/+page.svx | 85 +++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 src/routes/(demos)/portal/+page.svx diff --git a/package.json b/package.json index 575feda3..ac5341dc 100644 --- a/package.json +++ b/package.json @@ -48,14 +48,17 @@ "rehype-slug": "^6.0.0", "svelte-check": "^4.0.5", "svelte-multiselect": "^10.3.0", + "svelte-popperjs": "^1.3.2", "svelte-preprocess": "^6.0.3", "svelte-toc": "^0.5.9", - "svelte-zoo": "^0.4.13", + "svelte-zoo": "^0.4.12", "svelte2tsx": "^0.7.22", "typescript": "5.6.3", "typescript-eslint": "^8.11.0", "vite": "^5.4.9", - "vitest": "^2.1.3" + "vitest": "^2.1.3", + "tippy": "^0.0.0", + "tippy.js": "^6.2.5" }, "keywords": [ "svelte", diff --git a/src/lib/MultiSelect.svelte b/src/lib/MultiSelect.svelte index 582eb2fb..eb871068 100644 --- a/src/lib/MultiSelect.svelte +++ b/src/lib/MultiSelect.svelte @@ -1,11 +1,13 @@ + + +# Fixed Position +Often times you want the dropdown to escape a modal or a parent that forces the dropdown to scroll inside of it. + +svelte-popper.js is used to position the dropdown. By default it is in absolute mode, but by specifying the fixed prop it sets popper.js to fixed mode, enabling the dropdown to expand outside of it's parent. + +Below is an example where fixed position is useful, a div that has a fixed height and scroll. + +```css + +``` + + + + +## Without fixed + +
+ +```svelte example stackblitz id="without-fixed" + + +
+ + +
+ + +``` + +## With fixed + +the fixed prop enables the dropdown to be positioned fixed, and + +
+ +```svelte example stackblitz id="with-fixed" + + +
+ + +
+ + +``` \ No newline at end of file From 7a7442a409e49293f1ac763de00314215bfd631e Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 7 Mar 2025 14:30:44 -0500 Subject: [PATCH 2/3] added test-results to .gitignore, updated readme to include documentation for the new prop, updated how we apply popper.js so that it uses the default rendering system rather than popper.js by default --- .gitignore | 1 + readme.md | 5 +++++ src/lib/MultiSelect.svelte | 23 +++++++++++++++-------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 8c2a1ce0..645e47c5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ dist # test coverage reports coverage +text-results/ \ No newline at end of file diff --git a/readme.md b/readme.md index 84802297..ec8530b1 100644 --- a/readme.md +++ b/readme.md @@ -423,6 +423,11 @@ Full list of props/bindable variables for this component. The `Option` type you If `maxSelect={1}`, `value` will be the single item in `selected` (or `null` if `selected` is empty). If `maxSelect != 1`, `maxSelect` and `selected` are equal. Warning: Setting `value` does not rendered state on initial mount, meaning `bind:value` will update local variable `value` whenever internal component state changes but passing a `value` when component first mounts won't be reflected in UI. This is because the source of truth for rendering is `bind:selected`. `selected` is reactive to `value` internally but only on reassignment from initial value. Suggestions for better solutions than [#249](https://github.com/janosh/svelte-multiselect/issues/249) welcome! +1. ```ts + fixed: boolean | null = false + ``` + if fixed is set, will cause the dropdown to be rendered with popper.js fixed strategy, enabling the dropdown to expand outside it's parent. This is good for modals / scrollable containers. + ## 🎰   Slots `MultiSelect.svelte` accepts the following named slots: diff --git a/src/lib/MultiSelect.svelte b/src/lib/MultiSelect.svelte index eb871068..368d1d60 100644 --- a/src/lib/MultiSelect.svelte +++ b/src/lib/MultiSelect.svelte @@ -84,14 +84,12 @@ export let ulOptionsStyle: string | null = null export let value: Option | Option[] | null = null - export let fixed: boolean | undefined = false + export let fixed: boolean | null = false - export let popperOptions: Record = { + let popperOptions: Record = { placement: 'bottom-start', strategy: fixed ? 'fixed' : 'absolute', - modifiers: [ - { name: 'flip', options: { fallbackPlacements: ['top-start'] } }, - ], + modifiers: [{ name: 'flip', options: { fallbackPlacements: ['top-start'] } }], } const [popperRef, popperContent, popperInstance] = createPopperActions(popperOptions) @@ -102,9 +100,11 @@ if (outerDiv && fixed) { dropdownTransition = 'none' dropdownWidth = outerDiv.offsetWidth + 'px' - + // needs to be called so that popper can set the bounds to outerDiv once it's been rendered - tick().then(()=>{popperInstance()?.update()}) + tick().then(() => { + popperInstance()?.update() + }) } }) @@ -112,6 +112,13 @@ $: if (fixed && outerDiv) { dropdownWidth = outerDiv.offsetWidth + 'px' } + function popperContentOptional(node: HTMLElement) { + if (fixed) { + return popperContent(node) + } + return {} + } + const selected_to_value = (selected: Option[]) => { value = maxSelect === 1 ? (selected[0] ?? null) : selected } @@ -666,7 +673,7 @@ {#if (searchText && noMatchingOptionsMsg) || options?.length > 0}
    Date: Fri, 7 Mar 2025 19:39:12 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .gitignore | 2 +- src/routes/(demos)/portal/+page.svx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 645e47c5..7bbb37c4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ dist # test coverage reports coverage -text-results/ \ No newline at end of file +text-results/ diff --git a/src/routes/(demos)/portal/+page.svx b/src/routes/(demos)/portal/+page.svx index 92f8cff9..62421014 100644 --- a/src/routes/(demos)/portal/+page.svx +++ b/src/routes/(demos)/portal/+page.svx @@ -55,7 +55,7 @@ Below is an example where fixed position is useful, a div that has a fixed heigh ## With fixed -the fixed prop enables the dropdown to be positioned fixed, and +the fixed prop enables the dropdown to be positioned fixed, and
    @@ -82,4 +82,4 @@ the fixed prop enables the dropdown to be positioned fixed, and background-color: #00023A; } -``` \ No newline at end of file +```