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 da47da480..36404b38c 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 878a5a9a2..7221debfc 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 11209625c..42da4c938 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 01d599ceb..e97ce7717 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 38af0235b..e1d037154 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 d5efd3adb..24353f0f4 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 56616fd0c..8a2efa0a2 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 9a5dd9393..ee6d06e9e 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 6e4839348..99a9c9e38 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