@exmg/exm-form 0.0.2-alpha.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.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # `<exm-button>` [![Published on npm](https://img.shields.io/npm/v/@exmg/exm-button.svg)](https://www.npmjs.com/package/@exmg/exm-button)
2
+
3
+ # exm-form
4
+
5
+ The Exmg Form enhances form design by offering a more intuitive layout visualization, streamlining the user experience with several key features. These include:
6
+
7
+ - Automated form validity checks, ensuring data integrity
8
+ - Dynamic submit button control, which enables or disables the button based on form completeness
9
+ - JSON output capability, allowing for easy data serialization and integration
10
+ - A loading spinner, providing a visual indicator for asynchronous form submissions
11
+
12
+ ## Installation
13
+
14
+ ```sh
15
+ npm install @exmg/exm-form
16
+ ```
17
+
18
+ ## Example Usage
19
+
20
+ ### Text
21
+
22
+ ```html
23
+ <exm-form class="has-aside" @dialog-submit="${doFormAction}">
24
+ <div slot="toolbar" class="toolbar"><div class="title">Create contact</div></div>
25
+ <form>
26
+ <div class="row">
27
+ <md-filled-text-field name="firstname" dialogFocus label="First Name" required></md-filled-text-field>
28
+ <md-filled-text-field name="lastname" label="Last Name" required></md-filled-text-field>
29
+ </div>
30
+ <div class="row">
31
+ <md-filled-text-field name="company" label="Company"></md-filled-text-field>
32
+ <md-filled-text-field name="amount" label="Amount" type="number" min="0" max="10"></md-filled-text-field>
33
+ </div>
34
+ <md-filled-text-field
35
+ name="email"
36
+ label="Email"
37
+ pattern="[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,4}$"
38
+ required
39
+ ></md-filled-text-field>
40
+ <md-filled-text-field name="phone" label="Phone" required></md-filled-text-field>
41
+ </form>
42
+ <div slot="aside">
43
+ Ex Machina will send notices about the Data <a href="#">Processing Terms</a> and EU General Data Protection
44
+ Regulation to your primary contact. If your organization has a data protection officer or an EU representative, add
45
+ their contact information.
46
+ </div>
47
+ </exm-form>
48
+ ```
49
+
50
+ ```js
51
+ async function doFormAction(e: CustomEvent<unknown>) {
52
+ const formDialog = e.target as ExmForm;
53
+ try {
54
+ formDialog.submitting = true;
55
+ // Do server call
56
+ // Show success message
57
+ } catch (error) {
58
+ console.error(error instanceof Error ? error.message : 'Unknown error');
59
+ } finally {
60
+ formDialog.submitting = false;
61
+ }
62
+ }
63
+ ```
64
+
65
+ ## API
66
+
67
+ ### Properties/Attributes
68
+
69
+ | Name | Type | Default | Description |
70
+ | ----------------- | --------- | -------- | --------------------------------------------------------- |
71
+ | `submitBtn` | `string` | `Save` | Submit button copy |
72
+ | `cancelBtn` | `string` | `Cancel` | Cancel button copy |
73
+ | `submitting` | `boolean` | false | Indicated form submit in progress and disables the button |
74
+ | `hasAsideContent` | `boolean` | false | Indicated if form has a side help section |
75
+
76
+ For other options see the m3 docs:
77
+
78
+ - [Material 3 Button Docs](https://github.com/material-components/material-web/blob/main/docs/components/button.md)
79
+
80
+ ## Additional references
81
+
82
+ - [Demo / Docs](https://exmg.github.io/exmachina-web-components/demo/?el=exm-button)
@@ -0,0 +1,43 @@
1
+ import '@exmg/exm-button/exm-text-button.js';
2
+ import '@material/web/button/text-button.js';
3
+ import '@material/web/divider/divider.js';
4
+ import { ExmgElement } from '@exmg/lit-base';
5
+ export declare const CLOSE_ACTION = "close";
6
+ export declare const serializeForm: (form: any) => {};
7
+ declare const ExmFormBase_base: import("./exm-form-validate-mixin.js").Constructor<import("./exm-form-validate-mixin.js").FormValidateMixinInterface> & typeof ExmgElement;
8
+ export declare class ExmFormBase extends ExmFormBase_base {
9
+ /**
10
+ * Submit button copy
11
+ */
12
+ submitBtn: string;
13
+ /**
14
+ * Cancel button copy
15
+ */
16
+ cancelBtn: string;
17
+ /**
18
+ * Internall used to show button spinner.
19
+ */
20
+ submitting: boolean;
21
+ boundHandleBlur?: (e: Event) => void;
22
+ boundHandleKeyup?: (e: Event) => void;
23
+ hasAsideContent: boolean;
24
+ errorMessage?: string | null;
25
+ reset(): void;
26
+ submit(): void;
27
+ /**
28
+ * Action method that needs to be implemented
29
+ * @param {CustomEvent} e
30
+ */
31
+ doAction?(formData: unknown): Promise<void> | void;
32
+ protected handleSubmit(): Promise<void>;
33
+ showError(message: string): void;
34
+ protected renderToolbar(): import("lit-html").TemplateResult<1>;
35
+ protected renderFormContent(): import("lit-html").TemplateResult<1>;
36
+ protected renderAside(): import("lit-html").TemplateResult<1>;
37
+ handleAsideSlotChange(e: CustomEvent): void;
38
+ protected renderError(): import("lit-html").TemplateResult<1>;
39
+ protected renderActions(): import("lit-html").TemplateResult<1>;
40
+ protected renderContainer(): import("lit-html").TemplateResult<1>;
41
+ protected render(): import("lit-html").TemplateResult<1>;
42
+ }
43
+ export {};
@@ -0,0 +1,194 @@
1
+ import { __decorate } from "tslib";
2
+ import { html, nothing } from 'lit';
3
+ import { property } from 'lit/decorators.js';
4
+ import '@exmg/exm-button/exm-text-button.js';
5
+ import '@material/web/button/text-button.js';
6
+ import '@material/web/divider/divider.js';
7
+ import { ExmgElement } from '@exmg/lit-base';
8
+ import { classMap } from 'lit/directives/class-map.js';
9
+ import { ExmFormValidateMixin } from './exm-form-validate-mixin.js';
10
+ export const CLOSE_ACTION = 'close';
11
+ export const serializeForm = (form) => {
12
+ const obj = {};
13
+ const formElements = form === null || form === void 0 ? void 0 : form.elements;
14
+ const formElementsArray = Array.from(formElements);
15
+ /**
16
+ * Create list of checkbox elements. If no value is set the return value of the checkbox for 'on' will be a boolean
17
+ */
18
+ const checkboxNames = formElementsArray
19
+ .filter((input) => {
20
+ return input.value === 'on' && (input.type === 'checkbox' || input.tagName.toLowerCase().includes('checkbox'));
21
+ })
22
+ .map((input) => input.name);
23
+ /* Same for the radio items */
24
+ const radioNames = formElementsArray
25
+ .filter((input) => {
26
+ return input.type === 'radio' || input.tagName.toLowerCase().includes('radio');
27
+ })
28
+ .map((input) => input.name);
29
+ const numberNames = formElementsArray
30
+ .filter((input) => {
31
+ return input.type === 'number';
32
+ })
33
+ .map((input) => input.name);
34
+ const formData = new FormData(form);
35
+ for (const pair of formData.entries()) {
36
+ const key = pair[0];
37
+ const val = pair[1];
38
+ if (Object.hasOwnProperty.call(obj, key)) {
39
+ if (!Array.isArray(obj[key])) {
40
+ obj[key] = [obj[key]];
41
+ }
42
+ obj[key].push(val);
43
+ continue;
44
+ }
45
+ if (numberNames.includes(key)) {
46
+ obj[key] = val ? parseFloat(`${val}`) : undefined;
47
+ continue;
48
+ }
49
+ // When set to on convert to boolean return value
50
+ // @ts-ignore
51
+ if (checkboxNames.includes(key)) {
52
+ obj[key] = val === 'on';
53
+ continue;
54
+ }
55
+ // Check for a default value of on for radio items to set to true, if not, set to the value
56
+ if (radioNames.includes(key)) {
57
+ if (val === 'on') {
58
+ obj[key] = val === 'on';
59
+ }
60
+ else {
61
+ obj[key] = val;
62
+ }
63
+ continue;
64
+ }
65
+ obj[key] = formData.get(key);
66
+ }
67
+ // All checkboxes that are not checked will not be included in the form data and need to return false
68
+ for (const name of checkboxNames) {
69
+ // check for
70
+ if (!Object.hasOwnProperty.call(obj, name)) {
71
+ obj[name] = false;
72
+ }
73
+ }
74
+ return obj;
75
+ };
76
+ export class ExmFormBase extends ExmFormValidateMixin(ExmgElement) {
77
+ constructor() {
78
+ super(...arguments);
79
+ /**
80
+ * Submit button copy
81
+ */
82
+ this.submitBtn = 'Save';
83
+ /**
84
+ * Cancel button copy
85
+ */
86
+ this.cancelBtn = 'Cancel';
87
+ /**
88
+ * Internall used to show button spinner.
89
+ */
90
+ this.submitting = false;
91
+ this.hasAsideContent = false;
92
+ }
93
+ reset() {
94
+ const form = this.getForm();
95
+ form === null || form === void 0 ? void 0 : form.reset();
96
+ }
97
+ submit() {
98
+ this.handleSubmit();
99
+ }
100
+ async handleSubmit() {
101
+ this.errorMessage = null;
102
+ const form = this.getForm();
103
+ // Check form validity
104
+ this.checkFormValidity();
105
+ // Return when there are invalid fields
106
+ if (!this.formValid) {
107
+ return;
108
+ }
109
+ // Serialize form data
110
+ const data = serializeForm(form);
111
+ if (this.doAction) {
112
+ try {
113
+ this.submitting = true;
114
+ await this.doAction(data);
115
+ }
116
+ catch (error) {
117
+ this.showError(error instanceof Error ? error.message : 'Unknown error');
118
+ this.fire('form-error', { message: error instanceof Error ? error.message : 'Unknown error' }, true);
119
+ }
120
+ finally {
121
+ this.submitting = false;
122
+ }
123
+ }
124
+ else {
125
+ this.fire('form-submit', data, true);
126
+ }
127
+ }
128
+ showError(message) {
129
+ this.errorMessage = message;
130
+ }
131
+ renderToolbar() {
132
+ return html `<div class="toolbar-container"><slot name="toolbar"></slot></div>`;
133
+ }
134
+ renderFormContent() {
135
+ return html `<slot></slot>`;
136
+ }
137
+ renderAside() {
138
+ return html `<slot name="aside" @slotchange="${this.handleAsideSlotChange}"></slot>`;
139
+ }
140
+ handleAsideSlotChange(e) {
141
+ const slot = e.target;
142
+ // @ts-ignore
143
+ const nodes = slot.assignedNodes({ flatten: true });
144
+ this.hasAsideContent = nodes.length > 0;
145
+ }
146
+ renderError() {
147
+ return html `<div class="form-error"><div>${this.errorMessage}</div></div>`;
148
+ }
149
+ renderActions() {
150
+ return html `
151
+ <div class="actions">
152
+ <md-text-button slot="footer" dialogFocus @click=${() => this.fire('form-cancel')}
153
+ >${this.cancelBtn}</md-text-button
154
+ >
155
+ <exm-text-button
156
+ slot="footer"
157
+ @click=${this.handleSubmit}
158
+ ?disabled=${this.submitting || !this.formValid}
159
+ ?loading=${this.submitting}
160
+ >${this.submitBtn}</exm-text-button
161
+ >
162
+ </div>
163
+ `;
164
+ }
165
+ renderContainer() {
166
+ return html ` <div class="container">
167
+ <div class="content">${this.renderFormContent()}</div>
168
+ <div class="aside ${classMap({ empty: !this.hasAsideContent })}">${this.renderAside()}</div>
169
+ </div>`;
170
+ }
171
+ render() {
172
+ return html `
173
+ ${this.renderToolbar()} ${this.errorMessage ? this.renderError() : nothing} ${this.renderContainer()}
174
+ <div class="divider"><md-divider></md-divider></div>
175
+ ${this.renderActions()}
176
+ `;
177
+ }
178
+ }
179
+ __decorate([
180
+ property({ type: String })
181
+ ], ExmFormBase.prototype, "submitBtn", void 0);
182
+ __decorate([
183
+ property({ type: String })
184
+ ], ExmFormBase.prototype, "cancelBtn", void 0);
185
+ __decorate([
186
+ property({ type: Boolean })
187
+ ], ExmFormBase.prototype, "submitting", void 0);
188
+ __decorate([
189
+ property({ type: Boolean })
190
+ ], ExmFormBase.prototype, "hasAsideContent", void 0);
191
+ __decorate([
192
+ property({ type: String })
193
+ ], ExmFormBase.prototype, "errorMessage", void 0);
194
+ //# sourceMappingURL=exm-form-base.js.map
@@ -0,0 +1,10 @@
1
+ import { LitElement } from 'lit';
2
+ export type Constructor<T> = new (...args: any[]) => T;
3
+ export declare abstract class FormValidateMixinClass extends LitElement {
4
+ }
5
+ export declare class FormValidateMixinInterface {
6
+ formValid: boolean;
7
+ getForm(): HTMLFormElement | null;
8
+ checkFormValidity(): void;
9
+ }
10
+ export declare const ExmFormValidateMixin: <T extends Constructor<LitElement & FormValidateMixinClass>>(superClass: T) => Constructor<FormValidateMixinInterface> & T;
@@ -0,0 +1,60 @@
1
+ import { __decorate } from "tslib";
2
+ import { LitElement } from 'lit';
3
+ import { async, debounce } from '@exmg/lit-base/index.js';
4
+ import { state } from 'lit/decorators.js';
5
+ export class FormValidateMixinClass extends LitElement {
6
+ }
7
+ export const ExmFormValidateMixin = (superClass) => {
8
+ class FormvalidateMixinElement extends superClass {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.formValid = false;
12
+ }
13
+ getForm() {
14
+ return this.shadowRoot.querySelector('form');
15
+ }
16
+ checkFormValidity() {
17
+ const form = this.getForm();
18
+ const formElements = form === null || form === void 0 ? void 0 : form.elements;
19
+ let allValid = true;
20
+ for (const el of formElements || []) {
21
+ let isValid = true;
22
+ // @ts-ignore
23
+ if (typeof el.reportValidity === 'function') {
24
+ // @ts-ignore
25
+ isValid = el.checkValidity();
26
+ }
27
+ if (!isValid) {
28
+ allValid = false;
29
+ }
30
+ }
31
+ this.formValid = allValid;
32
+ }
33
+ _handleInputChange(e) {
34
+ const target = e.target;
35
+ // Only check validation every 200ms max
36
+ this._debouncer = debounce.Debouncer.debounce(this._debouncer, async.timeOut.after(200), () => {
37
+ // @ts-ignore
38
+ typeof target.reportValidity === 'function' && target.reportValidity();
39
+ this.checkFormValidity();
40
+ });
41
+ }
42
+ firstUpdated() {
43
+ const form = this.getForm();
44
+ this.boundHandleChange = this._handleInputChange.bind(this);
45
+ form.addEventListener('keyup', this.boundHandleChange, true);
46
+ form.addEventListener('input', this.boundHandleChange, true);
47
+ }
48
+ disconnectedCallback() {
49
+ const form = this.getForm();
50
+ this.boundHandleChange && form.addEventListener('keyup', this.boundHandleChange, true);
51
+ this.boundHandleChange && form.addEventListener('input', this.boundHandleChange, true);
52
+ super.disconnectedCallback();
53
+ }
54
+ }
55
+ __decorate([
56
+ state()
57
+ ], FormvalidateMixinElement.prototype, "formValid", void 0);
58
+ return FormvalidateMixinElement;
59
+ };
60
+ //# sourceMappingURL=exm-form-validate-mixin.js.map
@@ -0,0 +1,10 @@
1
+ import { ExmFormBase } from './exm-form-base.js';
2
+ export declare class ExmForm extends ExmFormBase {
3
+ static styles: import("lit").CSSResult[];
4
+ getForm(): HTMLFormElement | null;
5
+ }
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ 'exm-form': ExmForm;
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement } from 'lit/decorators.js';
3
+ import { style } from './styles/exm-form-base-css.js';
4
+ import { ExmFormBase } from './exm-form-base.js';
5
+ let ExmForm = class ExmForm extends ExmFormBase {
6
+ getForm() {
7
+ return this.querySelector('form');
8
+ }
9
+ };
10
+ ExmForm.styles = [style];
11
+ ExmForm = __decorate([
12
+ customElement('exm-form')
13
+ ], ExmForm);
14
+ export { ExmForm };
15
+ //# sourceMappingURL=exm-form.js.map
@@ -0,0 +1,5 @@
1
+ export { ExmForm } from './exm-form.js';
2
+ export { ExmFormValidateMixin, Constructor } from './exm-form-validate-mixin.js';
3
+ export { ExmFormBase, serializeForm } from './exm-form-base.js';
4
+ export { style as formStyles } from './styles/exm-form-css.js';
5
+ export { style as formBaseStyles } from './styles/exm-form-base-css.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { ExmForm } from './exm-form.js';
2
+ export { ExmFormValidateMixin } from './exm-form-validate-mixin.js';
3
+ export { ExmFormBase, serializeForm } from './exm-form-base.js';
4
+ export { style as formStyles } from './styles/exm-form-css.js';
5
+ export { style as formBaseStyles } from './styles/exm-form-base-css.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export declare const style: import("lit").CSSResult;
@@ -0,0 +1,81 @@
1
+ import { css } from 'lit';
2
+ export const style = css `
3
+ :host {
4
+ display: block;
5
+ --_exm-form-content-margin-left: var(--exm-form-content-margin-left, 0);
6
+ --_exm-form-container-margin-top: var(--exm-form-container-margin-top, 1rem);
7
+ --_exm-form-container-margin-bottom: var(--exm-form-container-margin-bottom, 1rem);
8
+ --_exm-form-divider-margin-top: var(--exm-form-divider-margin-top, 2rem);
9
+ --_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);
10
+ --_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);
11
+ --_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);
12
+ --_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);
13
+ --_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);
14
+ --_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);
15
+ --_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px);
16
+ }
17
+
18
+ .aside {
19
+ line-height: var(--_exm-form-aside-line-height);
20
+ font-size: var(--_exm-form-aside-font-size);
21
+ letter-spacing: var(--_exm-form-aside-letter-spacing);
22
+ font-weight: var(--_exm-form-aside-font-weight);
23
+ color: var(--_exm-form-aside-color, var(--md-sys-color-on-surface));
24
+ border-left: 1px solid var(--md-sys-color-outline-variant);
25
+ box-sizing: border-box;
26
+ margin-left: var(--_exm-form-aside-margin-left);
27
+ margin-right: var(--_exm-form-aside-margin-right);
28
+ min-height: 2rem;
29
+ padding-left: 1rem;
30
+ vertical-align: top;
31
+ height: 100%;
32
+ min-width: var(--_exm-form-aside-min-width);
33
+ flex: 0;
34
+ }
35
+
36
+ .aside.empty {
37
+ display: none;
38
+ }
39
+
40
+ .content,
41
+ .container {
42
+ display: flex;
43
+ }
44
+
45
+ .content {
46
+ flex: 1;
47
+ }
48
+
49
+ .container {
50
+ margin-top: var(--_exm-form-container-margin-top);
51
+ margin-bottom: var(--_exm-form-container-margin-bottom);
52
+ }
53
+
54
+ .actions {
55
+ display: flex;
56
+ padding: 8px 4px;
57
+ justify-content: flex-end;
58
+ }
59
+
60
+ .actions > * {
61
+ margin-right: 8px;
62
+ }
63
+
64
+ .divider {
65
+ margin-top: var(--_exm-form-divider-margin-top);
66
+ }
67
+
68
+ .content {
69
+ margin-left: var(--_exm-form-content-margin-left);
70
+ }
71
+
72
+ .form-error {
73
+ background-color: var(--_exm-form-error-background, var(--md-sys-color-error-container, red));
74
+ color: var(--_exm-form-error-color, var(--md-sys-color-on-error-container, white));
75
+ }
76
+
77
+ .form-error > div {
78
+ padding: 1rem;
79
+ }
80
+ `;
81
+ //# sourceMappingURL=exm-form-base-css.js.map
@@ -0,0 +1 @@
1
+ export declare const style: import("lit").CSSResult;
@@ -0,0 +1,113 @@
1
+ import { css } from 'lit';
2
+ export const style = css `
3
+ .section-title {
4
+ line-height: 1.5rem;
5
+ font-size: 1rem;
6
+ letter-spacing: 0.00625em;
7
+ font-weight: 500;
8
+ color: var(--_exm-form-title-color, var(--md-sys-color-on-surface));
9
+ padding-bottom: 8px;
10
+ }
11
+
12
+ .aside {
13
+ --_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);
14
+ --_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);
15
+ --_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);
16
+ --_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);
17
+ --_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);
18
+ --_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);
19
+ --_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px);
20
+ line-height: var(--_exm-form-aside-line-height);
21
+ font-size: var(--_exm-form-aside-font-size);
22
+ letter-spacing: var(--_exm-form-aside-letter-spacing);
23
+ font-weight: var(--_exm-form-aside-font-weight);
24
+ color: var(--md-sys-color-on-surface);
25
+ border-left: 1px solid var(--md-sys-color-outline-variant);
26
+ box-sizing: border-box;
27
+ margin-left: var(--_exm-form-aside-margin-left);
28
+ margin-right: var(--_exm-form-aside-margin-right);
29
+ min-height: 2rem;
30
+ padding-left: 1rem;
31
+ vertical-align: top;
32
+ height: 100%;
33
+ min-width: var(--_exm-form-aside-min-width);
34
+ flex: 0;
35
+ }
36
+
37
+ form {
38
+ margin: 0 1rem;
39
+ width: 100%;
40
+ }
41
+
42
+ form .row {
43
+ display: flex;
44
+ gap: 6px;
45
+ height: 76px;
46
+ align-items: flex-start;
47
+ }
48
+
49
+ form .row > * {
50
+ flex: 1;
51
+ height: fit-content;
52
+ }
53
+
54
+ form {
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 12px;
58
+ margin-top: 0.5rem;
59
+ }
60
+
61
+ form > * {
62
+ display: contents;
63
+ }
64
+
65
+ .actions > * {
66
+ margin-right: 8px;
67
+ }
68
+
69
+ .no-flex {
70
+ display: block;
71
+ }
72
+
73
+ .extra-margin {
74
+ margin-top: 2rem;
75
+ display: block;
76
+ }
77
+
78
+ label.checkbox {
79
+ display: flex;
80
+ justify-content: flex-start;
81
+ align-items: center;
82
+ font-size: 1rem;
83
+ font-weight: 500;
84
+ margin: 0.5rem 1rem;
85
+ }
86
+
87
+ label.checkbox md-checkbox {
88
+ margin-right: 1rem;
89
+ }
90
+
91
+ .toolbar {
92
+ display: flex;
93
+ align-items: center;
94
+ padding: 8px 4px 8px 16px;
95
+ height: 56px;
96
+ box-sizing: border-box;
97
+ }
98
+
99
+ .toolbar .title {
100
+ line-height: 1.5rem;
101
+ font-size: 1rem;
102
+ letter-spacing: 0.00625em;
103
+ font-weight: 500;
104
+ color: var(--md-sys-color-on-surface);
105
+ box-sizing: border-box;
106
+ overflow-wrap: break-word;
107
+ }
108
+
109
+ a {
110
+ color: var(--md-sys-color-primary);
111
+ }
112
+ `;
113
+ //# sourceMappingURL=exm-form-css.js.map
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@exmg/exm-form",
3
+ "version": "0.0.2-alpha.0+df24e0c",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "module": "dist/index.js",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./exm-form.js": "./dist/exm-form.js",
11
+ "./exm-form-validate-mixin.js": "./dist/exm-form-validate-mixin.js"
12
+ },
13
+ "description": "Form element",
14
+ "contributors": [
15
+ "Ex Machina"
16
+ ],
17
+ "keywords": [
18
+ "web-components",
19
+ "lit",
20
+ "form"
21
+ ],
22
+ "files": [
23
+ "**/*.scss",
24
+ "**/*.js",
25
+ "**/*.d.ts"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git@bitbucket.org:exmachina/exm-web-components.git",
30
+ "directory": "packages/exm-form"
31
+ },
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@exmg/exm-button": "^0.0.2-alpha.0+df24e0c"
35
+ },
36
+ "peerDependencies": {
37
+ "lit": "^3.2.1",
38
+ "tslib": "^2.6.2"
39
+ },
40
+ "scripts": {},
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "gitHead": "df24e0c74a76a7e1c258f69386036e24e7860256"
45
+ }