@spectric/ui 0.0.9 → 0.0.11
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/components/Button.d.ts +2 -2
- package/dist/components/pagination/pagination.d.ts +5 -5
- package/dist/components/query_bar/QueryBar.d.ts +4 -4
- package/dist/components/table/cell.d.ts +1 -0
- package/dist/components/table/header.d.ts +2 -1
- package/dist/components/table/sorting.d.ts +5 -0
- package/dist/components/table/table.d.ts +43 -36
- package/dist/components/tooltip/tooltip.d.ts +2 -2
- package/dist/custom-elements.json +28 -8
- package/dist/index.es.js +1587 -1518
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +87 -85
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/utils/once.d.ts +1 -0
- package/dist/utils/spread.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/Button.ts +2 -2
- package/src/components/input.ts +0 -1
- package/src/components/pagination/pagination.ts +7 -7
- package/src/components/query_bar/QueryBar.ts +31 -26
- package/src/components/table/cell.ts +13 -3
- package/src/components/table/header.ts +22 -3
- package/src/components/table/sorting.ts +34 -0
- package/src/components/table/table.css +52 -0
- package/src/components/table/table.ts +111 -50
- package/src/components/tooltip/tooltip.ts +2 -2
- package/src/stories/fixtures/ExampleContent.ts +15 -8
- package/src/stories/fixtures/data.ts +24 -11
- package/src/stories/table.stories.ts +27 -13
- package/src/utils/once.ts +12 -0
- package/src/utils/spread.ts +3 -3
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}spectric-table tr{text-align:center}spectric-table-body tr:hover{background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 70%)}spectric-table-header{display:table-header-group;font-weight:700}spectric-table div[role=table]{display:table}spectric-table-body{display:table-row-group}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-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}spectric-table tr{text-align:center}spectric-table-body tr:nth-child(odd){background-color:color-mix(in srgb,var(--spectric-primary, #1ea7fd),transparent 90%)}spectric-table-body 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-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-body{display:table-row-group}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-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%)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function once(func: Function): (...args: any[]) => any;
|
package/dist/utils/spread.d.ts
CHANGED
package/package.json
CHANGED
package/src/components/Button.ts
CHANGED
|
@@ -25,14 +25,14 @@ export enum ButtonVariants {
|
|
|
25
25
|
type ButtonVariantsTypes = `${ButtonVariants}`
|
|
26
26
|
export interface ButtonProps {
|
|
27
27
|
/** Is this the principal call to action on the page? */
|
|
28
|
-
variant
|
|
28
|
+
variant?: ButtonVariantsTypes;
|
|
29
29
|
/** What background color to use */
|
|
30
30
|
backgroundColor?: string;
|
|
31
31
|
/** How large should the button be? */
|
|
32
32
|
size: ButtonSizesTypes;
|
|
33
33
|
label?: string,
|
|
34
34
|
/* should the button be disabled*/
|
|
35
|
-
disabled
|
|
35
|
+
disabled?: boolean;
|
|
36
36
|
danger?: boolean;
|
|
37
37
|
icon?: boolean
|
|
38
38
|
tooltip?: DomRenderable
|
package/src/components/input.ts
CHANGED
|
@@ -303,7 +303,6 @@ export class SpectricInput extends LitElement implements InputProps {
|
|
|
303
303
|
<spectric-button @click=${() => {
|
|
304
304
|
this.checked = !this.checked;
|
|
305
305
|
this.value = Boolean(this.checked);
|
|
306
|
-
console.log(this.checked, this.value)
|
|
307
306
|
this.dispatchEvent(new Event("change", { bubbles: true }))
|
|
308
307
|
}} icon size=${this.size || "xxsmall"} variant=${this.checked ? "primary" : "secondary"}>${this.checked ? '✓' : "\u00A0"}</spectric-button>
|
|
309
308
|
${this.invalid || this.helperText ? html`<spectric-tooltip text=${this.invalid || this.helperText}></spectric-tooltip>` : null}
|
|
@@ -8,12 +8,12 @@ import { ButtonSizesTypes } from '../Button';
|
|
|
8
8
|
export type { PaginationProps, PaginationChangeProps, PaginationEvents }
|
|
9
9
|
|
|
10
10
|
interface PaginationChangeProps {
|
|
11
|
-
page
|
|
12
|
-
pageSize
|
|
11
|
+
page?: number;
|
|
12
|
+
pageSize?: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
interface PaginationProps extends PaginationChangeProps {
|
|
16
|
-
size
|
|
16
|
+
size?: ButtonSizesTypes
|
|
17
17
|
totalItems?: number
|
|
18
18
|
pageSizeOptions?: number[]
|
|
19
19
|
}
|
|
@@ -93,8 +93,8 @@ export class PaginationElement extends LitElement implements PaginationProps {
|
|
|
93
93
|
${pageText}
|
|
94
94
|
</div>
|
|
95
95
|
<div>
|
|
96
|
-
<spectric-button size=${this.size} ?disabled=${this.page === 1} @click=${this._handlePageDown} icon
|
|
97
|
-
<spectric-button size=${this.size} ?disabled=${nextPageDisabled} @click=${this._handlePageUp} icon
|
|
96
|
+
<spectric-button size=${this.size} ?disabled=${this.page === 1} @click=${this._handlePageDown} icon>🠈</spectric-button>
|
|
97
|
+
<spectric-button size=${this.size} ?disabled=${nextPageDisabled} @click=${this._handlePageUp} icon>🠊</spectric-button>
|
|
98
98
|
</div>
|
|
99
99
|
</div>
|
|
100
100
|
`: null}
|
|
@@ -115,7 +115,7 @@ declare global {
|
|
|
115
115
|
namespace JSX {
|
|
116
116
|
interface IntrinsicElements {
|
|
117
117
|
/**
|
|
118
|
-
* @see {@link
|
|
118
|
+
* @see {@link PaginationElement}
|
|
119
119
|
*/
|
|
120
120
|
[PaginationElementTag]: ReactElementWithPropsAndEvents<PaginationElement, PaginationProps, PaginationEvents>;
|
|
121
121
|
}
|
|
@@ -124,7 +124,7 @@ declare global {
|
|
|
124
124
|
namespace JSX {
|
|
125
125
|
interface IntrinsicElements {
|
|
126
126
|
/**
|
|
127
|
-
* @see {@link
|
|
127
|
+
* @see {@link PaginationElement}
|
|
128
128
|
*/
|
|
129
129
|
[PaginationElementTag]: ReactElementWithPropsAndEvents<PaginationElement, PaginationProps, PaginationEvents>
|
|
130
130
|
}
|
|
@@ -39,7 +39,7 @@ export interface IQueryProps {
|
|
|
39
39
|
/**
|
|
40
40
|
* The output of the query in a specific format
|
|
41
41
|
*/
|
|
42
|
-
outputLanguage
|
|
42
|
+
outputLanguage?: SupportedLanguagesTypes;
|
|
43
43
|
/**
|
|
44
44
|
* The output of the query
|
|
45
45
|
*/
|
|
@@ -47,16 +47,16 @@ export interface IQueryProps {
|
|
|
47
47
|
/**
|
|
48
48
|
* Fields that are used for the auto complete
|
|
49
49
|
*/
|
|
50
|
-
fields
|
|
50
|
+
fields?: FieldTypes[];
|
|
51
51
|
/**
|
|
52
52
|
* Callback that will provide values for specific fields
|
|
53
53
|
*/
|
|
54
|
-
getValuesForField
|
|
54
|
+
getValuesForField?: (field: string, text: string) => Promise<string[]>;
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Input placeholder
|
|
58
58
|
*/
|
|
59
|
-
placeholder
|
|
59
|
+
placeholder?: string;
|
|
60
60
|
}
|
|
61
61
|
type LabelValue = {
|
|
62
62
|
label?: string;
|
|
@@ -133,32 +133,34 @@ export class SpectricQuery extends LitElement implements IQueryProps {
|
|
|
133
133
|
protected _input!: SpectricInput;
|
|
134
134
|
_parseQuery = (e: InputEvent | undefined = undefined) => {
|
|
135
135
|
let ast;
|
|
136
|
-
if(e && e?.currentTarget
|
|
136
|
+
if (e && e?.currentTarget) {
|
|
137
137
|
this.value = (e.currentTarget as HTMLInputElement).value
|
|
138
138
|
}
|
|
139
|
-
if (this.value
|
|
140
|
-
|
|
139
|
+
if (this.value) {
|
|
140
|
+
try {
|
|
141
|
+
if (e && e.data == "(") {
|
|
142
|
+
//Auto close parentheses or parsing and suggestions fail
|
|
143
|
+
this.value = this.value + " )"
|
|
144
|
+
this._input.setSelectionRange(this.value.length - 2, this.value.length - 2)
|
|
145
|
+
}
|
|
146
|
+
let value = this.value;
|
|
147
|
+
if (this._input.selectionStart !== null) {
|
|
148
|
+
value = value.substring(0, this._input.selectionStart) + "@kuery-cursor@" + value.substring(this._input.selectionStart)
|
|
149
|
+
}
|
|
150
|
+
//FIXME: make auto complete work well.
|
|
151
|
+
let suggestions = kuery.parse(value, { parseCursor: true, cursorSymbol: "@kuery-cursor@", allowLeadingWildcards: false }) as unknown as Suggestion;
|
|
152
|
+
this.autoComplete(suggestions)
|
|
153
|
+
} catch (error: any) {
|
|
154
|
+
// this.completions = []
|
|
155
|
+
// this._input.invalid = true;
|
|
156
|
+
// let [expect, _, arrow] = e.message.split("\n")
|
|
157
|
+
// this._input.invalidText = html`  ${arrow} ${expect}`;
|
|
158
|
+
return
|
|
159
|
+
}
|
|
141
160
|
}
|
|
142
161
|
try {
|
|
143
|
-
if (e && e.data == "(") {
|
|
144
|
-
//Auto close parentheses or parsing and suggestions fail
|
|
145
|
-
this.value = this.value + " )"
|
|
146
|
-
this._input.setSelectionRange(this.value.length - 2, this.value.length - 2)
|
|
147
|
-
}
|
|
148
|
-
let value = this.value;
|
|
149
|
-
if (this._input.selectionStart !== null) {
|
|
150
|
-
value = value.substring(0, this._input.selectionStart) + "@kuery-cursor@" + value.substring(this._input.selectionStart)
|
|
151
|
-
}
|
|
152
|
-
//FIXME: make auto complete work well.
|
|
153
|
-
let suggestions = kuery.parse(value, { parseCursor: true, cursorSymbol: "@kuery-cursor@", allowLeadingWildcards: false }) as unknown as Suggestion;
|
|
154
|
-
this.autoComplete(suggestions)
|
|
155
|
-
|
|
156
162
|
ast = kuery.parse(this.value, { allowLeadingWildcards: false });
|
|
157
|
-
} catch (
|
|
158
|
-
// this.completions = []
|
|
159
|
-
// this._input.invalid = true;
|
|
160
|
-
// let [expect, _, arrow] = e.message.split("\n")
|
|
161
|
-
// this._input.invalidText = html`  ${arrow} ${expect}`;
|
|
163
|
+
} catch (error: any) {
|
|
162
164
|
return
|
|
163
165
|
}
|
|
164
166
|
let output
|
|
@@ -288,17 +290,20 @@ export class SpectricQuery extends LitElement implements IQueryProps {
|
|
|
288
290
|
} else {
|
|
289
291
|
this.value = prefix + this.value.substring(completion.end)
|
|
290
292
|
}
|
|
293
|
+
//Important if the underlying inputs value hasn't been set the setSelectionRange will fail to set a range greater than the inputs current value
|
|
294
|
+
this._input.value = this.value
|
|
291
295
|
this._input.setSelectionRange(insertIndex, insertIndex)
|
|
292
296
|
if (completion.onSelect) {
|
|
293
297
|
let value = await completion.onSelect()
|
|
294
298
|
if (value !== undefined) {
|
|
295
299
|
this.value += value
|
|
296
|
-
setTimeout(()=>{this._input.focus();})
|
|
300
|
+
setTimeout(() => { this._input.focus(); })
|
|
297
301
|
}
|
|
298
302
|
}
|
|
299
303
|
this.completionIndex = 0;
|
|
300
304
|
this.completions = []
|
|
301
305
|
this._parseQuery()
|
|
306
|
+
this._input.focus()
|
|
302
307
|
}
|
|
303
308
|
_handleArrows = (e: KeyboardEvent) => {
|
|
304
309
|
if (e.key === "Escape") {
|
|
@@ -43,7 +43,7 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
43
43
|
_handleFilterOut = () => {
|
|
44
44
|
let value = undefined;
|
|
45
45
|
if (this.column.key && typeof this.row === "object") {
|
|
46
|
-
value = (this.row as Record<any, any
|
|
46
|
+
value = rowGetValue(this.row as Record<any, any>, this.column.key)
|
|
47
47
|
}
|
|
48
48
|
this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter", {
|
|
49
49
|
composed: true,
|
|
@@ -59,7 +59,7 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
59
59
|
_handleFilterFor = () => {
|
|
60
60
|
let value = undefined;
|
|
61
61
|
if (this.column.key && typeof this.row === "object") {
|
|
62
|
-
value = (this.row as Record<any, any
|
|
62
|
+
value = rowGetValue(this.row as Record<any, any>, this.column.key)
|
|
63
63
|
}
|
|
64
64
|
this.dispatchEvent(new CustomEvent<FilterEvent<T>>("filter", {
|
|
65
65
|
composed: true,
|
|
@@ -77,7 +77,7 @@ export class TableCellElement<T> extends LitElement implements CellProps<T> {
|
|
|
77
77
|
if (this.column.render) {
|
|
78
78
|
rendered = this.column.render(this.row, this.table)
|
|
79
79
|
} else if (this.column.key && typeof this.row === 'object') {
|
|
80
|
-
rendered = (this.row as
|
|
80
|
+
rendered = rowGetValue(this.row as any, this.column.key)
|
|
81
81
|
} else {
|
|
82
82
|
rendered = html`error`
|
|
83
83
|
}
|
|
@@ -131,3 +131,13 @@ declare global {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
export const rowGetValue = (context: Record<string, any>, key: string) => {
|
|
137
|
+
let path = key.split(".")
|
|
138
|
+
let value = context[path[0]]
|
|
139
|
+
if (path.length > 1) {
|
|
140
|
+
value = rowGetValue(value, path.slice(1).join("."))
|
|
141
|
+
}
|
|
142
|
+
return value
|
|
143
|
+
}
|
|
@@ -4,7 +4,7 @@ import { customElement, property, } from 'lit/decorators.js';
|
|
|
4
4
|
import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from '../types';
|
|
5
5
|
import "./table.css"
|
|
6
6
|
export const TableHeaderElementTag = "spectric-table-header"
|
|
7
|
-
import { ColumnSettings } from './table';
|
|
7
|
+
import { ColumnSettings, TableSortDirection } from './table';
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
interface HeaderProps<T> {
|
|
@@ -22,6 +22,20 @@ export class TableHeaderElement<T> extends LitElement implements HeaderProps<T>
|
|
|
22
22
|
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
|
23
23
|
return this
|
|
24
24
|
}
|
|
25
|
+
_handleSortChange = (column: ColumnSettings<T>) => {
|
|
26
|
+
column = JSON.parse(JSON.stringify(column))// Clone the column to not mutate the original object
|
|
27
|
+
if (!column.sortable) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if (column.sortDirection === TableSortDirection.none || column.sortDirection === undefined) {
|
|
31
|
+
column.sortDirection = TableSortDirection.ascending
|
|
32
|
+
} else if (column.sortDirection === TableSortDirection.ascending) {
|
|
33
|
+
column.sortDirection = TableSortDirection.decending
|
|
34
|
+
} else if (column.sortDirection === TableSortDirection.decending) {
|
|
35
|
+
column.sortDirection = TableSortDirection.none
|
|
36
|
+
}
|
|
37
|
+
this.dispatchEvent(new CustomEvent<ColumnSettings<T>>("sortChange", { detail: column }))
|
|
38
|
+
}
|
|
25
39
|
protected render(): unknown {
|
|
26
40
|
|
|
27
41
|
return html`
|
|
@@ -31,7 +45,12 @@ export class TableHeaderElement<T> extends LitElement implements HeaderProps<T>
|
|
|
31
45
|
if (column.filterable) {
|
|
32
46
|
//classes.push("filterable")
|
|
33
47
|
}
|
|
34
|
-
|
|
48
|
+
if (column.sortable) {
|
|
49
|
+
classes.push("sortable")
|
|
50
|
+
}
|
|
51
|
+
let sortDirection = column.sortDirection === TableSortDirection.ascending ? `🠉` : column.sortDirection == TableSortDirection.decending ? `🠋` : ``
|
|
52
|
+
let sortClass = column.sortDirection || TableSortDirection.none
|
|
53
|
+
return html`<td @click=${() => this._handleSortChange(column)}><div class=${classes.join(" ")}>${column.title || column.key} <span class="sort-direction ${sortClass}">${sortDirection}</span></div></td>`
|
|
35
54
|
})}
|
|
36
55
|
</tr>
|
|
37
56
|
`
|
|
@@ -39,7 +58,7 @@ export class TableHeaderElement<T> extends LitElement implements HeaderProps<T>
|
|
|
39
58
|
}
|
|
40
59
|
|
|
41
60
|
interface TableHeaderEvents {
|
|
42
|
-
'
|
|
61
|
+
'sortChange': (event: CustomEvent<ColumnSettings<any>>) => void; //TODO sort events
|
|
43
62
|
}
|
|
44
63
|
|
|
45
64
|
declare global {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { once } from "../../utils/once";
|
|
2
|
+
import { rowGetValue } from "./cell";
|
|
3
|
+
import { ColumnSettings, TableSortDirection } from "./table";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a chain of sort functions so you can perform multi column sorting.
|
|
7
|
+
*/
|
|
8
|
+
export const createSortChain = <T>(sorts: ColumnSettings<T>[]) => {
|
|
9
|
+
return sorts.map(({ key, sortDirection, compareFn }) => {
|
|
10
|
+
return (a: T, b: T) => {
|
|
11
|
+
if (!key) {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
let v1 = rowGetValue(a as Record<string, any>, key)
|
|
15
|
+
let v2 = rowGetValue(b as Record<string, any>, key)
|
|
16
|
+
if (compareFn) {
|
|
17
|
+
return compareFn(a, b)
|
|
18
|
+
}
|
|
19
|
+
if (typeof v1 === "number" || typeof v1 === "bigint" || typeof v1 === "boolean") {
|
|
20
|
+
//@ts-ignore
|
|
21
|
+
let sort: number = v1 - v2 as unknown as number
|
|
22
|
+
if (sortDirection === TableSortDirection.decending) {
|
|
23
|
+
sort = sort * -1
|
|
24
|
+
}
|
|
25
|
+
return sort
|
|
26
|
+
} else if (typeof v1 === "string") {
|
|
27
|
+
return v1.localeCompare(v2) * (sortDirection === TableSortDirection.decending ? -1 : 1)
|
|
28
|
+
}
|
|
29
|
+
once(() => { console.error(`Unable to sort type ${typeof v1}`) })
|
|
30
|
+
return undefined
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
@@ -1,20 +1,53 @@
|
|
|
1
1
|
spectric-table{
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
}
|
|
6
|
+
spectric-table .table-wrapper{
|
|
7
|
+
overflow: auto;
|
|
8
|
+
flex-grow: 1;
|
|
4
9
|
}
|
|
5
10
|
spectric-table tr{
|
|
6
11
|
text-align: center;
|
|
7
12
|
}
|
|
8
13
|
|
|
14
|
+
spectric-table-body tr:nth-child(odd){
|
|
15
|
+
background-color: color-mix(in srgb, var(--spectric-primary, #1ea7fd), transparent 90%);
|
|
16
|
+
}
|
|
9
17
|
spectric-table-body tr:hover{
|
|
10
18
|
background-color: color-mix(in srgb, var(--spectric-primary, #1ea7fd), transparent 70%)
|
|
11
19
|
}
|
|
12
20
|
spectric-table-header{
|
|
13
21
|
display: table-header-group;
|
|
14
22
|
font-weight: bold;
|
|
23
|
+
position: sticky;
|
|
24
|
+
top: 0px;
|
|
25
|
+
left: 0px;
|
|
26
|
+
z-index: 1;
|
|
27
|
+
background: var(--spectric-background, #ffffff);
|
|
28
|
+
}
|
|
29
|
+
spectric-table-header td {
|
|
30
|
+
vertical-align: middle;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
spectric-table-header .header-contents {
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
spectric-table-header .header-contents .sort-direction {
|
|
38
|
+
position: absolute;
|
|
39
|
+
right: 0;
|
|
40
|
+
}
|
|
41
|
+
spectric-table-header .header-contents.sortable {
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
}
|
|
44
|
+
spectric-table-header .header-contents.sortable:hover .sort-direction.none::before
|
|
45
|
+
{
|
|
46
|
+
content: "\2B81";
|
|
15
47
|
}
|
|
16
48
|
spectric-table div[role="table"]{
|
|
17
49
|
display: table;
|
|
50
|
+
min-width: 100%;
|
|
18
51
|
}
|
|
19
52
|
spectric-table-body {
|
|
20
53
|
display: table-row-group;
|
|
@@ -43,4 +76,23 @@ spectric-table-cell .table-cell-actions{
|
|
|
43
76
|
}
|
|
44
77
|
spectric-table-cell td:hover .table-cell-actions{
|
|
45
78
|
visibility: unset;
|
|
79
|
+
}
|
|
80
|
+
spectric-table .table-checkbox-single spectric-button{
|
|
81
|
+
--button-border-radius: 50%;
|
|
82
|
+
}
|
|
83
|
+
spectric-input.table-checkbox-single[checked] spectric-button{
|
|
84
|
+
--text-on-color: transparent;
|
|
85
|
+
border-radius: 50%;
|
|
86
|
+
position: relative;
|
|
87
|
+
}
|
|
88
|
+
spectric-input.table-checkbox-single[checked] spectric-button::before {
|
|
89
|
+
position: absolute;
|
|
90
|
+
content: " ";
|
|
91
|
+
height: 50%;
|
|
92
|
+
width: 50%;
|
|
93
|
+
left: 25%;
|
|
94
|
+
top: 25%;
|
|
95
|
+
border-radius: 50%;
|
|
96
|
+
z-index: 1;
|
|
97
|
+
box-shadow: 0px 0px 0px 4px var(--input-color);
|
|
46
98
|
}
|