@spectric/ui 0.0.12 → 0.0.14

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/style.css CHANGED
@@ -1 +1 @@
1
- spectric-input{--input-color: var(--spectric-input-color, #f4f4f4);--border-radius: var(--spectric-border-radius, .4em);--input-bottom: var(--spectric-input-bottom, var(--spectric-button-primary, #a8a8a8));--input-bottom-focused: var(--primary, #1ea7fd);--text-on-color: var(--spectric-text-on-color, #ffffff);--text-on-color-disabled: var(--spectric-text-on-color-disabled, #8d8d8d);--text-placeholder: rgba(22, 22, 22, .4);--text-primary: var(--spectric-text-primary, #161616);--text-secondary: var(--spectric-text-secondary, #525252)}spectric-input .inputWrapper{color:var(--text-secondary)}spectric-input .inputWrapper input{box-sizing:border-box;margin:0;vertical-align:baseline;font-size:.875rem;font-weight:400;line-height:1.28572;letter-spacing:.16px;outline:transparent solid 2px;outline-offset:-2px;border:none;padding:0 1rem;background-color:var(--input-color);color:var(--text-primary, #161616);font-family:inherit;inline-size:100%;block-size:2.5rem}spectric-input .inputWrapper .inputContainer:active:after,spectric-input .inputContainer:focus-within:after{border-bottom-color:var(--input-bottom-focused);width:calc(100% - 5px);transition:width .4s ease-in-out}spectric-input .inputWrapper input:read-only{background-color:transparent;border-bottom-color:var(--border-disabled)}spectric-input .inputContainer{position:relative;border-radius:var(--border-radius);overflow:hidden}spectric-input .inputContainer:after{content:"";width:0px;transition:background-color .4s cubic-bezier(.2,0,.38,.9),border-bottom-color .4s cubic-bezier(.2,0,.38,.9);border-bottom-color:var(--input-bottom);border-bottom-style:solid;border-bottom-width:1px;position:absolute;left:2.5px;bottom:0}spectric-input #helper-text{height:18px}spectric-input[variant=password] spectric-button{position:absolute;right:4px;bottom:3px}spectric-input .checkbox{display:flex;justify-self:center}spectric-query{font-family:monospace}spectric-query .autocomplete{color:var(--spectric-text-primary, #161616);border-radius:0em 0em var(--spectric-border-radius, .4em) var(--spectric-border-radius, .4em);background-color:var(--spectric-background, #ffffff);border:1px solid var(--spectric-background-hover, rgba(141, 141, 141, .12));max-height:300px;border-top:0px;margin:-18px 0 0;position:fixed;top:anchor(bottom);justify-self:anchor-center;text-align:center}spectric-query .autocomplete .optiontype{float:left;max-width:10px}spectric-query .autocomplete .label{position:absolute;right:0}spectric-query .autocomplete .option.active,spectric-query .autocomplete .option:hover{background-color:var(--spectric-background-hover, rgba(141, 141, 141, .12));border-bottom:1px solid var(--primary, #1ea7fd)}spectric-query .autocomplete .option{border-bottom:1px solid transparent;padding:8px}.query-bar-date-quick-select{display:flex;justify-content:space-evenly}spectric-pagination .spectric-pagination-container{display:flex;justify-content:space-between;align-items:center}spectric-pagination .spectric-pagination-text{flex-grow:1;text-align:center}spectric-table{display:flex;flex-direction:column;overflow:hidden}spectric-table .table-wrapper{overflow:auto;flex-grow:1;position:relative}spectric-table tr{text-align:center}spectric-table tr.odd{background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 90%)}spectric-table tr:hover{background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 70%)}spectric-table-header{display:table-header-group;font-weight:700;position:sticky;top:0;left:0;z-index:1;background:var(--spectric-background, #ffffff)}spectric-table-header td{vertical-align:middle}spectric-table tr{line-height:var(--rowHeight)}spectric-table td{height:var(--rowHeight)}spectric-table-header .header-contents{position:relative}spectric-table-header .header-contents .sort-direction{position:absolute;right:0}spectric-table-header .header-contents.sortable{cursor:pointer}spectric-table-header .header-contents.sortable:hover .sort-direction.none:before{content:"⮁"}spectric-table div[role=table]{display:table;min-width:100%}spectric-table-cell{display:contents;vertical-align:middle}spectric-table-cell td{position:relative}spectric-table td:hover:has(.filterable){border:1px solid var(--spectric-primary, #1ea7fd)}spectric-table td{border:1px solid transparent}spectric-table-cell .table-cell-actions{position:absolute;display:flex;width:100%;flex-direction:row-reverse;visibility:hidden;top:-10px}spectric-table-cell td:hover .table-cell-actions{visibility:unset}spectric-table .table-checkbox-single spectric-button{--button-border-radius: 50%}spectric-input.table-checkbox-single[checked] spectric-button{--text-on-color: transparent;border-radius:50%;position:relative}spectric-input.table-checkbox-single[checked] spectric-button:before{position:absolute;content:" ";height:50%;width:50%;left:25%;top:25%;border-radius:50%;z-index:1;box-shadow:0 0 0 4px var(--input-color)}spectric-table-body{display:table-row-group}spectric-table-virtual-body{display:contents}spectric-table-virtual-body .virtual-scroll-spacer td{padding:0;border:0px}.spectric-tooltip-portal{position:fixed;z-index:9999;pointer-events:none;--spectric-tooltip-background: color-mix(in srgb,var(--spectric-background-inverse,#f4f4f4) 100%,var(--spectric-primary,#1ea7fd) 90%) }.spectric-tooltip-portal .tooltip-container{display:flex;justify-content:center;align-items:center}.spectric-tooltip-portal.top .tooltip-container{flex-direction:column-reverse}.spectric-tooltip-portal.bottom .tooltip-container{flex-direction:column}.spectric-tooltip-portal.left .tooltip-container{flex-direction:row-reverse}.spectric-tooltip-portal .tooltip-content{background:var(--spectric-tooltip-background);border-radius:var(--spectric-border-radius,.4em);box-shadow:0 0 .01em .01em color-mix(in srgb,var(--spectric-background-hover,rgba(141, 141, 141, .12)) 90%,var(--spectric-text-on-color,#ffffff) 90%);padding:.2em;color:var(--spectric-text-on-color,#ffffff)}.spectric-tooltip-portal .tooltip-caret{background:var(--spectric-tooltip-background)}.spectric-tooltip-portal.top .tooltip-caret,.spectric-tooltip-portal.bottom .tooltip-caret{inline-size:.75rem;block-size:.374rem}.spectric-tooltip-portal.left .tooltip-caret,.spectric-tooltip-portal.right .tooltip-caret{inline-size:.375rem;block-size:.75rem}.spectric-tooltip-portal.top .tooltip-caret{clip-path:polygon(0 0,50% 100%,100% 0)}.spectric-tooltip-portal.bottom .tooltip-caret{clip-path:polygon(0 100%,50% 0,100% 100%)}.spectric-tooltip-portal.left .tooltip-caret{clip-path:polygon(0 0,100% 50%,0 100%)}.spectric-tooltip-portal.right .tooltip-caret{clip-path:polygon(0 50%,100% 0,100% 100%)}
1
+ spectric-input{--input-color: var(--spectric-input-color, #f4f4f4);--border-radius: var(--spectric-border-radius, .4em);--input-bottom: var(--spectric-input-bottom, var(--spectric-button-primary, #a8a8a8));--input-bottom-focused: var(--primary, #1ea7fd);--text-on-color: var(--spectric-text-on-color, #ffffff);--text-on-color-disabled: var(--spectric-text-on-color-disabled, #8d8d8d);--text-placeholder: rgba(22, 22, 22, .4);--text-primary: var(--spectric-text-primary, #161616);--text-secondary: var(--spectric-text-secondary, #525252)}spectric-input .inputWrapper{color:var(--text-secondary)}spectric-input .inputWrapper input{box-sizing:border-box;margin:0;vertical-align:baseline;font-size:.875rem;font-weight:400;line-height:1.28572;letter-spacing:.16px;outline:transparent solid 2px;outline-offset:-2px;border:none;padding:0 1rem;background-color:var(--input-color);color:var(--text-primary, #161616);font-family:inherit;inline-size:100%;block-size:2.5rem}spectric-input .inputWrapper .inputContainer:active:after,spectric-input .inputContainer:focus-within:after{border-bottom-color:var(--input-bottom-focused);width:calc(100% - 5px);transition:width .4s ease-in-out}spectric-input .inputWrapper input:read-only{background-color:transparent;border-bottom-color:var(--border-disabled)}spectric-input .inputContainer{position:relative;border-radius:var(--border-radius);overflow:hidden}spectric-input .inputContainer:after{content:"";width:0px;transition:background-color .4s cubic-bezier(.2,0,.38,.9),border-bottom-color .4s cubic-bezier(.2,0,.38,.9);border-bottom-color:var(--input-bottom);border-bottom-style:solid;border-bottom-width:1px;position:absolute;left:2.5px;bottom:0}spectric-input #helper-text{height:18px}spectric-input[variant=password] spectric-button{position:absolute;right:4px;bottom:3px}spectric-input .checkbox{display:flex;justify-self:center}spectric-query{font-family:monospace}spectric-query .autocomplete{color:var(--spectric-text-primary, #161616);border-radius:0em 0em var(--spectric-border-radius, .4em) var(--spectric-border-radius, .4em);background-color:var(--spectric-background, #ffffff);border:1px solid var(--spectric-background-hover, rgba(141, 141, 141, .12));max-height:300px;border-top:0px;margin:-18px 0 0;position:fixed;top:anchor(bottom);justify-self:anchor-center;text-align:center}spectric-query .autocomplete .optiontype{float:left;max-width:10px}spectric-query .autocomplete .label{position:absolute;right:0}spectric-query .autocomplete .option.active,spectric-query .autocomplete .option:hover{background-color:var(--spectric-background-hover, rgba(141, 141, 141, .12));border-bottom:1px solid var(--primary, #1ea7fd)}spectric-query .autocomplete .option{border-bottom:1px solid transparent;padding:8px}.query-bar-date-quick-select{display:flex;justify-content:space-evenly}spectric-pagination .spectric-pagination-container{display:flex;justify-content:space-between;align-items:center}spectric-pagination .spectric-pagination-text{flex-grow:1;text-align:center}spectric-table{display:flex;flex-direction:column;overflow:hidden}spectric-table .table-wrapper{overflow:auto;flex-grow:1;position:relative}spectric-table tr{text-align:center}spectric-table tr.odd{background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 90%)}spectric-table tr:hover{background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 70%)}spectric-table-header{display:table-header-group;font-weight:700;position:sticky;top:0;left:0;z-index:1;background:var(--spectric-background, #ffffff)}spectric-table-header td{vertical-align:middle}spectric-table tr{line-height:var(--rowHeight)}spectric-table td{height:var(--rowHeight)}spectric-table-header .header-contents{position:relative}spectric-table-header .header-contents .sort-direction{position:absolute;right:0;top:calc(50% - 8px)}spectric-table-header .header-contents.sortable{cursor:pointer;padding-right:15px}spectric-table-header .header-contents.sortable:hover .sort-direction.none:before{content:"⮁"}spectric-table div[role=table]{display:table;min-width:100%}spectric-table-cell{display:contents;vertical-align:middle}spectric-table-cell td{position:relative}spectric-table td:hover:has(.filterable){border:1px solid var(--spectric-primary, #1ea7fd)}spectric-table td{border:1px solid transparent}spectric-table-cell .table-cell-actions{position:absolute;display:flex;width:100%;flex-direction:row-reverse;visibility:hidden;top:-10px}spectric-table-cell td:hover .table-cell-actions{visibility:unset}spectric-table .table-checkbox-single spectric-button{--button-border-radius: 50%}spectric-input.table-checkbox-single[checked] spectric-button{--text-on-color: transparent;border-radius:50%;position:relative}spectric-input.table-checkbox-single[checked] spectric-button:before{position:absolute;content:" ";height:50%;width:50%;left:25%;top:25%;border-radius:50%;z-index:1;box-shadow:0 0 0 4px var(--input-color)}spectric-table-body{display:table-row-group}spectric-table-virtual-body{display:contents}spectric-table-virtual-body .virtual-scroll-spacer td{padding:0;border:0px}.spectric-tooltip-portal{position:fixed;z-index:9999;pointer-events:none;--spectric-tooltip-background: color-mix(in srgb,var(--spectric-background-inverse,#f4f4f4) 100%,var(--spectric-primary,#1ea7fd) 90%) }.spectric-tooltip-portal .tooltip-container{display:flex;justify-content:center;align-items:center}.spectric-tooltip-portal.top .tooltip-container{flex-direction:column-reverse}.spectric-tooltip-portal.bottom .tooltip-container{flex-direction:column}.spectric-tooltip-portal.left .tooltip-container{flex-direction:row-reverse}.spectric-tooltip-portal .tooltip-content{background:var(--spectric-tooltip-background);border-radius:var(--spectric-border-radius,.4em);box-shadow:0 0 .01em .01em color-mix(in srgb,var(--spectric-background-hover,rgba(141, 141, 141, .12)) 90%,var(--spectric-text-on-color,#ffffff) 90%);padding:.2em;color:var(--spectric-text-on-color,#ffffff)}.spectric-tooltip-portal .tooltip-caret{background:var(--spectric-tooltip-background)}.spectric-tooltip-portal.top .tooltip-caret,.spectric-tooltip-portal.bottom .tooltip-caret{inline-size:.75rem;block-size:.374rem}.spectric-tooltip-portal.left .tooltip-caret,.spectric-tooltip-portal.right .tooltip-caret{inline-size:.375rem;block-size:.75rem}.spectric-tooltip-portal.top .tooltip-caret{clip-path:polygon(0 0,50% 100%,100% 0)}.spectric-tooltip-portal.bottom .tooltip-caret{clip-path:polygon(0 100%,50% 0,100% 100%)}.spectric-tooltip-portal.left .tooltip-caret{clip-path:polygon(0 0,100% 50%,0 100%)}.spectric-tooltip-portal.right .tooltip-caret{clip-path:polygon(0 50%,100% 0,100% 100%)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectric/ui",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
5
  "main": "./dist/index.es.js",
6
6
  "module": "./dist/index.es.js",
@@ -56,7 +56,7 @@ class DomListener implements IDisposable {
56
56
  export class DisposableElement extends LitElement {
57
57
  private readonly _disposables = new Set<IDisposable>();
58
58
  private _isDisposed = false;
59
- private _disposableListeners: { target: DisposableTarget, event: string, handler: any }[] = []
59
+ private _disposableListeners: { target: DisposableTarget, event: string, handler: any, options?: AddEventListenerOptions }[] = []
60
60
  private _connected: boolean = false;
61
61
  /**
62
62
  * Creates listeners on a target that will automatically get cleaned up when the element is removed from the DOM. This prevents memory leaks.
@@ -64,17 +64,17 @@ export class DisposableElement extends LitElement {
64
64
  * @param event The event name
65
65
  * @param handler The event handler
66
66
  */
67
- public addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(target: DisposableTarget, event: K, handler: (event: GlobalEventHandlersEventMap[K]) => void): void
68
- public addDisposableListener<K extends keyof SpectricGlobalEvents>(target: DisposableTarget, event: K, handler: SpectricGlobalEvents[K]): void
69
- public addDisposableListener(target: DisposableTarget, event: string, handler: any): void {
67
+ public addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(target: DisposableTarget, event: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, options?: AddEventListenerOptions): void
68
+ public addDisposableListener<K extends keyof SpectricGlobalEvents>(target: DisposableTarget, event: K, handler: SpectricGlobalEvents[K], options?: AddEventListenerOptions): void
69
+ public addDisposableListener(target: DisposableTarget, event: string, handler: any, options?: AddEventListenerOptions): void {
70
70
  let exists = this._disposableListeners.find(d => d.event === event && d.target === target && d.handler === handler)
71
71
  if (exists) {
72
72
  console.warn("Event handler already exists best practice is to add the this in the constructor")
73
73
  return //Event handler has already been added, maybe they added it in a callback
74
74
  }
75
- this._disposableListeners.push({ target, event, handler })
75
+ this._disposableListeners.push({ target, event, handler, options })
76
76
  if (this._connected) {
77
- this.registerDisposable(new DomListener(target, event, handler))
77
+ this.registerDisposable(new DomListener(target, event, handler, options))
78
78
  }
79
79
  }
80
80
  public registerDisposable<T extends IDisposable>(o: T): T {
@@ -97,8 +97,8 @@ export class DisposableElement extends LitElement {
97
97
  super.connectedCallback();
98
98
  this._connected = true
99
99
  this._isDisposed = false
100
- this._disposableListeners.forEach(({ target, event, handler }) => {
101
- this.registerDisposable(new DomListener(target, event, handler))
100
+ this._disposableListeners.forEach(({ target, event, handler, options }) => {
101
+ this.registerDisposable(new DomListener(target, event, handler, options))
102
102
  })
103
103
  }
104
104
 
@@ -1,4 +1,4 @@
1
- import { CSSResultGroup, html, LitElement } from 'lit';
1
+ import { CSSResultGroup, html } from 'lit';
2
2
  import { styleMap } from 'lit/directives/style-map.js';
3
3
 
4
4
  import style from './button.css';
@@ -6,6 +6,7 @@ import { customElement, property } from 'lit/decorators.js';
6
6
  import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from './types';
7
7
  import { DomRenderable } from './table';
8
8
  import { TooltipPostionsTypes } from './tooltip';
9
+ import { DisposableElement } from '../classes/DisposibleElement';
9
10
 
10
11
  export enum ButtonSizes {
11
12
  large = "large",
@@ -45,7 +46,7 @@ const MODES = {
45
46
  }
46
47
 
47
48
  @customElement('spectric-button')
48
- export class SpectricButton extends LitElement implements ButtonProps {
49
+ export class SpectricButton extends DisposableElement implements ButtonProps {
49
50
 
50
51
  static styles?: CSSResultGroup | undefined = style;
51
52
  @property({ type: String, reflect: true })
@@ -66,14 +67,11 @@ export class SpectricButton extends LitElement implements ButtonProps {
66
67
  tooltip?: DomRenderable;
67
68
  @property({ type: String, reflect: true })
68
69
  tooltipPosition?: TooltipPostionsTypes = "right";
69
- connectedCallback(): void {
70
- super.connectedCallback()
71
- this.addEventListener("click", this._onClick, { capture: true })
72
- }
73
- disconnectedCallback(): void {
74
- super.disconnectedCallback()
75
- this.removeEventListener("click", this._onClick)
70
+ constructor() {
71
+ super()
72
+ this.addDisposableListener(this, "click", this._onClick, { capture: true })
76
73
  }
74
+
77
75
  private _onClick = (e: MouseEvent) => {
78
76
  if (e instanceof CustomEvent) {
79
77
  return
@@ -1,6 +1,6 @@
1
1
  import { html, LitElement, PropertyValues } from 'lit';
2
2
  import "../Button";
3
- import { customElement, property, } from 'lit/decorators.js';
3
+ import { customElement, property, query, } from 'lit/decorators.js';
4
4
  import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from '../types';
5
5
  export const PaginationElementTag = "spectric-pagination"
6
6
  import "./pagination.css"
@@ -37,6 +37,8 @@ export class PaginationElement extends LitElement implements PaginationProps {
37
37
  @property({ type: Array })
38
38
  pageSizeOptions = [10, 20, 50, 100, 1000];
39
39
 
40
+ @query("select")
41
+ select?: HTMLSelectElement
40
42
  /**
41
43
  * Size of the pagination buttons
42
44
  */
@@ -48,6 +50,15 @@ export class PaginationElement extends LitElement implements PaginationProps {
48
50
  protected updated(_changedProperties: PropertyValues): void {
49
51
  if (_changedProperties.has("pageSize") && !this.pageSizeOptions.includes(this.pageSize)) {
50
52
  this.pageSizeOptions = [...this.pageSizeOptions, this.pageSize].sort((a, b) => a - b)
53
+ /**
54
+ * If an option isn't present in the select options list it cannot update its value until after the option is present.
55
+ * We requests an animation frame to make sure we the value was set correctly after the option is added. We update it if the value is incorrect
56
+ */
57
+ requestAnimationFrame(() => {
58
+ if (this.select && this.select.value !== String(this.pageSize)) {
59
+ this.select.value = String(this.pageSize)
60
+ }
61
+ })
51
62
  }
52
63
  }
53
64
  private _handlePageUp = () => {
@@ -59,6 +70,8 @@ export class PaginationElement extends LitElement implements PaginationProps {
59
70
  this._emitChange()
60
71
  }
61
72
  private _handleSizeChange = (e: any) => {
73
+ e.stopPropagation()
74
+ e.preventDefault()
62
75
  let value = parseInt(e.target.value)
63
76
  this.pageSize = value
64
77
  this._emitChange()
@@ -3,6 +3,8 @@ import { customElement, property, query, } from 'lit/decorators.js';
3
3
  import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from '../types';
4
4
  export const TableCellElementTag = "spectric-table-cell"
5
5
  import { ColumnSettings, TableElement } from './table';
6
+ import { cache } from 'lit/directives/cache.js';
7
+ import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
6
8
 
7
9
  interface CellProps<T> {
8
10
  column: ColumnSettings<T>
@@ -30,50 +32,47 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
30
32
  column!: ColumnSettings<T>;
31
33
  columns!: ColumnSettings<T>[];
32
34
  table!: TableElement<T>
33
- styleRules: CSSStyleDeclaration;
35
+
34
36
  @query("td")
35
37
  td!: HTMLTableCellElement
36
- constructor() {
37
- super()
38
- this.styleRules = document.createElement('span').style;
38
+ styleRules: StyleInfo = { whiteSpace: "", width: "" };
39
+ protected createRenderRoot(): HTMLElement | DocumentFragment {
40
+ return this
39
41
  }
40
42
  protected updated(_changedProperties: PropertyValues): void {
41
- Object.assign(this.td.style, this.styleRules)
43
+
42
44
  }
43
- protected createRenderRoot(): HTMLElement | DocumentFragment {
44
- return this
45
+ _emitFilter(filter: FilterEvent<T>) {
46
+ this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter", {
47
+ composed: true,
48
+ bubbles: true,
49
+ detail: filter
50
+ }))
45
51
  }
46
52
  _handleFilterOut = () => {
47
53
  let value = undefined;
48
54
  if (this.column.key && typeof this.row === "object") {
49
55
  value = rowGetValue(this.row as Record<any, any>, this.column.key)
50
56
  }
51
- this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter", {
52
- composed: true,
53
- bubbles: true,
54
- detail: {
55
- include: false,
56
- row: this.row,
57
- value,
58
- column: this.column
59
- }
60
- }))
57
+ this._emitFilter({
58
+ include: false,
59
+ row: this.row,
60
+ value,
61
+ column: this.column
62
+ })
63
+
61
64
  }
62
65
  _handleFilterFor = () => {
63
66
  let value = undefined;
64
67
  if (this.column.key && typeof this.row === "object") {
65
68
  value = rowGetValue(this.row as Record<any, any>, this.column.key)
66
69
  }
67
- this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter", {
68
- composed: true,
69
- bubbles: true,
70
- detail: {
71
- include: true,
72
- row: this.row,
73
- value,
74
- column: this.column
75
- }
76
- }))
70
+ this._emitFilter({
71
+ include: true,
72
+ row: this.row,
73
+ value,
74
+ column: this.column
75
+ })
77
76
  }
78
77
  protected render(): unknown {
79
78
  let rendered
@@ -88,17 +87,20 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
88
87
  if (this.column.filterable) {
89
88
  classes.push("filterable")
90
89
  }
91
- let filterButtons = html`<div class="table-cell-actions">
90
+
91
+ let filterButtons = cache(this.column.filterable
92
+ ? html`<div class="table-cell-actions">
92
93
  <spectric-button @click=${this._handleFilterOut} size="tiny" variant="text" icon tooltip="Filter Out Value">-</spectric-button>
93
94
  <spectric-button @click=${this._handleFilterFor} size="tiny" variant="text" icon tooltip="Filter For Value">+</spectric-button></div>`
95
+ : null
96
+ )
94
97
  this.styleRules = {
95
- ...this.styleRules,
96
98
  width: this.column.width ? this.column.width + "px" : "",
97
99
  whiteSpace: this.column.whiteSpace || ""
98
100
  }
99
101
  return html`
100
- <td>
101
- ${this.column.filterable ? filterButtons : null}
102
+ <td style=${styleMap(this.styleRules)}>
103
+ ${filterButtons}
102
104
  <div class=${classes.join(" ")}>${rendered}</div>
103
105
  </td>
104
106
  `
@@ -30,11 +30,15 @@ export class TableHeaderElement<T> extends LitElement implements HeaderProps<T>
30
30
  if (column.sortDirection === TableSortDirection.none || column.sortDirection === undefined) {
31
31
  column.sortDirection = TableSortDirection.ascending
32
32
  } else if (column.sortDirection === TableSortDirection.ascending) {
33
- column.sortDirection = TableSortDirection.decending
34
- } else if (column.sortDirection === TableSortDirection.decending) {
33
+ column.sortDirection = TableSortDirection.descending
34
+ } else if (column.sortDirection === TableSortDirection.descending) {
35
35
  column.sortDirection = TableSortDirection.none
36
36
  }
37
- this.dispatchEvent(new CustomEvent<ColumnSettings<T>>("sortChange", { detail: column }))
37
+ this.dispatchEvent(new CustomEvent<ColumnSettings<T>>("sortChange", {
38
+ composed: true,
39
+ bubbles: true,
40
+ detail: column
41
+ }))
38
42
  }
39
43
  protected render(): unknown {
40
44
  return html`
@@ -48,7 +52,7 @@ export class TableHeaderElement<T> extends LitElement implements HeaderProps<T>
48
52
  classes.push("sortable")
49
53
  }
50
54
  let columnWidth = column.width ? `width:${column.width}px;` : ""
51
- let sortDirection = column.sortDirection === TableSortDirection.ascending ? `🠉` : column.sortDirection == TableSortDirection.decending ? `🠋` : ``
55
+ let sortDirection = column.sortDirection === TableSortDirection.ascending ? `🠉` : column.sortDirection == TableSortDirection.descending ? `🠋` : ``
52
56
  let sortClass = column.sortDirection || TableSortDirection.none
53
57
  return html`
54
58
  <td @click=${() => this._handleSortChange(column)} style="${columnWidth}">
@@ -19,12 +19,12 @@ export const createSortChain = <T>(sorts: ColumnSettings<T>[]) => {
19
19
  if (typeof v1 === "number" || typeof v1 === "bigint" || typeof v1 === "boolean") {
20
20
  //@ts-ignore
21
21
  let sort: number = v1 - v2 as unknown as number
22
- if (sortDirection === TableSortDirection.decending) {
22
+ if (sortDirection === TableSortDirection.descending) {
23
23
  sort = sort * -1
24
24
  }
25
25
  return sort
26
26
  } else if (typeof v1 === "string") {
27
- return v1.localeCompare(v2) * (sortDirection === TableSortDirection.decending ? -1 : 1)
27
+ return v1.localeCompare(v2) * (sortDirection === TableSortDirection.descending ? -1 : 1)
28
28
  }
29
29
  once(() => { console.error(`Unable to sort type ${typeof v1}`) })
30
30
  return undefined
@@ -43,9 +43,11 @@ spectric-table-header .header-contents {
43
43
  spectric-table-header .header-contents .sort-direction {
44
44
  position: absolute;
45
45
  right: 0;
46
+ top: calc(50% - 8px)
46
47
  }
47
48
  spectric-table-header .header-contents.sortable {
48
49
  cursor: pointer;
50
+ padding-right:15px
49
51
  }
50
52
  spectric-table-header .header-contents.sortable:hover .sort-direction.none::before
51
53
  {
@@ -28,7 +28,7 @@ export enum TableSortOption {
28
28
  export type TableSortOptionTypes = `${TableSortOption}`
29
29
  export enum TableSortDirection {
30
30
  ascending = "ascending",
31
- decending = "decending",
31
+ descending = "descending",
32
32
  none = "none"
33
33
  }
34
34
  export type TableSortDirectionTypes = `${TableSortDirection}`
@@ -121,8 +121,6 @@ export class TableElement<T> extends LitElement implements TableProps<T> {
121
121
  }
122
122
 
123
123
  private _handlePaginationChange = (e: CustomEvent<PaginationChangeProps>) => {
124
- e.preventDefault()
125
- e.stopPropagation()
126
124
  if (this.pagination) {
127
125
  let pagination = { ...this.pagination, ...e.detail }
128
126
 
@@ -132,6 +130,7 @@ export class TableElement<T> extends LitElement implements TableProps<T> {
132
130
  }
133
131
  this.pagination = pagination
134
132
  }
133
+ this.dispatchEvent(new CustomEvent<PaginationChangeProps>("paginationChange", { detail: e.detail }))
135
134
  this._emitChange()
136
135
  };
137
136
  private _handleSortChange = (e: CustomEvent<ColumnSettings<T>>) => {
@@ -158,22 +157,30 @@ export class TableElement<T> extends LitElement implements TableProps<T> {
158
157
  }
159
158
  //@ts-ignore
160
159
  private __DO_NOT_USE_filter = () => {
161
- //This is only here to document events that bubble up from lower components
160
+ //This is only here to auto document events that bubble up from lower components
162
161
  this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter"))
162
+ this.dispatchEvent(new CustomEvent<ColumnSettings<T>>("sortChange"))
163
163
  }
164
164
  @state()
165
165
  private selected: T[] = [];
166
166
  protected createRenderRoot(): HTMLElement | DocumentFragment {
167
167
  return this
168
168
  }
169
+ deselectAll() {
170
+ this.selected = []
171
+ this.dispatchEvent(new CustomEvent("selected", { detail: this.selected }))
172
+ }
173
+ selectAll() {
174
+ this.selected = [...this.data]
175
+ this.dispatchEvent(new CustomEvent("selected", { detail: this.selected }))
176
+ }
169
177
  _handleSelectAllChange = (e: DomEvent<HTMLInputElement>) => {
170
178
  e.stopPropagation()
171
179
  if (e.target.checked) {
172
- this.selected = [...this.data]
180
+ this.selectAll()
173
181
  } else {
174
- this.selected = []
182
+ this.deselectAll()
175
183
  }
176
- this.dispatchEvent(new CustomEvent("selected", { detail: this.selected }))
177
184
  }
178
185
  protected update(changedProperties: PropertyValues): void {
179
186
  if (changedProperties.has("select")) {
@@ -235,7 +242,9 @@ export class TableElement<T> extends LitElement implements TableProps<T> {
235
242
 
236
243
  interface TableEvents {
237
244
  'change': (event: CustomEvent<TableDataOptions<any>>) => void;
245
+ 'paginationChange': (event: CustomEvent<PaginationChangeProps>) => void;
238
246
  'filter': (event: CustomEvent<FilterEvent<any>>) => void;
247
+ 'sortChange': (event: CustomEvent<ColumnSettings<any>>) => void;
239
248
  }
240
249
 
241
250
  declare global {
@@ -63,7 +63,7 @@ export class TooltipElement extends DisposableElement implements TooltipProps {
63
63
  position: TooltipPostionsTypes = "right";
64
64
  @property({ type: Number, reflect: true })
65
65
  maxWidth?: number = 300;
66
- private portalElement = document.createElement("div")
66
+ private portalElement!: HTMLDivElement
67
67
  private mouseLocation?: { left: number; top: number; };
68
68
  static styles?: CSSResultGroup | undefined = css`:host{max-height: 0px;
69
69
  max-width: 0px;
@@ -90,10 +90,14 @@ export class TooltipElement extends DisposableElement implements TooltipProps {
90
90
  }
91
91
  connectedCallback(): void {
92
92
  super.connectedCallback()
93
+ this.portalElement = document.createElement("div")
94
+ this.portalElement.className = "spectric-tooltip-portal"
93
95
  }
94
96
  disconnectedCallback(): void {
95
- super.disconnectedCallback()
97
+ super.disconnectedCallback();
96
98
  this.portalElement.remove()
99
+ //@ts-ignore
100
+ this.portalElement = undefined
97
101
  }
98
102
  private _getMousePosition = (ev: MouseEvent) => {
99
103
  this.mouseLocation = {
@@ -199,6 +203,7 @@ export class TooltipElement extends DisposableElement implements TooltipProps {
199
203
  protected render() {
200
204
  //We don't need to render anything here this is just a placeholder element the content is displayed in a portal attached to the body.
201
205
  // See showTooltip for the real rendering
206
+ return html`<!-- ToolTip -->`
202
207
  }
203
208
  }
204
209