@exmg/exm-form 1.0.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 ExmgForm;
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)
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { ExmgForm } from './src/exm-form.js';
2
+ export { ExmgFormBase, serializeForm } from './src/exm-form-base.js';
3
+ export { style as exmgFormStyles } from './src/styles/exm-form-css.js';
4
+ export { style as exmgFormBaseStyles } from './src/styles/exm-form-base-css.js';
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { ExmgForm } from './src/exm-form.js';
2
+ export { ExmgFormBase, serializeForm } from './src/exm-form-base.js';
3
+ export { style as exmgFormStyles } from './src/styles/exm-form-css.js';
4
+ export { style as exmgFormBaseStyles } from './src/styles/exm-form-base-css.js';
5
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@exmg/exm-form",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "index.js",
6
+ "module": "index.js",
7
+ "exports": {
8
+ ".": "./index.js",
9
+ "./exm-form.js": "./src/exm-form.js"
10
+ },
11
+ "description": "Form element",
12
+ "contributors": [
13
+ "Ex Machina"
14
+ ],
15
+ "keywords": [
16
+ "web-components",
17
+ "lit",
18
+ "form"
19
+ ],
20
+ "files": [
21
+ "**/*.scss",
22
+ "**/*.js",
23
+ "**/*.d.ts"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git@github.com:exmg/exm-web-components.git",
28
+ "directory": "packages/exm-form"
29
+ },
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@exmg/exm-button": "^1.0.0",
33
+ "@material/typography": "^14.0.0",
34
+ "lit": "^3.0.0",
35
+ "tslib": "^2.6.2"
36
+ },
37
+ "devDependencies": {
38
+ "@exmg/lit-cli": "1.1.13"
39
+ },
40
+ "scripts": {
41
+ "build:styles": "exmg-lit-cli sass -f \"./**/*.scss\""
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "gitHead": "0907b55c89325d59902b98a64c352bf6e1fc81ff"
47
+ }
@@ -0,0 +1,48 @@
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
+ export declare class ExmgFormBase extends ExmgElement {
8
+ /**
9
+ * Submit button copy
10
+ */
11
+ submitBtn: string;
12
+ /**
13
+ * Cancel button copy
14
+ */
15
+ cancelBtn: string;
16
+ /**
17
+ * Internall used to show button spinner.
18
+ */
19
+ submitting: boolean;
20
+ formValid: boolean;
21
+ boundHandleBlur?: (e: Event) => void;
22
+ boundHandleKeyup?: (e: Event) => void;
23
+ hasAsideContent: boolean;
24
+ errorMessage?: string | null;
25
+ protected getForm(): HTMLFormElement | null;
26
+ reset(): void;
27
+ submit(): void;
28
+ protected _handleKeyup(): void;
29
+ protected _handleBlur(e: Event): void;
30
+ protected firstUpdated(): Promise<void>;
31
+ disconnectedCallback(): void;
32
+ protected _checkFormValidity(): void;
33
+ /**
34
+ * Action method that needs to be implemented
35
+ * @param {CustomEvent} e
36
+ */
37
+ doAction?(formData: unknown): Promise<void> | void;
38
+ protected handleSubmit(): Promise<void>;
39
+ showError(message: string): void;
40
+ protected renderToolbar(): import("lit-html").TemplateResult<1>;
41
+ protected renderFormContent(): import("lit-html").TemplateResult<1>;
42
+ protected renderAside(): import("lit-html").TemplateResult<1>;
43
+ handleAsideSlotChange(e: CustomEvent): void;
44
+ protected renderError(): import("lit-html").TemplateResult<1>;
45
+ protected renderActions(): import("lit-html").TemplateResult<1>;
46
+ protected renderContainer(): import("lit-html").TemplateResult<1>;
47
+ protected render(): import("lit-html").TemplateResult<1>;
48
+ }
@@ -0,0 +1,239 @@
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
+ export const CLOSE_ACTION = 'close';
10
+ export const serializeForm = (form) => {
11
+ const obj = {};
12
+ const formElements = form === null || form === void 0 ? void 0 : form.elements;
13
+ const formElementsArray = Array.from(formElements);
14
+ /**
15
+ * Create list of checkbox elements. If no value is set the return value of the checkbox for 'on' will be a boolean
16
+ */
17
+ const checkboxNames = formElementsArray
18
+ .filter((input) => {
19
+ return input.value === 'on' && (input.type === 'checkbox' || input.tagName.toLowerCase().includes('checkbox'));
20
+ })
21
+ .map((input) => input.name);
22
+ /* Same for the radio items */
23
+ const radioNames = formElementsArray
24
+ .filter((input) => {
25
+ return input.type === 'radio' || input.tagName.toLowerCase().includes('radio');
26
+ })
27
+ .map((input) => input.name);
28
+ const numberNames = formElementsArray
29
+ .filter((input) => {
30
+ return input.type === 'number';
31
+ })
32
+ .map((input) => input.name);
33
+ const formData = new FormData(form);
34
+ for (const pair of formData.entries()) {
35
+ const key = pair[0];
36
+ const val = pair[1];
37
+ if (Object.hasOwnProperty.call(obj, key)) {
38
+ if (!Array.isArray(obj[key])) {
39
+ obj[key] = [obj[key]];
40
+ }
41
+ obj[key].push(val);
42
+ continue;
43
+ }
44
+ if (numberNames.includes(key)) {
45
+ obj[key] = val ? parseFloat(`${val}`) : undefined;
46
+ continue;
47
+ }
48
+ // When set to on convert to boolean return value
49
+ // @ts-ignore
50
+ if (checkboxNames.includes(key)) {
51
+ obj[key] = val === 'on';
52
+ continue;
53
+ }
54
+ // Check for a default value of on for radio items to set to true, if not, set to the value
55
+ if (radioNames.includes(key)) {
56
+ if (val === 'on') {
57
+ obj[key] = val === 'on';
58
+ }
59
+ else {
60
+ obj[key] = val;
61
+ }
62
+ continue;
63
+ }
64
+ obj[key] = formData.get(key);
65
+ }
66
+ // All checkboxes that are not checked will not be included in the form data and need to return false
67
+ for (const name of checkboxNames) {
68
+ // check for
69
+ if (!Object.hasOwnProperty.call(obj, name)) {
70
+ obj[name] = false;
71
+ }
72
+ }
73
+ return obj;
74
+ };
75
+ export class ExmgFormBase extends ExmgElement {
76
+ constructor() {
77
+ super(...arguments);
78
+ /**
79
+ * Submit button copy
80
+ */
81
+ this.submitBtn = 'Save';
82
+ /**
83
+ * Cancel button copy
84
+ */
85
+ this.cancelBtn = 'Cancel';
86
+ /**
87
+ * Internall used to show button spinner.
88
+ */
89
+ this.submitting = false;
90
+ this.formValid = false;
91
+ this.hasAsideContent = false;
92
+ }
93
+ getForm() {
94
+ return this.shadowRoot.querySelector('form');
95
+ }
96
+ reset() {
97
+ const form = this.getForm();
98
+ form === null || form === void 0 ? void 0 : form.reset();
99
+ }
100
+ submit() {
101
+ this.handleSubmit();
102
+ }
103
+ _handleKeyup() {
104
+ this._checkFormValidity();
105
+ }
106
+ _handleBlur(e) {
107
+ // @ts-ignore
108
+ typeof e.target.reportValidity === 'function' && e.target.reportValidity();
109
+ this._checkFormValidity();
110
+ }
111
+ async firstUpdated() {
112
+ const form = this.getForm();
113
+ this.boundHandleBlur = this._handleBlur.bind(this);
114
+ form.addEventListener('blur', this.boundHandleBlur, true);
115
+ this.boundHandleKeyup = this._handleKeyup.bind(this);
116
+ form.addEventListener('keyup', this.boundHandleKeyup, true);
117
+ await this.updateComplete;
118
+ this._checkFormValidity();
119
+ }
120
+ disconnectedCallback() {
121
+ const form = this.getForm();
122
+ this.boundHandleBlur && form.removeEventListener('blur', this.boundHandleBlur, true);
123
+ this.boundHandleKeyup && form.removeEventListener('keyup', this.boundHandleKeyup, true);
124
+ super.disconnectedCallback();
125
+ }
126
+ _checkFormValidity() {
127
+ const form = this.getForm();
128
+ const formElements = form === null || form === void 0 ? void 0 : form.elements;
129
+ let allValid = true;
130
+ for (const el of formElements || []) {
131
+ // @ts-ignore
132
+ if (typeof el.reportValidity !== 'function')
133
+ continue;
134
+ // @ts-ignore
135
+ const isValid = el.checkValidity();
136
+ if (!isValid) {
137
+ allValid = false;
138
+ }
139
+ }
140
+ this.formValid = allValid;
141
+ }
142
+ async handleSubmit() {
143
+ this.errorMessage = null;
144
+ const form = this.getForm();
145
+ // Check form validity
146
+ this._checkFormValidity();
147
+ // Return when there are invalid fields
148
+ if (!this.formValid) {
149
+ return;
150
+ }
151
+ // Serialize form data
152
+ const data = serializeForm(form);
153
+ if (this.doAction) {
154
+ try {
155
+ this.submitting = true;
156
+ await this.doAction(data);
157
+ }
158
+ catch (error) {
159
+ this.showError(error instanceof Error ? error.message : 'Unknown error');
160
+ this.fire('form-error', { message: error instanceof Error ? error.message : 'Unknown error' }, true);
161
+ }
162
+ finally {
163
+ this.submitting = false;
164
+ }
165
+ }
166
+ else {
167
+ this.fire('form-submit', data, true);
168
+ }
169
+ }
170
+ showError(message) {
171
+ this.errorMessage = message;
172
+ }
173
+ renderToolbar() {
174
+ return html `<div class="toolbar-container"><slot name="toolbar"></slot></div>`;
175
+ }
176
+ renderFormContent() {
177
+ return html `<slot></slot>`;
178
+ }
179
+ renderAside() {
180
+ return html `<slot name="aside" @slotchange="${this.handleAsideSlotChange}"></slot>`;
181
+ }
182
+ handleAsideSlotChange(e) {
183
+ const slot = e.target;
184
+ // @ts-ignore
185
+ const nodes = slot.assignedNodes({ flatten: true });
186
+ this.hasAsideContent = nodes.length > 0;
187
+ }
188
+ renderError() {
189
+ return html `<div class="form-error"><div>${this.errorMessage}</div></div>`;
190
+ }
191
+ renderActions() {
192
+ return html `
193
+ <div class="actions">
194
+ <md-text-button slot="footer" dialogFocus @click=${() => this.fire('form-cancel')}
195
+ >${this.cancelBtn}</md-text-button
196
+ >
197
+ <exm-text-button
198
+ slot="footer"
199
+ @click=${this.handleSubmit}
200
+ ?disabled=${this.submitting || !this.formValid}
201
+ ?loading=${this.submitting}
202
+ >${this.submitBtn}</exm-text-button
203
+ >
204
+ </div>
205
+ `;
206
+ }
207
+ renderContainer() {
208
+ return html ` <div class="container">
209
+ <div class="content">${this.renderFormContent()}</div>
210
+ <div class="aside ${classMap({ empty: !this.hasAsideContent })}">${this.renderAside()}</div>
211
+ </div>`;
212
+ }
213
+ render() {
214
+ return html `
215
+ ${this.renderToolbar()} ${this.errorMessage ? this.renderError() : nothing} ${this.renderContainer()}
216
+ <div class="divider"><md-divider></md-divider></div>
217
+ ${this.renderActions()}
218
+ `;
219
+ }
220
+ }
221
+ __decorate([
222
+ property({ type: String })
223
+ ], ExmgFormBase.prototype, "submitBtn", void 0);
224
+ __decorate([
225
+ property({ type: String })
226
+ ], ExmgFormBase.prototype, "cancelBtn", void 0);
227
+ __decorate([
228
+ property({ type: Boolean })
229
+ ], ExmgFormBase.prototype, "submitting", void 0);
230
+ __decorate([
231
+ property({ type: Boolean })
232
+ ], ExmgFormBase.prototype, "formValid", void 0);
233
+ __decorate([
234
+ property({ type: Boolean })
235
+ ], ExmgFormBase.prototype, "hasAsideContent", void 0);
236
+ __decorate([
237
+ property({ type: String })
238
+ ], ExmgFormBase.prototype, "errorMessage", void 0);
239
+ //# sourceMappingURL=exm-form-base.js.map
@@ -0,0 +1,10 @@
1
+ import { ExmgFormBase } from './exm-form-base.js';
2
+ export declare class ExmgForm extends ExmgFormBase {
3
+ static styles: import("lit").CSSResult[];
4
+ getForm(): HTMLFormElement | null;
5
+ }
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ 'exm-form': ExmgForm;
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 { ExmgFormBase } from './exm-form-base.js';
5
+ let ExmgForm = class ExmgForm extends ExmgFormBase {
6
+ getForm() {
7
+ return this.querySelector('form');
8
+ }
9
+ };
10
+ ExmgForm.styles = [style];
11
+ ExmgForm = __decorate([
12
+ customElement('exm-form')
13
+ ], ExmgForm);
14
+ export { ExmgForm };
15
+ //# sourceMappingURL=exm-form.js.map
@@ -0,0 +1,2 @@
1
+ export declare const style: import("lit").CSSResult;
2
+ export default style;
@@ -0,0 +1,4 @@
1
+ import { css } from 'lit';
2
+ export const style = css `:host{display:block;--_exm-form-content-margin-left: var(--exm-form-content-margin-left, 0);--_exm-form-container-margin-top: var(--exm-form-container-margin-top, 1rem);--_exm-form-container-margin-bottom: var(--exm-form-container-margin-bottom, 1rem);--_exm-form-divider-margin-top: var(--exm-form-divider-margin-top, 2rem);--_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);--_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);--_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);--_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);--_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);--_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);--_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px)}.aside{line-height:var(--_exm-form-aside-line-height);font-size:var(--_exm-form-aside-font-size);letter-spacing:var(--_exm-form-aside-letter-spacing);font-weight:var(--_exm-form-aside-font-weight);color:var(--_exm-form-aside-color, var(--md-sys-color-on-surface));border-left:1px solid var(--md-sys-color-outline-variant);box-sizing:border-box;margin-left:var(--_exm-form-aside-margin-left);margin-right:var(--_exm-form-aside-margin-right);min-height:2rem;padding-left:1rem;vertical-align:top;height:100%;min-width:var(--_exm-form-aside-min-width);flex:0}.aside.empty{display:none}.content,.container{display:flex}.content{flex:1}.container{margin-top:var(--_exm-form-container-margin-top);margin-bottom:var(--_exm-form-container-margin-bottom)}.actions{display:flex;padding:8px 4px;justify-content:flex-end}.actions>*{margin-right:8px}.divider{margin-top:var(--_exm-form-divider-margin-top)}.content{margin-left:var(--_exm-form-content-margin-left)}.form-error{background-color:var(--_exm-form-error-background, var(--md-sys-color-error-container, red));color:var(--_exm-form-error-color, var(--md-sys-color-on-error-container, white))}.form-error>div{padding:1rem}`;
3
+ export default style;
4
+ //# sourceMappingURL=exm-form-base-css.js.map
@@ -0,0 +1,79 @@
1
+ :host {
2
+ display: block;
3
+
4
+ --_exm-form-content-margin-left: var(--exm-form-content-margin-left, 0);
5
+ --_exm-form-container-margin-top: var(--exm-form-container-margin-top, 1rem);
6
+ --_exm-form-container-margin-bottom: var(--exm-form-container-margin-bottom, 1rem);
7
+ --_exm-form-divider-margin-top: var(--exm-form-divider-margin-top, 2rem);
8
+
9
+ // Aside
10
+ --_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);
11
+ --_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);
12
+ --_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);
13
+ --_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);
14
+ --_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);
15
+ --_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);
16
+ --_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px);
17
+ }
18
+
19
+ .aside {
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(--_exm-form-aside-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
+ .aside.empty {
38
+ display: none;
39
+ }
40
+
41
+ .content,
42
+ .container {
43
+ display: flex;
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
+ }
@@ -0,0 +1,2 @@
1
+ export declare const style: import("lit").CSSResult;
2
+ export default style;
@@ -0,0 +1,4 @@
1
+ import { css } from 'lit';
2
+ export const style = css `.section-title{line-height:1.5rem;font-size:1rem;letter-spacing:.00625em;font-weight:500;color:var(--_exm-form-title-color, var(--md-sys-color-on-surface));padding-bottom:8px}.aside{--_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);--_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);--_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);--_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);--_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);--_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);--_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px);line-height:var(--_exm-form-aside-line-height);font-size:var(--_exm-form-aside-font-size);letter-spacing:var(--_exm-form-aside-letter-spacing);font-weight:var(--_exm-form-aside-font-weight);color:var(--md-sys-color-on-surface);border-left:1px solid var(--md-sys-color-outline-variant);box-sizing:border-box;margin-left:var(--_exm-form-aside-margin-left);margin-right:var(--_exm-form-aside-margin-right);min-height:2rem;padding-left:1rem;vertical-align:top;height:100%;min-width:var(--_exm-form-aside-min-width);flex:0}form{margin:0 1rem;width:100%}form .row{display:flex;gap:6px;height:76px;align-items:flex-start}form .row>*{flex:1;height:fit-content}form{display:flex;flex-direction:column;gap:12px;margin-top:.5rem}form>*{display:contents}.actions>*{margin-right:8px}.no-flex{display:block}.extra-margin{margin-top:2rem;display:block}label.checkbox{display:flex;justify-content:flex-start;align-items:center;font-size:1rem;font-weight:500;margin:.5rem 1rem}label.checkbox md-checkbox{margin-right:1rem}.toolbar{display:flex;align-items:center;padding:8px 4px 8px 16px;height:56px;box-sizing:border-box}.toolbar .title{line-height:1.5rem;font-size:1rem;letter-spacing:.00625em;font-weight:500;color:var(--md-sys-color-on-surface);box-sizing:border-box;overflow-wrap:break-word}a{color:var(--md-sys-color-primary)}`;
3
+ export default style;
4
+ //# sourceMappingURL=exm-form-css.js.map
@@ -0,0 +1,108 @@
1
+ .section-title {
2
+ line-height: 1.5rem;
3
+ font-size: 1rem;
4
+ letter-spacing: 0.00625em;
5
+ font-weight: 500;
6
+ color: var(--_exm-form-title-color, var(--md-sys-color-on-surface));
7
+ padding-bottom: 8px;
8
+ }
9
+
10
+ .aside {
11
+ --_exm-form-aside-font-size: var(--exm-form-aside-font-size, 0.875rem);
12
+ --_exm-form-aside-line-height: var(--exm-form-aside-line-height, 1.25rem);
13
+ --_exm-form-aside-letter-spacing: var(--exm-form-aside-letter-spacing, 0.0142857143em);
14
+ --_exm-form-aside-font-weight: var(--exm-form-aside-font-weight, 400);
15
+ --_exm-form-aside-margin-left: var(--exm-form-aside-margin-left, 1rem);
16
+ --_exm-form-aside-margin-right: var(--exm-form-aside-margin-right, 5rem);
17
+ --_exm-form-aside-min-width: var(--exm-form-aside-min-width, 180px);
18
+ line-height: var(--_exm-form-aside-line-height);
19
+ font-size: var(--_exm-form-aside-font-size);
20
+ letter-spacing: var(--_exm-form-aside-letter-spacing);
21
+ font-weight: var(--_exm-form-aside-font-weight);
22
+ color: var(--md-sys-color-on-surface);
23
+ border-left: 1px solid var(--md-sys-color-outline-variant);
24
+ box-sizing: border-box;
25
+ margin-left: var(--_exm-form-aside-margin-left);
26
+ margin-right: var(--_exm-form-aside-margin-right);
27
+ min-height: 2rem;
28
+ padding-left: 1rem;
29
+ vertical-align: top;
30
+ height: 100%;
31
+ min-width: var(--_exm-form-aside-min-width);
32
+ flex: 0;
33
+ }
34
+
35
+ form {
36
+ margin: 0 1rem;
37
+ width: 100%;
38
+ }
39
+
40
+ form .row {
41
+ display: flex;
42
+ gap: 6px;
43
+ height: 76px;
44
+ align-items: flex-start;
45
+ }
46
+
47
+ form .row > * {
48
+ flex: 1;
49
+ height: fit-content;
50
+ }
51
+
52
+ form {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: 12px;
56
+ margin-top: 0.5rem;
57
+ }
58
+
59
+ form > * {
60
+ display: contents;
61
+ }
62
+
63
+ .actions > * {
64
+ margin-right: 8px;
65
+ }
66
+
67
+ .no-flex {
68
+ display: block;
69
+ }
70
+
71
+ .extra-margin {
72
+ margin-top: 2rem;
73
+ display: block;
74
+ }
75
+
76
+ label.checkbox {
77
+ display: flex;
78
+ justify-content: flex-start;
79
+ align-items: center;
80
+ font-size: 1rem;
81
+ font-weight: 500;
82
+ margin: 0.5rem 1rem;
83
+ md-checkbox {
84
+ margin-right: 1rem;
85
+ }
86
+ }
87
+
88
+ .toolbar {
89
+ display: flex;
90
+ align-items: center;
91
+ padding: 8px 4px 8px 16px;
92
+ height: 56px;
93
+ box-sizing: border-box;
94
+ }
95
+
96
+ .toolbar .title {
97
+ line-height: 1.5rem;
98
+ font-size: 1rem;
99
+ letter-spacing: 0.00625em;
100
+ font-weight: 500;
101
+ color: var(--md-sys-color-on-surface);
102
+ box-sizing: border-box;
103
+ overflow-wrap: break-word;
104
+ }
105
+
106
+ a {
107
+ color: var(--md-sys-color-primary);
108
+ }