@limetech/lime-elements 40.17.1 → 40.18.1
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/CHANGELOG.md +14 -0
- package/dist/cjs/limel-form.cjs.entry.js +55 -7
- package/dist/collection/components/form/fields/schema-field.js +8 -1
- package/dist/collection/components/form/form.js +12 -6
- package/dist/collection/components/form/form.test-schemas.js +86 -0
- package/dist/collection/components/form/show-field.js +38 -1
- package/dist/esm/limel-form.entry.js +55 -7
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/{p-74db50a8.entry.js → p-565c85ac.entry.js} +1 -1
- package/dist/types/components/form/fields/schema-field.d.ts +1 -0
- package/dist/types/components/form/form.d.ts +2 -0
- package/dist/types/components/form/form.test-schemas.d.ts +4 -0
- package/dist/types/components/form/form.types.d.ts +17 -1
- package/dist/types/components/form/show-field.d.ts +6 -0
- package/dist/types/components.d.ts +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [40.18.1](https://github.com/Lundalogik/lime-elements/compare/v40.18.0...v40.18.1) (2026-10-30)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
* **form:** keep a highlighted field in view while the form grows ([41055e0](https://github.com/Lundalogik/lime-elements/commit/41055e0782a19bb7eed1de450ea93b950741d222))
|
|
7
|
+
|
|
8
|
+
## [40.18.0](https://github.com/Lundalogik/lime-elements/compare/v40.17.1...v40.18.0) (2026-10-29)
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
* **form:** let the form draw the header of a custom component ([4933ff8](https://github.com/Lundalogik/lime-elements/commit/4933ff81471f0e2cb2a695eb4941d56c632eb2ec))
|
|
14
|
+
|
|
1
15
|
## [40.17.1](https://github.com/Lundalogik/lime-elements/compare/v40.17.0...v40.17.1) (2026-10-29)
|
|
2
16
|
|
|
3
17
|
### Bug Fixes
|
|
@@ -45349,6 +45349,10 @@ class SchemaField extends React.Component {
|
|
|
45349
45349
|
const fallbackText = (_c = (_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.props) === null || _c === void 0 ? void 0 : _c.helperText;
|
|
45350
45350
|
return getErrorText(errors, schema.description, fallbackText);
|
|
45351
45351
|
}
|
|
45352
|
+
hasHeaderFromForm(schema) {
|
|
45353
|
+
var _a, _b;
|
|
45354
|
+
return ((_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.showHeader) === true && !this.context;
|
|
45355
|
+
}
|
|
45352
45356
|
handleCustomComponentChange(event) {
|
|
45353
45357
|
const { schema } = this.props;
|
|
45354
45358
|
event.stopPropagation();
|
|
@@ -45407,7 +45411,9 @@ class SchemaField extends React.Component {
|
|
|
45407
45411
|
const { name, props: userDefinedComponentProps } = getCustomComponent(schema);
|
|
45408
45412
|
verifyCustomComponentIsDefined(name);
|
|
45409
45413
|
const component = React.createElement(name, Object.assign(Object.assign(Object.assign({}, userDefinedComponentProps), this.buildCustomComponentProps()), { onChange: this.handleCustomComponentChange }));
|
|
45410
|
-
|
|
45414
|
+
const hasHeader = this.hasHeaderFromForm(schema);
|
|
45415
|
+
return React.createElement(FieldTemplate, Object.assign(Object.assign({}, this.props), { classNames: 'rjsf-field rjsf-field-custom' }), hasHeader &&
|
|
45416
|
+
renderHeader(schema.title, schema.description, schema.lime.help), component, !hasHeader && getHelpComponent(schema));
|
|
45411
45417
|
}
|
|
45412
45418
|
render() {
|
|
45413
45419
|
var _a;
|
|
@@ -46019,7 +46025,10 @@ var reactDomExports = requireReactDom();
|
|
|
46019
46025
|
const HIGHLIGHT_CLASS = 'limel-form-field--highlighted';
|
|
46020
46026
|
const STABLE_FRAMES = 3;
|
|
46021
46027
|
const MAX_SETTLE_MS = 2000;
|
|
46028
|
+
const FOLLOW_MS = 3000;
|
|
46022
46029
|
const MAX_RENDER_FRAMES = 30;
|
|
46030
|
+
const USER_INPUT_EVENTS = ['wheel', 'touchmove', 'pointerdown', 'keydown'];
|
|
46031
|
+
const stopFollowing = new WeakMap();
|
|
46023
46032
|
/**
|
|
46024
46033
|
* Open what is closed above a field, scroll it into view, focus it and
|
|
46025
46034
|
* highlight it.
|
|
@@ -46047,14 +46056,48 @@ async function showField(root, path) {
|
|
|
46047
46056
|
// around it opened, before the field is where it will stay.
|
|
46048
46057
|
const focusTarget = await getFocusTarget.getFocusTarget(target);
|
|
46049
46058
|
await waitForLayoutToSettle(target);
|
|
46050
|
-
target.scrollIntoView({
|
|
46059
|
+
const scrollToTarget = () => target.scrollIntoView({
|
|
46051
46060
|
block: 'center',
|
|
46052
46061
|
behavior: prefersReducedMotion() ? 'instant' : 'smooth',
|
|
46053
46062
|
});
|
|
46063
|
+
scrollToTarget();
|
|
46054
46064
|
focusTarget === null || focusTarget === void 0 ? void 0 : focusTarget.focus({ preventScroll: true });
|
|
46065
|
+
keepInViewWhileFormGrows(root, scrollToTarget);
|
|
46055
46066
|
await waitForLayoutToSettle(target);
|
|
46056
46067
|
highlight(target);
|
|
46057
46068
|
}
|
|
46069
|
+
// What the form draws a while later, such as a custom component that loads
|
|
46070
|
+
// its code, can move the field after it was scrolled to. Follow the field for
|
|
46071
|
+
// a while, until the user takes over.
|
|
46072
|
+
function keepInViewWhileFormGrows(root, scrollToTarget) {
|
|
46073
|
+
stopShowingField(root);
|
|
46074
|
+
const observer = new ResizeObserver(scrollToTarget);
|
|
46075
|
+
const stop = () => {
|
|
46076
|
+
observer.disconnect();
|
|
46077
|
+
clearTimeout(deadline);
|
|
46078
|
+
stopFollowing.delete(root);
|
|
46079
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
46080
|
+
window.removeEventListener(type, stop, true);
|
|
46081
|
+
}
|
|
46082
|
+
};
|
|
46083
|
+
const deadline = setTimeout(stop, FOLLOW_MS);
|
|
46084
|
+
stopFollowing.set(root, stop);
|
|
46085
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
46086
|
+
window.addEventListener(type, stop, { capture: true, passive: true });
|
|
46087
|
+
}
|
|
46088
|
+
observer.observe(root);
|
|
46089
|
+
}
|
|
46090
|
+
/**
|
|
46091
|
+
* Stop keeping the field that was shown last in view.
|
|
46092
|
+
*
|
|
46093
|
+
* @param root - the element the form is rendered in
|
|
46094
|
+
*/
|
|
46095
|
+
function stopShowingField(root) {
|
|
46096
|
+
var _a;
|
|
46097
|
+
if (root) {
|
|
46098
|
+
(_a = stopFollowing.get(root)) === null || _a === void 0 ? void 0 : _a();
|
|
46099
|
+
}
|
|
46100
|
+
}
|
|
46058
46101
|
function findByPath(root, path) {
|
|
46059
46102
|
const schemaPath = toSchemaPath(path.map(String));
|
|
46060
46103
|
return root.querySelector(`[data-schema-path="${CSS.escape(schemaPath)}"]`);
|
|
@@ -46200,9 +46243,11 @@ const Form = class {
|
|
|
46200
46243
|
}
|
|
46201
46244
|
handleHighlightedFieldChange(newPath, oldPath) {
|
|
46202
46245
|
// A host that renders again passes an equal path in a new array.
|
|
46203
|
-
if (
|
|
46204
|
-
|
|
46246
|
+
if (isEqual.isEqual(newPath, oldPath)) {
|
|
46247
|
+
return;
|
|
46205
46248
|
}
|
|
46249
|
+
stopShowingField(this.rootElement);
|
|
46250
|
+
this.showHighlightedField();
|
|
46206
46251
|
}
|
|
46207
46252
|
initialize() {
|
|
46208
46253
|
if (this.initialized || !this.host.shadowRoot.querySelector('.root')) {
|
|
@@ -46217,6 +46262,7 @@ const Form = class {
|
|
|
46217
46262
|
this.validateFormData();
|
|
46218
46263
|
}
|
|
46219
46264
|
disconnectedCallback() {
|
|
46265
|
+
stopShowingField(this.rootElement);
|
|
46220
46266
|
if (this.root) {
|
|
46221
46267
|
this.root.unmount();
|
|
46222
46268
|
this.root = undefined;
|
|
@@ -46224,7 +46270,7 @@ const Form = class {
|
|
|
46224
46270
|
this.initialized = false;
|
|
46225
46271
|
}
|
|
46226
46272
|
render() {
|
|
46227
|
-
return index.h("div", { key: '
|
|
46273
|
+
return index.h("div", { key: '74e2b0c57dd6acb08ebb364220cb4f2e6fbe1733', class: "root" });
|
|
46228
46274
|
}
|
|
46229
46275
|
reactRender() {
|
|
46230
46276
|
if (!this.root) {
|
|
@@ -46279,8 +46325,10 @@ const Form = class {
|
|
|
46279
46325
|
if (!this.highlightedField) {
|
|
46280
46326
|
return;
|
|
46281
46327
|
}
|
|
46282
|
-
|
|
46283
|
-
|
|
46328
|
+
void showField(this.rootElement, this.highlightedField);
|
|
46329
|
+
}
|
|
46330
|
+
get rootElement() {
|
|
46331
|
+
return this.host.shadowRoot.querySelector('.root');
|
|
46284
46332
|
}
|
|
46285
46333
|
handleChange(event) {
|
|
46286
46334
|
this.change.emit(event.formData);
|
|
@@ -4,6 +4,7 @@ import { isEmpty } from "lodash-es";
|
|
|
4
4
|
import { hasValue, isFieldInvalid, isFieldRequired, getErrorText, } from "../validation-display";
|
|
5
5
|
import { resetDependentFields, schemaAllowsNull } from "./field-helpers";
|
|
6
6
|
import { FieldTemplate } from "../templates";
|
|
7
|
+
import { renderHeader } from "../templates/common";
|
|
7
8
|
import { getHelpComponent } from "../help";
|
|
8
9
|
import { TimePicker } from "../widgets/time-picker";
|
|
9
10
|
import { isIntegerType, isNumberType } from "../schema";
|
|
@@ -111,6 +112,10 @@ export class SchemaField extends React.Component {
|
|
|
111
112
|
const fallbackText = (_c = (_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.props) === null || _c === void 0 ? void 0 : _c.helperText;
|
|
112
113
|
return getErrorText(errors, schema.description, fallbackText);
|
|
113
114
|
}
|
|
115
|
+
hasHeaderFromForm(schema) {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
return ((_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.showHeader) === true && !this.context;
|
|
118
|
+
}
|
|
114
119
|
handleCustomComponentChange(event) {
|
|
115
120
|
const { schema } = this.props;
|
|
116
121
|
event.stopPropagation();
|
|
@@ -169,7 +174,9 @@ export class SchemaField extends React.Component {
|
|
|
169
174
|
const { name, props: userDefinedComponentProps } = getCustomComponent(schema);
|
|
170
175
|
verifyCustomComponentIsDefined(name);
|
|
171
176
|
const component = React.createElement(name, Object.assign(Object.assign(Object.assign({}, userDefinedComponentProps), this.buildCustomComponentProps()), { onChange: this.handleCustomComponentChange }));
|
|
172
|
-
|
|
177
|
+
const hasHeader = this.hasHeaderFromForm(schema);
|
|
178
|
+
return React.createElement(FieldTemplate, Object.assign(Object.assign({}, this.props), { classNames: 'rjsf-field rjsf-field-custom' }), hasHeader &&
|
|
179
|
+
renderHeader(schema.title, schema.description, schema.lime.help), component, !hasHeader && getHelpComponent(schema));
|
|
173
180
|
}
|
|
174
181
|
render() {
|
|
175
182
|
var _a;
|
|
@@ -22,7 +22,7 @@ import { ObjectField as CustomObjectField } from "./fields/object-field";
|
|
|
22
22
|
import { widgets } from "./widgets";
|
|
23
23
|
import { rjsfValidator } from "./validator";
|
|
24
24
|
import { isEqual, mapValues } from "lodash-es";
|
|
25
|
-
import { showField } from "./show-field";
|
|
25
|
+
import { showField, stopShowingField } from "./show-field";
|
|
26
26
|
import { HeadingLevelContext } from "./templates/heading-level";
|
|
27
27
|
/**
|
|
28
28
|
* @exampleComponent limel-example-form
|
|
@@ -30,6 +30,7 @@ import { HeadingLevelContext } from "./templates/heading-level";
|
|
|
30
30
|
* @exampleComponent limel-example-list-form
|
|
31
31
|
* @exampleComponent limel-example-dynamic-form
|
|
32
32
|
* @exampleComponent limel-example-custom-component-form
|
|
33
|
+
* @exampleComponent limel-example-custom-component-header-form
|
|
33
34
|
* @exampleComponent limel-example-props-factory-form
|
|
34
35
|
* @exampleComponent limel-example-form-layout
|
|
35
36
|
* @exampleComponent limel-example-form-span-fields
|
|
@@ -97,9 +98,11 @@ export class Form {
|
|
|
97
98
|
}
|
|
98
99
|
handleHighlightedFieldChange(newPath, oldPath) {
|
|
99
100
|
// A host that renders again passes an equal path in a new array.
|
|
100
|
-
if (
|
|
101
|
-
|
|
101
|
+
if (isEqual(newPath, oldPath)) {
|
|
102
|
+
return;
|
|
102
103
|
}
|
|
104
|
+
stopShowingField(this.rootElement);
|
|
105
|
+
this.showHighlightedField();
|
|
103
106
|
}
|
|
104
107
|
initialize() {
|
|
105
108
|
if (this.initialized || !this.host.shadowRoot.querySelector('.root')) {
|
|
@@ -114,6 +117,7 @@ export class Form {
|
|
|
114
117
|
this.validateFormData();
|
|
115
118
|
}
|
|
116
119
|
disconnectedCallback() {
|
|
120
|
+
stopShowingField(this.rootElement);
|
|
117
121
|
if (this.root) {
|
|
118
122
|
this.root.unmount();
|
|
119
123
|
this.root = undefined;
|
|
@@ -121,7 +125,7 @@ export class Form {
|
|
|
121
125
|
this.initialized = false;
|
|
122
126
|
}
|
|
123
127
|
render() {
|
|
124
|
-
return h("div", { key: '
|
|
128
|
+
return h("div", { key: '74e2b0c57dd6acb08ebb364220cb4f2e6fbe1733', class: "root" });
|
|
125
129
|
}
|
|
126
130
|
reactRender() {
|
|
127
131
|
if (!this.root) {
|
|
@@ -176,8 +180,10 @@ export class Form {
|
|
|
176
180
|
if (!this.highlightedField) {
|
|
177
181
|
return;
|
|
178
182
|
}
|
|
179
|
-
|
|
180
|
-
|
|
183
|
+
void showField(this.rootElement, this.highlightedField);
|
|
184
|
+
}
|
|
185
|
+
get rootElement() {
|
|
186
|
+
return this.host.shadowRoot.querySelector('.root');
|
|
181
187
|
}
|
|
182
188
|
handleChange(event) {
|
|
183
189
|
this.change.emit(event.formData);
|
|
@@ -322,6 +322,92 @@ export const customComponentSchema = {
|
|
|
322
322
|
},
|
|
323
323
|
},
|
|
324
324
|
};
|
|
325
|
+
export const customComponentWithHeaderSchema = {
|
|
326
|
+
type: 'object',
|
|
327
|
+
title: 'Form',
|
|
328
|
+
properties: {
|
|
329
|
+
enabled: {
|
|
330
|
+
type: 'boolean',
|
|
331
|
+
title: 'Enabled',
|
|
332
|
+
description: 'Turns the feature on',
|
|
333
|
+
lime: {
|
|
334
|
+
help: 'Read more about the feature',
|
|
335
|
+
component: {
|
|
336
|
+
name: 'limel-switch',
|
|
337
|
+
showHeader: true,
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
section: {
|
|
342
|
+
type: 'object',
|
|
343
|
+
title: 'Section',
|
|
344
|
+
properties: {
|
|
345
|
+
nested: {
|
|
346
|
+
type: 'boolean',
|
|
347
|
+
title: 'Nested',
|
|
348
|
+
lime: {
|
|
349
|
+
component: {
|
|
350
|
+
name: 'limel-switch',
|
|
351
|
+
showHeader: true,
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
export const requiredCustomComponentWithHeaderSchema = {
|
|
360
|
+
type: 'object',
|
|
361
|
+
properties: {
|
|
362
|
+
name: { type: 'string', title: 'Name' },
|
|
363
|
+
enabled: {
|
|
364
|
+
type: 'boolean',
|
|
365
|
+
title: 'Enabled',
|
|
366
|
+
description: 'Turns the feature on',
|
|
367
|
+
lime: {
|
|
368
|
+
component: {
|
|
369
|
+
name: 'limel-switch',
|
|
370
|
+
showHeader: true,
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
required: ['name', 'enabled'],
|
|
376
|
+
};
|
|
377
|
+
export const customComponentWithHelpSchema = {
|
|
378
|
+
type: 'object',
|
|
379
|
+
properties: {
|
|
380
|
+
enabled: {
|
|
381
|
+
type: 'boolean',
|
|
382
|
+
title: 'Enabled',
|
|
383
|
+
lime: {
|
|
384
|
+
help: 'Read more about the feature',
|
|
385
|
+
component: { name: 'limel-switch' },
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
export const rowLayoutWithCustomComponentHeaderSchema = {
|
|
391
|
+
type: 'object',
|
|
392
|
+
properties: {
|
|
393
|
+
active: {
|
|
394
|
+
type: 'boolean',
|
|
395
|
+
title: 'Active',
|
|
396
|
+
description: 'Active description',
|
|
397
|
+
lime: {
|
|
398
|
+
component: {
|
|
399
|
+
name: 'limel-switch',
|
|
400
|
+
showHeader: true,
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
lime: {
|
|
406
|
+
layout: {
|
|
407
|
+
type: 'row',
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
};
|
|
325
411
|
export const undefinedComponentSchema = {
|
|
326
412
|
type: 'object',
|
|
327
413
|
properties: {
|
|
@@ -4,7 +4,10 @@ import { getFocusTarget } from "../../util/get-focus-target";
|
|
|
4
4
|
const HIGHLIGHT_CLASS = 'limel-form-field--highlighted';
|
|
5
5
|
const STABLE_FRAMES = 3;
|
|
6
6
|
const MAX_SETTLE_MS = 2000;
|
|
7
|
+
const FOLLOW_MS = 3000;
|
|
7
8
|
const MAX_RENDER_FRAMES = 30;
|
|
9
|
+
const USER_INPUT_EVENTS = ['wheel', 'touchmove', 'pointerdown', 'keydown'];
|
|
10
|
+
const stopFollowing = new WeakMap();
|
|
8
11
|
/**
|
|
9
12
|
* Open what is closed above a field, scroll it into view, focus it and
|
|
10
13
|
* highlight it.
|
|
@@ -32,14 +35,48 @@ export async function showField(root, path) {
|
|
|
32
35
|
// around it opened, before the field is where it will stay.
|
|
33
36
|
const focusTarget = await getFocusTarget(target);
|
|
34
37
|
await waitForLayoutToSettle(target);
|
|
35
|
-
target.scrollIntoView({
|
|
38
|
+
const scrollToTarget = () => target.scrollIntoView({
|
|
36
39
|
block: 'center',
|
|
37
40
|
behavior: prefersReducedMotion() ? 'instant' : 'smooth',
|
|
38
41
|
});
|
|
42
|
+
scrollToTarget();
|
|
39
43
|
focusTarget === null || focusTarget === void 0 ? void 0 : focusTarget.focus({ preventScroll: true });
|
|
44
|
+
keepInViewWhileFormGrows(root, scrollToTarget);
|
|
40
45
|
await waitForLayoutToSettle(target);
|
|
41
46
|
highlight(target);
|
|
42
47
|
}
|
|
48
|
+
// What the form draws a while later, such as a custom component that loads
|
|
49
|
+
// its code, can move the field after it was scrolled to. Follow the field for
|
|
50
|
+
// a while, until the user takes over.
|
|
51
|
+
function keepInViewWhileFormGrows(root, scrollToTarget) {
|
|
52
|
+
stopShowingField(root);
|
|
53
|
+
const observer = new ResizeObserver(scrollToTarget);
|
|
54
|
+
const stop = () => {
|
|
55
|
+
observer.disconnect();
|
|
56
|
+
clearTimeout(deadline);
|
|
57
|
+
stopFollowing.delete(root);
|
|
58
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
59
|
+
window.removeEventListener(type, stop, true);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const deadline = setTimeout(stop, FOLLOW_MS);
|
|
63
|
+
stopFollowing.set(root, stop);
|
|
64
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
65
|
+
window.addEventListener(type, stop, { capture: true, passive: true });
|
|
66
|
+
}
|
|
67
|
+
observer.observe(root);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Stop keeping the field that was shown last in view.
|
|
71
|
+
*
|
|
72
|
+
* @param root - the element the form is rendered in
|
|
73
|
+
*/
|
|
74
|
+
export function stopShowingField(root) {
|
|
75
|
+
var _a;
|
|
76
|
+
if (root) {
|
|
77
|
+
(_a = stopFollowing.get(root)) === null || _a === void 0 ? void 0 : _a();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
43
80
|
function findByPath(root, path) {
|
|
44
81
|
const schemaPath = toSchemaPath(path.map(String));
|
|
45
82
|
return root.querySelector(`[data-schema-path="${CSS.escape(schemaPath)}"]`);
|
|
@@ -45347,6 +45347,10 @@ class SchemaField extends React.Component {
|
|
|
45347
45347
|
const fallbackText = (_c = (_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.props) === null || _c === void 0 ? void 0 : _c.helperText;
|
|
45348
45348
|
return getErrorText(errors, schema.description, fallbackText);
|
|
45349
45349
|
}
|
|
45350
|
+
hasHeaderFromForm(schema) {
|
|
45351
|
+
var _a, _b;
|
|
45352
|
+
return ((_b = (_a = schema.lime) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.showHeader) === true && !this.context;
|
|
45353
|
+
}
|
|
45350
45354
|
handleCustomComponentChange(event) {
|
|
45351
45355
|
const { schema } = this.props;
|
|
45352
45356
|
event.stopPropagation();
|
|
@@ -45405,7 +45409,9 @@ class SchemaField extends React.Component {
|
|
|
45405
45409
|
const { name, props: userDefinedComponentProps } = getCustomComponent(schema);
|
|
45406
45410
|
verifyCustomComponentIsDefined(name);
|
|
45407
45411
|
const component = React.createElement(name, Object.assign(Object.assign(Object.assign({}, userDefinedComponentProps), this.buildCustomComponentProps()), { onChange: this.handleCustomComponentChange }));
|
|
45408
|
-
|
|
45412
|
+
const hasHeader = this.hasHeaderFromForm(schema);
|
|
45413
|
+
return React.createElement(FieldTemplate, Object.assign(Object.assign({}, this.props), { classNames: 'rjsf-field rjsf-field-custom' }), hasHeader &&
|
|
45414
|
+
renderHeader(schema.title, schema.description, schema.lime.help), component, !hasHeader && getHelpComponent(schema));
|
|
45409
45415
|
}
|
|
45410
45416
|
render() {
|
|
45411
45417
|
var _a;
|
|
@@ -46017,7 +46023,10 @@ var reactDomExports = requireReactDom();
|
|
|
46017
46023
|
const HIGHLIGHT_CLASS = 'limel-form-field--highlighted';
|
|
46018
46024
|
const STABLE_FRAMES = 3;
|
|
46019
46025
|
const MAX_SETTLE_MS = 2000;
|
|
46026
|
+
const FOLLOW_MS = 3000;
|
|
46020
46027
|
const MAX_RENDER_FRAMES = 30;
|
|
46028
|
+
const USER_INPUT_EVENTS = ['wheel', 'touchmove', 'pointerdown', 'keydown'];
|
|
46029
|
+
const stopFollowing = new WeakMap();
|
|
46021
46030
|
/**
|
|
46022
46031
|
* Open what is closed above a field, scroll it into view, focus it and
|
|
46023
46032
|
* highlight it.
|
|
@@ -46045,14 +46054,48 @@ async function showField(root, path) {
|
|
|
46045
46054
|
// around it opened, before the field is where it will stay.
|
|
46046
46055
|
const focusTarget = await getFocusTarget(target);
|
|
46047
46056
|
await waitForLayoutToSettle(target);
|
|
46048
|
-
target.scrollIntoView({
|
|
46057
|
+
const scrollToTarget = () => target.scrollIntoView({
|
|
46049
46058
|
block: 'center',
|
|
46050
46059
|
behavior: prefersReducedMotion() ? 'instant' : 'smooth',
|
|
46051
46060
|
});
|
|
46061
|
+
scrollToTarget();
|
|
46052
46062
|
focusTarget === null || focusTarget === void 0 ? void 0 : focusTarget.focus({ preventScroll: true });
|
|
46063
|
+
keepInViewWhileFormGrows(root, scrollToTarget);
|
|
46053
46064
|
await waitForLayoutToSettle(target);
|
|
46054
46065
|
highlight(target);
|
|
46055
46066
|
}
|
|
46067
|
+
// What the form draws a while later, such as a custom component that loads
|
|
46068
|
+
// its code, can move the field after it was scrolled to. Follow the field for
|
|
46069
|
+
// a while, until the user takes over.
|
|
46070
|
+
function keepInViewWhileFormGrows(root, scrollToTarget) {
|
|
46071
|
+
stopShowingField(root);
|
|
46072
|
+
const observer = new ResizeObserver(scrollToTarget);
|
|
46073
|
+
const stop = () => {
|
|
46074
|
+
observer.disconnect();
|
|
46075
|
+
clearTimeout(deadline);
|
|
46076
|
+
stopFollowing.delete(root);
|
|
46077
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
46078
|
+
window.removeEventListener(type, stop, true);
|
|
46079
|
+
}
|
|
46080
|
+
};
|
|
46081
|
+
const deadline = setTimeout(stop, FOLLOW_MS);
|
|
46082
|
+
stopFollowing.set(root, stop);
|
|
46083
|
+
for (const type of USER_INPUT_EVENTS) {
|
|
46084
|
+
window.addEventListener(type, stop, { capture: true, passive: true });
|
|
46085
|
+
}
|
|
46086
|
+
observer.observe(root);
|
|
46087
|
+
}
|
|
46088
|
+
/**
|
|
46089
|
+
* Stop keeping the field that was shown last in view.
|
|
46090
|
+
*
|
|
46091
|
+
* @param root - the element the form is rendered in
|
|
46092
|
+
*/
|
|
46093
|
+
function stopShowingField(root) {
|
|
46094
|
+
var _a;
|
|
46095
|
+
if (root) {
|
|
46096
|
+
(_a = stopFollowing.get(root)) === null || _a === void 0 ? void 0 : _a();
|
|
46097
|
+
}
|
|
46098
|
+
}
|
|
46056
46099
|
function findByPath(root, path) {
|
|
46057
46100
|
const schemaPath = toSchemaPath(path.map(String));
|
|
46058
46101
|
return root.querySelector(`[data-schema-path="${CSS.escape(schemaPath)}"]`);
|
|
@@ -46198,9 +46241,11 @@ const Form = class {
|
|
|
46198
46241
|
}
|
|
46199
46242
|
handleHighlightedFieldChange(newPath, oldPath) {
|
|
46200
46243
|
// A host that renders again passes an equal path in a new array.
|
|
46201
|
-
if (
|
|
46202
|
-
|
|
46244
|
+
if (isEqual(newPath, oldPath)) {
|
|
46245
|
+
return;
|
|
46203
46246
|
}
|
|
46247
|
+
stopShowingField(this.rootElement);
|
|
46248
|
+
this.showHighlightedField();
|
|
46204
46249
|
}
|
|
46205
46250
|
initialize() {
|
|
46206
46251
|
if (this.initialized || !this.host.shadowRoot.querySelector('.root')) {
|
|
@@ -46215,6 +46260,7 @@ const Form = class {
|
|
|
46215
46260
|
this.validateFormData();
|
|
46216
46261
|
}
|
|
46217
46262
|
disconnectedCallback() {
|
|
46263
|
+
stopShowingField(this.rootElement);
|
|
46218
46264
|
if (this.root) {
|
|
46219
46265
|
this.root.unmount();
|
|
46220
46266
|
this.root = undefined;
|
|
@@ -46222,7 +46268,7 @@ const Form = class {
|
|
|
46222
46268
|
this.initialized = false;
|
|
46223
46269
|
}
|
|
46224
46270
|
render() {
|
|
46225
|
-
return h$1("div", { key: '
|
|
46271
|
+
return h$1("div", { key: '74e2b0c57dd6acb08ebb364220cb4f2e6fbe1733', class: "root" });
|
|
46226
46272
|
}
|
|
46227
46273
|
reactRender() {
|
|
46228
46274
|
if (!this.root) {
|
|
@@ -46277,8 +46323,10 @@ const Form = class {
|
|
|
46277
46323
|
if (!this.highlightedField) {
|
|
46278
46324
|
return;
|
|
46279
46325
|
}
|
|
46280
|
-
|
|
46281
|
-
|
|
46326
|
+
void showField(this.rootElement, this.highlightedField);
|
|
46327
|
+
}
|
|
46328
|
+
get rootElement() {
|
|
46329
|
+
return this.host.shadowRoot.querySelector('.root');
|
|
46282
46330
|
}
|
|
46283
46331
|
handleChange(event) {
|
|
46284
46332
|
this.change.emit(event.formData);
|