@astralui/core 0.1.10 → 0.1.12
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 +130 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +130 -24
- package/dist/index.js.map +1 -1
- package/dist/styles.css +5 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -173,48 +173,139 @@ function AstralThemeProvider({ colors, children }) {
|
|
|
173
173
|
children
|
|
174
174
|
] });
|
|
175
175
|
}
|
|
176
|
-
|
|
176
|
+
var dialogSeq = 0;
|
|
177
|
+
var dialogStack = [];
|
|
178
|
+
var FOCUSABLE = [
|
|
179
|
+
"a[href]",
|
|
180
|
+
"area[href]",
|
|
181
|
+
"button:not([disabled])",
|
|
182
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
183
|
+
"select:not([disabled])",
|
|
184
|
+
"textarea:not([disabled])",
|
|
185
|
+
"iframe",
|
|
186
|
+
"object",
|
|
187
|
+
"embed",
|
|
188
|
+
"[contenteditable]",
|
|
189
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
190
|
+
].join(",");
|
|
191
|
+
function useDialog(opened, onClose) {
|
|
192
|
+
const panelRef = react.useRef(null);
|
|
193
|
+
const idRef = react.useRef("");
|
|
194
|
+
if (!idRef.current) idRef.current = "au-dialog-title-" + String(++dialogSeq);
|
|
195
|
+
const onCloseRef = react.useRef(onClose);
|
|
196
|
+
onCloseRef.current = onClose;
|
|
177
197
|
react.useEffect(() => {
|
|
178
198
|
if (!opened) return;
|
|
199
|
+
const panel = panelRef.current;
|
|
200
|
+
if (!panel) return;
|
|
201
|
+
const restoreTo = document.activeElement;
|
|
202
|
+
dialogStack.push(panel);
|
|
203
|
+
const isTop = () => dialogStack[dialogStack.length - 1] === panel;
|
|
204
|
+
const focusables = () => Array.from(panel.querySelectorAll(FOCUSABLE)).filter(
|
|
205
|
+
(el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el === document.activeElement
|
|
206
|
+
);
|
|
207
|
+
const raf = requestAnimationFrame(() => {
|
|
208
|
+
if (panel.contains(document.activeElement)) return;
|
|
209
|
+
const list = focusables();
|
|
210
|
+
const target = list.find((el) => !el.classList.contains("au-modal-x")) ?? list[0] ?? panel;
|
|
211
|
+
target.focus();
|
|
212
|
+
});
|
|
179
213
|
const onKey = (e) => {
|
|
180
|
-
if (
|
|
214
|
+
if (!isTop()) return;
|
|
215
|
+
if (e.key === "Escape") {
|
|
216
|
+
onCloseRef.current();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (e.key !== "Tab") return;
|
|
220
|
+
const list = focusables();
|
|
221
|
+
if (!list.length) {
|
|
222
|
+
e.preventDefault();
|
|
223
|
+
panel.focus();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const first = list[0];
|
|
227
|
+
const last = list[list.length - 1];
|
|
228
|
+
const active = document.activeElement;
|
|
229
|
+
if (!panel.contains(active)) {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
(e.shiftKey ? last : first).focus();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (e.shiftKey && active === first) {
|
|
235
|
+
e.preventDefault();
|
|
236
|
+
last.focus();
|
|
237
|
+
} else if (!e.shiftKey && active === last) {
|
|
238
|
+
e.preventDefault();
|
|
239
|
+
first.focus();
|
|
240
|
+
}
|
|
181
241
|
};
|
|
182
|
-
document.addEventListener("keydown", onKey);
|
|
183
|
-
const
|
|
242
|
+
document.addEventListener("keydown", onKey, true);
|
|
243
|
+
const prevOverflow = document.body.style.overflow;
|
|
184
244
|
document.body.style.overflow = "hidden";
|
|
185
245
|
return () => {
|
|
186
|
-
|
|
187
|
-
document.
|
|
246
|
+
cancelAnimationFrame(raf);
|
|
247
|
+
document.removeEventListener("keydown", onKey, true);
|
|
248
|
+
const at = dialogStack.indexOf(panel);
|
|
249
|
+
if (at !== -1) dialogStack.splice(at, 1);
|
|
250
|
+
document.body.style.overflow = prevOverflow;
|
|
251
|
+
if (restoreTo && document.contains(restoreTo)) restoreTo.focus();
|
|
188
252
|
};
|
|
189
|
-
}, [opened
|
|
253
|
+
}, [opened]);
|
|
254
|
+
return { panelRef, titleId: idRef.current };
|
|
190
255
|
}
|
|
191
256
|
function AstralModal({ opened, onClose, title, brand, width = 460, zIndex, children }) {
|
|
192
|
-
|
|
257
|
+
const { panelRef, titleId } = useDialog(opened, onClose);
|
|
193
258
|
if (!opened) return null;
|
|
194
259
|
const style = { maxWidth: width, ...brand ? { "--au-ic": brand } : {} };
|
|
195
260
|
return reactDom.createPortal(
|
|
196
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-modal-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
261
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-modal-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
262
|
+
"div",
|
|
263
|
+
{
|
|
264
|
+
ref: panelRef,
|
|
265
|
+
className: "au-modal-panel",
|
|
266
|
+
style,
|
|
267
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
268
|
+
role: "dialog",
|
|
269
|
+
"aria-modal": "true",
|
|
270
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
271
|
+
tabIndex: -1,
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "au-modal-head", children: [
|
|
274
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "au-modal-title", id: titleId, children: title }),
|
|
275
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "au-modal-x", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconX, {}) })
|
|
276
|
+
] }),
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-modal-body", children })
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
) }),
|
|
203
281
|
document.body
|
|
204
282
|
);
|
|
205
283
|
}
|
|
206
284
|
function AstralDrawer({ opened, onClose, title, brand, width = 440, zIndex, children }) {
|
|
207
|
-
|
|
285
|
+
const { panelRef, titleId } = useDialog(opened, onClose);
|
|
208
286
|
if (!opened) return null;
|
|
209
287
|
const style = { width, ...brand ? { "--au-ic": brand } : {} };
|
|
210
288
|
return reactDom.createPortal(
|
|
211
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-drawer-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
289
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-drawer-overlay", onMouseDown: onClose, style: zIndex != null ? { zIndex } : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
290
|
+
"div",
|
|
291
|
+
{
|
|
292
|
+
ref: panelRef,
|
|
293
|
+
className: "au-drawer-panel",
|
|
294
|
+
style,
|
|
295
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
296
|
+
role: "dialog",
|
|
297
|
+
"aria-modal": "true",
|
|
298
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
299
|
+
tabIndex: -1,
|
|
300
|
+
children: [
|
|
301
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "au-drawer-head", children: [
|
|
302
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "au-drawer-title", id: titleId, children: title }),
|
|
303
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "au-modal-x", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconX, {}) })
|
|
304
|
+
] }),
|
|
305
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "au-drawer-body", children })
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
) }),
|
|
218
309
|
document.body
|
|
219
310
|
);
|
|
220
311
|
}
|
|
@@ -918,6 +1009,17 @@ var COLOR_MAP = {
|
|
|
918
1009
|
replied: "#8b5cf6",
|
|
919
1010
|
success: "#16a34a"
|
|
920
1011
|
};
|
|
1012
|
+
var FG = {
|
|
1013
|
+
"#eab308": ["#854d0e", "#fde047"],
|
|
1014
|
+
"#06b6d4": ["#155e75", "#67e8f9"],
|
|
1015
|
+
"#EF8E2E": ["#9a4a06", "#fdba74"],
|
|
1016
|
+
"#9ca3af": ["#4b5563", "#d1d5db"],
|
|
1017
|
+
"#16a34a": ["#14532d", "#4ade80"],
|
|
1018
|
+
"#3b82f6": ["#1e40af", "#93c5fd"],
|
|
1019
|
+
"#ef4444": ["#991b1b", "#fca5a5"],
|
|
1020
|
+
"#8b5cf6": ["#5b21b6", "#c4b5fd"]
|
|
1021
|
+
};
|
|
1022
|
+
var SOLID = { "#16a34a": "#166534" };
|
|
921
1023
|
var FILLED = /* @__PURE__ */ new Set(["running", "active", "online"]);
|
|
922
1024
|
function StatusBadge({ status, label, color, filled }) {
|
|
923
1025
|
const c = color ?? COLOR_MAP[status] ?? "#9ca3af";
|
|
@@ -927,7 +1029,11 @@ function StatusBadge({ status, label, color, filled }) {
|
|
|
927
1029
|
"span",
|
|
928
1030
|
{
|
|
929
1031
|
className: `au-sbadge${isFilled ? " filled" : ""}`,
|
|
930
|
-
style: {
|
|
1032
|
+
style: {
|
|
1033
|
+
"--au-sb": c,
|
|
1034
|
+
...FG[c] ? { "--au-sb-fg": `light-dark(${FG[c][0]}, ${FG[c][1]})` } : {},
|
|
1035
|
+
...SOLID[c] ? { "--au-sb-solid": SOLID[c] } : {}
|
|
1036
|
+
},
|
|
931
1037
|
title: typeof text === "string" ? text : void 0,
|
|
932
1038
|
children: [
|
|
933
1039
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "au-sbadge-dot" }),
|