@spectric/ui 0.0.20 → 0.0.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectric/ui",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "type": "module",
5
5
  "main": "./dist/index.es.js",
6
6
  "module": "./dist/index.es.js",
@@ -1,35 +1,35 @@
1
- import { html, LitElement } from 'lit';
2
- import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
3
- import "./Button"
4
- import { customElement, property } from 'lit/decorators.js';
5
- import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from './types';
1
+ import { html, LitElement } from "lit";
2
+ import { StyleInfo, styleMap } from "lit/directives/style-map.js";
3
+ import "./Button";
4
+ import { customElement, property } from "lit/decorators.js";
5
+ import {
6
+ HTMLElementTagWithEvents,
7
+ ReactElementWithPropsAndEvents,
8
+ } from "./types";
6
9
 
7
10
  export interface BannerProps {
8
11
  /**What is returned in the event details when a banner is dismissed */
9
- bannerId?: any,
12
+ bannerId?: any;
10
13
  /** Banner Text to display */
11
14
  text?: string;
12
15
  /** What background color to use */
13
16
  headerStyle?: StyleInfo;
14
17
  /** Can be dismissed */
15
18
  dismissable?: boolean;
16
-
17
19
  }
18
20
 
19
-
20
-
21
21
  const DEFAULT_STYLE: StyleInfo = {
22
22
  display: "flex",
23
23
  alignItems: "center",
24
24
  backgroundColor: "black",
25
25
  color: "white",
26
- textAlign: "center"
27
- }
26
+ textAlign: "center",
27
+ };
28
28
 
29
29
  /**
30
30
  * @slot text - Banner Text content
31
31
  */
32
- @customElement('spectric-banner')
32
+ @customElement("spectric-banner")
33
33
  export class SpectricBanner extends LitElement implements BannerProps {
34
34
  @property({ type: Boolean, reflect: true })
35
35
  dismissable: boolean = false;
@@ -45,40 +45,47 @@ export class SpectricBanner extends LitElement implements BannerProps {
45
45
  private _dismissed: boolean = false;
46
46
 
47
47
  private onDismiss = (e: PointerEvent) => {
48
- e.preventDefault()
49
- e.stopPropagation()
48
+ e.preventDefault();
49
+ e.stopPropagation();
50
50
  const options = {
51
51
  bubbles: true,
52
52
  composed: true,
53
53
  };
54
54
  this._dismissed = true;
55
- let { bannerId, text, headerStyle, dismissable }: BannerProps = this
56
- this.dispatchEvent(new CustomEvent<BannerProps>('bannerDismissed', {
57
- detail: { bannerId, text, headerStyle, dismissable },
58
- ...options
59
- }));
60
- }
55
+ let { bannerId, text, headerStyle, dismissable }: BannerProps = this;
56
+ this.dispatchEvent(
57
+ new CustomEvent<BannerProps>("bannerDismissed", {
58
+ detail: { bannerId, text, headerStyle, dismissable },
59
+ ...options,
60
+ })
61
+ );
62
+ };
61
63
  protected render(): unknown {
62
64
  if (this._dismissed) {
63
- return
65
+ return;
64
66
  }
65
67
  return html`
66
- <header style=${styleMap({ ...DEFAULT_STYLE, ...this.headerStyle })}>
67
- <div style="flex-grow:1"><slot name="text">${this.text}</slot><slot></slot></div>
68
- ${this.dismissable ? html`<spectric-button size="small" @click=${this.onDismiss}>X</spectric-button>` : null}
69
- </header>
68
+ <header style=${styleMap({ ...DEFAULT_STYLE, ...this.headerStyle })}>
69
+ <div style="flex-grow:1">
70
+ <slot name="text">${this.text}</slot><slot></slot>
71
+ </div>
72
+ ${this.dismissable
73
+ ? html`<spectric-button size="small" @click=${this.onDismiss} icon
74
+ >X</spectric-button
75
+ >`
76
+ : null}
77
+ </header>
70
78
  `;
71
79
  }
72
80
  }
73
81
 
74
82
  export interface BannerEventMap {
75
- 'bannerDismissed': (event: CustomEvent<BannerProps>) => void
83
+ bannerDismissed: (event: CustomEvent<BannerProps>) => void;
76
84
  }
77
85
 
78
86
  declare global {
79
-
80
87
  interface HTMLElementTagNameMap {
81
- "spectric-banner": HTMLElementTagWithEvents<SpectricBanner, BannerEventMap>
88
+ "spectric-banner": HTMLElementTagWithEvents<SpectricBanner, BannerEventMap>;
82
89
  }
83
90
 
84
91
  namespace JSX {
@@ -86,7 +93,11 @@ declare global {
86
93
  /**
87
94
  * {@link SpectricBanner}
88
95
  */
89
- "spectric-banner": ReactElementWithPropsAndEvents<SpectricBanner, BannerProps, BannerEventMap>;
96
+ "spectric-banner": ReactElementWithPropsAndEvents<
97
+ SpectricBanner,
98
+ BannerProps,
99
+ BannerEventMap
100
+ >;
90
101
  }
91
102
  }
92
103
  namespace React {
@@ -95,8 +106,12 @@ declare global {
95
106
  /**
96
107
  * {@link SpectricBanner}
97
108
  */
98
- "spectric-banner": ReactElementWithPropsAndEvents<SpectricBanner, BannerProps, BannerEventMap>;
109
+ "spectric-banner": ReactElementWithPropsAndEvents<
110
+ SpectricBanner,
111
+ BannerProps,
112
+ BannerEventMap
113
+ >;
99
114
  }
100
115
  }
101
116
  }
102
- }
117
+ }
@@ -1,163 +1,191 @@
1
- import { CSSResultGroup, html, LitElement, PropertyValues, render } from 'lit';
1
+ import { CSSResultGroup, html, LitElement, PropertyValues, render } from "lit";
2
2
  import "../Button";
3
- import { customElement, property, queryAsync } from 'lit/decorators.js';
4
- import { style } from './dialog.css';
5
- import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from '../types';
6
- export const DialogElementTag = "spectric-dialog"
7
- export type { DialogProps as Props, DialogEvents }
3
+ import { customElement, property, queryAsync } from "lit/decorators.js";
4
+ import { style } from "./dialog.css";
5
+ import {
6
+ HTMLElementTagWithEvents,
7
+ ReactElementWithPropsAndEvents,
8
+ } from "../types";
9
+ export const DialogElementTag = "spectric-dialog";
10
+ export type { DialogProps as Props, DialogEvents };
8
11
  interface DialogProps {
9
- open?: boolean;
10
- dismissable?: boolean;
11
- hideBackdrop?: boolean;
12
- title?: string;
13
- closeOnEscape?: boolean;
14
- closeOnOutsideClick?: boolean;
12
+ open?: boolean;
13
+ dismissable?: boolean;
14
+ hideBackdrop?: boolean;
15
+ title?: string;
16
+ closeOnEscape?: boolean;
17
+ closeOnOutsideClick?: boolean;
15
18
  }
16
19
 
17
-
18
-
19
20
  /**
20
21
  * Dialog Element
21
22
  * @slot title - sets the title of the dialog attribute/property can also be use for setting the title to a string
22
23
  */
23
24
  @customElement(DialogElementTag)
24
25
  export class DialogElement extends LitElement implements DialogProps {
25
- static styles: CSSResultGroup = style;
26
- static display(props: DialogProps, body: any) {
27
- let dialog = document.createElement(DialogElementTag);
28
- dialog.addEventListener("close", () => {
29
- dialog.remove()
30
- });
31
- for (let prop in props) {
32
- //@ts-ignore
33
- dialog[prop] = props[prop];
26
+ static styles: CSSResultGroup = style;
27
+ static display(props: DialogProps, body: any) {
28
+ let dialog = document.createElement(DialogElementTag);
29
+ dialog.addEventListener("close", () => {
30
+ dialog.remove();
31
+ });
32
+ for (let prop in props) {
33
+ //@ts-ignore
34
+ dialog[prop] = props[prop];
35
+ }
36
+ let frag = document.createDocumentFragment();
37
+ render(body, frag);
38
+ dialog.appendChild(frag);
39
+ dialog.open = true;
40
+ document.body.appendChild(dialog);
41
+ return dialog;
42
+ }
43
+ @property({ type: Boolean, reflect: true })
44
+ open: boolean = false;
45
+
46
+ @property({ type: Boolean, reflect: true })
47
+ dismissable: boolean = true;
48
+
49
+ @property({ type: Boolean, reflect: true })
50
+ hideBackdrop: boolean = false;
51
+
52
+ @property({ type: String, reflect: true })
53
+ title: string = "";
54
+
55
+ @property({ type: Boolean, reflect: true })
56
+ closeOnEscape: boolean = true;
57
+
58
+ @property({ type: Boolean, reflect: true })
59
+ closeOnOutsideClick: boolean = true;
60
+
61
+ @queryAsync("dialog")
62
+ dialogElement!: Promise<HTMLDialogElement>;
63
+
64
+ connectedCallback(): void {
65
+ super.connectedCallback();
66
+ this.dialogElement.then((dialog) =>
67
+ dialog.addEventListener("keydown", this._handleKeyDown)
68
+ );
69
+ }
70
+
71
+ disconnectedCallback(): void {
72
+ super.disconnectedCallback();
73
+ this.dialogElement.then((dialog) =>
74
+ dialog.removeEventListener("keydown", this._handleKeyDown)
75
+ );
76
+ }
77
+
78
+ protected updated(_changedProperties: PropertyValues): void {
79
+ if (_changedProperties.has("open")) {
80
+ this.dialogElement.then((dialog) => {
81
+ if (this.open) {
82
+ dialog.showModal();
83
+ } else {
84
+ dialog.close();
34
85
  }
35
- let frag = document.createDocumentFragment()
36
- render(body, frag);
37
- dialog.appendChild(frag)
38
- dialog.open = true;
39
- document.body.appendChild(dialog)
40
- return dialog
86
+ });
41
87
  }
42
- @property({ type: Boolean, reflect: true })
43
- open: boolean = false;
44
-
45
- @property({ type: Boolean, reflect: true })
46
- dismissable: boolean = true;
47
-
48
- @property({ type: Boolean, reflect: true })
49
- hideBackdrop: boolean = false;
50
-
51
- @property({ type: String, reflect: true })
52
- title: string = "";
88
+ }
53
89
 
54
- @property({ type: Boolean, reflect: true })
55
- closeOnEscape: boolean = true;
56
-
57
- @property({ type: Boolean, reflect: true })
58
- closeOnOutsideClick: boolean = true;
59
-
60
- @queryAsync("dialog")
61
- dialogElement!: Promise<HTMLDialogElement>;
62
-
63
- connectedCallback(): void {
64
- super.connectedCallback();
65
- this.dialogElement.then(dialog => dialog.addEventListener('keydown', this._handleKeyDown));
90
+ private clickHandler = async (e: PointerEvent): Promise<void> => {
91
+ const dialog = await this.dialogElement;
92
+ if (!this.dismissable || !this.closeOnOutsideClick) {
93
+ return;
66
94
  }
67
-
68
- disconnectedCallback(): void {
69
- super.disconnectedCallback();
70
- this.dialogElement.then(dialog => dialog.removeEventListener('keydown', this._handleKeyDown));
95
+ if (dialog === e.target) {
96
+ // clicked on backdrop
97
+ this.open = false;
71
98
  }
99
+ };
72
100
 
73
- protected updated(_changedProperties: PropertyValues): void {
74
- if (_changedProperties.has("open")) {
75
- this.dialogElement.then(dialog => {
76
- if (this.open) {
77
- dialog.showModal();
78
- } else {
79
- dialog.close();
80
- }
81
- });
82
- }
101
+ private _handleKeyDown = (e: KeyboardEvent): void => {
102
+ if (!this.closeOnEscape) {
103
+ e.preventDefault();
83
104
  }
84
-
85
- private clickHandler = async (e: PointerEvent): Promise<void> => {
86
- const dialog = await this.dialogElement;
87
- if (!this.dismissable || !this.closeOnOutsideClick) {
88
- return;
89
- }
90
- if (dialog === e.target) {
91
- // clicked on backdrop
92
- this.open = false;
93
- }
94
- };
95
-
96
- private _handleKeyDown = (e: KeyboardEvent): void => {
97
- if (!this.closeOnEscape) {
98
- e.preventDefault()
99
- }
100
- if (this.open && this.closeOnEscape && e.key === 'Escape') {
101
- this.open = false;
102
- }
103
- };
104
-
105
- private _onClose = (e: PointerEvent): void => {
106
- e.preventDefault();
107
- e.stopPropagation();
108
- this.open = false;
109
- this.dispatchEvent(new CustomEvent('close', {
110
- bubbles: true,
111
- composed: true,
112
- }));
113
- };
114
-
115
- protected render(): unknown {
116
- return html`
117
- <dialog class=${this.hideBackdrop ? '' : 'backdrop'} @close=${this._onClose} @click=${this.clickHandler}>
118
- <spectric-panel>
119
- <div class="modal">
120
- ${this.dismissable ? html`<spectric-button variant="text" size="small" @click=${() => { this.open = false }}>X</spectric-button>` : null}
121
- <h3 >
122
- <slot name="title">
123
- ${this.title.length ? this.title : null}
124
- </slot>
125
- </h3>
126
-
127
- <div class="content"><slot></slot></div>
128
- <div class="footer"><slot name="footer"></slot></div>
129
- </div>
130
- </spectric-panel>
131
- </dialog>
132
- `;
105
+ if (this.open && this.closeOnEscape && e.key === "Escape") {
106
+ this.open = false;
133
107
  }
108
+ };
109
+
110
+ private _onClose = (e: PointerEvent): void => {
111
+ e.preventDefault();
112
+ e.stopPropagation();
113
+ this.open = false;
114
+ this.dispatchEvent(
115
+ new CustomEvent("close", {
116
+ bubbles: true,
117
+ composed: true,
118
+ })
119
+ );
120
+ };
121
+
122
+ protected render(): unknown {
123
+ return html`
124
+ <dialog
125
+ class=${this.hideBackdrop ? "" : "backdrop"}
126
+ @close=${this._onClose}
127
+ @click=${this.clickHandler}
128
+ >
129
+ <spectric-panel>
130
+ <div class="modal">
131
+ ${this.dismissable
132
+ ? html`<spectric-button
133
+ variant="text"
134
+ size="small"
135
+ @click=${() => {
136
+ this.open = false;
137
+ }}
138
+ icon
139
+ >X</spectric-button
140
+ >`
141
+ : null}
142
+ <h3>
143
+ <slot name="title">
144
+ ${this.title.length ? this.title : null}
145
+ </slot>
146
+ </h3>
147
+
148
+ <div class="content"><slot></slot></div>
149
+ <div class="footer"><slot name="footer"></slot></div>
150
+ </div>
151
+ </spectric-panel>
152
+ </dialog>
153
+ `;
154
+ }
134
155
  }
135
156
 
136
157
  interface DialogEvents {
137
- 'close': (event: CustomEvent) => void;
158
+ close: (event: CustomEvent) => void;
138
159
  }
139
160
 
140
161
  declare global {
141
- interface HTMLElementTagNameMap {
142
- [DialogElementTag]: HTMLElementTagWithEvents<DialogElement, DialogEvents>
143
-
162
+ interface HTMLElementTagNameMap {
163
+ [DialogElementTag]: HTMLElementTagWithEvents<DialogElement, DialogEvents>;
164
+ }
165
+ namespace JSX {
166
+ interface IntrinsicElements {
167
+ /**
168
+ * @see {@link DialogElement}
169
+ */
170
+ [DialogElementTag]: ReactElementWithPropsAndEvents<
171
+ DialogElement,
172
+ DialogProps,
173
+ DialogEvents
174
+ >;
144
175
  }
176
+ }
177
+ namespace React {
145
178
  namespace JSX {
146
- interface IntrinsicElements {
147
- /**
148
- * @see {@link DialogElement}
149
- */
150
- [DialogElementTag]: ReactElementWithPropsAndEvents<DialogElement, DialogProps, DialogEvents>;
151
- }
152
- }
153
- namespace React {
154
- namespace JSX {
155
- interface IntrinsicElements {
156
- /**
157
- * @see {@link DialogElement}
158
- */
159
- [DialogElementTag]: ReactElementWithPropsAndEvents<DialogElement, DialogProps, DialogEvents>
160
- }
161
- }
179
+ interface IntrinsicElements {
180
+ /**
181
+ * @see {@link DialogElement}
182
+ */
183
+ [DialogElementTag]: ReactElementWithPropsAndEvents<
184
+ DialogElement,
185
+ DialogProps,
186
+ DialogEvents
187
+ >;
188
+ }
162
189
  }
190
+ }
163
191
  }
@@ -11,7 +11,7 @@ import { SpectricButton } from "../Button";
11
11
  import { PopoverElement } from "../tooltip/popover";
12
12
  export type FieldTypes = {
13
13
  name: string;
14
- type: "string" | "number" | "boolean"
14
+ type: "string" | "number" | "boolean" | "integer" | "object"
15
15
  format?: "date-time"
16
16
  }
17
17
  type SuggestionType = 'conjunction' | "field" | 'operator' | 'value'
@@ -76,6 +76,9 @@ const NumberOperators: Record<string, LabelValue> = {
76
76
  "gte": { value: " >= ", label: " is greater than or equal to some value" },
77
77
  "lte": { value: " <= ", label: " is less than or equal to some value" }
78
78
  }
79
+ const ObjectOperators: Record<string, LabelValue> = {
80
+ "exists": { value: ": *", label: " exists in any form" }
81
+ }
79
82
  const StringOperators: Record<string, LabelValue> = {
80
83
  "eq": { value: ": ", label: " equals some value" },
81
84
  "exists": { value: ": *", label: " exists in any form" }
@@ -199,8 +202,10 @@ export class SpectricQuery extends LitElement implements IQueryProps {
199
202
  if (type === "operator") {
200
203
  let fieldType = this.fields.find(field => field.name === suggestion.fieldName);
201
204
  if (fieldType) {
202
- if (fieldType.type === "number") {
205
+ if (["number", "integer"].includes(fieldType.type)) {
203
206
  completions.push(...Object.values(NumberOperators).map(value => ({ type, ...value, start: end, end: end })))
207
+ } else if (fieldType.type === "object") {
208
+ completions.push(...Object.values(ObjectOperators).map(value => ({ type, ...value, start: end, end: end })))
204
209
  } else if (fieldType.type === "string") {
205
210
  if (fieldType.format === "date-time") {
206
211
  completions.push(...Object.values(DateOperators).map(value => ({