@jsswift/ui 1.0.54 → 2.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/dist/css/animation.css +36 -36
- package/dist/css/base.css +374 -374
- package/dist/css/docs.css +54 -54
- package/dist/css/fonts-nunito.css +2 -2
- package/dist/css/min-ui.css +1 -1
- package/dist/css/responsive-base.css +549 -549
- package/dist/css/responsive.css +3225 -3225
- package/dist/css/ui-components.css +2902 -2930
- package/dist/css/ui-light.css +3853 -3881
- package/dist/css/ui-light.min.css +1 -1
- package/dist/css/ui.css +6530 -6558
- package/dist/css/ui.min.css +1 -1
- package/dist/min-ui.js +12 -12
- package/dist/ui.js +4354 -9379
- package/dist/ui.min.js +12 -12
- package/package.json +2 -2
- package/src/00-bootstrap.js +305 -305
- package/src/01-foundation-helpers.js +328 -325
- package/src/10-primitives-layout.js +242 -242
- package/src/20-display-content.js +76 -76
- package/src/21-list-content.js +21 -21
- package/src/22-banner-content.js +376 -376
- package/src/23-tooltip.js +9 -9
- package/src/31-form-advanced.js +141 -141
- package/src/40-navigation.js +81 -81
- package/src/41-tab-panel.js +37 -37
- package/src/50-feedback.js +52 -52
- package/src/51-feedback-service.js +166 -166
- package/src/60-shell-app.js +1082 -1082
- package/src/61-form-service.js +5 -5
- package/src/70-dialog.js +34 -34
- package/src/71-menu-overlays.js +73 -73
- package/src/80-data.js +38 -38
- package/src/css/animation.css +36 -36
- package/src/css/base.css +374 -374
- package/src/css/docs.css +54 -54
- package/src/css/fonts-nunito.css +2 -2
- package/src/css/responsive.css +3225 -3225
- package/src/css/ui-components.css +2902 -2930
package/src/60-shell-app.js
CHANGED
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
UI.Header = (...args) => {
|
|
2
|
-
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
3
|
-
const slots = rawProps.slots || {};
|
|
4
|
-
const props = { ...rawProps };
|
|
5
|
-
applyCommonProps(props);
|
|
6
|
-
|
|
7
|
-
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(rawProps, key);
|
|
8
|
-
const currentStateKey = rawProps.drawerStateKey ?? drawerStateKey;
|
|
9
|
-
if (currentStateKey) {
|
|
10
|
-
drawerStateKey = currentStateKey;
|
|
11
|
-
drawerOpen = readDrawerOpen(currentStateKey);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const isDrawerOpen = () => readDrawerOpen(currentStateKey);
|
|
15
|
-
const openDrawer = () => setDrawerOpen(true, currentStateKey);
|
|
16
|
-
const closeDrawer = () => setDrawerOpen(false, currentStateKey);
|
|
17
|
-
const toggleDrawer = () => setDrawerOpen(!isDrawerOpen(), currentStateKey);
|
|
18
|
-
const ctx = {
|
|
19
|
-
props: rawProps,
|
|
20
|
-
stateKey: currentStateKey,
|
|
21
|
-
isDrawerOpen,
|
|
22
|
-
openDrawer,
|
|
23
|
-
closeDrawer,
|
|
24
|
-
toggleDrawer,
|
|
25
|
-
toggleAside: toggleDrawer
|
|
26
|
-
};
|
|
27
|
-
const appendResolvedValue = (host, value) => {
|
|
28
|
-
if (value == null || value === false) return;
|
|
29
|
-
if (Array.isArray(value)) {
|
|
30
|
-
value.forEach((item) => appendResolvedValue(host, item));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (value?.nodeType) {
|
|
34
|
-
host.appendChild(value);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
host.appendChild(document.createTextNode(String(value)));
|
|
38
|
-
};
|
|
39
|
-
const renderPropNodes = (name, fallback, map = (value) => value) => {
|
|
40
|
-
const slot = JSswift.ui.getSlot(slots, name);
|
|
41
|
-
if (slot !== null && slot !== undefined) {
|
|
42
|
-
return renderSlotToArray(slots, name, ctx, null);
|
|
43
|
-
}
|
|
44
|
-
if (typeof fallback === "function") {
|
|
45
|
-
const inlineNames = new Set(["eyebrow", "title", "subtitle"]);
|
|
46
|
-
const host = _[inlineNames.has(name) ? "span" : "div"]({ class: `
|
|
47
|
-
JSswift.reactive.effect(() => {
|
|
48
|
-
const nextValue = map(fallback(ctx));
|
|
49
|
-
const normalized = flattenSlotValue(JSswift.ui.slot(nextValue));
|
|
50
|
-
host.replaceChildren();
|
|
51
|
-
if (Array.isArray(normalized)) normalized.forEach((item) => appendResolvedValue(host, item));
|
|
52
|
-
else appendResolvedValue(host, normalized);
|
|
53
|
-
}, `UI.Header:${name}`);
|
|
54
|
-
return [host];
|
|
55
|
-
}
|
|
56
|
-
return renderSlotToArray(slots, name, ctx, map(fallback));
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const renderIconValue = (value, as = "icon", sizeFallback = rawProps.iconSize || rawProps.size || "md") => {
|
|
60
|
-
if (value == null || value === false) return null;
|
|
61
|
-
if (typeof value === "string") return UI.Icon({ name: value, size: sizeFallback });
|
|
62
|
-
return JSswift.ui.slot(value, { as });
|
|
63
|
-
};
|
|
64
|
-
const renderDrawerToggleValue = (open) => {
|
|
65
|
-
const value = open ? (rawProps.drawerOpenIcon ?? "✕") : (rawProps.drawerCloseIcon ?? "☰");
|
|
66
|
-
if (value == null || value === false) return null;
|
|
67
|
-
if (typeof value === "string") return value;
|
|
68
|
-
return JSswift.ui.slot(value, { as: open ? "drawerOpenIcon" : "drawerCloseIcon" });
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const toggleIconHost = _.span({ class: "
|
|
72
|
-
const paintToggleIcon = (open) => {
|
|
73
|
-
const nodes = renderSlotToArray(null, "default", ctx, renderDrawerToggleValue(open));
|
|
74
|
-
toggleIconHost.replaceChildren(...(nodes.length ? nodes : [""]));
|
|
75
|
-
};
|
|
76
|
-
paintToggleIcon(isDrawerOpen());
|
|
77
|
-
|
|
78
|
-
const autoLeft = UI.Btn({
|
|
79
|
-
class: "
|
|
80
|
-
outline: true,
|
|
81
|
-
size: rawProps.toggleSize ?? rawProps.size ?? "sm",
|
|
82
|
-
onClick: toggleDrawer,
|
|
83
|
-
"aria-label": rawProps.toggleLabel || "Toggle navigation"
|
|
84
|
-
}, toggleIconHost);
|
|
85
|
-
if (rawProps.left == null && rawProps.left !== false && !JSswift.ui.getSlot(slots, "left")) {
|
|
86
|
-
drawerToggleIcons.add({ update: paintToggleIcon });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const leftFallback = rawProps.left === false
|
|
90
|
-
? null
|
|
91
|
-
: (rawProps.left != null ? rawProps.left : autoLeft);
|
|
92
|
-
const titleFallback = hasOwn("title") ? rawProps.title : (rawProps.label ?? "App");
|
|
93
|
-
const subtitleFallback = rawProps.subtitle ?? rawProps.description ?? "";
|
|
94
|
-
const rightFallback = hasOwn("right") ? rawProps.right : rawProps.end;
|
|
95
|
-
const contentFallback = hasOwn("content")
|
|
96
|
-
? rawProps.content
|
|
97
|
-
: (hasOwn("body") ? rawProps.body : (children?.length ? children : null));
|
|
98
|
-
|
|
99
|
-
const startNodes = [
|
|
100
|
-
...renderPropNodes("left", leftFallback),
|
|
101
|
-
...renderPropNodes("start", null)
|
|
102
|
-
];
|
|
103
|
-
const iconNodes = renderPropNodes("icon", rawProps.icon, renderIconValue);
|
|
104
|
-
const eyebrowNodes = renderPropNodes("eyebrow", rawProps.eyebrow ?? rawProps.kicker);
|
|
105
|
-
const titleNodes = renderPropNodes("title", titleFallback);
|
|
106
|
-
const subtitleNodes = renderPropNodes("subtitle", subtitleFallback);
|
|
107
|
-
const metaNodes = renderPropNodes("meta", rawProps.meta);
|
|
108
|
-
const contentNodes = (() => {
|
|
109
|
-
const explicit = renderPropNodes("content", null);
|
|
110
|
-
return explicit.length ? explicit : renderPropNodes("default", contentFallback);
|
|
111
|
-
})();
|
|
112
|
-
const customCenterNodes = [
|
|
113
|
-
...renderPropNodes("center", null),
|
|
114
|
-
...renderPropNodes("body", null)
|
|
115
|
-
];
|
|
116
|
-
const rightNodes = [
|
|
117
|
-
...renderPropNodes("right", rightFallback),
|
|
118
|
-
...renderPropNodes("end", null)
|
|
119
|
-
];
|
|
120
|
-
const actionNodes = renderPropNodes("actions", rawProps.actions);
|
|
121
|
-
|
|
122
|
-
const structuredCenter = _.div(
|
|
123
|
-
{ class: uiClass(["
|
|
124
|
-
_.div(
|
|
125
|
-
{ class: "
|
|
126
|
-
iconNodes.length ? _.div({ class: "
|
|
127
|
-
_.div(
|
|
128
|
-
{ class: "
|
|
129
|
-
eyebrowNodes.length ? _.div({ class: uiClass(["
|
|
130
|
-
titleNodes.length ? _.div({ class: uiClass(["
|
|
131
|
-
subtitleNodes.length ? _.div({ class: uiClass(["
|
|
132
|
-
contentNodes.length ? _.div({ class: uiClass(["
|
|
133
|
-
),
|
|
134
|
-
metaNodes.length ? _.div({ class: uiClass(["
|
|
135
|
-
)
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
const endContent = [
|
|
139
|
-
...rightNodes,
|
|
140
|
-
...(actionNodes.length ? [_.div({ class: uiClass(["
|
|
141
|
-
];
|
|
142
|
-
|
|
143
|
-
const p = JSswift.omit(props, [
|
|
144
|
-
"actions", "actionsClass", "body", "bodyClass", "centerClass", "content", "contentClass",
|
|
145
|
-
"description", "divider", "drawerCloseIcon", "drawerOpenIcon", "drawerStateKey", "elevated",
|
|
146
|
-
"end", "eyebrow", "eyebrowClass", "icon", "iconSize", "kicker", "label", "left", "meta",
|
|
147
|
-
"metaClass", "right", "slots", "stack", "sticky", "subtitle", "subtitleClass", "title",
|
|
148
|
-
"titleClass", "toggleLabel", "toggleSize", "gap", "minHeight", "startClass", "endClass"
|
|
149
|
-
]);
|
|
150
|
-
p.class = uiClass([
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
uiWhen(rawProps.sticky !== false, "sticky"),
|
|
155
|
-
uiWhen(rawProps.stack, "stack"),
|
|
156
|
-
uiWhen(rawProps.elevated, "elevated"),
|
|
157
|
-
uiWhen(rawProps.divider !== false, "divider"),
|
|
158
|
-
props.class
|
|
159
|
-
]);
|
|
160
|
-
p.style = { ...(props.style || {}) };
|
|
161
|
-
if (rawProps.gap != null) p.style["--
|
|
162
|
-
if (rawProps.minHeight != null) p.style.minHeight = toCssSize(uiUnwrap(rawProps.minHeight));
|
|
163
|
-
|
|
164
|
-
const el = _.div(
|
|
165
|
-
p,
|
|
166
|
-
...(startNodes.length ? [_.div({ class: uiClass(["
|
|
167
|
-
_.div(
|
|
168
|
-
{ class: "
|
|
169
|
-
...(customCenterNodes.length
|
|
170
|
-
? [_.div({ class: uiClass(["
|
|
171
|
-
: [structuredCenter]),
|
|
172
|
-
...(endContent.length ? [_.div({ class: uiClass(["
|
|
173
|
-
)
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
setPropertyProps(el, rawProps);
|
|
177
|
-
return el;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
|
|
1
|
+
UI.Header = (...args) => {
|
|
2
|
+
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
3
|
+
const slots = rawProps.slots || {};
|
|
4
|
+
const props = { ...rawProps };
|
|
5
|
+
applyCommonProps(props);
|
|
6
|
+
|
|
7
|
+
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(rawProps, key);
|
|
8
|
+
const currentStateKey = rawProps.drawerStateKey ?? drawerStateKey;
|
|
9
|
+
if (currentStateKey) {
|
|
10
|
+
drawerStateKey = currentStateKey;
|
|
11
|
+
drawerOpen = readDrawerOpen(currentStateKey);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const isDrawerOpen = () => readDrawerOpen(currentStateKey);
|
|
15
|
+
const openDrawer = () => setDrawerOpen(true, currentStateKey);
|
|
16
|
+
const closeDrawer = () => setDrawerOpen(false, currentStateKey);
|
|
17
|
+
const toggleDrawer = () => setDrawerOpen(!isDrawerOpen(), currentStateKey);
|
|
18
|
+
const ctx = {
|
|
19
|
+
props: rawProps,
|
|
20
|
+
stateKey: currentStateKey,
|
|
21
|
+
isDrawerOpen,
|
|
22
|
+
openDrawer,
|
|
23
|
+
closeDrawer,
|
|
24
|
+
toggleDrawer,
|
|
25
|
+
toggleAside: toggleDrawer
|
|
26
|
+
};
|
|
27
|
+
const appendResolvedValue = (host, value) => {
|
|
28
|
+
if (value == null || value === false) return;
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
value.forEach((item) => appendResolvedValue(host, item));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (value?.nodeType) {
|
|
34
|
+
host.appendChild(value);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
host.appendChild(document.createTextNode(String(value)));
|
|
38
|
+
};
|
|
39
|
+
const renderPropNodes = (name, fallback, map = (value) => value) => {
|
|
40
|
+
const slot = JSswift.ui.getSlot(slots, name);
|
|
41
|
+
if (slot !== null && slot !== undefined) {
|
|
42
|
+
return renderSlotToArray(slots, name, ctx, null);
|
|
43
|
+
}
|
|
44
|
+
if (typeof fallback === "function") {
|
|
45
|
+
const inlineNames = new Set(["eyebrow", "title", "subtitle"]);
|
|
46
|
+
const host = _[inlineNames.has(name) ? "span" : "div"]({ class: `jss-header-slot-${name}` });
|
|
47
|
+
JSswift.reactive.effect(() => {
|
|
48
|
+
const nextValue = map(fallback(ctx));
|
|
49
|
+
const normalized = flattenSlotValue(JSswift.ui.slot(nextValue));
|
|
50
|
+
host.replaceChildren();
|
|
51
|
+
if (Array.isArray(normalized)) normalized.forEach((item) => appendResolvedValue(host, item));
|
|
52
|
+
else appendResolvedValue(host, normalized);
|
|
53
|
+
}, `UI.Header:${name}`);
|
|
54
|
+
return [host];
|
|
55
|
+
}
|
|
56
|
+
return renderSlotToArray(slots, name, ctx, map(fallback));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const renderIconValue = (value, as = "icon", sizeFallback = rawProps.iconSize || rawProps.size || "md") => {
|
|
60
|
+
if (value == null || value === false) return null;
|
|
61
|
+
if (typeof value === "string") return UI.Icon({ name: value, size: sizeFallback });
|
|
62
|
+
return JSswift.ui.slot(value, { as });
|
|
63
|
+
};
|
|
64
|
+
const renderDrawerToggleValue = (open) => {
|
|
65
|
+
const value = open ? (rawProps.drawerOpenIcon ?? "✕") : (rawProps.drawerCloseIcon ?? "☰");
|
|
66
|
+
if (value == null || value === false) return null;
|
|
67
|
+
if (typeof value === "string") return value;
|
|
68
|
+
return JSswift.ui.slot(value, { as: open ? "drawerOpenIcon" : "drawerCloseIcon" });
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const toggleIconHost = _.span({ class: "jss-header-toggle-icon" });
|
|
72
|
+
const paintToggleIcon = (open) => {
|
|
73
|
+
const nodes = renderSlotToArray(null, "default", ctx, renderDrawerToggleValue(open));
|
|
74
|
+
toggleIconHost.replaceChildren(...(nodes.length ? nodes : [""]));
|
|
75
|
+
};
|
|
76
|
+
paintToggleIcon(isDrawerOpen());
|
|
77
|
+
|
|
78
|
+
const autoLeft = UI.Btn({
|
|
79
|
+
class: "jss-header-toggle",
|
|
80
|
+
outline: true,
|
|
81
|
+
size: rawProps.toggleSize ?? rawProps.size ?? "sm",
|
|
82
|
+
onClick: toggleDrawer,
|
|
83
|
+
"aria-label": rawProps.toggleLabel || "Toggle navigation"
|
|
84
|
+
}, toggleIconHost);
|
|
85
|
+
if (rawProps.left == null && rawProps.left !== false && !JSswift.ui.getSlot(slots, "left")) {
|
|
86
|
+
drawerToggleIcons.add({ update: paintToggleIcon });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const leftFallback = rawProps.left === false
|
|
90
|
+
? null
|
|
91
|
+
: (rawProps.left != null ? rawProps.left : autoLeft);
|
|
92
|
+
const titleFallback = hasOwn("title") ? rawProps.title : (rawProps.label ?? "App");
|
|
93
|
+
const subtitleFallback = rawProps.subtitle ?? rawProps.description ?? "";
|
|
94
|
+
const rightFallback = hasOwn("right") ? rawProps.right : rawProps.end;
|
|
95
|
+
const contentFallback = hasOwn("content")
|
|
96
|
+
? rawProps.content
|
|
97
|
+
: (hasOwn("body") ? rawProps.body : (children?.length ? children : null));
|
|
98
|
+
|
|
99
|
+
const startNodes = [
|
|
100
|
+
...renderPropNodes("left", leftFallback),
|
|
101
|
+
...renderPropNodes("start", null)
|
|
102
|
+
];
|
|
103
|
+
const iconNodes = renderPropNodes("icon", rawProps.icon, renderIconValue);
|
|
104
|
+
const eyebrowNodes = renderPropNodes("eyebrow", rawProps.eyebrow ?? rawProps.kicker);
|
|
105
|
+
const titleNodes = renderPropNodes("title", titleFallback);
|
|
106
|
+
const subtitleNodes = renderPropNodes("subtitle", subtitleFallback);
|
|
107
|
+
const metaNodes = renderPropNodes("meta", rawProps.meta);
|
|
108
|
+
const contentNodes = (() => {
|
|
109
|
+
const explicit = renderPropNodes("content", null);
|
|
110
|
+
return explicit.length ? explicit : renderPropNodes("default", contentFallback);
|
|
111
|
+
})();
|
|
112
|
+
const customCenterNodes = [
|
|
113
|
+
...renderPropNodes("center", null),
|
|
114
|
+
...renderPropNodes("body", null)
|
|
115
|
+
];
|
|
116
|
+
const rightNodes = [
|
|
117
|
+
...renderPropNodes("right", rightFallback),
|
|
118
|
+
...renderPropNodes("end", null)
|
|
119
|
+
];
|
|
120
|
+
const actionNodes = renderPropNodes("actions", rawProps.actions);
|
|
121
|
+
|
|
122
|
+
const structuredCenter = _.div(
|
|
123
|
+
{ class: uiClass(["jss-header-body", rawProps.bodyClass, rawProps.centerClass]) },
|
|
124
|
+
_.div(
|
|
125
|
+
{ class: "jss-header-heading" },
|
|
126
|
+
iconNodes.length ? _.div({ class: "jss-header-icon" }, ...iconNodes) : null,
|
|
127
|
+
_.div(
|
|
128
|
+
{ class: "jss-header-copy" },
|
|
129
|
+
eyebrowNodes.length ? _.div({ class: uiClass(["jss-header-eyebrow", rawProps.eyebrowClass]) }, ...eyebrowNodes) : null,
|
|
130
|
+
titleNodes.length ? _.div({ class: uiClass(["jss-header-title", rawProps.titleClass]) }, ...titleNodes) : null,
|
|
131
|
+
subtitleNodes.length ? _.div({ class: uiClass(["jss-header-subtitle", rawProps.subtitleClass]) }, ...subtitleNodes) : null,
|
|
132
|
+
contentNodes.length ? _.div({ class: uiClass(["jss-header-content", rawProps.contentClass]) }, ...contentNodes) : null
|
|
133
|
+
),
|
|
134
|
+
metaNodes.length ? _.div({ class: uiClass(["jss-header-meta", rawProps.metaClass]) }, ...metaNodes) : null
|
|
135
|
+
)
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
const endContent = [
|
|
139
|
+
...rightNodes,
|
|
140
|
+
...(actionNodes.length ? [_.div({ class: uiClass(["jss-header-actions", rawProps.actionsClass]) }, ...actionNodes)] : [])
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const p = JSswift.omit(props, [
|
|
144
|
+
"actions", "actionsClass", "body", "bodyClass", "centerClass", "content", "contentClass",
|
|
145
|
+
"description", "divider", "drawerCloseIcon", "drawerOpenIcon", "drawerStateKey", "elevated",
|
|
146
|
+
"end", "eyebrow", "eyebrowClass", "icon", "iconSize", "kicker", "label", "left", "meta",
|
|
147
|
+
"metaClass", "right", "slots", "stack", "sticky", "subtitle", "subtitleClass", "title",
|
|
148
|
+
"titleClass", "toggleLabel", "toggleSize", "gap", "minHeight", "startClass", "endClass"
|
|
149
|
+
]);
|
|
150
|
+
p.class = uiClass([
|
|
151
|
+
"jss-panel",
|
|
152
|
+
"jss-header",
|
|
153
|
+
"jss-singularity",
|
|
154
|
+
uiWhen(rawProps.sticky !== false, "sticky"),
|
|
155
|
+
uiWhen(rawProps.stack, "stack"),
|
|
156
|
+
uiWhen(rawProps.elevated, "elevated"),
|
|
157
|
+
uiWhen(rawProps.divider !== false, "divider"),
|
|
158
|
+
props.class
|
|
159
|
+
]);
|
|
160
|
+
p.style = { ...(props.style || {}) };
|
|
161
|
+
if (rawProps.gap != null) p.style["--jss-header-gap"] = toCssSize(uiUnwrap(rawProps.gap));
|
|
162
|
+
if (rawProps.minHeight != null) p.style.minHeight = toCssSize(uiUnwrap(rawProps.minHeight));
|
|
163
|
+
|
|
164
|
+
const el = _.div(
|
|
165
|
+
p,
|
|
166
|
+
...(startNodes.length ? [_.div({ class: uiClass(["jss-header-start", rawProps.startClass]) }, ...startNodes)] : []),
|
|
167
|
+
_.div(
|
|
168
|
+
{ class: "jss-header-main" },
|
|
169
|
+
...(customCenterNodes.length
|
|
170
|
+
? [_.div({ class: uiClass(["jss-header-body", rawProps.bodyClass, rawProps.centerClass]) }, ...customCenterNodes)]
|
|
171
|
+
: [structuredCenter]),
|
|
172
|
+
...(endContent.length ? [_.div({ class: uiClass(["jss-header-end", rawProps.endClass]) }, ...endContent)] : [])
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
setPropertyProps(el, rawProps);
|
|
177
|
+
return el;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
|
|
181
181
|
UI.Drawer = (...args) => {
|
|
182
182
|
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
183
183
|
const slots = rawProps.slots || {};
|
|
184
184
|
const props = { ...rawProps };
|
|
185
185
|
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(rawProps, key);
|
|
186
|
-
const currentStateKey = rawProps.stateKey ?? drawerStateKey;
|
|
187
|
-
if (currentStateKey) {
|
|
188
|
-
drawerStateKey = currentStateKey;
|
|
189
|
-
drawerOpen = readDrawerOpen(currentStateKey);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const isDrawerOpen = () => readDrawerOpen(currentStateKey);
|
|
193
|
-
const openDrawer = () => setDrawerOpen(true, currentStateKey);
|
|
194
|
-
const closeDrawer = () => setDrawerOpen(false, currentStateKey);
|
|
195
|
-
const toggleDrawer = () => setDrawerOpen(!isDrawerOpen(), currentStateKey);
|
|
196
|
-
const ctx = {
|
|
197
|
-
props: rawProps,
|
|
198
|
-
stateKey: currentStateKey,
|
|
199
|
-
isDrawerOpen,
|
|
200
|
-
openDrawer,
|
|
201
|
-
closeDrawer,
|
|
202
|
-
toggleDrawer,
|
|
203
|
-
toggleAside: toggleDrawer
|
|
204
|
-
};
|
|
186
|
+
const currentStateKey = rawProps.stateKey ?? drawerStateKey;
|
|
187
|
+
if (currentStateKey) {
|
|
188
|
+
drawerStateKey = currentStateKey;
|
|
189
|
+
drawerOpen = readDrawerOpen(currentStateKey);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const isDrawerOpen = () => readDrawerOpen(currentStateKey);
|
|
193
|
+
const openDrawer = () => setDrawerOpen(true, currentStateKey);
|
|
194
|
+
const closeDrawer = () => setDrawerOpen(false, currentStateKey);
|
|
195
|
+
const toggleDrawer = () => setDrawerOpen(!isDrawerOpen(), currentStateKey);
|
|
196
|
+
const ctx = {
|
|
197
|
+
props: rawProps,
|
|
198
|
+
stateKey: currentStateKey,
|
|
199
|
+
isDrawerOpen,
|
|
200
|
+
openDrawer,
|
|
201
|
+
closeDrawer,
|
|
202
|
+
toggleDrawer,
|
|
203
|
+
toggleAside: toggleDrawer
|
|
204
|
+
};
|
|
205
205
|
|
|
206
206
|
const store = JSswift?.store;
|
|
207
207
|
const canStore = !!(store?.get && store?.set);
|
|
@@ -211,38 +211,38 @@ UI.Drawer = (...args) => {
|
|
|
211
211
|
let activeItemKey = canStore ? (store.get(activeStateKey, null) ?? null) : null;
|
|
212
212
|
const activeLeafRefs = new Map();
|
|
213
213
|
const activeGroupRefs = new Map();
|
|
214
|
-
|
|
215
|
-
const normalizeList = (value) => {
|
|
216
|
-
const raw = uiUnwrap(value);
|
|
217
|
-
if (raw == null || raw === false) return [];
|
|
218
|
-
if (Array.isArray(raw)) return raw.flat(Infinity);
|
|
219
|
-
return [raw];
|
|
220
|
-
};
|
|
221
|
-
const renderArea = (names, fallback, localCtx = ctx) => {
|
|
222
|
-
const list = Array.isArray(names) ? names : [names];
|
|
223
|
-
for (const name of list) {
|
|
224
|
-
if (JSswift.ui.getSlot(slots, name) != null) {
|
|
225
|
-
return renderSlotToArray(slots, name, localCtx, fallback);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return fallback == null ? [] : renderSlotToArray(null, "default", localCtx, uiUnwrap(fallback));
|
|
229
|
-
};
|
|
230
|
-
const hasArea = (names) => {
|
|
231
|
-
const list = Array.isArray(names) ? names : [names];
|
|
232
|
-
return list.some((name) => JSswift.ui.getSlot(slots, name) != null);
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const isExternalLink = (it) => {
|
|
236
|
-
if (typeof uiUnwrap(it.external) === "boolean") return !!uiUnwrap(it.external);
|
|
237
|
-
const href = uiUnwrap(it.href || it.to || it.link || "");
|
|
238
|
-
return /^(https?:)?\/\//.test(href);
|
|
239
|
-
};
|
|
240
|
-
const closeOnSelect = rawProps.closeOnSelect ?? true;
|
|
241
|
-
const shouldClose = (it) => !!closeOnSelect && uiUnwrap(it.keepOpen) !== true;
|
|
242
|
-
const itemIconSize = rawProps.itemIconSize ?? rawProps.size ?? "md";
|
|
243
|
-
const groupOpenIcon = rawProps.groupOpenIcon ?? "arrow_drop_up";
|
|
244
|
-
const groupCloseIcon = rawProps.groupCloseIcon ?? "arrow_drop_down";
|
|
245
|
-
|
|
214
|
+
|
|
215
|
+
const normalizeList = (value) => {
|
|
216
|
+
const raw = uiUnwrap(value);
|
|
217
|
+
if (raw == null || raw === false) return [];
|
|
218
|
+
if (Array.isArray(raw)) return raw.flat(Infinity);
|
|
219
|
+
return [raw];
|
|
220
|
+
};
|
|
221
|
+
const renderArea = (names, fallback, localCtx = ctx) => {
|
|
222
|
+
const list = Array.isArray(names) ? names : [names];
|
|
223
|
+
for (const name of list) {
|
|
224
|
+
if (JSswift.ui.getSlot(slots, name) != null) {
|
|
225
|
+
return renderSlotToArray(slots, name, localCtx, fallback);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return fallback == null ? [] : renderSlotToArray(null, "default", localCtx, uiUnwrap(fallback));
|
|
229
|
+
};
|
|
230
|
+
const hasArea = (names) => {
|
|
231
|
+
const list = Array.isArray(names) ? names : [names];
|
|
232
|
+
return list.some((name) => JSswift.ui.getSlot(slots, name) != null);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const isExternalLink = (it) => {
|
|
236
|
+
if (typeof uiUnwrap(it.external) === "boolean") return !!uiUnwrap(it.external);
|
|
237
|
+
const href = uiUnwrap(it.href || it.to || it.link || "");
|
|
238
|
+
return /^(https?:)?\/\//.test(href);
|
|
239
|
+
};
|
|
240
|
+
const closeOnSelect = rawProps.closeOnSelect ?? true;
|
|
241
|
+
const shouldClose = (it) => !!closeOnSelect && uiUnwrap(it.keepOpen) !== true;
|
|
242
|
+
const itemIconSize = rawProps.itemIconSize ?? rawProps.size ?? "md";
|
|
243
|
+
const groupOpenIcon = rawProps.groupOpenIcon ?? "arrow_drop_up";
|
|
244
|
+
const groupCloseIcon = rawProps.groupCloseIcon ?? "arrow_drop_down";
|
|
245
|
+
|
|
246
246
|
const isStoredActive = (key) => !!key && activeItemKey === key;
|
|
247
247
|
const isBranchActive = (key) => !!key && !!activeItemKey && (activeItemKey === key || activeItemKey.startsWith(`${key}::`));
|
|
248
248
|
const syncActiveClasses = () => {
|
|
@@ -269,8 +269,8 @@ UI.Drawer = (...args) => {
|
|
|
269
269
|
if (!href || isExternalLink(it)) return false;
|
|
270
270
|
try {
|
|
271
271
|
if (href.startsWith("#")) return window.location.hash === href;
|
|
272
|
-
const fullPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
273
|
-
return href === fullPath || href === window.location.pathname;
|
|
272
|
+
const fullPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
273
|
+
return href === fullPath || href === window.location.pathname;
|
|
274
274
|
} catch {
|
|
275
275
|
return false;
|
|
276
276
|
}
|
|
@@ -289,139 +289,139 @@ UI.Drawer = (...args) => {
|
|
|
289
289
|
return hasActiveChildren(nested, level + 1, path.concat(keyPart));
|
|
290
290
|
});
|
|
291
291
|
};
|
|
292
|
-
const iconNodes = (icon, localCtx = {}) => {
|
|
293
|
-
const raw = uiUnwrap(icon);
|
|
294
|
-
if (raw == null || raw === false) return [];
|
|
295
|
-
const slotValue = typeof raw === "string"
|
|
296
|
-
? UI.Icon({ name: raw, size: localCtx.iconSize ?? itemIconSize })
|
|
297
|
-
: JSswift.ui.slot(raw, { ...localCtx, as: "icon" });
|
|
298
|
-
return renderSlotToArray(null, "default", localCtx, slotValue);
|
|
299
|
-
};
|
|
300
|
-
const wrapIconNodes = (icon, side, localCtx = {}) => {
|
|
301
|
-
const nodes = iconNodes(icon, localCtx);
|
|
302
|
-
return nodes.length ? [_.span({ class: uiClass(["
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
const getItemIcons = (it) => {
|
|
306
|
-
const side = uiUnwrap(it.iconPosition) || "left";
|
|
307
|
-
const leftIcon = Object.prototype.hasOwnProperty.call(it, "iconLeft") ? it.iconLeft : (side !== "right" ? it.icon : null);
|
|
308
|
-
const rightIcon = Object.prototype.hasOwnProperty.call(it, "iconRight") ? it.iconRight : (side === "right" ? it.icon : null);
|
|
309
|
-
return {
|
|
310
|
-
left: leftIcon,
|
|
311
|
-
right: rightIcon
|
|
312
|
-
};
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
const itemKeyPart = (it, label, level, idx) => uiUnwrap(it.key || it.id || it.to || it.href || label || `item-${level}-${idx}`);
|
|
316
|
-
|
|
317
|
-
const readGroupOpen = (key, fallback) => {
|
|
318
|
-
if (!canStore) return fallback;
|
|
319
|
-
if (Object.prototype.hasOwnProperty.call(groupState, key)) return !!groupState[key];
|
|
320
|
-
return fallback;
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const writeGroupOpen = (key, open) => {
|
|
324
|
-
if (!canStore) return;
|
|
325
|
-
groupState = { ...groupState, [key]: !!open };
|
|
326
|
-
store.set(groupStateKey, groupState);
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const buildStructuredHeader = () => {
|
|
330
|
-
const headerCtx = { ...ctx, area: "header" };
|
|
331
|
-
const icon = renderArea(["headerIcon", "icon"], rawProps.icon, headerCtx);
|
|
332
|
-
const eyebrow = renderArea(["eyebrow"], rawProps.eyebrow, headerCtx);
|
|
333
|
-
const title = renderArea(["title"], rawProps.title, headerCtx);
|
|
334
|
-
const subtitle = renderArea(["subtitle"], rawProps.subtitle, headerCtx);
|
|
335
|
-
const meta = renderArea(["meta"], rawProps.meta, headerCtx);
|
|
336
|
-
const content = renderArea(["content"], rawProps.content, headerCtx);
|
|
337
|
-
const actions = renderArea(["actions"], rawProps.actions, headerCtx);
|
|
338
|
-
const extra = hasOwn("header") ? renderSlotToArray(null, "default", headerCtx, uiUnwrap(rawProps.header)) : [];
|
|
339
|
-
const hasStructured = icon.length || eyebrow.length || title.length || subtitle.length || meta.length || content.length || actions.length;
|
|
340
|
-
if (!hasStructured && !extra.length) return [];
|
|
341
|
-
if (!hasStructured) return extra;
|
|
342
|
-
return [
|
|
343
|
-
_.div(
|
|
344
|
-
{ class: uiClass(["
|
|
345
|
-
...(icon.length ? [_.div({ class: "
|
|
346
|
-
_.div(
|
|
347
|
-
{ class: "
|
|
348
|
-
...(eyebrow.length ? [_.div({ class: "
|
|
349
|
-
...(title.length ? [_.div({ class: "
|
|
350
|
-
...(subtitle.length ? [_.div({ class: "
|
|
351
|
-
...(meta.length ? [_.div({ class: "
|
|
352
|
-
...(content.length ? [_.div({ class: "
|
|
353
|
-
...(extra.length ? [_.div({ class: "
|
|
354
|
-
),
|
|
355
|
-
...(actions.length ? [_.div({ class: "
|
|
356
|
-
)
|
|
357
|
-
];
|
|
358
|
-
};
|
|
359
|
-
const invokeItemHandler = (it, itemCtx, e) => {
|
|
360
|
-
const itemResult = it.onClick?.(e, itemCtx);
|
|
361
|
-
if (itemResult === false || e?.defaultPrevented) return false;
|
|
362
|
-
const rootResult = rawProps.onSelect?.(it, itemCtx, e);
|
|
363
|
-
if (rootResult === false || e?.defaultPrevented) return false;
|
|
364
|
-
return true;
|
|
365
|
-
};
|
|
366
|
-
const renderEntryNodes = (it, itemCtx, extras = {}) => {
|
|
367
|
-
const slotPrefix = itemCtx.hasChildren ? "group" : "item";
|
|
368
|
-
const labelNodes = renderSlotToArray(slots, `${slotPrefix}Label`, itemCtx, itemCtx.label);
|
|
369
|
-
const noteNodes = renderSlotToArray(slots, `${slotPrefix}Note`, itemCtx, itemCtx.note);
|
|
370
|
-
const badgeNodes = renderSlotToArray(slots, `${slotPrefix}Badge`, itemCtx, itemCtx.badge);
|
|
371
|
-
const asideNodes = renderSlotToArray(slots, `${slotPrefix}Aside`, itemCtx, itemCtx.aside);
|
|
372
|
-
const contentNodes = renderSlotToArray(slots, `${slotPrefix}Content`, itemCtx, itemCtx.content);
|
|
373
|
-
const mainChildren = [];
|
|
374
|
-
|
|
375
|
-
if (labelNodes.length || noteNodes.length || badgeNodes.length || asideNodes.length) {
|
|
376
|
-
mainChildren.push(
|
|
377
|
-
_.div(
|
|
378
|
-
{ class: "
|
|
379
|
-
_.div(
|
|
380
|
-
{ class: "
|
|
381
|
-
...(labelNodes.length ? [_.div({ class: "
|
|
382
|
-
...(noteNodes.length ? [_.div({ class: "
|
|
383
|
-
),
|
|
384
|
-
...(badgeNodes.length || asideNodes.length
|
|
385
|
-
? [_.div(
|
|
386
|
-
{ class: "
|
|
387
|
-
...(badgeNodes.length ? [_.div({ class: "
|
|
388
|
-
...(asideNodes.length ? [_.div({ class: "
|
|
389
|
-
)]
|
|
390
|
-
: [])
|
|
391
|
-
)
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
if (contentNodes.length) mainChildren.push(_.div({ class: "
|
|
395
|
-
|
|
396
|
-
return [
|
|
397
|
-
...(extras.start || []),
|
|
398
|
-
...wrapIconNodes(itemCtx.iconLeft, "left", itemCtx),
|
|
399
|
-
...(mainChildren.length ? [_.div({ class: "
|
|
400
|
-
...wrapIconNodes(itemCtx.iconRight, "right", itemCtx),
|
|
401
|
-
...(extras.end || [])
|
|
402
|
-
];
|
|
403
|
-
};
|
|
404
|
-
const renderItems = (list = [], level = 0, path = []) => {
|
|
405
|
-
return normalizeList(list).map((entry, idx) => {
|
|
406
|
-
const it = uiUnwrap(entry);
|
|
407
|
-
if (it == null || it === false) return null;
|
|
408
|
-
|
|
409
|
-
if (it.nodeType || typeof it !== "object" || Array.isArray(it)) {
|
|
410
|
-
return _.div({
|
|
411
|
-
class: "
|
|
412
|
-
"data-level": String(level)
|
|
413
|
-
}, ...renderSlotToArray(null, "default", { ...ctx, item: it, level, index: idx, path }, it));
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (uiUnwrap(it.hidden) === true || uiUnwrap(it.visible) === false) return null;
|
|
417
|
-
|
|
418
|
-
const childItems = normalizeList(it.items || it.children || it.sub);
|
|
419
|
-
const href = uiUnwrap(it.href || it.to || it.link || null);
|
|
420
|
-
const rawLabel = uiUnwrap(it.label ?? it.title ?? it.text ?? href ?? null);
|
|
421
|
-
const label = rawLabel ?? `item-${level}-${idx}`;
|
|
422
|
-
const note = uiUnwrap(it.note ?? it.subtitle ?? it.description ?? null);
|
|
423
|
-
const badge = uiUnwrap(it.badge ?? null);
|
|
424
|
-
const aside = uiUnwrap(it.aside ?? it.meta ?? null);
|
|
292
|
+
const iconNodes = (icon, localCtx = {}) => {
|
|
293
|
+
const raw = uiUnwrap(icon);
|
|
294
|
+
if (raw == null || raw === false) return [];
|
|
295
|
+
const slotValue = typeof raw === "string"
|
|
296
|
+
? UI.Icon({ name: raw, size: localCtx.iconSize ?? itemIconSize })
|
|
297
|
+
: JSswift.ui.slot(raw, { ...localCtx, as: "icon" });
|
|
298
|
+
return renderSlotToArray(null, "default", localCtx, slotValue);
|
|
299
|
+
};
|
|
300
|
+
const wrapIconNodes = (icon, side, localCtx = {}) => {
|
|
301
|
+
const nodes = iconNodes(icon, localCtx);
|
|
302
|
+
return nodes.length ? [_.span({ class: uiClass(["jss-drawer-item-icon", side]) }, ...nodes)] : [];
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const getItemIcons = (it) => {
|
|
306
|
+
const side = uiUnwrap(it.iconPosition) || "left";
|
|
307
|
+
const leftIcon = Object.prototype.hasOwnProperty.call(it, "iconLeft") ? it.iconLeft : (side !== "right" ? it.icon : null);
|
|
308
|
+
const rightIcon = Object.prototype.hasOwnProperty.call(it, "iconRight") ? it.iconRight : (side === "right" ? it.icon : null);
|
|
309
|
+
return {
|
|
310
|
+
left: leftIcon,
|
|
311
|
+
right: rightIcon
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const itemKeyPart = (it, label, level, idx) => uiUnwrap(it.key || it.id || it.to || it.href || label || `item-${level}-${idx}`);
|
|
316
|
+
|
|
317
|
+
const readGroupOpen = (key, fallback) => {
|
|
318
|
+
if (!canStore) return fallback;
|
|
319
|
+
if (Object.prototype.hasOwnProperty.call(groupState, key)) return !!groupState[key];
|
|
320
|
+
return fallback;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const writeGroupOpen = (key, open) => {
|
|
324
|
+
if (!canStore) return;
|
|
325
|
+
groupState = { ...groupState, [key]: !!open };
|
|
326
|
+
store.set(groupStateKey, groupState);
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const buildStructuredHeader = () => {
|
|
330
|
+
const headerCtx = { ...ctx, area: "header" };
|
|
331
|
+
const icon = renderArea(["headerIcon", "icon"], rawProps.icon, headerCtx);
|
|
332
|
+
const eyebrow = renderArea(["eyebrow"], rawProps.eyebrow, headerCtx);
|
|
333
|
+
const title = renderArea(["title"], rawProps.title, headerCtx);
|
|
334
|
+
const subtitle = renderArea(["subtitle"], rawProps.subtitle, headerCtx);
|
|
335
|
+
const meta = renderArea(["meta"], rawProps.meta, headerCtx);
|
|
336
|
+
const content = renderArea(["content"], rawProps.content, headerCtx);
|
|
337
|
+
const actions = renderArea(["actions"], rawProps.actions, headerCtx);
|
|
338
|
+
const extra = hasOwn("header") ? renderSlotToArray(null, "default", headerCtx, uiUnwrap(rawProps.header)) : [];
|
|
339
|
+
const hasStructured = icon.length || eyebrow.length || title.length || subtitle.length || meta.length || content.length || actions.length;
|
|
340
|
+
if (!hasStructured && !extra.length) return [];
|
|
341
|
+
if (!hasStructured) return extra;
|
|
342
|
+
return [
|
|
343
|
+
_.div(
|
|
344
|
+
{ class: uiClass(["jss-drawer-header", rawProps.headerClass]) },
|
|
345
|
+
...(icon.length ? [_.div({ class: "jss-drawer-header-icon" }, ...icon)] : []),
|
|
346
|
+
_.div(
|
|
347
|
+
{ class: "jss-drawer-header-body" },
|
|
348
|
+
...(eyebrow.length ? [_.div({ class: "jss-drawer-header-eyebrow" }, ...eyebrow)] : []),
|
|
349
|
+
...(title.length ? [_.div({ class: "jss-drawer-header-title" }, ...title)] : []),
|
|
350
|
+
...(subtitle.length ? [_.div({ class: "jss-drawer-header-subtitle" }, ...subtitle)] : []),
|
|
351
|
+
...(meta.length ? [_.div({ class: "jss-drawer-header-meta" }, ...meta)] : []),
|
|
352
|
+
...(content.length ? [_.div({ class: "jss-drawer-header-content" }, ...content)] : []),
|
|
353
|
+
...(extra.length ? [_.div({ class: "jss-drawer-header-extra" }, ...extra)] : [])
|
|
354
|
+
),
|
|
355
|
+
...(actions.length ? [_.div({ class: "jss-drawer-header-actions" }, ...actions)] : [])
|
|
356
|
+
)
|
|
357
|
+
];
|
|
358
|
+
};
|
|
359
|
+
const invokeItemHandler = (it, itemCtx, e) => {
|
|
360
|
+
const itemResult = it.onClick?.(e, itemCtx);
|
|
361
|
+
if (itemResult === false || e?.defaultPrevented) return false;
|
|
362
|
+
const rootResult = rawProps.onSelect?.(it, itemCtx, e);
|
|
363
|
+
if (rootResult === false || e?.defaultPrevented) return false;
|
|
364
|
+
return true;
|
|
365
|
+
};
|
|
366
|
+
const renderEntryNodes = (it, itemCtx, extras = {}) => {
|
|
367
|
+
const slotPrefix = itemCtx.hasChildren ? "group" : "item";
|
|
368
|
+
const labelNodes = renderSlotToArray(slots, `${slotPrefix}Label`, itemCtx, itemCtx.label);
|
|
369
|
+
const noteNodes = renderSlotToArray(slots, `${slotPrefix}Note`, itemCtx, itemCtx.note);
|
|
370
|
+
const badgeNodes = renderSlotToArray(slots, `${slotPrefix}Badge`, itemCtx, itemCtx.badge);
|
|
371
|
+
const asideNodes = renderSlotToArray(slots, `${slotPrefix}Aside`, itemCtx, itemCtx.aside);
|
|
372
|
+
const contentNodes = renderSlotToArray(slots, `${slotPrefix}Content`, itemCtx, itemCtx.content);
|
|
373
|
+
const mainChildren = [];
|
|
374
|
+
|
|
375
|
+
if (labelNodes.length || noteNodes.length || badgeNodes.length || asideNodes.length) {
|
|
376
|
+
mainChildren.push(
|
|
377
|
+
_.div(
|
|
378
|
+
{ class: "jss-drawer-item-top" },
|
|
379
|
+
_.div(
|
|
380
|
+
{ class: "jss-drawer-item-copy" },
|
|
381
|
+
...(labelNodes.length ? [_.div({ class: "jss-drawer-item-label" }, ...labelNodes)] : []),
|
|
382
|
+
...(noteNodes.length ? [_.div({ class: "jss-drawer-item-note" }, ...noteNodes)] : [])
|
|
383
|
+
),
|
|
384
|
+
...(badgeNodes.length || asideNodes.length
|
|
385
|
+
? [_.div(
|
|
386
|
+
{ class: "jss-drawer-item-meta" },
|
|
387
|
+
...(badgeNodes.length ? [_.div({ class: "jss-drawer-item-badge" }, ...badgeNodes)] : []),
|
|
388
|
+
...(asideNodes.length ? [_.div({ class: "jss-drawer-item-aside" }, ...asideNodes)] : [])
|
|
389
|
+
)]
|
|
390
|
+
: [])
|
|
391
|
+
)
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
if (contentNodes.length) mainChildren.push(_.div({ class: "jss-drawer-item-content" }, ...contentNodes));
|
|
395
|
+
|
|
396
|
+
return [
|
|
397
|
+
...(extras.start || []),
|
|
398
|
+
...wrapIconNodes(itemCtx.iconLeft, "left", itemCtx),
|
|
399
|
+
...(mainChildren.length ? [_.div({ class: "jss-drawer-item-main" }, ...mainChildren)] : []),
|
|
400
|
+
...wrapIconNodes(itemCtx.iconRight, "right", itemCtx),
|
|
401
|
+
...(extras.end || [])
|
|
402
|
+
];
|
|
403
|
+
};
|
|
404
|
+
const renderItems = (list = [], level = 0, path = []) => {
|
|
405
|
+
return normalizeList(list).map((entry, idx) => {
|
|
406
|
+
const it = uiUnwrap(entry);
|
|
407
|
+
if (it == null || it === false) return null;
|
|
408
|
+
|
|
409
|
+
if (it.nodeType || typeof it !== "object" || Array.isArray(it)) {
|
|
410
|
+
return _.div({
|
|
411
|
+
class: "jss-drawer-custom",
|
|
412
|
+
"data-level": String(level)
|
|
413
|
+
}, ...renderSlotToArray(null, "default", { ...ctx, item: it, level, index: idx, path }, it));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (uiUnwrap(it.hidden) === true || uiUnwrap(it.visible) === false) return null;
|
|
417
|
+
|
|
418
|
+
const childItems = normalizeList(it.items || it.children || it.sub);
|
|
419
|
+
const href = uiUnwrap(it.href || it.to || it.link || null);
|
|
420
|
+
const rawLabel = uiUnwrap(it.label ?? it.title ?? it.text ?? href ?? null);
|
|
421
|
+
const label = rawLabel ?? `item-${level}-${idx}`;
|
|
422
|
+
const note = uiUnwrap(it.note ?? it.subtitle ?? it.description ?? null);
|
|
423
|
+
const badge = uiUnwrap(it.badge ?? null);
|
|
424
|
+
const aside = uiUnwrap(it.aside ?? it.meta ?? null);
|
|
425
425
|
const content = uiUnwrap(it.content ?? null);
|
|
426
426
|
const keyPart = itemKeyPart(it, label, level, idx);
|
|
427
427
|
const itemStateKey = path.concat(keyPart).join("::");
|
|
@@ -433,89 +433,89 @@ UI.Drawer = (...args) => {
|
|
|
433
433
|
const itemCtx = {
|
|
434
434
|
...ctx,
|
|
435
435
|
item: it,
|
|
436
|
-
index: idx,
|
|
437
|
-
level,
|
|
438
|
-
path,
|
|
439
|
-
label,
|
|
440
|
-
note,
|
|
441
|
-
badge,
|
|
442
|
-
aside,
|
|
443
|
-
content,
|
|
444
|
-
itemStateKey,
|
|
445
|
-
iconLeft: itemIconLeft,
|
|
446
|
-
iconRight: itemIconRight,
|
|
447
|
-
iconSize: uiUnwrap(it.iconSize) || itemIconSize,
|
|
448
|
-
active: isActive,
|
|
449
|
-
disabled,
|
|
450
|
-
hasChildren: false
|
|
451
|
-
};
|
|
452
|
-
const dividerLike = uiUnwrap(it.divider) === true || it.type === "divider" || it.type === "separator";
|
|
453
|
-
const sectionLike = uiUnwrap(it.section) === true || it.type === "section" || it.type === "heading" || it.type === "label";
|
|
454
|
-
const contentOnly = it.type === "content" || it.type === "custom" || (!href && !childItems.length && !uiUnwrap(it.button) && it.type !== "button" && rawLabel == null && content != null);
|
|
455
|
-
|
|
456
|
-
if (dividerLike) {
|
|
457
|
-
return _.div({
|
|
458
|
-
class: uiClass(["
|
|
459
|
-
"data-level": String(level)
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
if (sectionLike) {
|
|
464
|
-
const sectionNodes = renderSlotToArray(slots, "sectionLabel", itemCtx, label || content);
|
|
465
|
-
return _.div({
|
|
466
|
-
class: uiClass(["
|
|
467
|
-
"data-level": String(level)
|
|
468
|
-
}, ...sectionNodes);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (contentOnly) {
|
|
472
|
-
const customNodes = renderSlotToArray(slots, "item", itemCtx, content ?? label);
|
|
473
|
-
return _.div({
|
|
474
|
-
class: uiClass(["
|
|
475
|
-
style: it.style,
|
|
476
|
-
"data-level": String(level)
|
|
477
|
-
}, ...customNodes);
|
|
436
|
+
index: idx,
|
|
437
|
+
level,
|
|
438
|
+
path,
|
|
439
|
+
label,
|
|
440
|
+
note,
|
|
441
|
+
badge,
|
|
442
|
+
aside,
|
|
443
|
+
content,
|
|
444
|
+
itemStateKey,
|
|
445
|
+
iconLeft: itemIconLeft,
|
|
446
|
+
iconRight: itemIconRight,
|
|
447
|
+
iconSize: uiUnwrap(it.iconSize) || itemIconSize,
|
|
448
|
+
active: isActive,
|
|
449
|
+
disabled,
|
|
450
|
+
hasChildren: false
|
|
451
|
+
};
|
|
452
|
+
const dividerLike = uiUnwrap(it.divider) === true || it.type === "divider" || it.type === "separator";
|
|
453
|
+
const sectionLike = uiUnwrap(it.section) === true || it.type === "section" || it.type === "heading" || it.type === "label";
|
|
454
|
+
const contentOnly = it.type === "content" || it.type === "custom" || (!href && !childItems.length && !uiUnwrap(it.button) && it.type !== "button" && rawLabel == null && content != null);
|
|
455
|
+
|
|
456
|
+
if (dividerLike) {
|
|
457
|
+
return _.div({
|
|
458
|
+
class: uiClass(["jss-drawer-separator", it.class]),
|
|
459
|
+
"data-level": String(level)
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (sectionLike) {
|
|
464
|
+
const sectionNodes = renderSlotToArray(slots, "sectionLabel", itemCtx, label || content);
|
|
465
|
+
return _.div({
|
|
466
|
+
class: uiClass(["jss-drawer-section-label", it.class]),
|
|
467
|
+
"data-level": String(level)
|
|
468
|
+
}, ...sectionNodes);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (contentOnly) {
|
|
472
|
+
const customNodes = renderSlotToArray(slots, "item", itemCtx, content ?? label);
|
|
473
|
+
return _.div({
|
|
474
|
+
class: uiClass(["jss-drawer-custom", tone ? `jss-drawer-tone-${tone}` : "", it.class]),
|
|
475
|
+
style: it.style,
|
|
476
|
+
"data-level": String(level)
|
|
477
|
+
}, ...customNodes);
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
if (childItems.length) {
|
|
481
481
|
const baseActiveInGroup = baseIsActive || hasActiveChildren(childItems, level + 1, path.concat(keyPart));
|
|
482
482
|
const activeInGroup = baseActiveInGroup || isBranchActive(itemStateKey);
|
|
483
483
|
let open = readGroupOpen(itemStateKey, !!uiUnwrap(it.expanded) || !!uiUnwrap(it.open) || activeInGroup);
|
|
484
|
-
const toggleIconEl = _.span({ class: "
|
|
484
|
+
const toggleIconEl = _.span({ class: "jss-drawer-group-icon" });
|
|
485
485
|
const groupCtx = {
|
|
486
486
|
...itemCtx,
|
|
487
|
-
active: activeInGroup,
|
|
488
|
-
hasChildren: true,
|
|
489
|
-
isOpen: () => open,
|
|
490
|
-
setOpen: (value) => setOpen(value),
|
|
491
|
-
toggle: () => setOpen(!open)
|
|
492
|
-
};
|
|
493
|
-
const paintToggleIcon = () => {
|
|
494
|
-
const icon = open ? (it.openIcon ?? groupOpenIcon) : (it.closeIcon ?? groupCloseIcon);
|
|
495
|
-
const side = uiUnwrap(
|
|
496
|
-
open
|
|
497
|
-
? (it.iconSidePosition || it.openIconSide || it.openIconPosition || "right")
|
|
498
|
-
: (it.iconSidePosition || it.closeIconSide || it.closeIconPosition || "right")
|
|
499
|
-
) === "left" ? "left" : "right";
|
|
500
|
-
toggleIconEl.innerHTML = "";
|
|
501
|
-
toggleIconEl.className = `
|
|
502
|
-
iconNodes(icon, { ...groupCtx, as: "toggleIcon" }).forEach((node) => toggleIconEl.appendChild(node));
|
|
503
|
-
};
|
|
504
|
-
const toggleBtn = _.button({
|
|
505
|
-
type: "button",
|
|
506
|
-
class: uiClass([
|
|
507
|
-
"
|
|
508
|
-
"
|
|
509
|
-
open ? "open" : "",
|
|
510
|
-
activeInGroup ? "active" : "",
|
|
511
|
-
disabled ? "is-disabled" : "",
|
|
512
|
-
tone ? `
|
|
513
|
-
it.class
|
|
514
|
-
]),
|
|
515
|
-
style: it.style,
|
|
516
|
-
"data-level": String(level),
|
|
517
|
-
"aria-expanded": String(open),
|
|
518
|
-
"aria-disabled": disabled ? "true" : null,
|
|
487
|
+
active: activeInGroup,
|
|
488
|
+
hasChildren: true,
|
|
489
|
+
isOpen: () => open,
|
|
490
|
+
setOpen: (value) => setOpen(value),
|
|
491
|
+
toggle: () => setOpen(!open)
|
|
492
|
+
};
|
|
493
|
+
const paintToggleIcon = () => {
|
|
494
|
+
const icon = open ? (it.openIcon ?? groupOpenIcon) : (it.closeIcon ?? groupCloseIcon);
|
|
495
|
+
const side = uiUnwrap(
|
|
496
|
+
open
|
|
497
|
+
? (it.iconSidePosition || it.openIconSide || it.openIconPosition || "right")
|
|
498
|
+
: (it.iconSidePosition || it.closeIconSide || it.closeIconPosition || "right")
|
|
499
|
+
) === "left" ? "left" : "right";
|
|
500
|
+
toggleIconEl.innerHTML = "";
|
|
501
|
+
toggleIconEl.className = `jss-drawer-group-icon ${side}`;
|
|
502
|
+
iconNodes(icon, { ...groupCtx, as: "toggleIcon" }).forEach((node) => toggleIconEl.appendChild(node));
|
|
503
|
+
};
|
|
504
|
+
const toggleBtn = _.button({
|
|
505
|
+
type: "button",
|
|
506
|
+
class: uiClass([
|
|
507
|
+
"jss-drawer-group-toggle",
|
|
508
|
+
"jss-drawer-entry",
|
|
509
|
+
open ? "open" : "",
|
|
510
|
+
activeInGroup ? "active" : "",
|
|
511
|
+
disabled ? "is-disabled" : "",
|
|
512
|
+
tone ? `jss-drawer-tone-${tone}` : "",
|
|
513
|
+
it.class
|
|
514
|
+
]),
|
|
515
|
+
style: it.style,
|
|
516
|
+
"data-level": String(level),
|
|
517
|
+
"aria-expanded": String(open),
|
|
518
|
+
"aria-disabled": disabled ? "true" : null,
|
|
519
519
|
onClick: (e) => {
|
|
520
520
|
if (disabled) {
|
|
521
521
|
e.preventDefault();
|
|
@@ -527,24 +527,24 @@ UI.Drawer = (...args) => {
|
|
|
527
527
|
}, ...renderEntryNodes(it, groupCtx, {
|
|
528
528
|
start: uiUnwrap(it.iconSidePosition || it.openIconSide || it.closeIconSide || it.openIconPosition || it.closeIconPosition || "right") === "left" ? [toggleIconEl] : [],
|
|
529
529
|
end: uiUnwrap(it.iconSidePosition || it.openIconSide || it.closeIconSide || it.openIconPosition || it.closeIconPosition || "right") === "right" ? [toggleIconEl] : []
|
|
530
|
-
}));
|
|
531
|
-
const customGroupHeader = renderSlotToArray(slots, "group", groupCtx, null);
|
|
532
|
-
const groupItems = _.div({ class: "
|
|
533
|
-
const groupWrap = _.div({
|
|
534
|
-
class: uiClass([
|
|
535
|
-
"
|
|
536
|
-
open ? "open" : "",
|
|
537
|
-
activeInGroup ? "active" : "",
|
|
538
|
-
tone ? `
|
|
539
|
-
]),
|
|
540
|
-
"data-level": String(level)
|
|
541
|
-
}, ...(customGroupHeader.length ? customGroupHeader : [toggleBtn]), groupItems);
|
|
530
|
+
}));
|
|
531
|
+
const customGroupHeader = renderSlotToArray(slots, "group", groupCtx, null);
|
|
532
|
+
const groupItems = _.div({ class: "jss-drawer-group-items" }, ...renderItems(childItems, level + 1, path.concat(keyPart)));
|
|
533
|
+
const groupWrap = _.div({
|
|
534
|
+
class: uiClass([
|
|
535
|
+
"jss-drawer-group",
|
|
536
|
+
open ? "open" : "",
|
|
537
|
+
activeInGroup ? "active" : "",
|
|
538
|
+
tone ? `jss-drawer-tone-${tone}` : ""
|
|
539
|
+
]),
|
|
540
|
+
"data-level": String(level)
|
|
541
|
+
}, ...(customGroupHeader.length ? customGroupHeader : [toggleBtn]), groupItems);
|
|
542
542
|
const setOpen = (value) => {
|
|
543
543
|
open = !!value;
|
|
544
544
|
groupWrap.classList.toggle("open", open);
|
|
545
545
|
toggleBtn.classList.toggle("open", open);
|
|
546
546
|
toggleBtn.setAttribute("aria-expanded", String(open));
|
|
547
|
-
paintToggleIcon();
|
|
547
|
+
paintToggleIcon();
|
|
548
548
|
writeGroupOpen(itemStateKey, open);
|
|
549
549
|
};
|
|
550
550
|
activeGroupRefs.set(itemStateKey, {
|
|
@@ -555,25 +555,25 @@ UI.Drawer = (...args) => {
|
|
|
555
555
|
paintToggleIcon();
|
|
556
556
|
return groupWrap;
|
|
557
557
|
}
|
|
558
|
-
|
|
559
|
-
const customItem = renderSlotToArray(slots, "item", itemCtx, null);
|
|
560
|
-
const isButtonItem = uiUnwrap(it.button) === true || it.type === "button" || (!href && typeof it.onClick === "function");
|
|
561
|
-
const sharedProps = {
|
|
562
|
-
class: uiClass([
|
|
563
|
-
"
|
|
564
|
-
isButtonItem ? "
|
|
565
|
-
isActive ? "active" : "",
|
|
566
|
-
disabled ? "is-disabled" : "",
|
|
567
|
-
tone ? `
|
|
568
|
-
it.class
|
|
569
|
-
]),
|
|
570
|
-
style: it.style,
|
|
571
|
-
"data-level": String(level),
|
|
572
|
-
"aria-current": isActive ? "page" : null,
|
|
573
|
-
"aria-disabled": disabled ? "true" : null
|
|
574
|
-
};
|
|
575
|
-
const entryNodes = customItem.length ? customItem : renderEntryNodes(it, itemCtx);
|
|
576
|
-
|
|
558
|
+
|
|
559
|
+
const customItem = renderSlotToArray(slots, "item", itemCtx, null);
|
|
560
|
+
const isButtonItem = uiUnwrap(it.button) === true || it.type === "button" || (!href && typeof it.onClick === "function");
|
|
561
|
+
const sharedProps = {
|
|
562
|
+
class: uiClass([
|
|
563
|
+
"jss-drawer-entry",
|
|
564
|
+
isButtonItem ? "jss-drawer-btn" : "jss-drawer-link",
|
|
565
|
+
isActive ? "active" : "",
|
|
566
|
+
disabled ? "is-disabled" : "",
|
|
567
|
+
tone ? `jss-drawer-tone-${tone}` : "",
|
|
568
|
+
it.class
|
|
569
|
+
]),
|
|
570
|
+
style: it.style,
|
|
571
|
+
"data-level": String(level),
|
|
572
|
+
"aria-current": isActive ? "page" : null,
|
|
573
|
+
"aria-disabled": disabled ? "true" : null
|
|
574
|
+
};
|
|
575
|
+
const entryNodes = customItem.length ? customItem : renderEntryNodes(it, itemCtx);
|
|
576
|
+
|
|
577
577
|
if (isButtonItem) {
|
|
578
578
|
const entryEl = _.button({
|
|
579
579
|
...sharedProps,
|
|
@@ -592,27 +592,27 @@ UI.Drawer = (...args) => {
|
|
|
592
592
|
activeLeafRefs.set(itemStateKey, { el: entryEl, baseActive: baseIsActive });
|
|
593
593
|
return entryEl;
|
|
594
594
|
}
|
|
595
|
-
|
|
596
|
-
const external = isExternalLink(it);
|
|
597
|
-
const target = external ? (uiUnwrap(it.target) || "_blank") : uiUnwrap(it.target);
|
|
598
|
-
const rel = external ? (uiUnwrap(it.rel) || "noopener noreferrer") : uiUnwrap(it.rel);
|
|
599
|
-
|
|
595
|
+
|
|
596
|
+
const external = isExternalLink(it);
|
|
597
|
+
const target = external ? (uiUnwrap(it.target) || "_blank") : uiUnwrap(it.target);
|
|
598
|
+
const rel = external ? (uiUnwrap(it.rel) || "noopener noreferrer") : uiUnwrap(it.rel);
|
|
599
|
+
|
|
600
600
|
const entryEl = _.a({
|
|
601
601
|
...sharedProps,
|
|
602
602
|
href: href || "#",
|
|
603
603
|
target: target || null,
|
|
604
604
|
rel: rel || null,
|
|
605
|
-
tabIndex: disabled ? -1 : null,
|
|
606
|
-
onClick: (e) => {
|
|
607
|
-
if (disabled) {
|
|
608
|
-
e.preventDefault();
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
if (!invokeItemHandler(it, itemCtx, e)) return;
|
|
612
|
-
if (!external && it.to && app.router?.navigate) {
|
|
613
|
-
e.preventDefault();
|
|
614
|
-
app.router.navigate(it.to);
|
|
615
|
-
}
|
|
605
|
+
tabIndex: disabled ? -1 : null,
|
|
606
|
+
onClick: (e) => {
|
|
607
|
+
if (disabled) {
|
|
608
|
+
e.preventDefault();
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (!invokeItemHandler(it, itemCtx, e)) return;
|
|
612
|
+
if (!external && it.to && app.router?.navigate) {
|
|
613
|
+
e.preventDefault();
|
|
614
|
+
app.router.navigate(it.to);
|
|
615
|
+
}
|
|
616
616
|
if (shouldClose(it)) closeDrawer();
|
|
617
617
|
}
|
|
618
618
|
}, ...entryNodes);
|
|
@@ -620,54 +620,54 @@ UI.Drawer = (...args) => {
|
|
|
620
620
|
return entryEl;
|
|
621
621
|
}).filter(Boolean);
|
|
622
622
|
};
|
|
623
|
-
|
|
624
|
-
const beforeNodes = renderArea(["before", "beforeItems"], rawProps.before ?? rawProps.beforeItems);
|
|
625
|
-
const bodyCustom = hasArea(["body"]) ? renderArea(["body"], null) : [];
|
|
626
|
-
const itemNodes = renderItems(rawProps.items || []);
|
|
627
|
-
const defaultNodes = renderArea(["default"], children);
|
|
628
|
-
const afterNodes = renderArea(["after", "afterItems"], rawProps.after ?? rawProps.afterItems);
|
|
629
|
-
const bodyNodes = bodyCustom.length ? bodyCustom : [...beforeNodes, ...itemNodes, ...defaultNodes, ...afterNodes];
|
|
630
|
-
const emptyFallback = hasOwn("empty") || hasOwn("emptyText")
|
|
631
|
-
? (rawProps.empty ?? _.div({ class: uiClass(["
|
|
632
|
-
: _.div({ class: uiClass(["
|
|
633
|
-
const headerNodes = renderArea(["header"], buildStructuredHeader());
|
|
634
|
-
const footerNodes = renderArea(["footer"], rawProps.footer);
|
|
635
|
-
const finalBodyNodes = bodyNodes.length ? bodyNodes : renderArea(["empty"], emptyFallback);
|
|
636
|
-
|
|
637
|
-
const p = JSswift.omit(props, [
|
|
638
|
-
"items", "header", "footer", "before", "beforeItems", "after", "afterItems",
|
|
639
|
-
"title", "subtitle", "eyebrow", "icon", "content", "meta", "actions",
|
|
640
|
-
"empty", "emptyText", "closeOnSelect", "groupOpenIcon", "groupCloseIcon",
|
|
641
|
-
"stateKey", "sticky", "slots", "headerClass", "bodyClass", "footerClass",
|
|
642
|
-
"emptyClass", "itemIconSize", "gap", "indent", "padding", "minHeight",
|
|
643
|
-
"maxHeight", "width", "onSelect"
|
|
644
|
-
]);
|
|
645
|
-
p.class = uiClass([
|
|
646
|
-
"
|
|
647
|
-
"
|
|
648
|
-
drawerOpen ? "open" : "",
|
|
649
|
-
uiWhen(rawProps.sticky, "sticky"),
|
|
650
|
-
props.class
|
|
651
|
-
]);
|
|
652
|
-
p.style = { ...(props.style || {}) };
|
|
653
|
-
if (rawProps.gap != null) p.style["--
|
|
654
|
-
if (rawProps.indent != null) p.style["--
|
|
655
|
-
if (rawProps.padding != null) p.style["--
|
|
656
|
-
if (rawProps.width != null) p.style.width = toCssSize(uiUnwrap(rawProps.width));
|
|
657
|
-
if (rawProps.minHeight != null) p.style.minHeight = toCssSize(uiUnwrap(rawProps.minHeight));
|
|
658
|
-
if (rawProps.maxHeight != null) p.style.maxHeight = toCssSize(uiUnwrap(rawProps.maxHeight));
|
|
659
|
-
|
|
660
|
-
const drawerEl = _.div(
|
|
661
|
-
p,
|
|
662
|
-
...(headerNodes.length ? headerNodes : []),
|
|
663
|
-
_.div({ class: uiClass(["
|
|
664
|
-
...(footerNodes.length ? [_.div({ class: uiClass(["
|
|
665
|
-
);
|
|
666
|
-
const drawerSet = drawerElsByKey.get(currentStateKey) || new Set();
|
|
667
|
-
drawerSet.add(drawerEl);
|
|
668
|
-
drawerElsByKey.set(currentStateKey, drawerSet);
|
|
669
|
-
setDrawerOpen(drawerOpen, currentStateKey);
|
|
670
|
-
drawerEl.isDrawerOpen = isDrawerOpen;
|
|
623
|
+
|
|
624
|
+
const beforeNodes = renderArea(["before", "beforeItems"], rawProps.before ?? rawProps.beforeItems);
|
|
625
|
+
const bodyCustom = hasArea(["body"]) ? renderArea(["body"], null) : [];
|
|
626
|
+
const itemNodes = renderItems(rawProps.items || []);
|
|
627
|
+
const defaultNodes = renderArea(["default"], children);
|
|
628
|
+
const afterNodes = renderArea(["after", "afterItems"], rawProps.after ?? rawProps.afterItems);
|
|
629
|
+
const bodyNodes = bodyCustom.length ? bodyCustom : [...beforeNodes, ...itemNodes, ...defaultNodes, ...afterNodes];
|
|
630
|
+
const emptyFallback = hasOwn("empty") || hasOwn("emptyText")
|
|
631
|
+
? (rawProps.empty ?? _.div({ class: uiClass(["jss-drawer-empty", rawProps.emptyClass]) }, rawProps.emptyText || "Nessun contenuto"))
|
|
632
|
+
: _.div({ class: uiClass(["jss-drawer-empty", rawProps.emptyClass]) }, "Nessun contenuto");
|
|
633
|
+
const headerNodes = renderArea(["header"], buildStructuredHeader());
|
|
634
|
+
const footerNodes = renderArea(["footer"], rawProps.footer);
|
|
635
|
+
const finalBodyNodes = bodyNodes.length ? bodyNodes : renderArea(["empty"], emptyFallback);
|
|
636
|
+
|
|
637
|
+
const p = JSswift.omit(props, [
|
|
638
|
+
"items", "header", "footer", "before", "beforeItems", "after", "afterItems",
|
|
639
|
+
"title", "subtitle", "eyebrow", "icon", "content", "meta", "actions",
|
|
640
|
+
"empty", "emptyText", "closeOnSelect", "groupOpenIcon", "groupCloseIcon",
|
|
641
|
+
"stateKey", "sticky", "slots", "headerClass", "bodyClass", "footerClass",
|
|
642
|
+
"emptyClass", "itemIconSize", "gap", "indent", "padding", "minHeight",
|
|
643
|
+
"maxHeight", "width", "onSelect"
|
|
644
|
+
]);
|
|
645
|
+
p.class = uiClass([
|
|
646
|
+
"jss-panel",
|
|
647
|
+
"jss-drawer",
|
|
648
|
+
drawerOpen ? "open" : "",
|
|
649
|
+
uiWhen(rawProps.sticky, "sticky"),
|
|
650
|
+
props.class
|
|
651
|
+
]);
|
|
652
|
+
p.style = { ...(props.style || {}) };
|
|
653
|
+
if (rawProps.gap != null) p.style["--jss-drawer-gap"] = toCssSize(uiUnwrap(rawProps.gap));
|
|
654
|
+
if (rawProps.indent != null) p.style["--jss-drawer-indent"] = toCssSize(uiUnwrap(rawProps.indent));
|
|
655
|
+
if (rawProps.padding != null) p.style["--jss-drawer-padding"] = toCssSize(uiUnwrap(rawProps.padding));
|
|
656
|
+
if (rawProps.width != null) p.style.width = toCssSize(uiUnwrap(rawProps.width));
|
|
657
|
+
if (rawProps.minHeight != null) p.style.minHeight = toCssSize(uiUnwrap(rawProps.minHeight));
|
|
658
|
+
if (rawProps.maxHeight != null) p.style.maxHeight = toCssSize(uiUnwrap(rawProps.maxHeight));
|
|
659
|
+
|
|
660
|
+
const drawerEl = _.div(
|
|
661
|
+
p,
|
|
662
|
+
...(headerNodes.length ? headerNodes : []),
|
|
663
|
+
_.div({ class: uiClass(["jss-drawer-body", rawProps.bodyClass]) }, ...finalBodyNodes),
|
|
664
|
+
...(footerNodes.length ? [_.div({ class: uiClass(["jss-drawer-footer", rawProps.footerClass]) }, ...footerNodes)] : [])
|
|
665
|
+
);
|
|
666
|
+
const drawerSet = drawerElsByKey.get(currentStateKey) || new Set();
|
|
667
|
+
drawerSet.add(drawerEl);
|
|
668
|
+
drawerElsByKey.set(currentStateKey, drawerSet);
|
|
669
|
+
setDrawerOpen(drawerOpen, currentStateKey);
|
|
670
|
+
drawerEl.isDrawerOpen = isDrawerOpen;
|
|
671
671
|
drawerEl.openDrawer = openDrawer;
|
|
672
672
|
drawerEl.closeDrawer = closeDrawer;
|
|
673
673
|
drawerEl.toggleDrawer = toggleDrawer;
|
|
@@ -676,548 +676,548 @@ UI.Drawer = (...args) => {
|
|
|
676
676
|
syncActiveClasses();
|
|
677
677
|
return drawerEl;
|
|
678
678
|
};
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
UI.Page = (...args) => {
|
|
682
|
-
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
683
|
-
const slots = rawProps.slots || {};
|
|
684
|
-
const props = { ...rawProps };
|
|
685
|
-
|
|
686
|
-
const isSectionNode = (node, name) => {
|
|
687
|
-
return !!(node && node.nodeType === 1 && node.classList?.contains(`
|
|
688
|
-
};
|
|
689
|
-
const renderIconFallback = (value) => {
|
|
690
|
-
if (value == null) return null;
|
|
691
|
-
if (typeof value === "string") return UI.Icon({ name: value, size: rawProps.iconSize || rawProps.size || "xl" });
|
|
692
|
-
return JSswift.ui.slot(value, { as: "icon" });
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
const ctx = {
|
|
696
|
-
dense: !!uiUnwrap(rawProps.dense),
|
|
697
|
-
flat: !!uiUnwrap(rawProps.flat),
|
|
698
|
-
centered: !!uiUnwrap(rawProps.centered),
|
|
699
|
-
narrow: !!uiUnwrap(rawProps.narrow)
|
|
700
|
-
};
|
|
701
|
-
const appendResolvedValue = (host, value) => {
|
|
702
|
-
if (value == null || value === false) return;
|
|
703
|
-
if (Array.isArray(value)) {
|
|
704
|
-
value.forEach((item) => appendResolvedValue(host, item));
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
if (value?.nodeType) {
|
|
708
|
-
host.appendChild(value);
|
|
709
|
-
return;
|
|
710
|
-
}
|
|
711
|
-
host.appendChild(document.createTextNode(String(value)));
|
|
712
|
-
};
|
|
713
|
-
const renderPropNodes = (name, fallback, map = (value) => value) => {
|
|
714
|
-
const slot = JSswift.ui.getSlot(slots, name);
|
|
715
|
-
if (slot !== null && slot !== undefined) {
|
|
716
|
-
return renderSlotToArray(slots, name, ctx, null);
|
|
717
|
-
}
|
|
718
|
-
if (typeof fallback === "function") {
|
|
719
|
-
const inlineNames = new Set(["eyebrow", "title", "subtitle"]);
|
|
720
|
-
const host = _[inlineNames.has(name) ? "span" : "div"]({ class: `
|
|
721
|
-
JSswift.reactive.effect(() => {
|
|
722
|
-
const nextValue = map(fallback(ctx));
|
|
723
|
-
const normalized = flattenSlotValue(JSswift.ui.slot(nextValue));
|
|
724
|
-
host.replaceChildren();
|
|
725
|
-
if (Array.isArray(normalized)) normalized.forEach((item) => appendResolvedValue(host, item));
|
|
726
|
-
else appendResolvedValue(host, normalized);
|
|
727
|
-
}, `UI.Page:${name}`);
|
|
728
|
-
return [host];
|
|
729
|
-
}
|
|
730
|
-
return renderSlotToArray(slots, name, ctx, map(fallback));
|
|
731
|
-
};
|
|
732
|
-
|
|
733
|
-
const defaultNodes = renderSlotToArray(slots, "default", ctx, children?.length ? children : []);
|
|
734
|
-
const sectionNodes = {
|
|
735
|
-
hero: [],
|
|
736
|
-
header: [],
|
|
737
|
-
body: [],
|
|
738
|
-
footer: [],
|
|
739
|
-
actions: []
|
|
740
|
-
};
|
|
741
|
-
const looseNodes = [];
|
|
742
|
-
|
|
743
|
-
defaultNodes.forEach((node) => {
|
|
744
|
-
if (isSectionNode(node, "hero")) sectionNodes.hero.push(node);
|
|
745
|
-
else if (isSectionNode(node, "header")) sectionNodes.header.push(node);
|
|
746
|
-
else if (isSectionNode(node, "body")) sectionNodes.body.push(node);
|
|
747
|
-
else if (isSectionNode(node, "footer")) sectionNodes.footer.push(node);
|
|
748
|
-
else if (isSectionNode(node, "actions")) sectionNodes.actions.push(node);
|
|
749
|
-
else looseNodes.push(node);
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
const iconNodes = renderPropNodes("icon", rawProps.icon, renderIconFallback);
|
|
753
|
-
const heroNodes = renderPropNodes("hero", rawProps.hero ?? rawProps.banner);
|
|
754
|
-
const eyebrowNodes = renderPropNodes("eyebrow", rawProps.eyebrow ?? rawProps.kicker);
|
|
755
|
-
const titleNodes = renderPropNodes("title", rawProps.title);
|
|
756
|
-
const subtitleNodes = renderPropNodes("subtitle", rawProps.subtitle ?? rawProps.description);
|
|
757
|
-
const headerNodes = renderPropNodes("header", rawProps.header);
|
|
758
|
-
const asideNodes = renderPropNodes("aside", rawProps.aside);
|
|
759
|
-
const bodyNodes = renderPropNodes("body", rawProps.body ?? rawProps.content);
|
|
760
|
-
const footerNodes = renderPropNodes("footer", rawProps.footer);
|
|
761
|
-
const actionsNodes = renderPropNodes("actions", rawProps.actions);
|
|
762
|
-
|
|
763
|
-
const generatedHero = heroNodes.length
|
|
764
|
-
? _.div({ class: uiClass(["
|
|
765
|
-
: null;
|
|
766
|
-
|
|
767
|
-
const hasStructuredHeader = iconNodes.length || eyebrowNodes.length || titleNodes.length || subtitleNodes.length || headerNodes.length || asideNodes.length;
|
|
768
|
-
const generatedHeader = hasStructuredHeader
|
|
769
|
-
? _.div(
|
|
770
|
-
{ class: uiClass(["
|
|
771
|
-
_.div(
|
|
772
|
-
{ class: "
|
|
773
|
-
iconNodes.length ? _.div({ class: uiClass(["
|
|
774
|
-
_.div(
|
|
775
|
-
{ class: "
|
|
776
|
-
eyebrowNodes.length ? _.div({ class: uiClass(["
|
|
777
|
-
titleNodes.length ? _.div({ class: uiClass(["
|
|
778
|
-
subtitleNodes.length ? _.div({ class: uiClass(["
|
|
779
|
-
headerNodes.length ? _.div({ class: uiClass(["
|
|
780
|
-
),
|
|
781
|
-
asideNodes.length ? _.div({ class: uiClass(["
|
|
782
|
-
)
|
|
783
|
-
)
|
|
784
|
-
: null;
|
|
785
|
-
|
|
786
|
-
const mergedBodyNodes = [...bodyNodes, ...looseNodes];
|
|
787
|
-
const generatedBody = mergedBodyNodes.length
|
|
788
|
-
? _.div({ class: uiClass(["
|
|
789
|
-
: null;
|
|
790
|
-
|
|
791
|
-
const mergedActionNodes = [...actionsNodes, ...sectionNodes.actions];
|
|
792
|
-
const generatedFooter = (footerNodes.length || mergedActionNodes.length)
|
|
793
|
-
? _.div(
|
|
794
|
-
{ class: uiClass(["
|
|
795
|
-
...footerNodes,
|
|
796
|
-
mergedActionNodes.length ? _.div({ class: "
|
|
797
|
-
)
|
|
798
|
-
: null;
|
|
799
|
-
|
|
800
|
-
const hasHero = !!(heroNodes.length || sectionNodes.hero.length);
|
|
801
|
-
const hasHeader = !!(hasStructuredHeader || sectionNodes.header.length);
|
|
802
|
-
const p = JSswift.omit(props, [
|
|
803
|
-
"actions", "aside", "asideClass", "banner", "body", "bodyClass", "centered", "content",
|
|
804
|
-
"dense", "description", "eyebrow", "eyebrowClass", "flat", "footer", "footerClass",
|
|
805
|
-
"gap", "header", "headerClass", "headerContentClass", "headerGap", "hero", "heroClass",
|
|
806
|
-
"heroPadding", "icon", "iconClass", "iconSize", "kicker", "maxWidth", "minHeight",
|
|
807
|
-
"narrow", "padding", "size", "slots", "subtitle", "subtitleClass", "title", "titleClass"
|
|
808
|
-
]);
|
|
809
|
-
p.class = uiClass([
|
|
810
|
-
"
|
|
811
|
-
"
|
|
812
|
-
uiWhen(rawProps.dense, "dense"),
|
|
813
|
-
uiWhen(rawProps.flat, "
|
|
814
|
-
uiWhen(rawProps.centered, "
|
|
815
|
-
uiWhen(rawProps.narrow, "
|
|
816
|
-
uiWhen(hasHero, "
|
|
817
|
-
uiWhen(hasHeader, "
|
|
818
|
-
props.class
|
|
819
|
-
]);
|
|
820
|
-
p.style = { ...(props.style || {}) };
|
|
821
|
-
|
|
822
|
-
if (rawProps.gap != null || uiIsReactive(rawProps.gap)) {
|
|
823
|
-
p.style["--
|
|
824
|
-
}
|
|
825
|
-
if (rawProps.padding != null || uiIsReactive(rawProps.padding)) {
|
|
826
|
-
p.style["--
|
|
827
|
-
}
|
|
828
|
-
if (rawProps.maxWidth != null || uiIsReactive(rawProps.maxWidth)) {
|
|
829
|
-
p.style["--
|
|
830
|
-
}
|
|
831
|
-
if (rawProps.minHeight != null || uiIsReactive(rawProps.minHeight)) {
|
|
832
|
-
p.style["--
|
|
833
|
-
}
|
|
834
|
-
if (rawProps.headerGap != null || uiIsReactive(rawProps.headerGap)) {
|
|
835
|
-
p.style["--
|
|
836
|
-
}
|
|
837
|
-
if (rawProps.heroPadding != null || uiIsReactive(rawProps.heroPadding)) {
|
|
838
|
-
p.style["--
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
const el = _.div(
|
|
842
|
-
p,
|
|
843
|
-
generatedHero,
|
|
844
|
-
...sectionNodes.hero,
|
|
845
|
-
generatedHeader,
|
|
846
|
-
...sectionNodes.header,
|
|
847
|
-
generatedBody,
|
|
848
|
-
...sectionNodes.body,
|
|
849
|
-
generatedFooter,
|
|
850
|
-
...sectionNodes.footer
|
|
851
|
-
);
|
|
852
|
-
|
|
853
|
-
setPropertyProps(el, rawProps);
|
|
854
|
-
return el;
|
|
855
|
-
};
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
UI.AppShell = (...args) => {
|
|
859
|
-
const { props, children } = JSswift.uiNormalizeArgs(args);
|
|
860
|
-
const slots = props.slots || {};
|
|
861
|
-
const hasOwn = (obj, key) => !!obj && Object.prototype.hasOwnProperty.call(obj, key);
|
|
862
|
-
|
|
863
|
-
const noDrawer = uiUnwrap(props.noDrawer) === true || props.drawer === false;
|
|
864
|
-
const reverse = uiUnwrap(props.reverse) === true;
|
|
865
|
-
const stack = uiUnwrap(props.stack) === true;
|
|
866
|
-
const currentStateKey = props.drawerStateKey ?? props.stateKey ?? drawerStateKey;
|
|
867
|
-
|
|
868
|
-
if (currentStateKey) {
|
|
869
|
-
drawerStateKey = currentStateKey;
|
|
870
|
-
drawerOpen = readDrawerOpen(currentStateKey);
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
const shellCtx = {
|
|
874
|
-
props,
|
|
875
|
-
noDrawer,
|
|
876
|
-
stateKey: currentStateKey,
|
|
877
|
-
isDrawerOpen: () => readDrawerOpen(currentStateKey),
|
|
878
|
-
openDrawer: () => setDrawerOpen(true, currentStateKey),
|
|
879
|
-
closeDrawer: () => setDrawerOpen(false, currentStateKey),
|
|
880
|
-
toggleDrawer: () => setDrawerOpen(!readDrawerOpen(currentStateKey), currentStateKey)
|
|
881
|
-
};
|
|
882
|
-
|
|
883
|
-
const headerProps = (props.headerProps && typeof props.headerProps === "object") ? { ...props.headerProps } : {};
|
|
884
|
-
let headerFallback = props.header;
|
|
885
|
-
if (!hasOwn(props, "header") && (
|
|
886
|
-
Object.keys(headerProps).length ||
|
|
887
|
-
hasOwn(props, "title") ||
|
|
888
|
-
hasOwn(props, "subtitle") ||
|
|
889
|
-
hasOwn(props, "left") ||
|
|
890
|
-
hasOwn(props, "right")
|
|
891
|
-
)) {
|
|
892
|
-
if (!hasOwn(headerProps, "title") && hasOwn(props, "title")) headerProps.title = props.title;
|
|
893
|
-
if (!hasOwn(headerProps, "subtitle") && hasOwn(props, "subtitle")) headerProps.subtitle = props.subtitle;
|
|
894
|
-
if (!hasOwn(headerProps, "left") && hasOwn(props, "left")) headerProps.left = props.left;
|
|
895
|
-
if (!hasOwn(headerProps, "right") && hasOwn(props, "right")) headerProps.right = props.right;
|
|
896
|
-
if (!hasOwn(headerProps, "drawerStateKey")) headerProps.drawerStateKey = currentStateKey;
|
|
897
|
-
if (noDrawer && !hasOwn(headerProps, "left")) headerProps.left = false;
|
|
898
|
-
headerFallback = UI.Header(headerProps);
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
const drawerProps = (props.drawerProps && typeof props.drawerProps === "object") ? { ...props.drawerProps } : {};
|
|
902
|
-
const drawerItems = hasOwn(props, "drawerItems") ? props.drawerItems : props.items;
|
|
903
|
-
const drawerHeader = hasOwn(props, "drawerHeader") ? props.drawerHeader : undefined;
|
|
904
|
-
let drawerFallback = props.drawer;
|
|
905
|
-
if (!hasOwn(props, "drawer") && !noDrawer && (
|
|
906
|
-
Object.keys(drawerProps).length ||
|
|
907
|
-
drawerItems != null ||
|
|
908
|
-
drawerHeader != null
|
|
909
|
-
)) {
|
|
910
|
-
if (!hasOwn(drawerProps, "items") && drawerItems != null) drawerProps.items = drawerItems;
|
|
911
|
-
if (!hasOwn(drawerProps, "header") && drawerHeader != null) drawerProps.header = drawerHeader;
|
|
912
|
-
if (!hasOwn(drawerProps, "stateKey")) drawerProps.stateKey = currentStateKey;
|
|
913
|
-
drawerFallback = UI.Drawer(drawerProps);
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
const pageProps = (props.pageProps && typeof props.pageProps === "object") ? { ...props.pageProps } : {};
|
|
917
|
-
const pageContentFallback = hasOwn(props, "content") ? props.content : children;
|
|
918
|
-
const defaultPageContent = renderSlotToArray(slots, "default", shellCtx, pageContentFallback);
|
|
919
|
-
let pageFallback = props.page;
|
|
920
|
-
if (!hasOwn(props, "page") && (Object.keys(pageProps).length || defaultPageContent.length)) {
|
|
921
|
-
pageFallback = UI.Page(pageProps, ...defaultPageContent);
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
const footerProps = (props.footerProps && typeof props.footerProps === "object") ? { ...props.footerProps } : {};
|
|
925
|
-
const footerContent = hasOwn(props, "footerContent") ? props.footerContent : undefined;
|
|
926
|
-
let footerFallback = props.footer;
|
|
927
|
-
if (!hasOwn(props, "footer") && (Object.keys(footerProps).length || footerContent != null)) {
|
|
928
|
-
footerFallback = UI.Footer(footerProps, ...renderSlotToArray(null, "default", shellCtx, footerContent));
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
const headerNodes = renderSlotToArray(slots, "header", shellCtx, headerFallback);
|
|
932
|
-
const drawerNodes = noDrawer ? [] : renderSlotToArray(slots, "drawer", shellCtx, drawerFallback);
|
|
933
|
-
const pageNodes = renderSlotToArray(slots, "page", shellCtx, pageFallback);
|
|
934
|
-
const footerNodes = renderSlotToArray(slots, "footer", shellCtx, footerFallback);
|
|
935
|
-
|
|
936
|
-
const cls = uiClass([
|
|
937
|
-
"
|
|
938
|
-
"
|
|
939
|
-
uiWhen(noDrawer, "no-drawer"),
|
|
940
|
-
uiWhen(reverse, "is-reverse"),
|
|
941
|
-
uiWhen(stack, "is-stack"),
|
|
942
|
-
uiWhen(props.flush, "is-flush"),
|
|
943
|
-
uiWhen(props.divider, "is-divider"),
|
|
944
|
-
props.class
|
|
945
|
-
]);
|
|
946
|
-
|
|
947
|
-
const p = JSswift.omit(props, [
|
|
948
|
-
"header", "drawer", "page", "footer", "content",
|
|
949
|
-
"title", "subtitle", "left", "right",
|
|
950
|
-
"items", "drawerItems", "drawerHeader",
|
|
951
|
-
"headerProps", "drawerProps", "pageProps", "footerProps",
|
|
952
|
-
"footerContent",
|
|
953
|
-
"noDrawer", "reverse", "stack", "flush", "divider",
|
|
954
|
-
"drawerStateKey", "stateKey",
|
|
955
|
-
"drawerWidth", "gap", "padding",
|
|
956
|
-
"slots"
|
|
957
|
-
]);
|
|
958
|
-
p.class = cls;
|
|
959
|
-
p.style = { ...(props.style || {}) };
|
|
960
|
-
|
|
961
|
-
const drawerWidth = uiStyleValue(props.drawerWidth, toCssSize);
|
|
962
|
-
if (drawerWidth != null) p.style["--
|
|
963
|
-
const gap = uiStyleValue(props.gap, toCssSize);
|
|
964
|
-
if (gap != null) p.style["--
|
|
965
|
-
const padding = uiStyleValue(props.padding, toCssSize);
|
|
966
|
-
if (padding != null) p.style["--
|
|
967
|
-
|
|
968
|
-
const headerWrap = headerNodes.length
|
|
969
|
-
? _.div({ class: "
|
|
970
|
-
: null;
|
|
971
|
-
const drawerWrap = drawerNodes.length
|
|
972
|
-
? _.div({ class: "
|
|
973
|
-
: null;
|
|
974
|
-
const pageWrap = pageNodes.length
|
|
975
|
-
? _.div({ class: "
|
|
976
|
-
: null;
|
|
977
|
-
const footerWrap = footerNodes.length
|
|
978
|
-
? _.div({ class: "
|
|
979
|
-
: null;
|
|
980
|
-
|
|
981
|
-
const bodyNodes = reverse
|
|
982
|
-
? [pageWrap, drawerWrap]
|
|
983
|
-
: [drawerWrap, pageWrap];
|
|
984
|
-
|
|
985
|
-
const root = _.div(
|
|
986
|
-
p,
|
|
987
|
-
...(headerWrap ? [headerWrap] : []),
|
|
988
|
-
_.div({ class: "
|
|
989
|
-
...(footerWrap ? [footerWrap] : [])
|
|
990
|
-
);
|
|
991
|
-
|
|
992
|
-
root.openDrawer = shellCtx.openDrawer;
|
|
993
|
-
root.closeDrawer = shellCtx.closeDrawer;
|
|
994
|
-
root.toggleDrawer = shellCtx.toggleDrawer;
|
|
995
|
-
root.isDrawerOpen = shellCtx.isDrawerOpen;
|
|
996
|
-
root.header = headerWrap;
|
|
997
|
-
root.drawer = drawerWrap;
|
|
998
|
-
root.page = pageWrap;
|
|
999
|
-
root.footer = footerWrap;
|
|
1000
|
-
|
|
1001
|
-
setPropertyProps(root, props);
|
|
1002
|
-
return root;
|
|
1003
|
-
};
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
UI.Parallax = function Parallax(...args) {
|
|
1007
|
-
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
1008
|
-
const slots = rawProps.slots || {};
|
|
1009
|
-
const props = { ...rawProps };
|
|
1010
|
-
|
|
1011
|
-
if (props.color != null && props.textColor == null) props.textColor = props.color;
|
|
1012
|
-
delete props.color;
|
|
1013
|
-
applyCommonProps(props);
|
|
1014
|
-
|
|
1015
|
-
const stateClass = uiComputed(rawProps.state, () => {
|
|
1016
|
-
const state = normalizeState(uiUnwrap(rawProps.state));
|
|
1017
|
-
return state ? `
|
|
1018
|
-
});
|
|
1019
|
-
const mapColorValue = (value) => {
|
|
1020
|
-
if (value == null || value === false || value === "") return "";
|
|
1021
|
-
const text = String(value);
|
|
1022
|
-
return isTokenCSS(text) ? `var(--
|
|
1023
|
-
};
|
|
1024
|
-
const getBackgroundImage = () => {
|
|
1025
|
-
const background = uiUnwrap(rawProps.background);
|
|
1026
|
-
if (background) return String(background);
|
|
1027
|
-
const source = uiUnwrap(rawProps.image) || uiUnwrap(rawProps.src) || "";
|
|
1028
|
-
if (!source) return "linear-gradient(120deg, #1b2c5a, #2f6d8f, #2a8f5c)";
|
|
1029
|
-
const text = String(source);
|
|
1030
|
-
if (/^url\(/i.test(text) || /gradient\(/i.test(text) || /^var\(/i.test(text)) return text;
|
|
1031
|
-
return `url(${text})`;
|
|
1032
|
-
};
|
|
1033
|
-
const getNumericValue = (value, fallback) => {
|
|
1034
|
-
const num = Number(uiUnwrap(value));
|
|
1035
|
-
return Number.isFinite(num) ? num : fallback;
|
|
1036
|
-
};
|
|
1037
|
-
|
|
1038
|
-
const ctx = {
|
|
1039
|
-
speed: () => uiUnwrap(rawProps.speed) ?? 0.18,
|
|
1040
|
-
state: () => uiUnwrap(rawProps.state) || "",
|
|
1041
|
-
disabled: () => !!uiUnwrap(rawProps.disabled)
|
|
1042
|
-
};
|
|
1043
|
-
|
|
1044
|
-
const badgeNodes = renderSlotToArray(slots, "badge", ctx, rawProps.badge);
|
|
1045
|
-
const backgroundNodes = renderSlotToArray(slots, "background", ctx, rawProps.backgroundContent);
|
|
1046
|
-
const eyebrowNodes = renderSlotToArray(slots, "eyebrow", ctx, rawProps.eyebrow ?? rawProps.kicker);
|
|
1047
|
-
const titleNodes = renderSlotToArray(slots, "title", ctx, rawProps.title);
|
|
1048
|
-
const subtitleNodes = renderSlotToArray(slots, "subtitle", ctx, rawProps.subtitle);
|
|
1049
|
-
const headerNodes = renderSlotToArray(slots, "header", ctx, rawProps.header);
|
|
1050
|
-
const asideNodes = renderSlotToArray(slots, "aside", ctx, rawProps.aside);
|
|
1051
|
-
const mediaNodes = renderSlotToArray(slots, "media", ctx, rawProps.media);
|
|
1052
|
-
const contentNodes = renderSlotToArray(slots, "content", ctx, rawProps.content ?? rawProps.body);
|
|
1053
|
-
const defaultNodes = renderSlotToArray(slots, "default", ctx, children?.length ? children : []);
|
|
1054
|
-
const footerNodes = renderSlotToArray(slots, "footer", ctx, rawProps.footer);
|
|
1055
|
-
const actionsNodes = renderSlotToArray(slots, "actions", ctx, rawProps.actions);
|
|
1056
|
-
const mergedBodyNodes = [...contentNodes, ...defaultNodes];
|
|
1057
|
-
|
|
1058
|
-
const generatedBadge = badgeNodes.length
|
|
1059
|
-
? _.div({ class: uiClass(["
|
|
1060
|
-
: null;
|
|
1061
|
-
const hasStructuredHeader = eyebrowNodes.length || titleNodes.length || subtitleNodes.length || headerNodes.length || asideNodes.length;
|
|
1062
|
-
const generatedHeader = hasStructuredHeader
|
|
1063
|
-
? _.div(
|
|
1064
|
-
{ class: uiClass(["
|
|
1065
|
-
_.div(
|
|
1066
|
-
{ class: "
|
|
1067
|
-
_.div(
|
|
1068
|
-
{ class: "
|
|
1069
|
-
eyebrowNodes.length ? _.div({ class: uiClass(["
|
|
1070
|
-
titleNodes.length ? _.div({ class: uiClass(["
|
|
1071
|
-
subtitleNodes.length ? _.div({ class: uiClass(["
|
|
1072
|
-
headerNodes.length ? _.div({ class: uiClass(["
|
|
1073
|
-
),
|
|
1074
|
-
asideNodes.length ? _.div({ class: uiClass(["
|
|
1075
|
-
)
|
|
1076
|
-
)
|
|
1077
|
-
: null;
|
|
1078
|
-
const generatedMedia = mediaNodes.length
|
|
1079
|
-
? _.div({ class: uiClass(["
|
|
1080
|
-
: null;
|
|
1081
|
-
const generatedBody = mergedBodyNodes.length
|
|
1082
|
-
? _.div({ class: uiClass(["
|
|
1083
|
-
: null;
|
|
1084
|
-
const generatedFooter = (footerNodes.length || actionsNodes.length)
|
|
1085
|
-
? _.div(
|
|
1086
|
-
{ class: uiClass(["
|
|
1087
|
-
footerNodes.length ? _.div({ class: "
|
|
1088
|
-
actionsNodes.length ? _.div({ class: "
|
|
1089
|
-
)
|
|
1090
|
-
: null;
|
|
1091
|
-
|
|
1092
|
-
const wrapProps = JSswift.omit(props, [
|
|
1093
|
-
"actions", "align", "aside", "asideClass", "background", "backgroundContent", "backgroundContentClass",
|
|
1094
|
-
"badge", "badgeClass", "bgClass", "bgPosition", "bgRepeat", "bgSize", "body", "bodyClass", "color",
|
|
1095
|
-
"content", "contentClass", "contentMaxWidth", "disabled", "eyebrow", "eyebrowClass", "footer",
|
|
1096
|
-
"footerClass", "gap", "header", "headerClass", "headerContentClass", "height", "image", "imageAlt",
|
|
1097
|
-
"imageClass", "innerClass", "justify", "kicker", "maxOffset", "media", "mediaClass", "minHeight",
|
|
1098
|
-
"overlay", "padding", "slots", "speed", "src", "startTop", "state", "subtitle", "subtitleClass",
|
|
1099
|
-
"textColor", "title", "titleClass"
|
|
1100
|
-
]);
|
|
1101
|
-
wrapProps.class = uiClass([
|
|
1102
|
-
"
|
|
1103
|
-
"
|
|
1104
|
-
stateClass,
|
|
1105
|
-
uiWhen(rawProps.disabled, "
|
|
1106
|
-
uiWhen(generatedBadge, "
|
|
1107
|
-
uiWhen(hasStructuredHeader, "
|
|
1108
|
-
props.class
|
|
1109
|
-
]);
|
|
1110
|
-
wrapProps.style = { ...(props.style || {}) };
|
|
1111
|
-
if (rawProps.height != null) wrapProps.style["--
|
|
1112
|
-
if (rawProps.minHeight != null) wrapProps.style["--
|
|
1113
|
-
if (rawProps.padding != null) wrapProps.style["--
|
|
1114
|
-
if (rawProps.gap != null) wrapProps.style["--
|
|
1115
|
-
if (rawProps.contentMaxWidth != null) wrapProps.style["--
|
|
1116
|
-
if (rawProps.justify != null) wrapProps.style["--
|
|
1117
|
-
if (rawProps.align != null) wrapProps.style["--
|
|
1118
|
-
if (rawProps.color != null) wrapProps.style["--
|
|
1119
|
-
if (rawProps.overlay != null) wrapProps.style["--
|
|
1120
|
-
if (rawProps.bgPosition != null) wrapProps.style["--
|
|
1121
|
-
if (rawProps.bgSize != null) wrapProps.style["--
|
|
1122
|
-
if (rawProps.bgRepeat != null) wrapProps.style["--
|
|
1123
|
-
wrapProps.style["--
|
|
1124
|
-
? () => getBackgroundImage()
|
|
1125
|
-
: getBackgroundImage();
|
|
1126
|
-
|
|
1127
|
-
const bg = _.div(
|
|
1128
|
-
{ class: uiClass(["
|
|
1129
|
-
backgroundNodes.length
|
|
1130
|
-
? _.div({ class: uiClass(["
|
|
1131
|
-
: null
|
|
1132
|
-
);
|
|
1133
|
-
const content = _.div(
|
|
1134
|
-
{ class: uiClass(["
|
|
1135
|
-
generatedBadge,
|
|
1136
|
-
generatedHeader,
|
|
1137
|
-
generatedMedia,
|
|
1138
|
-
generatedBody,
|
|
1139
|
-
generatedFooter
|
|
1140
|
-
);
|
|
1141
|
-
|
|
1142
|
-
const wrap = _.div(wrapProps, bg, content);
|
|
1143
|
-
|
|
1144
|
-
let disposed = false;
|
|
1145
|
-
let ticking = false;
|
|
1146
|
-
let resizeObserver = null;
|
|
1147
|
-
|
|
1148
|
-
const cleanup = () => {
|
|
1149
|
-
if (disposed) return;
|
|
1150
|
-
disposed = true;
|
|
1151
|
-
if (typeof window !== "undefined") {
|
|
1152
|
-
window.removeEventListener("scroll", scheduleUpdate);
|
|
1153
|
-
window.removeEventListener("resize", scheduleUpdate);
|
|
1154
|
-
}
|
|
1155
|
-
resizeObserver?.disconnect?.();
|
|
1156
|
-
resizeObserver = null;
|
|
1157
|
-
};
|
|
1158
|
-
|
|
1159
|
-
const update = () => {
|
|
1160
|
-
if (disposed) return;
|
|
1161
|
-
if (!wrap.isConnected) {
|
|
1162
|
-
cleanup();
|
|
1163
|
-
return;
|
|
1164
|
-
}
|
|
1165
|
-
if (uiUnwrap(rawProps.disabled)) {
|
|
1166
|
-
bg.style.transform = "translate3d(0, 0, 0)";
|
|
1167
|
-
wrap.style.setProperty("--
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
|
-
const rect = wrap.getBoundingClientRect();
|
|
1171
|
-
const speed = getNumericValue(rawProps.speed, 0.18);
|
|
1172
|
-
const maxOffset = Math.abs(getNumericValue(rawProps.maxOffset, 96));
|
|
1173
|
-
const explicitStartTop = uiUnwrap(rawProps.startTop);
|
|
1174
|
-
const rawOffset = explicitStartTop != null && explicitStartTop !== ""
|
|
1175
|
-
? (rect.top - getNumericValue(rawProps.startTop, 0)) * speed
|
|
1176
|
-
: (((typeof window !== "undefined" ? window.innerHeight || document.documentElement.clientHeight || 0 : 0) / 2) - (rect.top + (rect.height / 2))) * speed;
|
|
1177
|
-
const offset = maxOffset > 0 ? Math.max(-maxOffset, Math.min(maxOffset, rawOffset)) : rawOffset;
|
|
1178
|
-
const cssOffset = `${offset.toFixed(2)}px`;
|
|
1179
|
-
bg.style.transform = `translate3d(0, ${cssOffset}, 0)`;
|
|
1180
|
-
wrap.style.setProperty("--
|
|
1181
|
-
};
|
|
1182
|
-
|
|
1183
|
-
function scheduleUpdate() {
|
|
1184
|
-
if (disposed || ticking) return;
|
|
1185
|
-
ticking = true;
|
|
1186
|
-
requestAnimationFrame(() => {
|
|
1187
|
-
ticking = false;
|
|
1188
|
-
update();
|
|
1189
|
-
});
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
if (typeof window !== "undefined") {
|
|
1193
|
-
window.addEventListener("scroll", scheduleUpdate, { passive: true });
|
|
1194
|
-
window.addEventListener("resize", scheduleUpdate);
|
|
1195
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
1196
|
-
resizeObserver = new ResizeObserver(() => { scheduleUpdate(); });
|
|
1197
|
-
resizeObserver.observe(wrap);
|
|
1198
|
-
}
|
|
1199
|
-
requestAnimationFrame(() => { scheduleUpdate(); });
|
|
1200
|
-
setTimeout(() => { scheduleUpdate(); }, 90);
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
wrap.refresh = () => {
|
|
1204
|
-
scheduleUpdate();
|
|
1205
|
-
return wrap;
|
|
1206
|
-
};
|
|
1207
|
-
wrap.update = wrap.refresh;
|
|
1208
|
-
wrap.destroy = () => {
|
|
1209
|
-
cleanup();
|
|
1210
|
-
wrap.remove();
|
|
1211
|
-
return null;
|
|
1212
|
-
};
|
|
1213
|
-
wrap._dispose = cleanup;
|
|
1214
|
-
|
|
1215
|
-
setPropertyProps(wrap, rawProps);
|
|
1216
|
-
return wrap;
|
|
1217
|
-
};
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
// Example:
|
|
1221
|
-
// _.Parallax({ src: "/assets/hero.jpg", height: "280px", speed: 0.2 }, _.h2("Hello"));
|
|
1222
|
-
|
|
1223
|
-
// -------------------------------
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
UI.Page = (...args) => {
|
|
682
|
+
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
683
|
+
const slots = rawProps.slots || {};
|
|
684
|
+
const props = { ...rawProps };
|
|
685
|
+
|
|
686
|
+
const isSectionNode = (node, name) => {
|
|
687
|
+
return !!(node && node.nodeType === 1 && node.classList?.contains(`jss-page-${name}`));
|
|
688
|
+
};
|
|
689
|
+
const renderIconFallback = (value) => {
|
|
690
|
+
if (value == null) return null;
|
|
691
|
+
if (typeof value === "string") return UI.Icon({ name: value, size: rawProps.iconSize || rawProps.size || "xl" });
|
|
692
|
+
return JSswift.ui.slot(value, { as: "icon" });
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
const ctx = {
|
|
696
|
+
dense: !!uiUnwrap(rawProps.dense),
|
|
697
|
+
flat: !!uiUnwrap(rawProps.flat),
|
|
698
|
+
centered: !!uiUnwrap(rawProps.centered),
|
|
699
|
+
narrow: !!uiUnwrap(rawProps.narrow)
|
|
700
|
+
};
|
|
701
|
+
const appendResolvedValue = (host, value) => {
|
|
702
|
+
if (value == null || value === false) return;
|
|
703
|
+
if (Array.isArray(value)) {
|
|
704
|
+
value.forEach((item) => appendResolvedValue(host, item));
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
if (value?.nodeType) {
|
|
708
|
+
host.appendChild(value);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
host.appendChild(document.createTextNode(String(value)));
|
|
712
|
+
};
|
|
713
|
+
const renderPropNodes = (name, fallback, map = (value) => value) => {
|
|
714
|
+
const slot = JSswift.ui.getSlot(slots, name);
|
|
715
|
+
if (slot !== null && slot !== undefined) {
|
|
716
|
+
return renderSlotToArray(slots, name, ctx, null);
|
|
717
|
+
}
|
|
718
|
+
if (typeof fallback === "function") {
|
|
719
|
+
const inlineNames = new Set(["eyebrow", "title", "subtitle"]);
|
|
720
|
+
const host = _[inlineNames.has(name) ? "span" : "div"]({ class: `jss-page-slot-${name}` });
|
|
721
|
+
JSswift.reactive.effect(() => {
|
|
722
|
+
const nextValue = map(fallback(ctx));
|
|
723
|
+
const normalized = flattenSlotValue(JSswift.ui.slot(nextValue));
|
|
724
|
+
host.replaceChildren();
|
|
725
|
+
if (Array.isArray(normalized)) normalized.forEach((item) => appendResolvedValue(host, item));
|
|
726
|
+
else appendResolvedValue(host, normalized);
|
|
727
|
+
}, `UI.Page:${name}`);
|
|
728
|
+
return [host];
|
|
729
|
+
}
|
|
730
|
+
return renderSlotToArray(slots, name, ctx, map(fallback));
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
const defaultNodes = renderSlotToArray(slots, "default", ctx, children?.length ? children : []);
|
|
734
|
+
const sectionNodes = {
|
|
735
|
+
hero: [],
|
|
736
|
+
header: [],
|
|
737
|
+
body: [],
|
|
738
|
+
footer: [],
|
|
739
|
+
actions: []
|
|
740
|
+
};
|
|
741
|
+
const looseNodes = [];
|
|
742
|
+
|
|
743
|
+
defaultNodes.forEach((node) => {
|
|
744
|
+
if (isSectionNode(node, "hero")) sectionNodes.hero.push(node);
|
|
745
|
+
else if (isSectionNode(node, "header")) sectionNodes.header.push(node);
|
|
746
|
+
else if (isSectionNode(node, "body")) sectionNodes.body.push(node);
|
|
747
|
+
else if (isSectionNode(node, "footer")) sectionNodes.footer.push(node);
|
|
748
|
+
else if (isSectionNode(node, "actions")) sectionNodes.actions.push(node);
|
|
749
|
+
else looseNodes.push(node);
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
const iconNodes = renderPropNodes("icon", rawProps.icon, renderIconFallback);
|
|
753
|
+
const heroNodes = renderPropNodes("hero", rawProps.hero ?? rawProps.banner);
|
|
754
|
+
const eyebrowNodes = renderPropNodes("eyebrow", rawProps.eyebrow ?? rawProps.kicker);
|
|
755
|
+
const titleNodes = renderPropNodes("title", rawProps.title);
|
|
756
|
+
const subtitleNodes = renderPropNodes("subtitle", rawProps.subtitle ?? rawProps.description);
|
|
757
|
+
const headerNodes = renderPropNodes("header", rawProps.header);
|
|
758
|
+
const asideNodes = renderPropNodes("aside", rawProps.aside);
|
|
759
|
+
const bodyNodes = renderPropNodes("body", rawProps.body ?? rawProps.content);
|
|
760
|
+
const footerNodes = renderPropNodes("footer", rawProps.footer);
|
|
761
|
+
const actionsNodes = renderPropNodes("actions", rawProps.actions);
|
|
762
|
+
|
|
763
|
+
const generatedHero = heroNodes.length
|
|
764
|
+
? _.div({ class: uiClass(["jss-page-hero", rawProps.heroClass]) }, ...heroNodes)
|
|
765
|
+
: null;
|
|
766
|
+
|
|
767
|
+
const hasStructuredHeader = iconNodes.length || eyebrowNodes.length || titleNodes.length || subtitleNodes.length || headerNodes.length || asideNodes.length;
|
|
768
|
+
const generatedHeader = hasStructuredHeader
|
|
769
|
+
? _.div(
|
|
770
|
+
{ class: uiClass(["jss-page-header", rawProps.headerClass]) },
|
|
771
|
+
_.div(
|
|
772
|
+
{ class: "jss-page-head" },
|
|
773
|
+
iconNodes.length ? _.div({ class: uiClass(["jss-page-icon", rawProps.iconClass]) }, ...iconNodes) : null,
|
|
774
|
+
_.div(
|
|
775
|
+
{ class: "jss-page-head-main" },
|
|
776
|
+
eyebrowNodes.length ? _.div({ class: uiClass(["jss-page-eyebrow", rawProps.eyebrowClass]) }, ...eyebrowNodes) : null,
|
|
777
|
+
titleNodes.length ? _.div({ class: uiClass(["jss-page-title", rawProps.titleClass]) }, ...titleNodes) : null,
|
|
778
|
+
subtitleNodes.length ? _.div({ class: uiClass(["jss-page-subtitle", rawProps.subtitleClass]) }, ...subtitleNodes) : null,
|
|
779
|
+
headerNodes.length ? _.div({ class: uiClass(["jss-page-header-content", rawProps.headerContentClass]) }, ...headerNodes) : null
|
|
780
|
+
),
|
|
781
|
+
asideNodes.length ? _.div({ class: uiClass(["jss-page-aside", rawProps.asideClass]) }, ...asideNodes) : null
|
|
782
|
+
)
|
|
783
|
+
)
|
|
784
|
+
: null;
|
|
785
|
+
|
|
786
|
+
const mergedBodyNodes = [...bodyNodes, ...looseNodes];
|
|
787
|
+
const generatedBody = mergedBodyNodes.length
|
|
788
|
+
? _.div({ class: uiClass(["jss-page-body", rawProps.bodyClass]) }, ...mergedBodyNodes)
|
|
789
|
+
: null;
|
|
790
|
+
|
|
791
|
+
const mergedActionNodes = [...actionsNodes, ...sectionNodes.actions];
|
|
792
|
+
const generatedFooter = (footerNodes.length || mergedActionNodes.length)
|
|
793
|
+
? _.div(
|
|
794
|
+
{ class: uiClass(["jss-page-footer", rawProps.footerClass]) },
|
|
795
|
+
...footerNodes,
|
|
796
|
+
mergedActionNodes.length ? _.div({ class: "jss-page-actions" }, ...mergedActionNodes) : null
|
|
797
|
+
)
|
|
798
|
+
: null;
|
|
799
|
+
|
|
800
|
+
const hasHero = !!(heroNodes.length || sectionNodes.hero.length);
|
|
801
|
+
const hasHeader = !!(hasStructuredHeader || sectionNodes.header.length);
|
|
802
|
+
const p = JSswift.omit(props, [
|
|
803
|
+
"actions", "aside", "asideClass", "banner", "body", "bodyClass", "centered", "content",
|
|
804
|
+
"dense", "description", "eyebrow", "eyebrowClass", "flat", "footer", "footerClass",
|
|
805
|
+
"gap", "header", "headerClass", "headerContentClass", "headerGap", "hero", "heroClass",
|
|
806
|
+
"heroPadding", "icon", "iconClass", "iconSize", "kicker", "maxWidth", "minHeight",
|
|
807
|
+
"narrow", "padding", "size", "slots", "subtitle", "subtitleClass", "title", "titleClass"
|
|
808
|
+
]);
|
|
809
|
+
p.class = uiClass([
|
|
810
|
+
"jss-panel",
|
|
811
|
+
"jss-page",
|
|
812
|
+
uiWhen(rawProps.dense, "dense"),
|
|
813
|
+
uiWhen(rawProps.flat, "jss-page-flat"),
|
|
814
|
+
uiWhen(rawProps.centered, "jss-page-centered"),
|
|
815
|
+
uiWhen(rawProps.narrow, "jss-page-narrow"),
|
|
816
|
+
uiWhen(hasHero, "jss-page-has-hero"),
|
|
817
|
+
uiWhen(hasHeader, "jss-page-has-header"),
|
|
818
|
+
props.class
|
|
819
|
+
]);
|
|
820
|
+
p.style = { ...(props.style || {}) };
|
|
821
|
+
|
|
822
|
+
if (rawProps.gap != null || uiIsReactive(rawProps.gap)) {
|
|
823
|
+
p.style["--jss-page-gap"] = uiStyleValue(rawProps.gap, toCssSize);
|
|
824
|
+
}
|
|
825
|
+
if (rawProps.padding != null || uiIsReactive(rawProps.padding)) {
|
|
826
|
+
p.style["--jss-page-padding"] = uiStyleValue(rawProps.padding, toCssSize);
|
|
827
|
+
}
|
|
828
|
+
if (rawProps.maxWidth != null || uiIsReactive(rawProps.maxWidth)) {
|
|
829
|
+
p.style["--jss-page-max-width"] = uiStyleValue(rawProps.maxWidth, toCssSize);
|
|
830
|
+
}
|
|
831
|
+
if (rawProps.minHeight != null || uiIsReactive(rawProps.minHeight)) {
|
|
832
|
+
p.style["--jss-page-min-height"] = uiStyleValue(rawProps.minHeight, toCssSize);
|
|
833
|
+
}
|
|
834
|
+
if (rawProps.headerGap != null || uiIsReactive(rawProps.headerGap)) {
|
|
835
|
+
p.style["--jss-page-header-gap"] = uiStyleValue(rawProps.headerGap, toCssSize);
|
|
836
|
+
}
|
|
837
|
+
if (rawProps.heroPadding != null || uiIsReactive(rawProps.heroPadding)) {
|
|
838
|
+
p.style["--jss-page-hero-padding"] = uiStyleValue(rawProps.heroPadding, toCssSize);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
const el = _.div(
|
|
842
|
+
p,
|
|
843
|
+
generatedHero,
|
|
844
|
+
...sectionNodes.hero,
|
|
845
|
+
generatedHeader,
|
|
846
|
+
...sectionNodes.header,
|
|
847
|
+
generatedBody,
|
|
848
|
+
...sectionNodes.body,
|
|
849
|
+
generatedFooter,
|
|
850
|
+
...sectionNodes.footer
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
setPropertyProps(el, rawProps);
|
|
854
|
+
return el;
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
UI.AppShell = (...args) => {
|
|
859
|
+
const { props, children } = JSswift.uiNormalizeArgs(args);
|
|
860
|
+
const slots = props.slots || {};
|
|
861
|
+
const hasOwn = (obj, key) => !!obj && Object.prototype.hasOwnProperty.call(obj, key);
|
|
862
|
+
|
|
863
|
+
const noDrawer = uiUnwrap(props.noDrawer) === true || props.drawer === false;
|
|
864
|
+
const reverse = uiUnwrap(props.reverse) === true;
|
|
865
|
+
const stack = uiUnwrap(props.stack) === true;
|
|
866
|
+
const currentStateKey = props.drawerStateKey ?? props.stateKey ?? drawerStateKey;
|
|
867
|
+
|
|
868
|
+
if (currentStateKey) {
|
|
869
|
+
drawerStateKey = currentStateKey;
|
|
870
|
+
drawerOpen = readDrawerOpen(currentStateKey);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const shellCtx = {
|
|
874
|
+
props,
|
|
875
|
+
noDrawer,
|
|
876
|
+
stateKey: currentStateKey,
|
|
877
|
+
isDrawerOpen: () => readDrawerOpen(currentStateKey),
|
|
878
|
+
openDrawer: () => setDrawerOpen(true, currentStateKey),
|
|
879
|
+
closeDrawer: () => setDrawerOpen(false, currentStateKey),
|
|
880
|
+
toggleDrawer: () => setDrawerOpen(!readDrawerOpen(currentStateKey), currentStateKey)
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
const headerProps = (props.headerProps && typeof props.headerProps === "object") ? { ...props.headerProps } : {};
|
|
884
|
+
let headerFallback = props.header;
|
|
885
|
+
if (!hasOwn(props, "header") && (
|
|
886
|
+
Object.keys(headerProps).length ||
|
|
887
|
+
hasOwn(props, "title") ||
|
|
888
|
+
hasOwn(props, "subtitle") ||
|
|
889
|
+
hasOwn(props, "left") ||
|
|
890
|
+
hasOwn(props, "right")
|
|
891
|
+
)) {
|
|
892
|
+
if (!hasOwn(headerProps, "title") && hasOwn(props, "title")) headerProps.title = props.title;
|
|
893
|
+
if (!hasOwn(headerProps, "subtitle") && hasOwn(props, "subtitle")) headerProps.subtitle = props.subtitle;
|
|
894
|
+
if (!hasOwn(headerProps, "left") && hasOwn(props, "left")) headerProps.left = props.left;
|
|
895
|
+
if (!hasOwn(headerProps, "right") && hasOwn(props, "right")) headerProps.right = props.right;
|
|
896
|
+
if (!hasOwn(headerProps, "drawerStateKey")) headerProps.drawerStateKey = currentStateKey;
|
|
897
|
+
if (noDrawer && !hasOwn(headerProps, "left")) headerProps.left = false;
|
|
898
|
+
headerFallback = UI.Header(headerProps);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
const drawerProps = (props.drawerProps && typeof props.drawerProps === "object") ? { ...props.drawerProps } : {};
|
|
902
|
+
const drawerItems = hasOwn(props, "drawerItems") ? props.drawerItems : props.items;
|
|
903
|
+
const drawerHeader = hasOwn(props, "drawerHeader") ? props.drawerHeader : undefined;
|
|
904
|
+
let drawerFallback = props.drawer;
|
|
905
|
+
if (!hasOwn(props, "drawer") && !noDrawer && (
|
|
906
|
+
Object.keys(drawerProps).length ||
|
|
907
|
+
drawerItems != null ||
|
|
908
|
+
drawerHeader != null
|
|
909
|
+
)) {
|
|
910
|
+
if (!hasOwn(drawerProps, "items") && drawerItems != null) drawerProps.items = drawerItems;
|
|
911
|
+
if (!hasOwn(drawerProps, "header") && drawerHeader != null) drawerProps.header = drawerHeader;
|
|
912
|
+
if (!hasOwn(drawerProps, "stateKey")) drawerProps.stateKey = currentStateKey;
|
|
913
|
+
drawerFallback = UI.Drawer(drawerProps);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const pageProps = (props.pageProps && typeof props.pageProps === "object") ? { ...props.pageProps } : {};
|
|
917
|
+
const pageContentFallback = hasOwn(props, "content") ? props.content : children;
|
|
918
|
+
const defaultPageContent = renderSlotToArray(slots, "default", shellCtx, pageContentFallback);
|
|
919
|
+
let pageFallback = props.page;
|
|
920
|
+
if (!hasOwn(props, "page") && (Object.keys(pageProps).length || defaultPageContent.length)) {
|
|
921
|
+
pageFallback = UI.Page(pageProps, ...defaultPageContent);
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const footerProps = (props.footerProps && typeof props.footerProps === "object") ? { ...props.footerProps } : {};
|
|
925
|
+
const footerContent = hasOwn(props, "footerContent") ? props.footerContent : undefined;
|
|
926
|
+
let footerFallback = props.footer;
|
|
927
|
+
if (!hasOwn(props, "footer") && (Object.keys(footerProps).length || footerContent != null)) {
|
|
928
|
+
footerFallback = UI.Footer(footerProps, ...renderSlotToArray(null, "default", shellCtx, footerContent));
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const headerNodes = renderSlotToArray(slots, "header", shellCtx, headerFallback);
|
|
932
|
+
const drawerNodes = noDrawer ? [] : renderSlotToArray(slots, "drawer", shellCtx, drawerFallback);
|
|
933
|
+
const pageNodes = renderSlotToArray(slots, "page", shellCtx, pageFallback);
|
|
934
|
+
const footerNodes = renderSlotToArray(slots, "footer", shellCtx, footerFallback);
|
|
935
|
+
|
|
936
|
+
const cls = uiClass([
|
|
937
|
+
"jss-app",
|
|
938
|
+
"jss-app-shell",
|
|
939
|
+
uiWhen(noDrawer, "no-drawer"),
|
|
940
|
+
uiWhen(reverse, "is-reverse"),
|
|
941
|
+
uiWhen(stack, "is-stack"),
|
|
942
|
+
uiWhen(props.flush, "is-flush"),
|
|
943
|
+
uiWhen(props.divider, "is-divider"),
|
|
944
|
+
props.class
|
|
945
|
+
]);
|
|
946
|
+
|
|
947
|
+
const p = JSswift.omit(props, [
|
|
948
|
+
"header", "drawer", "page", "footer", "content",
|
|
949
|
+
"title", "subtitle", "left", "right",
|
|
950
|
+
"items", "drawerItems", "drawerHeader",
|
|
951
|
+
"headerProps", "drawerProps", "pageProps", "footerProps",
|
|
952
|
+
"footerContent",
|
|
953
|
+
"noDrawer", "reverse", "stack", "flush", "divider",
|
|
954
|
+
"drawerStateKey", "stateKey",
|
|
955
|
+
"drawerWidth", "gap", "padding",
|
|
956
|
+
"slots"
|
|
957
|
+
]);
|
|
958
|
+
p.class = cls;
|
|
959
|
+
p.style = { ...(props.style || {}) };
|
|
960
|
+
|
|
961
|
+
const drawerWidth = uiStyleValue(props.drawerWidth, toCssSize);
|
|
962
|
+
if (drawerWidth != null) p.style["--jss-app-shell-drawer-width"] = drawerWidth;
|
|
963
|
+
const gap = uiStyleValue(props.gap, toCssSize);
|
|
964
|
+
if (gap != null) p.style["--jss-app-shell-gap"] = gap;
|
|
965
|
+
const padding = uiStyleValue(props.padding, toCssSize);
|
|
966
|
+
if (padding != null) p.style["--jss-app-shell-padding"] = padding;
|
|
967
|
+
|
|
968
|
+
const headerWrap = headerNodes.length
|
|
969
|
+
? _.div({ class: "jss-app-shell-header-slot" }, ...headerNodes)
|
|
970
|
+
: null;
|
|
971
|
+
const drawerWrap = drawerNodes.length
|
|
972
|
+
? _.div({ class: "jss-app-shell-drawer-slot" }, ...drawerNodes)
|
|
973
|
+
: null;
|
|
974
|
+
const pageWrap = pageNodes.length
|
|
975
|
+
? _.div({ class: "jss-app-shell-page-slot" }, ...pageNodes)
|
|
976
|
+
: null;
|
|
977
|
+
const footerWrap = footerNodes.length
|
|
978
|
+
? _.div({ class: "jss-app-shell-footer-slot" }, ...footerNodes)
|
|
979
|
+
: null;
|
|
980
|
+
|
|
981
|
+
const bodyNodes = reverse
|
|
982
|
+
? [pageWrap, drawerWrap]
|
|
983
|
+
: [drawerWrap, pageWrap];
|
|
984
|
+
|
|
985
|
+
const root = _.div(
|
|
986
|
+
p,
|
|
987
|
+
...(headerWrap ? [headerWrap] : []),
|
|
988
|
+
_.div({ class: "jss-app-shell-body" }, ...bodyNodes.filter(Boolean)),
|
|
989
|
+
...(footerWrap ? [footerWrap] : [])
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
root.openDrawer = shellCtx.openDrawer;
|
|
993
|
+
root.closeDrawer = shellCtx.closeDrawer;
|
|
994
|
+
root.toggleDrawer = shellCtx.toggleDrawer;
|
|
995
|
+
root.isDrawerOpen = shellCtx.isDrawerOpen;
|
|
996
|
+
root.header = headerWrap;
|
|
997
|
+
root.drawer = drawerWrap;
|
|
998
|
+
root.page = pageWrap;
|
|
999
|
+
root.footer = footerWrap;
|
|
1000
|
+
|
|
1001
|
+
setPropertyProps(root, props);
|
|
1002
|
+
return root;
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
UI.Parallax = function Parallax(...args) {
|
|
1007
|
+
const { props: rawProps, children } = JSswift.uiNormalizeArgs(args);
|
|
1008
|
+
const slots = rawProps.slots || {};
|
|
1009
|
+
const props = { ...rawProps };
|
|
1010
|
+
|
|
1011
|
+
if (props.color != null && props.textColor == null) props.textColor = props.color;
|
|
1012
|
+
delete props.color;
|
|
1013
|
+
applyCommonProps(props);
|
|
1014
|
+
|
|
1015
|
+
const stateClass = uiComputed(rawProps.state, () => {
|
|
1016
|
+
const state = normalizeState(uiUnwrap(rawProps.state));
|
|
1017
|
+
return state ? `jss-state-${state}` : "";
|
|
1018
|
+
});
|
|
1019
|
+
const mapColorValue = (value) => {
|
|
1020
|
+
if (value == null || value === false || value === "") return "";
|
|
1021
|
+
const text = String(value);
|
|
1022
|
+
return isTokenCSS(text) ? `var(--jss-${text})` : text;
|
|
1023
|
+
};
|
|
1024
|
+
const getBackgroundImage = () => {
|
|
1025
|
+
const background = uiUnwrap(rawProps.background);
|
|
1026
|
+
if (background) return String(background);
|
|
1027
|
+
const source = uiUnwrap(rawProps.image) || uiUnwrap(rawProps.src) || "";
|
|
1028
|
+
if (!source) return "linear-gradient(120deg, #1b2c5a, #2f6d8f, #2a8f5c)";
|
|
1029
|
+
const text = String(source);
|
|
1030
|
+
if (/^url\(/i.test(text) || /gradient\(/i.test(text) || /^var\(/i.test(text)) return text;
|
|
1031
|
+
return `url(${text})`;
|
|
1032
|
+
};
|
|
1033
|
+
const getNumericValue = (value, fallback) => {
|
|
1034
|
+
const num = Number(uiUnwrap(value));
|
|
1035
|
+
return Number.isFinite(num) ? num : fallback;
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
const ctx = {
|
|
1039
|
+
speed: () => uiUnwrap(rawProps.speed) ?? 0.18,
|
|
1040
|
+
state: () => uiUnwrap(rawProps.state) || "",
|
|
1041
|
+
disabled: () => !!uiUnwrap(rawProps.disabled)
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
const badgeNodes = renderSlotToArray(slots, "badge", ctx, rawProps.badge);
|
|
1045
|
+
const backgroundNodes = renderSlotToArray(slots, "background", ctx, rawProps.backgroundContent);
|
|
1046
|
+
const eyebrowNodes = renderSlotToArray(slots, "eyebrow", ctx, rawProps.eyebrow ?? rawProps.kicker);
|
|
1047
|
+
const titleNodes = renderSlotToArray(slots, "title", ctx, rawProps.title);
|
|
1048
|
+
const subtitleNodes = renderSlotToArray(slots, "subtitle", ctx, rawProps.subtitle);
|
|
1049
|
+
const headerNodes = renderSlotToArray(slots, "header", ctx, rawProps.header);
|
|
1050
|
+
const asideNodes = renderSlotToArray(slots, "aside", ctx, rawProps.aside);
|
|
1051
|
+
const mediaNodes = renderSlotToArray(slots, "media", ctx, rawProps.media);
|
|
1052
|
+
const contentNodes = renderSlotToArray(slots, "content", ctx, rawProps.content ?? rawProps.body);
|
|
1053
|
+
const defaultNodes = renderSlotToArray(slots, "default", ctx, children?.length ? children : []);
|
|
1054
|
+
const footerNodes = renderSlotToArray(slots, "footer", ctx, rawProps.footer);
|
|
1055
|
+
const actionsNodes = renderSlotToArray(slots, "actions", ctx, rawProps.actions);
|
|
1056
|
+
const mergedBodyNodes = [...contentNodes, ...defaultNodes];
|
|
1057
|
+
|
|
1058
|
+
const generatedBadge = badgeNodes.length
|
|
1059
|
+
? _.div({ class: uiClass(["jss-parallax-badge", rawProps.badgeClass]) }, ...badgeNodes)
|
|
1060
|
+
: null;
|
|
1061
|
+
const hasStructuredHeader = eyebrowNodes.length || titleNodes.length || subtitleNodes.length || headerNodes.length || asideNodes.length;
|
|
1062
|
+
const generatedHeader = hasStructuredHeader
|
|
1063
|
+
? _.div(
|
|
1064
|
+
{ class: uiClass(["jss-parallax-header", rawProps.headerClass]) },
|
|
1065
|
+
_.div(
|
|
1066
|
+
{ class: "jss-parallax-head" },
|
|
1067
|
+
_.div(
|
|
1068
|
+
{ class: "jss-parallax-head-main" },
|
|
1069
|
+
eyebrowNodes.length ? _.div({ class: uiClass(["jss-parallax-eyebrow", rawProps.eyebrowClass]) }, ...eyebrowNodes) : null,
|
|
1070
|
+
titleNodes.length ? _.div({ class: uiClass(["jss-parallax-title", rawProps.titleClass]) }, ...titleNodes) : null,
|
|
1071
|
+
subtitleNodes.length ? _.div({ class: uiClass(["jss-parallax-subtitle", rawProps.subtitleClass]) }, ...subtitleNodes) : null,
|
|
1072
|
+
headerNodes.length ? _.div({ class: uiClass(["jss-parallax-header-content", rawProps.headerContentClass]) }, ...headerNodes) : null
|
|
1073
|
+
),
|
|
1074
|
+
asideNodes.length ? _.div({ class: uiClass(["jss-parallax-aside", rawProps.asideClass]) }, ...asideNodes) : null
|
|
1075
|
+
)
|
|
1076
|
+
)
|
|
1077
|
+
: null;
|
|
1078
|
+
const generatedMedia = mediaNodes.length
|
|
1079
|
+
? _.div({ class: uiClass(["jss-parallax-media", rawProps.mediaClass]) }, ...mediaNodes)
|
|
1080
|
+
: null;
|
|
1081
|
+
const generatedBody = mergedBodyNodes.length
|
|
1082
|
+
? _.div({ class: uiClass(["jss-parallax-body", rawProps.bodyClass]) }, ...mergedBodyNodes)
|
|
1083
|
+
: null;
|
|
1084
|
+
const generatedFooter = (footerNodes.length || actionsNodes.length)
|
|
1085
|
+
? _.div(
|
|
1086
|
+
{ class: uiClass(["jss-parallax-footer", rawProps.footerClass]) },
|
|
1087
|
+
footerNodes.length ? _.div({ class: "jss-parallax-footer-content" }, ...footerNodes) : null,
|
|
1088
|
+
actionsNodes.length ? _.div({ class: "jss-parallax-actions" }, ...actionsNodes) : null
|
|
1089
|
+
)
|
|
1090
|
+
: null;
|
|
1091
|
+
|
|
1092
|
+
const wrapProps = JSswift.omit(props, [
|
|
1093
|
+
"actions", "align", "aside", "asideClass", "background", "backgroundContent", "backgroundContentClass",
|
|
1094
|
+
"badge", "badgeClass", "bgClass", "bgPosition", "bgRepeat", "bgSize", "body", "bodyClass", "color",
|
|
1095
|
+
"content", "contentClass", "contentMaxWidth", "disabled", "eyebrow", "eyebrowClass", "footer",
|
|
1096
|
+
"footerClass", "gap", "header", "headerClass", "headerContentClass", "height", "image", "imageAlt",
|
|
1097
|
+
"imageClass", "innerClass", "justify", "kicker", "maxOffset", "media", "mediaClass", "minHeight",
|
|
1098
|
+
"overlay", "padding", "slots", "speed", "src", "startTop", "state", "subtitle", "subtitleClass",
|
|
1099
|
+
"textColor", "title", "titleClass"
|
|
1100
|
+
]);
|
|
1101
|
+
wrapProps.class = uiClass([
|
|
1102
|
+
"jss-parallax",
|
|
1103
|
+
"jss-singularity",
|
|
1104
|
+
stateClass,
|
|
1105
|
+
uiWhen(rawProps.disabled, "jss-parallax-static"),
|
|
1106
|
+
uiWhen(generatedBadge, "jss-parallax-has-badge"),
|
|
1107
|
+
uiWhen(hasStructuredHeader, "jss-parallax-has-header"),
|
|
1108
|
+
props.class
|
|
1109
|
+
]);
|
|
1110
|
+
wrapProps.style = { ...(props.style || {}) };
|
|
1111
|
+
if (rawProps.height != null) wrapProps.style["--jss-parallax-height"] = uiStyleValue(rawProps.height, toCssSize);
|
|
1112
|
+
if (rawProps.minHeight != null) wrapProps.style["--jss-parallax-min-height"] = uiStyleValue(rawProps.minHeight, toCssSize);
|
|
1113
|
+
if (rawProps.padding != null) wrapProps.style["--jss-parallax-padding"] = uiStyleValue(rawProps.padding, toCssSize);
|
|
1114
|
+
if (rawProps.gap != null) wrapProps.style["--jss-parallax-gap"] = uiStyleValue(rawProps.gap, toCssSize);
|
|
1115
|
+
if (rawProps.contentMaxWidth != null) wrapProps.style["--jss-parallax-content-max-width"] = uiStyleValue(rawProps.contentMaxWidth, toCssSize);
|
|
1116
|
+
if (rawProps.justify != null) wrapProps.style["--jss-parallax-justify"] = uiStyleValue(rawProps.justify);
|
|
1117
|
+
if (rawProps.align != null) wrapProps.style["--jss-parallax-align"] = uiStyleValue(rawProps.align);
|
|
1118
|
+
if (rawProps.color != null) wrapProps.style["--jss-parallax-color"] = uiStyleValue(rawProps.color, mapColorValue);
|
|
1119
|
+
if (rawProps.overlay != null) wrapProps.style["--jss-parallax-overlay"] = uiStyleValue(rawProps.overlay);
|
|
1120
|
+
if (rawProps.bgPosition != null) wrapProps.style["--jss-parallax-position"] = uiStyleValue(rawProps.bgPosition);
|
|
1121
|
+
if (rawProps.bgSize != null) wrapProps.style["--jss-parallax-size"] = uiStyleValue(rawProps.bgSize);
|
|
1122
|
+
if (rawProps.bgRepeat != null) wrapProps.style["--jss-parallax-repeat"] = uiStyleValue(rawProps.bgRepeat);
|
|
1123
|
+
wrapProps.style["--jss-parallax-image"] = (uiIsReactive(rawProps.background) || uiIsReactive(rawProps.image) || uiIsReactive(rawProps.src))
|
|
1124
|
+
? () => getBackgroundImage()
|
|
1125
|
+
: getBackgroundImage();
|
|
1126
|
+
|
|
1127
|
+
const bg = _.div(
|
|
1128
|
+
{ class: uiClass(["jss-parallax-bg", rawProps.bgClass]) },
|
|
1129
|
+
backgroundNodes.length
|
|
1130
|
+
? _.div({ class: uiClass(["jss-parallax-bg-content", rawProps.backgroundContentClass]) }, ...backgroundNodes)
|
|
1131
|
+
: null
|
|
1132
|
+
);
|
|
1133
|
+
const content = _.div(
|
|
1134
|
+
{ class: uiClass(["jss-parallax-content", rawProps.contentClass, rawProps.innerClass]) },
|
|
1135
|
+
generatedBadge,
|
|
1136
|
+
generatedHeader,
|
|
1137
|
+
generatedMedia,
|
|
1138
|
+
generatedBody,
|
|
1139
|
+
generatedFooter
|
|
1140
|
+
);
|
|
1141
|
+
|
|
1142
|
+
const wrap = _.div(wrapProps, bg, content);
|
|
1143
|
+
|
|
1144
|
+
let disposed = false;
|
|
1145
|
+
let ticking = false;
|
|
1146
|
+
let resizeObserver = null;
|
|
1147
|
+
|
|
1148
|
+
const cleanup = () => {
|
|
1149
|
+
if (disposed) return;
|
|
1150
|
+
disposed = true;
|
|
1151
|
+
if (typeof window !== "undefined") {
|
|
1152
|
+
window.removeEventListener("scroll", scheduleUpdate);
|
|
1153
|
+
window.removeEventListener("resize", scheduleUpdate);
|
|
1154
|
+
}
|
|
1155
|
+
resizeObserver?.disconnect?.();
|
|
1156
|
+
resizeObserver = null;
|
|
1157
|
+
};
|
|
1158
|
+
|
|
1159
|
+
const update = () => {
|
|
1160
|
+
if (disposed) return;
|
|
1161
|
+
if (!wrap.isConnected) {
|
|
1162
|
+
cleanup();
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
if (uiUnwrap(rawProps.disabled)) {
|
|
1166
|
+
bg.style.transform = "translate3d(0, 0, 0)";
|
|
1167
|
+
wrap.style.setProperty("--jss-parallax-offset", "0px");
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
const rect = wrap.getBoundingClientRect();
|
|
1171
|
+
const speed = getNumericValue(rawProps.speed, 0.18);
|
|
1172
|
+
const maxOffset = Math.abs(getNumericValue(rawProps.maxOffset, 96));
|
|
1173
|
+
const explicitStartTop = uiUnwrap(rawProps.startTop);
|
|
1174
|
+
const rawOffset = explicitStartTop != null && explicitStartTop !== ""
|
|
1175
|
+
? (rect.top - getNumericValue(rawProps.startTop, 0)) * speed
|
|
1176
|
+
: (((typeof window !== "undefined" ? window.innerHeight || document.documentElement.clientHeight || 0 : 0) / 2) - (rect.top + (rect.height / 2))) * speed;
|
|
1177
|
+
const offset = maxOffset > 0 ? Math.max(-maxOffset, Math.min(maxOffset, rawOffset)) : rawOffset;
|
|
1178
|
+
const cssOffset = `${offset.toFixed(2)}px`;
|
|
1179
|
+
bg.style.transform = `translate3d(0, ${cssOffset}, 0)`;
|
|
1180
|
+
wrap.style.setProperty("--jss-parallax-offset", cssOffset);
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
function scheduleUpdate() {
|
|
1184
|
+
if (disposed || ticking) return;
|
|
1185
|
+
ticking = true;
|
|
1186
|
+
requestAnimationFrame(() => {
|
|
1187
|
+
ticking = false;
|
|
1188
|
+
update();
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
if (typeof window !== "undefined") {
|
|
1193
|
+
window.addEventListener("scroll", scheduleUpdate, { passive: true });
|
|
1194
|
+
window.addEventListener("resize", scheduleUpdate);
|
|
1195
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1196
|
+
resizeObserver = new ResizeObserver(() => { scheduleUpdate(); });
|
|
1197
|
+
resizeObserver.observe(wrap);
|
|
1198
|
+
}
|
|
1199
|
+
requestAnimationFrame(() => { scheduleUpdate(); });
|
|
1200
|
+
setTimeout(() => { scheduleUpdate(); }, 90);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
wrap.refresh = () => {
|
|
1204
|
+
scheduleUpdate();
|
|
1205
|
+
return wrap;
|
|
1206
|
+
};
|
|
1207
|
+
wrap.update = wrap.refresh;
|
|
1208
|
+
wrap.destroy = () => {
|
|
1209
|
+
cleanup();
|
|
1210
|
+
wrap.remove();
|
|
1211
|
+
return null;
|
|
1212
|
+
};
|
|
1213
|
+
wrap._dispose = cleanup;
|
|
1214
|
+
|
|
1215
|
+
setPropertyProps(wrap, rawProps);
|
|
1216
|
+
return wrap;
|
|
1217
|
+
};
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
// Example:
|
|
1221
|
+
// _.Parallax({ src: "/assets/hero.jpg", height: "280px", speed: 0.2 }, _.h2("Hello"));
|
|
1222
|
+
|
|
1223
|
+
// -------------------------------
|