Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@
"peerDependencies": {
"@ember/string": "^3.1.1 || ^4.0.0",
"ember-basic-dropdown": "^7.3.0 || ^8.6.1",
"ember-engines": ">= 0.11.0",
"ember-intl": "^7.3.0"
},
"peerDependenciesMeta": {
Expand Down
33 changes: 16 additions & 17 deletions packages/components/src/components/hds/breadcrumb/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@
*/

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { htmlSafe } from '@ember/template';
import { assert } from '@ember/debug';

import { hdsResolveLinkToExternal } from '../../../utils/hds-resolve-link-to-external.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';
import { getLinkToExternal } from '../../../utils/hds-link-to-external.ts';

export interface HdsBreadcrumbItemSignature {
Args: {
Expand All @@ -33,21 +30,23 @@ export interface HdsBreadcrumbItemSignature {
}

export default class HdsBreadcrumbItem extends Component<HdsBreadcrumbItemSignature> {
@tracked linkToExternal: LinkTo | null = null;

constructor(owner: Owner, args: HdsBreadcrumbItemSignature['Args']) {
super(owner, args);
/**
*
* @param linkToExternal
* @type LinkTo | null
* @default null
*/
get linkToExternal(): LinkTo | null {
const component = getLinkToExternal();
if (component === null) {
assert(
`HdsBreadcrumbItem: You attempted to use an external link without configuring HDS with an external component. Please add this in your app.js file:

// we want to avoid resolving the component if it's not needed
if (args.isRouteExternal) {
void this.resolveLinkToExternal();
import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';
setLinkToExternal(LinkToExternalComponent);`
);
}
}

async resolveLinkToExternal() {
this.linkToExternal = await hdsResolveLinkToExternal(
this.args.isRouteExternal
);
return component;
}

/**
Expand Down
34 changes: 18 additions & 16 deletions packages/components/src/components/hds/interactive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
*/

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { assert } from '@ember/debug';

import { hdsResolveLinkToExternal } from '../../../utils/hds-resolve-link-to-external.ts';

import type Owner from '@ember/owner';
import type { LinkTo } from '@ember/routing';
import { getLinkToExternal } from '../../../utils/hds-link-to-external.ts';

export interface HdsInteractiveSignature {
Args: {
Expand All @@ -33,22 +31,26 @@ export interface HdsInteractiveSignature {
}

export default class HdsInteractive extends Component<HdsInteractiveSignature> {
@tracked linkToExternal: LinkTo | null = null;

constructor(owner: Owner, args: HdsInteractiveSignature['Args']) {
super(owner, args);
/**
* Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer")
*
* @param linkToExternal
* @type LinkTo | null
* @default null
*/
get linkToExternal(): LinkTo | null {
const component = getLinkToExternal();
if (component === null) {
assert(
`HdsInteractive: You attempted to use an external link without configuring HDS with an external component. Please add this in your app.js file:

// we want to avoid resolving the component if it's not needed
if (args.isRouteExternal) {
void this.resolveLinkToExternal();
import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';
setLinkToExternal(LinkToExternalComponent);`
);
}
return component;
}

async resolveLinkToExternal() {
this.linkToExternal = await hdsResolveLinkToExternal(
this.args.isRouteExternal
);
}
/**
* Determines if a @href value is "external" (it adds target="_blank" rel="noopener noreferrer")
*
Expand Down
11 changes: 11 additions & 0 deletions packages/components/src/utils/hds-link-to-external.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { LinkTo } from '@ember/routing';

let LINK_TO_EXTERNAL_COMPONENT: LinkTo | null = null;

export function getLinkToExternal(): LinkTo | null {
return LINK_TO_EXTERNAL_COMPONENT;
}

export function setLinkToExternal(component: LinkTo | null): void {
LINK_TO_EXTERNAL_COMPONENT = component;
}
36 changes: 0 additions & 36 deletions packages/components/src/utils/hds-resolve-link-to-external.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { module, test } from 'qunit';
import { render, setupOnerror } from '@ember/test-helpers';

import { HdsBreadcrumbItem } from '@hashicorp/design-system-components/components';
import { LinkTo } from '@ember/routing';
import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';

import { setupRenderingTest } from 'showcase/tests/helpers';

Expand Down Expand Up @@ -90,4 +92,47 @@ module('Integration | Component | hds/breadcrumb/item', function (hooks) {
throw new Error(errorMessage);
});
});

// EXTERNAL LINK

test('it should error if @isRouteExternal is true and no component has been configured on the HdsBreadcrumbItem class', async function (assert) {
const errorMessage = `HdsBreadcrumbItem: You attempted to use an external link without configuring HDS with an external component. Please add this in your app.js file:

import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';
setLinkToExternal(LinkToExternalComponent);`;

assert.expect(1);
setupOnerror(function (error) {
assert.strictEqual(error.message, `Assertion Failed: ${errorMessage}`);
});

await render(
<template>
<HdsBreadcrumbItem
@route="index"
@text="a route"
@isRouteExternal={{true}}
id="test-interactive"
/>
</template>,
);
});

test('it should render configured link component when @isRouteExternal is true', async function (assert) {
setLinkToExternal(LinkTo);
assert.expect(1);

await render(
<template>
<HdsBreadcrumbItem
@route="index"
@text="a route"
@isRouteExternal={{true}}
id="test-interactive"
/>
</template>,
);
assert.dom('#test-breadcrumb-item > a').doesNotExist();
setLinkToExternal(null);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
*/

import { module, test } from 'qunit';
import { render, click } from '@ember/test-helpers';
import { render, click, setupOnerror } from '@ember/test-helpers';
import { on } from '@ember/modifier';
import { tracked } from 'tracked-built-ins';

import { HdsInteractive } from '@hashicorp/design-system-components/components';
import { LinkTo } from '@ember/routing';
import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';

import { setupRenderingTest } from 'showcase/tests/helpers';

Expand Down Expand Up @@ -154,4 +156,44 @@ module('Integration | Component | hds/interactive/index', function (hooks) {

assert.ok(context.isClicked);
});

// External Link
test('it should error if @isRouteExternal is true and no component has been configured on the HdsInteractive class', async function (assert) {
const errorMessage = `HdsInteractive: You attempted to use an external link without configuring HDS with an external component. Please add this in your app.js file:

import { setLinkToExternal } from '@hashicorp/design-system-components/utils/hds-link-to-external';
setLinkToExternal(LinkToExternalComponent);`;

assert.expect(1);
setupOnerror(function (error) {
assert.strictEqual(error.message, `Assertion Failed: ${errorMessage}`);
});

await render(
<template>
<HdsInteractive
@route="index"
@isRouteExternal={{true}}
id="test-interactive"
>External<pre>test</pre></HdsInteractive>
</template>,
);
});

test('it should render configured link component when @isRouteExternal is true', async function (assert) {
setLinkToExternal(LinkTo);
assert.expect(1);

await render(
<template>
<HdsInteractive
@route="index"
@isRouteExternal={{true}}
id="test-interactive"
>External</HdsInteractive>
</template>,
);
assert.dom('a#test-interactive').exists();
setLinkToExternal(null);
});
});
Loading