@hashicorp/design-system-components 1.5.2 → 1.6.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/NEW-COMPONENT-CHECKLIST.md +5 -2
  3. package/addon/components/hds/flyout/body.hbs +3 -0
  4. package/addon/components/hds/flyout/description.hbs +3 -0
  5. package/addon/components/hds/flyout/header.hbs +14 -0
  6. package/addon/components/hds/flyout/index.hbs +14 -0
  7. package/addon/components/hds/flyout/index.js +107 -0
  8. package/addon/components/hds/pagination/compact/index.hbs +26 -0
  9. package/addon/components/hds/pagination/compact/index.js +87 -0
  10. package/addon/components/hds/pagination/info/index.hbs +7 -0
  11. package/addon/components/hds/pagination/info/index.js +12 -0
  12. package/addon/components/hds/pagination/nav/arrow.hbs +28 -0
  13. package/addon/components/hds/pagination/nav/arrow.js +74 -0
  14. package/addon/components/hds/pagination/nav/ellipsis.hbs +1 -0
  15. package/addon/components/hds/pagination/nav/number.hbs +12 -0
  16. package/addon/components/hds/pagination/nav/number.js +45 -0
  17. package/addon/components/hds/pagination/numbered/index.hbs +65 -0
  18. package/addon/components/hds/pagination/numbered/index.js +327 -0
  19. package/addon/components/hds/pagination/size-selector/index.hbs +10 -0
  20. package/addon/components/hds/pagination/size-selector/index.js +56 -0
  21. package/addon/components/hds/table/index.hbs +1 -1
  22. package/app/components/hds/flyout/body.js +1 -0
  23. package/app/components/hds/flyout/description.js +1 -0
  24. package/app/components/hds/flyout/header.js +1 -0
  25. package/app/components/hds/flyout/index.js +1 -0
  26. package/app/components/hds/pagination/compact/index.js +1 -0
  27. package/app/components/hds/pagination/info.js +1 -0
  28. package/app/components/hds/pagination/nav/arrow.js +1 -0
  29. package/app/components/hds/pagination/nav/ellipsis.js +1 -0
  30. package/app/components/hds/pagination/nav/number.js +1 -0
  31. package/app/components/hds/pagination/numbered/index.js +1 -0
  32. package/app/components/hds/pagination/size-selector.js +1 -0
  33. package/app/styles/@hashicorp/design-system-components.scss +3 -1
  34. package/app/styles/components/flyout.scss +95 -0
  35. package/app/styles/components/pagination.scss +194 -0
  36. package/blueprints/hds-component/files/app/styles/components/__name__.scss +3 -0
  37. package/blueprints/hds-component-test/files/tests/dummy/app/templates/components/__name__.hbs +0 -52
  38. package/package.json +6 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @hashicorp/design-system-components
2
2
 
3
+ ## 1.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1193](https://github.com/hashicorp/design-system/pull/1191) [`0f76e60`](https://github.com/hashicorp/design-system/commit/0f76e60f6eb4293dc5ba1ffb75f72d7f981a8e88) Thanks [@fivetanley](https://github.com/alex-ju)! - Fix `Hds::Table` compile error for Ember 3.28 or lower
8
+
9
+ ## 1.6.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#661](https://github.com/hashicorp/design-system/pull/661) [`2c6024a38`](https://github.com/hashicorp/design-system/commit/2c6024a38f5f457231f7301d219478a4f746de37) Thanks [@KristinLBradley](https://github.com/KristinLBradley)! - Add new **`Pagination`** component (`Numbered`, `Compact`)
14
+
15
+ * [#1070](https://github.com/hashicorp/design-system/pull/1070) [`91b004f93`](https://github.com/hashicorp/design-system/commit/91b004f9329034064890f3e7a18e35912312fb5d) Thanks [@alex-ju](https://github.com/alex-ju)! - Add `Flyout` component
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [[`2c6024a38`](https://github.com/hashicorp/design-system/commit/2c6024a38f5f457231f7301d219478a4f746de37)]:
20
+ - @hashicorp/design-system-tokens@1.4.0
21
+
3
22
  ## 1.5.2
4
23
 
5
24
  ### Patch Changes
@@ -77,8 +77,11 @@ The engineering checklist has six parts: creating the feature branch, component
77
77
 
78
78
  - [ ] create new branch from main for the component (`git checkout -b USER/COMPONENT-NAME`)
79
79
  - [ ] create new component using a blueprint
80
- - `ember generate hds-component COMPONENT-NAME`
81
- - if it's a child component, then `hds/COMPONENT_NAME/CHILD_NAME`
80
+ - if it's a component, you have to run two commands, one for the component code (and its tests) and one for the documentation pages:
81
+ - `cd packages/component` and then `ember generate hds-component COMPONENT-NAME`
82
+ - `cd website` and then `ember generate hds-component-docs COMPONENT-NAME`
83
+ - if it's a child component, then you have to run only one command:
84
+ - `cd packages/component` and then `ember generate hds-component COMPONENT_NAME/CHILD_NAME`
82
85
  - (Note: Many of the below mentioned files will be automatically generated.)
83
86
  - [ ] **component template**
84
87
  - use semantic HTML
@@ -0,0 +1,3 @@
1
+ <div class="hds-flyout__body" ...attributes>
2
+ {{yield}}
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="hds-flyout__description hds-typography-body-200" ...attributes>
2
+ {{yield}}
3
+ </div>
@@ -0,0 +1,14 @@
1
+ <div class="hds-flyout__header" ...attributes>
2
+ {{#if @icon}}
3
+ <FlightIcon class="hds-flyout__icon" @name={{@icon}} @size="24" @isInlineBlock={{false}} />
4
+ {{/if}}
5
+ <div class="hds-flyout__title hds-typography-display-300 hds-font-weight-semibold" id={{@id}}>
6
+ {{#if @tagline}}
7
+ <div class="hds-flyout__tagline hds-typography-body-100 hds-font-weight-regular">
8
+ {{@tagline}}
9
+ </div>
10
+ {{/if}}
11
+ {{yield}}
12
+ </div>
13
+ <Hds::DismissButton class="hds-flyout__dismiss" {{on "click" @onDismiss}} />
14
+ </div>
@@ -0,0 +1,14 @@
1
+ <dialog
2
+ class={{this.classNames}}
3
+ ...attributes
4
+ aria-labelledby={{this.id}}
5
+ {{did-insert this.didInsert}}
6
+ {{focus-trap isActive=this.isOpen focusTrapOptions=(hash onDeactivate=this.onDismiss clickOutsideDeactivates=true)}}
7
+ >
8
+ {{yield (hash Header=(component "hds/flyout/header" id=this.id onDismiss=this.onDismiss))}}
9
+ {{yield (hash Description=(component "hds/flyout/description"))}}
10
+ {{yield (hash Body=(component "hds/flyout/body"))}}
11
+ </dialog>
12
+ {{#if this.isOpen}}
13
+ <div class="hds-flyout__overlay"></div>
14
+ {{/if}}
@@ -0,0 +1,107 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { assert } from '@ember/debug';
4
+ import { getElementId } from '../form/utils/getElementId';
5
+ import { tracked } from '@glimmer/tracking';
6
+
7
+ export const DEFAULT_SIZE = 'medium';
8
+ export const DEFAULT_HAS_OVERLAY = true;
9
+ export const SIZES = ['medium', 'large'];
10
+
11
+ export default class HdsFlyoutIndexComponent extends Component {
12
+ @tracked isOpen = false;
13
+
14
+ /**
15
+ * Sets the size of the flyout
16
+ * Accepted values: medium, large
17
+ *
18
+ * @param size
19
+ * @type {string}
20
+ * @default 'medium'
21
+ */
22
+ get size() {
23
+ let { size = DEFAULT_SIZE } = this.args;
24
+
25
+ assert(
26
+ `@size for "Hds::Flyout" must be one of the following: ${SIZES.join(
27
+ ', '
28
+ )}; received: ${size}`,
29
+ SIZES.includes(size)
30
+ );
31
+
32
+ return size;
33
+ }
34
+
35
+ /**
36
+ * Calculates the unique ID to assign to the title
37
+ */
38
+ get id() {
39
+ return getElementId(this);
40
+ }
41
+
42
+ /**
43
+ * Get the class names to apply to the component.
44
+ * @method classNames
45
+ * @return {string} The "class" attribute to apply to the component.
46
+ */
47
+ get classNames() {
48
+ let classes = ['hds-flyout'];
49
+
50
+ // add a class based on the @size argument
51
+ classes.push(`hds-flyout--size-${this.size}`);
52
+
53
+ return classes.join(' ');
54
+ }
55
+
56
+ @action
57
+ didInsert(element) {
58
+ // Store a reference of the `<dialog>` element
59
+ this.element = element;
60
+
61
+ // Register `<dialog>` element for polyfilling if no native support is available
62
+ if (!element.showModal) {
63
+ Promise.all([import('dialog-polyfill'), import('dialog-polyfill-css')])
64
+ .then(([dialogPolyfill]) => {
65
+ const dialog = dialogPolyfill.default;
66
+ if (dialog.registerDialog) {
67
+ dialog.registerDialog(element);
68
+ // This unscoped class is defined in the dialog polyfill: https://github.com/GoogleChrome/dialog-polyfill/blob/master/dist/dialog-polyfill.css#L33
69
+ element.classList.add('fixed');
70
+ }
71
+ })
72
+ .catch({});
73
+ }
74
+
75
+ // Register "onClose" callback function to be called when a native 'close' event is dispatched
76
+ this.element.addEventListener('close', () => {
77
+ if (this.args.onClose && typeof this.args.onClose === 'function') {
78
+ this.args.onClose();
79
+ }
80
+
81
+ this.isOpen = false;
82
+ });
83
+
84
+ // If the flyout dialog is not already open
85
+ if (!this.element.open) {
86
+ this.open();
87
+ }
88
+ }
89
+
90
+ @action
91
+ open() {
92
+ // Make flyout dialog visible using the native `showModal` method
93
+ this.element.showModal();
94
+ this.isOpen = true;
95
+
96
+ // Call "onOpen" callback function
97
+ if (this.args.onOpen && typeof this.args.onOpen === 'function') {
98
+ this.args.onOpen();
99
+ }
100
+ }
101
+
102
+ @action
103
+ onDismiss() {
104
+ // Make flyout dialog invisible using the native `close` method
105
+ this.element.close();
106
+ }
107
+ }
@@ -0,0 +1,26 @@
1
+ <div class="hds-pagination" ...attributes>
2
+ <nav class="hds-pagination-nav" aria-label="Pagination navigation">
3
+ <Hds::Pagination::Nav::Arrow
4
+ @direction="prev"
5
+ @showLabel={{this.showLabels}}
6
+ @route={{this.routing.route}}
7
+ @query={{this.routing.queryPrev}}
8
+ @model={{this.routing.model}}
9
+ @models={{this.routing.models}}
10
+ @replace={{this.routing.replace}}
11
+ @onClick={{this.onPageChange}}
12
+ @disabled={{@isDisabledPrev}}
13
+ />
14
+ <Hds::Pagination::Nav::Arrow
15
+ @direction="next"
16
+ @showLabel={{this.showLabels}}
17
+ @route={{this.routing.route}}
18
+ @query={{this.routing.queryNext}}
19
+ @model={{this.routing.model}}
20
+ @models={{this.routing.models}}
21
+ @replace={{this.routing.replace}}
22
+ @onClick={{this.onPageChange}}
23
+ @disabled={{@isDisabledNext}}
24
+ />
25
+ </nav>
26
+ </div>
@@ -0,0 +1,87 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { assert } from '@ember/debug';
4
+ import { inject as service } from '@ember/service';
5
+
6
+ export default class HdsPaginationCompactIndexComponent extends Component {
7
+ @service router;
8
+
9
+ constructor() {
10
+ super(...arguments);
11
+
12
+ let { queryFunction } = this.args;
13
+
14
+ // This component works in two different ways, depending if we need to support
15
+ // routing through links (`LinkTo`) for the "navigation controls", or not.
16
+ // If there's no routing then the component behaves as "uncontrolled"
17
+ // (the state updates are handled by its internal logic).
18
+ // If instead the component needs to update the routing (and we infer this via the "query" arguments)
19
+ // then the component behaves as "controlled", where the state is
20
+ // initialized and updated using the arguments passed to it.
21
+
22
+ if (queryFunction === undefined) {
23
+ this.hasRouting = false;
24
+ } else {
25
+ assert(
26
+ '@queryFunction for "Hds::Pagination::Numbered" must be a function',
27
+ typeof queryFunction === 'function'
28
+ );
29
+ this.hasRouting = true;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * @param showLabels
35
+ * @type {boolean}
36
+ * @default true
37
+ * @description Show the labels for the "prev/next" controls
38
+ */
39
+ get showLabels() {
40
+ let { showLabels = true } = this.args;
41
+
42
+ return showLabels;
43
+ }
44
+
45
+ get routeQueryParams() {
46
+ return this.router.currentRoute?.queryParams || {};
47
+ }
48
+
49
+ buildQueryParamsObject(page) {
50
+ if (this.hasRouting) {
51
+ return this.args.queryFunction(page, this.currentPage);
52
+ } else {
53
+ return {};
54
+ }
55
+ }
56
+
57
+ get routing() {
58
+ let routing = {
59
+ route: this.args.route ?? undefined,
60
+ model: this.args.model ?? undefined,
61
+ models: this.args.models ?? undefined,
62
+ replace: this.args.replace ?? undefined,
63
+ };
64
+
65
+ // the "query" is dynamic and needs to be calculated
66
+ if (this.hasRouting) {
67
+ routing.queryPrev = this.buildQueryParamsObject('prev');
68
+ routing.queryNext = this.buildQueryParamsObject('next');
69
+ } else {
70
+ routing.queryPrev = undefined;
71
+ routing.queryNext = undefined;
72
+ }
73
+
74
+ return routing;
75
+ }
76
+
77
+ @action
78
+ onPageChange(newPage) {
79
+ this.currentPage = newPage;
80
+
81
+ let { onPageChange } = this.args;
82
+
83
+ if (typeof onPageChange === 'function') {
84
+ onPageChange(newPage);
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,7 @@
1
+ <div class="hds-pagination-info hds-typography-body-100 hds-font-weight-medium" ...attributes>
2
+ {{@itemsRangeStart}}–{{@itemsRangeEnd}}
3
+ {{#if this.showTotalItems}}
4
+ of
5
+ {{@totalItems}}
6
+ {{/if}}
7
+ </div>
@@ -0,0 +1,12 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class HdsPaginationInfoComponent extends Component {
4
+ /**
5
+ * @param showTotalItems
6
+ * @type {boolean}
7
+ * @description Controls the visibility of the total items
8
+ */
9
+ get showTotalItems() {
10
+ return this.args.showTotalItems ?? true;
11
+ }
12
+ }
@@ -0,0 +1,28 @@
1
+ {{#if @disabled}}
2
+ <Hds::Interactive class={{this.classNames}} aria-label={{this.content.ariaLabel}} disabled={{true}} ...attributes>
3
+ <FlightIcon @name={{this.content.icon}} />
4
+ {{#if this.showLabel}}
5
+ <span class="hds-pagination-nav__arrow-label" aria-hidden="true">
6
+ {{this.content.label}}
7
+ </span>
8
+ {{/if}}
9
+ </Hds::Interactive>
10
+ {{else}}
11
+ <Hds::Interactive
12
+ class={{this.classNames}}
13
+ @route={{@route}}
14
+ @query={{hds-link-to-query @query}}
15
+ @models={{hds-link-to-models @model @models}}
16
+ @replace={{@replace}}
17
+ {{on "click" this.onClick}}
18
+ aria-label={{this.content.ariaLabel}}
19
+ ...attributes
20
+ >
21
+ <FlightIcon @name={{this.content.icon}} />
22
+ {{#if this.showLabel}}
23
+ <span class="hds-pagination-nav__arrow-label" aria-hidden="true">
24
+ {{this.content.label}}
25
+ </span>
26
+ {{/if}}
27
+ </Hds::Interactive>
28
+ {{/if}}
@@ -0,0 +1,74 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { assert } from '@ember/debug';
4
+
5
+ export const DIRECTIONS = ['prev', 'next'];
6
+
7
+ export default class HdsPaginationControlArrowComponent extends Component {
8
+ get content() {
9
+ let { direction } = this.args;
10
+
11
+ assert(
12
+ `@direction for "Pagination::Nav::Arrow" must be one of the following: ${DIRECTIONS.join(
13
+ ', '
14
+ )}; received: ${direction}`,
15
+ DIRECTIONS.includes(direction)
16
+ );
17
+
18
+ let content;
19
+ if (direction === 'prev') {
20
+ content = {
21
+ label: 'Previous',
22
+ icon: 'chevron-left',
23
+ ariaLabel: 'Previous page',
24
+ };
25
+ }
26
+ if (direction === 'next') {
27
+ content = {
28
+ label: 'Next',
29
+ icon: 'chevron-right',
30
+ ariaLabel: 'Next page',
31
+ };
32
+ }
33
+
34
+ return content;
35
+ }
36
+
37
+ /**
38
+ * @param showLabel
39
+ * @type {boolean}
40
+ * @default true
41
+ * @description Show the labels for the control
42
+ */
43
+ get showLabel() {
44
+ let { showLabel = true } = this.args;
45
+
46
+ return showLabel;
47
+ }
48
+
49
+ /**
50
+ * Get the class names to apply to the component.
51
+ * @method classNames
52
+ * @return {string} The "class" attribute to apply to the component.
53
+ */
54
+ get classNames() {
55
+ let classes = [
56
+ 'hds-pagination-nav__control',
57
+ 'hds-pagination-nav__arrow',
58
+ `hds-pagination-nav__arrow--direction-${this.args.direction}`,
59
+ 'hds-typography-body-100',
60
+ 'hds-font-weight-medium',
61
+ ];
62
+
63
+ return classes.join(' ');
64
+ }
65
+
66
+ @action
67
+ onClick() {
68
+ let { onClick } = this.args;
69
+
70
+ if (typeof onClick === 'function') {
71
+ onClick(this.args.direction);
72
+ }
73
+ }
74
+ }
@@ -0,0 +1 @@
1
+ <div class="hds-pagination-nav__ellipsis" ...attributes>...</div>
@@ -0,0 +1,12 @@
1
+ <Hds::Interactive
2
+ class={{this.classNames}}
3
+ @route={{@route}}
4
+ @query={{hds-link-to-query @query}}
5
+ @models={{hds-link-to-models @model @models}}
6
+ @replace={{@replace}}
7
+ {{on "click" this.onClick}}
8
+ ...attributes
9
+ aria-current={{if @isSelected "page" null}}
10
+ >
11
+ <span class="sr-only">page </span>{{this.page}}
12
+ </Hds::Interactive>
@@ -0,0 +1,45 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { assert } from '@ember/debug';
4
+
5
+ export default class HdsPaginationControlNumberComponent extends Component {
6
+ get page() {
7
+ let { page } = this.args;
8
+
9
+ assert(
10
+ '@page for "Pagination::Nav::Number" must have a valid value',
11
+ page !== undefined
12
+ );
13
+
14
+ return page;
15
+ }
16
+
17
+ /**
18
+ * Get the class names to apply to the component.
19
+ * @method classNames
20
+ * @return {string} The "class" attribute to apply to the component.
21
+ */
22
+ get classNames() {
23
+ let classes = [
24
+ 'hds-pagination-nav__control',
25
+ 'hds-pagination-nav__number',
26
+ 'hds-typography-body-100',
27
+ 'hds-font-weight-medium"',
28
+ ];
29
+
30
+ if (this.args.isSelected) {
31
+ classes.push(`hds-pagination-nav__number--is-selected`);
32
+ }
33
+
34
+ return classes.join(' ');
35
+ }
36
+
37
+ @action
38
+ onClick() {
39
+ let { onClick } = this.args;
40
+
41
+ if (typeof onClick === 'function') {
42
+ onClick(this.args.page);
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,65 @@
1
+ <div class="hds-pagination" ...attributes>
2
+ {{#if this.showInfo}}
3
+ <Hds::Pagination::Info
4
+ @itemsRangeStart={{this.itemsRangeStart}}
5
+ @itemsRangeEnd={{this.itemsRangeEnd}}
6
+ @totalItems={{@totalItems}}
7
+ @showTotalItems={{@showTotalItems}}
8
+ />
9
+ {{/if}}
10
+
11
+ <nav class="hds-pagination-nav" aria-label="Pagination navigation">
12
+ <Hds::Pagination::Nav::Arrow
13
+ @direction="prev"
14
+ @showLabel={{this.showLabels}}
15
+ @route={{this.routing.route}}
16
+ @query={{this.routing.queryPrev}}
17
+ @model={{this.routing.model}}
18
+ @models={{this.routing.models}}
19
+ @replace={{this.routing.replace}}
20
+ @onClick={{this.onPageChange}}
21
+ @disabled={{this.isDisabledPrev}}
22
+ />
23
+ {{#if this.showPageNumbers}}
24
+ <ul class="hds-pagination-nav__page-list">
25
+ {{#each this.pages as |page|}}
26
+ <li class="hds-pagination-nav__page-item">
27
+ {{#if (eq page "…")}}
28
+ <Hds::Pagination::Nav::Ellipsis />
29
+ {{else}}
30
+ <Hds::Pagination::Nav::Number
31
+ @page={{page}}
32
+ @route={{this.routing.route}}
33
+ @query={{get this.routing.queryPages page}}
34
+ @model={{this.routing.model}}
35
+ @models={{this.routing.models}}
36
+ @replace={{this.routing.replace}}
37
+ @onClick={{this.onPageChange}}
38
+ @isSelected={{if (eq page this.currentPage) true false}}
39
+ />
40
+ {{/if}}
41
+ </li>
42
+ {{/each}}
43
+ </ul>
44
+ {{/if}}
45
+ <Hds::Pagination::Nav::Arrow
46
+ @direction="next"
47
+ @showLabel={{this.showLabels}}
48
+ @route={{this.routing.route}}
49
+ @query={{this.routing.queryNext}}
50
+ @model={{this.routing.model}}
51
+ @models={{this.routing.models}}
52
+ @replace={{this.routing.replace}}
53
+ @onClick={{this.onPageChange}}
54
+ @disabled={{this.isDisabledNext}}
55
+ />
56
+ </nav>
57
+
58
+ {{#if this.showSizeSelector}}
59
+ <Hds::Pagination::SizeSelector
60
+ @pageSizes={{this.pageSizes}}
61
+ @selectedSize={{this.currentPageSize}}
62
+ @onChange={{this.onPageSizeChange}}
63
+ />
64
+ {{/if}}
65
+ </div>