@aortl/admin-react 0.12.1 → 0.13.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/dist/AdminRoot.d.ts +1 -1
- package/dist/AdminRoot.d.ts.map +1 -1
- package/dist/Button.d.ts +8 -7
- package/dist/Button.d.ts.map +1 -1
- package/dist/ButtonGroup.d.ts +7 -1
- package/dist/ButtonGroup.d.ts.map +1 -1
- package/dist/Input.d.ts +1 -1
- package/dist/Input.d.ts.map +1 -1
- package/dist/Link.d.ts +21 -0
- package/dist/Link.d.ts.map +1 -0
- package/dist/Textarea.d.ts +15 -2
- package/dist/Textarea.d.ts.map +1 -1
- package/dist/admin.scoped.css +156 -0
- package/dist/hotkey-parse.d.ts +9 -6
- package/dist/hotkey-parse.d.ts.map +1 -1
- package/dist/hotkey-registry.d.ts +5 -4
- package/dist/hotkey-registry.d.ts.map +1 -1
- package/dist/index.cjs +104 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +105 -29
- package/dist/index.mjs.map +1 -1
- package/dist/portal-context.d.ts +7 -4
- package/dist/portal-context.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4,12 +4,12 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
4
4
|
let react = require("react");
|
|
5
5
|
let _base_ui_react_button = require("@base-ui/react/button");
|
|
6
6
|
let _base_ui_react_input = require("@base-ui/react/input");
|
|
7
|
+
let _base_ui_react_field = require("@base-ui/react/field");
|
|
7
8
|
let _base_ui_react_checkbox = require("@base-ui/react/checkbox");
|
|
8
9
|
let _base_ui_react_radio = require("@base-ui/react/radio");
|
|
9
10
|
let _base_ui_react_radio_group = require("@base-ui/react/radio-group");
|
|
10
11
|
let _base_ui_react_switch = require("@base-ui/react/switch");
|
|
11
12
|
let _base_ui_react_select = require("@base-ui/react/select");
|
|
12
|
-
let _base_ui_react_field = require("@base-ui/react/field");
|
|
13
13
|
let _base_ui_react_tabs = require("@base-ui/react/tabs");
|
|
14
14
|
let _base_ui_react_tooltip = require("@base-ui/react/tooltip");
|
|
15
15
|
let _base_ui_react_dialog = require("@base-ui/react/dialog");
|
|
@@ -65,17 +65,40 @@ var Accordion = Object.assign(AccordionRoot, {
|
|
|
65
65
|
Content: AccordionContent
|
|
66
66
|
});
|
|
67
67
|
//#endregion
|
|
68
|
+
//#region src/portal-context.ts
|
|
69
|
+
/**
|
|
70
|
+
* Container that Base UI popups (Select, Tooltip, etc.) should portal into.
|
|
71
|
+
* `<AdminRoot>` publishes its own element here so popups render inside the
|
|
72
|
+
* scoped subtree and match the `@scope (._ao-admin-root)` CSS — without it
|
|
73
|
+
* they portal to `document.body`, outside the scope, and render unstyled. A
|
|
74
|
+
* `<Dialog>` ancestor overrides it with its own `<dialog>` element so popups
|
|
75
|
+
* join the top layer, painting above the backdrop and escaping its
|
|
76
|
+
* `overflow: hidden`. With no provider the context is null and popups fall
|
|
77
|
+
* back to `document.body`.
|
|
78
|
+
*/
|
|
79
|
+
var PortalContainerContext = (0, react.createContext)(null);
|
|
80
|
+
//#endregion
|
|
68
81
|
//#region src/AdminRoot.tsx
|
|
69
|
-
function AdminRoot({ className, theme, systemAccent, style, ...rest }) {
|
|
82
|
+
function AdminRoot({ className, theme, systemAccent, style, ref, ...rest }) {
|
|
70
83
|
const rootStyle = systemAccent !== void 0 ? {
|
|
71
84
|
...style,
|
|
72
85
|
"--color-system-accent": systemAccent
|
|
73
86
|
} : style;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
const portalRef = (0, react.useRef)(null);
|
|
88
|
+
const setRef = (0, react.useCallback)((node) => {
|
|
89
|
+
portalRef.current = node;
|
|
90
|
+
if (typeof ref === "function") ref(node);
|
|
91
|
+
else if (ref) ref.current = node;
|
|
92
|
+
}, [ref]);
|
|
93
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PortalContainerContext.Provider, {
|
|
94
|
+
value: portalRef,
|
|
95
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
96
|
+
ref: setRef,
|
|
97
|
+
className: cn("admin-root", className),
|
|
98
|
+
style: rootStyle,
|
|
99
|
+
...rest,
|
|
100
|
+
...theme !== void 0 && { "data-theme": theme }
|
|
101
|
+
})
|
|
79
102
|
});
|
|
80
103
|
}
|
|
81
104
|
//#endregion
|
|
@@ -208,9 +231,22 @@ var MOD_ORDER = [
|
|
|
208
231
|
"alt",
|
|
209
232
|
"meta"
|
|
210
233
|
];
|
|
234
|
+
/**
|
|
235
|
+
* Resolve the modifier `mod` aliases to. Apple platforms use ⌘ (`meta`) as the
|
|
236
|
+
* primary command modifier; everywhere else it's Ctrl. Detected once at module
|
|
237
|
+
* load (SSR-safe — the registry never dispatches server-side) and shared by the
|
|
238
|
+
* parse and display layers so the binding and its `<Kbd>` chip always agree.
|
|
239
|
+
*/
|
|
240
|
+
function detectApplePlatform() {
|
|
241
|
+
if (typeof navigator === "undefined") return false;
|
|
242
|
+
const platform = navigator.userAgentData?.platform || navigator.platform || "";
|
|
243
|
+
return /^(mac|iphone|ipad|ipod)/i.test(platform);
|
|
244
|
+
}
|
|
245
|
+
var IS_APPLE = detectApplePlatform();
|
|
246
|
+
var MOD_TARGET = IS_APPLE ? "meta" : "ctrl";
|
|
211
247
|
function tokenToMod(token) {
|
|
212
248
|
switch (token) {
|
|
213
|
-
case "mod":
|
|
249
|
+
case "mod": return MOD_TARGET;
|
|
214
250
|
case "ctrl":
|
|
215
251
|
case "control": return "ctrl";
|
|
216
252
|
case "shift": return "shift";
|
|
@@ -259,7 +295,7 @@ function normalizeEvent(e) {
|
|
|
259
295
|
if (key === "control" || key === "shift" || key === "alt" || key === "meta") return null;
|
|
260
296
|
const mods = /* @__PURE__ */ new Set();
|
|
261
297
|
if (e.ctrlKey) mods.add("ctrl");
|
|
262
|
-
if (e.shiftKey) mods.add("shift");
|
|
298
|
+
if (e.shiftKey && !isShiftedSymbol(key)) mods.add("shift");
|
|
263
299
|
if (e.altKey) mods.add("alt");
|
|
264
300
|
if (e.metaKey) mods.add("meta");
|
|
265
301
|
return canonicalize({
|
|
@@ -267,6 +303,10 @@ function normalizeEvent(e) {
|
|
|
267
303
|
key
|
|
268
304
|
});
|
|
269
305
|
}
|
|
306
|
+
/** A single printable symbol (`?`, `+`, `:`, …) — not a letter, digit, or named key. */
|
|
307
|
+
function isShiftedSymbol(key) {
|
|
308
|
+
return key.length === 1 && !/[a-z0-9]/.test(key);
|
|
309
|
+
}
|
|
270
310
|
var SPECIAL_KEY_LABELS = {
|
|
271
311
|
escape: "Esc",
|
|
272
312
|
esc: "Esc",
|
|
@@ -282,7 +322,12 @@ var SPECIAL_KEY_LABELS = {
|
|
|
282
322
|
backspace: "Backspace",
|
|
283
323
|
delete: "Del"
|
|
284
324
|
};
|
|
285
|
-
var MOD_LABELS = {
|
|
325
|
+
var MOD_LABELS = IS_APPLE ? {
|
|
326
|
+
ctrl: "⌃",
|
|
327
|
+
shift: "⇧",
|
|
328
|
+
alt: "⌥",
|
|
329
|
+
meta: "⌘"
|
|
330
|
+
} : {
|
|
286
331
|
ctrl: "Ctrl",
|
|
287
332
|
shift: "Shift",
|
|
288
333
|
alt: "Alt",
|
|
@@ -372,6 +417,7 @@ function isEditableTarget(target) {
|
|
|
372
417
|
return tag === "INPUT" || tag === "TEXTAREA";
|
|
373
418
|
}
|
|
374
419
|
function dispatch(e) {
|
|
420
|
+
if (e.repeat) return;
|
|
375
421
|
const chord = normalizeEvent(e);
|
|
376
422
|
if (chord === null) return;
|
|
377
423
|
const bucket = registry.get(chord);
|
|
@@ -447,10 +493,17 @@ function useHotkey(keys, handler, options) {
|
|
|
447
493
|
}
|
|
448
494
|
//#endregion
|
|
449
495
|
//#region src/Button.tsx
|
|
450
|
-
function Button({ variant = "default", size = "md", fullWidth, loading, icon, iconTrailing, hotkey, className, type = "button", disabled, children, onClick, ...rest }) {
|
|
451
|
-
const
|
|
496
|
+
function Button({ variant = "default", size = "md", fullWidth, loading, icon, iconTrailing, hotkey, className, type = "button", disabled, children, onClick, ref, ...rest }) {
|
|
497
|
+
const elementRef = (0, react.useRef)(null);
|
|
498
|
+
const setRef = (0, react.useCallback)((node) => {
|
|
499
|
+
elementRef.current = node;
|
|
500
|
+
if (typeof ref === "function") ref(node);
|
|
501
|
+
else if (ref) ref.current = node;
|
|
502
|
+
}, [ref]);
|
|
503
|
+
const { ariaKeyShortcuts, primaryChord } = useHotkey(hotkey, () => elementRef.current?.click(), { enabled: !disabled && !loading });
|
|
452
504
|
const iconOnly = children == null && (icon != null || iconTrailing != null);
|
|
453
505
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_button.Button, {
|
|
506
|
+
ref: setRef,
|
|
454
507
|
onClick,
|
|
455
508
|
type,
|
|
456
509
|
disabled: disabled || loading,
|
|
@@ -475,10 +528,14 @@ function Button({ variant = "default", size = "md", fullWidth, loading, icon, ic
|
|
|
475
528
|
}
|
|
476
529
|
//#endregion
|
|
477
530
|
//#region src/ButtonGroup.tsx
|
|
478
|
-
function ButtonGroup({ orientation = "horizontal", role = "group", className, ...rest }) {
|
|
531
|
+
function ButtonGroup({ orientation = "horizontal", fullWidth = false, role = "group", className, ...rest }) {
|
|
479
532
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
480
533
|
role,
|
|
481
|
-
className: cn([
|
|
534
|
+
className: cn([
|
|
535
|
+
"btn-group",
|
|
536
|
+
orientation === "vertical" && "btn-group-vertical",
|
|
537
|
+
fullWidth && "btn-group-full-width"
|
|
538
|
+
], className),
|
|
482
539
|
...rest
|
|
483
540
|
});
|
|
484
541
|
}
|
|
@@ -598,6 +655,26 @@ function Indicator({ label, variant = "neutral", size = "sm", icon, placement =
|
|
|
598
655
|
});
|
|
599
656
|
}
|
|
600
657
|
//#endregion
|
|
658
|
+
//#region src/Link.tsx
|
|
659
|
+
/**
|
|
660
|
+
* A text link — a plain `<a>` with the design system's link styling: primary
|
|
661
|
+
* color, hover shift, underline, and a focus-visible ring. Pass `external` for
|
|
662
|
+
* the new-tab affordance.
|
|
663
|
+
*/
|
|
664
|
+
function Link({ external, icon, iconTrailing, className, target, rel, children, ...rest }) {
|
|
665
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
666
|
+
target: target ?? (external ? "_blank" : void 0),
|
|
667
|
+
rel: rel ?? (external ? "noopener noreferrer" : void 0),
|
|
668
|
+
className: cn(["link", external && "link-external"], className),
|
|
669
|
+
...rest,
|
|
670
|
+
children: [
|
|
671
|
+
renderIcon(icon),
|
|
672
|
+
children,
|
|
673
|
+
renderIcon(iconTrailing)
|
|
674
|
+
]
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
//#endregion
|
|
601
678
|
//#region src/Pagination.tsx
|
|
602
679
|
/**
|
|
603
680
|
* Compute the items to render for a given `page` / `total`. Always returns:
|
|
@@ -759,12 +836,21 @@ function defaultRender(item, onPageChange, prev, next) {
|
|
|
759
836
|
}
|
|
760
837
|
//#endregion
|
|
761
838
|
//#region src/Textarea.tsx
|
|
762
|
-
|
|
763
|
-
|
|
839
|
+
/**
|
|
840
|
+
* Multi-line text input. Rendered through Base UI's `Field.Control` with a
|
|
841
|
+
* `<textarea>` swapped in for the default `<input>`, so inside a `<Field>` it
|
|
842
|
+
* gets the same wiring as `<Input>`: a generated id, label `htmlFor`
|
|
843
|
+
* association, and validity-driven `:user-valid` / `<Field.Error>`. Works
|
|
844
|
+
* standalone too — `Field.Control` falls back to a default context.
|
|
845
|
+
*/
|
|
846
|
+
function Textarea({ variant = "bordered", textareaSize = "md", autoResize, className, ...rest }) {
|
|
847
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_field.Field.Control, {
|
|
848
|
+
render: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", { ...props }),
|
|
764
849
|
className: cn([
|
|
765
850
|
"textarea",
|
|
766
851
|
variant !== "bordered" && `textarea-${variant}`,
|
|
767
|
-
textareaSize !== "md" && `textarea-${textareaSize}
|
|
852
|
+
textareaSize !== "md" && `textarea-${textareaSize}`,
|
|
853
|
+
autoResize && "textarea-autosize"
|
|
768
854
|
], className),
|
|
769
855
|
...rest
|
|
770
856
|
});
|
|
@@ -861,16 +947,6 @@ function SwitchThumb({ className, ...rest }) {
|
|
|
861
947
|
}
|
|
862
948
|
var Switch = Object.assign(SwitchRoot, { Thumb: SwitchThumb });
|
|
863
949
|
//#endregion
|
|
864
|
-
//#region src/portal-context.ts
|
|
865
|
-
/**
|
|
866
|
-
* Container that Base UI popups (Select, Tooltip, etc.) should portal into.
|
|
867
|
-
* When a `<Dialog>` ancestor publishes its `<dialog>` element through this
|
|
868
|
-
* context, popups render inside that top-layer dialog so they paint above
|
|
869
|
-
* the backdrop and escape its `overflow: hidden`. Outside a dialog the
|
|
870
|
-
* context is null and popups portal to `document.body` as before.
|
|
871
|
-
*/
|
|
872
|
-
var PortalContainerContext = (0, react.createContext)(null);
|
|
873
|
-
//#endregion
|
|
874
950
|
//#region src/Select.tsx
|
|
875
951
|
function SelectRoot(props) {
|
|
876
952
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Root, { ...props });
|
|
@@ -1952,6 +2028,7 @@ exports.Indicator = Indicator;
|
|
|
1952
2028
|
exports.Input = Input;
|
|
1953
2029
|
exports.InputGroup = InputGroup;
|
|
1954
2030
|
exports.Kbd = Kbd;
|
|
2031
|
+
exports.Link = Link;
|
|
1955
2032
|
exports.Menu = Menu;
|
|
1956
2033
|
exports.Navbar = Navbar;
|
|
1957
2034
|
exports.Pagination = Pagination;
|