@zywave/zui-table 4.3.4-pre.0 → 4.4.0-pre.0

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.
@@ -515,6 +515,17 @@
515
515
  "attribute": "banded",
516
516
  "reflects": true
517
517
  },
518
+ {
519
+ "kind": "field",
520
+ "name": "mode",
521
+ "type": {
522
+ "text": "ZuiTableMode"
523
+ },
524
+ "default": "'default'",
525
+ "description": "Ability to modify the table's layout behavior. The supported values are:\n- `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.\n- `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.",
526
+ "attribute": "mode",
527
+ "reflects": true
528
+ },
518
529
  {
519
530
  "kind": "field",
520
531
  "name": "noResults",
@@ -545,14 +556,6 @@
545
556
  },
546
557
  "privacy": "private"
547
558
  },
548
- {
549
- "kind": "field",
550
- "name": "_footer",
551
- "type": {
552
- "text": "Array<ZuiTableFooterElement>"
553
- },
554
- "privacy": "private"
555
- },
556
559
  {
557
560
  "kind": "field",
558
561
  "name": "#internals",
@@ -585,12 +588,7 @@
585
588
  },
586
589
  {
587
590
  "kind": "method",
588
- "name": "#renderNoResultsView",
589
- "privacy": "private"
590
- },
591
- {
592
- "kind": "method",
593
- "name": "#reassignFooter",
591
+ "name": "#onSlotChange",
594
592
  "privacy": "private"
595
593
  },
596
594
  {
@@ -620,6 +618,15 @@
620
618
  "description": "Set for alternating table row background colors",
621
619
  "fieldName": "banded"
622
620
  },
621
+ {
622
+ "name": "mode",
623
+ "type": {
624
+ "text": "ZuiTableMode"
625
+ },
626
+ "default": "'default'",
627
+ "description": "Ability to modify the table's layout behavior. The supported values are:\n- `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.\n- `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.",
628
+ "fieldName": "mode"
629
+ },
623
630
  {
624
631
  "name": "no-results",
625
632
  "type": {
@@ -1,3 +1,3 @@
1
1
  import { css } from 'lit';
2
- export const style = css `:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;
2
+ export const style = css `:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}@media(width > 45em){:host([mode=fixed-sizing]){max-width:var(--zui-table-max-width, none)}:host([mode=fixed-sizing]) .body{max-height:var(--zui-table-max-height, none);overflow:auto}:host([mode=fixed-sizing]) ::slotted(zui-table-row[header]){position:sticky;top:0;left:0;width:fit-content;z-index:1}}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;
3
3
  //# sourceMappingURL=zui-table-css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zui-table-css.js","sourceRoot":"","sources":["../src/zui-table-css.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA,qoCAAqoC,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const style = css`:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;\n"]}
1
+ {"version":3,"file":"zui-table-css.js","sourceRoot":"","sources":["../src/zui-table-css.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA,k7CAAk7C,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const style = css`:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}@media(width > 45em){:host([mode=fixed-sizing]){max-width:var(--zui-table-max-width, none)}:host([mode=fixed-sizing]) .body{max-height:var(--zui-table-max-height, none);overflow:auto}:host([mode=fixed-sizing]) ::slotted(zui-table-row[header]){position:sticky;top:0;left:0;width:fit-content;z-index:1}}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;\n"]}
@@ -1,3 +1,3 @@
1
1
  import { css } from 'lit';
2
- export const style = css `:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;
2
+ export const style = css `:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){--zui-table-columns-template: 1fr;background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;
3
3
  //# sourceMappingURL=zui-table-row-css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zui-table-row-css.js","sourceRoot":"","sources":["../src/zui-table-row-css.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA,w+BAAw+B,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;\n"]}
1
+ {"version":3,"file":"zui-table-row-css.js","sourceRoot":"","sources":["../src/zui-table-row-css.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA,0gCAA0gC,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){--zui-table-columns-template: 1fr;background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;\n"]}
@@ -28,21 +28,11 @@ export class ZuiTableTopbarElement extends ZuiTableBaseElement {
28
28
  }
29
29
  connectedCallback() {
30
30
  super.connectedCallback();
31
- if (this.#mobileBreakpoint.addEventListener) {
32
- this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);
33
- }
34
- else {
35
- this.#mobileBreakpoint.addListener(this.#mobileTopbarActionButtonsEvent);
36
- }
31
+ this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);
37
32
  }
38
33
  disconnectedCallback() {
39
34
  super.disconnectedCallback();
40
- if (this.#mobileBreakpoint.addEventListener) {
41
- this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);
42
- }
43
- else if (this.#mobileBreakpoint.addListener) {
44
- this.#mobileBreakpoint.removeListener(this.#mobileTopbarActionButtonsEvent);
45
- }
35
+ this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);
46
36
  }
47
37
  firstUpdated() {
48
38
  this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();
@@ -1 +1 @@
1
- {"version":3,"file":"zui-table-topbar.js","sourceRoot":"","sources":["../src/zui-table-topbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZuiTableBaseElement } from './base.js';\nimport { html } from 'lit';\nimport { queryAssignedElements, queryAssignedNodes } from 'lit/decorators.js';\nimport { style } from './zui-table-topbar-css.js';\nimport { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';\nimport type { ZuiButton } from '@zywave/zui-button/dist/zui-button.js';\n\n/**\n * Used to house table related pieces such as a search input or `<zui-search>`, and other up front information.\n *\n * @element zui-table-topbar\n *\n * @slot - Default, unnamed slot; for inserting content into `<zui-table-topbar>`\n * @slot counter - Total number of results from table goes here\n * @slot action - Action(s) that affect the whole table goes here\n */\nexport class ZuiTableTopbarElement extends ZuiTableBaseElement {\n @queryAssignedElements({ slot: 'action' })\n private _actionSlottedElements: Array<HTMLCollection>;\n\n @queryAssignedNodes({ slot: 'counter' })\n private _counterSlottedNodes: Array<HTMLCollection>;\n\n @queryAssignedElements({ selector: 'zui-button', slot: 'action' })\n private _actionButtons: Array<ZuiButton>;\n\n #mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);\n\n #mobileTopbarActionButtonsEvent = (b: MediaQueryListEvent) => {\n b.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n };\n\n static get styles() {\n return [super.styles, style];\n }\n\n connectedCallback() {\n super.connectedCallback();\n\n if (this.#mobileBreakpoint.addEventListener) {\n this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);\n } else {\n this.#mobileBreakpoint.addListener(this.#mobileTopbarActionButtonsEvent);\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n if (this.#mobileBreakpoint.addEventListener) {\n this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);\n } else if (this.#mobileBreakpoint.addListener) {\n this.#mobileBreakpoint.removeListener(this.#mobileTopbarActionButtonsEvent);\n }\n }\n\n firstUpdated() {\n this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n this.#toggleActionDivDisplay();\n this.#toggleCounterDivDisplay();\n }\n\n render() {\n return html`<div class=\"topbar\">\n <div class=\"content\"><slot></slot></div>\n <div class=\"counter\"><slot name=\"counter\" @slotchange=\"${this.#toggleCounterDivDisplay}\"></slot></div>\n <div class=\"action\"><slot name=\"action\" @slotchange=${this.#handleActionSlotchange}></slot></div>\n </div>`;\n }\n\n #handleActionSlotchange() {\n this.#toggleActionDivDisplay();\n this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n }\n\n #addBlockStylingToButtons() {\n if (this._actionButtons.length > 0) {\n for (const button of this._actionButtons) {\n if (!button.hasAttribute('block')) {\n button.setAttribute('block', '');\n }\n }\n }\n\n this.requestUpdate();\n }\n\n #removeBlockStylingFromButtons() {\n if (this._actionButtons.length > 0) {\n for (const button of this._actionButtons) {\n if (button.hasAttribute('block')) {\n button.removeAttribute('block');\n }\n }\n }\n\n this.requestUpdate();\n }\n\n #toggleCounterDivDisplay() {\n const counter: HTMLElement = this.shadowRoot.querySelector('.counter');\n\n if (this._counterSlottedNodes.length === 0) {\n counter.style.display = 'none';\n } else if (this._counterSlottedNodes.length > 0 && counter.style.display === 'none') {\n counter.style.removeProperty('display');\n }\n\n this.requestUpdate();\n }\n\n #toggleActionDivDisplay() {\n const action: HTMLElement = this.shadowRoot.querySelector('.action');\n\n if (this._actionSlottedElements.length === 0) {\n action.style.display = 'none';\n } else if (this._actionSlottedElements.length > 0 && action.style.display === 'none') {\n action.style.removeProperty('display');\n }\n\n this.requestUpdate();\n }\n}\n\nwindow.customElements.define('zui-table-topbar', ZuiTableTopbarElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'zui-table-topbar': ZuiTableTopbarElement;\n }\n}\n"]}
1
+ {"version":3,"file":"zui-table-topbar.js","sourceRoot":"","sources":["../src/zui-table-topbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZuiTableBaseElement } from './base.js';\nimport { html } from 'lit';\nimport { queryAssignedElements, queryAssignedNodes } from 'lit/decorators.js';\nimport { style } from './zui-table-topbar-css.js';\nimport { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';\nimport type { ZuiButton } from '@zywave/zui-button/dist/zui-button.js';\n\n/**\n * Used to house table related pieces such as a search input or `<zui-search>`, and other up front information.\n *\n * @element zui-table-topbar\n *\n * @slot - Default, unnamed slot; for inserting content into `<zui-table-topbar>`\n * @slot counter - Total number of results from table goes here\n * @slot action - Action(s) that affect the whole table goes here\n */\nexport class ZuiTableTopbarElement extends ZuiTableBaseElement {\n @queryAssignedElements({ slot: 'action' })\n private _actionSlottedElements: Array<HTMLCollection>;\n\n @queryAssignedNodes({ slot: 'counter' })\n private _counterSlottedNodes: Array<HTMLCollection>;\n\n @queryAssignedElements({ selector: 'zui-button', slot: 'action' })\n private _actionButtons: Array<ZuiButton>;\n\n #mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);\n\n #mobileTopbarActionButtonsEvent = (b: MediaQueryListEvent) => {\n b.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n };\n\n static get styles() {\n return [super.styles, style];\n }\n\n connectedCallback() {\n super.connectedCallback();\n\n this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);\n }\n\n firstUpdated() {\n this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n this.#toggleActionDivDisplay();\n this.#toggleCounterDivDisplay();\n }\n\n render() {\n return html`<div class=\"topbar\">\n <div class=\"content\"><slot></slot></div>\n <div class=\"counter\"><slot name=\"counter\" @slotchange=\"${this.#toggleCounterDivDisplay}\"></slot></div>\n <div class=\"action\"><slot name=\"action\" @slotchange=${this.#handleActionSlotchange}></slot></div>\n </div>`;\n }\n\n #handleActionSlotchange() {\n this.#toggleActionDivDisplay();\n this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();\n }\n\n #addBlockStylingToButtons() {\n if (this._actionButtons.length > 0) {\n for (const button of this._actionButtons) {\n if (!button.hasAttribute('block')) {\n button.setAttribute('block', '');\n }\n }\n }\n\n this.requestUpdate();\n }\n\n #removeBlockStylingFromButtons() {\n if (this._actionButtons.length > 0) {\n for (const button of this._actionButtons) {\n if (button.hasAttribute('block')) {\n button.removeAttribute('block');\n }\n }\n }\n\n this.requestUpdate();\n }\n\n #toggleCounterDivDisplay() {\n const counter: HTMLElement = this.shadowRoot.querySelector('.counter');\n\n if (this._counterSlottedNodes.length === 0) {\n counter.style.display = 'none';\n } else if (this._counterSlottedNodes.length > 0 && counter.style.display === 'none') {\n counter.style.removeProperty('display');\n }\n\n this.requestUpdate();\n }\n\n #toggleActionDivDisplay() {\n const action: HTMLElement = this.shadowRoot.querySelector('.action');\n\n if (this._actionSlottedElements.length === 0) {\n action.style.display = 'none';\n } else if (this._actionSlottedElements.length > 0 && action.style.display === 'none') {\n action.style.removeProperty('display');\n }\n\n this.requestUpdate();\n }\n}\n\nwindow.customElements.define('zui-table-topbar', ZuiTableTopbarElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'zui-table-topbar': ZuiTableTopbarElement;\n }\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import { ZuiTableBaseElement } from './base.js';
2
2
  import '@zywave/zui-spinner';
3
3
  import type { ZuiTableCellElement, ZuiTableSortDirection } from './zui-table-cell.js';
4
+ import type { PropertyValues } from 'lit';
5
+ type ZuiTableMode = 'default' | 'fixed-sizing';
4
6
  /**
5
7
  * A standardized responsive table component.
6
8
  *
@@ -27,6 +29,12 @@ export declare class ZuiTableElement extends ZuiTableBaseElement {
27
29
  * Set for alternating table row background colors
28
30
  */
29
31
  banded: boolean;
32
+ /**
33
+ * Ability to modify the table's layout behavior. The supported values are:
34
+ * - `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.
35
+ * - `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.
36
+ */
37
+ mode: ZuiTableMode;
30
38
  /**
31
39
  * Set to show or hide no results message when there are no results; use in conjunction with the assigned slot `no-results-message` to include a no results message
32
40
  */
@@ -36,12 +44,11 @@ export declare class ZuiTableElement extends ZuiTableBaseElement {
36
44
  */
37
45
  loading: boolean;
38
46
  private _rows;
39
- private _footer;
40
47
  static get styles(): (import("lit").CSSResult | import("lit").CSSResultArray)[];
41
48
  constructor();
42
49
  connectedCallback(): void;
43
50
  disconnectedCallback(): void;
44
- firstUpdated(): void;
51
+ updated(changedProperties: PropertyValues<this>): void;
45
52
  render(): import("lit-html").TemplateResult<1>;
46
53
  }
47
54
  declare global {
@@ -53,3 +60,4 @@ export type SortEventDetail = {
53
60
  sort: ZuiTableSortDirection;
54
61
  cell: ZuiTableCellElement;
55
62
  };
63
+ export {};
package/dist/zui-table.js CHANGED
@@ -45,6 +45,12 @@ export class ZuiTableElement extends ZuiTableBaseElement {
45
45
  * Set for alternating table row background colors
46
46
  */
47
47
  this.banded = false;
48
+ /**
49
+ * Ability to modify the table's layout behavior. The supported values are:
50
+ * - `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.
51
+ * - `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.
52
+ */
53
+ this.mode = 'default';
48
54
  // TODO: add divided prop so all table cells will have 1px border
49
55
  /**
50
56
  * Set to show or hide no results message when there are no results; use in conjunction with the assigned slot `no-results-message` to include a no results message
@@ -77,53 +83,52 @@ export class ZuiTableElement extends ZuiTableBaseElement {
77
83
  connectedCallback() {
78
84
  super.connectedCallback();
79
85
  this.setAttribute('role', 'table');
80
- if (this.#mobileBreakpoint.addEventListener) {
81
- this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);
82
- }
83
- else {
84
- this.#mobileBreakpoint.addListener(this.#mobileHeadersEvent);
85
- }
86
+ this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);
86
87
  }
87
88
  disconnectedCallback() {
88
89
  super.disconnectedCallback();
89
- if (this.#mobileBreakpoint.addEventListener) {
90
- this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);
91
- }
92
- else if (this.#mobileBreakpoint.addListener) {
93
- this.#mobileBreakpoint.removeListener(this.#mobileHeadersEvent);
94
- }
90
+ this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);
95
91
  }
96
- firstUpdated() {
97
- this.#reassignFooter();
92
+ updated(changedProperties) {
93
+ super.updated(changedProperties);
94
+ const footer = this.querySelector('zui-table-footer:not([slot])');
95
+ const header = this.querySelector('zui-table-row[header]:not([slot])');
96
+ const topbar = this.querySelector('zui-table-topbar:not([slot])');
97
+ const summary = this.querySelector('zui-table-row[summary]:not([slot])');
98
+ footer?.setAttribute('slot', 'footer');
99
+ header?.setAttribute('slot', 'header');
100
+ topbar?.setAttribute('slot', 'topbar');
101
+ summary?.setAttribute('slot', 'summary');
98
102
  this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();
99
103
  }
100
104
  render() {
101
105
  return html `<div class="table">
102
- <slot
103
- @slotchange="${this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells : this.#removeRowHeadersFromCells}"
104
- ></slot>
105
- ${this.loading ? html `<zui-spinner active="" part="loader"></zui-spinner>` : html ``}
106
- ${this.#renderNoResultsView()}</div
107
- >
106
+ <slot name="topbar"></slot>
107
+ <div class="body" role="rowgroup">
108
+ <slot name="header" @slotchange="${this.#onSlotChange}"></slot>
109
+ <slot @slotchange="${this.#onSlotChange}"></slot>
110
+ ${this.loading ? html `<zui-spinner active="" part="loader"></zui-spinner>` : html ``}
111
+ <div class="no-results"><slot name="no-results-message"></slot></div>
112
+ </div>
113
+ <slot name="summary"></slot>
114
+ </div>
108
115
  <div><slot name="footer"></slot></div>`;
109
116
  }
110
- #renderNoResultsView() {
111
- return html `<div class="no-results"><slot name="no-results-message"></slot></div>`;
112
- }
113
- #reassignFooter() {
114
- this._footer?.map((f) => f.setAttribute('slot', 'footer'));
117
+ #onSlotChange() {
118
+ this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();
119
+ this.requestUpdate();
115
120
  }
116
121
  #addRowHeadersToCells() {
117
- const rowHeadersList = this._rows.filter((h) => h.hasAttribute('header'));
118
- const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));
119
- if (rowHeadersList.length > 0) {
122
+ const headerRow = this.querySelector('zui-table-row[header]');
123
+ if (headerRow) {
124
+ const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));
120
125
  for (const row of rowBodyList) {
121
126
  for (let i = 0; i < row.children.length; i++) {
122
127
  const cell = row.children[i];
123
128
  if (!cell.shadowRoot.querySelector('.header')) {
124
129
  const rowHeaderContainer = document.createElement('div');
125
130
  rowHeaderContainer.classList.add('header');
126
- const rowHeaderText = rowHeadersList[0].children[i].textContent;
131
+ const rowHeaderText = headerRow.children[i].textContent;
127
132
  rowHeaderContainer.innerText = rowHeaderText;
128
133
  cell.shadowRoot.prepend(rowHeaderContainer);
129
134
  }
@@ -131,7 +136,6 @@ export class ZuiTableElement extends ZuiTableBaseElement {
131
136
  }
132
137
  }
133
138
  updateCustomState(this.#internals, 'add', 'mobile');
134
- this.requestUpdate();
135
139
  }
136
140
  #removeRowHeadersFromCells() {
137
141
  const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));
@@ -146,12 +150,14 @@ export class ZuiTableElement extends ZuiTableBaseElement {
146
150
  }
147
151
  // remove custom state --mobile from zui-table
148
152
  updateCustomState(this.#internals, 'delete', 'mobile');
149
- this.requestUpdate();
150
153
  }
151
154
  }
152
155
  __decorate([
153
156
  property({ type: Boolean, reflect: true })
154
157
  ], ZuiTableElement.prototype, "banded", void 0);
158
+ __decorate([
159
+ property({ reflect: true })
160
+ ], ZuiTableElement.prototype, "mode", void 0);
155
161
  __decorate([
156
162
  property({ type: Boolean, reflect: true, attribute: 'no-results' })
157
163
  ], ZuiTableElement.prototype, "noResults", void 0);
@@ -161,8 +167,5 @@ __decorate([
161
167
  __decorate([
162
168
  queryAssignedElements({ selector: 'zui-table-row' })
163
169
  ], ZuiTableElement.prototype, "_rows", void 0);
164
- __decorate([
165
- queryAssignedElements({ selector: 'zui-table-footer' })
166
- ], ZuiTableElement.prototype, "_footer", void 0);
167
170
  window.customElements.define('zui-table', ZuiTableElement);
168
171
  //# sourceMappingURL=zui-table.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zui-table.js","sourceRoot":"","sources":["../src/zui-table.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZuiTableBaseElement, TableElementConnectedEvent } from './base.js';\nimport { html } from 'lit';\nimport { property, queryAssignedElements } from 'lit/decorators.js';\nimport { style } from './zui-table-css.js';\nimport { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';\nimport '@zywave/zui-spinner';\nimport { updateCustomState } from '@zywave/zui-base/dist/utils/update-custom-state.js';\nimport type { ZuiTableRowElement } from './zui-table-row.js';\nimport type { ZuiTableFooterElement } from './zui-table-footer.js';\nimport type { ZuiTableCellElement, ZuiTableSortDirection } from './zui-table-cell.js';\n\n/**\n * A standardized responsive table component.\n *\n * @element zui-table\n *\n * @slot - Default, unnamed slot; for inserting `<zui-table-topbar>`, `<zui-table-row>`, and `<zui-table-footer>` elements, including a custom no results view, into `<zui-table>`\n * @slot no-results-message - Customize the no results message that is shown when the `no-results` attribute is set on `<zui-table>`: `<zui-table no-results>`\n * @slot footer - Only for `<zui-table-footer>`. When there is a `<zui-table-footer>` present inside `<zui-table>`, it will be auto-assigned to this slot in order to place it outside of the rendered table for styling purposes.\n *\n * @cssprop [--zui-table-cell-padding=13px 20px] - Override cell padding\n * @cssprop [--zui-table-columns-template=repeat(auto-fit, minmax(0, 1fr))] - Override the table columns template. See https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns for more information on valid values.\n * @cssprop [--zui-table-summary-background-color=var(--zui-gray-600)] - Override the table summary background color\n * @cssprop [--zui-table-summary-text-color=#fff] - Override the the table summary text color\n * @cssprop [--zui-table-footer-margin=10px] - Override the margin between the table and footer of the table\n * @cssprop [--zui-table-loading-min-height=20rem] - Override the minimum height of the table body when in a loading state\n *\n * @event sort - Event fires when the table's active sort changes. Event detail is an object with the `sort` direction and `cell` ZuiTableCellElement.\n *\n * @cssState mobile - Applied when the table is rendered in mobile mode\n */\nexport class ZuiTableElement extends ZuiTableBaseElement {\n /**\n * Set for alternating table row background colors\n */\n @property({ type: Boolean, reflect: true })\n banded = false;\n\n // TODO: add divided prop so all table cells will have 1px border\n\n /**\n * Set to show or hide no results message when there are no results; use in conjunction with the assigned slot `no-results-message` to include a no results message\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-results' })\n noResults = false;\n\n /**\n * Set to show a loading spinner in the table\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n @queryAssignedElements({ selector: 'zui-table-row' })\n private _rows: Array<ZuiTableRowElement>;\n\n @queryAssignedElements({ selector: 'zui-table-footer' })\n private _footer: Array<ZuiTableFooterElement>;\n\n #internals?: ElementInternals;\n #mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);\n #sortLock = false;\n\n #mobileHeadersEvent = (b: MediaQueryListEvent) => {\n b.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();\n };\n\n static get styles() {\n return [super.styles, style];\n }\n\n constructor() {\n super();\n\n this.#internals = this.attachInternals?.();\n\n ZuiTableBaseElement._globalChannel.addEventListener('connected', (event: TableElementConnectedEvent) => {\n if (this.contains(event.detail.element)) {\n this._associateElement(event.detail.element);\n }\n });\n\n this._state.channel.addEventListener('sort', (event: CustomEvent<SortEventDetail>) => {\n if (this.#sortLock) {\n return;\n }\n this.#sortLock = true;\n this.dispatchEvent(new CustomEvent<SortEventDetail>('sort', { detail: event.detail, bubbles: true }));\n setTimeout(() => (this.#sortLock = false), 0);\n });\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.setAttribute('role', 'table');\n\n if (this.#mobileBreakpoint.addEventListener) {\n this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);\n } else {\n this.#mobileBreakpoint.addListener(this.#mobileHeadersEvent);\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n if (this.#mobileBreakpoint.addEventListener) {\n this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);\n } else if (this.#mobileBreakpoint.addListener) {\n this.#mobileBreakpoint.removeListener(this.#mobileHeadersEvent);\n }\n }\n\n firstUpdated() {\n this.#reassignFooter();\n\n this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();\n }\n\n render() {\n return html`<div class=\"table\">\n <slot\n @slotchange=\"${this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells : this.#removeRowHeadersFromCells}\"\n ></slot>\n ${this.loading ? html`<zui-spinner active=\"\" part=\"loader\"></zui-spinner>` : html``}\n ${this.#renderNoResultsView()}</div\n >\n <div><slot name=\"footer\"></slot></div>`;\n }\n\n #renderNoResultsView() {\n return html`<div class=\"no-results\"><slot name=\"no-results-message\"></slot></div>`;\n }\n\n #reassignFooter() {\n this._footer?.map((f) => f.setAttribute('slot', 'footer'));\n }\n\n #addRowHeadersToCells() {\n const rowHeadersList = this._rows.filter((h) => h.hasAttribute('header'));\n const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));\n\n if (rowHeadersList.length > 0) {\n for (const row of rowBodyList) {\n for (let i = 0; i < row.children.length; i++) {\n const cell = row.children[i];\n if (!cell.shadowRoot.querySelector('.header')) {\n const rowHeaderContainer = document.createElement('div');\n rowHeaderContainer.classList.add('header');\n const rowHeaderText = rowHeadersList[0].children[i].textContent;\n rowHeaderContainer.innerText = rowHeaderText;\n cell.shadowRoot.prepend(rowHeaderContainer);\n }\n }\n }\n }\n\n updateCustomState(this.#internals, 'add', 'mobile');\n\n this.requestUpdate();\n }\n\n #removeRowHeadersFromCells() {\n const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));\n\n for (const row of rowBodyList) {\n for (let i = 0; i < row.children.length; i++) {\n const rowChildren = row.children[i].shadowRoot;\n const header = rowChildren.querySelector('.header');\n if (header) {\n rowChildren.removeChild(header);\n }\n }\n }\n\n // remove custom state --mobile from zui-table\n updateCustomState(this.#internals, 'delete', 'mobile');\n\n this.requestUpdate();\n }\n}\n\nwindow.customElements.define('zui-table', ZuiTableElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'zui-table': ZuiTableElement;\n }\n}\n\nexport type SortEventDetail = { sort: ZuiTableSortDirection; cell: ZuiTableCellElement };\n"]}
1
+ {"version":3,"file":"zui-table.js","sourceRoot":"","sources":["../src/zui-table.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZuiTableBaseElement, TableElementConnectedEvent } from './base.js';\nimport { html } from 'lit';\nimport { property, queryAssignedElements } from 'lit/decorators.js';\nimport { style } from './zui-table-css.js';\nimport { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';\nimport '@zywave/zui-spinner';\nimport { updateCustomState } from '@zywave/zui-base/dist/utils/update-custom-state.js';\nimport type { ZuiTableRowElement } from './zui-table-row.js';\nimport type { ZuiTableCellElement, ZuiTableSortDirection } from './zui-table-cell.js';\nimport type { PropertyValues } from 'lit';\n\ntype ZuiTableMode = 'default' | 'fixed-sizing';\n\n/**\n * A standardized responsive table component.\n *\n * @element zui-table\n *\n * @slot - Default, unnamed slot; for inserting `<zui-table-topbar>`, `<zui-table-row>`, and `<zui-table-footer>` elements, including a custom no results view, into `<zui-table>`\n * @slot no-results-message - Customize the no results message that is shown when the `no-results` attribute is set on `<zui-table>`: `<zui-table no-results>`\n * @slot footer - Only for `<zui-table-footer>`. When there is a `<zui-table-footer>` present inside `<zui-table>`, it will be auto-assigned to this slot in order to place it outside of the rendered table for styling purposes.\n *\n * @cssprop [--zui-table-cell-padding=13px 20px] - Override cell padding\n * @cssprop [--zui-table-columns-template=repeat(auto-fit, minmax(0, 1fr))] - Override the table columns template. See https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns for more information on valid values.\n * @cssprop [--zui-table-summary-background-color=var(--zui-gray-600)] - Override the table summary background color\n * @cssprop [--zui-table-summary-text-color=#fff] - Override the the table summary text color\n * @cssprop [--zui-table-footer-margin=10px] - Override the margin between the table and footer of the table\n * @cssprop [--zui-table-loading-min-height=20rem] - Override the minimum height of the table body when in a loading state\n *\n * @event sort - Event fires when the table's active sort changes. Event detail is an object with the `sort` direction and `cell` ZuiTableCellElement.\n *\n * @cssState mobile - Applied when the table is rendered in mobile mode\n */\nexport class ZuiTableElement extends ZuiTableBaseElement {\n /**\n * Set for alternating table row background colors\n */\n @property({ type: Boolean, reflect: true })\n banded = false;\n\n /**\n * Ability to modify the table's layout behavior. The supported values are:\n * - `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.\n * - `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.\n */\n @property({ reflect: true })\n mode: ZuiTableMode = 'default';\n\n // TODO: add divided prop so all table cells will have 1px border\n\n /**\n * Set to show or hide no results message when there are no results; use in conjunction with the assigned slot `no-results-message` to include a no results message\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-results' })\n noResults = false;\n\n /**\n * Set to show a loading spinner in the table\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n @queryAssignedElements({ selector: 'zui-table-row' })\n private _rows: Array<ZuiTableRowElement>;\n\n #internals?: ElementInternals;\n #mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);\n #sortLock = false;\n\n #mobileHeadersEvent = (b: MediaQueryListEvent) => {\n b.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();\n };\n\n static get styles() {\n return [super.styles, style];\n }\n\n constructor() {\n super();\n\n this.#internals = this.attachInternals?.();\n\n ZuiTableBaseElement._globalChannel.addEventListener('connected', (event: TableElementConnectedEvent) => {\n if (this.contains(event.detail.element)) {\n this._associateElement(event.detail.element);\n }\n });\n\n this._state.channel.addEventListener('sort', (event: CustomEvent<SortEventDetail>) => {\n if (this.#sortLock) {\n return;\n }\n this.#sortLock = true;\n this.dispatchEvent(new CustomEvent<SortEventDetail>('sort', { detail: event.detail, bubbles: true }));\n setTimeout(() => (this.#sortLock = false), 0);\n });\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.setAttribute('role', 'table');\n\n this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);\n }\n\n updated(changedProperties: PropertyValues<this>) {\n super.updated(changedProperties);\n\n const footer = this.querySelector('zui-table-footer:not([slot])');\n const header = this.querySelector('zui-table-row[header]:not([slot])');\n const topbar = this.querySelector('zui-table-topbar:not([slot])');\n const summary = this.querySelector('zui-table-row[summary]:not([slot])');\n footer?.setAttribute('slot', 'footer');\n header?.setAttribute('slot', 'header');\n topbar?.setAttribute('slot', 'topbar');\n summary?.setAttribute('slot', 'summary');\n\n this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();\n }\n\n render() {\n return html`<div class=\"table\">\n <slot name=\"topbar\"></slot>\n <div class=\"body\" role=\"rowgroup\">\n <slot name=\"header\" @slotchange=\"${this.#onSlotChange}\"></slot>\n <slot @slotchange=\"${this.#onSlotChange}\"></slot>\n ${this.loading ? html`<zui-spinner active=\"\" part=\"loader\"></zui-spinner>` : html``}\n <div class=\"no-results\"><slot name=\"no-results-message\"></slot></div>\n </div>\n <slot name=\"summary\"></slot>\n </div>\n <div><slot name=\"footer\"></slot></div>`;\n }\n\n #onSlotChange() {\n this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();\n this.requestUpdate();\n }\n\n #addRowHeadersToCells() {\n const headerRow = this.querySelector('zui-table-row[header]');\n\n if (headerRow) {\n const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));\n for (const row of rowBodyList) {\n for (let i = 0; i < row.children.length; i++) {\n const cell = row.children[i];\n if (!cell.shadowRoot.querySelector('.header')) {\n const rowHeaderContainer = document.createElement('div');\n rowHeaderContainer.classList.add('header');\n const rowHeaderText = headerRow.children[i].textContent;\n rowHeaderContainer.innerText = rowHeaderText;\n cell.shadowRoot.prepend(rowHeaderContainer);\n }\n }\n }\n }\n\n updateCustomState(this.#internals, 'add', 'mobile');\n }\n\n #removeRowHeadersFromCells() {\n const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));\n\n for (const row of rowBodyList) {\n for (let i = 0; i < row.children.length; i++) {\n const rowChildren = row.children[i].shadowRoot;\n const header = rowChildren.querySelector('.header');\n if (header) {\n rowChildren.removeChild(header);\n }\n }\n }\n\n // remove custom state --mobile from zui-table\n updateCustomState(this.#internals, 'delete', 'mobile');\n }\n}\n\nwindow.customElements.define('zui-table', ZuiTableElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'zui-table': ZuiTableElement;\n }\n}\n\nexport type SortEventDetail = { sort: ZuiTableSortDirection; cell: ZuiTableCellElement };\n"]}
package/lab.html CHANGED
@@ -45,7 +45,13 @@
45
45
  }
46
46
 
47
47
  zui-table::part(loader) {
48
- top: 10%;
48
+ top: 20%;
49
+ }
50
+
51
+ zui-table.scroll {
52
+ --zui-table-max-width: 600px;
53
+ --zui-table-max-height: 200px;
54
+ --zui-table-columns-template: repeat(8, 200px);
49
55
  }
50
56
  </style>
51
57
  </head>
@@ -484,9 +490,7 @@
484
490
  </zui-table-cell>
485
491
  </zui-table-row>
486
492
  <zui-table-row summary>
487
- <zui-table-cell style="text-align: right;">
488
- Average lifespan: 742 years
489
- </zui-table-cell>
493
+ <zui-table-cell style="text-align: right"> Average lifespan: 742 years </zui-table-cell>
490
494
  </zui-table-row>
491
495
  </zui-table>
492
496
 
@@ -696,9 +700,7 @@
696
700
  </zui-table-cell>
697
701
  </zui-table-row>
698
702
  <zui-table-row summary>
699
- <zui-table-cell style="text-align: right;">
700
- Average lifespan: 742 years
701
- </zui-table-cell>
703
+ <zui-table-cell style="text-align: right"> Average lifespan: 742 years </zui-table-cell>
702
704
  </zui-table-row>
703
705
  </zui-table>
704
706
 
@@ -793,7 +795,7 @@
793
795
  </zui-button-dropdown>
794
796
  <zui-button type="secondary"><a href="#">Whisper</a></zui-button>
795
797
  <zui-button id="export" type="secondary">Betray all</zui-button>
796
- </zui-button-group>
798
+ </zui-button-group>
797
799
  </zui-table-topbar>
798
800
  <zui-table-row header>
799
801
  <zui-table-cell>Name</zui-table-cell>
@@ -1133,6 +1135,93 @@
1133
1135
  </zui-table-footer>
1134
1136
  </zui-table>
1135
1137
 
1138
+ <h2>Scrollable table</h2>
1139
+
1140
+ <zui-table mode="fixed-sizing" class="scroll" banded>
1141
+ <zui-table-topbar>
1142
+ <zui-search placeholder="Search for a family member" no-submit></zui-search>
1143
+ <div slot="counter">5 family members</div>
1144
+ <zui-button slot="action" type="secondary">Whisper</zui-button>
1145
+ <zui-button slot="action">Add a family member</zui-button>
1146
+ </zui-table-topbar>
1147
+ <zui-table-row header>
1148
+ <zui-table-cell>Name</zui-table-cell>
1149
+ <zui-table-cell>Title</zui-table-cell>
1150
+ <zui-table-cell>Title 2</zui-table-cell>
1151
+ <zui-table-cell>Title 3</zui-table-cell>
1152
+ <zui-table-cell>Born</zui-table-cell>
1153
+ <zui-table-cell>Died</zui-table-cell>
1154
+ <zui-table-cell>Age</zui-table-cell>
1155
+ <zui-table-cell>Action</zui-table-cell>
1156
+ </zui-table-row>
1157
+ <zui-table-row>
1158
+ <zui-table-cell>Paulus Atreides</zui-table-cell>
1159
+ <zui-table-cell>Old Duke</zui-table-cell>
1160
+ <zui-table-cell>Title 2</zui-table-cell>
1161
+ <zui-table-cell>Title 3</zui-table-cell>
1162
+ <zui-table-cell>10,089 A.G.</zui-table-cell>
1163
+ <zui-table-cell>10,156 A.G.</zui-table-cell>
1164
+ <zui-table-cell>67 years old</zui-table-cell>
1165
+ <zui-table-cell action>
1166
+ <zui-button type="secondary">Betray</zui-button>
1167
+ </zui-table-cell>
1168
+ </zui-table-row>
1169
+ <zui-table-row>
1170
+ <zui-table-cell>Leto Atreides I</zui-table-cell>
1171
+ <zui-table-cell>Red Duke</zui-table-cell>
1172
+ <zui-table-cell>Title 2</zui-table-cell>
1173
+ <zui-table-cell>Title 3</zui-table-cell>
1174
+ <zui-table-cell>10,140 A.G.</zui-table-cell>
1175
+ <zui-table-cell>10,191 A.G.</zui-table-cell>
1176
+ <zui-table-cell>51 years old</zui-table-cell>
1177
+ <zui-table-cell action>
1178
+ <zui-button type="secondary">Betray</zui-button>
1179
+ </zui-table-cell>
1180
+ </zui-table-row>
1181
+ <zui-table-row>
1182
+ <zui-table-cell>Paul Atreides</zui-table-cell>
1183
+ <zui-table-cell>Padishah Emperor</zui-table-cell>
1184
+ <zui-table-cell>Title 2</zui-table-cell>
1185
+ <zui-table-cell>Title 3</zui-table-cell>
1186
+ <zui-table-cell>10,176 A.G.</zui-table-cell>
1187
+ <zui-table-cell>10,219 A.G.</zui-table-cell>
1188
+ <zui-table-cell>43 years old</zui-table-cell>
1189
+ <zui-table-cell action>
1190
+ <zui-button type="secondary">Betray</zui-button>
1191
+ </zui-table-cell>
1192
+ </zui-table-row>
1193
+ <zui-table-row>
1194
+ <zui-table-cell>Alia Atreides</zui-table-cell>
1195
+ <zui-table-cell>Imperial Regent</zui-table-cell>
1196
+ <zui-table-cell>Title 2</zui-table-cell>
1197
+ <zui-table-cell>Title 3</zui-table-cell>
1198
+ <zui-table-cell>10,191 A.G.</zui-table-cell>
1199
+ <zui-table-cell>10,219 A.G.</zui-table-cell>
1200
+ <zui-table-cell>28 years old</zui-table-cell>
1201
+ <zui-table-cell action>
1202
+ <zui-button type="secondary">Betray</zui-button>
1203
+ </zui-table-cell>
1204
+ </zui-table-row>
1205
+ <zui-table-row>
1206
+ <zui-table-cell>Leto Atreides II</zui-table-cell>
1207
+ <zui-table-cell>God Emperor</zui-table-cell>
1208
+ <zui-table-cell>Title 2</zui-table-cell>
1209
+ <zui-table-cell>Title 3</zui-table-cell>
1210
+ <zui-table-cell>10,207 A.G.</zui-table-cell>
1211
+ <zui-table-cell>13,728 A.G.</zui-table-cell>
1212
+ <zui-table-cell>3,521 years old</zui-table-cell>
1213
+ <zui-table-cell action>
1214
+ <zui-button type="secondary">Betray</zui-button>
1215
+ </zui-table-cell>
1216
+ </zui-table-row>
1217
+ <zui-table-row summary>
1218
+ <zui-table-cell style="text-align: right"> Average lifespan: 742 years </zui-table-cell>
1219
+ </zui-table-row>
1220
+ <zui-table-footer>
1221
+ <zui-pager current-page="1" total-pages="10"></zui-pager>
1222
+ </zui-table-footer>
1223
+ </zui-table>
1224
+
1136
1225
  <script>
1137
1226
  const sortableHeaders = document.querySelectorAll("zui-table-row[header] zui-table-cell[sortable]");
1138
1227
  const displaySortDirection = document.querySelector("#table-sorting-value");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zywave/zui-table",
3
- "version": "4.3.4-pre.0",
3
+ "version": "4.4.0-pre.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "license": "UNLICENSED",
@@ -22,12 +22,12 @@
22
22
  },
23
23
  "customElements": "dist/custom-elements.json",
24
24
  "dependencies": {
25
- "@zywave/zui-base": "^4.5.1-pre.0",
26
- "@zywave/zui-icons": "^4.5.3-pre.0",
27
- "@zywave/zui-spinner": "^4.0.41-pre.0"
25
+ "@zywave/zui-base": "^4.5.1-pre.1",
26
+ "@zywave/zui-icons": "^4.5.3-pre.1",
27
+ "@zywave/zui-spinner": "^4.0.41-pre.1"
28
28
  },
29
29
  "devDependencies": {
30
- "@zywave/zui-button": "^4.1.9-pre.0"
30
+ "@zywave/zui-button": "^4.1.9-pre.1"
31
31
  },
32
- "gitHead": "45e147d72811feff70cd64024a3af21811011e31"
32
+ "gitHead": "0ebe68dcc84df724d715319cc07edda440eae751"
33
33
  }
@@ -1,3 +1,3 @@
1
1
  import { css } from 'lit';
2
2
 
3
- export const style = css`:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;
3
+ export const style = css`:host{contain:none;display:block}:host .no-results{display:none}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{display:block;padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:rgba(0,0,0,0);box-shadow:none}}:host([loading]) ::slotted(zui-table-row:not([header])),:host([loading]) .no-results{visibility:hidden}:host([loading]) zui-spinner{position:absolute;top:50%;left:50%}:host([loading]) .table{min-height:var(--zui-table-loading-min-height, 20rem)}@media(width > 45em){:host([mode=fixed-sizing]){max-width:var(--zui-table-max-width, none)}:host([mode=fixed-sizing]) .body{max-height:var(--zui-table-max-height, none);overflow:auto}:host([mode=fixed-sizing]) ::slotted(zui-table-row[header]){position:sticky;top:0;left:0;width:fit-content;z-index:1}}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{position:relative;display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;
@@ -1,3 +1,3 @@
1
1
  import { css } from 'lit';
2
2
 
3
- export const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;
3
+ export const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:rgba(0,0,0,0);box-shadow:none}}:host([summary]){--zui-table-columns-template: 1fr;background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:rgba(0,0,0,0)}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;
@@ -49,6 +49,7 @@ div {
49
49
  }
50
50
 
51
51
  :host([summary]) {
52
+ --zui-table-columns-template: 1fr;
52
53
  background-color: var(--zui-table-summary-background-color, var(--zui-gray-600)) !important;
53
54
 
54
55
  div {
@@ -37,21 +37,13 @@ export class ZuiTableTopbarElement extends ZuiTableBaseElement {
37
37
  connectedCallback() {
38
38
  super.connectedCallback();
39
39
 
40
- if (this.#mobileBreakpoint.addEventListener) {
41
- this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);
42
- } else {
43
- this.#mobileBreakpoint.addListener(this.#mobileTopbarActionButtonsEvent);
44
- }
40
+ this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);
45
41
  }
46
42
 
47
43
  disconnectedCallback() {
48
44
  super.disconnectedCallback();
49
45
 
50
- if (this.#mobileBreakpoint.addEventListener) {
51
- this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);
52
- } else if (this.#mobileBreakpoint.addListener) {
53
- this.#mobileBreakpoint.removeListener(this.#mobileTopbarActionButtonsEvent);
54
- }
46
+ this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);
55
47
  }
56
48
 
57
49
  firstUpdated() {
@@ -51,6 +51,25 @@
51
51
  }
52
52
  }
53
53
 
54
+ @media (width > $bp-xs) {
55
+ :host([mode='fixed-sizing']) {
56
+ max-width: var(--zui-table-max-width, none);
57
+
58
+ .body {
59
+ max-height: var(--zui-table-max-height, none);
60
+ overflow: auto;
61
+ }
62
+
63
+ ::slotted(zui-table-row[header]) {
64
+ position: sticky;
65
+ top: 0;
66
+ left: 0;
67
+ width: fit-content;
68
+ z-index: 1;
69
+ }
70
+ }
71
+ }
72
+
54
73
  ::slotted(zui-table-row:not([header])) {
55
74
  border-bottom: 2px solid var(--zui-gray-100);
56
75
 
package/src/zui-table.ts CHANGED
@@ -6,8 +6,10 @@ import { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';
6
6
  import '@zywave/zui-spinner';
7
7
  import { updateCustomState } from '@zywave/zui-base/dist/utils/update-custom-state.js';
8
8
  import type { ZuiTableRowElement } from './zui-table-row.js';
9
- import type { ZuiTableFooterElement } from './zui-table-footer.js';
10
9
  import type { ZuiTableCellElement, ZuiTableSortDirection } from './zui-table-cell.js';
10
+ import type { PropertyValues } from 'lit';
11
+
12
+ type ZuiTableMode = 'default' | 'fixed-sizing';
11
13
 
12
14
  /**
13
15
  * A standardized responsive table component.
@@ -36,6 +38,14 @@ export class ZuiTableElement extends ZuiTableBaseElement {
36
38
  @property({ type: Boolean, reflect: true })
37
39
  banded = false;
38
40
 
41
+ /**
42
+ * Ability to modify the table's layout behavior. The supported values are:
43
+ * - `default` (default): Table width is determined by its content. Columns will expand to fit the content within them.
44
+ * - `fixed-sizing`: Opts-in to constrainig dimensions by the `--zui-table-max-width` and `--zui-table-max-height` CSS properties. This unlocks the ability to make a table vertically and horizontally scrollable within a container. The following CSS properties are required: `--zui-table-columns-template`. You should set at least one of the following: `--zui-table-max-width`, `--zui-table-max-height`.
45
+ */
46
+ @property({ reflect: true })
47
+ mode: ZuiTableMode = 'default';
48
+
39
49
  // TODO: add divided prop so all table cells will have 1px border
40
50
 
41
51
  /**
@@ -53,9 +63,6 @@ export class ZuiTableElement extends ZuiTableBaseElement {
53
63
  @queryAssignedElements({ selector: 'zui-table-row' })
54
64
  private _rows: Array<ZuiTableRowElement>;
55
65
 
56
- @queryAssignedElements({ selector: 'zui-table-footer' })
57
- private _footer: Array<ZuiTableFooterElement>;
58
-
59
66
  #internals?: ElementInternals;
60
67
  #mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);
61
68
  #sortLock = false;
@@ -93,60 +100,61 @@ export class ZuiTableElement extends ZuiTableBaseElement {
93
100
  super.connectedCallback();
94
101
  this.setAttribute('role', 'table');
95
102
 
96
- if (this.#mobileBreakpoint.addEventListener) {
97
- this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);
98
- } else {
99
- this.#mobileBreakpoint.addListener(this.#mobileHeadersEvent);
100
- }
103
+ this.#mobileBreakpoint.addEventListener('change', this.#mobileHeadersEvent);
101
104
  }
102
105
 
103
106
  disconnectedCallback() {
104
107
  super.disconnectedCallback();
105
108
 
106
- if (this.#mobileBreakpoint.addEventListener) {
107
- this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);
108
- } else if (this.#mobileBreakpoint.addListener) {
109
- this.#mobileBreakpoint.removeListener(this.#mobileHeadersEvent);
110
- }
109
+ this.#mobileBreakpoint.removeEventListener('change', this.#mobileHeadersEvent);
111
110
  }
112
111
 
113
- firstUpdated() {
114
- this.#reassignFooter();
112
+ updated(changedProperties: PropertyValues<this>) {
113
+ super.updated(changedProperties);
114
+
115
+ const footer = this.querySelector('zui-table-footer:not([slot])');
116
+ const header = this.querySelector('zui-table-row[header]:not([slot])');
117
+ const topbar = this.querySelector('zui-table-topbar:not([slot])');
118
+ const summary = this.querySelector('zui-table-row[summary]:not([slot])');
119
+ footer?.setAttribute('slot', 'footer');
120
+ header?.setAttribute('slot', 'header');
121
+ topbar?.setAttribute('slot', 'topbar');
122
+ summary?.setAttribute('slot', 'summary');
115
123
 
116
124
  this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();
117
125
  }
118
126
 
119
127
  render() {
120
128
  return html`<div class="table">
121
- <slot
122
- @slotchange="${this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells : this.#removeRowHeadersFromCells}"
123
- ></slot>
124
- ${this.loading ? html`<zui-spinner active="" part="loader"></zui-spinner>` : html``}
125
- ${this.#renderNoResultsView()}</div
126
- >
129
+ <slot name="topbar"></slot>
130
+ <div class="body" role="rowgroup">
131
+ <slot name="header" @slotchange="${this.#onSlotChange}"></slot>
132
+ <slot @slotchange="${this.#onSlotChange}"></slot>
133
+ ${this.loading ? html`<zui-spinner active="" part="loader"></zui-spinner>` : html``}
134
+ <div class="no-results"><slot name="no-results-message"></slot></div>
135
+ </div>
136
+ <slot name="summary"></slot>
137
+ </div>
127
138
  <div><slot name="footer"></slot></div>`;
128
139
  }
129
140
 
130
- #renderNoResultsView() {
131
- return html`<div class="no-results"><slot name="no-results-message"></slot></div>`;
132
- }
133
-
134
- #reassignFooter() {
135
- this._footer?.map((f) => f.setAttribute('slot', 'footer'));
141
+ #onSlotChange() {
142
+ this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();
143
+ this.requestUpdate();
136
144
  }
137
145
 
138
146
  #addRowHeadersToCells() {
139
- const rowHeadersList = this._rows.filter((h) => h.hasAttribute('header'));
140
- const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));
147
+ const headerRow = this.querySelector('zui-table-row[header]');
141
148
 
142
- if (rowHeadersList.length > 0) {
149
+ if (headerRow) {
150
+ const rowBodyList = this._rows.filter((r) => !r.hasAttribute('header') && !r.hasAttribute('summary'));
143
151
  for (const row of rowBodyList) {
144
152
  for (let i = 0; i < row.children.length; i++) {
145
153
  const cell = row.children[i];
146
154
  if (!cell.shadowRoot.querySelector('.header')) {
147
155
  const rowHeaderContainer = document.createElement('div');
148
156
  rowHeaderContainer.classList.add('header');
149
- const rowHeaderText = rowHeadersList[0].children[i].textContent;
157
+ const rowHeaderText = headerRow.children[i].textContent;
150
158
  rowHeaderContainer.innerText = rowHeaderText;
151
159
  cell.shadowRoot.prepend(rowHeaderContainer);
152
160
  }
@@ -155,8 +163,6 @@ export class ZuiTableElement extends ZuiTableBaseElement {
155
163
  }
156
164
 
157
165
  updateCustomState(this.#internals, 'add', 'mobile');
158
-
159
- this.requestUpdate();
160
166
  }
161
167
 
162
168
  #removeRowHeadersFromCells() {
@@ -174,8 +180,6 @@ export class ZuiTableElement extends ZuiTableBaseElement {
174
180
 
175
181
  // remove custom state --mobile from zui-table
176
182
  updateCustomState(this.#internals, 'delete', 'mobile');
177
-
178
- this.requestUpdate();
179
183
  }
180
184
  }
181
185
 
@@ -138,54 +138,66 @@ suite('zui-table', () => {
138
138
  assert.equal(actionComputedDisplayStyle, 'none', 'Expected counter div to be hidden on mobile if empty');
139
139
  });
140
140
 
141
- test('mobile table with headers in cell', async () => {
142
- const rowHeader = document.createElement('zui-table-row');
143
- const rowHeaderCell = document.createElement('zui-table-cell');
144
- rowHeader.setAttribute('header', '');
145
- rowHeaderCell.innerText = 'Dank';
146
- rowHeader.appendChild(rowHeaderCell);
147
- topbar.insertAdjacentElement('afterend', rowHeader);
148
- cell.innerText = 'Farrik!';
141
+ suite('mobile', () => {
142
+ let initialWidth, initialHeight: number;
143
+ setup(async () => {
144
+ initialHeight = window.innerHeight;
145
+ initialWidth = window.innerWidth;
146
+ await setViewport({ width: 400, height: 640 });
147
+
148
+ await table.updateComplete;
149
+ await sleep(100);
150
+ });
149
151
 
150
- // Order matters here
151
- // TODO: Investigate why setting viewport prior to table update completion fails
152
- await table.updateComplete;
153
- await sleep(100);
154
- await setViewport({ width: 479, height: 640 });
155
-
156
- const rowHeaderComputedDisplayStyle = window.getComputedStyle(rowHeader).getPropertyValue('display');
157
- const rowHeaderText = rowHeaderCell.textContent;
158
- const bodyCellHeaderText = cell.shadowRoot.children[0].textContent;
159
-
160
- assert.isTrue(isMobile(), `Expected viewport to be <${screenBreakpoints.xsmall}`);
161
- assert.equal(rowHeaderComputedDisplayStyle, 'none', 'Expected table row header to be hidden on mobile');
162
- assert.exists(
163
- cell.shadowRoot.querySelector('.header'),
164
- 'Expected cell to have an element with class .header in its shadow DOM'
165
- );
166
- assert.equal(
167
- rowHeaderText,
168
- bodyCellHeaderText,
169
- `Expected table body cell text (${bodyCellHeaderText}) to have header text (${rowHeaderText}) in it`
170
- );
171
- });
152
+ teardown(async () => {
153
+ await setViewport({ width: initialWidth, height: initialHeight });
154
+ });
155
+
156
+ test('sets mobile state on small viewports', async () => {
157
+ assert.isTrue(table.matches(':state(mobile)'), 'Expected zui-table to match :state(mobile)');
158
+ });
172
159
 
173
- test('ZuiButtons in the ZuiTableTopbar action slot switches to block style on mobile', async () => {
174
- const actionButton = document.createElement('zui-button');
175
- actionButton.innerText = 'Add a new entry';
176
- actionButton.setAttribute('slot', 'action');
177
- topbar.appendChild(actionButton);
160
+ test('mobile table with headers in cell', async () => {
161
+ const rowHeader = document.createElement('zui-table-row');
162
+ const rowHeaderCell = document.createElement('zui-table-cell');
163
+ rowHeader.setAttribute('header', '');
164
+ rowHeaderCell.innerText = 'Dank';
165
+ rowHeader.appendChild(rowHeaderCell);
166
+ topbar.insertAdjacentElement('afterend', rowHeader);
167
+ cell.innerText = 'Farrik!';
178
168
 
179
- // Order matters here
180
- // TODO: Investigate why setting viewport prior to table update completion fails
181
- await table.updateComplete;
182
- await sleep(100);
183
- await setViewport({ width: 479, height: 640 });
169
+ await cell.updateComplete;
170
+ await sleep(100);
171
+
172
+ const rowHeaderComputedDisplayStyle = window.getComputedStyle(rowHeader).getPropertyValue('display');
173
+ const rowHeaderText = rowHeaderCell.textContent;
174
+ const bodyCellHeaderText = cell.shadowRoot.children[0].textContent;
175
+
176
+ assert.isTrue(isMobile(), `Expected viewport to be <${screenBreakpoints.xsmall}`);
177
+ assert.equal(rowHeaderComputedDisplayStyle, 'none', 'Expected table row header to be hidden on mobile');
178
+ assert.exists(
179
+ cell.shadowRoot.querySelector('.header'),
180
+ 'Expected cell to have an element with class .header in its shadow DOM'
181
+ );
182
+ assert.equal(
183
+ rowHeaderText,
184
+ bodyCellHeaderText,
185
+ `Expected table body cell text (${bodyCellHeaderText}) to have header text (${rowHeaderText}) in it`
186
+ );
187
+ });
184
188
 
185
- const actionButtonStyle = actionButton.hasAttribute('block');
189
+ test('ZuiButtons in the ZuiTableTopbar action slot switches to block style on mobile', async () => {
190
+ const actionButton = document.createElement('zui-button');
191
+ actionButton.innerText = 'Add a new entry';
192
+ actionButton.setAttribute('slot', 'action');
193
+ topbar.appendChild(actionButton);
186
194
 
187
- assert.isTrue(isMobile(), `Expected viewport to be <${screenBreakpoints.xsmall}`);
188
- assert.isTrue(actionButtonStyle);
195
+ await table.updateComplete;
196
+ await sleep(100);
197
+
198
+ assert.isTrue(isMobile(), `Expected viewport to be <${screenBreakpoints.xsmall}`);
199
+ assert.isTrue(actionButton.hasAttribute('block'));
200
+ });
189
201
  });
190
202
 
191
203
  suite('sort', () => {