jsswift 2.0.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI.md +30 -3
- package/README.md +2 -0
- package/dist/build/build-configured-runtime.d.mts +29 -0
- package/dist/build/build-configured-runtime.mjs +92 -0
- package/dist/build/runtime-layout.mjs +13 -0
- package/dist/build/select-ui.mjs +167 -0
- package/dist/build/vite-jss.d.mts +2 -0
- package/dist/build/vite-jss.mjs +73 -0
- package/dist/cms.js +3522 -0
- package/dist/css/min-ui.css +1 -1
- package/dist/css/ui-components.css +13 -0
- package/dist/css/ui-light.css +13 -0
- package/dist/css/ui-light.min.css +1 -1
- package/dist/css/ui.css +13 -0
- package/dist/css/ui.min.css +1 -1
- package/dist/documentions/AI.md +30 -3
- package/dist/documentions/README.md +1 -0
- package/dist/documentions/components/table.md +3 -0
- package/dist/documentions/configured-runtime.md +82 -0
- package/dist/documentions/examples/crud.md +9 -5
- package/dist/documentions/knowledge-map.json +20 -1
- package/dist/jsswift.js +2 -2
- package/dist/jsswift.min.js +1 -1
- package/dist/min-jsswift.js +1 -1
- package/dist/ui-src/00-bootstrap.js +330 -0
- package/dist/ui-src/01-foundation-helpers.js +809 -0
- package/dist/ui-src/10-primitives-layout.js +5091 -0
- package/dist/ui-src/20-display-content.js +780 -0
- package/dist/ui-src/21-list-content.js +246 -0
- package/dist/ui-src/22-banner-content.js +376 -0
- package/dist/ui-src/23-tooltip.js +276 -0
- package/dist/ui-src/31-form-advanced.js +2784 -0
- package/dist/ui-src/40-navigation.js +1262 -0
- package/dist/ui-src/41-tab-panel.js +896 -0
- package/dist/ui-src/50-feedback.js +999 -0
- package/dist/ui-src/51-feedback-service.js +166 -0
- package/dist/ui-src/60-shell-app.js +1223 -0
- package/dist/ui-src/61-form-service.js +368 -0
- package/dist/ui-src/70-dialog.js +333 -0
- package/dist/ui-src/71-menu-overlays.js +1217 -0
- package/dist/ui-src/80-data.js +437 -0
- package/dist/ui-src/modules.json +212 -0
- package/dist/ui.js +12565 -0
- package/package.json +26 -2
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
UI.Dialog = (...args) => {
|
|
2
|
+
const { props, children } = JSswift.uiNormalizeArgs(args);
|
|
3
|
+
const slots = props.slots || {};
|
|
4
|
+
const stateList = ["primary", "secondary", "warning", "danger", "success", "info", "light", "dark"];
|
|
5
|
+
const sizeList = ["xs", "sm", "md", "lg", "xl", "full"];
|
|
6
|
+
let currentProps = { ...props };
|
|
7
|
+
let entry = null;
|
|
8
|
+
let lastActive = null;
|
|
9
|
+
const resolveRender = (value, ctx) => typeof value === "function" ? value(ctx) : value;
|
|
10
|
+
const splitClasses = (value) => String(value || "").split(/\s+/).filter(Boolean);
|
|
11
|
+
const setTrackedClasses = (target, key, classes) => {
|
|
12
|
+
if (!target) return;
|
|
13
|
+
const prev = target[key] || [];
|
|
14
|
+
if (prev.length) target.classList.remove(...prev);
|
|
15
|
+
const next = (classes || []).filter(Boolean);
|
|
16
|
+
if (next.length) target.classList.add(...next);
|
|
17
|
+
target[key] = next;
|
|
18
|
+
};
|
|
19
|
+
const setStyleValue = (target, name, value, formatter = (v) => v) => {
|
|
20
|
+
if (!target) return;
|
|
21
|
+
if (value == null || value === "") {
|
|
22
|
+
target.style.removeProperty(name);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
target.style.setProperty(name, formatter(value));
|
|
26
|
+
};
|
|
27
|
+
const fullscreenViewportSize = () => {
|
|
28
|
+
const vv = window.visualViewport;
|
|
29
|
+
const left = Math.max(0, Math.round(vv?.offsetLeft ?? 0));
|
|
30
|
+
const top = Math.max(0, Math.round(vv?.offsetTop ?? 0));
|
|
31
|
+
const width = Math.max(0, Math.round(vv?.width ?? window.innerWidth ?? 0));
|
|
32
|
+
const height = Math.max(0, Math.round(vv?.height ?? window.innerHeight ?? 0));
|
|
33
|
+
return { left, top, width, height };
|
|
34
|
+
};
|
|
35
|
+
const syncFullscreenViewport = (currentEntry) => {
|
|
36
|
+
if (!currentEntry?.panel) return;
|
|
37
|
+
const { left, top, width, height } = fullscreenViewportSize();
|
|
38
|
+
setStyleValue(currentEntry.panel, "position", "fixed");
|
|
39
|
+
setStyleValue(currentEntry.panel, "inset", 0, (v) => `${v}px`);
|
|
40
|
+
setStyleValue(currentEntry.panel, "top", top, (v) => `${v}px`);
|
|
41
|
+
setStyleValue(currentEntry.panel, "left", left, (v) => `${v}px`);
|
|
42
|
+
setStyleValue(currentEntry.panel, "right", "auto");
|
|
43
|
+
setStyleValue(currentEntry.panel, "bottom", "auto");
|
|
44
|
+
setStyleValue(currentEntry.panel, "width", width, (v) => `${v}px`);
|
|
45
|
+
setStyleValue(currentEntry.panel, "height", height, (v) => `${v}px`);
|
|
46
|
+
setStyleValue(currentEntry.panel, "min-height", height, (v) => `${v}px`);
|
|
47
|
+
setStyleValue(currentEntry.panel, "max-width", width, (v) => `${v}px`);
|
|
48
|
+
setStyleValue(currentEntry.panel, "max-height", height, (v) => `${v}px`);
|
|
49
|
+
setStyleValue(currentEntry.panel, "min-width", 0, (v) => `${v}px`);
|
|
50
|
+
setStyleValue(currentEntry.panel, "margin", 0, (v) => `${v}px`);
|
|
51
|
+
setStyleValue(currentEntry.panel, "box-sizing", "border-box");
|
|
52
|
+
setStyleValue(currentEntry.panel, "border-width", 0, (v) => `${v}px`);
|
|
53
|
+
setStyleValue(currentEntry.panel, "border-radius", 0, (v) => `${v}px`);
|
|
54
|
+
setStyleValue(currentEntry.panel, "transform", "none");
|
|
55
|
+
setStyleValue(currentEntry.panel, "overflow", "hidden");
|
|
56
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-left", left, (v) => `${v}px`);
|
|
57
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-top", top, (v) => `${v}px`);
|
|
58
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-width", width, (v) => `${v}px`);
|
|
59
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-height", height, (v) => `${v}px`);
|
|
60
|
+
};
|
|
61
|
+
const clearFullscreenViewport = (currentEntry) => {
|
|
62
|
+
if (!currentEntry?.panel) return;
|
|
63
|
+
setStyleValue(currentEntry.panel, "position", null);
|
|
64
|
+
setStyleValue(currentEntry.panel, "inset", null);
|
|
65
|
+
setStyleValue(currentEntry.panel, "top", null);
|
|
66
|
+
setStyleValue(currentEntry.panel, "left", null);
|
|
67
|
+
setStyleValue(currentEntry.panel, "right", null);
|
|
68
|
+
setStyleValue(currentEntry.panel, "bottom", null);
|
|
69
|
+
setStyleValue(currentEntry.panel, "width", null);
|
|
70
|
+
setStyleValue(currentEntry.panel, "height", null);
|
|
71
|
+
setStyleValue(currentEntry.panel, "min-height", null);
|
|
72
|
+
setStyleValue(currentEntry.panel, "max-width", null);
|
|
73
|
+
setStyleValue(currentEntry.panel, "max-height", null);
|
|
74
|
+
setStyleValue(currentEntry.panel, "min-width", null);
|
|
75
|
+
setStyleValue(currentEntry.panel, "margin", null);
|
|
76
|
+
setStyleValue(currentEntry.panel, "box-sizing", null);
|
|
77
|
+
setStyleValue(currentEntry.panel, "border-width", null);
|
|
78
|
+
setStyleValue(currentEntry.panel, "border-radius", null);
|
|
79
|
+
setStyleValue(currentEntry.panel, "transform", null);
|
|
80
|
+
setStyleValue(currentEntry.panel, "overflow", null);
|
|
81
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-left", null);
|
|
82
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-top", null);
|
|
83
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-width", null);
|
|
84
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-fullscreen-height", null);
|
|
85
|
+
};
|
|
86
|
+
const ensureFullscreenViewportTracking = (currentEntry, enabled) => {
|
|
87
|
+
if (!currentEntry) return;
|
|
88
|
+
currentEntry._dialogViewportCleanup?.();
|
|
89
|
+
currentEntry._dialogViewportCleanup = null;
|
|
90
|
+
if (!enabled) {
|
|
91
|
+
clearFullscreenViewport(currentEntry);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
let frameId = null;
|
|
95
|
+
const raf = globalThis.requestAnimationFrame || ((fn) => setTimeout(() => fn(Date.now()), 0));
|
|
96
|
+
const caf = globalThis.cancelAnimationFrame || clearTimeout;
|
|
97
|
+
const sync = () => syncFullscreenViewport(currentEntry);
|
|
98
|
+
const scheduleSync = () => {
|
|
99
|
+
if (frameId != null) caf(frameId);
|
|
100
|
+
frameId = raf(() => {
|
|
101
|
+
frameId = null;
|
|
102
|
+
sync();
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
sync();
|
|
106
|
+
scheduleSync();
|
|
107
|
+
window.addEventListener("resize", sync);
|
|
108
|
+
window.addEventListener("orientationchange", scheduleSync);
|
|
109
|
+
window.visualViewport?.addEventListener?.("resize", sync);
|
|
110
|
+
window.visualViewport?.addEventListener?.("scroll", scheduleSync);
|
|
111
|
+
currentEntry._dialogViewportCleanup = () => {
|
|
112
|
+
if (frameId != null) {
|
|
113
|
+
caf(frameId);
|
|
114
|
+
frameId = null;
|
|
115
|
+
}
|
|
116
|
+
window.removeEventListener("resize", sync);
|
|
117
|
+
window.removeEventListener("orientationchange", scheduleSync);
|
|
118
|
+
window.visualViewport?.removeEventListener?.("resize", sync);
|
|
119
|
+
window.visualViewport?.removeEventListener?.("scroll", scheduleSync);
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
const getOptions = () => currentProps;
|
|
123
|
+
const getStateClass = (opts) => {
|
|
124
|
+
const value = uiUnwrap(opts.state ?? opts.color);
|
|
125
|
+
if (!value) return "";
|
|
126
|
+
return stateList.includes(value) ? value : String(value);
|
|
127
|
+
};
|
|
128
|
+
const getSizeClass = (opts) => {
|
|
129
|
+
const value = uiUnwrap(opts.size);
|
|
130
|
+
return (typeof value === "string" && sizeList.includes(value)) ? value : "";
|
|
131
|
+
};
|
|
132
|
+
const getAlignClass = (opts) => {
|
|
133
|
+
const raw = String(uiUnwrap(opts.actionsAlign ?? opts.footerAlign ?? opts.alignActions ?? "end")).toLowerCase();
|
|
134
|
+
if (["start", "left"].includes(raw)) return "start";
|
|
135
|
+
if (["center", "middle"].includes(raw)) return "center";
|
|
136
|
+
if (["between", "space-between"].includes(raw)) return "between";
|
|
137
|
+
if (["stretch", "full"].includes(raw)) return "stretch";
|
|
138
|
+
return "end";
|
|
139
|
+
};
|
|
140
|
+
const getVerticalAlignClass = (opts) => {
|
|
141
|
+
const raw = String(uiUnwrap(opts.align ?? opts.verticalAlign ?? opts.position ?? "center")).toLowerCase();
|
|
142
|
+
if (["top", "start", "flex-start"].includes(raw)) return "jss-dialog-align-top";
|
|
143
|
+
if (["bottom", "end", "flex-end"].includes(raw)) return "jss-dialog-align-bottom";
|
|
144
|
+
return "";
|
|
145
|
+
};
|
|
146
|
+
const isClosable = (opts) => {
|
|
147
|
+
const value = opts.closable ?? opts.dismissible ?? opts.closeButton;
|
|
148
|
+
return value !== false;
|
|
149
|
+
};
|
|
150
|
+
const buildContent = () => {
|
|
151
|
+
const opts = getOptions();
|
|
152
|
+
const ctx = {
|
|
153
|
+
close,
|
|
154
|
+
dismiss: close,
|
|
155
|
+
open,
|
|
156
|
+
toggle,
|
|
157
|
+
update,
|
|
158
|
+
isOpen,
|
|
159
|
+
entry: () => entry,
|
|
160
|
+
props: opts
|
|
161
|
+
};
|
|
162
|
+
const iconFallback = opts.icon != null
|
|
163
|
+
? (typeof opts.icon === "string"
|
|
164
|
+
? UI.Icon({ name: opts.icon, size: opts.iconSize || "md" })
|
|
165
|
+
: JSswift.ui.slot(opts.icon, { as: "icon" }))
|
|
166
|
+
: null;
|
|
167
|
+
const eyebrowNodes = renderSlotToArray(slots, "eyebrow", ctx, resolveRender(opts.eyebrow, ctx));
|
|
168
|
+
const titleNodes = renderSlotToArray(slots, "title", ctx, resolveRender(opts.title ?? opts.heading ?? opts.header, ctx));
|
|
169
|
+
const subtitleNodes = renderSlotToArray(slots, "subtitle", ctx, resolveRender(opts.subtitle ?? opts.description, ctx));
|
|
170
|
+
const iconNodes = renderSlotToArray(slots, "icon", ctx, iconFallback);
|
|
171
|
+
const customHeaderNodes = renderSlotToArray(slots, "header", ctx, resolveRender(opts.headerContent ?? opts.head, ctx));
|
|
172
|
+
const closeSlotNodes = isClosable(opts)
|
|
173
|
+
? renderSlotToArray(slots, "close", ctx, UI.Btn({
|
|
174
|
+
class: "jss-dialog-close",
|
|
175
|
+
size: "sm",
|
|
176
|
+
outline: true,
|
|
177
|
+
"aria-label": opts.closeLabel || "Chiudi dialog",
|
|
178
|
+
"data-dialog-close": true
|
|
179
|
+
}, UI.Icon({ name: opts.closeIcon || "close", size: "sm" })))
|
|
180
|
+
: [];
|
|
181
|
+
const bodyRaw = opts.content ?? opts.body ?? opts.message ?? (children && children.length ? children : null);
|
|
182
|
+
let contentNodes = renderSlotToArray(slots, "content", ctx, resolveRender(bodyRaw, ctx));
|
|
183
|
+
if (!contentNodes.length) contentNodes = renderSlotToArray(slots, "body", ctx, resolveRender(bodyRaw, ctx));
|
|
184
|
+
if (!contentNodes.length) contentNodes = renderSlotToArray(slots, "default", ctx, resolveRender(bodyRaw, ctx));
|
|
185
|
+
const footerRaw = resolveRender(opts.footer ?? opts.actions, ctx);
|
|
186
|
+
let footerNodes = renderSlotToArray(slots, "footer", ctx, footerRaw);
|
|
187
|
+
if (!footerNodes.length) footerNodes = renderSlotToArray(slots, "actions", ctx, footerRaw);
|
|
188
|
+
|
|
189
|
+
let headerEl = null;
|
|
190
|
+
if (customHeaderNodes.length) {
|
|
191
|
+
headerEl = _.div({ class: "jss-dialog-head jss-dialog-head-custom" }, ...customHeaderNodes);
|
|
192
|
+
} else if (eyebrowNodes.length || titleNodes.length || subtitleNodes.length || iconNodes.length || closeSlotNodes.length) {
|
|
193
|
+
headerEl = _.div(
|
|
194
|
+
{ class: "jss-dialog-head" },
|
|
195
|
+
iconNodes.length ? _.div({ class: "jss-dialog-icon" }, ...iconNodes) : null,
|
|
196
|
+
_.div(
|
|
197
|
+
{ class: "jss-dialog-head-main" },
|
|
198
|
+
eyebrowNodes.length ? _.div({ class: "jss-dialog-eyebrow" }, ...eyebrowNodes) : null,
|
|
199
|
+
titleNodes.length ? _.div({ class: "jss-dialog-title" }, ...titleNodes) : null,
|
|
200
|
+
subtitleNodes.length ? _.div({ class: "jss-dialog-subtitle" }, ...subtitleNodes) : null
|
|
201
|
+
),
|
|
202
|
+
closeSlotNodes.length ? _.div({ class: "jss-dialog-close-wrap" }, ...closeSlotNodes) : null
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const bodyEl = _.div(
|
|
207
|
+
{ class: uiClass(["jss-dialog-body", opts.bodyClass]) },
|
|
208
|
+
...contentNodes
|
|
209
|
+
);
|
|
210
|
+
const footerEl = footerNodes.length
|
|
211
|
+
? _.div({
|
|
212
|
+
class: uiClass([
|
|
213
|
+
"jss-dialog-actions",
|
|
214
|
+
`is-${getAlignClass(opts)}`,
|
|
215
|
+
uiWhen(opts.stackActions, "is-stacked"),
|
|
216
|
+
opts.actionsClass,
|
|
217
|
+
opts.footerClass
|
|
218
|
+
])
|
|
219
|
+
}, ...footerNodes)
|
|
220
|
+
: null;
|
|
221
|
+
|
|
222
|
+
return _.div({
|
|
223
|
+
class: uiClass([
|
|
224
|
+
"jss-dialog-shell",
|
|
225
|
+
uiWhen(!!headerEl, "has-head"),
|
|
226
|
+
uiWhen(!!footerEl, "has-footer"),
|
|
227
|
+
uiWhen(opts.divider !== false, "with-divider")
|
|
228
|
+
])
|
|
229
|
+
}, ...[headerEl, bodyEl, footerEl].filter(Boolean));
|
|
230
|
+
};
|
|
231
|
+
const applyEntryOptions = (currentEntry) => {
|
|
232
|
+
if (!currentEntry?.panel) return;
|
|
233
|
+
const opts = getOptions();
|
|
234
|
+
const stateClass = getStateClass(opts);
|
|
235
|
+
const sizeClass = getSizeClass(opts);
|
|
236
|
+
setTrackedClasses(currentEntry.panel, "_dialogClassTokens", [
|
|
237
|
+
"jss-dialog",
|
|
238
|
+
"jss-singularity",
|
|
239
|
+
"jss-clear-set",
|
|
240
|
+
sizeClass ? `jss-dialog-${sizeClass}` : "",
|
|
241
|
+
stateClass,
|
|
242
|
+
stateClass ? `jss-state-${stateClass}` : "",
|
|
243
|
+
uiUnwrap(opts.fullscreen) ? "fullscreen" : "",
|
|
244
|
+
uiUnwrap(opts.scrollable) ? "scrollable" : "",
|
|
245
|
+
uiUnwrap(opts.stickyHeader) ? "sticky-head" : "",
|
|
246
|
+
uiUnwrap(opts.stickyActions) ? "sticky-actions" : "",
|
|
247
|
+
uiUnwrap(opts.borderless) ? "borderless" : "",
|
|
248
|
+
...splitClasses(opts.class),
|
|
249
|
+
...splitClasses(opts.panelClass)
|
|
250
|
+
]);
|
|
251
|
+
setTrackedClasses(currentEntry.overlay, "_dialogOverlayClassTokens", [
|
|
252
|
+
getVerticalAlignClass(opts),
|
|
253
|
+
uiUnwrap(opts.backdropBlur) ? "jss-dialog-overlay-blur" : "",
|
|
254
|
+
...splitClasses(opts.overlayClass)
|
|
255
|
+
]);
|
|
256
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-width", uiUnwrap(opts.width), toCssSize);
|
|
257
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-min-width", uiUnwrap(opts.minWidth), toCssSize);
|
|
258
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-max-width", uiUnwrap(opts.maxWidth), toCssSize);
|
|
259
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-max-height", uiUnwrap(opts.maxHeight), toCssSize);
|
|
260
|
+
setStyleValue(currentEntry.panel, "--jss-dialog-body-max-height", uiUnwrap(opts.bodyMaxHeight ?? opts.contentMaxHeight), toCssSize);
|
|
261
|
+
if (opts.style) Object.assign(currentEntry.panel.style, opts.style);
|
|
262
|
+
setPropertyProps(currentEntry.panel, opts);
|
|
263
|
+
ensureFullscreenViewportTracking(currentEntry, uiUnwrap(opts.fullscreen));
|
|
264
|
+
currentEntry.panel.setAttribute("role", opts.role || "dialog");
|
|
265
|
+
currentEntry.panel.setAttribute("aria-modal", opts.modal === false ? "false" : "true");
|
|
266
|
+
if (opts.ariaLabel) currentEntry.panel.setAttribute("aria-label", opts.ariaLabel);
|
|
267
|
+
else currentEntry.panel.removeAttribute("aria-label");
|
|
268
|
+
};
|
|
269
|
+
const renderOpenContent = () => {
|
|
270
|
+
if (!entry?.panel) return;
|
|
271
|
+
entry.panel.replaceChildren(buildContent());
|
|
272
|
+
};
|
|
273
|
+
const update = (nextProps = {}) => {
|
|
274
|
+
if (nextProps && typeof nextProps === "object") currentProps = { ...currentProps, ...nextProps };
|
|
275
|
+
if (entry) {
|
|
276
|
+
applyEntryOptions(entry);
|
|
277
|
+
renderOpenContent();
|
|
278
|
+
}
|
|
279
|
+
return api;
|
|
280
|
+
};
|
|
281
|
+
const open = (nextProps = null) => {
|
|
282
|
+
if (nextProps && typeof nextProps === "object") currentProps = { ...currentProps, ...nextProps };
|
|
283
|
+
if (entry) {
|
|
284
|
+
applyEntryOptions(entry);
|
|
285
|
+
renderOpenContent();
|
|
286
|
+
return entry;
|
|
287
|
+
}
|
|
288
|
+
lastActive = document.activeElement;
|
|
289
|
+
const opts = getOptions();
|
|
290
|
+
const persistent = opts.persistent === true;
|
|
291
|
+
entry = JSswift.overlay.open(() => buildContent(), {
|
|
292
|
+
type: "dialog",
|
|
293
|
+
backdrop: opts.backdrop !== false,
|
|
294
|
+
lockScroll: opts.lockScroll !== false,
|
|
295
|
+
trapFocus: opts.trapFocus !== false,
|
|
296
|
+
autoFocus: opts.autoFocus !== false,
|
|
297
|
+
closeOnOutside: opts.closeOnOutside ?? !persistent,
|
|
298
|
+
closeOnBackdrop: opts.closeOnBackdrop ?? !persistent,
|
|
299
|
+
closeOnEsc: opts.closeOnEsc ?? !persistent,
|
|
300
|
+
className: uiClassStatic(["jss-dialog"]),
|
|
301
|
+
onClose: () => {
|
|
302
|
+
entry?._dialogViewportCleanup?.();
|
|
303
|
+
entry?.panel?.removeEventListener("click", onPanelClick);
|
|
304
|
+
entry = null;
|
|
305
|
+
getOptions().onClose?.();
|
|
306
|
+
if (lastActive && typeof lastActive.focus === "function") {
|
|
307
|
+
setTimeout(() => lastActive.focus(), 0);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
const onPanelClick = (e) => {
|
|
312
|
+
const target = e.target;
|
|
313
|
+
if (target && target.closest && target.closest("[data-dialog-close]")) close();
|
|
314
|
+
};
|
|
315
|
+
entry.panel.addEventListener("click", onPanelClick);
|
|
316
|
+
applyEntryOptions(entry);
|
|
317
|
+
overlayEnter(entry);
|
|
318
|
+
getOptions().onOpen?.(entry);
|
|
319
|
+
return entry;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const close = () => {
|
|
323
|
+
if (!entry) return;
|
|
324
|
+
const toClose = entry;
|
|
325
|
+
overlayLeave(toClose, () => JSswift.overlay.close(toClose.id));
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const isOpen = () => !!entry;
|
|
329
|
+
const toggle = (nextProps = null) => isOpen() ? (close(), null) : open(nextProps);
|
|
330
|
+
const api = { open, close, toggle, update, isOpen, entry: () => entry, props: () => ({ ...currentProps }) };
|
|
331
|
+
|
|
332
|
+
return api;
|
|
333
|
+
};
|