diff --git a/addon/components/bs-dropdown/menu/link-to.hbs b/addon/components/bs-dropdown/menu/link-to.hbs new file mode 100644 index 000000000..d1ad2d8fe --- /dev/null +++ b/addon/components/bs-dropdown/menu/link-to.hbs @@ -0,0 +1,29 @@ +{{#if this.model}} + + {{yield}} + +{{else}} + + {{yield}} + +{{/if}} \ No newline at end of file diff --git a/addon/components/bs-dropdown/menu/link-to.js b/addon/components/bs-dropdown/menu/link-to.js index cb8cd73b4..1c0fd8507 100644 --- a/addon/components/bs-dropdown/menu/link-to.js +++ b/addon/components/bs-dropdown/menu/link-to.js @@ -1,6 +1,4 @@ -import LinkComponent from '@ember/routing/link-component'; -import { classNames } from '@ember-decorators/component'; -import { macroCondition, getOwnConfig } from '@embroider/macros'; +import LinkComponent from 'ember-bootstrap/components/bs-link-to'; /** @@ -8,8 +6,7 @@ import { macroCondition, getOwnConfig } from '@embroider/macros'; @class DropdownMenuLinkTo @namespace Components - @extends Ember.LinkComponent + @extends Ember.Component @public */ -@classNames(macroCondition(getOwnConfig().isBS4) ? 'dropdown-item' : '') export default class DropdownMenuLinkTo extends LinkComponent {} diff --git a/addon/components/bs-link-to.js b/addon/components/bs-link-to.js new file mode 100644 index 000000000..5f7bb4e3c --- /dev/null +++ b/addon/components/bs-link-to.js @@ -0,0 +1,113 @@ +/* eslint-disable ember/classic-decorator-no-classic-methods */ +import Component from '@ember/component'; +import { tagName } from '@ember-decorators/component'; +import { computed } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { assert } from '@ember/debug'; + +/** + This is largely copied from Ember.LinkComponent. It is used as extending from Ember.LinkComponent has been deprecated. + We need this to + * register ourselves to a parent component that needs to know `active` state due to Bootstrap markup requirements, see Nav/LinkTo + * continue supporting positional params until we can remove support + + @class LinkComponent + @namespace Components + @extends Component + @private +*/ +@tagName('') +class LinkComponent extends Component { + // We still need to use the private service, so this component can react to changes of `currentState`, e.g. changing + // the model while the route in unchanged. + // eslint-disable-next-line ember/no-private-routing-service + @service('-routing') + _routing; + + @computed('models', 'query', 'route', '_routing.currentState', 'current-when') + get active() { + let state = this._routing.currentState; + + if (state) { + return this._isActive(state); + } else { + return false; + } + } + + @computed('model', 'models') + get _models() { + let { model, models } = this; + + if (model !== undefined) { + return [model]; + } else if (models !== undefined) { + assert('The `@models` argument must be an array.', Array.isArray(models)); + return models; + } else { + return []; + } + } + + _isActive(routerState) { + let currentWhen = this['current-when']; + + if (typeof currentWhen === 'boolean') { + return currentWhen; + } + + let { _models: models, _routing: routing } = this; + + if (typeof currentWhen === 'string') { + return currentWhen + .split(' ') + .some((route) => routing.isActiveForRoute(models, undefined, this._namespaceRoute(route), routerState)); + } else { + return routing.isActiveForRoute(models, this.query || {}, this.route, routerState); + } + } + + // eslint-disable-next-line ember/no-component-lifecycle-hooks + didReceiveAttrs() { + super.didReceiveAttrs(...arguments); + + let { params } = this; + if (!params || params.length === 0) { + return; + } + + params = params.slice(); + + // Process the positional arguments, in order. + // 1. Inline link title comes first, if present. + // if (!hasBlock) { + // this.set('linkTitle', params.shift()); + // } + + // 2. The last argument is possibly the `query` object. + let queryParams = params[params.length - 1]; + + if (queryParams && queryParams.isQueryParams) { + this.set('query', params.pop().values); + } else { + this.set('query', undefined); + } + + // 3. If there is a `route`, it is now at index 0. + if (params.length === 0) { + this.set('route', undefined); + } else { + this.set('route', params.shift()); + } + + // 4. Any remaining indices (if any) are `models`. + this.set('model', undefined); + this.set('models', params); + } +} + +LinkComponent.reopenClass({ + positionalParams: 'params', +}); + +export default LinkComponent; diff --git a/addon/components/bs-nav/item.js b/addon/components/bs-nav/item.js index 0801d32e7..0f273f4b2 100644 --- a/addon/components/bs-nav/item.js +++ b/addon/components/bs-nav/item.js @@ -4,7 +4,7 @@ import { filter, filterBy, gt } from '@ember/object/computed'; import Component from '@ember/component'; import { action } from '@ember/object'; import { scheduleOnce } from '@ember/runloop'; -import LinkComponent from '@ember/routing/link-component'; +import LinkComponent from 'ember-bootstrap/components/bs-link-to'; import ComponentParent from 'ember-bootstrap/mixins/component-parent'; import overrideableCP from 'ember-bootstrap/utils/cp/overrideable'; import { assert } from '@ember/debug'; diff --git a/addon/components/bs-nav/link-to.hbs b/addon/components/bs-nav/link-to.hbs new file mode 100644 index 000000000..d875a7bb9 --- /dev/null +++ b/addon/components/bs-nav/link-to.hbs @@ -0,0 +1,29 @@ +{{#if this.model}} + + {{yield}} + +{{else}} + + {{yield}} + +{{/if}} \ No newline at end of file diff --git a/addon/components/bs-nav/link-to.js b/addon/components/bs-nav/link-to.js index d7321c212..206b71fed 100644 --- a/addon/components/bs-nav/link-to.js +++ b/addon/components/bs-nav/link-to.js @@ -1,7 +1,5 @@ -import LinkComponent from '@ember/routing/link-component'; +import LinkComponent from 'ember-bootstrap/components/bs-link-to'; import ComponentChild from 'ember-bootstrap/mixins/component-child'; -import { classNames } from '@ember-decorators/component'; -import { macroCondition, getOwnConfig } from '@embroider/macros'; /** @@ -9,9 +7,8 @@ import { macroCondition, getOwnConfig } from '@embroider/macros'; @class NavLinkTo @namespace Components - @extends Ember.LinkComponent + @extends Ember.Component @uses Mixins.ComponentChild @public */ -@classNames(macroCondition(getOwnConfig().isBS4) ? 'nav-link' : '') export default class NavLinkTo extends LinkComponent.extend(ComponentChild) {} diff --git a/addon/components/bs-navbar/link-to.hbs b/addon/components/bs-navbar/link-to.hbs new file mode 100644 index 000000000..e7f3a7f3f --- /dev/null +++ b/addon/components/bs-navbar/link-to.hbs @@ -0,0 +1,14 @@ + + {{yield}} + \ No newline at end of file diff --git a/addon/components/bs-navbar/link-to.js b/addon/components/bs-navbar/link-to.js index bdcaf558d..285258780 100644 --- a/addon/components/bs-navbar/link-to.js +++ b/addon/components/bs-navbar/link-to.js @@ -1,6 +1,5 @@ -import BsNavLinkToComponent from 'ember-bootstrap/components/bs-nav/link-to'; -import defaultValue from 'ember-bootstrap/utils/default-decorator'; - +import Component from '@glimmer/component'; +import { action } from '@ember/object'; /** * Extended `{{link-to}}` component for use within Navbars. * @@ -9,25 +8,18 @@ import defaultValue from 'ember-bootstrap/utils/default-decorator'; * @extends Components.NavLinkTo * @public */ -export default class NavbarLinkTo extends BsNavLinkToComponent { +export default class NavbarLinkTo extends Component { /** * @property collapseNavbar * @type {Boolean} * @default true * @public */ - @defaultValue - collapseNavbar = true; - - /** - * @event onCollapse - * @private - */ - onCollapse() {} - click() { - if (this.collapseNavbar) { - this.onCollapse(); + @action + onClick() { + if (this.args.collapseNavbar ?? true) { + this.args.onCollapse(); } } }