@widgetic/editor 4.0.10 → 4.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.
Files changed (55) hide show
  1. package/README.md +118 -0
  2. package/dist/components/WidgetPreview.svelte +65 -27
  3. package/dist/components/WidgetPreview.svelte.d.ts +8 -0
  4. package/dist/components/editors/CompositionEditorApp.svelte +508 -0
  5. package/dist/components/editors/CompositionEditorApp.svelte.d.ts +75 -0
  6. package/dist/components/editors/PropsEditor.svelte +193 -792
  7. package/dist/components/editors/PropsEditor.svelte.d.ts +7 -0
  8. package/dist/components/ic/BrowserInputController.svelte +21 -2
  9. package/dist/components/ic/ColorPickerInputController.svelte +24 -6
  10. package/dist/components/ic/DateFieldInputController.svelte +7 -3
  11. package/dist/components/ic/DatePickerInputController.svelte +10 -4
  12. package/dist/components/ic/DropdownInputController.svelte +11 -4
  13. package/dist/components/ic/FontInputController.svelte +68 -49
  14. package/dist/components/ic/InputControllerHeader.svelte +11 -8
  15. package/dist/components/ic/NumberInputController.svelte +4 -2
  16. package/dist/components/ic/PositionInputController.svelte +14 -11
  17. package/dist/components/ic/RangeCalendarInputController.svelte +10 -4
  18. package/dist/components/ic/RoundedCornersInputController.svelte +17 -9
  19. package/dist/components/ic/TextAreaInputController.svelte +20 -7
  20. package/dist/components/ic/TextAreaPreviewInputController.svelte +19 -69
  21. package/dist/components/ic/TimeInputController.svelte +9 -3
  22. package/dist/components/ic/VectorInputController.svelte +80 -54
  23. package/dist/components/ic/shared/ItemGrid.svelte +5 -1
  24. package/dist/composition/compositionApi.d.ts +95 -0
  25. package/dist/composition/compositionApi.js +289 -0
  26. package/dist/composition/compositionEditorController.d.ts +254 -0
  27. package/dist/composition/compositionEditorController.js +734 -0
  28. package/dist/composition/compositionHelpers.d.ts +72 -0
  29. package/dist/composition/compositionHelpers.js +403 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +4 -0
  32. package/dist/mediaLibraryContext.d.ts +10 -0
  33. package/dist/mediaLibraryContext.js +30 -0
  34. package/dist/utils/FontManager.d.ts +21 -5
  35. package/dist/utils/FontManager.js +62 -67
  36. package/dist/utils/VectorManager.d.ts +0 -1
  37. package/dist/utils/VectorManager.js +10 -12
  38. package/dist/utils/editorStorage.d.ts +23 -0
  39. package/dist/utils/editorStorage.js +95 -0
  40. package/dist/utils/fontUtils.js +5 -3
  41. package/dist/utils/htmlSafety.d.ts +21 -0
  42. package/dist/utils/htmlSafety.js +38 -0
  43. package/dist/utils/itemReorder.d.ts +90 -0
  44. package/dist/utils/itemReorder.js +354 -0
  45. package/dist/utils/recentColors.js +4 -2
  46. package/dist/utils/richTextPreview.d.ts +38 -0
  47. package/dist/utils/richTextPreview.js +207 -0
  48. package/dist/utils/scrollActivity.d.ts +14 -0
  49. package/dist/utils/scrollActivity.js +63 -0
  50. package/dist/utils/shadowDom.d.ts +67 -0
  51. package/dist/utils/shadowDom.js +211 -0
  52. package/dist/utils/vectorUtils.js +5 -3
  53. package/dist/utils/visibilityCondition.d.ts +40 -0
  54. package/dist/utils/visibilityCondition.js +535 -0
  55. package/package.json +6 -5
@@ -0,0 +1,63 @@
1
+ import { listenForScroll } from './shadowDom';
2
+ /** The shared listeners of each tree, found by the tree's root node (the document or a shadow root). */
3
+ const sharedListenersByTree = new Map();
4
+ /** The node that stands for the tree `anchor` lives in. */
5
+ function treeKeyOf(anchor) {
6
+ if (typeof document === 'undefined')
7
+ return null;
8
+ try {
9
+ const rootNode = anchor?.getRootNode?.();
10
+ // A node that is not in a page (yet) has no tree of its own: the page's listeners are the ones it wants.
11
+ return rootNode && rootNode.nodeType === 11 ? rootNode : document;
12
+ }
13
+ catch (error) {
14
+ console.warn('[scrollActivity] Could not tell which tree the control is in:', error);
15
+ return document;
16
+ }
17
+ }
18
+ /**
19
+ * Calls `listener` whenever the user scrolls in the tree `anchor` lives in: the page scrolling, a panel scrolling, a
20
+ * wheel turning or a finger moving. Gives back the function that stops it; call that when the control goes away.
21
+ */
22
+ export function onScrollActivity(anchor, listener) {
23
+ const treeKey = treeKeyOf(anchor);
24
+ if (!treeKey)
25
+ return () => { };
26
+ let shared = sharedListenersByTree.get(treeKey);
27
+ if (!shared) {
28
+ const listeners = new Set();
29
+ const tellEveryone = () => {
30
+ // Copied, because a listener may stop listening while it is being told.
31
+ for (const interested of [...listeners]) {
32
+ try {
33
+ interested();
34
+ }
35
+ catch (error) {
36
+ console.error('[scrollActivity] A scroll listener failed:', error);
37
+ }
38
+ }
39
+ };
40
+ const stopScroll = listenForScroll(anchor, tellEveryone, { passive: true });
41
+ // The wheel and a finger moving leave a shadow root, so the document hears about them in either tree.
42
+ document.addEventListener('wheel', tellEveryone, { capture: true, passive: true });
43
+ document.addEventListener('touchmove', tellEveryone, { capture: true, passive: true });
44
+ shared = {
45
+ listeners,
46
+ stop: () => {
47
+ stopScroll();
48
+ document.removeEventListener('wheel', tellEveryone, true);
49
+ document.removeEventListener('touchmove', tellEveryone, true);
50
+ }
51
+ };
52
+ sharedListenersByTree.set(treeKey, shared);
53
+ }
54
+ const sharedForThisTree = shared;
55
+ sharedForThisTree.listeners.add(listener);
56
+ return () => {
57
+ sharedForThisTree.listeners.delete(listener);
58
+ if (sharedForThisTree.listeners.size === 0 && sharedListenersByTree.get(treeKey) === sharedForThisTree) {
59
+ sharedForThisTree.stop();
60
+ sharedListenersByTree.delete(treeKey);
61
+ }
62
+ };
63
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Finding things on the page when the editor can be inside a shadow root.
3
+ *
4
+ * The editor also runs inside a module on a customer's page, in a shadow root. `document.querySelector(...)` and
5
+ * `document.getElementById(...)` only look at the page's own tree and never inside a shadow root, so code that looks
6
+ * something up that way finds nothing there (or, worse, finds something of the customer's page). `node.getRootNode()`
7
+ * is the tree a node lives in: the shadow root inside a module, the document on a normal page. These helpers look
8
+ * there.
9
+ */
10
+ /** What a document and a shadow root have in common, which is all these helpers need of either. */
11
+ export interface SearchableTree {
12
+ readonly nodeType: number;
13
+ querySelector(selector: string): Element | null;
14
+ querySelectorAll(selector: string): ArrayLike<Element>;
15
+ getElementById(id: string): HTMLElement | null;
16
+ appendChild<NodeType extends Node>(node: NodeType): NodeType;
17
+ }
18
+ /**
19
+ * The tree a node lives in: the shadow root it is inside, or the document. A node that is not on a page yet, or no
20
+ * node at all, gives the document (and nothing when there is no document, as when rendering on a server).
21
+ */
22
+ export declare function treeOf(anchor: Node | null | undefined): SearchableTree | null;
23
+ /** `document.querySelector(selector)`, but in the tree `anchor` lives in. */
24
+ export declare function queryInTreeOf(anchor: Node | null | undefined, selector: string): Element | null;
25
+ /** `document.querySelectorAll(selector)` as a list, but in the tree `anchor` lives in. */
26
+ export declare function queryAllInTreeOf(anchor: Node | null | undefined, selector: string): Element[];
27
+ /**
28
+ * Whether an event happened inside `element`. Heard on the document or the window, an event that started inside a
29
+ * shadow root has the shadow root's host as its target, so `element.contains(event.target)` is false for everything
30
+ * inside the editor; the event's path still lists the elements it really went through. (Call it while the event is
31
+ * being handled: the path is gone once handling is over.)
32
+ */
33
+ export declare function isEventInside(event: Event, element: Node | null | undefined): boolean;
34
+ /**
35
+ * The element that has the keyboard focus in the tree `anchor` lives in. `document.activeElement` is the module's
36
+ * host element for anything focused inside a shadow root, which is never one of the editor's fields.
37
+ */
38
+ export declare function activeElementIn(anchor: Node | null | undefined): Element | null;
39
+ /**
40
+ * Calls `handler` when something scrolls and gives back the function that stops it. A scroll is not an event that
41
+ * leaves a shadow root, so a listener on the window only hears about the page being scrolled; to hear about the
42
+ * editor's own panels scrolling the listener goes on the shadow root too. Both are listened to while the event goes
43
+ * down (capture), as a scroll does not bubble.
44
+ */
45
+ export declare function listenForScroll(anchor: Node | null | undefined, handler: (event: Event) => void, { passive }?: {
46
+ passive?: boolean;
47
+ }): () => void;
48
+ /**
49
+ * The layer a popover is drawn in when it must sit above everything else, found or made in the tree `anchor` lives in
50
+ * and shared by every component that asks for the same `id`. On a page it is a node at the end of the body; inside a
51
+ * module it is a node in the module's portal layer (or, failing that, in the shadow root), never in the customer's
52
+ * body. Give it back with `releasePortalHost` when the component goes away.
53
+ */
54
+ export declare function acquirePortalHost(anchor: Node | null | undefined, id: string, zIndex?: string): HTMLElement | null;
55
+ /** Gives a layer from `acquirePortalHost` back; the last one to give it back removes it from the page. */
56
+ export declare function releasePortalHost(host: HTMLElement | null | undefined): void;
57
+ /** What `lockPointerStyle` can be asked to do besides showing a cursor. */
58
+ export interface PointerStyleOptions {
59
+ /** Also stop text from being selected as the pointer moves. On unless told otherwise. */
60
+ blockTextSelection?: boolean;
61
+ }
62
+ /**
63
+ * Shows `cursor` for as long as a drag or a resize lasts (and, unless told otherwise, stops text from being selected as
64
+ * the pointer moves). Gives back the function that puts back what was there before; it puts it back once, however
65
+ * often it is called, so it can be called from every way a gesture can end.
66
+ */
67
+ export declare function lockPointerStyle(anchor: EventTarget | null | undefined, cursor: string, { blockTextSelection }?: PointerStyleOptions): () => void;
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Finding things on the page when the editor can be inside a shadow root.
3
+ *
4
+ * The editor also runs inside a module on a customer's page, in a shadow root. `document.querySelector(...)` and
5
+ * `document.getElementById(...)` only look at the page's own tree and never inside a shadow root, so code that looks
6
+ * something up that way finds nothing there (or, worse, finds something of the customer's page). `node.getRootNode()`
7
+ * is the tree a node lives in: the shadow root inside a module, the document on a normal page. These helpers look
8
+ * there.
9
+ */
10
+ const DOCUMENT_NODE = 9;
11
+ const DOCUMENT_FRAGMENT_NODE = 11;
12
+ /**
13
+ * The class of the layer a module keeps inside its shadow root for menus, dialogs and popovers. It is set by the
14
+ * module (ui-sdk/modules/src/shared/shadowMount.ts); this file only finds it.
15
+ */
16
+ const MODULE_PORTAL_LAYER_SELECTOR = '.widgetic-ui-portal';
17
+ /**
18
+ * The tree a node lives in: the shadow root it is inside, or the document. A node that is not on a page yet, or no
19
+ * node at all, gives the document (and nothing when there is no document, as when rendering on a server).
20
+ */
21
+ export function treeOf(anchor) {
22
+ try {
23
+ const rootNode = anchor?.getRootNode?.();
24
+ if (rootNode &&
25
+ (rootNode.nodeType === DOCUMENT_NODE || rootNode.nodeType === DOCUMENT_FRAGMENT_NODE)) {
26
+ return rootNode;
27
+ }
28
+ }
29
+ catch (error) {
30
+ console.warn('[shadowDom] Could not tell which tree a node is in, using the document:', error);
31
+ }
32
+ return typeof document === 'undefined' ? null : document;
33
+ }
34
+ /** `document.querySelector(selector)`, but in the tree `anchor` lives in. */
35
+ export function queryInTreeOf(anchor, selector) {
36
+ try {
37
+ return treeOf(anchor)?.querySelector(selector) ?? null;
38
+ }
39
+ catch (error) {
40
+ console.warn(`[shadowDom] Could not search for "${selector}":`, error);
41
+ return null;
42
+ }
43
+ }
44
+ /** `document.querySelectorAll(selector)` as a list, but in the tree `anchor` lives in. */
45
+ export function queryAllInTreeOf(anchor, selector) {
46
+ try {
47
+ return Array.from(treeOf(anchor)?.querySelectorAll(selector) ?? []);
48
+ }
49
+ catch (error) {
50
+ console.warn(`[shadowDom] Could not search for "${selector}":`, error);
51
+ return [];
52
+ }
53
+ }
54
+ /**
55
+ * Whether an event happened inside `element`. Heard on the document or the window, an event that started inside a
56
+ * shadow root has the shadow root's host as its target, so `element.contains(event.target)` is false for everything
57
+ * inside the editor; the event's path still lists the elements it really went through. (Call it while the event is
58
+ * being handled: the path is gone once handling is over.)
59
+ */
60
+ export function isEventInside(event, element) {
61
+ if (!element)
62
+ return false;
63
+ try {
64
+ const path = event.composedPath?.();
65
+ if (path && path.length > 0)
66
+ return path.includes(element);
67
+ return element.contains(event.target);
68
+ }
69
+ catch (error) {
70
+ console.warn('[shadowDom] Could not tell where an event happened:', error);
71
+ return false;
72
+ }
73
+ }
74
+ /**
75
+ * The element that has the keyboard focus in the tree `anchor` lives in. `document.activeElement` is the module's
76
+ * host element for anything focused inside a shadow root, which is never one of the editor's fields.
77
+ */
78
+ export function activeElementIn(anchor) {
79
+ try {
80
+ const rootNode = anchor?.getRootNode?.();
81
+ if (rootNode && (rootNode.nodeType === DOCUMENT_NODE || rootNode.nodeType === DOCUMENT_FRAGMENT_NODE)) {
82
+ return rootNode.activeElement ?? null;
83
+ }
84
+ }
85
+ catch (error) {
86
+ console.warn('[shadowDom] Could not tell which element has the focus:', error);
87
+ }
88
+ return typeof document === 'undefined' ? null : document.activeElement;
89
+ }
90
+ /**
91
+ * Calls `handler` when something scrolls and gives back the function that stops it. A scroll is not an event that
92
+ * leaves a shadow root, so a listener on the window only hears about the page being scrolled; to hear about the
93
+ * editor's own panels scrolling the listener goes on the shadow root too. Both are listened to while the event goes
94
+ * down (capture), as a scroll does not bubble.
95
+ */
96
+ export function listenForScroll(anchor, handler, { passive = false } = {}) {
97
+ const targets = [];
98
+ if (typeof window !== 'undefined')
99
+ targets.push(window);
100
+ try {
101
+ const rootNode = anchor?.getRootNode?.();
102
+ if (rootNode?.nodeType === DOCUMENT_FRAGMENT_NODE)
103
+ targets.push(rootNode);
104
+ }
105
+ catch (error) {
106
+ console.warn('[shadowDom] Could not tell which tree to listen for scrolling in:', error);
107
+ }
108
+ for (const target of targets)
109
+ target.addEventListener('scroll', handler, { capture: true, passive });
110
+ return () => {
111
+ for (const target of targets)
112
+ target.removeEventListener('scroll', handler, true);
113
+ };
114
+ }
115
+ /** How many components use each popover layer, so the last one to leave can remove it. */
116
+ const portalHostUsers = new WeakMap();
117
+ /** The layers made here (a layer found already in place belongs to whoever made it). */
118
+ const portalHostsMadeHere = new WeakSet();
119
+ /**
120
+ * The layer a popover is drawn in when it must sit above everything else, found or made in the tree `anchor` lives in
121
+ * and shared by every component that asks for the same `id`. On a page it is a node at the end of the body; inside a
122
+ * module it is a node in the module's portal layer (or, failing that, in the shadow root), never in the customer's
123
+ * body. Give it back with `releasePortalHost` when the component goes away.
124
+ */
125
+ export function acquirePortalHost(anchor, id, zIndex = '100000000') {
126
+ try {
127
+ const tree = treeOf(anchor);
128
+ if (!tree)
129
+ return null;
130
+ let host = tree.getElementById(id);
131
+ if (!host) {
132
+ host = document.createElement('div');
133
+ host.id = id;
134
+ host.style.position = 'relative';
135
+ host.style.zIndex = zIndex;
136
+ const parent = tree.nodeType === DOCUMENT_FRAGMENT_NODE
137
+ ? (tree.querySelector(MODULE_PORTAL_LAYER_SELECTOR) ?? tree)
138
+ : document.body;
139
+ parent.appendChild(host);
140
+ portalHostsMadeHere.add(host);
141
+ }
142
+ portalHostUsers.set(host, (portalHostUsers.get(host) ?? 0) + 1);
143
+ return host;
144
+ }
145
+ catch (error) {
146
+ console.error(`[shadowDom] Could not make the "${id}" layer for popovers:`, error);
147
+ return null;
148
+ }
149
+ }
150
+ /** Gives a layer from `acquirePortalHost` back; the last one to give it back removes it from the page. */
151
+ export function releasePortalHost(host) {
152
+ if (!host)
153
+ return;
154
+ try {
155
+ const remaining = (portalHostUsers.get(host) ?? 1) - 1;
156
+ if (remaining > 0) {
157
+ portalHostUsers.set(host, remaining);
158
+ return;
159
+ }
160
+ portalHostUsers.delete(host);
161
+ if (portalHostsMadeHere.has(host)) {
162
+ portalHostsMadeHere.delete(host);
163
+ host.remove();
164
+ }
165
+ }
166
+ catch (error) {
167
+ console.error('[shadowDom] Could not remove the layer for popovers:', error);
168
+ }
169
+ }
170
+ /**
171
+ * The element a drag or a resize shows its cursor on: the host of the shadow root `anchor` lives in (the module the
172
+ * editor is in), or the page's body when it is not in a shadow root. The body of a customer's page is not the editor's
173
+ * to change, and an editor that sets a cursor there and then clears it also deletes the cursor the page had set.
174
+ */
175
+ function pointerStyleElementOf(anchor) {
176
+ const rootNode = anchor?.getRootNode?.();
177
+ if (rootNode?.nodeType === DOCUMENT_FRAGMENT_NODE && rootNode.host) {
178
+ return rootNode.host;
179
+ }
180
+ return typeof document === 'undefined' ? null : document.body;
181
+ }
182
+ /**
183
+ * Shows `cursor` for as long as a drag or a resize lasts (and, unless told otherwise, stops text from being selected as
184
+ * the pointer moves). Gives back the function that puts back what was there before; it puts it back once, however
185
+ * often it is called, so it can be called from every way a gesture can end.
186
+ */
187
+ export function lockPointerStyle(anchor, cursor, { blockTextSelection = true } = {}) {
188
+ try {
189
+ const styledElement = pointerStyleElementOf(anchor);
190
+ if (!styledElement)
191
+ return () => { };
192
+ const previousCursor = styledElement.style.cursor;
193
+ const previousUserSelect = styledElement.style.userSelect;
194
+ styledElement.style.cursor = cursor;
195
+ if (blockTextSelection)
196
+ styledElement.style.userSelect = 'none';
197
+ let isRestored = false;
198
+ return () => {
199
+ if (isRestored)
200
+ return;
201
+ isRestored = true;
202
+ styledElement.style.cursor = previousCursor;
203
+ if (blockTextSelection)
204
+ styledElement.style.userSelect = previousUserSelect;
205
+ };
206
+ }
207
+ catch (error) {
208
+ console.error('[shadowDom] Could not change the pointer for the drag:', error);
209
+ return () => { };
210
+ }
211
+ }
@@ -1,4 +1,5 @@
1
1
  import { writable } from 'svelte/store';
2
+ import { readEditorStorageValue, writeEditorStorageValue } from './editorStorage';
2
3
  export const vectorCategories = {
3
4
  map: {
4
5
  'icons': 'Icons',
@@ -22,13 +23,14 @@ export const vectorCategories = {
22
23
  return 'Icons'; // Default category
23
24
  }
24
25
  };
26
+ // Stored in the editor's own corner of localStorage (see editorStorage.ts), not under a key the customer's page may use.
25
27
  const RECENT_VECTORS_KEY = 'recent_vectors';
26
28
  const MAX_RECENT_VECTORS = 3;
27
29
  export const recentVectorsStore = writable([]);
28
30
  export const vectorUtils = {
29
31
  getRecentVectors() {
30
32
  try {
31
- const stored = localStorage.getItem(RECENT_VECTORS_KEY);
33
+ const stored = readEditorStorageValue(RECENT_VECTORS_KEY);
32
34
  return stored ? JSON.parse(stored) : [];
33
35
  }
34
36
  catch (error) {
@@ -47,7 +49,7 @@ export const vectorUtils = {
47
49
  },
48
50
  ...filteredVectors
49
51
  ].slice(0, MAX_RECENT_VECTORS);
50
- localStorage.setItem(RECENT_VECTORS_KEY, JSON.stringify(newRecentVectors));
52
+ writeEditorStorageValue(RECENT_VECTORS_KEY, JSON.stringify(newRecentVectors));
51
53
  recentVectorsStore.set(newRecentVectors);
52
54
  return newRecentVectors;
53
55
  }
@@ -60,7 +62,7 @@ export const vectorUtils = {
60
62
  try {
61
63
  const recentVectors = this.getRecentVectors();
62
64
  const filteredVectors = recentVectors.filter(v => v.name !== name);
63
- localStorage.setItem(RECENT_VECTORS_KEY, JSON.stringify(filteredVectors));
65
+ writeEditorStorageValue(RECENT_VECTORS_KEY, JSON.stringify(filteredVectors));
64
66
  return filteredVectors;
65
67
  }
66
68
  catch (error) {
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Decides, from the condition a widget's schema gives a control (`autoplay === true`), whether the control is shown.
3
+ *
4
+ * The condition is text that comes with a widget, written by whoever made the widget, and the editor can run inside
5
+ * a customer's own page. So it is never handed to `eval` or `new Function`: that would run the widget author's code
6
+ * with the rights of the customer's page (its cookies, its logged-in visitor, its API calls), and it fails outright
7
+ * under a Content-Security-Policy that does not allow `'unsafe-eval'`. It is read here instead, by a small parser for
8
+ * the part of JavaScript a condition is made of:
9
+ *
10
+ * - values: numbers, 'strings' and "strings", true, false, null, undefined, and [lists];
11
+ * - the settings the condition depends on, by name (`autoplay`), with `.name` and `[key]` to look inside them;
12
+ * - comparisons (`===` `!==` `==` `!=` `<` `<=` `>` `>=`), `&&`, `||`, `??`, `!`, `+ - * / %`, `a ? b : c`, brackets;
13
+ * - the methods `includes`, `indexOf`, `startsWith`, `endsWith`, `toLowerCase`, `toUpperCase` and `trim`.
14
+ *
15
+ * It can read the values it is given and nothing else: no globals (`window`, `document`, `Function`), no other call,
16
+ * no assignment, no template string, no `constructor` or `__proto__`.
17
+ */
18
+ /** The current value of each setting a condition may name. */
19
+ export type ConditionValues = Record<string, unknown>;
20
+ /** A condition that cannot be read or cannot be worked out. */
21
+ export declare class ConditionError extends Error {
22
+ constructor(message: string);
23
+ }
24
+ /** Longer than any real condition; a limit so that a hostile schema cannot make the editor work for long. */
25
+ export declare const MAX_CONDITION_LENGTH = 1000;
26
+ /** How deeply brackets, lists, `!`s and `?:` may be nested; a limit that keeps the parser from running out of stack. */
27
+ export declare const MAX_CONDITION_DEPTH = 40;
28
+ /**
29
+ * Works out a condition from the values of the settings it names, the way JavaScript would.
30
+ *
31
+ * @throws {ConditionError} when the condition cannot be read, names something that is not in `values`, or cannot be
32
+ * worked out (looking inside a setting that has no value, say).
33
+ */
34
+ export declare function evaluateCondition(condition: string, values: ConditionValues): unknown;
35
+ /**
36
+ * Whether a control whose condition is `condition` is shown. A condition the editor cannot use (it is not valid, or
37
+ * names a setting it does not depend on) keeps the control shown: a mistake in a widget's schema must not hide one of
38
+ * its settings for good. The problem is reported in the console, once per condition.
39
+ */
40
+ export declare function conditionHolds(condition: string, values: ConditionValues): boolean;