From 2501a1fa659463f36b5788c2512a4b24d4bfce1d Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Tue, 22 Apr 2025 15:21:42 -0700 Subject: [PATCH 1/5] fix(components): `LinkToExtrnal` & make `ember-engines` optional --- packages/components/package.json | 8 +++- .../src/components/hds/breadcrumb/item.hbs | 48 ++++++------------- .../src/components/hds/breadcrumb/item.ts | 29 ++++++++++- .../src/components/hds/interactive/index.hbs | 27 ++++------- .../src/components/hds/interactive/index.ts | 29 +++++++++++ 5 files changed, 87 insertions(+), 54 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index 47667a78c11..971faa4b2e3 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -120,7 +120,13 @@ "webpack": "^5.97.1" }, "peerDependencies": { - "ember-source": "^3.28.0 || ^4.0.0 || ^5.3.0" + "ember-source": "^3.28.0 || ^4.0.0 || ^5.3.0", + "ember-engines": ">= 0.11.0" + }, + "peerDependenciesMeta": { + "ember-engines": { + "optional": true + } }, "ember": { "edition": "octane" diff --git a/packages/components/src/components/hds/breadcrumb/item.hbs b/packages/components/src/components/hds/breadcrumb/item.hbs index 1f500761608..1504579f72f 100644 --- a/packages/components/src/components/hds/breadcrumb/item.hbs +++ b/packages/components/src/components/hds/breadcrumb/item.hbs @@ -13,38 +13,20 @@ {{@text}} {{else}} - {{#if @isRouteExternal}} - - {{#if @icon}} -
- -
- {{/if}} - {{@text}} -
- {{else}} - - {{#if @icon}} -
- -
- {{/if}} - {{@text}} -
- {{/if}} + + {{#if @icon}} +
+ +
+ {{/if}} + {{@text}} +
{{/if}} \ No newline at end of file diff --git a/packages/components/src/components/hds/breadcrumb/item.ts b/packages/components/src/components/hds/breadcrumb/item.ts index a3c5f970bb0..20adfabb01a 100644 --- a/packages/components/src/components/hds/breadcrumb/item.ts +++ b/packages/components/src/components/hds/breadcrumb/item.ts @@ -6,8 +6,16 @@ import Component from '@glimmer/component'; import { htmlSafe } from '@ember/template'; import { assert } from '@ember/debug'; +import { LinkTo } from '@ember/routing'; +import { + dependencySatisfies, + importSync, + macroCondition, +} from '@embroider/macros'; + +import type Owner from '@ember/owner'; import type { SafeString } from '@ember/template'; -import type { HdsIconSignature } from '../icon'; +import type { HdsIconSignature } from '../icon/index'; export interface HdsBreadcrumbItemSignature { Args: { @@ -27,6 +35,25 @@ export interface HdsBreadcrumbItemSignature { } export default class HdsBreadcrumbItem extends Component { + linkToComponent = LinkTo; + + constructor(owner: Owner, args: HdsBreadcrumbItemSignature['Args']) { + super(owner, args); + + if (this.args.isRouteExternal) { + if (macroCondition(dependencySatisfies('ember-engines', '*'))) { + // @ts-expect-error: shape is unknown + this.linkToComponent = importSync( + 'ember-engines/components/link-to-external-component.js' + ).default as LinkTo; + } else { + assert( + `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, + false + ); + } + } + } /** * @param maxWidth * @type {string} diff --git a/packages/components/src/components/hds/interactive/index.hbs b/packages/components/src/components/hds/interactive/index.hbs index 64a7aa39ee7..b13008f390f 100644 --- a/packages/components/src/components/hds/interactive/index.hbs +++ b/packages/components/src/components/hds/interactive/index.hbs @@ -2,25 +2,14 @@ {{! IMPORTANT: we need to add "squishies" here (~) because otherwise the whitespace added by Ember becomes visible in the link (being an inline element) - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }} {{! NOTICE: we can't support the direct use of the "href" HTML attribute via ...attributes in the elements, because we need to rely on the "@href" Ember argument to differentiate between different types of generated output }} {{~#if @route~}} - {{~#if this.isRouteExternal~}} - {{yield}} - {{~else~}} - {{yield}} - {{~/if~}} + {{yield}} {{~else if @href~}} {{~#if this.isHrefExternal~}} {{yield}} diff --git a/packages/components/src/components/hds/interactive/index.ts b/packages/components/src/components/hds/interactive/index.ts index d299065389a..5d9c011c72b 100644 --- a/packages/components/src/components/hds/interactive/index.ts +++ b/packages/components/src/components/hds/interactive/index.ts @@ -5,6 +5,15 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; +import { assert } from '@ember/debug'; +import { LinkTo } from '@ember/routing'; +import { + dependencySatisfies, + importSync, + macroCondition, +} from '@embroider/macros'; + +import type Owner from '@ember/owner'; export interface HdsInteractiveSignature { Args: { @@ -27,6 +36,26 @@ export interface HdsInteractiveSignature { } export default class HdsInteractive extends Component { + linkToComponent = LinkTo; + + constructor(owner: Owner, args: HdsInteractiveSignature['Args']) { + super(owner, args); + + if (this.args.isRouteExternal) { + if (macroCondition(dependencySatisfies('ember-engines', '*'))) { + // @ts-expect-error: shape is unknown + this.linkToComponent = importSync( + 'ember-engines/components/link-to-external-component.js' + ).default as LinkTo; + } else { + assert( + `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, + false + ); + } + } + } + /** * Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer") * From 91175f1e6aef1cc2bd8cf070896c164ea43cb887 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Thu, 24 Apr 2025 01:34:51 -0700 Subject: [PATCH 2/5] fix(components): convert common code to the new `hdsResolveLinkToComponent ` helper function --- packages/components/package.json | 1 + .../src/components/hds/breadcrumb/item.ts | 28 ++-------------- .../src/components/hds/interactive/index.ts | 29 ++-------------- .../helpers/hds-resolve-link-to-component.ts | 33 +++++++++++++++++++ 4 files changed, 39 insertions(+), 52 deletions(-) create mode 100644 packages/components/src/helpers/hds-resolve-link-to-component.ts diff --git a/packages/components/package.json b/packages/components/package.json index 971faa4b2e3..77f80ca7a7e 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -351,6 +351,7 @@ "./helpers/hds-format-relative.js": "./dist/_app_/helpers/hds-format-relative.js", "./helpers/hds-link-to-models.js": "./dist/_app_/helpers/hds-link-to-models.js", "./helpers/hds-link-to-query.js": "./dist/_app_/helpers/hds-link-to-query.js", + "./helpers/hds-resolve-link-to-component.js": "./dist/_app_/helpers/hds-resolve-link-to-component.js", "./instance-initializers/load-sprite.js": "./dist/_app_/instance-initializers/load-sprite.js", "./modifiers/hds-advanced-table-cell.js": "./dist/_app_/modifiers/hds-advanced-table-cell.js", "./modifiers/hds-advanced-table-cell/dom-management.js": "./dist/_app_/modifiers/hds-advanced-table-cell/dom-management.js", diff --git a/packages/components/src/components/hds/breadcrumb/item.ts b/packages/components/src/components/hds/breadcrumb/item.ts index 20adfabb01a..58b3d8ed3a8 100644 --- a/packages/components/src/components/hds/breadcrumb/item.ts +++ b/packages/components/src/components/hds/breadcrumb/item.ts @@ -6,14 +6,9 @@ import Component from '@glimmer/component'; import { htmlSafe } from '@ember/template'; import { assert } from '@ember/debug'; -import { LinkTo } from '@ember/routing'; -import { - dependencySatisfies, - importSync, - macroCondition, -} from '@embroider/macros'; -import type Owner from '@ember/owner'; +import { hdsResolveLinkToComponent } from '../../../helpers/hds-resolve-link-to-component.ts'; + import type { SafeString } from '@ember/template'; import type { HdsIconSignature } from '../icon/index'; @@ -35,25 +30,8 @@ export interface HdsBreadcrumbItemSignature { } export default class HdsBreadcrumbItem extends Component { - linkToComponent = LinkTo; - - constructor(owner: Owner, args: HdsBreadcrumbItemSignature['Args']) { - super(owner, args); + linkToComponent = hdsResolveLinkToComponent(this.args.isRouteExternal); - if (this.args.isRouteExternal) { - if (macroCondition(dependencySatisfies('ember-engines', '*'))) { - // @ts-expect-error: shape is unknown - this.linkToComponent = importSync( - 'ember-engines/components/link-to-external-component.js' - ).default as LinkTo; - } else { - assert( - `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, - false - ); - } - } - } /** * @param maxWidth * @type {string} diff --git a/packages/components/src/components/hds/interactive/index.ts b/packages/components/src/components/hds/interactive/index.ts index 5d9c011c72b..27db8c5389a 100644 --- a/packages/components/src/components/hds/interactive/index.ts +++ b/packages/components/src/components/hds/interactive/index.ts @@ -5,15 +5,8 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; -import { assert } from '@ember/debug'; -import { LinkTo } from '@ember/routing'; -import { - dependencySatisfies, - importSync, - macroCondition, -} from '@embroider/macros'; -import type Owner from '@ember/owner'; +import { hdsResolveLinkToComponent } from '../../../helpers/hds-resolve-link-to-component.ts'; export interface HdsInteractiveSignature { Args: { @@ -36,25 +29,7 @@ export interface HdsInteractiveSignature { } export default class HdsInteractive extends Component { - linkToComponent = LinkTo; - - constructor(owner: Owner, args: HdsInteractiveSignature['Args']) { - super(owner, args); - - if (this.args.isRouteExternal) { - if (macroCondition(dependencySatisfies('ember-engines', '*'))) { - // @ts-expect-error: shape is unknown - this.linkToComponent = importSync( - 'ember-engines/components/link-to-external-component.js' - ).default as LinkTo; - } else { - assert( - `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, - false - ); - } - } - } + linkToComponent = hdsResolveLinkToComponent(this.args.isRouteExternal); /** * Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer") diff --git a/packages/components/src/helpers/hds-resolve-link-to-component.ts b/packages/components/src/helpers/hds-resolve-link-to-component.ts new file mode 100644 index 00000000000..89e9bd99425 --- /dev/null +++ b/packages/components/src/helpers/hds-resolve-link-to-component.ts @@ -0,0 +1,33 @@ +import { LinkTo } from '@ember/routing'; +import { assert } from '@ember/debug'; +import { + dependencySatisfies, + importSync, + macroCondition, +} from '@embroider/macros'; + +/** + * Resolves the correct component to use for the `LinkTo` helper. + * + * @param isRouteExternal - If true, will return the `LinkToExternal` component. If `ember-engines` is not installed, an assertion will be thrown. + * @returns The correct component to use for the `LinkTo` helper. + */ +export function hdsResolveLinkToComponent( + isRouteExternal?: boolean +): typeof LinkTo { + if (isRouteExternal) { + if (macroCondition(dependencySatisfies('ember-engines', '*'))) { + // @ts-expect-error: shape is unknown + return importSync( + 'ember-engines/components/link-to-external-component.js' + ).default as LinkTo; + } else { + assert( + `@isRouteExternal is only available when using the "ember-engines" addon. Please install it to use this feature.`, + false + ); + } + } + + return LinkTo; +} From 3f4d4383dd7a1a76637165daeb6d2b60d5793e00 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 25 Apr 2025 19:20:33 -0700 Subject: [PATCH 3/5] fix(components): move to utils folder --- packages/components/package.json | 1 - packages/components/src/components/hds/breadcrumb/item.ts | 2 +- packages/components/src/components/hds/interactive/index.ts | 2 +- .../src/{helpers => utils}/hds-resolve-link-to-component.ts | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) rename packages/components/src/{helpers => utils}/hds-resolve-link-to-component.ts (86%) diff --git a/packages/components/package.json b/packages/components/package.json index 77f80ca7a7e..971faa4b2e3 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -351,7 +351,6 @@ "./helpers/hds-format-relative.js": "./dist/_app_/helpers/hds-format-relative.js", "./helpers/hds-link-to-models.js": "./dist/_app_/helpers/hds-link-to-models.js", "./helpers/hds-link-to-query.js": "./dist/_app_/helpers/hds-link-to-query.js", - "./helpers/hds-resolve-link-to-component.js": "./dist/_app_/helpers/hds-resolve-link-to-component.js", "./instance-initializers/load-sprite.js": "./dist/_app_/instance-initializers/load-sprite.js", "./modifiers/hds-advanced-table-cell.js": "./dist/_app_/modifiers/hds-advanced-table-cell.js", "./modifiers/hds-advanced-table-cell/dom-management.js": "./dist/_app_/modifiers/hds-advanced-table-cell/dom-management.js", diff --git a/packages/components/src/components/hds/breadcrumb/item.ts b/packages/components/src/components/hds/breadcrumb/item.ts index 58b3d8ed3a8..9785ae039a0 100644 --- a/packages/components/src/components/hds/breadcrumb/item.ts +++ b/packages/components/src/components/hds/breadcrumb/item.ts @@ -7,7 +7,7 @@ import Component from '@glimmer/component'; import { htmlSafe } from '@ember/template'; import { assert } from '@ember/debug'; -import { hdsResolveLinkToComponent } from '../../../helpers/hds-resolve-link-to-component.ts'; +import { hdsResolveLinkToComponent } from '../../../utils/hds-resolve-link-to-component.ts'; import type { SafeString } from '@ember/template'; import type { HdsIconSignature } from '../icon/index'; diff --git a/packages/components/src/components/hds/interactive/index.ts b/packages/components/src/components/hds/interactive/index.ts index 27db8c5389a..5c61cf8bc15 100644 --- a/packages/components/src/components/hds/interactive/index.ts +++ b/packages/components/src/components/hds/interactive/index.ts @@ -6,7 +6,7 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; -import { hdsResolveLinkToComponent } from '../../../helpers/hds-resolve-link-to-component.ts'; +import { hdsResolveLinkToComponent } from '../../../utils/hds-resolve-link-to-component.ts'; export interface HdsInteractiveSignature { Args: { diff --git a/packages/components/src/helpers/hds-resolve-link-to-component.ts b/packages/components/src/utils/hds-resolve-link-to-component.ts similarity index 86% rename from packages/components/src/helpers/hds-resolve-link-to-component.ts rename to packages/components/src/utils/hds-resolve-link-to-component.ts index 89e9bd99425..3f6fc08c963 100644 --- a/packages/components/src/helpers/hds-resolve-link-to-component.ts +++ b/packages/components/src/utils/hds-resolve-link-to-component.ts @@ -7,10 +7,10 @@ import { } from '@embroider/macros'; /** - * Resolves the correct component to use for the `LinkTo` helper. + * Resolves the correct component to use for the `LinkTo`. * * @param isRouteExternal - If true, will return the `LinkToExternal` component. If `ember-engines` is not installed, an assertion will be thrown. - * @returns The correct component to use for the `LinkTo` helper. + * @returns The correct component to use for the `LinkTo`. */ export function hdsResolveLinkToComponent( isRouteExternal?: boolean From e2db5d541a2cc3d375d92e949f645fe5695eddfc Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 27 Apr 2025 13:53:26 -0700 Subject: [PATCH 4/5] fix: initialize the value in constructor as it is derived from `args` --- .../components/src/components/hds/breadcrumb/item.ts | 10 +++++++++- .../src/components/hds/interactive/index.ts | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/hds/breadcrumb/item.ts b/packages/components/src/components/hds/breadcrumb/item.ts index 9785ae039a0..24f1333739a 100644 --- a/packages/components/src/components/hds/breadcrumb/item.ts +++ b/packages/components/src/components/hds/breadcrumb/item.ts @@ -9,6 +9,8 @@ import { assert } from '@ember/debug'; import { hdsResolveLinkToComponent } from '../../../utils/hds-resolve-link-to-component.ts'; +import type Owner from '@ember/owner'; +import type { LinkTo } from '@ember/routing'; import type { SafeString } from '@ember/template'; import type { HdsIconSignature } from '../icon/index'; @@ -30,7 +32,13 @@ export interface HdsBreadcrumbItemSignature { } export default class HdsBreadcrumbItem extends Component { - linkToComponent = hdsResolveLinkToComponent(this.args.isRouteExternal); + linkToComponent: LinkTo; + + constructor(owner: Owner, args: HdsBreadcrumbItemSignature['Args']) { + super(owner, args); + + this.linkToComponent = hdsResolveLinkToComponent(args.isRouteExternal); + } /** * @param maxWidth diff --git a/packages/components/src/components/hds/interactive/index.ts b/packages/components/src/components/hds/interactive/index.ts index 5c61cf8bc15..d7e87b20e59 100644 --- a/packages/components/src/components/hds/interactive/index.ts +++ b/packages/components/src/components/hds/interactive/index.ts @@ -8,6 +8,9 @@ import { action } from '@ember/object'; import { hdsResolveLinkToComponent } from '../../../utils/hds-resolve-link-to-component.ts'; +import type Owner from '@ember/owner'; +import type { LinkTo } from '@ember/routing'; + export interface HdsInteractiveSignature { Args: { href?: string; @@ -29,7 +32,13 @@ export interface HdsInteractiveSignature { } export default class HdsInteractive extends Component { - linkToComponent = hdsResolveLinkToComponent(this.args.isRouteExternal); + linkToComponent: LinkTo; + + constructor(owner: Owner, args: HdsInteractiveSignature['Args']) { + super(owner, args); + + this.linkToComponent = hdsResolveLinkToComponent(args.isRouteExternal); + } /** * Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer") From 3fad1473ab0538b0ca3eed848e5985a827f80946 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Thu, 1 May 2025 01:17:10 -0700 Subject: [PATCH 5/5] feat(components): add changeset entry --- .changeset/tall-rings-act.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tall-rings-act.md diff --git a/.changeset/tall-rings-act.md b/.changeset/tall-rings-act.md new file mode 100644 index 00000000000..39615d35a9b --- /dev/null +++ b/.changeset/tall-rings-act.md @@ -0,0 +1,5 @@ +--- +'@hashicorp/design-system-components': patch +--- + +Introduce the `hds-resolve-link-to-component` utility to correctly resolve the LinkTo component when `@isRouteExternal` is set on `HdsBreadcrumbItem` or `HdsInteractive`. Consumers are now required to install `ember-engines` when `@isRouteExternal` is `true`.