@astralui/core 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +114 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +114 -23
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -167,48 +167,139 @@ function AstralThemeProvider({ colors, children }) {
|
|
|
167
167
|
children
|
|
168
168
|
] });
|
|
169
169
|
}
|
|
170
|
-
|
|
170
|
+
var dialogSeq = 0;
|
|
171
|
+
var dialogStack = [];
|
|
172
|
+
var FOCUSABLE = [
|
|
173
|
+
"a[href]",
|
|
174
|
+
"area[href]",
|
|
175
|
+
"button:not([disabled])",
|
|
176
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
177
|
+
"select:not([disabled])",
|
|
178
|
+
"textarea:not([disabled])",
|
|
179
|
+
"iframe",
|
|
180
|
+
"object",
|
|
181
|
+
"embed",
|
|
182
|
+
"[contenteditable]",
|
|
183
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
184
|
+
].join(",");
|
|
185
|
+
function useDialog(opened, onClose) {
|
|
186
|
+
const panelRef = useRef(null);
|
|
187
|
+
const idRef = useRef("");
|
|
188
|
+
if (!idRef.current) idRef.current = "au-dialog-title-" + String(++dialogSeq);
|
|
189
|
+
const onCloseRef = useRef(onClose);
|
|
190
|
+
onCloseRef.current = onClose;
|
|
171
191
|
useEffect(() => {
|
|
172
192
|
if (!opened) return;
|
|
193
|
+
const panel = panelRef.current;
|
|
194
|
+
if (!panel) return;
|
|
195
|
+
const restoreTo = document.activeElement;
|
|
196
|
+
dialogStack.push(panel);
|
|
197
|
+
const isTop = () => dialogStack[dialogStack.length - 1] === panel;
|
|
198
|
+
const focusables = () => Array.from(panel.querySelectorAll(FOCUSABLE)).filter(
|
|
199
|
+
(el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el === document.activeElement
|
|
200
|
+
);
|
|
201
|
+
const raf = requestAnimationFrame(() => {
|
|
202
|
+
if (panel.contains(document.activeElement)) return;
|
|
203
|
+
const list = focusables();
|
|
204
|
+
const target = list.find((el) => !el.classList.contains("au-modal-x")) ?? list[0] ?? panel;
|
|
205
|
+
target.focus();
|
|
206
|
+
});
|
|
173
207
|
const onKey = (e) => {
|
|
174
|
-
if (
|
|
208
|
+
if (!isTop()) return;
|
|
209
|
+
if (e.key === "Escape") {
|
|
210
|
+
onCloseRef.current();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (e.key !== "Tab") return;
|
|
214
|
+
const list = focusables();
|
|
215
|
+
if (!list.length) {
|
|
216
|
+
e.preventDefault();
|
|
217
|
+
panel.focus();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const first = list[0];
|
|
221
|
+
const last = list[list.length - 1];
|
|
222
|
+
const active = document.activeElement;
|
|
223
|
+
if (!panel.contains(active)) {
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
(e.shiftKey ? last : first).focus();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (e.shiftKey && active === first) {
|
|
229
|
+
e.preventDefault();
|
|
230
|
+
last.focus();
|
|
231
|
+
} else if (!e.shiftKey && active === last) {
|
|
232
|
+
e.preventDefault();
|
|
233
|
+
first.focus();
|
|
234
|
+
}
|
|
175
235
|
};
|
|
176
|
-
document.addEventListener("keydown", onKey);
|
|
177
|
-
const
|
|
236
|
+
document.addEventListener("keydown", onKey, true);
|
|
237
|
+
const prevOverflow = document.body.style.overflow;
|
|
178
238
|
document.body.style.overflow = "hidden";
|
|
179
239
|
return () => {
|
|
180
|
-
|
|
181
|
-
document.
|
|
240
|
+
cancelAnimationFrame(raf);
|
|
241
|
+
document.removeEventListener("keydown", onKey, true);
|
|
242
|
+
const at = dialogStack.indexOf(panel);
|
|
243
|
+
if (at !== -1) dialogStack.splice(at, 1);
|
|
244
|
+
document.body.style.overflow = prevOverflow;
|
|
245
|
+
if (restoreTo && document.contains(restoreTo)) restoreTo.focus();
|
|
182
246
|
};
|
|
183
|
-
}, [opened
|
|
247
|
+
}, [opened]);
|
|
248
|
+
return { panelRef, titleId: idRef.current };
|
|
184
249
|
}
|
|
185
250
|
function AstralModal({ opened, onClose, title, brand, width = 460, zIndex, children }) {
|
|
186
|
-
|
|
251
|
+
const { panelRef, titleId } = useDialog(opened, onClose);
|
|
187
252
|
if (!opened) return null;
|
|
188
253
|
const style = { maxWidth: width, ...brand ? { "--au-ic": brand } : {} };
|
|
189
254
|
return createPortal(
|
|
190
|
-
/* @__PURE__ */ jsx("div", { className: "au-modal-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxs(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
255
|
+
/* @__PURE__ */ jsx("div", { className: "au-modal-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxs(
|
|
256
|
+
"div",
|
|
257
|
+
{
|
|
258
|
+
ref: panelRef,
|
|
259
|
+
className: "au-modal-panel",
|
|
260
|
+
style,
|
|
261
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
262
|
+
role: "dialog",
|
|
263
|
+
"aria-modal": "true",
|
|
264
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
265
|
+
tabIndex: -1,
|
|
266
|
+
children: [
|
|
267
|
+
/* @__PURE__ */ jsxs("div", { className: "au-modal-head", children: [
|
|
268
|
+
/* @__PURE__ */ jsx("span", { className: "au-modal-title", id: titleId, children: title }),
|
|
269
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "au-modal-x", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(IconX, {}) })
|
|
270
|
+
] }),
|
|
271
|
+
/* @__PURE__ */ jsx("div", { className: "au-modal-body", children })
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
) }),
|
|
197
275
|
document.body
|
|
198
276
|
);
|
|
199
277
|
}
|
|
200
278
|
function AstralDrawer({ opened, onClose, title, brand, width = 440, zIndex, children }) {
|
|
201
|
-
|
|
279
|
+
const { panelRef, titleId } = useDialog(opened, onClose);
|
|
202
280
|
if (!opened) return null;
|
|
203
281
|
const style = { width, ...brand ? { "--au-ic": brand } : {} };
|
|
204
282
|
return createPortal(
|
|
205
|
-
/* @__PURE__ */ jsx("div", { className: "au-drawer-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxs(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
283
|
+
/* @__PURE__ */ jsx("div", { className: "au-drawer-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxs(
|
|
284
|
+
"div",
|
|
285
|
+
{
|
|
286
|
+
ref: panelRef,
|
|
287
|
+
className: "au-drawer-panel",
|
|
288
|
+
style,
|
|
289
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
290
|
+
role: "dialog",
|
|
291
|
+
"aria-modal": "true",
|
|
292
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
293
|
+
tabIndex: -1,
|
|
294
|
+
children: [
|
|
295
|
+
/* @__PURE__ */ jsxs("div", { className: "au-drawer-head", children: [
|
|
296
|
+
/* @__PURE__ */ jsx("span", { className: "au-drawer-title", id: titleId, children: title }),
|
|
297
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "au-modal-x", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(IconX, {}) })
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsx("div", { className: "au-drawer-body", children })
|
|
300
|
+
]
|
|
301
|
+
}
|
|
302
|
+
) }),
|
|
212
303
|
document.body
|
|
213
304
|
);
|
|
214
305
|
}
|