@aortl/admin-react 0.7.1 → 0.8.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/icon.d.ts CHANGED
@@ -10,17 +10,19 @@ export interface IconRenderProps {
10
10
  export type IconComponent = ComponentType<IconRenderProps>;
11
11
  /**
12
12
  * The value a component prop named `icon` will accept. Either:
13
- * - a component reference (`icon={IconHome}`) — rendered with `size={16} aria-hidden`,
13
+ * - a component reference (`icon={IconHome}`) — rendered with `size="1em" aria-hidden`,
14
14
  * - or an already-instantiated React element (`icon={<IconHome size={20} />}`) — rendered as-is.
15
15
  */
16
16
  export type IconProp = IconComponent | ReactElement | null | undefined;
17
17
  /**
18
- * Render an `IconProp` to a React node, defaulting to `size={16} aria-hidden`
19
- * when given a component reference.
18
+ * Render an `IconProp` to a React node, defaulting to `size="1em" aria-hidden`
19
+ * when given a component reference. The `"1em"` default makes SVG icons inherit
20
+ * the host's `font-size`, matching how the Tabler webfont (`<i class="ti …">`)
21
+ * renders in the vanilla bundle — so both previews end up the same size.
20
22
  *
21
23
  * Anything that is not `null`/`undefined` and not already a React element is
22
24
  * treated as a component type — `createElement` accepts function components,
23
25
  * `forwardRef`s (e.g. `@tabler/icons-react`), `memo`, etc.
24
26
  */
25
- export declare function renderIcon(icon: IconProp, size?: number): ReactNode;
27
+ export declare function renderIcon(icon: IconProp, size?: number | string): ReactNode;
26
28
  //# sourceMappingURL=icon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C;AAED,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;AAEvE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,MAAW,GAAG,SAAS,CAIvE"}
1
+ {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C;AAED,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;AAEvE;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,MAAM,GAAG,MAAc,GAAG,SAAS,CAInF"}
package/dist/index.cjs CHANGED
@@ -81,14 +81,16 @@ function AdminRoot({ className, theme, systemAccent, style, ...rest }) {
81
81
  //#endregion
82
82
  //#region src/icon.ts
83
83
  /**
84
- * Render an `IconProp` to a React node, defaulting to `size={16} aria-hidden`
85
- * when given a component reference.
84
+ * Render an `IconProp` to a React node, defaulting to `size="1em" aria-hidden`
85
+ * when given a component reference. The `"1em"` default makes SVG icons inherit
86
+ * the host's `font-size`, matching how the Tabler webfont (`<i class="ti …">`)
87
+ * renders in the vanilla bundle — so both previews end up the same size.
86
88
  *
87
89
  * Anything that is not `null`/`undefined` and not already a React element is
88
90
  * treated as a component type — `createElement` accepts function components,
89
91
  * `forwardRef`s (e.g. `@tabler/icons-react`), `memo`, etc.
90
92
  */
91
- function renderIcon(icon, size = 16) {
93
+ function renderIcon(icon, size = "1em") {
92
94
  if (icon == null) return null;
93
95
  if ((0, react.isValidElement)(icon)) return icon;
94
96
  return (0, react.createElement)(icon, {
@@ -199,13 +201,261 @@ function BrandTile({ monogram, icon, className, children, ...rest }) {
199
201
  });
200
202
  }
201
203
  //#endregion
204
+ //#region src/hotkey-parse.ts
205
+ var MOD_ORDER = [
206
+ "ctrl",
207
+ "shift",
208
+ "alt",
209
+ "meta"
210
+ ];
211
+ function tokenToMod(token) {
212
+ switch (token) {
213
+ case "mod":
214
+ case "ctrl":
215
+ case "control": return "ctrl";
216
+ case "shift": return "shift";
217
+ case "alt": return "alt";
218
+ case "meta": return "meta";
219
+ default: return null;
220
+ }
221
+ }
222
+ function parseChord(input) {
223
+ const tokens = input.trim().toLowerCase().split("+").map((t) => t.trim()).filter(Boolean);
224
+ if (tokens.length === 0) throw new Error(`Invalid hotkey: empty string`);
225
+ const mods = /* @__PURE__ */ new Set();
226
+ let key = null;
227
+ for (const token of tokens) {
228
+ const mod = tokenToMod(token);
229
+ if (mod !== null) {
230
+ mods.add(mod);
231
+ continue;
232
+ }
233
+ if (key !== null) throw new Error(`Invalid hotkey "${input}": multiple non-modifier keys`);
234
+ key = token;
235
+ }
236
+ if (key === null) throw new Error(`Invalid hotkey "${input}": missing key`);
237
+ return {
238
+ mods,
239
+ key
240
+ };
241
+ }
242
+ function parseKeys(keys) {
243
+ return (typeof keys === "string" ? [keys] : keys).map(parseChord);
244
+ }
245
+ /** Canonical wire form used as a map key in the registry. */
246
+ function canonicalize(chord) {
247
+ const parts = [];
248
+ for (const mod of MOD_ORDER) if (chord.mods.has(mod)) parts.push(mod);
249
+ parts.push(chord.key);
250
+ return parts.join("+");
251
+ }
252
+ /**
253
+ * Normalize a keyboard event to its canonical chord string. Returns `null`
254
+ * if the event is a bare modifier press (`Shift` by itself, etc.) so callers
255
+ * can short-circuit before a map lookup.
256
+ */
257
+ function normalizeEvent(e) {
258
+ const key = e.key.toLowerCase();
259
+ if (key === "control" || key === "shift" || key === "alt" || key === "meta") return null;
260
+ const mods = /* @__PURE__ */ new Set();
261
+ if (e.ctrlKey) mods.add("ctrl");
262
+ if (e.shiftKey) mods.add("shift");
263
+ if (e.altKey) mods.add("alt");
264
+ if (e.metaKey) mods.add("meta");
265
+ return canonicalize({
266
+ mods,
267
+ key
268
+ });
269
+ }
270
+ var SPECIAL_KEY_LABELS = {
271
+ escape: "Esc",
272
+ esc: "Esc",
273
+ enter: "Enter",
274
+ return: "Enter",
275
+ tab: "Tab",
276
+ " ": "Space",
277
+ space: "Space",
278
+ arrowup: "↑",
279
+ arrowdown: "↓",
280
+ arrowleft: "←",
281
+ arrowright: "→",
282
+ backspace: "Backspace",
283
+ delete: "Del"
284
+ };
285
+ var MOD_LABELS = {
286
+ ctrl: "Ctrl",
287
+ shift: "Shift",
288
+ alt: "Alt",
289
+ meta: "Meta"
290
+ };
291
+ /** Visual chips for a chord — one entry per modifier and the final key. */
292
+ function formatChord(chord) {
293
+ const parts = [];
294
+ for (const mod of MOD_ORDER) if (chord.mods.has(mod)) parts.push(MOD_LABELS[mod]);
295
+ const special = SPECIAL_KEY_LABELS[chord.key];
296
+ if (special !== void 0) parts.push(special);
297
+ else if (chord.key.length === 1) parts.push(chord.key.toUpperCase());
298
+ else parts.push(chord.key.charAt(0).toUpperCase() + chord.key.slice(1));
299
+ return parts;
300
+ }
301
+ var ARIA_MOD_LABELS = {
302
+ ctrl: "Control",
303
+ shift: "Shift",
304
+ alt: "Alt",
305
+ meta: "Meta"
306
+ };
307
+ function toAriaPart(chord) {
308
+ const parts = [];
309
+ for (const mod of MOD_ORDER) if (chord.mods.has(mod)) parts.push(ARIA_MOD_LABELS[mod]);
310
+ parts.push(chord.key.length === 1 ? chord.key.toUpperCase() : chord.key);
311
+ return parts.join("+");
312
+ }
313
+ /**
314
+ * Serialize one or more chords to the `aria-keyshortcuts` format
315
+ * (space-separated alternatives, modifiers as `Control`/`Shift`/etc.).
316
+ */
317
+ function toAriaKeyShortcuts(chords) {
318
+ return chords.map(toAriaPart).join(" ");
319
+ }
320
+ //#endregion
321
+ //#region src/Kbd.tsx
322
+ /**
323
+ * Visual representation of a keyboard shortcut. Two shapes:
324
+ *
325
+ * ```tsx
326
+ * <Kbd keys="mod+s" /> // parsed: <Ctrl><S> in a .kbd-group
327
+ * <Kbd>Esc</Kbd> // literal: single <kbd>Esc</kbd>
328
+ * ```
329
+ *
330
+ * Render outside of action surfaces (tooltips, help dialogs) or inside them
331
+ * via the `hotkey` prop on `<Button>` / `<Menu.Item>`.
332
+ */
333
+ function Kbd({ keys, children, className, ...rest }) {
334
+ if (keys != null) {
335
+ const chord = parseKeys(keys)[0];
336
+ if (!chord) return null;
337
+ const parts = formatChord(chord);
338
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
339
+ className: cn("kbd-group", className),
340
+ ...rest,
341
+ children: parts.map((part, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("kbd", {
342
+ className: cn("kbd", void 0),
343
+ children: part
344
+ }, `${i}-${part}`))
345
+ });
346
+ }
347
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("kbd", {
348
+ className: cn("kbd", className),
349
+ ...rest,
350
+ children
351
+ });
352
+ }
353
+ //#endregion
354
+ //#region src/hotkey-registry.ts
355
+ var registry = /* @__PURE__ */ new Map();
356
+ var listenerAttached = false;
357
+ function ensureListener() {
358
+ if (listenerAttached || typeof window === "undefined") return;
359
+ window.addEventListener("keydown", dispatch);
360
+ listenerAttached = true;
361
+ }
362
+ function maybeDetachListener() {
363
+ if (!listenerAttached || typeof window === "undefined") return;
364
+ if (registry.size > 0) return;
365
+ window.removeEventListener("keydown", dispatch);
366
+ listenerAttached = false;
367
+ }
368
+ function isEditableTarget(target) {
369
+ if (!(target instanceof HTMLElement)) return false;
370
+ if (target.isContentEditable) return true;
371
+ const tag = target.tagName;
372
+ return tag === "INPUT" || tag === "TEXTAREA";
373
+ }
374
+ function dispatch(e) {
375
+ const chord = normalizeEvent(e);
376
+ if (chord === null) return;
377
+ const bucket = registry.get(chord);
378
+ if (!bucket || bucket.size === 0) return;
379
+ if (isEditableTarget(e.target) && !chord.includes("+") && chord !== "escape") return;
380
+ e.preventDefault();
381
+ for (const entry of bucket) entry.handlerRef.current?.(e);
382
+ }
383
+ /**
384
+ * Register a hotkey entry under each of its canonical chord strings.
385
+ * Returns an unregister function that removes the entry from every bucket
386
+ * and detaches the listener if the registry is empty.
387
+ */
388
+ function register(canonicalChords, entry) {
389
+ for (const chord of canonicalChords) {
390
+ let bucket = registry.get(chord);
391
+ if (!bucket) {
392
+ bucket = /* @__PURE__ */ new Set();
393
+ registry.set(chord, bucket);
394
+ }
395
+ bucket.add(entry);
396
+ }
397
+ ensureListener();
398
+ return () => {
399
+ for (const chord of canonicalChords) {
400
+ const bucket = registry.get(chord);
401
+ if (!bucket) continue;
402
+ bucket.delete(entry);
403
+ if (bucket.size === 0) registry.delete(chord);
404
+ }
405
+ maybeDetachListener();
406
+ };
407
+ }
408
+ //#endregion
409
+ //#region src/useHotkey.ts
410
+ /**
411
+ * Register a keyboard shortcut. The handler is latched in a ref internally so
412
+ * callers don't need to memoize it. Passing nullish `keys` is a no-op, so
413
+ * the hook is safe to call unconditionally from components that may or may
414
+ * not have a binding (e.g. the `hotkey` prop on `<Button>`).
415
+ *
416
+ * @example
417
+ * useHotkey("mod+s", save);
418
+ * useHotkey(["mod+s", "mod+enter"], save, { enabled: !isLoading });
419
+ *
420
+ * Returns derived strings for rendering — see {@link HotkeyInfo}.
421
+ */
422
+ function useHotkey(keys, handler, options) {
423
+ const enabled = options?.enabled ?? true;
424
+ const handlerRef = (0, react.useRef)(handler);
425
+ handlerRef.current = handler;
426
+ const keyId = keys == null ? "" : Array.isArray(keys) ? keys.join("|") : keys;
427
+ const derived = (0, react.useMemo)(() => {
428
+ if (keyId === "") return {
429
+ canonicalChords: [],
430
+ ariaKeyShortcuts: void 0,
431
+ primaryChord: void 0
432
+ };
433
+ const parsed = parseKeys(keys);
434
+ const cans = parsed.map(canonicalize);
435
+ return {
436
+ canonicalChords: cans,
437
+ ariaKeyShortcuts: toAriaKeyShortcuts(parsed),
438
+ primaryChord: cans[0]
439
+ };
440
+ }, [keyId]);
441
+ (0, react.useEffect)(() => {
442
+ if (!enabled || derived.canonicalChords.length === 0) return;
443
+ const entry = { handlerRef };
444
+ return register(derived.canonicalChords, entry);
445
+ }, [derived, enabled]);
446
+ return derived;
447
+ }
448
+ //#endregion
202
449
  //#region src/Button.tsx
203
- function Button({ variant = "primary", size = "md", fullWidth, loading, icon, iconTrailing, className, type = "button", disabled, children, ...rest }) {
450
+ function Button({ variant = "primary", size = "md", fullWidth, loading, icon, iconTrailing, hotkey, className, type = "button", disabled, children, onClick, ...rest }) {
451
+ const { ariaKeyShortcuts, primaryChord } = useHotkey(hotkey, (e) => onClick?.(e), { enabled: !disabled && !loading });
204
452
  const iconOnly = children == null && (icon != null || iconTrailing != null);
205
453
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_button.Button, {
454
+ onClick,
206
455
  type,
207
456
  disabled: disabled || loading,
208
457
  "aria-busy": loading || void 0,
458
+ "aria-keyshortcuts": ariaKeyShortcuts,
209
459
  className: cn([
210
460
  "btn",
211
461
  `btn-${variant}`,
@@ -218,7 +468,8 @@ function Button({ variant = "primary", size = "md", fullWidth, loading, icon, ic
218
468
  children: [
219
469
  loading ? null : renderIcon(icon),
220
470
  children,
221
- renderIcon(iconTrailing)
471
+ renderIcon(iconTrailing),
472
+ primaryChord !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Kbd, { keys: primaryChord }) : null
222
473
  ]
223
474
  });
224
475
  }
@@ -315,6 +566,38 @@ function InputGroupAddon({ className, ...rest }) {
315
566
  }
316
567
  var InputGroup = Object.assign(InputGroupRoot, { Addon: InputGroupAddon });
317
568
  //#endregion
569
+ //#region src/Indicator.tsx
570
+ function Indicator({ label, variant = "neutral", size = "sm", icon, placement = "top-end", offset, className, "aria-label": ariaLabel, children }) {
571
+ const [vertical, horizontal] = placement.split("-");
572
+ const placementClasses = [
573
+ "indicator-item",
574
+ vertical !== "top" && `indicator-${vertical}`,
575
+ horizontal !== "end" && `indicator-${horizontal}`
576
+ ];
577
+ const hasContent = label !== void 0 || icon !== void 0;
578
+ const style = offset !== void 0 ? { "--indicator-offset": `${offset}px` } : void 0;
579
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
580
+ className: cn("indicator", className),
581
+ style,
582
+ children: [hasContent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
583
+ className: cn(placementClasses, void 0),
584
+ variant,
585
+ size,
586
+ icon,
587
+ "aria-label": ariaLabel,
588
+ children: label
589
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
590
+ className: cn([
591
+ ...placementClasses,
592
+ "indicator-dot",
593
+ variant !== "neutral" && `indicator-dot-${variant}`
594
+ ], void 0),
595
+ role: ariaLabel !== void 0 ? "status" : void 0,
596
+ "aria-label": ariaLabel
597
+ }), children]
598
+ });
599
+ }
600
+ //#endregion
318
601
  //#region src/Pagination.tsx
319
602
  /**
320
603
  * Compute the items to render for a given `page` / `total`. Always returns:
@@ -578,6 +861,16 @@ function SwitchThumb({ className, ...rest }) {
578
861
  }
579
862
  var Switch = Object.assign(SwitchRoot, { Thumb: SwitchThumb });
580
863
  //#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
581
874
  //#region src/Select.tsx
582
875
  function SelectRoot(props) {
583
876
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Root, { ...props });
@@ -603,14 +896,19 @@ function SelectIcon({ className, children, ...rest }) {
603
896
  });
604
897
  }
605
898
  function SelectPopup({ className, sideOffset = 4, children, ...rest }) {
606
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Positioner, {
607
- sideOffset,
608
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Popup, {
609
- className: cn("select-popup", className),
610
- ...rest,
611
- children
899
+ const portalContainer = (0, react.useContext)(PortalContainerContext);
900
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Portal, {
901
+ container: portalContainer ?? void 0,
902
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Positioner, {
903
+ sideOffset,
904
+ alignItemWithTrigger: false,
905
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Popup, {
906
+ className: cn("select-popup", className),
907
+ ...rest,
908
+ children
909
+ })
612
910
  })
613
- }) });
911
+ });
614
912
  }
615
913
  function SelectItem({ className, ...rest }) {
616
914
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_select.Select.Item, {
@@ -802,12 +1100,15 @@ function DialogContainer({ open, onOpenChange, size = "md", closedby = "any", cl
802
1100
  }, []);
803
1101
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogContext.Provider, {
804
1102
  value: { close: () => ref.current?.close() },
805
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
806
- ref,
807
- className: cn(["dialog", size !== "md" && `dialog-${size}`], className),
808
- closedby,
809
- ...rest,
810
- children
1103
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PortalContainerContext.Provider, {
1104
+ value: ref,
1105
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
1106
+ ref,
1107
+ className: cn(["dialog", size !== "md" && `dialog-${size}`], className),
1108
+ closedby,
1109
+ ...rest,
1110
+ children
1111
+ })
811
1112
  })
812
1113
  });
813
1114
  }
@@ -972,22 +1273,37 @@ function MenuPopup({ className, role = "menu", ...rest }) {
972
1273
  });
973
1274
  }
974
1275
  function MenuItem(props) {
1276
+ const ref = (0, react.useRef)(null);
1277
+ const hotkey = props.hotkey;
1278
+ const { ariaKeyShortcuts, primaryChord } = useHotkey(hotkey, () => ref.current?.click(), { enabled: !("disabled" in props && props.disabled) });
975
1279
  if (props.href !== void 0) {
976
- const { className, role = "menuitem", icon, children, ...rest } = props;
1280
+ const { className, role = "menuitem", icon, children, hotkey: _hk, ...rest } = props;
977
1281
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1282
+ ref,
978
1283
  role,
1284
+ "aria-keyshortcuts": ariaKeyShortcuts,
979
1285
  className: cn("menu-item", className),
980
1286
  ...rest,
981
- children: [renderIcon(icon), children]
1287
+ children: [
1288
+ renderIcon(icon),
1289
+ children,
1290
+ primaryChord !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Kbd, { keys: primaryChord }) : null
1291
+ ]
982
1292
  });
983
1293
  }
984
- const { className, type = "button", role = "menuitem", icon, children, ...rest } = props;
1294
+ const { className, type = "button", role = "menuitem", icon, children, hotkey: _hk, ...rest } = props;
985
1295
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1296
+ ref,
986
1297
  type,
987
1298
  role,
1299
+ "aria-keyshortcuts": ariaKeyShortcuts,
988
1300
  className: cn("menu-item", className),
989
1301
  ...rest,
990
- children: [renderIcon(icon), children]
1302
+ children: [
1303
+ renderIcon(icon),
1304
+ children,
1305
+ primaryChord !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Kbd, { keys: primaryChord }) : null
1306
+ ]
991
1307
  });
992
1308
  }
993
1309
  function MenuSeparator({ className, ...rest }) {
@@ -1136,17 +1452,21 @@ function TooltipTrigger(props) {
1136
1452
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Trigger, { ...props });
1137
1453
  }
1138
1454
  function TooltipPopup({ size = "md", side = "top", align = "center", sideOffset = 6, role = "tooltip", className, children, ...rest }) {
1139
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Positioner, {
1140
- sideOffset,
1141
- side,
1142
- align,
1143
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Popup, {
1144
- role,
1145
- className: cn(["tooltip", size !== "md" && `tooltip-${size}`], className),
1146
- ...rest,
1147
- children
1455
+ const portalContainer = (0, react.useContext)(PortalContainerContext);
1456
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Portal, {
1457
+ container: portalContainer ?? void 0,
1458
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Positioner, {
1459
+ sideOffset,
1460
+ side,
1461
+ align,
1462
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tooltip.Tooltip.Popup, {
1463
+ role,
1464
+ className: cn(["tooltip", size !== "md" && `tooltip-${size}`], className),
1465
+ ...rest,
1466
+ children
1467
+ })
1148
1468
  })
1149
- }) });
1469
+ });
1150
1470
  }
1151
1471
  function TooltipShorthand({ content, side, align, sideOffset, size, children, ...rootProps }) {
1152
1472
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TooltipRoot, {
@@ -1200,13 +1520,12 @@ function CheckGlyph({ className }) {
1200
1520
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5 12l5 5l10 -10" })
1201
1521
  });
1202
1522
  }
1203
- function PropertyListRoot({ striped, compact, copyable, hideIfAllEmpty, title, className, children, ...rest }) {
1523
+ function PropertyListRoot({ striped, compact, hideIfAllEmpty, title, className, children, ...rest }) {
1204
1524
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1205
1525
  className: cn([
1206
1526
  "property-list",
1207
1527
  striped && "property-list-striped",
1208
1528
  compact && "property-list-compact",
1209
- copyable && "property-list-copyable",
1210
1529
  hideIfAllEmpty && "property-list-hide-if-empty"
1211
1530
  ], className),
1212
1531
  ...rest,
@@ -1523,8 +1842,10 @@ exports.Dialog = Dialog;
1523
1842
  exports.Field = Field;
1524
1843
  exports.FileInput = FileInput;
1525
1844
  exports.Footer = Footer;
1845
+ exports.Indicator = Indicator;
1526
1846
  exports.Input = Input;
1527
1847
  exports.InputGroup = InputGroup;
1848
+ exports.Kbd = Kbd;
1528
1849
  exports.Menu = Menu;
1529
1850
  exports.Navbar = Navbar;
1530
1851
  exports.Pagination = Pagination;
@@ -1542,5 +1863,6 @@ exports.Textarea = Textarea;
1542
1863
  exports.Tooltip = Tooltip;
1543
1864
  exports.getPaginationItems = getPaginationItems;
1544
1865
  exports.useAppShell = useAppShell;
1866
+ exports.useHotkey = useHotkey;
1545
1867
 
1546
1868
  //# sourceMappingURL=index.cjs.map