From f7088e5d28d019f9876b71333185120b811ecb08 Mon Sep 17 00:00:00 2001 From: Rohit Sharma Date: Wed, 10 Feb 2021 00:46:13 +0530 Subject: [PATCH] Add function type for `popperConfig` option (#32882) * Add function type for `popperConfig` option * Update .bundlewatch.config.json * copy edits Co-authored-by: XhmikosR Co-authored-by: Mark Otto --- .bundlewatch.config.json | 2 +- js/src/dropdown.js | 10 ++++----- js/src/tooltip.js | 8 +++---- js/tests/unit/dropdown.spec.js | 22 +++++++++++++++++++ js/tests/unit/tooltip.spec.js | 15 +++++++++++++ site/content/docs/5.0/components/dropdowns.md | 19 ++++++++++++++-- site/content/docs/5.0/components/popovers.md | 19 ++++++++++++++-- site/content/docs/5.0/components/tooltips.md | 19 ++++++++++++++-- site/content/docs/5.0/migration.md | 1 + 9 files changed, 99 insertions(+), 16 deletions(-) diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index da47da4801..36404b38cf 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -34,7 +34,7 @@ }, { "path": "./dist/js/bootstrap.bundle.js", - "maxSize": "41 kB" + "maxSize": "42 kB" }, { "path": "./dist/js/bootstrap.bundle.min.js", diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 878a5a9a21..7221debfc2 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -86,7 +86,7 @@ const DefaultType = { boundary: '(string|element)', reference: '(string|element|object)', display: 'string', - popperConfig: '(null|object)' + popperConfig: '(null|object|function)' } /** @@ -322,7 +322,7 @@ class Dropdown extends BaseComponent { } _getPopperConfig() { - const popperConfig = { + const defaultBsPopperConfig = { placement: this._getPlacement(), modifiers: [{ name: 'preventOverflow', @@ -341,15 +341,15 @@ class Dropdown extends BaseComponent { // Disable Popper if we have a static display if (this._config.display === 'static') { - popperConfig.modifiers = [{ + defaultBsPopperConfig.modifiers = [{ name: 'applyStyles', enabled: false }] } return { - ...popperConfig, - ...this._config.popperConfig + ...defaultBsPopperConfig, + ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) } } diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 11209625cd..42da4c9385 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -58,7 +58,7 @@ const DefaultType = { sanitize: 'boolean', sanitizeFn: '(null|function)', allowList: 'object', - popperConfig: '(null|object)' + popperConfig: '(null|object|function)' } const AttachmentMap = { @@ -490,7 +490,7 @@ class Tooltip extends BaseComponent { } _getPopperConfig(attachment) { - const defaultBsConfig = { + const defaultBsPopperConfig = { placement: attachment, modifiers: [ { @@ -533,8 +533,8 @@ class Tooltip extends BaseComponent { } return { - ...defaultBsConfig, - ...this.config.popperConfig + ...defaultBsPopperConfig, + ...(typeof this.config.popperConfig === 'function' ? this.config.popperConfig(defaultBsPopperConfig) : this.config.popperConfig) } } diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js index 01d599ceb6..e97ce7717c 100644 --- a/js/tests/unit/dropdown.spec.js +++ b/js/tests/unit/dropdown.spec.js @@ -123,6 +123,28 @@ describe('Dropdown', () => { expect(popperConfig.placement).toEqual('left') }) + + it('should allow to pass config to Popper with `popperConfig` as a function', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const getPopperConfig = jasmine.createSpy('getPopperConfig').and.returnValue({ placement: 'left' }) + const dropdown = new Dropdown(btnDropdown, { + popperConfig: getPopperConfig + }) + + const popperConfig = dropdown._getPopperConfig() + + expect(getPopperConfig).toHaveBeenCalled() + expect(popperConfig.placement).toEqual('left') + }) }) describe('toggle', () => { diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js index 38af0235ba..e1d0371546 100644 --- a/js/tests/unit/tooltip.spec.js +++ b/js/tests/unit/tooltip.spec.js @@ -156,6 +156,21 @@ describe('Tooltip', () => { expect(popperConfig.placement).toEqual('left') }) + + it('should allow to pass config to Popper with `popperConfig` as a function', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const getPopperConfig = jasmine.createSpy('getPopperConfig').and.returnValue({ placement: 'left' }) + const tooltip = new Tooltip(tooltipEl, { + popperConfig: getPopperConfig + }) + + const popperConfig = tooltip._getPopperConfig('top') + + expect(getPopperConfig).toHaveBeenCalled() + expect(popperConfig.placement).toEqual('left') + }) }) describe('enable', () => { diff --git a/site/content/docs/5.0/components/dropdowns.md b/site/content/docs/5.0/components/dropdowns.md index d5efd3adbc..24353f0f4d 100644 --- a/site/content/docs/5.0/components/dropdowns.md +++ b/site/content/docs/5.0/components/dropdowns.md @@ -993,13 +993,28 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap popperConfig - null | object + null | object | function null - To change Bootstrap's default Popper config, see Popper's configuration + +

To change Bootstrap's default Popper config, see Popper's configuration.

+

When a function is used to create the Popper configuration, it's called with an object that contains the Bootstrap's default Popper configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Popper.

+ +#### Using function with `popperConfig` + +```js +var dropdown = new bootstrap.Dropdown(element, { + popperConfig: function (defaultBsPopperConfig) { + // var newPopperConfig = {...} + // use defaultBsPopperConfig if needed... + // return newPopperConfig + } +}) +``` + ### Methods diff --git a/site/content/docs/5.0/components/popovers.md b/site/content/docs/5.0/components/popovers.md index 56616fd0cd..8a2efa0a2a 100644 --- a/site/content/docs/5.0/components/popovers.md +++ b/site/content/docs/5.0/components/popovers.md @@ -279,9 +279,12 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt - + - +
popperConfignull | objectnull | object | function nullTo change Bootstrap's default Popper config, see Popper's configuration +

To change Bootstrap's default Popper config, see Popper's configuration.

+

When a function is used to create the Popper configuration, it's called with an object that contains the Bootstrap's default Popper configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Popper.

+
@@ -292,6 +295,18 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt Options for individual popovers can alternatively be specified through the use of data attributes, as explained above. {{< /callout >}} +#### Using function with `popperConfig` + +```js +var popover = new bootstrap.Popover(element, { + popperConfig: function (defaultBsPopperConfig) { + // var newPopperConfig = {...} + // use defaultBsPopperConfig if needed... + // return newPopperConfig + } +}) +``` + ### Methods {{< callout danger >}} diff --git a/site/content/docs/5.0/components/tooltips.md b/site/content/docs/5.0/components/tooltips.md index 9a5dd93931..ee6d06e9e9 100644 --- a/site/content/docs/5.0/components/tooltips.md +++ b/site/content/docs/5.0/components/tooltips.md @@ -304,9 +304,12 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt popperConfig - null | object + null | object | function null - To change Bootstrap's default Popper config, see Popper's configuration + +

To change Bootstrap's default Popper config, see Popper's configuration.

+

When a function is used to create the Popper configuration, it's called with an object that contains the Bootstrap's default Popper configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Popper.

+ @@ -317,6 +320,18 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt Options for individual tooltips can alternatively be specified through the use of data attributes, as explained above. {{< /callout >}} +#### Using function with `popperConfig` + +```js +var tooltip = new bootstrap.Tooltip(element, { + popperConfig: function (defaultBsPopperConfig) { + // var newPopperConfig = {...} + // use defaultBsPopperConfig if needed... + // return newPopperConfig + } +}) +``` + ### Methods {{< callout danger >}} diff --git a/site/content/docs/5.0/migration.md b/site/content/docs/5.0/migration.md index 6e4839348e..99a9c9e38c 100644 --- a/site/content/docs/5.0/migration.md +++ b/site/content/docs/5.0/migration.md @@ -24,6 +24,7 @@ toc: true - The default value for the `fallbackPlacements` is changed to `['top', 'right', 'bottom', 'left']` for better placement of popper elements. - All the events for the dropdown are now triggered on the dropdown toggle button and then bubbled up to the parent element. - Dropdown menus now have a `data-bs-popper="static"` attribute set when the positioning of the dropdown is static and `data-bs-popper="none"` when dropdown is in the navbar. This is added by our JavaScript and helps us use custom position styles without interfering with Popper's positioning. +- `popperConfig` can be passed as a function that accepts the Bootstrap's default Popper config as an argument, so that you can merge this default configuration in your way. ## v5.0.0-beta1