@liquefy/cascade.ui 1.0.0 → 2.1.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.
@@ -0,0 +1,84 @@
1
+ import { Component, frozen, callback } from "@liquefy/cascade.component";
2
+ import { span, text } from "@liquefy/cascade.dom";
3
+ import { button, icon, card, listItem } from "./widgets.js";
4
+ import { popover } from "./Popover.js";
5
+
6
+ /**
7
+ * Dropdown - one choice out of several, compactly: a button showing the
8
+ * choice made, opening a list of them all below it (a popover - see
9
+ * Popover.js). Made of the theme's own widgets - button, card, list
10
+ * items - so it looks like the rest of whatever theme it's in.
11
+ *
12
+ * dropdown({
13
+ * options: [{ value: "Title", label: "Title", style: { fontWeight: 700 } }, ...],
14
+ * value: "Title",
15
+ * onSelect: (value) => ...,
16
+ * })
17
+ *
18
+ * - options: `{ value, label, style }` - `style`, if given, is the label's
19
+ * own in the list: a preview of what choosing it means (a font, say).
20
+ * - value: the option chosen - none shows `placeholder`.
21
+ * - onSelect(value): called with the option clicked; the list closes.
22
+ * - disabled, title, placeholder, style (the button's).
23
+ */
24
+ export function dropdown(...parameters) {
25
+ return new Dropdown(...parameters);
26
+ }
27
+
28
+ export class Dropdown extends Component {
29
+ setProperties({ options, value, onSelect, disabled, title, placeholder, style }) {
30
+ this.options = frozen(options || []);
31
+ this.value = value;
32
+ this.onSelect = onSelect || null;
33
+ this.disabled = !!disabled;
34
+ this.title = title || undefined;
35
+ this.placeholder = placeholder || "";
36
+ this.style = frozen(style || null);
37
+ }
38
+
39
+ initialState() {
40
+ return { open: false, anchor: null };
41
+ }
42
+
43
+ choose(value) {
44
+ this.open = false;
45
+ if (this.onSelect) this.onSelect(value);
46
+ }
47
+
48
+ build() {
49
+ // Disabled while open: closed, for good - not hidden only to pop open on
50
+ // its own again once it's enabled.
51
+ if (this.disabled && this.open) this.setState({ open: false });
52
+ const chosen = this.options.find((option) => option.value === this.value);
53
+ return [
54
+ button(
55
+ {
56
+ disabled: this.disabled,
57
+ title: this.title,
58
+ style: { justifyContent: "space-between", gap: "4px", paddingRight: "6px", ...this.style },
59
+ onClick: callback("toggle", (event) => {
60
+ // The button itself - the list follows it, should it move.
61
+ this.anchor = event.currentTarget;
62
+ this.open = !this.open;
63
+ }),
64
+ },
65
+ text(chosen ? chosen.label : this.placeholder),
66
+ icon({ name: "arrow_drop_down" }),
67
+ ),
68
+ popover(
69
+ { anchor: this.anchor, showing: this.open, close: callback("close", () => { this.open = false; }) },
70
+ card(
71
+ { style: { padding: "4px", display: "flex", flexDirection: "column", gap: "2px", minWidth: "160px", maxHeight: "60vh", overflowY: "auto", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.25)" } },
72
+ this.options.map((option) => listItem(
73
+ {
74
+ key: "option" + option.value,
75
+ active: option.value === this.value,
76
+ onClick: callback("choose" + option.value, () => this.choose(option.value)),
77
+ },
78
+ span({ style: option.style || {} }, text(option.label)),
79
+ )),
80
+ ),
81
+ ),
82
+ ];
83
+ }
84
+ }
package/src/Layout.js CHANGED
@@ -1,120 +1,153 @@
1
- import { toPropertiesWithChildren } from "@liquefy/cascade.component";
2
- import { div } from "@liquefy/cascade.dom";
3
-
4
- /**
5
- * Layout - ported from flow.ui/basic/src/Layout.js: a small kit of style
6
- * constants plus the styled-div functions built from them, all following
7
- * the same unwritten flow convention every component's own doc in this
8
- * codebase now points back to (see cascade.DOM/src/applyStyle.js): every
9
- * one of these takes an optional `style` property, merged as
10
- * `{...ownDefault, ...style}` - the caller's own value always wins - and
11
- * applied straight onto the one div each of these builds, not onto some
12
- * further wrapper. That's the actual mechanism behind "extra divs are
13
- * usually unnecessary": a creator styles its child directly, including
14
- * fitting it into a flex row/column or making it fill its container,
15
- * instead of wrapping it in a div dedicated to just that.
16
- *
17
- * Two style families here, not one "fillStyle": fitContainerStyle sizes by
18
- * *absolute* dimensions (width/height: 100% of the parent's own box, no
19
- * flex participation implied), fillerStyle sizes by *flex* participation
20
- * (flexGrow/Shrink: 1, flexBasis: 0 - takes an equal share of whatever
21
- * room a flex row/column has left). Reach for fitContainerStyle when the
22
- * parent isn't a flex container (or you want 100% regardless of flex
23
- * distribution) and fillerStyle when it is and you want this child to
24
- * share/absorb the remaining space with its siblings.
25
- *
26
- * One deliberate correction from flow's own copy: flow.ui/basic/src/Layout.js's
27
- * own flexContainerStyle sets `justifyContent: "flexStart"` - not valid CSS
28
- * (camelCase is for the *property* name in a JS style object, not a
29
- * property's *value* - the real value is the kebab-case string
30
- * "flex-start"). Harmless there in practice (an invalid value is simply
31
- * ignored, and justify-content's own initial value, "normal", already packs
32
- * items at the start for ordinary content) but not worth reproducing
33
- * knowingly - fixed here to the real value.
34
- *
35
- * flow's own componentTypeName argument to styledDiv() (purely a debug-id
36
- * label, baked into flow.core's own aggregateToString()-style element id)
37
- * isn't ported - cascade.DOM's DOMElementComponent doesn't have an equivalent
38
- * hook yet (setProperties() has no special case for it, so passing one
39
- * through today would just land as a meaningless "componenttypename" DOM
40
- * attribute instead). Every element built here still gets a real, unique
41
- * debug id from DOMNodeRenderComponent's own aggregateToString() fallback
42
- * (this.constructor.name-based) - just not one that says "row" vs "column".
43
- */
44
-
45
- // --- Basic layout styles ---
46
-
47
- export const flexContainerStyle = {
48
- overflow: "hidden",
49
- boxSizing: "border-box",
50
- display: "flex",
51
- alignItems: "stretch",
52
- justifyContent: "flex-start",
53
- whiteSpace: "normal",
54
- userSelect: "none",
55
- };
56
-
57
- export const rowStyle = { ...flexContainerStyle, flexDirection: "row" };
58
- export const columnStyle = { ...flexContainerStyle, flexDirection: "column" };
59
-
60
- export const centerStyle = { ...rowStyle, justifyContent: "center", alignItems: "stretch" };
61
- export const middleStyle = { ...columnStyle, justifyContent: "center", alignItems: "stretch" };
62
- export const centerMiddleStyle = { ...rowStyle, justifyContent: "center", alignItems: "center" };
63
-
64
- // --- Basic element styles ---
65
-
66
- // For a bottom-up component inside a scroll container - sized by its own
67
- // content, not stretched or shrunk to fit.
68
- export const naturalSizeStyle = { overflow: "visible", flexGrow: "0", flexShrink: "0", flexBasis: "auto" };
69
-
70
- // Fill 100% of the parent's own box - absolute sizing, no flex participation
71
- // implied (works inside or outside a flex container).
72
- export const fitContainerStyle = { overflow: "hidden", boxSizing: "border-box", width: "100%", height: "100%" };
73
-
74
- // Grow/shrink to take an equal share of whatever room is left in a flex
75
- // row/column, ignoring its own content's natural size - scroll panels,
76
- // equal space distribution.
77
- export const fillerStyle = { overflow: "hidden", boxSizing: "border-box", flexGrow: "1", flexShrink: "1", flexBasis: "0" };
78
-
79
- // Same, but based on its own content's natural size rather than an equal
80
- // 0-basis share - grows/shrinks around whatever it would naturally be.
81
- export const autoFillerStyle = { overflow: "hidden", boxSizing: "border-box", flexGrow: "1", flexShrink: "1", flexBasis: "auto" };
82
-
83
- // Visualizes a component's own bounds during development - not meant to
84
- // ship.
85
- export const layoutBorderStyle = { borderStyle: "solid", borderColor: "light-gray", borderWidth: "1px", boxSizing: "border-box" };
86
-
87
- // Opts back out of fitContainerStyle/fillerStyle's own overflow: hidden -
88
- // for content that must be allowed to overflow its own box (an animation,
89
- // a popover, ...).
90
- export const overflowVisibleStyle = { overflow: "visible" };
91
-
92
- // --- styledDiv: the shared mechanism behind every function below ---
93
-
94
- // A div (asked for through the service locator, like any div() call) with
95
- // `defaultStyle` merged underneath whatever `style` property is given, so
96
- // the caller's own value always wins (see this file's own class doc).
97
- function styledDiv(defaultStyle, parameters) {
98
- const properties = toPropertiesWithChildren(parameters);
99
- properties.style = { ...defaultStyle, ...properties.style };
100
- return div(properties);
101
- }
102
-
103
- // --- Basic layout containers ---
104
-
105
- export const wrapper = (...parameters) => styledDiv({}, parameters);
106
- export const row = (...parameters) => styledDiv(rowStyle, parameters);
107
- export const column = (...parameters) => styledDiv(columnStyle, parameters);
108
- export const center = (...parameters) => styledDiv(centerStyle, parameters);
109
- export const middle = (...parameters) => styledDiv(middleStyle, parameters);
110
- export const centerMiddle = (...parameters) => styledDiv(centerMiddleStyle, parameters);
111
-
112
- // --- Basic layout fillers ---
113
-
114
- export const filler = (...parameters) => styledDiv(fillerStyle, parameters);
115
-
116
- // --- zStack: children stacked on top of each other, edge to edge ---
117
-
118
- export const zStackElementStyle = { ...fitContainerStyle, position: "absolute", top: 0, left: 0, width: "100%", height: "100%" };
119
-
120
- export const zStack = (...parameters) => styledDiv({ position: "relative" }, parameters);
1
+ import { toPropertiesWithChildren } from "@liquefy/cascade.component";
2
+ import { div } from "@liquefy/cascade.dom";
3
+
4
+ /**
5
+ * Layout - ported from flow.ui/basic/src/Layout.js: a small kit of style
6
+ * constants plus the styled-div functions built from them, all following
7
+ * the same unwritten flow convention every component's own doc in this
8
+ * codebase now points back to (see cascade.DOM/src/applyStyle.js): every
9
+ * one of these takes an optional `style` property, merged as
10
+ * `{...ownDefault, ...style}` - the caller's own value always wins - and
11
+ * applied straight onto the one div each of these builds, not onto some
12
+ * further wrapper. That's the actual mechanism behind "extra divs are
13
+ * usually unnecessary": a creator styles its child directly, including
14
+ * fitting it into a flex row/column or making it fill its container,
15
+ * instead of wrapping it in a div dedicated to just that.
16
+ *
17
+ * Two style families here, not one "fillStyle": fitContainerStyle sizes by
18
+ * *absolute* dimensions (width/height: 100% of the parent's own box, no
19
+ * flex participation implied), fillerStyle sizes by *flex* participation
20
+ * (flexGrow/Shrink: 1, flexBasis: 0 - takes an equal share of whatever
21
+ * room a flex row/column has left). Reach for fitContainerStyle when the
22
+ * parent isn't a flex container (or you want 100% regardless of flex
23
+ * distribution) and fillerStyle when it is and you want this child to
24
+ * share/absorb the remaining space with its siblings.
25
+ *
26
+ * One deliberate correction from flow's own copy: flow.ui/basic/src/Layout.js's
27
+ * own flexContainerStyle sets `justifyContent: "flexStart"` - not valid CSS
28
+ * (camelCase is for the *property* name in a JS style object, not a
29
+ * property's *value* - the real value is the kebab-case string
30
+ * "flex-start"). Harmless there in practice (an invalid value is simply
31
+ * ignored, and justify-content's own initial value, "normal", already packs
32
+ * items at the start for ordinary content) but not worth reproducing
33
+ * knowingly - fixed here to the real value.
34
+ *
35
+ * flow's own componentTypeName argument to styledDiv() (purely a debug-id
36
+ * label, baked into flow.core's own aggregateToString()-style element id)
37
+ * isn't ported - cascade.DOM's DOMElementComponent doesn't have an equivalent
38
+ * hook yet (setProperties() has no special case for it, so passing one
39
+ * through today would just land as a meaningless "componenttypename" DOM
40
+ * attribute instead). Every element built here still gets a real, unique
41
+ * debug id from DOMNodeComponent's own aggregateToString() fallback
42
+ * (this.constructor.name-based) - just not one that says "row" vs "column".
43
+ */
44
+
45
+ // --- Basic layout styles ---
46
+
47
+ // No overflow: hidden, unlike flow's: flow clipped every layout container,
48
+ // for a strict top-down layout that made bounds easier to calculate further
49
+ // down - measured bounds (cascade.dom's elementBoundsProvider()) do that job
50
+ // now. What it did for flex layout is kept, though: min-width/min-height 0
51
+ // let a container shrink below its content's size in the row or column
52
+ // it's in (flex items don't, by default - they'd push the row wider
53
+ // instead). Its content then overflows, visibly, where it doesn't fit;
54
+ // clip it where that's wanted (overflow: "hidden" in its style). And text
55
+ // in it can be selected, like text anywhere else.
56
+ const shrinkable = { minWidth: 0, minHeight: 0 };
57
+
58
+ export const flexContainerStyle = {
59
+ ...shrinkable,
60
+ boxSizing: "border-box",
61
+ display: "flex",
62
+ alignItems: "stretch",
63
+ justifyContent: "flex-start",
64
+ whiteSpace: "normal",
65
+ };
66
+
67
+ export const rowStyle = { ...flexContainerStyle, flexDirection: "row" };
68
+ export const columnStyle = { ...flexContainerStyle, flexDirection: "column" };
69
+
70
+ export const centerStyle = { ...rowStyle, justifyContent: "center", alignItems: "stretch" };
71
+ export const middleStyle = { ...columnStyle, justifyContent: "center", alignItems: "stretch" };
72
+ export const centerMiddleStyle = { ...rowStyle, justifyContent: "center", alignItems: "center" };
73
+
74
+ // --- Basic element styles ---
75
+
76
+ // For a bottom-up component inside a scroll container - sized by its own
77
+ // content, not stretched or shrunk to fit.
78
+ export const naturalSizeStyle = { overflow: "visible", flexGrow: "0", flexShrink: "0", flexBasis: "auto" };
79
+
80
+ // Fill 100% of the parent's own box - absolute sizing, no flex participation
81
+ // implied (works inside or outside a flex container).
82
+ export const fitContainerStyle = { ...shrinkable, boxSizing: "border-box", width: "100%", height: "100%" };
83
+
84
+ // Grow/shrink to take an equal share of whatever room is left in a flex
85
+ // row/column, ignoring its own content's natural size - scroll panels,
86
+ // equal space distribution.
87
+ export const fillerStyle = { ...shrinkable, boxSizing: "border-box", flexGrow: "1", flexShrink: "1", flexBasis: "0" };
88
+
89
+ // Same, but based on its own content's natural size rather than an equal
90
+ // 0-basis share - grows/shrinks around whatever it would naturally be.
91
+ export const autoFillerStyle = { ...shrinkable, boxSizing: "border-box", flexGrow: "1", flexShrink: "1", flexBasis: "auto" };
92
+
93
+ // Visualizes a component's own bounds during development - not meant to
94
+ // ship.
95
+ export const layoutBorderStyle = { borderStyle: "solid", borderColor: "lightgray", borderWidth: "1px", boxSizing: "border-box" };
96
+
97
+ // Content allowed to overflow its own box - what every layout container
98
+ // here does already (there's no clipping by default any more); kept for
99
+ // what's written against the old default.
100
+ export const overflowVisibleStyle = { overflow: "visible" };
101
+
102
+ // --- styledDiv: the shared mechanism behind every function below ---
103
+
104
+ // A div (asked for through the service locator, like any div() call) with
105
+ // `defaultStyle` merged underneath whatever `style` property is given, so
106
+ // the caller's own value always wins (see this file's own class doc).
107
+ function styledDiv(defaultStyle, parameters) {
108
+ const properties = toPropertiesWithChildren(parameters);
109
+ properties.style = { ...defaultStyle, ...properties.style };
110
+ return div(properties);
111
+ }
112
+
113
+ // --- Basic layout containers ---
114
+
115
+ export const wrapper = (...parameters) => styledDiv({}, parameters);
116
+ export const row = (...parameters) => styledDiv(rowStyle, parameters);
117
+ export const column = (...parameters) => styledDiv(columnStyle, parameters);
118
+ export const center = (...parameters) => styledDiv(centerStyle, parameters);
119
+ export const middle = (...parameters) => styledDiv(middleStyle, parameters);
120
+ export const centerMiddle = (...parameters) => styledDiv(centerMiddleStyle, parameters);
121
+
122
+ // --- Basic layout fillers ---
123
+
124
+ export const filler = (...parameters) => styledDiv(fillerStyle, parameters);
125
+
126
+ // --- zStack: children stacked on top of each other, edge to edge ---
127
+
128
+ // What each child of a zStack gets - by the zStack itself (a class, and a
129
+ // stylesheet rule for its direct children), so its children need no style
130
+ // of their own for it. A child's own style still wins: it can deviate.
131
+ export const zStackElementStyle = { ...fitContainerStyle, position: "absolute", top: 0, left: 0, width: "100%", height: "100%" };
132
+
133
+ const zStackClass = "cascade-z-stack";
134
+ const documentsStyled = new WeakSet();
135
+
136
+ function ensureZStackRule() {
137
+ if (typeof(document) === "undefined" || !document.head || documentsStyled.has(document)) return;
138
+ documentsStyled.add(document);
139
+ const element = document.createElement("style");
140
+ element.setAttribute("data-cascade-layout", "");
141
+ element.textContent = "." + zStackClass + " > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; min-width: 0; min-height: 0; }";
142
+ document.head.appendChild(element);
143
+ }
144
+
145
+ export const zStack = (...parameters) => {
146
+ ensureZStackRule();
147
+ const properties = toPropertiesWithChildren(parameters);
148
+ const given = properties.className || properties.class;
149
+ delete properties.className;
150
+ properties.class = given ? zStackClass + " " + given : zStackClass;
151
+ properties.style = { position: "relative", ...properties.style };
152
+ return div(properties);
153
+ };
package/src/Modal.js ADDED
@@ -0,0 +1,136 @@
1
+ import { Component, frozen, observable, accessInitialValues, withoutRecording } from "@liquefy/cascade.component";
2
+ import { div } from "@liquefy/cascade.dom";
3
+
4
+ /**
5
+ * Modals - ready-made pieces for what an overlay() shows, each usable on
6
+ * its own:
7
+ *
8
+ * - modalBackdrop({ close, style }): the dimmed layer behind a modal,
9
+ * covering the frame; a click on it calls `close`.
10
+ * - modal({ fullScreen, width, height, style }, content): places its
11
+ * content in the frame - a window of the given size, centered, or
12
+ * (`fullScreen`) filling the whole frame. The content fills it. What's
13
+ * inside can tell which: modal() provides `modalPresentation`
14
+ * ("window" or "fullScreen") - a themed dialog() goes full screen by
15
+ * itself, back arrow and all.
16
+ * - modalAssembly({ close, fullScreenBelow, width, height, backdrop }, content):
17
+ * both - a backdrop (unless `backdrop: false`) and a modal - and full
18
+ * screen, without a backdrop, while the frame is narrower than
19
+ * `fullScreenBelow` (a phone's screen): it reads the frame's size where
20
+ * it's shown (see OverlayFrame - a layer is a measured element).
21
+ *
22
+ * The ready-to-go way to show a dialog modally, then:
23
+ *
24
+ * overlay({ showing: this.open },
25
+ * modalAssembly({ close, fullScreenBelow: 600, width: 360 },
26
+ * dialog({ title: "Settings", close }, ...)))
27
+ *
28
+ * And for anything else - an animated entrance, a sheet sliding up from
29
+ * below - overlay() takes any content at all, a backdrop of its own
30
+ * included.
31
+ */
32
+ export function modalBackdrop(...parameters) {
33
+ return new ModalBackdrop(...parameters);
34
+ }
35
+
36
+ export function modal(...parameters) {
37
+ return new Modal(...parameters);
38
+ }
39
+
40
+ export function modalAssembly(...parameters) {
41
+ return new ModalAssembly(...parameters);
42
+ }
43
+
44
+ // The dimmed layer behind a modal - where a click closes it.
45
+ export const modalBackdropColor = "rgba(0, 0, 0, 0.4)";
46
+
47
+ const coverFrame = { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", boxSizing: "border-box" };
48
+
49
+ export class ModalBackdrop extends Component {
50
+ setProperties({ close, style }) {
51
+ this.close = close || null;
52
+ this.style = frozen(style || null);
53
+ }
54
+
55
+ build() {
56
+ return div({
57
+ onclick: this.close,
58
+ style: { ...coverFrame, pointerEvents: "auto", background: modalBackdropColor, ...this.style },
59
+ });
60
+ }
61
+ }
62
+
63
+ export class Modal extends Component {
64
+ setProperties({ fullScreen, width, height, style, children }) {
65
+ this.fullScreen = !!fullScreen;
66
+ this.width = typeof(width) === "number" ? width + "px" : (width || null);
67
+ this.height = typeof(height) === "number" ? height + "px" : (height || null);
68
+ this.style = frozen(style || null);
69
+ this.modalChildren = frozen(children || []);
70
+ }
71
+
72
+ // What's inside can tell how it's presented - not a size, a mode, the
73
+ // same for everything in it. An object of its own, rewritten at the
74
+ // baseline when it changes, as everything a context holds (see
75
+ // cascade.component's RenderContext.js).
76
+ provide() {
77
+ const u = this.unobservable;
78
+ if (!u.provided) u.provided = observable({ modalPresentation: this.presentation() });
79
+ return u.provided;
80
+ }
81
+
82
+ presentation() {
83
+ return this.fullScreen ? "fullScreen" : "window";
84
+ }
85
+
86
+ build() {
87
+ const presentation = this.presentation();
88
+ const provided = this.provide();
89
+ if (withoutRecording(() => provided.modalPresentation) !== presentation) {
90
+ accessInitialValues(() => { provided.modalPresentation = presentation; });
91
+ }
92
+ // The content fills whatever it's in: the frame, or the window.
93
+ const box = { display: "flex", flexDirection: "column", boxSizing: "border-box", pointerEvents: "auto" };
94
+ if (this.fullScreen) {
95
+ return div({ style: { ...coverFrame, ...box, ...this.style } }, this.modalChildren);
96
+ }
97
+ return div(
98
+ { style: { ...coverFrame, display: "flex", alignItems: "center", justifyContent: "center", pointerEvents: "none" } },
99
+ div(
100
+ { style: { ...box, width: this.width || "auto", height: this.height || "auto", maxWidth: "100%", maxHeight: "100%", ...this.style } },
101
+ this.modalChildren,
102
+ ),
103
+ );
104
+ }
105
+ }
106
+
107
+ export class ModalAssembly extends Component {
108
+ setProperties({ close, fullScreen, fullScreenBelow, width, height, backdrop, style, children }) {
109
+ this.close = close || null;
110
+ this.fullScreen = typeof(fullScreen) === "boolean" ? fullScreen : null;
111
+ this.fullScreenBelow = typeof(fullScreenBelow) === "number" ? fullScreenBelow : null;
112
+ this.width = width;
113
+ this.height = height;
114
+ this.backdrop = backdrop !== false;
115
+ this.style = frozen(style || null);
116
+ this.modalChildren = frozen(children || []);
117
+ }
118
+
119
+ // Full screen: as told - or below `fullScreenBelow`, by the width of the
120
+ // frame it's shown in (a measured layer - see OverlayFrame).
121
+ isFullScreen() {
122
+ if (this.fullScreen !== null) return this.fullScreen;
123
+ if (this.fullScreenBelow === null) return false;
124
+ const width = this.fromTarget("width");
125
+ return typeof(width) === "number" && width < this.fullScreenBelow;
126
+ }
127
+
128
+ build() {
129
+ const fullScreen = this.isFullScreen();
130
+ return [
131
+ // Keyed: left out while full screen, and kept.
132
+ modalBackdrop({ key: "backdrop", close: this.close }).showIf(this.backdrop && !fullScreen),
133
+ modal({ fullScreen, width: this.width, height: this.height, style: this.style }, this.modalChildren),
134
+ ];
135
+ }
136
+ }