@ni/nimble-components 34.3.0 → 34.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all-components-bundle.js +115 -17
- package/dist/all-components-bundle.js.map +1 -1
- package/dist/all-components-bundle.min.js +51 -5
- package/dist/all-components-bundle.min.js.map +1 -1
- package/dist/esm/breadcrumb/breadcrumb.foundation.spec.d.ts +1 -0
- package/dist/esm/breadcrumb/breadcrumb.foundation.spec.js +109 -0
- package/dist/esm/breadcrumb/breadcrumb.foundation.spec.js.map +1 -0
- package/dist/esm/breadcrumb/index.d.ts +31 -0
- package/dist/esm/breadcrumb/index.js +56 -2
- package/dist/esm/breadcrumb/index.js.map +1 -1
- package/dist/esm/breadcrumb/styles.js +25 -4
- package/dist/esm/breadcrumb/styles.js.map +1 -1
- package/dist/esm/breadcrumb/template.d.ts +8 -0
- package/dist/esm/breadcrumb/template.js +44 -0
- package/dist/esm/breadcrumb/template.js.map +1 -0
- package/dist/esm/breadcrumb/testing/breadcrumb.pageobject.d.ts +19 -0
- package/dist/esm/breadcrumb/testing/breadcrumb.pageobject.js +89 -0
- package/dist/esm/breadcrumb/testing/breadcrumb.pageobject.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { breadcrumbItemTemplate } from '@ni/fast-foundation';
|
|
2
|
+
import { DOM } from '@ni/fast-element';
|
|
3
|
+
import { Breadcrumb } from '.';
|
|
4
|
+
import { breadcrumbTemplate as template } from './template';
|
|
5
|
+
import { fixture } from '../utilities/tests/fixture';
|
|
6
|
+
import { BreadcrumbItem } from '../breadcrumb-item';
|
|
7
|
+
const fastBreadcrumb = Breadcrumb.compose({
|
|
8
|
+
baseName: 'breadcrumb',
|
|
9
|
+
template
|
|
10
|
+
});
|
|
11
|
+
const fastBreadcrumbItem = BreadcrumbItem.compose({
|
|
12
|
+
baseName: 'breadcrumb-item',
|
|
13
|
+
breadcrumbItemTemplate
|
|
14
|
+
});
|
|
15
|
+
async function setup() {
|
|
16
|
+
const { element, connect, disconnect } = await fixture([
|
|
17
|
+
fastBreadcrumb(),
|
|
18
|
+
fastBreadcrumbItem()
|
|
19
|
+
]);
|
|
20
|
+
const item1 = document.createElement('fast-breadcrumb-item');
|
|
21
|
+
const item2 = document.createElement('fast-breadcrumb-item');
|
|
22
|
+
const item3 = document.createElement('fast-breadcrumb-item');
|
|
23
|
+
element.appendChild(item1);
|
|
24
|
+
element.appendChild(item2);
|
|
25
|
+
element.appendChild(item3);
|
|
26
|
+
return { element, connect, disconnect, item1, item2, item3 };
|
|
27
|
+
}
|
|
28
|
+
describe('Breadcrumb', () => {
|
|
29
|
+
it('should include a `role` of `navigation`', async () => {
|
|
30
|
+
const { element, connect, disconnect } = await setup();
|
|
31
|
+
await connect();
|
|
32
|
+
expect(element.getAttribute('role')).toEqual('navigation');
|
|
33
|
+
await disconnect();
|
|
34
|
+
});
|
|
35
|
+
it('should include a `role` of `list`', async () => {
|
|
36
|
+
const { element, connect, disconnect } = await setup();
|
|
37
|
+
await connect();
|
|
38
|
+
expect(element.shadowRoot?.querySelector("[role='list']")).not.toEqual(null);
|
|
39
|
+
await disconnect();
|
|
40
|
+
});
|
|
41
|
+
it('should not render a separator on last item', async () => {
|
|
42
|
+
const { element, connect, disconnect } = await setup();
|
|
43
|
+
await connect();
|
|
44
|
+
const items = element.querySelectorAll('fast-breadcrumb-item');
|
|
45
|
+
const lastItem = items[items.length - 1];
|
|
46
|
+
expect(lastItem?.separator).toEqual(false);
|
|
47
|
+
await disconnect();
|
|
48
|
+
});
|
|
49
|
+
it('should set the `aria-current` on the internal, last node, anchor when `href` is passed', async () => {
|
|
50
|
+
const { element, connect, disconnect, item1, item2, item3 } = await setup();
|
|
51
|
+
const anchor1 = document.createElement('a');
|
|
52
|
+
anchor1.href = '#';
|
|
53
|
+
const anchor2 = document.createElement('a');
|
|
54
|
+
anchor2.href = '#';
|
|
55
|
+
const anchor3 = document.createElement('a');
|
|
56
|
+
anchor3.href = '#';
|
|
57
|
+
item1.appendChild(anchor1);
|
|
58
|
+
item2.appendChild(anchor2);
|
|
59
|
+
item3.appendChild(anchor3);
|
|
60
|
+
await connect();
|
|
61
|
+
expect(element.querySelectorAll('a[href]')[2]?.getAttribute('aria-current')).toEqual('page');
|
|
62
|
+
await disconnect();
|
|
63
|
+
});
|
|
64
|
+
it('should remove aria-current from any prior Breadcrumb Item children with hrefs when a new node is appended', async () => {
|
|
65
|
+
const { element, connect, disconnect, item1, item2, item3 } = await setup();
|
|
66
|
+
item1.setAttribute('href', '#');
|
|
67
|
+
item2.setAttribute('href', '#');
|
|
68
|
+
item3.setAttribute('href', '#');
|
|
69
|
+
await connect();
|
|
70
|
+
expect(element
|
|
71
|
+
.querySelectorAll('fast-breadcrumb-item')[2]
|
|
72
|
+
?.getAttribute('aria-current')).toEqual('page');
|
|
73
|
+
const item4 = document.createElement('fast-breadcrumb-item');
|
|
74
|
+
item4.setAttribute('href', '#');
|
|
75
|
+
element.appendChild(item4);
|
|
76
|
+
await DOM.nextUpdate();
|
|
77
|
+
expect(element
|
|
78
|
+
.querySelectorAll('fast-breadcrumb-item')[2]
|
|
79
|
+
?.hasAttribute('aria-current')).toEqual(false);
|
|
80
|
+
expect(element
|
|
81
|
+
.querySelectorAll('fast-breadcrumb-item')[3]
|
|
82
|
+
?.getAttribute('aria-current')).toEqual('page');
|
|
83
|
+
await disconnect();
|
|
84
|
+
});
|
|
85
|
+
it('should remove aria-current from any prior Breadcrumb Item children with child anchors when a new node is appended', async () => {
|
|
86
|
+
const { element, connect, disconnect, item1, item2, item3 } = await setup();
|
|
87
|
+
const anchor1 = document.createElement('a');
|
|
88
|
+
anchor1.href = '#';
|
|
89
|
+
const anchor2 = document.createElement('a');
|
|
90
|
+
anchor2.href = '#';
|
|
91
|
+
const anchor3 = document.createElement('a');
|
|
92
|
+
anchor3.href = '#';
|
|
93
|
+
item1.appendChild(anchor1);
|
|
94
|
+
item2.appendChild(anchor2);
|
|
95
|
+
item3.appendChild(anchor3);
|
|
96
|
+
await connect();
|
|
97
|
+
expect(element.querySelectorAll('a[href]')[2]?.getAttribute('aria-current')).toEqual('page');
|
|
98
|
+
const item4 = document.createElement('fast-breadcrumb-item');
|
|
99
|
+
const anchor4 = document.createElement('a');
|
|
100
|
+
anchor4.href = '#';
|
|
101
|
+
item4.appendChild(anchor4);
|
|
102
|
+
element.appendChild(item4);
|
|
103
|
+
await DOM.nextUpdate();
|
|
104
|
+
expect(element.querySelectorAll('a[href]')[2]?.hasAttribute('aria-current')).toEqual(false);
|
|
105
|
+
expect(element.querySelectorAll('a[href]')[3]?.getAttribute('aria-current')).toEqual('page');
|
|
106
|
+
await disconnect();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=breadcrumb.foundation.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.foundation.spec.js","sourceRoot":"","sources":["../../../src/breadcrumb/breadcrumb.foundation.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { breadcrumbItemTemplate } from '@ni/fast-foundation';\nimport { DOM } from '@ni/fast-element';\nimport { Breadcrumb } from '.';\nimport { breadcrumbTemplate as template } from './template';\nimport { fixture } from '../utilities/tests/fixture';\nimport { BreadcrumbItem } from '../breadcrumb-item';\n\nconst fastBreadcrumb = Breadcrumb.compose({\n baseName: 'breadcrumb',\n template\n});\n\nconst fastBreadcrumbItem = BreadcrumbItem.compose({\n baseName: 'breadcrumb-item',\n breadcrumbItemTemplate\n});\n\ninterface BreadcrumbTestSetup {\n element: Breadcrumb;\n connect: () => Promise<void>;\n disconnect: () => Promise<void>;\n item1: BreadcrumbItem;\n item2: BreadcrumbItem;\n item3: BreadcrumbItem;\n}\n\nasync function setup(): Promise<BreadcrumbTestSetup> {\n const { element, connect, disconnect } = await fixture<Breadcrumb>([\n fastBreadcrumb(),\n fastBreadcrumbItem()\n ]);\n\n const item1 = document.createElement(\n 'fast-breadcrumb-item'\n ) as BreadcrumbItem;\n const item2 = document.createElement(\n 'fast-breadcrumb-item'\n ) as BreadcrumbItem;\n const item3 = document.createElement(\n 'fast-breadcrumb-item'\n ) as BreadcrumbItem;\n\n element.appendChild(item1);\n element.appendChild(item2);\n element.appendChild(item3);\n\n return { element, connect, disconnect, item1, item2, item3 };\n}\n\ndescribe('Breadcrumb', () => {\n it('should include a `role` of `navigation`', async () => {\n const { element, connect, disconnect } = await setup();\n\n await connect();\n\n expect(element.getAttribute('role')).toEqual('navigation');\n\n await disconnect();\n });\n\n it('should include a `role` of `list`', async () => {\n const { element, connect, disconnect } = await setup();\n\n await connect();\n\n expect(element.shadowRoot?.querySelector(\"[role='list']\")).not.toEqual(\n null\n );\n\n await disconnect();\n });\n\n it('should not render a separator on last item', async () => {\n const { element, connect, disconnect } = await setup();\n\n await connect();\n\n const items: NodeListOf<BreadcrumbItem> = element.querySelectorAll(\n 'fast-breadcrumb-item'\n );\n\n const lastItem: BreadcrumbItem | undefined = items[items.length - 1];\n\n expect(lastItem?.separator).toEqual(false);\n\n await disconnect();\n });\n\n it('should set the `aria-current` on the internal, last node, anchor when `href` is passed', async () => {\n const { element, connect, disconnect, item1, item2, item3 } = await setup();\n\n const anchor1 = document.createElement('a');\n anchor1.href = '#';\n\n const anchor2 = document.createElement('a');\n anchor2.href = '#';\n\n const anchor3 = document.createElement('a');\n anchor3.href = '#';\n\n item1.appendChild(anchor1);\n item2.appendChild(anchor2);\n item3.appendChild(anchor3);\n\n await connect();\n\n expect(\n element.querySelectorAll('a[href]')[2]?.getAttribute('aria-current')\n ).toEqual('page');\n\n await disconnect();\n });\n\n it('should remove aria-current from any prior Breadcrumb Item children with hrefs when a new node is appended', async () => {\n const { element, connect, disconnect, item1, item2, item3 } = await setup();\n\n item1.setAttribute('href', '#');\n item2.setAttribute('href', '#');\n item3.setAttribute('href', '#');\n\n await connect();\n\n expect(\n element\n .querySelectorAll('fast-breadcrumb-item')[2]\n ?.getAttribute('aria-current')\n ).toEqual('page');\n\n const item4 = document.createElement('fast-breadcrumb-item');\n (item4 as BreadcrumbItem).setAttribute('href', '#');\n element.appendChild(item4);\n\n await DOM.nextUpdate();\n\n expect(\n element\n .querySelectorAll('fast-breadcrumb-item')[2]\n ?.hasAttribute('aria-current')\n ).toEqual(false);\n\n expect(\n element\n .querySelectorAll('fast-breadcrumb-item')[3]\n ?.getAttribute('aria-current')\n ).toEqual('page');\n\n await disconnect();\n });\n\n it('should remove aria-current from any prior Breadcrumb Item children with child anchors when a new node is appended', async () => {\n const { element, connect, disconnect, item1, item2, item3 } = await setup();\n\n const anchor1 = document.createElement('a');\n anchor1.href = '#';\n\n const anchor2 = document.createElement('a');\n anchor2.href = '#';\n\n const anchor3 = document.createElement('a');\n anchor3.href = '#';\n\n item1.appendChild(anchor1);\n item2.appendChild(anchor2);\n item3.appendChild(anchor3);\n\n await connect();\n\n expect(\n element.querySelectorAll('a[href]')[2]?.getAttribute('aria-current')\n ).toEqual('page');\n\n const item4 = document.createElement('fast-breadcrumb-item');\n const anchor4 = document.createElement('a');\n anchor4.href = '#';\n\n item4.appendChild(anchor4);\n element.appendChild(item4);\n\n await DOM.nextUpdate();\n\n expect(\n element.querySelectorAll('a[href]')[2]?.hasAttribute('aria-current')\n ).toEqual(false);\n\n expect(\n element.querySelectorAll('a[href]')[3]?.getAttribute('aria-current')\n ).toEqual('page');\n\n await disconnect();\n });\n});\n"]}
|
|
@@ -10,5 +10,36 @@ declare global {
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class Breadcrumb extends FoundationBreadcrumb {
|
|
12
12
|
appearance: BreadcrumbAppearance;
|
|
13
|
+
/**
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
showScrollButtons: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* A reference to the list div
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
list: HTMLElement;
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
readonly leftScrollButton?: HTMLElement;
|
|
26
|
+
private readonly listResizeObserver;
|
|
27
|
+
constructor();
|
|
28
|
+
/**
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
onScrollLeftClick(): void;
|
|
32
|
+
/**
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
onScrollRightClick(): void;
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
connectedCallback(): void;
|
|
40
|
+
/**
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
disconnectedCallback(): void;
|
|
13
44
|
}
|
|
14
45
|
export declare const breadcrumbTag = "nimble-breadcrumb";
|
|
@@ -1,15 +1,69 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { attr } from '@ni/fast-element';
|
|
3
|
-
import { DesignSystem, Breadcrumb as FoundationBreadcrumb
|
|
2
|
+
import { attr, observable } from '@ni/fast-element';
|
|
3
|
+
import { DesignSystem, Breadcrumb as FoundationBreadcrumb } from '@ni/fast-foundation';
|
|
4
|
+
import { breadcrumbTemplate as template } from './template';
|
|
4
5
|
import { styles } from './styles';
|
|
5
6
|
/**
|
|
6
7
|
* A nimble-styled breadcrumb
|
|
7
8
|
*/
|
|
8
9
|
export class Breadcrumb extends FoundationBreadcrumb {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
/**
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
this.showScrollButtons = false;
|
|
16
|
+
this.listResizeObserver = new ResizeObserver(entries => {
|
|
17
|
+
let listVisibleWidth = entries[0]?.contentRect.width;
|
|
18
|
+
if (listVisibleWidth !== undefined) {
|
|
19
|
+
const buttonWidth = this.leftScrollButton?.clientWidth ?? 0;
|
|
20
|
+
listVisibleWidth = Math.ceil(listVisibleWidth);
|
|
21
|
+
if (this.showScrollButtons) {
|
|
22
|
+
listVisibleWidth += buttonWidth * 2;
|
|
23
|
+
}
|
|
24
|
+
this.showScrollButtons = listVisibleWidth < this.list.scrollWidth;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
onScrollLeftClick() {
|
|
32
|
+
this.list.scrollBy({
|
|
33
|
+
left: -this.list.clientWidth,
|
|
34
|
+
behavior: 'smooth'
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
onScrollRightClick() {
|
|
41
|
+
this.list.scrollBy({
|
|
42
|
+
left: this.list.clientWidth,
|
|
43
|
+
behavior: 'smooth'
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
connectedCallback() {
|
|
50
|
+
super.connectedCallback();
|
|
51
|
+
this.listResizeObserver.observe(this.list);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
disconnectedCallback() {
|
|
57
|
+
super.disconnectedCallback();
|
|
58
|
+
this.listResizeObserver.disconnect();
|
|
59
|
+
}
|
|
9
60
|
}
|
|
10
61
|
__decorate([
|
|
11
62
|
attr
|
|
12
63
|
], Breadcrumb.prototype, "appearance", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
observable
|
|
66
|
+
], Breadcrumb.prototype, "showScrollButtons", void 0);
|
|
13
67
|
const nimbleBreadcrumb = Breadcrumb.compose({
|
|
14
68
|
baseName: 'breadcrumb',
|
|
15
69
|
baseClass: FoundationBreadcrumb,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/breadcrumb/index.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/breadcrumb/index.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACH,YAAY,EACZ,UAAU,IAAI,oBAAoB,EACrC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AASlC;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,oBAAoB;IAsBhD;QACI,KAAK,EAAE,CAAC;QAnBZ;;WAEG;QAEI,sBAAiB,GAAG,KAAK,CAAC;QAgB7B,IAAI,CAAC,kBAAkB,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE;YACnD,IAAI,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC;YACrD,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,WAAW,IAAI,CAAC,CAAC;gBAC5D,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC/C,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACzB,gBAAgB,IAAI,WAAW,GAAG,CAAC,CAAC;gBACxC,CAAC;gBACD,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;YACtE,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACI,iBAAiB;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW;YAC5B,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACI,kBAAkB;QACrB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YAC3B,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACa,iBAAiB;QAC7B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACa,oBAAoB;QAChC,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC7B,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;CACJ;AAtEU;IADN,IAAI;8CACmC;AAMjC;IADN,UAAU;qDACsB;AAkErC,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC;IACxC,QAAQ,EAAE,YAAY;IACtB,SAAS,EAAE,oBAAoB;IAC/B,QAAQ;IACR,MAAM;CACT,CAAC,CAAC;AAEH,YAAY,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAC","sourcesContent":["import { attr, observable } from '@ni/fast-element';\nimport {\n DesignSystem,\n Breadcrumb as FoundationBreadcrumb\n} from '@ni/fast-foundation';\nimport { breadcrumbTemplate as template } from './template';\nimport { styles } from './styles';\nimport type { BreadcrumbAppearance } from './types';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nimble-breadcrumb': Breadcrumb;\n }\n}\n\n/**\n * A nimble-styled breadcrumb\n */\nexport class Breadcrumb extends FoundationBreadcrumb {\n @attr\n public appearance: BreadcrumbAppearance;\n\n /**\n * @internal\n */\n @observable\n public showScrollButtons = false;\n\n /**\n * A reference to the list div\n * @internal\n */\n public list!: HTMLElement;\n /**\n * @internal\n */\n public readonly leftScrollButton?: HTMLElement;\n\n private readonly listResizeObserver: ResizeObserver;\n\n public constructor() {\n super();\n this.listResizeObserver = new ResizeObserver(entries => {\n let listVisibleWidth = entries[0]?.contentRect.width;\n if (listVisibleWidth !== undefined) {\n const buttonWidth = this.leftScrollButton?.clientWidth ?? 0;\n listVisibleWidth = Math.ceil(listVisibleWidth);\n if (this.showScrollButtons) {\n listVisibleWidth += buttonWidth * 2;\n }\n this.showScrollButtons = listVisibleWidth < this.list.scrollWidth;\n }\n });\n }\n\n /**\n * @internal\n */\n public onScrollLeftClick(): void {\n this.list.scrollBy({\n left: -this.list.clientWidth,\n behavior: 'smooth'\n });\n }\n\n /**\n * @internal\n */\n public onScrollRightClick(): void {\n this.list.scrollBy({\n left: this.list.clientWidth,\n behavior: 'smooth'\n });\n }\n\n /**\n * @internal\n */\n public override connectedCallback(): void {\n super.connectedCallback();\n this.listResizeObserver.observe(this.list);\n }\n\n /**\n * @internal\n */\n public override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.listResizeObserver.disconnect();\n }\n}\n\nconst nimbleBreadcrumb = Breadcrumb.compose({\n baseName: 'breadcrumb',\n baseClass: FoundationBreadcrumb,\n template,\n styles\n});\n\nDesignSystem.getOrCreate().withPrefix('nimble').register(nimbleBreadcrumb());\nexport const breadcrumbTag = 'nimble-breadcrumb';\n"]}
|
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
import { css } from '@ni/fast-element';
|
|
2
2
|
import { display } from '../utilities/style/display';
|
|
3
|
-
import { bodyEmphasizedFont, linkFontColor, linkProminentFontColor } from '../theme-provider/design-tokens';
|
|
3
|
+
import { bodyEmphasizedFont, linkFontColor, linkProminentFontColor, smallPadding } from '../theme-provider/design-tokens';
|
|
4
4
|
export const styles = css `
|
|
5
|
-
${display('inline-
|
|
5
|
+
${display('inline-flex')}
|
|
6
|
+
|
|
7
|
+
:host {
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.scroll-button.left {
|
|
12
|
+
margin-right: ${smallPadding};
|
|
13
|
+
}
|
|
6
14
|
|
|
7
15
|
.list {
|
|
8
|
-
display: flex;
|
|
9
|
-
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
width: max-content;
|
|
19
|
+
align-self: end;
|
|
20
|
+
overflow-x: scroll;
|
|
21
|
+
scrollbar-width: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.scroll-button.right {
|
|
25
|
+
margin-left: ${smallPadding};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
::slotted(*) {
|
|
29
|
+
flex-shrink: 0;
|
|
30
|
+
white-space: nowrap;
|
|
10
31
|
}
|
|
11
32
|
|
|
12
33
|
::slotted(:last-child) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/breadcrumb/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,sBAAsB,
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/breadcrumb/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACf,MAAM,iCAAiC,CAAC;AAEzC,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;MACnB,OAAO,CAAC,aAAa,CAAC;;;;;;;wBAOJ,YAAY;;;;;;;;;;;;;uBAab,YAAY;;;;;;;;;gBASnB,kBAAkB;iBACjB,aAAa;;;;iBAIb,sBAAsB;;CAEtC,CAAC","sourcesContent":["import { css } from '@ni/fast-element';\nimport { display } from '../utilities/style/display';\nimport {\n bodyEmphasizedFont,\n linkFontColor,\n linkProminentFontColor,\n smallPadding\n} from '../theme-provider/design-tokens';\n\nexport const styles = css`\n ${display('inline-flex')}\n\n :host {\n flex-direction: row;\n }\n\n .scroll-button.left {\n margin-right: ${smallPadding};\n }\n\n .list {\n display: inline-flex;\n max-width: 100%;\n width: max-content;\n align-self: end;\n overflow-x: scroll;\n scrollbar-width: none;\n }\n\n .scroll-button.right {\n margin-left: ${smallPadding};\n }\n\n ::slotted(*) {\n flex-shrink: 0;\n white-space: nowrap;\n }\n\n ::slotted(:last-child) {\n font: ${bodyEmphasizedFont};\n color: ${linkFontColor};\n }\n\n :host([appearance='prominent']) ::slotted(:last-child) {\n color: ${linkProminentFontColor};\n }\n`;\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ViewTemplate } from '@ni/fast-element';
|
|
2
|
+
import type { FoundationElementTemplate } from '@ni/fast-foundation';
|
|
3
|
+
import type { Breadcrumb } from '.';
|
|
4
|
+
/**
|
|
5
|
+
* The template for the {@link @ni/fast-foundation#Breadcrumb} component.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare const breadcrumbTemplate: FoundationElementTemplate<ViewTemplate<Breadcrumb>>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { elements, html, ref, slotted, when } from '@ni/fast-element';
|
|
2
|
+
import { buttonTag } from '../button';
|
|
3
|
+
import { ButtonAppearance } from '../button/types';
|
|
4
|
+
import { scrollBackwardLabel, scrollForwardLabel } from '../label-provider/core/label-tokens';
|
|
5
|
+
import { iconArrowExpanderLeftTag } from '../icons/arrow-expander-left';
|
|
6
|
+
import { iconArrowExpanderRightTag } from '../icons/arrow-expander-right';
|
|
7
|
+
/**
|
|
8
|
+
* The template for the {@link @ni/fast-foundation#Breadcrumb} component.
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
// prettier-ignore
|
|
12
|
+
export const breadcrumbTemplate = (_context, _definition) => html `
|
|
13
|
+
<template role="navigation">
|
|
14
|
+
${when(x => x.showScrollButtons, html `
|
|
15
|
+
<${buttonTag}
|
|
16
|
+
content-hidden
|
|
17
|
+
class="scroll-button left"
|
|
18
|
+
appearance="${ButtonAppearance.ghost}"
|
|
19
|
+
@click="${x => x.onScrollLeftClick()}"
|
|
20
|
+
${ref('leftScrollButton')}
|
|
21
|
+
>
|
|
22
|
+
${x => scrollForwardLabel.getValueFor(x)}
|
|
23
|
+
<${iconArrowExpanderLeftTag} slot="start"></${iconArrowExpanderLeftTag}>
|
|
24
|
+
</${buttonTag}>
|
|
25
|
+
`)}
|
|
26
|
+
<div ${ref('list')} role="list" class="list" part="list" tabindex="-1">
|
|
27
|
+
<slot
|
|
28
|
+
${slotted({ property: 'slottedBreadcrumbItems', filter: elements() })}
|
|
29
|
+
></slot>
|
|
30
|
+
</div>
|
|
31
|
+
${when(x => x.showScrollButtons, html `
|
|
32
|
+
<${buttonTag}
|
|
33
|
+
content-hidden
|
|
34
|
+
class="scroll-button right"
|
|
35
|
+
appearance="${ButtonAppearance.ghost}"
|
|
36
|
+
@click="${x => x.onScrollRightClick()}"
|
|
37
|
+
>
|
|
38
|
+
${x => scrollBackwardLabel.getValueFor(x)}
|
|
39
|
+
<${iconArrowExpanderRightTag} slot="start"></${iconArrowExpanderRightTag}>
|
|
40
|
+
</${buttonTag}>
|
|
41
|
+
`)}
|
|
42
|
+
</template>
|
|
43
|
+
`;
|
|
44
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/breadcrumb/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAItE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACH,mBAAmB,EACnB,kBAAkB,EACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E;;;GAGG;AACH,kBAAkB;AAClB,MAAM,CAAC,MAAM,kBAAkB,GAAwD,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,CAAA;;UAE5G,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,IAAI,CAAY;eAC1C,SAAS;;;8BAGM,gBAAgB,CAAC,KAAK;0BAC1B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE;kBAClC,GAAG,CAAC,kBAAkB,CAAC;;kBAEvB,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC;mBACrC,wBAAwB,mBAAmB,wBAAwB;gBACtE,SAAS;SAChB,CAAC;eACK,GAAG,CAAC,MAAM,CAAC;;kBAER,OAAO,CAAC,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC;;;UAG3E,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,IAAI,CAAY;eAC1C,SAAS;;;8BAGM,gBAAgB,CAAC,KAAK;0BAC1B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE;;kBAEnC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC;mBACtC,yBAAyB,mBAAmB,yBAAyB;gBACxE,SAAS;SAChB,CAAC;;CAET,CAAC","sourcesContent":["import { elements, html, ref, slotted, when } from '@ni/fast-element';\nimport type { ViewTemplate } from '@ni/fast-element';\nimport type { FoundationElementTemplate } from '@ni/fast-foundation';\nimport type { Breadcrumb } from '.';\nimport { buttonTag } from '../button';\nimport { ButtonAppearance } from '../button/types';\nimport {\n scrollBackwardLabel,\n scrollForwardLabel\n} from '../label-provider/core/label-tokens';\nimport { iconArrowExpanderLeftTag } from '../icons/arrow-expander-left';\nimport { iconArrowExpanderRightTag } from '../icons/arrow-expander-right';\n\n/**\n * The template for the {@link @ni/fast-foundation#Breadcrumb} component.\n * @public\n */\n// prettier-ignore\nexport const breadcrumbTemplate: FoundationElementTemplate<ViewTemplate<Breadcrumb>> = (_context, _definition) => html`\n <template role=\"navigation\">\n ${when(x => x.showScrollButtons, html<Breadcrumb>`\n <${buttonTag} \n content-hidden\n class=\"scroll-button left\"\n appearance=\"${ButtonAppearance.ghost}\"\n @click=\"${x => x.onScrollLeftClick()}\"\n ${ref('leftScrollButton')}\n >\n ${x => scrollForwardLabel.getValueFor(x)}\n <${iconArrowExpanderLeftTag} slot=\"start\"></${iconArrowExpanderLeftTag}>\n </${buttonTag}>\n `)}\n <div ${ref('list')} role=\"list\" class=\"list\" part=\"list\" tabindex=\"-1\">\n <slot\n ${slotted({ property: 'slottedBreadcrumbItems', filter: elements() })}\n ></slot>\n </div>\n ${when(x => x.showScrollButtons, html<Breadcrumb>`\n <${buttonTag}\n content-hidden\n class=\"scroll-button right\"\n appearance=\"${ButtonAppearance.ghost}\"\n @click=\"${x => x.onScrollRightClick()}\"\n >\n ${x => scrollBackwardLabel.getValueFor(x)}\n <${iconArrowExpanderRightTag} slot=\"start\"></${iconArrowExpanderRightTag}>\n </${buttonTag}>\n `)}\n </template>\n`;\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Breadcrumb } from '..';
|
|
2
|
+
/**
|
|
3
|
+
* Page object for the `nimble-breadcrumb`
|
|
4
|
+
*/
|
|
5
|
+
export declare class BreadcrumbPageObject {
|
|
6
|
+
protected readonly breadcrumbElement: Breadcrumb;
|
|
7
|
+
constructor(breadcrumbElement: Breadcrumb);
|
|
8
|
+
clickBreadcrumb(index: number): Promise<void>;
|
|
9
|
+
pressKeyOnBreadcrumb(index: number, key: string): Promise<void>;
|
|
10
|
+
setBreadcrumbWidth(width: number): Promise<void>;
|
|
11
|
+
clickScrollLeftButton(): Promise<void>;
|
|
12
|
+
clickScrollRightButton(): Promise<void>;
|
|
13
|
+
areScrollButtonsVisible(): boolean;
|
|
14
|
+
addBreadcrumbItem(label: string): Promise<void>;
|
|
15
|
+
removeBreadcrumbItemByIndex(index: number): Promise<void>;
|
|
16
|
+
updateBreadcrumbItemLabel(index: number, label: string): Promise<void>;
|
|
17
|
+
scrollBreadcrumbItemIntoViewByIndex(index: number): Promise<void>;
|
|
18
|
+
getBreadcrumbViewScrollOffset(): number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { waitForUpdatesAsync } from '../../testing/async-helpers';
|
|
2
|
+
import { waitTimeout } from '../../utilities/testing/component';
|
|
3
|
+
import {} from '..';
|
|
4
|
+
import { breadcrumbItemTag } from '../../breadcrumb-item';
|
|
5
|
+
/**
|
|
6
|
+
* Page object for the `nimble-breadcrumb`
|
|
7
|
+
*/
|
|
8
|
+
export class BreadcrumbPageObject {
|
|
9
|
+
constructor(breadcrumbElement) {
|
|
10
|
+
this.breadcrumbElement = breadcrumbElement;
|
|
11
|
+
}
|
|
12
|
+
async clickBreadcrumb(index) {
|
|
13
|
+
if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {
|
|
14
|
+
throw new Error(`Breadcrumb with index ${index} not found`);
|
|
15
|
+
}
|
|
16
|
+
this.breadcrumbElement.slottedBreadcrumbItems[index].click();
|
|
17
|
+
await waitForUpdatesAsync();
|
|
18
|
+
}
|
|
19
|
+
async pressKeyOnBreadcrumb(index, key) {
|
|
20
|
+
if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {
|
|
21
|
+
throw new Error(`Breadcrumb with index ${index} not found`);
|
|
22
|
+
}
|
|
23
|
+
const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index];
|
|
24
|
+
breadcrumb.dispatchEvent(new KeyboardEvent('keydown', { key }));
|
|
25
|
+
await waitForUpdatesAsync();
|
|
26
|
+
}
|
|
27
|
+
async setBreadcrumbWidth(width) {
|
|
28
|
+
this.breadcrumbElement.style.width = `${width}px`;
|
|
29
|
+
await waitForUpdatesAsync();
|
|
30
|
+
await waitForUpdatesAsync(); // wait for the resize observer to fire
|
|
31
|
+
}
|
|
32
|
+
async clickScrollLeftButton() {
|
|
33
|
+
const leftButton = this.breadcrumbElement.shadowRoot.querySelector('.scroll-button.left');
|
|
34
|
+
if (!leftButton) {
|
|
35
|
+
throw new Error('Scroll left button not found');
|
|
36
|
+
}
|
|
37
|
+
leftButton.click();
|
|
38
|
+
await waitForUpdatesAsync();
|
|
39
|
+
await waitTimeout(50); // let animation run
|
|
40
|
+
}
|
|
41
|
+
async clickScrollRightButton() {
|
|
42
|
+
const rightButton = this.breadcrumbElement.shadowRoot.querySelector('.scroll-button.right');
|
|
43
|
+
if (!rightButton) {
|
|
44
|
+
throw new Error('Scroll right button not found');
|
|
45
|
+
}
|
|
46
|
+
rightButton.click();
|
|
47
|
+
await waitForUpdatesAsync();
|
|
48
|
+
await waitTimeout(50); // let animation run
|
|
49
|
+
}
|
|
50
|
+
areScrollButtonsVisible() {
|
|
51
|
+
return (this.breadcrumbElement.shadowRoot.querySelectorAll('.scroll-button').length > 0);
|
|
52
|
+
}
|
|
53
|
+
async addBreadcrumbItem(label) {
|
|
54
|
+
const breadcrumbItem = document.createElement(breadcrumbItemTag);
|
|
55
|
+
breadcrumbItem.textContent = label;
|
|
56
|
+
const lastBreadcrumbItem = this.breadcrumbElement.querySelector(`${breadcrumbItemTag}:last-of-type`);
|
|
57
|
+
lastBreadcrumbItem.insertAdjacentElement('afterend', breadcrumbItem);
|
|
58
|
+
await waitForUpdatesAsync();
|
|
59
|
+
}
|
|
60
|
+
async removeBreadcrumbItemByIndex(index) {
|
|
61
|
+
if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {
|
|
62
|
+
throw new Error(`Breadcrumb item with index ${index} not found`);
|
|
63
|
+
}
|
|
64
|
+
const breadcrumbItemToRemove = this.breadcrumbElement.slottedBreadcrumbItems[index];
|
|
65
|
+
breadcrumbItemToRemove?.remove();
|
|
66
|
+
await waitForUpdatesAsync();
|
|
67
|
+
}
|
|
68
|
+
async updateBreadcrumbItemLabel(index, label) {
|
|
69
|
+
if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {
|
|
70
|
+
throw new Error(`Breadcrumb item with index ${index} not found`);
|
|
71
|
+
}
|
|
72
|
+
const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index];
|
|
73
|
+
breadcrumb.textContent = label;
|
|
74
|
+
await waitForUpdatesAsync();
|
|
75
|
+
}
|
|
76
|
+
async scrollBreadcrumbItemIntoViewByIndex(index) {
|
|
77
|
+
if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {
|
|
78
|
+
throw new Error(`Breadcrumb item with index ${index} not found`);
|
|
79
|
+
}
|
|
80
|
+
const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index];
|
|
81
|
+
breadcrumb.scrollIntoView();
|
|
82
|
+
await waitForUpdatesAsync();
|
|
83
|
+
}
|
|
84
|
+
getBreadcrumbViewScrollOffset() {
|
|
85
|
+
return this.breadcrumbElement.shadowRoot.querySelector('.list')
|
|
86
|
+
.scrollLeft;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=breadcrumb.pageobject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.pageobject.js","sourceRoot":"","sources":["../../../../src/breadcrumb/testing/breadcrumb.pageobject.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Button } from '../../button';\nimport { waitForUpdatesAsync } from '../../testing/async-helpers';\nimport { waitTimeout } from '../../utilities/testing/component';\nimport { type Breadcrumb } from '..';\nimport { breadcrumbItemTag } from '../../breadcrumb-item';\n\n/**\n * Page object for the `nimble-breadcrumb`\n */\nexport class BreadcrumbPageObject {\n public constructor(protected readonly breadcrumbElement: Breadcrumb) {}\n\n public async clickBreadcrumb(index: number): Promise<void> {\n if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {\n throw new Error(`Breadcrumb with index ${index} not found`);\n }\n this.breadcrumbElement.slottedBreadcrumbItems[index]!.click();\n await waitForUpdatesAsync();\n }\n\n public async pressKeyOnBreadcrumb(\n index: number,\n key: string\n ): Promise<void> {\n if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {\n throw new Error(`Breadcrumb with index ${index} not found`);\n }\n const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index]!;\n breadcrumb.dispatchEvent(new KeyboardEvent('keydown', { key }));\n await waitForUpdatesAsync();\n }\n\n public async setBreadcrumbWidth(width: number): Promise<void> {\n this.breadcrumbElement.style.width = `${width}px`;\n await waitForUpdatesAsync();\n await waitForUpdatesAsync(); // wait for the resize observer to fire\n }\n\n public async clickScrollLeftButton(): Promise<void> {\n const leftButton = this.breadcrumbElement.shadowRoot!.querySelector<Button>(\n '.scroll-button.left'\n );\n if (!leftButton) {\n throw new Error('Scroll left button not found');\n }\n leftButton.click();\n await waitForUpdatesAsync();\n await waitTimeout(50); // let animation run\n }\n\n public async clickScrollRightButton(): Promise<void> {\n const rightButton = this.breadcrumbElement.shadowRoot!.querySelector<Button>(\n '.scroll-button.right'\n );\n if (!rightButton) {\n throw new Error('Scroll right button not found');\n }\n rightButton.click();\n await waitForUpdatesAsync();\n await waitTimeout(50); // let animation run\n }\n\n public areScrollButtonsVisible(): boolean {\n return (\n this.breadcrumbElement.shadowRoot!.querySelectorAll(\n '.scroll-button'\n ).length > 0\n );\n }\n\n public async addBreadcrumbItem(label: string): Promise<void> {\n const breadcrumbItem = document.createElement(breadcrumbItemTag);\n breadcrumbItem.textContent = label;\n const lastBreadcrumbItem = this.breadcrumbElement.querySelector(\n `${breadcrumbItemTag}:last-of-type`\n )!;\n lastBreadcrumbItem.insertAdjacentElement('afterend', breadcrumbItem);\n await waitForUpdatesAsync();\n }\n\n public async removeBreadcrumbItemByIndex(index: number): Promise<void> {\n if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {\n throw new Error(`Breadcrumb item with index ${index} not found`);\n }\n const breadcrumbItemToRemove = this.breadcrumbElement.slottedBreadcrumbItems[index];\n breadcrumbItemToRemove?.remove();\n await waitForUpdatesAsync();\n }\n\n public async updateBreadcrumbItemLabel(\n index: number,\n label: string\n ): Promise<void> {\n if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {\n throw new Error(`Breadcrumb item with index ${index} not found`);\n }\n const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index]!;\n breadcrumb.textContent = label;\n await waitForUpdatesAsync();\n }\n\n public async scrollBreadcrumbItemIntoViewByIndex(\n index: number\n ): Promise<void> {\n if (index >= this.breadcrumbElement.slottedBreadcrumbItems.length) {\n throw new Error(`Breadcrumb item with index ${index} not found`);\n }\n const breadcrumb = this.breadcrumbElement.slottedBreadcrumbItems[index]!;\n breadcrumb.scrollIntoView();\n await waitForUpdatesAsync();\n }\n\n public getBreadcrumbViewScrollOffset(): number {\n return this.breadcrumbElement.shadowRoot!.querySelector('.list')!\n .scrollLeft;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ni/nimble-components",
|
|
3
|
-
"version": "34.3.
|
|
3
|
+
"version": "34.3.1",
|
|
4
4
|
"description": "Styled web components for the NI Nimble Design System",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss",
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
104
|
"@ni-private/eslint-config-nimble": "*",
|
|
105
|
+
"@ni-private/jasmine-extensions": "^0.0.1",
|
|
105
106
|
"@ni/jasmine-parameterized": "^1.0.1",
|
|
106
107
|
"@rollup/plugin-commonjs": "^28.0.0",
|
|
107
108
|
"@rollup/plugin-node-resolve": "^16.0.0",
|