@inf-monkeys-tech/monkeys-design 0.4.55 → 0.4.56

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.
Files changed (91) hide show
  1. package/README.md +29 -5
  2. package/dist/{LandingPage-CR5KyIwR.d.mts → LandingPage-D7FF9gnM.d.mts} +3 -3
  3. package/dist/{LandingPage-CR5KyIwR.d.ts → LandingPage-D7FF9gnM.d.ts} +3 -3
  4. package/dist/components/base/index.d.mts +3 -3
  5. package/dist/components/base/index.d.ts +3 -3
  6. package/dist/components/base/index.js +7229 -2042
  7. package/dist/components/base/index.js.map +1 -1
  8. package/dist/components/base/index.mjs +7215 -2052
  9. package/dist/components/base/index.mjs.map +1 -1
  10. package/dist/components/data-explorer/index.d.mts +1 -1
  11. package/dist/components/data-explorer/index.d.ts +1 -1
  12. package/dist/components/data-explorer/index.js +166 -10
  13. package/dist/components/data-explorer/index.js.map +1 -1
  14. package/dist/components/data-explorer/index.mjs +167 -11
  15. package/dist/components/data-explorer/index.mjs.map +1 -1
  16. package/dist/components/layout/index.d.mts +1 -1
  17. package/dist/components/layout/index.d.ts +1 -1
  18. package/dist/components/layout/index.js +769 -1603
  19. package/dist/components/layout/index.js.map +1 -1
  20. package/dist/components/layout/index.mjs +772 -1607
  21. package/dist/components/layout/index.mjs.map +1 -1
  22. package/dist/components/login/index.d.mts +29 -29
  23. package/dist/components/login/index.d.ts +29 -29
  24. package/dist/components/toast/index.d.mts +2 -6
  25. package/dist/components/toast/index.d.ts +2 -6
  26. package/dist/components/toast/index.js +173 -11
  27. package/dist/components/toast/index.js.map +1 -1
  28. package/dist/components/toast/index.mjs +174 -12
  29. package/dist/components/toast/index.mjs.map +1 -1
  30. package/dist/components/toolbar/index.js +231 -21
  31. package/dist/components/toolbar/index.js.map +1 -1
  32. package/dist/components/toolbar/index.mjs +231 -21
  33. package/dist/components/toolbar/index.mjs.map +1 -1
  34. package/dist/components/workbench/index.d.mts +6 -6
  35. package/dist/components/workbench/index.d.ts +6 -6
  36. package/dist/components/workbench/index.js +2281 -1030
  37. package/dist/components/workbench/index.js.map +1 -1
  38. package/dist/components/workbench/index.mjs +2282 -1031
  39. package/dist/components/workbench/index.mjs.map +1 -1
  40. package/dist/icons/oauth/index.d.mts +5 -5
  41. package/dist/icons/oauth/index.d.ts +5 -5
  42. package/dist/index.d.mts +12 -8
  43. package/dist/index.d.ts +12 -8
  44. package/dist/index.js +7911 -4772
  45. package/dist/index.js.map +1 -1
  46. package/dist/index.mjs +7874 -4773
  47. package/dist/index.mjs.map +1 -1
  48. package/dist/locale/index.d.mts +236 -0
  49. package/dist/locale/index.d.ts +236 -0
  50. package/dist/locale/index.js +338 -0
  51. package/dist/locale/index.js.map +1 -0
  52. package/dist/locale/index.mjs +332 -0
  53. package/dist/locale/index.mjs.map +1 -0
  54. package/dist/palette/index.js +259 -2748
  55. package/dist/palette/index.js.map +1 -1
  56. package/dist/palette/index.mjs +255 -2748
  57. package/dist/palette/index.mjs.map +1 -1
  58. package/dist/provider/index.d.mts +51 -0
  59. package/dist/provider/index.d.ts +51 -0
  60. package/dist/provider/index.js +2688 -0
  61. package/dist/provider/index.js.map +1 -0
  62. package/dist/provider/index.mjs +2677 -0
  63. package/dist/provider/index.mjs.map +1 -0
  64. package/dist/styles.css +1 -0
  65. package/dist/theme-CJlW1TtA.d.mts +142 -0
  66. package/dist/{theme-CUATVszl.d.mts → theme-CplaoMqT.d.mts} +2 -2
  67. package/dist/{theme-BuvXrHFY.d.ts → theme-DPVX8CfK.d.ts} +2 -2
  68. package/dist/theme-r7GYhlCk.d.ts +142 -0
  69. package/dist/theme-system/index.d.mts +5 -92
  70. package/dist/theme-system/index.d.ts +5 -92
  71. package/dist/theme-system/index.js +295 -4329
  72. package/dist/theme-system/index.js.map +1 -1
  73. package/dist/theme-system/index.mjs +183 -4221
  74. package/dist/theme-system/index.mjs.map +1 -1
  75. package/dist/themes/artist/index.d.mts +3 -3
  76. package/dist/themes/artist/index.d.ts +3 -3
  77. package/dist/themes/bsd/index.d.mts +3 -3
  78. package/dist/themes/bsd/index.d.ts +3 -3
  79. package/dist/themes/concept/index.d.mts +2 -2
  80. package/dist/themes/concept/index.d.ts +2 -2
  81. package/dist/themes/default/index.d.mts +3 -3
  82. package/dist/themes/default/index.d.ts +3 -3
  83. package/dist/types-BkWanMMW.d.mts +159 -0
  84. package/dist/types-BkWanMMW.d.ts +159 -0
  85. package/dist/types-DpRjPpxY.d.mts +93 -0
  86. package/dist/{types-CL6yBAmi.d.mts → types-DvHvN4RJ.d.mts} +514 -10
  87. package/dist/{types-CL6yBAmi.d.ts → types-DvHvN4RJ.d.ts} +514 -10
  88. package/dist/types-vkJZUngT.d.ts +93 -0
  89. package/package.json +52 -4
  90. package/dist/theme-CPXLKeLc.d.mts +0 -101
  91. package/dist/theme-Chdxsqt1.d.ts +0 -101
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
+ var tailwindMerge = require('tailwind-merge');
4
5
  var jsxRuntime = require('react/jsx-runtime');
5
6
  var ContextMenu = require('@radix-ui/react-context-menu');
6
7
  require('react-dom');
@@ -27,10 +28,8 @@ function _interopNamespace(e) {
27
28
  var ContextMenu__namespace = /*#__PURE__*/_interopNamespace(ContextMenu);
28
29
 
29
30
  // src/components/workbench/WorkbenchResizableSidebar.tsx
30
-
31
- // src/components/base/utils.ts
32
31
  function cn(...parts) {
33
- return parts.filter(Boolean).join(" ");
32
+ return tailwindMerge.twMerge(parts.filter(Boolean).join(" "));
34
33
  }
35
34
  function hasRenderableNode(node) {
36
35
  return node !== void 0 && node !== null && typeof node !== "boolean";
@@ -380,6 +379,209 @@ var WorkbenchContentPane = react.forwardRef(
380
379
  }
381
380
  );
382
381
 
382
+ // src/locale/en-US.ts
383
+ var enUS = {
384
+ locale: "en-US",
385
+ messages: {
386
+ pagination: {
387
+ navigation: "Pagination",
388
+ first: "First",
389
+ previous: "Previous",
390
+ next: "Next",
391
+ last: "Last",
392
+ page: ({ page, pageCount }) => `Page ${page} of ${pageCount}`,
393
+ currentPage: ({ page, pageCount }) => `Page ${page} of ${pageCount}, current page`,
394
+ emptyResults: "0 results",
395
+ range: ({ start, end, total }) => `${start}-${end} of ${total}`
396
+ },
397
+ dialog: {
398
+ close: "Close dialog"
399
+ },
400
+ dropdownMenu: {
401
+ actions: "Actions"
402
+ },
403
+ loading: {
404
+ spinner: "Loading"
405
+ },
406
+ layout: {
407
+ resizePanels: "Resize panels"
408
+ },
409
+ steps: {
410
+ label: "Progress",
411
+ current: "Current",
412
+ completed: "Completed",
413
+ error: "Error",
414
+ disabled: "Disabled"
415
+ },
416
+ numberInput: {
417
+ increment: "Increase value",
418
+ decrement: "Decrease value"
419
+ },
420
+ passwordInput: {
421
+ showPassword: "Show password",
422
+ hidePassword: "Hide password"
423
+ },
424
+ multiSelect: {
425
+ placeholder: "Select options",
426
+ empty: "No options",
427
+ removeOption: ({ value }) => `Remove ${value}`
428
+ },
429
+ table: {
430
+ dragColumn: ({ columnId }) => `Drag column ${columnId}`,
431
+ resizeColumn: ({ columnId }) => `Resize column ${columnId}`,
432
+ sortColumn: ({ columnId }) => columnId ? `Sort column ${columnId}` : "Sort column",
433
+ loadingRow: "Loading table row"
434
+ },
435
+ toolbar: {
436
+ theme: {
437
+ label: "Appearance",
438
+ toggle: "Toggle theme",
439
+ auto: "Auto",
440
+ light: "Light",
441
+ dark: "Dark"
442
+ },
443
+ language: {
444
+ label: "Language",
445
+ switch: "Switch language"
446
+ }
447
+ },
448
+ toast: {
449
+ errorTitle: "Error",
450
+ warningTitle: "Warning",
451
+ defaultErrorDescription: "Something went wrong.",
452
+ defaultWarningDescription: "Please check and try again."
453
+ },
454
+ dataExplorer: {
455
+ viewTree: {
456
+ actions: "More actions",
457
+ expand: "Expand",
458
+ collapse: "Collapse",
459
+ loading: "Loading...",
460
+ empty: "No views",
461
+ error: "Unable to load views"
462
+ }
463
+ },
464
+ workbench: {
465
+ interactiveTable: {
466
+ columnActions: "Column actions",
467
+ freezeColumn: "Freeze to left",
468
+ freezeEndColumn: "Freeze to right",
469
+ unfreezeColumn: "Unfreeze from left",
470
+ unfreezeEndColumn: "Unfreeze from right",
471
+ unfreezeAllColumns: "Unfreeze all columns",
472
+ resetColumnWidth: "Reset column width",
473
+ frozenColumnTitle: "Frozen column"
474
+ }
475
+ }
476
+ }
477
+ };
478
+
479
+ // src/locale/resolve-locale.ts
480
+ function mergeMonkeysLocaleMessages(base, override) {
481
+ return base;
482
+ }
483
+ var defaultMonkeysLocale = {
484
+ locale: enUS.locale,
485
+ messages: mergeMonkeysLocaleMessages(
486
+ enUS.messages
487
+ )
488
+ };
489
+
490
+ // src/provider/context.ts
491
+ var EMPTY_ENVIRONMENT = Object.freeze({});
492
+ var EMPTY_PORTAL = Object.freeze({});
493
+ var MONKEYS_PROVIDER_CONTEXTS_KEY = /* @__PURE__ */ Symbol.for(
494
+ "@inf-monkeys-tech/monkeys-design/provider-context@1"
495
+ );
496
+ function createMonkeysProviderContexts() {
497
+ return Object.freeze({
498
+ locale: react.createContext({
499
+ ...defaultMonkeysLocale,
500
+ provided: false
501
+ }),
502
+ theme: react.createContext({
503
+ provided: false
504
+ }),
505
+ direction: react.createContext({
506
+ provided: false
507
+ }),
508
+ environment: react.createContext({
509
+ provided: false,
510
+ environment: EMPTY_ENVIRONMENT,
511
+ portal: EMPTY_PORTAL
512
+ })
513
+ });
514
+ }
515
+ function getMonkeysProviderContexts() {
516
+ const host = globalThis;
517
+ const existing = host[MONKEYS_PROVIDER_CONTEXTS_KEY];
518
+ if (existing) return existing;
519
+ const contexts = createMonkeysProviderContexts();
520
+ Object.defineProperty(host, MONKEYS_PROVIDER_CONTEXTS_KEY, {
521
+ value: contexts,
522
+ enumerable: false,
523
+ configurable: false,
524
+ writable: false
525
+ });
526
+ return contexts;
527
+ }
528
+ var providerContexts = getMonkeysProviderContexts();
529
+ var MonkeysLocaleContext = providerContexts.locale;
530
+ var MonkeysThemeContext = providerContexts.theme;
531
+ var MonkeysDirectionContext = providerContexts.direction;
532
+ var MonkeysEnvironmentContext = providerContexts.environment;
533
+ function mergeAppearance(inherited, explicit) {
534
+ if (explicit === void 0) return inherited;
535
+ if (inherited === void 0) return explicit;
536
+ return {
537
+ ...inherited,
538
+ ...explicit,
539
+ slots: inherited.slots || explicit.slots ? { ...inherited.slots, ...explicit.slots } : void 0,
540
+ styles: inherited.styles || explicit.styles ? { ...inherited.styles, ...explicit.styles } : void 0
541
+ };
542
+ }
543
+ function useMonkeysLocaleMessages() {
544
+ return react.useContext(MonkeysLocaleContext).messages;
545
+ }
546
+ function useMonkeysBaseAppearance(explicit) {
547
+ const inherited = react.useContext(MonkeysThemeContext).baseAppearance;
548
+ return react.useMemo(
549
+ () => mergeAppearance(inherited, explicit),
550
+ [explicit, inherited]
551
+ );
552
+ }
553
+ function useMonkeysDirection() {
554
+ return react.useContext(MonkeysDirectionContext).direction;
555
+ }
556
+ function useMonkeysEnvironment() {
557
+ return react.useContext(MonkeysEnvironmentContext).environment;
558
+ }
559
+ function useMonkeysPortalOptions() {
560
+ return react.useContext(MonkeysEnvironmentContext).portal;
561
+ }
562
+ function useMonkeysComponentAttributes() {
563
+ const locale = react.useContext(MonkeysLocaleContext);
564
+ const theme = react.useContext(MonkeysThemeContext);
565
+ const direction = react.useContext(MonkeysDirectionContext);
566
+ const providerActive = locale.provided || theme.provided || direction.provided;
567
+ return react.useMemo(
568
+ () => providerActive ? {
569
+ dir: direction.direction,
570
+ "data-monkeys-direction": direction.direction,
571
+ "data-monkeys-locale": locale.locale,
572
+ "data-monkeys-theme": theme.resolvedTheme?.id,
573
+ "data-monkeys-theme-mode": theme.resolvedTheme?.tokens.mode
574
+ } : {},
575
+ [
576
+ direction.direction,
577
+ locale.locale,
578
+ providerActive,
579
+ theme.resolvedTheme?.id,
580
+ theme.resolvedTheme?.tokens.mode
581
+ ]
582
+ );
583
+ }
584
+
383
585
  // src/components/base/theme.ts
384
586
  var emptyStyles = {};
385
587
  var motionBase = "motion-safe:transition motion-safe:duration-300 motion-safe:ease-out";
@@ -411,9 +613,9 @@ var baseSlots = {
411
613
  ),
412
614
  buttonDefault: "border-border bg-background text-foreground hover:bg-accent/60",
413
615
  buttonPrimary: "border-primary/20 bg-primary/10 text-primary hover:bg-primary/15",
414
- buttonSuccess: "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 hover:bg-emerald-500/15",
616
+ buttonSuccess: "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 hover:bg-emerald-500/15",
415
617
  buttonWarning: "border-amber-500/30 bg-amber-500/10 text-amber-700 hover:bg-amber-500/15",
416
- buttonDanger: "border-destructive/20 bg-destructive/10 text-destructive hover:bg-destructive/15",
618
+ buttonDanger: "border-destructive/20 bg-destructive/10 text-destructive-text hover:bg-destructive/15",
417
619
  buttonMuted: "border-border/60 bg-muted/45 text-muted-foreground hover:bg-muted/70 hover:text-foreground",
418
620
  buttonActive: "border-primary/35 bg-primary/10 text-primary",
419
621
  buttonDisabled: "!cursor-not-allowed opacity-60",
@@ -428,10 +630,101 @@ var baseSlots = {
428
630
  badgePrimary: "border-primary/30 bg-primary/10 text-primary",
429
631
  badgeSuccess: "border-emerald-500/30 bg-emerald-500/10 text-emerald-700",
430
632
  badgeWarning: "border-amber-500/30 bg-amber-500/10 text-amber-700",
431
- badgeDanger: "border-destructive/30 bg-destructive/10 text-destructive",
633
+ badgeDanger: "border-destructive/30 bg-destructive/10 text-destructive-text",
432
634
  badgeMuted: "border-border/60 bg-muted text-muted-foreground",
433
635
  badgeIcon: "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center",
434
636
  badgeLabel: "min-w-0 truncate",
637
+ textRoot: "min-w-0 break-words leading-6",
638
+ textSizeXs: "text-xs",
639
+ textSizeSm: "text-sm",
640
+ textSizeMd: "text-base",
641
+ textSizeLg: "text-lg",
642
+ textSizeXl: "text-xl",
643
+ typographyToneDefault: "text-foreground",
644
+ typographyToneMuted: "text-muted-foreground",
645
+ typographyTonePrimary: "text-primary",
646
+ typographyToneSuccess: "text-emerald-700 dark:text-emerald-400",
647
+ typographyToneWarning: "text-amber-700 dark:text-amber-400",
648
+ typographyToneDanger: "text-destructive-text",
649
+ typographyToneInherit: "text-inherit",
650
+ headingRoot: "min-w-0 break-words font-semibold tracking-tight",
651
+ headingSizeXs: "text-sm leading-5",
652
+ headingSizeSm: "text-base leading-6",
653
+ headingSizeMd: "text-lg leading-7",
654
+ headingSizeLg: "text-xl leading-7",
655
+ headingSizeXl: "text-2xl leading-8",
656
+ headingSize2xl: "text-3xl leading-9",
657
+ linkRoot: "inline break-words underline decoration-current/40 underline-offset-4 hover:decoration-current focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
658
+ codeInline: "rounded border border-border/70 bg-muted/60 px-1.5 py-0.5 font-mono text-[0.875em] leading-[1.45] text-foreground",
659
+ codeBlock: "m-0 max-w-full overflow-x-auto rounded-md border border-border/70 bg-muted/60 p-4 text-foreground",
660
+ codeContent: "font-mono text-sm leading-6",
661
+ kbdRoot: "inline-flex min-h-5 items-center rounded border border-border bg-muted/70 px-1.5 font-mono text-[0.75em] font-medium leading-5 text-foreground shadow-[inset_0_-1px_0_hsl(var(--monkeys-color-border))]",
662
+ listRoot: "m-0 min-w-0 list-outside break-words ps-5 text-foreground",
663
+ listSpacingCompact: "[&>li+li]:mt-1",
664
+ listSpacingDefault: "[&>li+li]:mt-2",
665
+ listSpacingRelaxed: "[&>li+li]:mt-3",
666
+ listMarkerNone: "list-none ps-0",
667
+ listMarkerDisc: "list-disc",
668
+ listMarkerCircle: "list-[circle]",
669
+ listMarkerSquare: "list-[square]",
670
+ listMarkerDecimal: "list-decimal",
671
+ listMarkerLowerAlpha: "list-[lower-alpha]",
672
+ listMarkerUpperAlpha: "list-[upper-alpha]",
673
+ listItem: "min-w-0 ps-1 leading-6 marker:text-muted-foreground",
674
+ stackRoot: "flex min-w-0 flex-col",
675
+ inlineRoot: "flex min-w-0 flex-row",
676
+ gridRoot: "grid min-w-0",
677
+ containerRoot: "mx-auto w-full min-w-0",
678
+ aspectRatioRoot: "relative min-w-0 overflow-hidden [&>*]:h-full [&>*]:w-full",
679
+ spinnerRoot: "inline-flex shrink-0 items-center justify-center text-current align-middle",
680
+ spinnerIndicator: "h-5 w-5 rounded-full border-2 border-current border-r-transparent motion-safe:animate-spin motion-reduce:animate-none",
681
+ visuallyHiddenRoot: "sr-only",
682
+ visuallyHiddenFocusable: "focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[1000] focus:rounded-md focus:bg-background focus:px-4 focus:py-2 focus:text-foreground focus:shadow-lg focus:outline-none focus:ring-2 focus:ring-ring focus-within:not-sr-only focus-within:fixed focus-within:left-4 focus-within:top-4 focus-within:z-[1000] focus-within:rounded-md focus-within:bg-background focus-within:px-4 focus-within:py-2 focus-within:text-foreground focus-within:shadow-lg focus-within:ring-2 focus-within:ring-ring",
683
+ fieldsetRoot: "min-w-0 border-0 p-0 text-foreground",
684
+ fieldsetLegend: "min-w-0 text-sm font-semibold leading-6 text-foreground",
685
+ fieldsetDescription: "mt-1 text-sm leading-5 text-muted-foreground",
686
+ fieldsetError: "mt-1 text-sm leading-5 text-destructive-text",
687
+ fieldsetContent: "mt-3 grid min-w-0 gap-3",
688
+ stepsRoot: "m-0 min-w-0 list-none p-0 text-foreground",
689
+ stepsHorizontal: "flex w-full max-w-full items-start overflow-x-auto pb-2",
690
+ stepsVertical: "grid",
691
+ stepsItem: "relative min-w-0",
692
+ stepsItemHorizontal: "flex min-w-52 flex-1 items-start",
693
+ stepsItemVertical: "pb-6 last:pb-0",
694
+ stepsTrigger: "flex min-w-0 flex-1 items-start gap-3 rounded-md border-0 bg-transparent p-1 text-start text-inherit",
695
+ stepsTriggerInteractive: "cursor-pointer hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
696
+ stepsTriggerDisabled: "!cursor-not-allowed opacity-60",
697
+ stepsIndicator: "relative z-[1] inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-xs font-semibold",
698
+ stepsIndicatorPending: "border-border bg-background text-muted-foreground",
699
+ stepsIndicatorCurrent: "border-primary/50 bg-primary/10 text-primary",
700
+ stepsIndicatorCompleted: "border-primary bg-primary text-primary-foreground",
701
+ stepsIndicatorError: "border-destructive bg-destructive text-destructive-foreground",
702
+ stepsContent: "grid min-w-0 gap-1 pt-0.5",
703
+ stepsLabel: "min-w-0 break-words text-sm font-medium leading-5",
704
+ stepsDescription: "min-w-0 break-words text-sm leading-5 text-muted-foreground",
705
+ stepsStatus: "sr-only",
706
+ stepsConnector: "shrink-0 bg-border",
707
+ stepsConnectorHorizontal: "mt-3.5 h-px w-8",
708
+ stepsConnectorVertical: "absolute bottom-0 top-8 start-3.5 w-px -translate-x-1/2",
709
+ stepsConnectorCompleted: "bg-primary/60",
710
+ stepsConnectorError: "bg-destructive/60",
711
+ scrollAreaViewport: "min-h-0 min-w-0",
712
+ numberInputControl: "tabular-nums",
713
+ numberInputStepControls: "me-1 flex shrink-0 self-stretch overflow-hidden border-s border-border",
714
+ numberInputStepButton: "flex min-h-6 w-7 cursor-pointer items-center justify-center border-0 bg-transparent px-1 text-xs leading-none text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:z-[1] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:!cursor-not-allowed disabled:opacity-40",
715
+ passwordInputControl: "pe-2",
716
+ passwordInputToggle: "me-1 inline-flex min-h-7 shrink-0 cursor-pointer items-center justify-center rounded px-2 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:!cursor-not-allowed disabled:opacity-40",
717
+ inputGroupRoot: cn(
718
+ "relative flex min-w-0 items-stretch overflow-hidden rounded-md border border-border bg-background text-foreground focus-within:border-primary/50 focus-within:ring-2 focus-within:ring-ring/30",
719
+ motionBase
720
+ ),
721
+ inputGroupInvalid: "border-destructive/55 focus-within:border-destructive/70 focus-within:ring-destructive/25",
722
+ inputGroupDisabled: "!cursor-not-allowed bg-muted/35",
723
+ inputGroupContent: "flex min-w-0 flex-1 items-stretch [&>*]:min-w-0",
724
+ inputGroupStartElement: "inline-flex shrink-0 items-center justify-center ps-3 pe-1 text-foreground/75",
725
+ inputGroupEndElement: "inline-flex shrink-0 items-center justify-center ps-1 pe-3 text-foreground/75",
726
+ inputGroupStartAddon: "inline-flex max-w-[min(40%,16rem)] shrink-0 items-center overflow-hidden border-e border-border bg-muted/60 px-3 text-sm text-foreground/75 text-ellipsis whitespace-nowrap [&>*]:min-w-0",
727
+ inputGroupEndAddon: "inline-flex max-w-[min(40%,16rem)] shrink-0 items-center overflow-hidden border-s border-border bg-muted/60 px-3 text-sm text-foreground/75 text-ellipsis whitespace-nowrap [&>*]:min-w-0",
435
728
  panelRoot: cn(
436
729
  "group relative flex min-w-0 flex-col overflow-hidden rounded-lg border border-border/70 bg-background",
437
730
  motionInteractive
@@ -454,11 +747,11 @@ var baseSlots = {
454
747
  stateTitle: "text-sm font-semibold text-foreground",
455
748
  stateDescription: "mt-2 max-w-md text-sm leading-6 text-muted-foreground",
456
749
  stateActions: "mt-5 flex flex-wrap items-center justify-center gap-2",
457
- loadingSpinner: "h-5 w-5 animate-spin",
750
+ loadingSpinner: "h-5 w-5 motion-safe:animate-spin motion-reduce:animate-none",
458
751
  fieldRoot: "grid min-w-0 gap-2",
459
752
  fieldLabelRow: "flex min-w-0 items-center justify-between gap-3",
460
753
  fieldLabel: "min-w-0 text-sm font-medium leading-none text-foreground",
461
- fieldRequired: "text-destructive",
754
+ fieldRequired: "text-destructive-text",
462
755
  fieldDescription: "text-sm leading-5 text-muted-foreground",
463
756
  fieldMessage: "text-sm leading-5 text-muted-foreground",
464
757
  fieldControl: "min-w-0",
@@ -538,9 +831,9 @@ var baseSlots = {
538
831
  dialogTrigger: "",
539
832
  dialogTriggerDisabled: "!cursor-not-allowed opacity-60",
540
833
  dialogOverlay: "fixed inset-0 z-50 bg-background/70 backdrop-blur-sm motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
541
- dialogContent: "fixed inset-0 z-50 flex min-h-0 items-center justify-center p-4",
834
+ dialogContent: "pointer-events-none fixed inset-0 z-50 flex min-h-0 items-center justify-center p-4",
542
835
  dialogPanel: cn(
543
- "relative flex max-h-[min(85vh,720px)] w-full max-w-lg min-w-0 flex-col overflow-hidden rounded-lg border border-border/70 bg-background text-foreground shadow-xl",
836
+ "pointer-events-auto relative flex max-h-[min(85vh,720px)] w-full max-w-lg min-w-0 flex-col overflow-hidden rounded-lg border border-border/70 bg-background text-foreground shadow-xl",
544
837
  "motion-safe:animate-in motion-safe:fade-in motion-safe:zoom-in-95 motion-safe:duration-300 motion-safe:ease-out"
545
838
  ),
546
839
  dialogHeader: "grid min-w-0 gap-1 border-b border-border/60 px-5 py-4",
@@ -555,17 +848,17 @@ var baseSlots = {
555
848
  dropdownRoot: "relative inline-flex min-w-0",
556
849
  dropdownTrigger: "",
557
850
  dropdownTriggerDisabled: "!cursor-not-allowed opacity-60",
558
- dropdownMenu: "absolute left-0 top-[calc(100%+0.375rem)] z-50 min-w-48 overflow-hidden rounded-md border border-border bg-background p-1 text-sm text-foreground shadow-lg motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
851
+ dropdownMenu: "z-50 min-w-48 overflow-hidden rounded-md border border-border bg-background p-1 text-sm text-foreground shadow-lg motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
559
852
  dropdownMenuTop: "bottom-[calc(100%+0.375rem)] top-auto",
560
853
  dropdownMenuEnd: "left-auto right-0",
561
854
  dropdownLabel: "px-2.5 py-1.5 text-xs font-semibold uppercase tracking-[0.12em] text-muted-foreground",
562
855
  dropdownSeparator: "my-1 h-px bg-border/70",
563
856
  dropdownItem: cn(
564
- "flex min-w-0 cursor-pointer items-center gap-2 rounded-sm px-2.5 py-2 text-left text-sm text-foreground hover:bg-accent/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
857
+ "flex min-w-0 cursor-pointer items-center gap-2 rounded-sm px-2.5 py-2 text-left text-sm text-foreground hover:bg-accent/60 focus:bg-accent/60 data-[highlighted]:bg-accent/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
565
858
  motionInteractive
566
859
  ),
567
- dropdownItemDanger: "text-destructive hover:bg-destructive/10",
568
- dropdownItemDisabled: "!cursor-not-allowed opacity-50 hover:bg-transparent",
860
+ dropdownItemDanger: "text-destructive-text hover:bg-destructive/10 focus:bg-destructive/10 data-[highlighted]:bg-destructive/10",
861
+ dropdownItemDisabled: "!cursor-not-allowed opacity-50 hover:bg-transparent focus:bg-transparent data-[highlighted]:bg-transparent",
569
862
  dropdownItemIcon: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
570
863
  dropdownItemContent: "grid min-w-0 flex-1 gap-0.5",
571
864
  dropdownItemLabel: "min-w-0 truncate",
@@ -573,7 +866,7 @@ var baseSlots = {
573
866
  dropdownItemShortcut: "ml-3 shrink-0 text-xs font-medium text-muted-foreground",
574
867
  tooltipRoot: "relative inline-flex min-w-0",
575
868
  tooltipTrigger: "inline-flex min-w-0",
576
- tooltipContent: "pointer-events-none absolute z-50 max-w-xs rounded-md border border-border bg-popover px-2.5 py-1.5 text-xs leading-5 text-popover-foreground shadow-lg motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
869
+ tooltipContent: "pointer-events-none z-50 max-w-xs rounded-md border border-border bg-popover px-2.5 py-1.5 text-xs leading-5 text-popover-foreground shadow-lg motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
577
870
  noticeBase: cn(
578
871
  "flex min-w-0 gap-3 rounded-lg border px-4 py-3 text-sm",
579
872
  motionBase,
@@ -583,7 +876,7 @@ var baseSlots = {
583
876
  noticePrimary: "border-primary/25 bg-primary/10 text-primary",
584
877
  noticeSuccess: "border-emerald-500/30 bg-emerald-500/10 text-emerald-700",
585
878
  noticeWarning: "border-amber-500/30 bg-amber-500/10 text-amber-700",
586
- noticeDanger: "border-destructive/30 bg-destructive/10 text-destructive",
879
+ noticeDanger: "border-destructive/30 bg-destructive/10 text-destructive-text",
587
880
  noticeMuted: "border-border/60 bg-muted/35 text-muted-foreground",
588
881
  noticeIcon: "mt-0.5 inline-flex h-4 w-4 shrink-0 items-center justify-center motion-safe:animate-in motion-safe:fade-in",
589
882
  noticeTitle: "font-semibold leading-5",
@@ -603,12 +896,12 @@ var baseSlots = {
603
896
  motionBase
604
897
  ),
605
898
  tabsTrigger: cn(
606
- "inline-flex min-w-0 cursor-pointer items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground hover:bg-background/70 hover:text-foreground focus-visible:outline-none",
899
+ "inline-flex min-w-0 cursor-pointer items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground hover:bg-background/70 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-offset-1 motion-reduce:transition-none",
607
900
  motionInteractive
608
901
  ),
609
902
  tabsTriggerActive: "bg-background text-foreground shadow-sm",
610
903
  tabsTriggerDisabled: "!cursor-not-allowed opacity-50 hover:bg-transparent",
611
- tabsPanel: "min-w-0 rounded-lg border border-border/70 bg-background p-4 text-sm text-foreground motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
904
+ tabsPanel: "min-w-0 rounded-lg border border-border/70 bg-background p-4 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out motion-reduce:transition-none",
612
905
  segmentedRoot: cn(
613
906
  "inline-flex min-w-0 items-center gap-1 rounded-lg border border-border/70 bg-muted/30 p-1",
614
907
  motionBase
@@ -628,7 +921,7 @@ var baseSlots = {
628
921
  skeletonRoot: "relative overflow-hidden rounded-md bg-muted/70",
629
922
  avatarRoot: "relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border bg-muted text-sm font-semibold text-muted-foreground motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
630
923
  avatarImage: "h-full w-full object-cover",
631
- avatarFallback: "flex h-full w-full items-center justify-center bg-muted text-muted-foreground",
924
+ avatarFallback: "flex h-full w-full items-center justify-center bg-muted text-foreground",
632
925
  avatarStatus: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-muted-foreground motion-safe:animate-pulse",
633
926
  avatarText: "min-w-0 truncate text-sm font-medium text-foreground",
634
927
  toolbarRoot: cn(
@@ -648,22 +941,24 @@ var baseSlots = {
648
941
  breadcrumbSeparator: "shrink-0 text-muted-foreground/70",
649
942
  paginationRoot: "flex min-w-0 flex-wrap items-center justify-between gap-3 text-sm",
650
943
  paginationInfo: "min-w-0 text-muted-foreground",
651
- paginationControls: "flex shrink-0 items-center gap-1.5",
652
- paginationButton: "inline-flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-md border border-border bg-background px-2.5 text-sm font-medium text-foreground hover:bg-accent/60 disabled:!cursor-not-allowed disabled:opacity-50 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
944
+ paginationControls: "flex min-w-0 flex-wrap items-center justify-end gap-1.5",
945
+ paginationButton: "inline-flex h-8 min-w-8 cursor-pointer items-center justify-center whitespace-nowrap rounded-md border border-border bg-background px-2.5 text-sm font-medium text-foreground hover:bg-accent/60 disabled:!cursor-not-allowed disabled:opacity-50 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
653
946
  paginationButtonDisabled: "!cursor-not-allowed opacity-50",
654
- paginationPage: "inline-flex h-8 min-w-8 items-center justify-center rounded-md bg-muted/50 px-2.5 text-sm font-medium text-foreground",
947
+ paginationPage: "inline-flex h-8 min-w-8 cursor-default items-center justify-center rounded-md bg-muted/50 px-2.5 text-sm font-medium text-foreground hover:bg-muted/50",
948
+ paginationEllipsis: "inline-flex h-8 min-w-6 items-center justify-center px-1 text-sm text-muted-foreground",
655
949
  descriptionListRoot: "grid min-w-0 gap-3 text-sm",
656
950
  descriptionListItem: "grid min-w-0 gap-1 rounded-md border border-border/60 bg-background px-3 py-2 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out hover:shadow-sm",
657
951
  descriptionListTerm: "min-w-0 truncate text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground",
658
952
  descriptionListValue: "min-w-0 text-sm leading-6 text-foreground",
659
953
  accordionRoot: "grid min-w-0 gap-2",
660
- accordionItem: "overflow-hidden rounded-lg border border-border/70 bg-background motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
661
- accordionTrigger: "flex w-full min-w-0 cursor-pointer items-center justify-between gap-3 px-4 py-3 text-left text-sm font-medium text-foreground hover:bg-muted/40 disabled:!cursor-not-allowed disabled:opacity-50 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out",
954
+ accordionItem: "overflow-hidden rounded-lg border border-border/70 bg-background motion-safe:transition motion-safe:duration-300 motion-safe:ease-out motion-reduce:transition-none",
955
+ accordionTrigger: "flex w-full min-w-0 cursor-pointer items-center justify-between gap-3 px-4 py-3 text-start text-sm font-medium text-foreground hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:!cursor-not-allowed disabled:opacity-50 motion-safe:transition motion-safe:duration-300 motion-safe:ease-out motion-reduce:transition-none",
662
956
  accordionTriggerIcon: cn(
663
957
  "h-2 w-2 shrink-0 rotate-45 border-b border-r border-current text-muted-foreground",
664
- motionTransform
958
+ motionTransform,
959
+ "motion-reduce:transition-none"
665
960
  ),
666
- accordionPanel: "border-t border-border/60 px-4 py-3 text-sm leading-6 text-muted-foreground motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out",
961
+ accordionPanel: "border-t border-border/60 px-4 py-3 text-sm leading-6 text-muted-foreground motion-safe:animate-in motion-safe:fade-in motion-safe:duration-300 motion-safe:ease-out motion-reduce:animate-none",
667
962
  menuTrigger: "inline-flex min-w-0",
668
963
  menuContent: "z-50 min-w-44 overflow-hidden rounded-md border border-border bg-background p-1 text-sm text-foreground shadow-lg outline-none motion-safe:animate-in motion-safe:fade-in motion-safe:zoom-in-95 motion-safe:duration-300 motion-safe:ease-out",
669
964
  menuLabel: "px-2 py-1.5 text-xs font-medium text-muted-foreground",
@@ -676,7 +971,7 @@ var baseSlots = {
676
971
  menuItemPrimary: "text-primary focus:text-primary data-[highlighted]:text-primary",
677
972
  menuItemSuccess: "text-emerald-700 focus:text-emerald-700 data-[highlighted]:text-emerald-700",
678
973
  menuItemWarning: "text-amber-700 focus:text-amber-700 data-[highlighted]:text-amber-700",
679
- menuItemDanger: "text-destructive focus:text-destructive data-[highlighted]:text-destructive",
974
+ menuItemDanger: "text-destructive-text focus:text-destructive-text data-[highlighted]:text-destructive-text",
680
975
  menuItemMuted: "text-muted-foreground focus:text-foreground data-[highlighted]:text-foreground",
681
976
  menuItemDisabled: "!cursor-not-allowed opacity-50 data-[disabled]:pointer-events-none",
682
977
  menuItemIcon: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
@@ -707,13 +1002,13 @@ var baseSlots = {
707
1002
  tableBody: "[&_tr:last-child>*]:border-b-0",
708
1003
  tableFooter: "bg-muted/30 font-medium [&_tr>*]:border-t [&_tr>*]:border-border/70",
709
1004
  tableFooterBar: cn(
710
- "flex min-w-0 flex-wrap items-center justify-between gap-3 rounded-lg border border-border/70 bg-muted/20 px-4 py-3 text-sm text-muted-foreground shadow-none",
1005
+ "flex min-w-0 flex-wrap items-center justify-between gap-3 rounded-lg border border-border/70 bg-muted/20 px-4 py-3 text-sm text-foreground shadow-none",
711
1006
  motionBase
712
1007
  ),
713
1008
  tableFooterBarAttached: "-mt-px rounded-t-none border-t border-border/70 shadow-none",
714
1009
  tableFooterBarLeading: "flex min-w-0 items-center gap-2",
715
1010
  tableFooterBarContent: "min-w-0 flex-1",
716
- tableFooterBarActions: "ml-auto flex shrink-0 flex-wrap items-center gap-2",
1011
+ tableFooterBarActions: "ms-auto flex shrink-0 flex-wrap items-center gap-2",
717
1012
  tableSplitRoot: "grid w-full min-w-0 grid-cols-[minmax(0,1fr)] grid-rows-[auto_minmax(0,1fr)_auto] caption-bottom border-separate border-spacing-0 text-sm text-foreground",
718
1013
  tableSplitHeader: "block w-full min-w-0 shrink-0 overflow-x-hidden overflow-y-hidden bg-transparent",
719
1014
  tableSplitBody: cn(
@@ -723,7 +1018,7 @@ var baseSlots = {
723
1018
  tableSplitFooter: "block w-full min-w-0 shrink-0 overflow-x-hidden overflow-y-hidden",
724
1019
  tableSplitRow: "grid w-max min-w-full [grid-template-columns:var(--base-table-column-template)]",
725
1020
  tableSplitHead: "flex min-w-0 overflow-hidden",
726
- tableSplitCell: "block min-w-0 overflow-hidden",
1021
+ tableSplitCell: "block min-w-0 overflow-hidden [overflow-wrap:anywhere]",
727
1022
  tableRow: cn(
728
1023
  "[&>*]:border-b [&>*]:border-border/60 data-[state=selected]:bg-primary/5 data-[state=selected]:[&>*]:bg-primary/5",
729
1024
  motionBase
@@ -752,8 +1047,11 @@ var baseSlots = {
752
1047
  "inline-flex h-5 w-4 shrink-0 cursor-grab items-center justify-center rounded-sm text-muted-foreground hover:bg-muted active:cursor-grabbing focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:!cursor-not-allowed disabled:opacity-50",
753
1048
  motionBase
754
1049
  ),
755
- tableHeadResizeHandle: "absolute right-0 top-1/2 h-7 w-2 -translate-y-1/2 cursor-col-resize rounded-sm after:absolute after:left-1/2 after:top-1/2 after:h-5 after:w-px after:-translate-x-1/2 after:-translate-y-1/2 after:bg-border hover:after:bg-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:!cursor-not-allowed disabled:opacity-50",
756
- tableCell: "px-3 py-2 align-middle text-sm text-foreground",
1050
+ tableHeadResizeHandle: cn(
1051
+ "absolute end-0 top-1/2 h-7 w-2 -translate-y-1/2 cursor-col-resize touch-none rounded-sm after:absolute after:start-1/2 after:top-1/2 after:h-5 after:w-px after:-translate-x-1/2 after:-translate-y-1/2 after:bg-border hover:after:bg-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:!cursor-not-allowed disabled:opacity-50",
1052
+ motionBase
1053
+ ),
1054
+ tableCell: "min-w-0 px-3 py-2 align-middle text-sm text-foreground [overflow-wrap:anywhere]",
757
1055
  tableCellAlignCenter: "text-center",
758
1056
  tableCellAlignRight: "text-right",
759
1057
  tableEmptyRow: "[&>*]:border-b [&>*]:border-border/60",
@@ -1728,13 +2026,31 @@ function getBaseMenuItemToneClassName(theme, tone = "default") {
1728
2026
  tone === "muted" && theme.slots.menuItemMuted
1729
2027
  );
1730
2028
  }
2029
+ var buttonSizeClassNames = {
2030
+ sm: "h-8 px-2.5 text-xs",
2031
+ md: "h-9 px-3 text-sm",
2032
+ lg: "h-10 px-3.5 text-base"
2033
+ };
2034
+ var iconOnlySizeClassNames = {
2035
+ sm: "h-8 w-8 px-0",
2036
+ md: "h-9 w-9 px-0",
2037
+ lg: "h-10 w-10 px-0"
2038
+ };
2039
+ var iconSizeClassNames = {
2040
+ sm: "h-3.5 w-3.5",
2041
+ md: "h-4 w-4",
2042
+ lg: "h-5 w-5"
2043
+ };
2044
+ function nonEmptyText(value) {
2045
+ return typeof value === "string" && value.trim() ? value : void 0;
2046
+ }
1731
2047
  function LoadingIcon() {
1732
2048
  return /* @__PURE__ */ jsxRuntime.jsxs(
1733
2049
  "svg",
1734
2050
  {
1735
2051
  "aria-hidden": "true",
1736
2052
  viewBox: "0 0 24 24",
1737
- className: "h-4 w-4 animate-spin",
2053
+ className: "h-full w-full motion-safe:animate-spin motion-reduce:animate-none",
1738
2054
  fill: "none",
1739
2055
  children: [
1740
2056
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1770,6 +2086,7 @@ var BaseButton = react.forwardRef(
1770
2086
  title,
1771
2087
  ariaLabel,
1772
2088
  tone,
2089
+ size,
1773
2090
  active = false,
1774
2091
  iconOnly = false,
1775
2092
  disabled = false,
@@ -1783,11 +2100,42 @@ var BaseButton = react.forwardRef(
1783
2100
  "aria-label": nativeAriaLabel,
1784
2101
  ...buttonProps
1785
2102
  }, ref) {
1786
- const theme = resolveBaseAppearance(appearance);
2103
+ for (const [name, value] of [
2104
+ ["active", active],
2105
+ ["iconOnly", iconOnly],
2106
+ ["disabled", disabled],
2107
+ ["loading", loading],
2108
+ ["stopPropagation", stopPropagation]
2109
+ ]) {
2110
+ if (typeof value !== "boolean") {
2111
+ throw new TypeError(`BaseButton ${name} must be a boolean.`);
2112
+ }
2113
+ }
2114
+ if (size !== void 0 && size !== "sm" && size !== "md" && size !== "lg") {
2115
+ throw new TypeError('BaseButton size must be "sm", "md", or "lg".');
2116
+ }
2117
+ if (tone !== void 0 && tone !== "default" && tone !== "primary" && tone !== "success" && tone !== "warning" && tone !== "danger" && tone !== "muted") {
2118
+ throw new TypeError(
2119
+ 'BaseButton tone must be "default", "primary", "success", "warning", "danger", or "muted".'
2120
+ );
2121
+ }
2122
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2123
+ const componentAttributes = useMonkeysComponentAttributes();
2124
+ const theme = resolveBaseAppearance(resolvedAppearance);
1787
2125
  const resolvedLabel = children ?? label;
1788
- const labelText = typeof resolvedLabel === "string" ? resolvedLabel : void 0;
1789
- const resolvedAriaLabel = ariaLabel ?? nativeAriaLabel ?? labelText ?? title ?? (iconOnly ? "Action" : void 0);
2126
+ const hasLabel = hasRenderableNode(resolvedLabel) && (typeof resolvedLabel !== "string" || Boolean(resolvedLabel.trim()));
2127
+ const explicitAriaLabel = nonEmptyText(ariaLabel) ?? nonEmptyText(nativeAriaLabel);
2128
+ const labelText = typeof resolvedLabel === "string" ? nonEmptyText(resolvedLabel) : void 0;
2129
+ const resolvedTitle = nonEmptyText(title);
2130
+ if (iconOnly && !hasLabel && !explicitAriaLabel && !resolvedTitle) {
2131
+ throw new TypeError(
2132
+ "BaseButton iconOnly requires ariaLabel, aria-label, title, or a renderable label."
2133
+ );
2134
+ }
2135
+ const resolvedAriaLabel = explicitAriaLabel ?? labelText ?? resolvedTitle;
1790
2136
  const resolvedDisabled = disabled || loading;
2137
+ const resolvedTone = tone ?? "default";
2138
+ const state = loading ? "loading" : disabled ? "disabled" : active ? "active" : "idle";
1791
2139
  const handleClick = (event) => {
1792
2140
  if (stopPropagation) {
1793
2141
  event.stopPropagation();
@@ -1798,6 +2146,7 @@ var BaseButton = react.forwardRef(
1798
2146
  return /* @__PURE__ */ jsxRuntime.jsxs(
1799
2147
  "button",
1800
2148
  {
2149
+ ...componentAttributes,
1801
2150
  ...buttonProps,
1802
2151
  ref,
1803
2152
  type,
@@ -1806,9 +2155,20 @@ var BaseButton = react.forwardRef(
1806
2155
  "aria-pressed": active || void 0,
1807
2156
  "aria-busy": loading || void 0,
1808
2157
  disabled: resolvedDisabled,
2158
+ "data-monkeys-component": "button",
2159
+ "data-slot": "root",
2160
+ "data-state": state,
2161
+ "data-tone": resolvedTone,
2162
+ "data-size": size,
2163
+ "data-active": active || void 0,
2164
+ "data-loading": loading || void 0,
2165
+ "data-disabled": resolvedDisabled || void 0,
2166
+ "data-icon-only": iconOnly || void 0,
1809
2167
  className: cn(
1810
2168
  theme.slots.buttonBase,
1811
2169
  iconOnly && theme.slots.buttonIconOnly,
2170
+ size && buttonSizeClassNames[size],
2171
+ iconOnly && size && iconOnlySizeClassNames[size],
1812
2172
  getBaseButtonToneClassName(theme, tone, active),
1813
2173
  resolvedDisabled && theme.slots.buttonDisabled,
1814
2174
  classNames?.root,
@@ -1822,23 +2182,96 @@ var BaseButton = react.forwardRef(
1822
2182
  },
1823
2183
  onClick: handleClick,
1824
2184
  children: [
1825
- loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.buttonIcon, classNames?.icon), children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIcon, {}) }) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.buttonIcon, classNames?.icon), children: icon }) : null,
1826
- iconOnly ? hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: resolvedLabel }) : null : hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.buttonLabel, classNames?.label), children: resolvedLabel }) : null,
1827
- !loading && endIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.buttonIcon, classNames?.icon), children: endIcon }) : null
2185
+ loading ? /* @__PURE__ */ jsxRuntime.jsx(
2186
+ "span",
2187
+ {
2188
+ "data-slot": "icon",
2189
+ "data-state": state,
2190
+ "data-tone": resolvedTone,
2191
+ "data-size": size,
2192
+ className: cn(
2193
+ theme.slots.buttonIcon,
2194
+ size && iconSizeClassNames[size],
2195
+ classNames?.icon
2196
+ ),
2197
+ children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIcon, {})
2198
+ }
2199
+ ) : icon ? /* @__PURE__ */ jsxRuntime.jsx(
2200
+ "span",
2201
+ {
2202
+ "data-slot": "icon",
2203
+ "data-state": state,
2204
+ "data-tone": resolvedTone,
2205
+ "data-size": size,
2206
+ className: cn(
2207
+ theme.slots.buttonIcon,
2208
+ size && iconSizeClassNames[size],
2209
+ classNames?.icon
2210
+ ),
2211
+ children: icon
2212
+ }
2213
+ ) : null,
2214
+ iconOnly ? hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx(
2215
+ "span",
2216
+ {
2217
+ "data-slot": "label",
2218
+ "data-state": state,
2219
+ "data-tone": resolvedTone,
2220
+ "data-size": size,
2221
+ className: "sr-only",
2222
+ children: resolvedLabel
2223
+ }
2224
+ ) : null : hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx(
2225
+ "span",
2226
+ {
2227
+ "data-slot": "label",
2228
+ "data-state": state,
2229
+ "data-tone": resolvedTone,
2230
+ "data-size": size,
2231
+ className: cn(theme.slots.buttonLabel, classNames?.label),
2232
+ children: resolvedLabel
2233
+ }
2234
+ ) : null,
2235
+ !loading && endIcon ? /* @__PURE__ */ jsxRuntime.jsx(
2236
+ "span",
2237
+ {
2238
+ "data-slot": "end-icon",
2239
+ "data-state": state,
2240
+ "data-tone": resolvedTone,
2241
+ "data-size": size,
2242
+ className: cn(
2243
+ theme.slots.buttonIcon,
2244
+ size && iconSizeClassNames[size],
2245
+ classNames?.icon,
2246
+ classNames?.endIcon
2247
+ ),
2248
+ children: endIcon
2249
+ }
2250
+ ) : null
1828
2251
  ]
1829
2252
  }
1830
2253
  );
1831
2254
  }
1832
2255
  );
2256
+ var boxSizeClassNames = {
2257
+ sm: "h-3.5 w-3.5",
2258
+ md: "h-4 w-4",
2259
+ lg: "h-5 w-5"
2260
+ };
2261
+ var indicatorSizeClassNames = {
2262
+ sm: "text-[10px]",
2263
+ md: "text-[11px]",
2264
+ lg: "text-xs"
2265
+ };
1833
2266
  function setRefs(element, ...refs) {
1834
- refs.forEach((ref) => {
1835
- if (!ref) return;
2267
+ for (const ref of refs) {
2268
+ if (!ref) continue;
1836
2269
  if (typeof ref === "function") {
1837
2270
  ref(element);
1838
- return;
2271
+ continue;
1839
2272
  }
1840
2273
  ref.current = element;
1841
- });
2274
+ }
1842
2275
  }
1843
2276
  var BaseCheckbox = react.forwardRef(
1844
2277
  function BaseCheckbox2({
@@ -1847,6 +2280,7 @@ var BaseCheckbox = react.forwardRef(
1847
2280
  indeterminate = false,
1848
2281
  invalid = false,
1849
2282
  disabled = false,
2283
+ controlSize,
1850
2284
  appearance,
1851
2285
  className,
1852
2286
  classNames,
@@ -1857,14 +2291,41 @@ var BaseCheckbox = react.forwardRef(
1857
2291
  "aria-invalid": nativeAriaInvalid,
1858
2292
  ...checkboxProps
1859
2293
  }, forwardedRef) {
1860
- const theme = resolveBaseAppearance(appearance);
2294
+ for (const [name, value] of [
2295
+ ["indeterminate", indeterminate],
2296
+ ["invalid", invalid],
2297
+ ["disabled", disabled]
2298
+ ]) {
2299
+ if (typeof value !== "boolean") {
2300
+ throw new TypeError(`BaseCheckbox ${name} must be a boolean.`);
2301
+ }
2302
+ }
2303
+ if (controlSize !== void 0 && controlSize !== "sm" && controlSize !== "md" && controlSize !== "lg") {
2304
+ throw new TypeError(
2305
+ 'BaseCheckbox controlSize must be "sm", "md", or "lg".'
2306
+ );
2307
+ }
2308
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2309
+ const componentAttributes = useMonkeysComponentAttributes();
2310
+ const theme = resolveBaseAppearance(resolvedAppearance);
1861
2311
  const inputRef = react.useRef(null);
2312
+ const indeterminateRef = react.useRef(indeterminate);
2313
+ indeterminateRef.current = indeterminate;
1862
2314
  const [uncontrolledChecked, setUncontrolledChecked] = react.useState(
1863
2315
  defaultChecked ?? false
1864
2316
  );
1865
2317
  const isControlled = checked !== void 0;
1866
2318
  const resolvedChecked = Boolean(isControlled ? checked : uncontrolledChecked);
1867
2319
  const active = indeterminate || resolvedChecked;
2320
+ const state = indeterminate ? "mixed" : resolvedChecked ? "checked" : "unchecked";
2321
+ const setInputRef = react.useCallback(
2322
+ (element) => {
2323
+ inputRef.current = element;
2324
+ if (element) element.indeterminate = indeterminateRef.current;
2325
+ setRefs(element, forwardedRef);
2326
+ },
2327
+ [forwardedRef]
2328
+ );
1868
2329
  react.useEffect(() => {
1869
2330
  if (inputRef.current) {
1870
2331
  inputRef.current.indeterminate = indeterminate;
@@ -1876,10 +2337,20 @@ var BaseCheckbox = react.forwardRef(
1876
2337
  setUncontrolledChecked(event.currentTarget.checked);
1877
2338
  }
1878
2339
  onChange?.(event);
2340
+ if (inputRef.current) {
2341
+ inputRef.current.indeterminate = indeterminate;
2342
+ }
1879
2343
  };
1880
2344
  return /* @__PURE__ */ jsxRuntime.jsxs(
1881
2345
  "label",
1882
2346
  {
2347
+ ...componentAttributes,
2348
+ "data-monkeys-component": "checkbox",
2349
+ "data-slot": "root",
2350
+ "data-state": state,
2351
+ "data-size": controlSize,
2352
+ "data-invalid": invalid || void 0,
2353
+ "data-disabled": disabled || void 0,
1883
2354
  className: cn(
1884
2355
  theme.slots.checkboxRoot,
1885
2356
  disabled && theme.slots.checkboxDisabled,
@@ -1894,10 +2365,14 @@ var BaseCheckbox = react.forwardRef(
1894
2365
  /* @__PURE__ */ jsxRuntime.jsxs(
1895
2366
  "span",
1896
2367
  {
2368
+ "data-slot": "box",
2369
+ "data-state": state,
2370
+ "data-size": controlSize,
1897
2371
  className: cn(
1898
2372
  theme.slots.checkboxBox,
1899
2373
  active && theme.slots.checkboxBoxChecked,
1900
2374
  invalid && theme.slots.checkboxBoxInvalid,
2375
+ controlSize && boxSizeClassNames[controlSize],
1901
2376
  classNames?.box
1902
2377
  ),
1903
2378
  style: {
@@ -1908,13 +2383,18 @@ var BaseCheckbox = react.forwardRef(
1908
2383
  "input",
1909
2384
  {
1910
2385
  ...checkboxProps,
1911
- ref: (element) => setRefs(element, inputRef, forwardedRef),
2386
+ ref: setInputRef,
1912
2387
  type: "checkbox",
1913
2388
  disabled,
1914
2389
  checked,
1915
2390
  defaultChecked,
1916
2391
  "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
1917
2392
  "aria-checked": indeterminate ? "mixed" : resolvedChecked,
2393
+ "data-slot": "input",
2394
+ "data-state": state,
2395
+ "data-size": controlSize,
2396
+ "data-invalid": invalid || void 0,
2397
+ "data-disabled": disabled || void 0,
1918
2398
  className: cn(theme.slots.checkboxInput, classNames?.input),
1919
2399
  onChange: handleChange
1920
2400
  }
@@ -1923,31 +2403,225 @@ var BaseCheckbox = react.forwardRef(
1923
2403
  "span",
1924
2404
  {
1925
2405
  "aria-hidden": "true",
1926
- className: cn(theme.slots.checkboxIndicator, classNames?.indicator),
2406
+ "data-slot": "indicator",
2407
+ "data-state": state,
2408
+ "data-size": controlSize,
2409
+ className: cn(
2410
+ theme.slots.checkboxIndicator,
2411
+ controlSize && indicatorSizeClassNames[controlSize],
2412
+ classNames?.indicator
2413
+ ),
1927
2414
  children: indeterminate ? "\u2013" : "\u2713"
1928
2415
  }
1929
2416
  ) : null
1930
2417
  ]
1931
2418
  }
1932
2419
  ),
1933
- hasRenderableNode(label) || hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(theme.slots.checkboxContent, classNames?.content), children: [
1934
- hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.checkboxLabel, classNames?.label), children: label }) : null,
1935
- hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
1936
- "span",
1937
- {
1938
- className: cn(
1939
- theme.slots.checkboxDescription,
1940
- classNames?.description
1941
- ),
1942
- children: description
1943
- }
1944
- ) : null
1945
- ] }) : null
2420
+ hasRenderableNode(label) || hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsxs(
2421
+ "span",
2422
+ {
2423
+ "data-slot": "content",
2424
+ className: cn(theme.slots.checkboxContent, classNames?.content),
2425
+ children: [
2426
+ hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx(
2427
+ "span",
2428
+ {
2429
+ "data-slot": "label",
2430
+ className: cn(theme.slots.checkboxLabel, classNames?.label),
2431
+ children: label
2432
+ }
2433
+ ) : null,
2434
+ hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
2435
+ "span",
2436
+ {
2437
+ "data-slot": "description",
2438
+ className: cn(
2439
+ theme.slots.checkboxDescription,
2440
+ classNames?.description
2441
+ ),
2442
+ children: description
2443
+ }
2444
+ ) : null
2445
+ ]
2446
+ }
2447
+ ) : null
1946
2448
  ]
1947
2449
  }
1948
2450
  );
1949
2451
  }
1950
2452
  );
2453
+ function resolveContainerValue(value, source) {
2454
+ const candidate = typeof value === "function" ? value() : value;
2455
+ if (candidate === null) return null;
2456
+ if (!candidate || typeof candidate !== "object" || candidate.nodeType !== 1) {
2457
+ throw new TypeError(`${source} must resolve to an Element or null.`);
2458
+ }
2459
+ return candidate;
2460
+ }
2461
+ function resolveBasePortalContainer({
2462
+ explicitProvided,
2463
+ explicitContainer,
2464
+ providerProvided,
2465
+ providerContainer,
2466
+ getDocument
2467
+ }) {
2468
+ if (explicitProvided) {
2469
+ return resolveContainerValue(
2470
+ explicitContainer,
2471
+ "BasePortal container"
2472
+ );
2473
+ }
2474
+ if (providerProvided) {
2475
+ return resolveContainerValue(
2476
+ providerContainer,
2477
+ "MonkeysProvider portal.container"
2478
+ );
2479
+ }
2480
+ if (!getDocument) return null;
2481
+ const ownerDocument = getDocument();
2482
+ if (ownerDocument === null) return null;
2483
+ if (!ownerDocument || typeof ownerDocument !== "object" || !("body" in ownerDocument)) {
2484
+ throw new TypeError(
2485
+ "MonkeysProvider environment.getDocument must resolve to a Document or null."
2486
+ );
2487
+ }
2488
+ return resolveContainerValue(
2489
+ ownerDocument.body,
2490
+ "MonkeysProvider environment.getDocument().body"
2491
+ );
2492
+ }
2493
+ function resolveBaseOverlayPortalState({
2494
+ mounted,
2495
+ explicitDisabled,
2496
+ explicitContainer,
2497
+ providerDisabled,
2498
+ providerContainer,
2499
+ getDocument
2500
+ }) {
2501
+ const disabled = explicitDisabled ?? providerDisabled ?? false;
2502
+ if (!mounted || disabled) {
2503
+ return {
2504
+ mounted,
2505
+ disabled,
2506
+ shouldPortal: false,
2507
+ container: null,
2508
+ radixPortalProps: void 0
2509
+ };
2510
+ }
2511
+ const container = resolveBasePortalContainer({
2512
+ explicitProvided: explicitContainer !== void 0,
2513
+ explicitContainer,
2514
+ providerProvided: providerContainer !== void 0,
2515
+ providerContainer,
2516
+ getDocument
2517
+ });
2518
+ if (!container) {
2519
+ return {
2520
+ mounted: true,
2521
+ disabled: false,
2522
+ shouldPortal: false,
2523
+ container: null,
2524
+ radixPortalProps: void 0
2525
+ };
2526
+ }
2527
+ return {
2528
+ mounted: true,
2529
+ disabled: false,
2530
+ shouldPortal: true,
2531
+ container,
2532
+ radixPortalProps: Object.freeze({ container })
2533
+ };
2534
+ }
2535
+ function getDefaultDocument() {
2536
+ return globalThis.document ?? null;
2537
+ }
2538
+ function useBaseOverlayPortal(options = {}) {
2539
+ const environment = useMonkeysEnvironment();
2540
+ const portalOptions = useMonkeysPortalOptions();
2541
+ const [mounted, setMounted] = react.useState(false);
2542
+ react.useEffect(() => {
2543
+ setMounted(true);
2544
+ }, []);
2545
+ return resolveBaseOverlayPortalState({
2546
+ mounted,
2547
+ explicitDisabled: options.disabled,
2548
+ explicitContainer: options.container,
2549
+ providerDisabled: portalOptions.disabled,
2550
+ providerContainer: portalOptions.container,
2551
+ getDocument: environment.getDocument ?? getDefaultDocument
2552
+ });
2553
+ }
2554
+ var contextMenuTones = [
2555
+ "default",
2556
+ "primary",
2557
+ "success",
2558
+ "warning",
2559
+ "danger",
2560
+ "muted"
2561
+ ];
2562
+ function validateBoolean(value, name) {
2563
+ if (typeof value !== "boolean") {
2564
+ throw new TypeError(`BaseContextMenu ${name} must be a boolean.`);
2565
+ }
2566
+ }
2567
+ function validateTone(value) {
2568
+ if (value !== void 0 && !contextMenuTones.includes(
2569
+ value
2570
+ )) {
2571
+ throw new TypeError(
2572
+ 'BaseContextMenu tone must be "default", "primary", "success", "warning", "danger", or "muted".'
2573
+ );
2574
+ }
2575
+ }
2576
+ function validateDirection(value) {
2577
+ if (value !== void 0 && value !== "ltr" && value !== "rtl") {
2578
+ throw new TypeError('BaseContextMenu dir must be "ltr" or "rtl".');
2579
+ }
2580
+ }
2581
+ function CheckIcon() {
2582
+ return /* @__PURE__ */ jsxRuntime.jsx(
2583
+ "svg",
2584
+ {
2585
+ "aria-hidden": "true",
2586
+ viewBox: "0 0 16 16",
2587
+ className: "h-3.5 w-3.5",
2588
+ fill: "none",
2589
+ stroke: "currentColor",
2590
+ strokeLinecap: "round",
2591
+ strokeLinejoin: "round",
2592
+ strokeWidth: "2",
2593
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5" })
2594
+ }
2595
+ );
2596
+ }
2597
+ function DotIcon() {
2598
+ return /* @__PURE__ */ jsxRuntime.jsx(
2599
+ "svg",
2600
+ {
2601
+ "aria-hidden": "true",
2602
+ viewBox: "0 0 16 16",
2603
+ className: "h-3.5 w-3.5",
2604
+ fill: "currentColor",
2605
+ children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "3" })
2606
+ }
2607
+ );
2608
+ }
2609
+ function ChevronRightIcon() {
2610
+ return /* @__PURE__ */ jsxRuntime.jsx(
2611
+ "svg",
2612
+ {
2613
+ "aria-hidden": "true",
2614
+ viewBox: "0 0 16 16",
2615
+ className: "h-3.5 w-3.5",
2616
+ fill: "none",
2617
+ stroke: "currentColor",
2618
+ strokeLinecap: "round",
2619
+ strokeLinejoin: "round",
2620
+ strokeWidth: "2",
2621
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 4 4 4-4 4" })
2622
+ }
2623
+ );
2624
+ }
1951
2625
  function renderItemContent({
1952
2626
  label,
1953
2627
  icon,
@@ -1960,9 +2634,16 @@ function renderItemContent({
1960
2634
  const resolvedLabel = children ?? label;
1961
2635
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1962
2636
  indicator ? indicator : null,
1963
- hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.icon), children: icon }) : inset ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }) : null,
1964
- hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.label), children: resolvedLabel }) : null,
1965
- hasRenderableNode(shortcut) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.shortcut), children: shortcut }) : null
2637
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "icon", className: cn(classNames?.icon), children: icon }) : inset ? /* @__PURE__ */ jsxRuntime.jsx(
2638
+ "span",
2639
+ {
2640
+ "aria-hidden": "true",
2641
+ "data-slot": "icon",
2642
+ className: "h-4 w-4 shrink-0"
2643
+ }
2644
+ ) : null,
2645
+ hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "label", className: cn(classNames?.label), children: resolvedLabel }) : null,
2646
+ hasRenderableNode(shortcut) ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "shortcut", className: cn(classNames?.shortcut), children: shortcut }) : null
1966
2647
  ] });
1967
2648
  }
1968
2649
  function BaseContextMenu({
@@ -1977,34 +2658,41 @@ function BaseContextMenu({
1977
2658
  classNames,
1978
2659
  onOpenChange
1979
2660
  }) {
1980
- const theme = resolveBaseAppearance(appearance);
2661
+ validateBoolean(disabled, "disabled");
2662
+ validateBoolean(modal, "modal");
2663
+ validateDirection(dir);
2664
+ const inheritedDirection = useMonkeysDirection();
2665
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
1981
2666
  return /* @__PURE__ */ jsxRuntime.jsxs(
1982
2667
  ContextMenu__namespace.Root,
1983
2668
  {
1984
2669
  onOpenChange,
1985
2670
  modal,
1986
- dir,
2671
+ dir: dir ?? inheritedDirection,
1987
2672
  children: [
1988
2673
  trigger ? /* @__PURE__ */ jsxRuntime.jsx(
1989
- ContextMenu__namespace.Trigger,
2674
+ BaseContextMenuTrigger,
1990
2675
  {
1991
2676
  disabled,
1992
- className: cn(
1993
- theme.slots.menuTrigger,
1994
- disabled && theme.slots.menuItemDisabled,
1995
- classNames?.trigger,
1996
- className
1997
- ),
2677
+ appearance: resolvedAppearance,
2678
+ className: cn(classNames?.trigger, className),
1998
2679
  children: trigger
1999
2680
  }
2000
2681
  ) : null,
2001
- content ? /* @__PURE__ */ jsxRuntime.jsx(BaseContextMenuContent, { appearance, className: classNames?.content, children: content }) : null,
2682
+ content ? /* @__PURE__ */ jsxRuntime.jsx(
2683
+ BaseContextMenuContent,
2684
+ {
2685
+ appearance: resolvedAppearance,
2686
+ className: classNames?.content,
2687
+ children: content
2688
+ }
2689
+ ) : null,
2002
2690
  children
2003
2691
  ]
2004
2692
  }
2005
2693
  );
2006
2694
  }
2007
- function BaseContextMenuTrigger({
2695
+ var BaseContextMenuTrigger = react.forwardRef(function BaseContextMenuTrigger2({
2008
2696
  children,
2009
2697
  disabled = false,
2010
2698
  asChild = false,
@@ -2012,14 +2700,23 @@ function BaseContextMenuTrigger({
2012
2700
  className,
2013
2701
  style,
2014
2702
  ...triggerProps
2015
- }) {
2016
- const theme = resolveBaseAppearance(appearance);
2703
+ }, ref) {
2704
+ validateBoolean(disabled, "Trigger disabled");
2705
+ validateBoolean(asChild, "Trigger asChild");
2706
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2707
+ const componentAttributes = useMonkeysComponentAttributes();
2708
+ const theme = resolveBaseAppearance(resolvedAppearance);
2017
2709
  return /* @__PURE__ */ jsxRuntime.jsx(
2018
2710
  ContextMenu__namespace.Trigger,
2019
2711
  {
2712
+ ...componentAttributes,
2020
2713
  ...triggerProps,
2714
+ ref,
2021
2715
  asChild,
2022
2716
  disabled,
2717
+ "data-monkeys-component": "context-menu",
2718
+ "data-slot": "trigger",
2719
+ "data-disabled": disabled || void 0,
2023
2720
  className: cn(
2024
2721
  !asChild && theme.slots.menuTrigger,
2025
2722
  disabled && !asChild && theme.slots.menuItemDisabled,
@@ -2029,20 +2726,27 @@ function BaseContextMenuTrigger({
2029
2726
  children
2030
2727
  }
2031
2728
  );
2032
- }
2033
- function BaseContextMenuContent({
2729
+ });
2730
+ var BaseContextMenuContent = react.forwardRef(function BaseContextMenuContent2({
2034
2731
  children,
2035
2732
  appearance,
2036
2733
  className,
2037
2734
  classNames,
2038
2735
  style,
2039
2736
  ...contentProps
2040
- }) {
2041
- const theme = resolveBaseAppearance(appearance);
2042
- return /* @__PURE__ */ jsxRuntime.jsx(ContextMenu__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2737
+ }, ref) {
2738
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2739
+ const componentAttributes = useMonkeysComponentAttributes();
2740
+ const theme = resolveBaseAppearance(resolvedAppearance);
2741
+ const portal = useBaseOverlayPortal();
2742
+ const content = /* @__PURE__ */ jsxRuntime.jsx(
2043
2743
  ContextMenu__namespace.Content,
2044
2744
  {
2745
+ ...componentAttributes,
2045
2746
  ...contentProps,
2747
+ ref,
2748
+ "data-monkeys-component": "context-menu",
2749
+ "data-slot": "content",
2046
2750
  className: cn(theme.slots.menuContent, classNames?.root, className),
2047
2751
  style: {
2048
2752
  ...theme.styles.menuContent,
@@ -2050,43 +2754,45 @@ function BaseContextMenuContent({
2050
2754
  },
2051
2755
  children
2052
2756
  }
2053
- ) });
2054
- }
2055
- function BaseContextMenuLabel({
2056
- children,
2057
- appearance,
2058
- className,
2059
- style,
2060
- ...labelProps
2061
- }) {
2062
- const theme = resolveBaseAppearance(appearance);
2757
+ );
2758
+ return portal.shouldPortal ? /* @__PURE__ */ jsxRuntime.jsx(ContextMenu__namespace.Portal, { ...portal.radixPortalProps, children: content }) : content;
2759
+ });
2760
+ var BaseContextMenuLabel = react.forwardRef(function BaseContextMenuLabel2({ children, appearance, className, style, ...labelProps }, ref) {
2761
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2762
+ const componentAttributes = useMonkeysComponentAttributes();
2763
+ const theme = resolveBaseAppearance(resolvedAppearance);
2063
2764
  return /* @__PURE__ */ jsxRuntime.jsx(
2064
2765
  ContextMenu__namespace.Label,
2065
2766
  {
2767
+ ...componentAttributes,
2066
2768
  ...labelProps,
2769
+ ref,
2770
+ "data-monkeys-component": "context-menu",
2771
+ "data-slot": "label",
2067
2772
  className: cn(theme.slots.menuLabel, className),
2068
2773
  style,
2069
2774
  children
2070
2775
  }
2071
2776
  );
2072
- }
2073
- function BaseContextMenuSeparator({
2074
- appearance,
2075
- className,
2076
- style,
2077
- ...separatorProps
2078
- }) {
2079
- const theme = resolveBaseAppearance(appearance);
2777
+ });
2778
+ var BaseContextMenuSeparator = react.forwardRef(function BaseContextMenuSeparator2({ appearance, className, style, ...separatorProps }, ref) {
2779
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2780
+ const componentAttributes = useMonkeysComponentAttributes();
2781
+ const theme = resolveBaseAppearance(resolvedAppearance);
2080
2782
  return /* @__PURE__ */ jsxRuntime.jsx(
2081
2783
  ContextMenu__namespace.Separator,
2082
2784
  {
2785
+ ...componentAttributes,
2083
2786
  ...separatorProps,
2787
+ ref,
2788
+ "data-monkeys-component": "context-menu",
2789
+ "data-slot": "separator",
2084
2790
  className: cn(theme.slots.menuSeparator, className),
2085
2791
  style
2086
2792
  }
2087
2793
  );
2088
- }
2089
- function BaseContextMenuItem({
2794
+ });
2795
+ var BaseContextMenuItem = react.forwardRef(function BaseContextMenuItem2({
2090
2796
  children,
2091
2797
  label,
2092
2798
  icon,
@@ -2100,13 +2806,25 @@ function BaseContextMenuItem({
2100
2806
  style,
2101
2807
  onSelect,
2102
2808
  ...itemProps
2103
- }) {
2104
- const theme = resolveBaseAppearance(appearance);
2809
+ }, ref) {
2810
+ validateBoolean(disabled, "Item disabled");
2811
+ validateBoolean(inset, "Item inset");
2812
+ validateTone(tone);
2813
+ const resolvedTone = tone ?? "default";
2814
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2815
+ const componentAttributes = useMonkeysComponentAttributes();
2816
+ const theme = resolveBaseAppearance(resolvedAppearance);
2105
2817
  return /* @__PURE__ */ jsxRuntime.jsx(
2106
2818
  ContextMenu__namespace.Item,
2107
2819
  {
2820
+ ...componentAttributes,
2108
2821
  ...itemProps,
2822
+ ref,
2109
2823
  disabled,
2824
+ "data-monkeys-component": "context-menu",
2825
+ "data-slot": "item",
2826
+ "data-tone": resolvedTone,
2827
+ "data-disabled": disabled || void 0,
2110
2828
  className: cn(
2111
2829
  theme.slots.menuItem,
2112
2830
  getBaseMenuItemToneClassName(theme, tone),
@@ -2139,423 +2857,558 @@ function BaseContextMenuItem({
2139
2857
  })
2140
2858
  }
2141
2859
  );
2142
- }
2143
- var columnClassNames = {
2144
- 1: "grid-cols-1",
2145
- 2: "md:grid-cols-2",
2146
- 3: "md:grid-cols-2 xl:grid-cols-3"
2147
- };
2148
- function BaseDescriptionList({
2149
- items,
2150
- columns = 1,
2860
+ });
2861
+ react.forwardRef(function BaseContextMenuCheckboxItem2({
2862
+ children,
2863
+ label,
2864
+ icon,
2865
+ shortcut,
2866
+ tone,
2867
+ disabled = false,
2868
+ inset = false,
2869
+ checked,
2870
+ onCheckedChange,
2151
2871
  appearance,
2152
2872
  className,
2153
2873
  classNames,
2154
2874
  style,
2155
- children,
2156
- ...listProps
2157
- }) {
2158
- const theme = resolveBaseAppearance(appearance);
2159
- return /* @__PURE__ */ jsxRuntime.jsxs(
2160
- "dl",
2875
+ onSelect,
2876
+ ...itemProps
2877
+ }, ref) {
2878
+ validateBoolean(disabled, "CheckboxItem disabled");
2879
+ validateBoolean(inset, "CheckboxItem inset");
2880
+ validateTone(tone);
2881
+ if (checked !== void 0 && checked !== "indeterminate" && typeof checked !== "boolean") {
2882
+ throw new TypeError(
2883
+ 'BaseContextMenu CheckboxItem checked must be a boolean or "indeterminate".'
2884
+ );
2885
+ }
2886
+ const resolvedTone = tone ?? "default";
2887
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2888
+ const componentAttributes = useMonkeysComponentAttributes();
2889
+ const theme = resolveBaseAppearance(resolvedAppearance);
2890
+ return /* @__PURE__ */ jsxRuntime.jsx(
2891
+ ContextMenu__namespace.CheckboxItem,
2161
2892
  {
2162
- ...listProps,
2893
+ ...componentAttributes,
2894
+ ...itemProps,
2895
+ ref,
2896
+ checked,
2897
+ disabled,
2898
+ "data-monkeys-component": "context-menu",
2899
+ "data-slot": "checkbox-item",
2900
+ "data-tone": resolvedTone,
2901
+ "data-disabled": disabled || void 0,
2902
+ "data-checked": checked === "indeterminate" ? "mixed" : checked === void 0 ? void 0 : String(checked),
2903
+ onCheckedChange: (nextChecked) => {
2904
+ if (disabled) return;
2905
+ onCheckedChange?.(nextChecked);
2906
+ },
2163
2907
  className: cn(
2164
- theme.slots.descriptionListRoot,
2165
- columnClassNames[columns],
2908
+ theme.slots.menuItem,
2909
+ "pl-8",
2910
+ getBaseMenuItemToneClassName(theme, tone),
2911
+ disabled && theme.slots.menuItemDisabled,
2166
2912
  classNames?.root,
2167
2913
  className
2168
2914
  ),
2169
2915
  style: {
2170
- ...theme.styles.descriptionList,
2916
+ ...theme.styles.menuItem,
2171
2917
  ...style
2172
2918
  },
2173
- children: [
2174
- items?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2175
- "div",
2919
+ onSelect: (event) => {
2920
+ if (disabled) {
2921
+ event.preventDefault();
2922
+ return;
2923
+ }
2924
+ onSelect?.(event);
2925
+ },
2926
+ children: renderItemContent({
2927
+ children,
2928
+ label,
2929
+ icon,
2930
+ shortcut,
2931
+ inset,
2932
+ classNames: {
2933
+ icon: cn(theme.slots.menuItemIcon, classNames?.icon),
2934
+ label: cn(theme.slots.menuItemLabel, classNames?.label),
2935
+ shortcut: cn(theme.slots.menuItemShortcut, classNames?.shortcut)
2936
+ },
2937
+ indicator: /* @__PURE__ */ jsxRuntime.jsx(
2938
+ ContextMenu__namespace.ItemIndicator,
2176
2939
  {
2177
- className: cn(theme.slots.descriptionListItem, classNames?.item),
2178
- children: [
2179
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: cn(theme.slots.descriptionListTerm, classNames?.term), children: item.term }),
2180
- /* @__PURE__ */ jsxRuntime.jsx(
2181
- "dd",
2182
- {
2183
- className: cn(theme.slots.descriptionListValue, classNames?.value),
2184
- children: item.value
2185
- }
2186
- )
2187
- ]
2188
- },
2189
- index
2190
- )),
2191
- children
2192
- ]
2940
+ "data-slot": "indicator",
2941
+ className: cn(theme.slots.menuCheckboxIndicator, classNames?.indicator),
2942
+ children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {})
2943
+ }
2944
+ )
2945
+ })
2193
2946
  }
2194
2947
  );
2195
- }
2196
- function BaseField({
2948
+ });
2949
+ react.forwardRef(function BaseContextMenuRadioItem2({
2950
+ children,
2197
2951
  label,
2198
- description,
2199
- message,
2200
- error,
2201
- required = false,
2952
+ icon,
2953
+ shortcut,
2954
+ tone,
2202
2955
  disabled = false,
2203
- htmlFor,
2956
+ inset = false,
2957
+ value,
2958
+ appearance,
2959
+ className,
2960
+ classNames,
2961
+ style,
2962
+ onSelect,
2963
+ ...itemProps
2964
+ }, ref) {
2965
+ validateBoolean(disabled, "RadioItem disabled");
2966
+ validateBoolean(inset, "RadioItem inset");
2967
+ validateTone(tone);
2968
+ const resolvedTone = tone ?? "default";
2969
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
2970
+ const componentAttributes = useMonkeysComponentAttributes();
2971
+ const theme = resolveBaseAppearance(resolvedAppearance);
2972
+ return /* @__PURE__ */ jsxRuntime.jsx(
2973
+ ContextMenu__namespace.RadioItem,
2974
+ {
2975
+ ...componentAttributes,
2976
+ ...itemProps,
2977
+ ref,
2978
+ value,
2979
+ disabled,
2980
+ "data-monkeys-component": "context-menu",
2981
+ "data-slot": "radio-item",
2982
+ "data-tone": resolvedTone,
2983
+ "data-value": value,
2984
+ "data-disabled": disabled || void 0,
2985
+ className: cn(
2986
+ theme.slots.menuItem,
2987
+ "pl-8",
2988
+ getBaseMenuItemToneClassName(theme, tone),
2989
+ disabled && theme.slots.menuItemDisabled,
2990
+ classNames?.root,
2991
+ className
2992
+ ),
2993
+ style: {
2994
+ ...theme.styles.menuItem,
2995
+ ...style
2996
+ },
2997
+ onSelect: (event) => {
2998
+ if (disabled) {
2999
+ event.preventDefault();
3000
+ return;
3001
+ }
3002
+ onSelect?.(event);
3003
+ },
3004
+ children: renderItemContent({
3005
+ children,
3006
+ label,
3007
+ icon,
3008
+ shortcut,
3009
+ inset,
3010
+ classNames: {
3011
+ icon: cn(theme.slots.menuItemIcon, classNames?.icon),
3012
+ label: cn(theme.slots.menuItemLabel, classNames?.label),
3013
+ shortcut: cn(theme.slots.menuItemShortcut, classNames?.shortcut)
3014
+ },
3015
+ indicator: /* @__PURE__ */ jsxRuntime.jsx(
3016
+ ContextMenu__namespace.ItemIndicator,
3017
+ {
3018
+ "data-slot": "indicator",
3019
+ className: cn(theme.slots.menuRadioIndicator, classNames?.indicator),
3020
+ children: /* @__PURE__ */ jsxRuntime.jsx(DotIcon, {})
3021
+ }
3022
+ )
3023
+ })
3024
+ }
3025
+ );
3026
+ });
3027
+ react.forwardRef(function BaseContextMenuSubTrigger2({
2204
3028
  children,
3029
+ label,
3030
+ icon,
3031
+ tone,
3032
+ disabled = false,
3033
+ inset = false,
2205
3034
  appearance,
2206
3035
  className,
2207
3036
  classNames,
2208
3037
  style,
2209
- ...fieldProps
2210
- }) {
2211
- const theme = resolveBaseAppearance(appearance);
2212
- const resolvedMessage = hasRenderableNode(error) ? error : message;
3038
+ ...itemProps
3039
+ }, ref) {
3040
+ validateBoolean(disabled, "SubTrigger disabled");
3041
+ validateBoolean(inset, "SubTrigger inset");
3042
+ validateTone(tone);
3043
+ const resolvedTone = tone ?? "default";
3044
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3045
+ const componentAttributes = useMonkeysComponentAttributes();
3046
+ const theme = resolveBaseAppearance(resolvedAppearance);
3047
+ const resolvedLabel = children ?? label;
2213
3048
  return /* @__PURE__ */ jsxRuntime.jsxs(
2214
- "div",
3049
+ ContextMenu__namespace.SubTrigger,
2215
3050
  {
2216
- ...fieldProps,
2217
- "aria-disabled": disabled || void 0,
3051
+ ...componentAttributes,
3052
+ ...itemProps,
3053
+ ref,
3054
+ disabled,
3055
+ "data-monkeys-component": "context-menu",
3056
+ "data-slot": "sub-trigger",
3057
+ "data-tone": resolvedTone,
3058
+ "data-disabled": disabled || void 0,
2218
3059
  className: cn(
2219
- theme.slots.fieldRoot,
2220
- disabled && theme.slots.controlDisabled,
3060
+ theme.slots.menuSubTrigger,
3061
+ getBaseMenuItemToneClassName(theme, tone),
3062
+ disabled && theme.slots.menuItemDisabled,
2221
3063
  classNames?.root,
2222
3064
  className
2223
3065
  ),
2224
3066
  style: {
2225
- ...theme.styles.field,
3067
+ ...theme.styles.menuItem,
2226
3068
  ...style
2227
3069
  },
2228
3070
  children: [
2229
- hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.fieldLabelRow, classNames?.labelRow), children: /* @__PURE__ */ jsxRuntime.jsxs(
2230
- "label",
3071
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx(
3072
+ "span",
2231
3073
  {
2232
- htmlFor,
2233
- className: cn(theme.slots.fieldLabel, classNames?.label),
2234
- children: [
2235
- label,
2236
- required ? /* @__PURE__ */ jsxRuntime.jsxs(
2237
- "span",
2238
- {
2239
- "aria-hidden": "true",
2240
- className: cn(theme.slots.fieldRequired, classNames?.required),
2241
- children: [
2242
- " ",
2243
- "*"
2244
- ]
2245
- }
2246
- ) : null
2247
- ]
3074
+ "data-slot": "icon",
3075
+ className: cn(theme.slots.menuItemIcon, classNames?.icon),
3076
+ children: icon
2248
3077
  }
2249
- ) }) : null,
2250
- hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
2251
- "div",
3078
+ ) : inset ? /* @__PURE__ */ jsxRuntime.jsx(
3079
+ "span",
2252
3080
  {
2253
- className: cn(theme.slots.fieldDescription, classNames?.description),
2254
- children: description
3081
+ "aria-hidden": "true",
3082
+ "data-slot": "icon",
3083
+ className: "h-4 w-4 shrink-0"
2255
3084
  }
2256
3085
  ) : null,
2257
- hasRenderableNode(children) ? /* @__PURE__ */ jsxRuntime.jsx(
2258
- "div",
3086
+ hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx(
3087
+ "span",
2259
3088
  {
2260
- className: cn(theme.slots.fieldControl, classNames?.control),
2261
- style: theme.styles.fieldControl,
2262
- children
3089
+ "data-slot": "label",
3090
+ className: cn(theme.slots.menuItemLabel, classNames?.label),
3091
+ children: resolvedLabel
2263
3092
  }
2264
3093
  ) : null,
2265
- hasRenderableNode(resolvedMessage) ? /* @__PURE__ */ jsxRuntime.jsx(
2266
- "div",
3094
+ /* @__PURE__ */ jsxRuntime.jsx(
3095
+ "span",
2267
3096
  {
3097
+ "data-slot": "sub-indicator",
2268
3098
  className: cn(
2269
- theme.slots.fieldMessage,
2270
- hasRenderableNode(error) && "text-destructive",
2271
- classNames?.message
3099
+ theme.slots.menuSubTriggerIcon,
3100
+ classNames?.shortcut,
3101
+ "rtl:rotate-180"
2272
3102
  ),
2273
- children: resolvedMessage
3103
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {})
2274
3104
  }
2275
- ) : null
3105
+ )
3106
+ ]
3107
+ }
3108
+ );
3109
+ });
3110
+ react.forwardRef(function BaseContextMenuSubContent2({
3111
+ children,
3112
+ appearance,
3113
+ className,
3114
+ classNames,
3115
+ style,
3116
+ sideOffset = 6,
3117
+ ...subContentProps
3118
+ }, ref) {
3119
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3120
+ const componentAttributes = useMonkeysComponentAttributes();
3121
+ const theme = resolveBaseAppearance(resolvedAppearance);
3122
+ const portal = useBaseOverlayPortal();
3123
+ const content = /* @__PURE__ */ jsxRuntime.jsx(
3124
+ ContextMenu__namespace.SubContent,
3125
+ {
3126
+ ...componentAttributes,
3127
+ ...subContentProps,
3128
+ ref,
3129
+ sideOffset,
3130
+ "data-monkeys-component": "context-menu",
3131
+ "data-slot": "sub-content",
3132
+ className: cn(theme.slots.menuSubContent, classNames?.root, className),
3133
+ style: {
3134
+ ...theme.styles.menuContent,
3135
+ ...style
3136
+ },
3137
+ children
3138
+ }
3139
+ );
3140
+ return portal.shouldPortal ? /* @__PURE__ */ jsxRuntime.jsx(ContextMenu__namespace.Portal, { ...portal.radixPortalProps, children: content }) : content;
3141
+ });
3142
+ var columnClassNames = {
3143
+ 1: "grid-cols-1",
3144
+ 2: "md:grid-cols-2",
3145
+ 3: "md:grid-cols-2 xl:grid-cols-3"
3146
+ };
3147
+ function BaseDescriptionList({
3148
+ items,
3149
+ columns = 1,
3150
+ appearance,
3151
+ className,
3152
+ classNames,
3153
+ style,
3154
+ children,
3155
+ ...listProps
3156
+ }) {
3157
+ const theme = resolveBaseAppearance(appearance);
3158
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3159
+ "dl",
3160
+ {
3161
+ ...listProps,
3162
+ className: cn(
3163
+ theme.slots.descriptionListRoot,
3164
+ columnClassNames[columns],
3165
+ classNames?.root,
3166
+ className
3167
+ ),
3168
+ style: {
3169
+ ...theme.styles.descriptionList,
3170
+ ...style
3171
+ },
3172
+ children: [
3173
+ items?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
3174
+ "div",
3175
+ {
3176
+ className: cn(theme.slots.descriptionListItem, classNames?.item),
3177
+ children: [
3178
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: cn(theme.slots.descriptionListTerm, classNames?.term), children: item.term }),
3179
+ /* @__PURE__ */ jsxRuntime.jsx(
3180
+ "dd",
3181
+ {
3182
+ className: cn(theme.slots.descriptionListValue, classNames?.value),
3183
+ children: item.value
3184
+ }
3185
+ )
3186
+ ]
3187
+ },
3188
+ index
3189
+ )),
3190
+ children
2276
3191
  ]
2277
3192
  }
2278
3193
  );
2279
3194
  }
2280
- var BaseInput = react.forwardRef(
2281
- function BaseInput2({
2282
- icon,
2283
- trailing,
2284
- invalid = false,
3195
+ function mergeAriaIds(...values) {
3196
+ const ids = values.flatMap(
3197
+ (value) => value?.split(/\s+/).filter(Boolean) ?? []
3198
+ );
3199
+ return ids.length ? Array.from(new Set(ids)).join(" ") : void 0;
3200
+ }
3201
+ function resolveOptionalId(value, fallback, name) {
3202
+ if (value === void 0) return fallback;
3203
+ if (!value.trim() || /\s/.test(value)) {
3204
+ throw new TypeError(
3205
+ `BaseField ${name} must be a non-empty ID without whitespace.`
3206
+ );
3207
+ }
3208
+ return value;
3209
+ }
3210
+ var BaseField = react.forwardRef(
3211
+ function BaseField2({
3212
+ label,
3213
+ description,
3214
+ message,
3215
+ error,
3216
+ required = false,
2285
3217
  disabled = false,
2286
- readOnly = false,
3218
+ htmlFor,
3219
+ descriptionId,
3220
+ messageId,
3221
+ errorId,
3222
+ children,
2287
3223
  appearance,
2288
3224
  className,
2289
3225
  classNames,
2290
3226
  style,
2291
- "aria-invalid": nativeAriaInvalid,
2292
- ...inputProps
3227
+ ...fieldProps
2293
3228
  }, ref) {
2294
- const theme = resolveBaseAppearance(appearance);
3229
+ for (const [name, value] of [
3230
+ ["required", required],
3231
+ ["disabled", disabled]
3232
+ ]) {
3233
+ if (typeof value !== "boolean") {
3234
+ throw new TypeError(`BaseField ${name} must be a boolean.`);
3235
+ }
3236
+ }
3237
+ const generatedId = react.useId();
3238
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3239
+ const componentAttributes = useMonkeysComponentAttributes();
3240
+ const theme = resolveBaseAppearance(resolvedAppearance);
3241
+ const hasDescription = hasRenderableNode(description);
3242
+ const hasError = hasRenderableNode(error);
3243
+ const hasMessage = !hasError && hasRenderableNode(message);
3244
+ const resolvedMessage = hasError ? error : message;
3245
+ const resolvedControlId = htmlFor ?? `${generatedId}-control`;
3246
+ const resolvedDescriptionId = hasDescription ? resolveOptionalId(
3247
+ descriptionId,
3248
+ `${generatedId}-description`,
3249
+ "descriptionId"
3250
+ ) : void 0;
3251
+ const resolvedMessageId = hasMessage ? resolveOptionalId(messageId, `${generatedId}-message`, "messageId") : void 0;
3252
+ const resolvedErrorId = hasError ? resolveOptionalId(errorId, `${generatedId}-error`, "errorId") : void 0;
3253
+ const controlProps = {
3254
+ id: resolvedControlId,
3255
+ "aria-describedby": mergeAriaIds(
3256
+ resolvedDescriptionId,
3257
+ resolvedMessageId
3258
+ ),
3259
+ "aria-errormessage": resolvedErrorId,
3260
+ "aria-invalid": hasError ? true : void 0,
3261
+ "aria-required": required ? true : void 0,
3262
+ required: required || void 0,
3263
+ disabled: disabled || void 0
3264
+ };
3265
+ const renderedChildren = typeof children === "function" ? children(controlProps) : children;
2295
3266
  return /* @__PURE__ */ jsxRuntime.jsxs(
2296
3267
  "div",
2297
3268
  {
3269
+ ...componentAttributes,
3270
+ ...fieldProps,
3271
+ ref,
3272
+ "aria-disabled": disabled || void 0,
3273
+ "data-monkeys-component": "field",
3274
+ "data-slot": "root",
3275
+ "data-required": required || void 0,
3276
+ "data-disabled": disabled || void 0,
3277
+ "data-invalid": hasError || void 0,
2298
3278
  className: cn(
2299
- theme.slots.controlWrapper,
2300
- invalid && theme.slots.controlInvalid,
3279
+ theme.slots.fieldRoot,
2301
3280
  disabled && theme.slots.controlDisabled,
2302
- readOnly && theme.slots.controlReadOnly,
2303
3281
  classNames?.root,
2304
3282
  className
2305
3283
  ),
2306
3284
  style: {
2307
- ...theme.styles.control,
2308
- ...invalid ? theme.styles.controlInvalid : void 0,
2309
- ...disabled ? theme.styles.controlDisabled : void 0,
3285
+ ...theme.styles.field,
2310
3286
  ...style
2311
3287
  },
2312
3288
  children: [
2313
- hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2314
- /* @__PURE__ */ jsxRuntime.jsx(
2315
- "input",
3289
+ hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx(
3290
+ "div",
2316
3291
  {
2317
- ...inputProps,
2318
- ref,
2319
- disabled,
2320
- readOnly,
2321
- "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2322
- className: cn(
2323
- theme.slots.controlBase,
2324
- theme.slots.controlInput,
2325
- classNames?.control
3292
+ "data-slot": "label-row",
3293
+ className: cn(theme.slots.fieldLabelRow, classNames?.labelRow),
3294
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3295
+ "label",
3296
+ {
3297
+ htmlFor: typeof children === "function" ? resolvedControlId : htmlFor,
3298
+ "data-slot": "label",
3299
+ className: cn(theme.slots.fieldLabel, classNames?.label),
3300
+ children: [
3301
+ label,
3302
+ required ? /* @__PURE__ */ jsxRuntime.jsxs(
3303
+ "span",
3304
+ {
3305
+ "aria-hidden": "true",
3306
+ "data-slot": "required-indicator",
3307
+ className: cn(
3308
+ theme.slots.fieldRequired,
3309
+ classNames?.required
3310
+ ),
3311
+ children: [
3312
+ " ",
3313
+ "*"
3314
+ ]
3315
+ }
3316
+ ) : null
3317
+ ]
3318
+ }
2326
3319
  )
2327
3320
  }
2328
- ),
2329
- hasRenderableNode(trailing) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlTrailing, classNames?.trailing), children: trailing }) : null
3321
+ ) : null,
3322
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(
3323
+ "div",
3324
+ {
3325
+ id: resolvedDescriptionId,
3326
+ "data-slot": "description",
3327
+ className: cn(
3328
+ theme.slots.fieldDescription,
3329
+ classNames?.description
3330
+ ),
3331
+ children: description
3332
+ }
3333
+ ) : null,
3334
+ hasRenderableNode(renderedChildren) ? /* @__PURE__ */ jsxRuntime.jsx(
3335
+ "div",
3336
+ {
3337
+ "data-slot": "control",
3338
+ className: cn(theme.slots.fieldControl, classNames?.control),
3339
+ style: theme.styles.fieldControl,
3340
+ children: renderedChildren
3341
+ }
3342
+ ) : null,
3343
+ hasRenderableNode(resolvedMessage) ? /* @__PURE__ */ jsxRuntime.jsx(
3344
+ "div",
3345
+ {
3346
+ id: hasError ? resolvedErrorId : resolvedMessageId,
3347
+ role: hasError ? "alert" : void 0,
3348
+ "data-slot": hasError ? "error" : "message",
3349
+ className: cn(
3350
+ theme.slots.fieldMessage,
3351
+ hasError && "text-destructive-text",
3352
+ classNames?.message
3353
+ ),
3354
+ children: resolvedMessage
3355
+ }
3356
+ ) : null
2330
3357
  ]
2331
3358
  }
2332
3359
  );
2333
3360
  }
2334
3361
  );
2335
- function normalizeValues(values) {
2336
- const nextValues = [];
2337
- const seen = /* @__PURE__ */ new Set();
2338
- values?.forEach((value) => {
2339
- if (seen.has(value)) return;
2340
- seen.add(value);
2341
- nextValues.push(value);
2342
- });
2343
- return nextValues;
2344
- }
2345
- function getNextEnabledIndex(options, currentIndex, direction) {
2346
- if (!options.length) return -1;
2347
- const startIndex = currentIndex >= 0 ? currentIndex : 0;
2348
- for (let offset = 1; offset <= options.length; offset += 1) {
2349
- const nextIndex = (startIndex + offset * direction + options.length) % options.length;
2350
- if (!options[nextIndex]?.disabled) {
2351
- return nextIndex;
2352
- }
2353
- }
2354
- return -1;
2355
- }
2356
- function getFirstEnabledIndex(options) {
2357
- return options.findIndex((option) => !option.disabled);
2358
- }
2359
- function getSafeTagCount(maxTagCount, total) {
2360
- if (maxTagCount === void 0) return total;
2361
- if (!Number.isFinite(maxTagCount)) return total;
2362
- return Math.max(0, Math.min(total, Math.floor(maxTagCount)));
2363
- }
2364
- function getDefaultRemoveLabel(option) {
2365
- return `Remove ${option.value}`;
2366
- }
2367
- react.forwardRef(
2368
- function BaseMultiSelect2({
2369
- options,
2370
- value,
2371
- defaultValue,
2372
- name,
2373
- placeholder = "Select options",
3362
+ var controlSizeClassNames = {
3363
+ sm: "h-8 px-2.5 text-xs",
3364
+ md: "h-9 px-3 text-sm",
3365
+ lg: "h-10 px-3.5 text-base"
3366
+ };
3367
+ var BaseInput = react.forwardRef(
3368
+ function BaseInput2({
2374
3369
  icon,
3370
+ trailing,
2375
3371
  invalid = false,
2376
3372
  disabled = false,
2377
- required = false,
2378
- openForPreview = false,
2379
- maxTagCount,
2380
- removeLabel = getDefaultRemoveLabel,
2381
- emptyLabel = "No options",
3373
+ readOnly = false,
3374
+ controlSize,
2382
3375
  appearance,
2383
3376
  className,
2384
3377
  classNames,
2385
3378
  style,
2386
- id,
2387
3379
  "aria-invalid": nativeAriaInvalid,
2388
- "aria-label": nativeAriaLabel,
2389
- "aria-labelledby": nativeAriaLabelledBy,
2390
- onValueChange,
2391
- ...rootProps
3380
+ ...inputProps
2392
3381
  }, ref) {
2393
- const theme = resolveBaseAppearance(appearance);
2394
- const generatedId = react.useId();
2395
- const multiSelectId = id ?? generatedId;
2396
- const controlId = `${multiSelectId}-control`;
2397
- const listboxId = `${multiSelectId}-listbox`;
2398
- const rootRef = react.useRef(null);
2399
- const optionList = options ?? [];
2400
- const forceOpen = openForPreview;
2401
- const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
2402
- const open = forceOpen || uncontrolledOpen;
2403
- const [uncontrolledValue, setUncontrolledValue] = react.useState(
2404
- () => normalizeValues(defaultValue)
2405
- );
2406
- const [activeIndex, setActiveIndex] = react.useState(
2407
- () => getFirstEnabledIndex(optionList)
2408
- );
2409
- const isControlled = value !== void 0;
2410
- const selectedValues = react.useMemo(
2411
- () => normalizeValues(isControlled ? value : uncontrolledValue),
2412
- [isControlled, uncontrolledValue, value]
2413
- );
2414
- const selectedValueSet = react.useMemo(
2415
- () => new Set(selectedValues),
2416
- [selectedValues]
2417
- );
2418
- const optionByValue = react.useMemo(() => {
2419
- const map = /* @__PURE__ */ new Map();
2420
- optionList.forEach((option) => {
2421
- if (!map.has(option.value)) {
2422
- map.set(option.value, option);
2423
- }
2424
- });
2425
- return map;
2426
- }, [optionList]);
2427
- const selectedOptions = react.useMemo(
2428
- () => selectedValues.map((selectedValue) => optionByValue.get(selectedValue)).filter(
2429
- (option) => option !== void 0
2430
- ),
2431
- [optionByValue, selectedValues]
2432
- );
2433
- const firstEnabledIndex = react.useMemo(
2434
- () => getFirstEnabledIndex(optionList),
2435
- [optionList]
2436
- );
2437
- const resolvedActiveIndex = activeIndex >= 0 && !optionList[activeIndex]?.disabled ? activeIndex : firstEnabledIndex;
2438
- const visibleTagCount = getSafeTagCount(
2439
- maxTagCount,
2440
- selectedOptions.length
2441
- );
2442
- const visibleOptions = selectedOptions.slice(0, visibleTagCount);
2443
- const overflowCount = selectedOptions.length - visibleOptions.length;
2444
- const isPlaceholder = selectedOptions.length === 0;
2445
- const setRootRef = (node) => {
2446
- rootRef.current = node;
2447
- if (typeof ref === "function") {
2448
- ref(node);
2449
- } else if (ref) {
2450
- ref.current = node;
2451
- }
2452
- };
2453
- const setOpen = (nextOpen) => {
2454
- if (disabled || forceOpen) return;
2455
- setUncontrolledOpen(nextOpen);
2456
- if (nextOpen) {
2457
- setActiveIndex(resolvedActiveIndex);
2458
- }
2459
- };
2460
- react.useEffect(() => {
2461
- if (!open || forceOpen) return void 0;
2462
- const handlePointerDown = (event) => {
2463
- if (!rootRef.current?.contains(event.target)) {
2464
- setUncontrolledOpen(false);
2465
- }
2466
- };
2467
- document.addEventListener("pointerdown", handlePointerDown);
2468
- return () => {
2469
- document.removeEventListener("pointerdown", handlePointerDown);
2470
- };
2471
- }, [forceOpen, open]);
2472
- react.useEffect(() => {
2473
- if (resolvedActiveIndex >= 0 && resolvedActiveIndex !== activeIndex) {
2474
- setActiveIndex(resolvedActiveIndex);
2475
- }
2476
- }, [activeIndex, resolvedActiveIndex]);
2477
- const commitValues = (nextValues) => {
2478
- const normalizedValues = normalizeValues(nextValues);
2479
- if (!isControlled) {
2480
- setUncontrolledValue(normalizedValues);
2481
- }
2482
- onValueChange?.(normalizedValues);
2483
- };
2484
- const toggleOption = (option) => {
2485
- if (!option || option.disabled || disabled) return;
2486
- const nextValues = selectedValueSet.has(option.value) ? selectedValues.filter((selectedValue) => selectedValue !== option.value) : [...selectedValues, option.value];
2487
- commitValues(nextValues);
2488
- };
2489
- const removeOption = (option) => {
2490
- if (disabled) return;
2491
- commitValues(
2492
- selectedValues.filter((selectedValue) => selectedValue !== option.value)
2493
- );
2494
- };
2495
- const focusOption = (direction) => {
2496
- const nextIndex = getNextEnabledIndex(
2497
- optionList,
2498
- resolvedActiveIndex,
2499
- direction
2500
- );
2501
- if (nextIndex >= 0) {
2502
- setActiveIndex(nextIndex);
2503
- }
2504
- };
2505
- const handleKeyDown = (event) => {
2506
- if (disabled) return;
2507
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2508
- event.preventDefault();
2509
- if (!open) {
2510
- setOpen(true);
2511
- setActiveIndex(firstEnabledIndex);
2512
- return;
2513
- }
2514
- focusOption(event.key === "ArrowDown" ? 1 : -1);
2515
- return;
2516
- }
2517
- if (event.key === "Home") {
2518
- event.preventDefault();
2519
- setOpen(true);
2520
- setActiveIndex(firstEnabledIndex);
2521
- return;
2522
- }
2523
- if (event.key === "End") {
2524
- event.preventDefault();
2525
- setOpen(true);
2526
- for (let index = optionList.length - 1; index >= 0; index -= 1) {
2527
- if (!optionList[index]?.disabled) {
2528
- setActiveIndex(index);
2529
- break;
2530
- }
2531
- }
2532
- return;
2533
- }
2534
- if (event.key === "Enter" || event.key === " ") {
2535
- event.preventDefault();
2536
- if (!open) {
2537
- setOpen(true);
2538
- return;
2539
- }
2540
- toggleOption(optionList[resolvedActiveIndex]);
2541
- return;
3382
+ for (const [name, value] of [
3383
+ ["invalid", invalid],
3384
+ ["disabled", disabled],
3385
+ ["readOnly", readOnly]
3386
+ ]) {
3387
+ if (typeof value !== "boolean") {
3388
+ throw new TypeError(`BaseInput ${name} must be a boolean.`);
2542
3389
  }
2543
- if (event.key === "Escape") {
2544
- setOpen(false);
2545
- }
2546
- };
3390
+ }
3391
+ if (controlSize !== void 0 && controlSize !== "sm" && controlSize !== "md" && controlSize !== "lg") {
3392
+ throw new TypeError('BaseInput controlSize must be "sm", "md", or "lg".');
3393
+ }
3394
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3395
+ const componentAttributes = useMonkeysComponentAttributes();
3396
+ const theme = resolveBaseAppearance(resolvedAppearance);
2547
3397
  return /* @__PURE__ */ jsxRuntime.jsxs(
2548
3398
  "div",
2549
3399
  {
2550
- ...rootProps,
2551
- id,
2552
- ref: setRootRef,
3400
+ ...componentAttributes,
3401
+ "data-monkeys-component": "input",
3402
+ "data-slot": "root",
3403
+ "data-size": controlSize,
3404
+ "data-invalid": invalid || void 0,
3405
+ "data-disabled": disabled || void 0,
3406
+ "data-readonly": readOnly || void 0,
2553
3407
  className: cn(
2554
3408
  theme.slots.controlWrapper,
2555
- "overflow-visible",
2556
- open && "z-50",
2557
3409
  invalid && theme.slots.controlInvalid,
2558
3410
  disabled && theme.slots.controlDisabled,
3411
+ readOnly && theme.slots.controlReadOnly,
2559
3412
  classNames?.root,
2560
3413
  className
2561
3414
  ),
@@ -2563,237 +3416,153 @@ react.forwardRef(
2563
3416
  ...theme.styles.control,
2564
3417
  ...invalid ? theme.styles.controlInvalid : void 0,
2565
3418
  ...disabled ? theme.styles.controlDisabled : void 0,
2566
- ...style
2567
- },
2568
- children: [
2569
- hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2570
- /* @__PURE__ */ jsxRuntime.jsx(
2571
- "div",
2572
- {
2573
- id: controlId,
2574
- role: "combobox",
2575
- tabIndex: disabled ? -1 : 0,
2576
- "aria-haspopup": "listbox",
2577
- "aria-expanded": open,
2578
- "aria-controls": listboxId,
2579
- "aria-disabled": disabled || void 0,
2580
- "aria-required": required || void 0,
2581
- "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2582
- "aria-label": nativeAriaLabel,
2583
- "aria-labelledby": nativeAriaLabelledBy,
2584
- className: cn(
2585
- theme.slots.controlBase,
2586
- "flex min-h-9 cursor-pointer flex-wrap items-center gap-1.5 py-1.5 pr-9 text-left",
2587
- disabled && "!cursor-not-allowed",
2588
- classNames?.control
2589
- ),
2590
- onClick: () => setOpen(!open),
2591
- onKeyDown: handleKeyDown,
2592
- children: /* @__PURE__ */ jsxRuntime.jsxs(
2593
- "span",
2594
- {
2595
- className: cn(
2596
- "flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
2597
- classNames?.tagList
2598
- ),
2599
- children: [
2600
- visibleOptions.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
2601
- "span",
2602
- {
2603
- className: cn(
2604
- "inline-flex max-w-full items-center gap-1 rounded-full border border-border/70 bg-muted/65 px-2 py-0.5 text-xs font-medium text-foreground",
2605
- classNames?.tag
2606
- ),
2607
- children: [
2608
- /* @__PURE__ */ jsxRuntime.jsx(
2609
- "span",
2610
- {
2611
- className: cn(
2612
- "max-w-40 truncate",
2613
- classNames?.tagLabel
2614
- ),
2615
- children: option.label
2616
- }
2617
- ),
2618
- /* @__PURE__ */ jsxRuntime.jsx(
2619
- "button",
2620
- {
2621
- type: "button",
2622
- "aria-label": removeLabel(option),
2623
- disabled,
2624
- className: cn(
2625
- "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-background/80 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:!cursor-not-allowed",
2626
- classNames?.tagRemove
2627
- ),
2628
- onClick: (event) => {
2629
- event.preventDefault();
2630
- event.stopPropagation();
2631
- removeOption(option);
2632
- },
2633
- onMouseDown: (event) => {
2634
- event.preventDefault();
2635
- event.stopPropagation();
2636
- },
2637
- onKeyDown: (event) => event.stopPropagation(),
2638
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "x" })
2639
- }
2640
- )
2641
- ]
2642
- },
2643
- option.value
2644
- )),
2645
- overflowCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
2646
- "span",
2647
- {
2648
- className: cn(
2649
- "inline-flex max-w-full items-center rounded-full border border-border/70 bg-muted/45 px-2 py-0.5 text-xs font-medium text-muted-foreground",
2650
- classNames?.tag
2651
- ),
2652
- children: [
2653
- "+",
2654
- overflowCount
2655
- ]
2656
- }
2657
- ) : null,
2658
- isPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
2659
- "span",
2660
- {
2661
- className: cn(
2662
- "min-w-0 truncate",
2663
- theme.slots.selectPlaceholder,
2664
- classNames?.placeholder
2665
- ),
2666
- children: placeholder
2667
- }
2668
- ) : null
2669
- ]
2670
- }
2671
- )
2672
- }
2673
- ),
2674
- /* @__PURE__ */ jsxRuntime.jsx(
2675
- "span",
2676
- {
2677
- className: cn(
2678
- theme.slots.selectChevron,
2679
- open && "rotate-[225deg]",
2680
- classNames?.chevron
2681
- )
2682
- }
2683
- ),
2684
- name ? selectedValues.map((selectedValue) => /* @__PURE__ */ jsxRuntime.jsx(
2685
- "input",
2686
- {
2687
- type: "hidden",
2688
- name,
2689
- value: selectedValue,
2690
- className: classNames?.hiddenInput
2691
- },
2692
- selectedValue
2693
- )) : null,
2694
- open ? /* @__PURE__ */ jsxRuntime.jsx(
2695
- "div",
2696
- {
2697
- id: listboxId,
2698
- role: "listbox",
2699
- "aria-multiselectable": "true",
2700
- "aria-labelledby": controlId,
2701
- className: cn(theme.slots.selectMenu, classNames?.menu),
2702
- style: theme.styles.selectMenu,
2703
- children: optionList.length > 0 ? optionList.map((option, index) => {
2704
- const selected = selectedValueSet.has(option.value);
2705
- const active = index === resolvedActiveIndex;
2706
- return /* @__PURE__ */ jsxRuntime.jsxs(
2707
- "button",
2708
- {
2709
- type: "button",
2710
- role: "option",
2711
- "aria-selected": selected,
2712
- disabled: option.disabled,
2713
- className: cn(
2714
- theme.slots.selectOption,
2715
- "gap-2",
2716
- active && theme.slots.selectOptionActive,
2717
- selected && theme.slots.selectOptionSelected,
2718
- option.disabled && theme.slots.selectOptionDisabled,
2719
- classNames?.option
2720
- ),
2721
- style: {
2722
- ...theme.styles.selectOption,
2723
- ...active ? theme.styles.selectOptionActive : void 0,
2724
- ...selected ? theme.styles.selectOptionSelected : void 0
2725
- },
2726
- onMouseEnter: () => {
2727
- if (!option.disabled) {
2728
- setActiveIndex(index);
2729
- }
2730
- },
2731
- onMouseDown: (event) => event.preventDefault(),
2732
- onClick: () => toggleOption(option),
2733
- children: [
2734
- /* @__PURE__ */ jsxRuntime.jsx(
2735
- "span",
2736
- {
2737
- "aria-hidden": "true",
2738
- className: cn(
2739
- "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border border-border/70 text-[10px]",
2740
- selected && "border-primary/40 bg-primary text-primary-foreground",
2741
- classNames?.optionIndicator
2742
- ),
2743
- children: selected ? "\u2713" : null
2744
- }
2745
- ),
2746
- /* @__PURE__ */ jsxRuntime.jsx(
2747
- "span",
2748
- {
2749
- className: cn(
2750
- "min-w-0 flex-1 truncate",
2751
- classNames?.optionLabel
2752
- ),
2753
- children: option.label
2754
- }
2755
- )
2756
- ]
2757
- },
2758
- option.value
2759
- );
2760
- }) : /* @__PURE__ */ jsxRuntime.jsx(
2761
- "div",
2762
- {
2763
- className: cn(
2764
- "px-2.5 py-2 text-sm text-muted-foreground",
2765
- classNames?.empty
2766
- ),
2767
- children: emptyLabel
2768
- }
3419
+ ...style
3420
+ },
3421
+ children: [
3422
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx(
3423
+ "span",
3424
+ {
3425
+ "data-slot": "icon",
3426
+ className: cn(theme.slots.controlIcon, classNames?.icon),
3427
+ children: icon
3428
+ }
3429
+ ) : null,
3430
+ /* @__PURE__ */ jsxRuntime.jsx(
3431
+ "input",
3432
+ {
3433
+ ...inputProps,
3434
+ ref,
3435
+ disabled,
3436
+ readOnly,
3437
+ "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
3438
+ "data-slot": "control",
3439
+ "data-size": controlSize,
3440
+ "data-invalid": invalid || void 0,
3441
+ "data-disabled": disabled || void 0,
3442
+ "data-readonly": readOnly || void 0,
3443
+ className: cn(
3444
+ theme.slots.controlBase,
3445
+ theme.slots.controlInput,
3446
+ controlSize && controlSizeClassNames[controlSize],
3447
+ classNames?.control
2769
3448
  )
2770
3449
  }
3450
+ ),
3451
+ hasRenderableNode(trailing) ? /* @__PURE__ */ jsxRuntime.jsx(
3452
+ "span",
3453
+ {
3454
+ "data-slot": "trailing",
3455
+ className: cn(theme.slots.controlTrailing, classNames?.trailing),
3456
+ children: trailing
3457
+ }
2771
3458
  ) : null
2772
3459
  ]
2773
3460
  }
2774
3461
  );
2775
3462
  }
2776
3463
  );
3464
+ var typeaheadResetDelay = 500;
3465
+ function noop() {
3466
+ }
3467
+ function validateSelectProps({
3468
+ options,
3469
+ value,
3470
+ defaultValue,
3471
+ invalid,
3472
+ disabled,
3473
+ openForPreview,
3474
+ required
3475
+ }) {
3476
+ for (const [name, state] of [
3477
+ ["invalid", invalid],
3478
+ ["disabled", disabled],
3479
+ ["openForPreview", openForPreview]
3480
+ ]) {
3481
+ if (typeof state !== "boolean") {
3482
+ throw new TypeError(`BaseSelect ${name} must be a boolean.`);
3483
+ }
3484
+ }
3485
+ if (required !== void 0 && typeof required !== "boolean") {
3486
+ throw new TypeError("BaseSelect required must be a boolean.");
3487
+ }
3488
+ if (options !== void 0 && !Array.isArray(options)) {
3489
+ throw new TypeError("BaseSelect options must be an array.");
3490
+ }
3491
+ options?.forEach((option, index) => {
3492
+ if (!option || typeof option !== "object") {
3493
+ throw new TypeError(`BaseSelect option at index ${index} must be an object.`);
3494
+ }
3495
+ if (typeof option.value !== "string") {
3496
+ throw new TypeError(
3497
+ `BaseSelect option value at index ${index} must be a string.`
3498
+ );
3499
+ }
3500
+ if (option.disabled !== void 0 && typeof option.disabled !== "boolean") {
3501
+ throw new TypeError(
3502
+ `BaseSelect option disabled at index ${index} must be a boolean.`
3503
+ );
3504
+ }
3505
+ if (option.textValue !== void 0 && typeof option.textValue !== "string") {
3506
+ throw new TypeError(
3507
+ `BaseSelect option textValue at index ${index} must be a string.`
3508
+ );
3509
+ }
3510
+ });
3511
+ if (options?.length) {
3512
+ if (value !== void 0 && typeof value !== "string" && typeof value !== "number") {
3513
+ throw new TypeError(
3514
+ "BaseSelect value must be a string or number when options are used."
3515
+ );
3516
+ }
3517
+ if (defaultValue !== void 0 && typeof defaultValue !== "string" && typeof defaultValue !== "number") {
3518
+ throw new TypeError(
3519
+ "BaseSelect defaultValue must be a string or number when options are used."
3520
+ );
3521
+ }
3522
+ }
3523
+ }
3524
+ function normalizeValue(value) {
3525
+ return typeof value === "string" || typeof value === "number" ? String(value) : "";
3526
+ }
2777
3527
  function findOption(options, value) {
2778
3528
  if (value === void 0) return void 0;
2779
3529
  return options.find((option) => option.value === value);
2780
3530
  }
2781
- function getInitialValue(options, defaultValue) {
2782
- if (typeof defaultValue === "string") {
2783
- return defaultValue;
2784
- }
2785
- return "";
3531
+ function getInitialActiveIndex(options, value) {
3532
+ const selectedIndex = options.findIndex(
3533
+ (option) => option.value === value && !option.disabled
3534
+ );
3535
+ if (selectedIndex >= 0) return selectedIndex;
3536
+ return options.findIndex((option) => !option.disabled);
2786
3537
  }
2787
- function getNextEnabledIndex2(options, currentIndex, direction) {
3538
+ function getNextEnabledIndex(options, currentIndex, direction) {
2788
3539
  if (!options.length) return -1;
3540
+ const startIndex = currentIndex >= 0 ? currentIndex : direction === 1 ? -1 : 0;
2789
3541
  for (let offset = 1; offset <= options.length; offset += 1) {
2790
- const nextIndex = (currentIndex + offset * direction + options.length) % options.length;
3542
+ const nextIndex = (startIndex + offset * direction + options.length) % options.length;
2791
3543
  if (!options[nextIndex]?.disabled) {
2792
3544
  return nextIndex;
2793
3545
  }
2794
3546
  }
2795
3547
  return -1;
2796
3548
  }
3549
+ function getBoundaryEnabledIndex(options, boundary) {
3550
+ if (boundary === "first") {
3551
+ return options.findIndex((option) => !option.disabled);
3552
+ }
3553
+ for (let index = options.length - 1; index >= 0; index -= 1) {
3554
+ if (!options[index]?.disabled) return index;
3555
+ }
3556
+ return -1;
3557
+ }
3558
+ function getOptionText(option) {
3559
+ if (option.textValue !== void 0) return option.textValue;
3560
+ if (typeof option.label === "string") return option.label;
3561
+ return option.value;
3562
+ }
3563
+ function toDomId(value) {
3564
+ return value.replace(/[^a-zA-Z0-9_-]/g, "-");
3565
+ }
2797
3566
  var BaseSelect = react.forwardRef(
2798
3567
  function BaseSelect2({
2799
3568
  options,
@@ -2810,40 +3579,64 @@ var BaseSelect = react.forwardRef(
2810
3579
  value,
2811
3580
  defaultValue,
2812
3581
  onChange,
3582
+ onFocus,
3583
+ onInvalid,
2813
3584
  name,
2814
3585
  id,
2815
3586
  required,
2816
3587
  "aria-invalid": nativeAriaInvalid,
2817
3588
  "aria-label": nativeAriaLabel,
2818
3589
  "aria-labelledby": nativeAriaLabelledBy,
3590
+ "aria-describedby": nativeAriaDescribedBy,
3591
+ "aria-errormessage": nativeAriaErrorMessage,
3592
+ "aria-required": nativeAriaRequired,
2819
3593
  ...selectProps
2820
3594
  }, ref) {
2821
- const theme = resolveBaseAppearance(appearance);
3595
+ validateSelectProps({
3596
+ options,
3597
+ value,
3598
+ defaultValue,
3599
+ invalid,
3600
+ disabled,
3601
+ openForPreview,
3602
+ required
3603
+ });
3604
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3605
+ const componentAttributes = useMonkeysComponentAttributes();
3606
+ const theme = resolveBaseAppearance(resolvedAppearance);
2822
3607
  const generatedId = react.useId();
2823
3608
  const selectId = id ?? generatedId;
3609
+ const triggerId = `${selectId}-button`;
2824
3610
  const listboxId = `${selectId}-listbox`;
2825
3611
  const rootRef = react.useRef(null);
3612
+ const triggerRef = react.useRef(null);
2826
3613
  const selectRef = react.useRef(null);
3614
+ const optionRefs = react.useRef([]);
3615
+ const composingRef = react.useRef(false);
3616
+ const typeaheadBufferRef = react.useRef("");
3617
+ const typeaheadTimerRef = react.useRef(null);
2827
3618
  const optionList = options ?? [];
2828
3619
  const isCustomSelect = optionList.length > 0;
2829
3620
  const forceOpen = openForPreview;
2830
3621
  const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
2831
3622
  const open = forceOpen || uncontrolledOpen;
2832
3623
  const [uncontrolledValue, setUncontrolledValue] = react.useState(
2833
- () => getInitialValue(optionList, defaultValue)
3624
+ () => normalizeValue(defaultValue)
2834
3625
  );
2835
3626
  const isControlled = value !== void 0;
2836
- const selectedValue = String(isControlled ? value : uncontrolledValue);
3627
+ const selectedValue = isControlled ? normalizeValue(value) : uncontrolledValue;
2837
3628
  const selectedOption = findOption(optionList, selectedValue);
2838
- const activeIndex = react.useMemo(() => {
2839
- const selectedIndex = optionList.findIndex(
2840
- (option) => option.value === selectedValue && !option.disabled
2841
- );
2842
- if (selectedIndex >= 0) return selectedIndex;
2843
- return optionList.findIndex((option) => !option.disabled);
2844
- }, [optionList, selectedValue]);
3629
+ const [activeIndex, setActiveIndex] = react.useState(
3630
+ () => getInitialActiveIndex(optionList, selectedValue)
3631
+ );
3632
+ const resolvedActiveIndex = activeIndex >= 0 && !optionList[activeIndex]?.disabled ? activeIndex : getInitialActiveIndex(optionList, selectedValue);
3633
+ const optionIds = optionList.map(
3634
+ (option, index) => `${selectId}-option-${index}-${toDomId(option.value)}`
3635
+ );
2845
3636
  const visibleLabel = selectedOption?.label ?? placeholder;
2846
3637
  const isPlaceholder = !selectedOption;
3638
+ const layerDirection = selectProps.dir ?? componentAttributes.dir;
3639
+ const rootState = disabled ? "disabled" : invalid ? "invalid" : open ? "open" : "closed";
2847
3640
  const setSelectRef = (node) => {
2848
3641
  selectRef.current = node;
2849
3642
  if (typeof ref === "function") {
@@ -2852,71 +3645,207 @@ var BaseSelect = react.forwardRef(
2852
3645
  ref.current = node;
2853
3646
  }
2854
3647
  };
2855
- react.useEffect(() => {
2856
- if (!open || forceOpen) return void 0;
2857
- const handlePointerDown = (event) => {
2858
- if (!rootRef.current?.contains(event.target)) {
2859
- setUncontrolledOpen(false);
2860
- }
2861
- };
2862
- document.addEventListener("pointerdown", handlePointerDown);
2863
- return () => {
2864
- document.removeEventListener("pointerdown", handlePointerDown);
2865
- };
2866
- }, [forceOpen, open]);
3648
+ const resetActiveIndex = () => {
3649
+ setActiveIndex(getInitialActiveIndex(optionList, selectedValue));
3650
+ };
3651
+ const cancelAndClose = () => {
3652
+ resetActiveIndex();
3653
+ if (!forceOpen) setUncontrolledOpen(false);
3654
+ };
3655
+ const openMenu = (nextActiveIndex) => {
3656
+ setActiveIndex(
3657
+ nextActiveIndex ?? getInitialActiveIndex(optionList, selectedValue)
3658
+ );
3659
+ if (!forceOpen) setUncontrolledOpen(true);
3660
+ };
2867
3661
  const notifyChange = (nextValue) => {
2868
3662
  const selectElement = selectRef.current;
2869
3663
  if (!selectElement) return;
3664
+ const ownerWindow = selectElement.ownerDocument.defaultView;
3665
+ if (!ownerWindow) {
3666
+ throw new Error(
3667
+ "BaseSelect cannot dispatch change without an owning window."
3668
+ );
3669
+ }
2870
3670
  const valueSetter = Object.getOwnPropertyDescriptor(
2871
- HTMLSelectElement.prototype,
3671
+ ownerWindow.HTMLSelectElement.prototype,
2872
3672
  "value"
2873
3673
  )?.set;
2874
- valueSetter?.call(selectElement, nextValue);
2875
- selectElement.dispatchEvent(new Event("change", { bubbles: true }));
2876
- };
2877
- const commitValue = (nextValue, optionDisabled) => {
2878
- if (optionDisabled || disabled) return;
2879
- if (!isControlled) {
2880
- setUncontrolledValue(nextValue);
3674
+ if (!valueSetter) {
3675
+ throw new Error("BaseSelect could not resolve the native select value setter.");
2881
3676
  }
2882
- notifyChange(nextValue);
2883
- if (!forceOpen) {
2884
- setUncontrolledOpen(false);
3677
+ valueSetter.call(selectElement, nextValue);
3678
+ selectElement.dispatchEvent(
3679
+ new ownerWindow.Event("change", { bubbles: true })
3680
+ );
3681
+ };
3682
+ const commitIndex = (nextIndex) => {
3683
+ const option = optionList[nextIndex];
3684
+ if (!option || option.disabled || disabled) return;
3685
+ setActiveIndex(nextIndex);
3686
+ if (option.value !== selectedValue) {
3687
+ if (!isControlled) {
3688
+ setUncontrolledValue(option.value);
3689
+ }
3690
+ notifyChange(option.value);
2885
3691
  }
3692
+ if (!forceOpen) setUncontrolledOpen(false);
3693
+ };
3694
+ const moveActive = (nextIndex) => {
3695
+ if (nextIndex < 0 || optionList[nextIndex]?.disabled) return;
3696
+ setActiveIndex(nextIndex);
3697
+ if (!open) openMenu(nextIndex);
2886
3698
  };
2887
- const focusOption = (direction) => {
2888
- const currentIndex = activeIndex >= 0 ? activeIndex : 0;
2889
- const nextIndex = getNextEnabledIndex2(optionList, currentIndex, direction);
2890
- if (nextIndex >= 0) {
2891
- commitValue(optionList[nextIndex].value, optionList[nextIndex].disabled);
3699
+ const handleTypeahead = (event, character) => {
3700
+ const ownerWindow = event.currentTarget.ownerDocument.defaultView;
3701
+ if (!ownerWindow) return;
3702
+ const nextBuffer = `${typeaheadBufferRef.current}${character}`.toLocaleLowerCase();
3703
+ typeaheadBufferRef.current = nextBuffer;
3704
+ if (typeaheadTimerRef.current) {
3705
+ typeaheadTimerRef.current.ownerWindow.clearTimeout(
3706
+ typeaheadTimerRef.current.timerId
3707
+ );
3708
+ }
3709
+ typeaheadTimerRef.current = {
3710
+ ownerWindow,
3711
+ timerId: ownerWindow.setTimeout(() => {
3712
+ typeaheadBufferRef.current = "";
3713
+ typeaheadTimerRef.current = null;
3714
+ }, typeaheadResetDelay)
3715
+ };
3716
+ const repeatedCharacter = Array.from(nextBuffer).every(
3717
+ (bufferCharacter) => bufferCharacter === nextBuffer[0]
3718
+ );
3719
+ const query = repeatedCharacter ? character.toLocaleLowerCase() : nextBuffer;
3720
+ const startIndex = open ? resolvedActiveIndex : optionList.findIndex(
3721
+ (option) => option.value === selectedValue && !option.disabled
3722
+ );
3723
+ for (let offset = 1; offset <= optionList.length; offset += 1) {
3724
+ const index = (startIndex + offset + optionList.length) % optionList.length;
3725
+ const option = optionList[index];
3726
+ if (!option?.disabled && getOptionText(option).trim().toLocaleLowerCase().startsWith(query)) {
3727
+ event.preventDefault();
3728
+ moveActive(index);
3729
+ return;
3730
+ }
2892
3731
  }
2893
3732
  };
2894
3733
  const handleKeyDown = (event) => {
2895
- if (disabled) return;
3734
+ if (disabled || composingRef.current || event.nativeEvent.isComposing) {
3735
+ return;
3736
+ }
2896
3737
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2897
3738
  event.preventDefault();
2898
- if (!open) {
2899
- setUncontrolledOpen(true);
2900
- return;
2901
- }
2902
- focusOption(event.key === "ArrowDown" ? 1 : -1);
3739
+ const selectedIndex = optionList.findIndex(
3740
+ (option) => option.value === selectedValue && !option.disabled
3741
+ );
3742
+ const currentIndex = open ? resolvedActiveIndex : selectedIndex;
3743
+ moveActive(
3744
+ getNextEnabledIndex(
3745
+ optionList,
3746
+ currentIndex,
3747
+ event.key === "ArrowDown" ? 1 : -1
3748
+ )
3749
+ );
3750
+ return;
3751
+ }
3752
+ if (event.key === "Home" || event.key === "End") {
3753
+ event.preventDefault();
3754
+ moveActive(
3755
+ getBoundaryEnabledIndex(
3756
+ optionList,
3757
+ event.key === "Home" ? "first" : "last"
3758
+ )
3759
+ );
2903
3760
  return;
2904
3761
  }
2905
3762
  if (event.key === "Enter" || event.key === " ") {
2906
3763
  event.preventDefault();
2907
- if (!forceOpen) {
2908
- setUncontrolledOpen((current) => !current);
3764
+ if (open) {
3765
+ commitIndex(resolvedActiveIndex);
3766
+ } else {
3767
+ openMenu();
2909
3768
  }
2910
3769
  return;
2911
3770
  }
2912
- if (event.key === "Escape") {
2913
- setUncontrolledOpen(false);
3771
+ if (event.key === "Escape" && open) {
3772
+ event.preventDefault();
3773
+ cancelAndClose();
3774
+ return;
3775
+ }
3776
+ if (event.key === "Tab" && open) {
3777
+ commitIndex(resolvedActiveIndex);
3778
+ return;
3779
+ }
3780
+ if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey && !/\s/.test(event.key)) {
3781
+ handleTypeahead(event, event.key);
2914
3782
  }
2915
3783
  };
3784
+ const handleCustomFocus = (event) => {
3785
+ onFocus?.(event);
3786
+ if (!event.defaultPrevented) triggerRef.current?.focus();
3787
+ };
3788
+ const handleCustomInvalid = (event) => {
3789
+ onInvalid?.(event);
3790
+ event.preventDefault();
3791
+ triggerRef.current?.focus();
3792
+ };
3793
+ react.useEffect(() => {
3794
+ if (!isCustomSelect || !open || forceOpen) return void 0;
3795
+ const ownerDocument = rootRef.current?.ownerDocument;
3796
+ if (!ownerDocument) return void 0;
3797
+ const handlePointerDown = (event) => {
3798
+ if (!rootRef.current?.contains(event.target)) {
3799
+ cancelAndClose();
3800
+ }
3801
+ };
3802
+ ownerDocument.addEventListener("pointerdown", handlePointerDown);
3803
+ return () => {
3804
+ ownerDocument.removeEventListener("pointerdown", handlePointerDown);
3805
+ };
3806
+ }, [forceOpen, isCustomSelect, open, optionList, selectedValue]);
3807
+ react.useEffect(() => {
3808
+ if (!isCustomSelect || !open || resolvedActiveIndex < 0) return;
3809
+ optionRefs.current[resolvedActiveIndex]?.scrollIntoView?.({
3810
+ block: "nearest"
3811
+ });
3812
+ }, [isCustomSelect, open, resolvedActiveIndex]);
3813
+ react.useEffect(() => {
3814
+ if (!isCustomSelect || isControlled) return void 0;
3815
+ const selectElement = selectRef.current;
3816
+ const form = selectElement?.form;
3817
+ const ownerWindow = selectElement?.ownerDocument.defaultView;
3818
+ if (!form || !ownerWindow) return void 0;
3819
+ const handleReset = () => {
3820
+ ownerWindow.setTimeout(() => {
3821
+ const resetValue = normalizeValue(defaultValue);
3822
+ setUncontrolledValue(resetValue);
3823
+ setActiveIndex(getInitialActiveIndex(optionList, resetValue));
3824
+ if (!forceOpen) setUncontrolledOpen(false);
3825
+ }, 0);
3826
+ };
3827
+ form.addEventListener("reset", handleReset);
3828
+ return () => form.removeEventListener("reset", handleReset);
3829
+ }, [defaultValue, forceOpen, isControlled, isCustomSelect, optionList]);
3830
+ react.useEffect(
3831
+ () => () => {
3832
+ if (typeaheadTimerRef.current) {
3833
+ typeaheadTimerRef.current.ownerWindow.clearTimeout(
3834
+ typeaheadTimerRef.current.timerId
3835
+ );
3836
+ }
3837
+ },
3838
+ []
3839
+ );
2916
3840
  if (!isCustomSelect) {
2917
3841
  return /* @__PURE__ */ jsxRuntime.jsxs(
2918
3842
  "div",
2919
3843
  {
3844
+ ...componentAttributes,
3845
+ "data-monkeys-component": "select",
3846
+ "data-slot": "root",
3847
+ "data-state": rootState,
3848
+ "data-native": "true",
2920
3849
  className: cn(
2921
3850
  theme.slots.controlWrapper,
2922
3851
  invalid && theme.slots.controlInvalid,
@@ -2935,6 +3864,7 @@ var BaseSelect = react.forwardRef(
2935
3864
  /* @__PURE__ */ jsxRuntime.jsxs(
2936
3865
  "select",
2937
3866
  {
3867
+ ...componentAttributes,
2938
3868
  ...selectProps,
2939
3869
  id,
2940
3870
  ref,
@@ -2946,6 +3876,15 @@ var BaseSelect = react.forwardRef(
2946
3876
  "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2947
3877
  "aria-label": nativeAriaLabel,
2948
3878
  "aria-labelledby": nativeAriaLabelledBy,
3879
+ "aria-describedby": nativeAriaDescribedBy,
3880
+ "aria-errormessage": nativeAriaErrorMessage,
3881
+ "aria-required": nativeAriaRequired,
3882
+ "data-monkeys-component": "select",
3883
+ "data-slot": "native",
3884
+ "data-state": rootState,
3885
+ "data-native": "true",
3886
+ onFocus,
3887
+ onInvalid,
2949
3888
  onChange,
2950
3889
  className: cn(
2951
3890
  theme.slots.controlBase,
@@ -2966,7 +3905,13 @@ var BaseSelect = react.forwardRef(
2966
3905
  return /* @__PURE__ */ jsxRuntime.jsxs(
2967
3906
  "div",
2968
3907
  {
3908
+ ...componentAttributes,
2969
3909
  ref: rootRef,
3910
+ dir: layerDirection,
3911
+ "data-monkeys-component": "select",
3912
+ "data-slot": "root",
3913
+ "data-state": rootState,
3914
+ "data-native": "false",
2970
3915
  className: cn(
2971
3916
  theme.slots.controlWrapper,
2972
3917
  "overflow-visible",
@@ -2987,15 +3932,27 @@ var BaseSelect = react.forwardRef(
2987
3932
  /* @__PURE__ */ jsxRuntime.jsx(
2988
3933
  "button",
2989
3934
  {
3935
+ ...componentAttributes,
3936
+ ref: triggerRef,
2990
3937
  type: "button",
2991
- id: `${selectId}-button`,
3938
+ id: triggerId,
3939
+ role: "combobox",
2992
3940
  disabled,
3941
+ dir: layerDirection,
2993
3942
  "aria-haspopup": "listbox",
2994
3943
  "aria-expanded": open,
2995
3944
  "aria-controls": listboxId,
3945
+ "aria-activedescendant": open && resolvedActiveIndex >= 0 ? optionIds[resolvedActiveIndex] : void 0,
3946
+ "aria-autocomplete": "none",
2996
3947
  "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2997
3948
  "aria-label": nativeAriaLabel,
2998
3949
  "aria-labelledby": nativeAriaLabelledBy,
3950
+ "aria-describedby": nativeAriaDescribedBy,
3951
+ "aria-errormessage": nativeAriaErrorMessage,
3952
+ "aria-required": nativeAriaRequired ?? (required || void 0),
3953
+ "data-monkeys-component": "select",
3954
+ "data-slot": "trigger",
3955
+ "data-state": rootState,
2999
3956
  className: cn(
3000
3957
  theme.slots.controlBase,
3001
3958
  theme.slots.controlSelect,
@@ -3003,10 +3960,20 @@ var BaseSelect = react.forwardRef(
3003
3960
  classNames?.control
3004
3961
  ),
3005
3962
  onClick: () => {
3006
- if (!forceOpen) {
3007
- setUncontrolledOpen((current) => !current);
3963
+ if (open) cancelAndClose();
3964
+ else openMenu();
3965
+ },
3966
+ onBlur: (event) => {
3967
+ if (!rootRef.current?.contains(event.relatedTarget)) {
3968
+ cancelAndClose();
3008
3969
  }
3009
3970
  },
3971
+ onCompositionStart: () => {
3972
+ composingRef.current = true;
3973
+ },
3974
+ onCompositionEnd: () => {
3975
+ composingRef.current = false;
3976
+ },
3010
3977
  onKeyDown: handleKeyDown,
3011
3978
  children: /* @__PURE__ */ jsxRuntime.jsx(
3012
3979
  "span",
@@ -3033,6 +4000,7 @@ var BaseSelect = react.forwardRef(
3033
4000
  /* @__PURE__ */ jsxRuntime.jsxs(
3034
4001
  "select",
3035
4002
  {
4003
+ ...componentAttributes,
3036
4004
  ...selectProps,
3037
4005
  ref: setSelectRef,
3038
4006
  id,
@@ -3040,10 +4008,17 @@ var BaseSelect = react.forwardRef(
3040
4008
  value: selectedValue,
3041
4009
  required,
3042
4010
  disabled,
4011
+ dir: layerDirection,
3043
4012
  "aria-hidden": "true",
3044
4013
  tabIndex: -1,
4014
+ "data-monkeys-component": "select",
4015
+ "data-slot": "native",
4016
+ "data-state": rootState,
4017
+ "data-native": "false",
3045
4018
  className: theme.slots.selectNative,
3046
- onChange,
4019
+ onFocus: handleCustomFocus,
4020
+ onInvalid: handleCustomInvalid,
4021
+ onChange: onChange ?? noop,
3047
4022
  children: [
3048
4023
  hasRenderableNode(placeholder) ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }) : null,
3049
4024
  optionList.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -3051,7 +4026,7 @@ var BaseSelect = react.forwardRef(
3051
4026
  {
3052
4027
  value: option.value,
3053
4028
  disabled: option.disabled,
3054
- children: typeof option.label === "string" ? option.label : option.value
4029
+ children: getOptionText(option)
3055
4030
  },
3056
4031
  option.value
3057
4032
  ))
@@ -3061,21 +4036,41 @@ var BaseSelect = react.forwardRef(
3061
4036
  open ? /* @__PURE__ */ jsxRuntime.jsx(
3062
4037
  "div",
3063
4038
  {
4039
+ ...componentAttributes,
3064
4040
  id: listboxId,
3065
4041
  role: "listbox",
3066
- "aria-labelledby": `${selectId}-button`,
4042
+ dir: layerDirection,
4043
+ "aria-labelledby": triggerId,
4044
+ "data-monkeys-component": "select",
4045
+ "data-slot": "menu",
4046
+ "data-state": "open",
3067
4047
  className: cn(theme.slots.selectMenu, classNames?.menu),
3068
4048
  style: theme.styles.selectMenu,
3069
4049
  children: optionList.map((option, index) => {
3070
4050
  const selected = option.value === selectedValue;
3071
- const active = index === activeIndex;
3072
- return /* @__PURE__ */ jsxRuntime.jsx(
4051
+ const active = index === resolvedActiveIndex;
4052
+ const optionState = option.disabled ? "disabled" : active ? "active" : selected ? "selected" : "idle";
4053
+ return /* @__PURE__ */ react.createElement(
3073
4054
  "button",
3074
4055
  {
4056
+ ...componentAttributes,
4057
+ ref: (node) => {
4058
+ optionRefs.current[index] = node;
4059
+ },
4060
+ key: option.value,
4061
+ id: optionIds[index],
3075
4062
  type: "button",
3076
4063
  role: "option",
3077
- "aria-selected": selected,
4064
+ tabIndex: -1,
3078
4065
  disabled: option.disabled,
4066
+ dir: layerDirection,
4067
+ "aria-selected": selected,
4068
+ "data-monkeys-component": "select",
4069
+ "data-slot": "option",
4070
+ "data-state": optionState,
4071
+ "data-active": active || void 0,
4072
+ "data-selected": selected || void 0,
4073
+ "data-disabled": option.disabled || void 0,
3079
4074
  className: cn(
3080
4075
  theme.slots.selectOption,
3081
4076
  active && theme.slots.selectOptionActive,
@@ -3089,10 +4084,9 @@ var BaseSelect = react.forwardRef(
3089
4084
  ...selected ? theme.styles.selectOptionSelected : void 0
3090
4085
  },
3091
4086
  onMouseDown: (event) => event.preventDefault(),
3092
- onClick: () => commitValue(option.value, option.disabled),
3093
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: option.label })
4087
+ onClick: () => commitIndex(index)
3094
4088
  },
3095
- option.value
4089
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: option.label })
3096
4090
  );
3097
4091
  })
3098
4092
  }
@@ -3173,115 +4167,193 @@ function BaseSegmentedControl({
3173
4167
  }
3174
4168
  );
3175
4169
  }
3176
- react.forwardRef(
3177
- function BaseSwitch2({
3178
- label,
3179
- description,
3180
- disabled = false,
3181
- appearance,
3182
- className,
3183
- classNames,
3184
- style,
3185
- checked,
3186
- defaultChecked,
3187
- onChange,
3188
- ...switchProps
3189
- }, ref) {
3190
- const theme = resolveBaseAppearance(appearance);
3191
- const [uncontrolledChecked, setUncontrolledChecked] = react.useState(
3192
- defaultChecked ?? false
4170
+ var DATA_TRANSFER_COLUMN_TYPE = "application/x-monkeys-base-table-column";
4171
+ var COLUMN_RESIZE_KEYBOARD_STEP = 8;
4172
+ function assignRef2(ref, value) {
4173
+ if (typeof ref === "function") {
4174
+ ref(value);
4175
+ } else if (ref) {
4176
+ ref.current = value;
4177
+ }
4178
+ }
4179
+ function assertBoolean(name, value) {
4180
+ if (value !== void 0 && typeof value !== "boolean") {
4181
+ throw new Error(`BaseTable ${name} must be a boolean.`);
4182
+ }
4183
+ }
4184
+ function assertEnum(name, value, values) {
4185
+ if (value !== void 0 && !values.includes(value)) {
4186
+ throw new Error(
4187
+ `BaseTable ${name} must be one of ${values.map((item) => `"${item}"`).join(", ")}.`
3193
4188
  );
3194
- const isControlled = checked !== void 0;
3195
- const resolvedChecked = isControlled ? checked : uncontrolledChecked;
3196
- const handleChange = (event) => {
3197
- if (!isControlled) {
3198
- setUncontrolledChecked(event.currentTarget.checked);
3199
- }
3200
- onChange?.(event);
3201
- };
3202
- return /* @__PURE__ */ jsxRuntime.jsxs(
3203
- "label",
3204
- {
3205
- className: cn(
3206
- theme.slots.switchRoot,
3207
- disabled && theme.slots.switchDisabled,
3208
- classNames?.root,
3209
- className
3210
- ),
3211
- style: {
3212
- ...theme.styles.switchRoot,
3213
- ...style
3214
- },
3215
- children: [
3216
- /* @__PURE__ */ jsxRuntime.jsxs(
3217
- "span",
3218
- {
3219
- className: cn(
3220
- theme.slots.switchTrack,
3221
- resolvedChecked && theme.slots.switchChecked,
3222
- classNames?.track
3223
- ),
3224
- style: theme.styles.switchTrack,
3225
- children: [
3226
- /* @__PURE__ */ jsxRuntime.jsx(
3227
- "input",
3228
- {
3229
- ...switchProps,
3230
- ref,
3231
- type: "checkbox",
3232
- disabled,
3233
- checked,
3234
- defaultChecked,
3235
- onChange: handleChange,
3236
- className: cn(theme.slots.switchInput, classNames?.input)
3237
- }
3238
- ),
3239
- /* @__PURE__ */ jsxRuntime.jsx(
3240
- "span",
3241
- {
3242
- className: cn(
3243
- theme.slots.switchThumb,
3244
- resolvedChecked && "translate-x-5",
3245
- classNames?.thumb
3246
- ),
3247
- style: theme.styles.switchThumb
3248
- }
3249
- )
3250
- ]
3251
- }
3252
- ),
3253
- hasRenderableNode(label) || hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(theme.slots.switchContent, classNames?.content), children: [
3254
- hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.switchLabel, classNames?.label), children: label }) : null,
3255
- hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
3256
- "span",
3257
- {
3258
- className: cn(
3259
- theme.slots.switchDescription,
3260
- classNames?.description
3261
- ),
3262
- children: description
3263
- }
3264
- ) : null
3265
- ] }) : null
3266
- ]
3267
- }
4189
+ }
4190
+ }
4191
+ function assertOptionalLabel(name, value) {
4192
+ if (value !== void 0 && (typeof value !== "string" || value.trim().length === 0)) {
4193
+ throw new Error(`BaseTable ${name} must be a non-empty string when provided.`);
4194
+ }
4195
+ }
4196
+ function assertOptionalFunction(name, value) {
4197
+ if (value !== void 0 && typeof value !== "function") {
4198
+ throw new Error(`BaseTable ${name} must be a function when provided.`);
4199
+ }
4200
+ }
4201
+ function validateCssSizeValue(value, name, options = {}) {
4202
+ if (value === void 0) return;
4203
+ if (typeof value === "number") {
4204
+ if (!Number.isFinite(value) || value < 0) {
4205
+ throw new Error(
4206
+ `BaseTable ${name} must be a finite non-negative number${options.stringAllowed ? " or a non-empty CSS size string" : ""}.`
4207
+ );
4208
+ }
4209
+ return;
4210
+ }
4211
+ if (options.stringAllowed && typeof value === "string" && value.trim().length > 0) {
4212
+ return;
4213
+ }
4214
+ throw new Error(
4215
+ `BaseTable ${name} must be ${options.stringAllowed ? "a finite non-negative number or a non-empty CSS size string" : "a finite non-negative number"}.`
4216
+ );
4217
+ }
4218
+ function validateColumns(columns) {
4219
+ if (columns === void 0) return void 0;
4220
+ if (!Array.isArray(columns)) {
4221
+ throw new Error("BaseTable columns must be an array when provided.");
4222
+ }
4223
+ const ids = /* @__PURE__ */ new Set();
4224
+ columns.forEach((column, index) => {
4225
+ if (!column || typeof column !== "object" || Array.isArray(column)) {
4226
+ throw new Error(`BaseTable column at index ${index} must be an object.`);
4227
+ }
4228
+ const definition = column;
4229
+ if (typeof definition.id !== "string" || definition.id.trim().length === 0) {
4230
+ throw new Error(
4231
+ `BaseTable column id at index ${index} must be a non-empty string.`
4232
+ );
4233
+ }
4234
+ const columnId = definition.id.trim();
4235
+ if (definition.id !== columnId) {
4236
+ throw new Error(
4237
+ `BaseTable column id "${definition.id}" must not contain surrounding whitespace.`
4238
+ );
4239
+ }
4240
+ if (ids.has(columnId)) {
4241
+ throw new Error(`BaseTable columns contain duplicate id "${columnId}".`);
4242
+ }
4243
+ ids.add(columnId);
4244
+ validateCssSizeValue(definition.width, `column "${columnId}" width`, {
4245
+ stringAllowed: true
4246
+ });
4247
+ validateCssSizeValue(definition.minWidth, `column "${columnId}" minWidth`, {
4248
+ stringAllowed: true
4249
+ });
4250
+ validateCssSizeValue(definition.maxWidth, `column "${columnId}" maxWidth`, {
4251
+ stringAllowed: true
4252
+ });
4253
+ if (typeof definition.minWidth === "number" && typeof definition.maxWidth === "number" && definition.minWidth > definition.maxWidth) {
4254
+ throw new Error(
4255
+ `BaseTable column "${columnId}" minWidth cannot be greater than maxWidth.`
4256
+ );
4257
+ }
4258
+ });
4259
+ return ids;
4260
+ }
4261
+ function validateColumnOrder(columnOrder, knownColumnIds) {
4262
+ if (columnOrder === void 0) return;
4263
+ if (!Array.isArray(columnOrder)) {
4264
+ throw new Error("BaseTable columnOrder must be an array when provided.");
4265
+ }
4266
+ const ids = /* @__PURE__ */ new Set();
4267
+ columnOrder.forEach((value, index) => {
4268
+ if (typeof value !== "string" || value.trim().length === 0) {
4269
+ throw new Error(
4270
+ `BaseTable columnOrder entry at index ${index} must be a non-empty string.`
4271
+ );
4272
+ }
4273
+ const columnId = value.trim();
4274
+ if (value !== columnId) {
4275
+ throw new Error(
4276
+ `BaseTable columnOrder entry "${value}" must not contain surrounding whitespace.`
4277
+ );
4278
+ }
4279
+ if (ids.has(columnId)) {
4280
+ throw new Error(
4281
+ `BaseTable columnOrder contains duplicate id "${columnId}".`
4282
+ );
4283
+ }
4284
+ if (knownColumnIds && !knownColumnIds.has(columnId)) {
4285
+ throw new Error(
4286
+ `BaseTable columnOrder contains unknown column id "${columnId}".`
4287
+ );
4288
+ }
4289
+ ids.add(columnId);
4290
+ });
4291
+ if (knownColumnIds && ids.size !== knownColumnIds.size) {
4292
+ const missing = [...knownColumnIds].filter((columnId) => !ids.has(columnId));
4293
+ throw new Error(
4294
+ `BaseTable columnOrder must contain every configured column id; missing ${missing.map((columnId) => `"${columnId}"`).join(", ")}.`
3268
4295
  );
3269
4296
  }
3270
- );
3271
- var DATA_TRANSFER_COLUMN_TYPE = "application/x-monkeys-base-table-column";
4297
+ }
4298
+ function validateColumnSizes(columnSizes, knownColumnIds) {
4299
+ if (columnSizes === void 0) return;
4300
+ if (!columnSizes || typeof columnSizes !== "object" || Array.isArray(columnSizes) || ![Object.prototype, null].includes(Object.getPrototypeOf(columnSizes))) {
4301
+ throw new Error(
4302
+ "BaseTable columnSizes must be a plain record when provided."
4303
+ );
4304
+ }
4305
+ Object.entries(columnSizes).forEach(([columnId, value]) => {
4306
+ const normalizedColumnId = columnId.trim();
4307
+ if (normalizedColumnId.length === 0) {
4308
+ throw new Error("BaseTable columnSizes keys must be non-empty strings.");
4309
+ }
4310
+ if (columnId !== normalizedColumnId) {
4311
+ throw new Error(
4312
+ `BaseTable columnSizes key "${columnId}" must not contain surrounding whitespace.`
4313
+ );
4314
+ }
4315
+ if (knownColumnIds && !knownColumnIds.has(normalizedColumnId)) {
4316
+ throw new Error(
4317
+ `BaseTable columnSizes contains unknown column id "${columnId}".`
4318
+ );
4319
+ }
4320
+ validateCssSizeValue(value, `columnSizes["${columnId}"]`);
4321
+ });
4322
+ }
4323
+ function isRtl(element) {
4324
+ const ownerWindow = element.ownerDocument.defaultView;
4325
+ if (ownerWindow) {
4326
+ return ownerWindow.getComputedStyle(element).direction === "rtl";
4327
+ }
4328
+ return element.closest('[dir="rtl"]') !== null;
4329
+ }
4330
+ function setPointerCaptureIfAvailable(target, pointerId) {
4331
+ if (!target.setPointerCapture) return;
4332
+ try {
4333
+ target.setPointerCapture(pointerId);
4334
+ } catch (error) {
4335
+ const OwnerDOMException = target.ownerDocument.defaultView?.DOMException;
4336
+ if (OwnerDOMException && error instanceof OwnerDOMException && error.name === "NotFoundError") {
4337
+ return;
4338
+ }
4339
+ throw error;
4340
+ }
4341
+ }
3272
4342
  var BaseTableContext = react.createContext(null);
3273
4343
  function useBaseTableContext(appearance) {
3274
4344
  const context = react.useContext(BaseTableContext);
4345
+ const providerAppearance = useMonkeysBaseAppearance(appearance);
3275
4346
  if (context) {
4347
+ const resolvedAppearance = appearance === void 0 ? context.appearance : providerAppearance;
3276
4348
  return {
3277
4349
  ...context,
3278
- theme: appearance ? resolveBaseAppearance(appearance) : context.theme,
3279
- appearance: appearance ?? context.appearance
4350
+ theme: appearance === void 0 ? context.theme : resolveBaseAppearance(resolvedAppearance),
4351
+ appearance: resolvedAppearance
3280
4352
  };
3281
4353
  }
3282
- const theme = resolveBaseAppearance(appearance);
4354
+ const theme = resolveBaseAppearance(providerAppearance);
3283
4355
  return {
3284
- appearance,
4356
+ appearance: providerAppearance,
3285
4357
  theme,
3286
4358
  layout: "native",
3287
4359
  setDraggingColumnId: () => {
@@ -3454,7 +4526,7 @@ function DragHandleIcon() {
3454
4526
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-0.5 w-0.5 rounded-full bg-current" })
3455
4527
  ] });
3456
4528
  }
3457
- function BaseTableContainer({
4529
+ var BaseTableContainer = react.forwardRef(function BaseTableContainer2({
3458
4530
  appearance,
3459
4531
  attachedFooter = false,
3460
4532
  children,
@@ -3462,8 +4534,11 @@ function BaseTableContainer({
3462
4534
  classNames,
3463
4535
  style,
3464
4536
  ...containerProps
3465
- }) {
3466
- const theme = resolveBaseAppearance(appearance);
4537
+ }, ref) {
4538
+ assertBoolean("attachedFooter", attachedFooter);
4539
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
4540
+ const componentAttributes = useMonkeysComponentAttributes();
4541
+ const theme = resolveBaseAppearance(resolvedAppearance);
3467
4542
  const containsSplitScrollTable = hasSplitScrollTable(children);
3468
4543
  const splitScrollContainerStyle = containsSplitScrollTable ? {
3469
4544
  overflow: "hidden",
@@ -3472,7 +4547,11 @@ function BaseTableContainer({
3472
4547
  return /* @__PURE__ */ jsxRuntime.jsx(
3473
4548
  "div",
3474
4549
  {
4550
+ ...componentAttributes,
3475
4551
  ...containerProps,
4552
+ ref,
4553
+ "data-monkeys-component": "table-container",
4554
+ "data-slot": "container",
3476
4555
  "data-base-table-container": "",
3477
4556
  "data-attached-footer": attachedFooter ? "" : void 0,
3478
4557
  className: cn(
@@ -3490,84 +4569,100 @@ function BaseTableContainer({
3490
4569
  children
3491
4570
  }
3492
4571
  );
3493
- }
3494
- function BaseTable({
3495
- appearance,
3496
- className,
3497
- classNames,
3498
- style,
3499
- layout = "native",
3500
- columns,
3501
- bodyMaxHeight,
3502
- bodyClassName,
3503
- columnOrder,
3504
- columnSizes,
3505
- columnDragEnabled = false,
3506
- columnResizeEnabled = false,
3507
- onColumnOrderChange,
3508
- onColumnSizeChange,
3509
- ...tableProps
3510
- }) {
3511
- const theme = resolveBaseAppearance(appearance);
3512
- const [draggingColumnId, setDraggingColumnId] = react.useState();
3513
- const splitHeaderRef = react.useRef(null);
3514
- const splitFooterRef = react.useRef(null);
3515
- const isSplitScroll = layout === "split-scroll";
3516
- const columnTemplate = isSplitScroll ? buildSplitColumnTemplate(columns, columnSizes) : void 0;
3517
- const contextValue = {
4572
+ });
4573
+ var BaseTable = react.forwardRef(
4574
+ function BaseTable2({
3518
4575
  appearance,
3519
- theme,
3520
- layout,
3521
- columnTemplate,
4576
+ className,
4577
+ classNames,
4578
+ style,
4579
+ layout = "native",
4580
+ columns,
3522
4581
  bodyMaxHeight,
3523
4582
  bodyClassName,
3524
- splitHeaderRef,
3525
- splitFooterRef,
3526
4583
  columnOrder,
3527
4584
  columnSizes,
3528
- columnDragEnabled,
3529
- columnResizeEnabled,
4585
+ columnDragEnabled = false,
4586
+ columnResizeEnabled = false,
3530
4587
  onColumnOrderChange,
3531
4588
  onColumnSizeChange,
3532
- draggingColumnId,
3533
- setDraggingColumnId
3534
- };
3535
- return /* @__PURE__ */ jsxRuntime.jsx(BaseTableContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
3536
- "table",
3537
- {
3538
- ...tableProps,
3539
- "data-base-table-layout": layout,
3540
- className: cn(
3541
- theme.slots.tableRoot,
3542
- isSplitScroll && theme.slots.tableSplitRoot,
3543
- classNames?.root,
3544
- className
3545
- ),
3546
- style: {
3547
- ...theme.styles.table,
3548
- ...isSplitScroll ? theme.styles.tableSplitRoot : void 0,
3549
- ...columnTemplate ? {
3550
- "--base-table-column-template": columnTemplate
3551
- } : void 0,
3552
- ...style
4589
+ ...tableProps
4590
+ }, ref) {
4591
+ assertEnum("layout", layout, ["native", "split-scroll"]);
4592
+ assertBoolean("columnDragEnabled", columnDragEnabled);
4593
+ assertBoolean("columnResizeEnabled", columnResizeEnabled);
4594
+ assertOptionalFunction("onColumnOrderChange", onColumnOrderChange);
4595
+ assertOptionalFunction("onColumnSizeChange", onColumnSizeChange);
4596
+ validateCssSizeValue(bodyMaxHeight, "bodyMaxHeight", { stringAllowed: true });
4597
+ const knownColumnIds = validateColumns(columns);
4598
+ validateColumnOrder(columnOrder, knownColumnIds);
4599
+ validateColumnSizes(columnSizes, knownColumnIds);
4600
+ const resolvedAppearance = useMonkeysBaseAppearance(appearance);
4601
+ const componentAttributes = useMonkeysComponentAttributes();
4602
+ const theme = resolveBaseAppearance(resolvedAppearance);
4603
+ const [draggingColumnId, setDraggingColumnId] = react.useState();
4604
+ const splitHeaderRef = react.useRef(null);
4605
+ const splitFooterRef = react.useRef(null);
4606
+ const isSplitScroll = layout === "split-scroll";
4607
+ const columnTemplate = isSplitScroll ? buildSplitColumnTemplate(columns, columnSizes) : void 0;
4608
+ const contextValue = {
4609
+ appearance: resolvedAppearance,
4610
+ theme,
4611
+ layout,
4612
+ columnTemplate,
4613
+ bodyMaxHeight,
4614
+ bodyClassName,
4615
+ splitHeaderRef,
4616
+ splitFooterRef,
4617
+ columnOrder,
4618
+ columnSizes,
4619
+ columnDragEnabled,
4620
+ columnResizeEnabled,
4621
+ onColumnOrderChange,
4622
+ onColumnSizeChange,
4623
+ draggingColumnId,
4624
+ setDraggingColumnId
4625
+ };
4626
+ return /* @__PURE__ */ jsxRuntime.jsx(BaseTableContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
4627
+ "table",
4628
+ {
4629
+ ...componentAttributes,
4630
+ ...tableProps,
4631
+ ref,
4632
+ "data-monkeys-component": "table",
4633
+ "data-slot": "root",
4634
+ "data-base-table-layout": layout,
4635
+ className: cn(
4636
+ theme.slots.tableRoot,
4637
+ isSplitScroll && theme.slots.tableSplitRoot,
4638
+ classNames?.root,
4639
+ className
4640
+ ),
4641
+ style: {
4642
+ ...theme.styles.table,
4643
+ ...isSplitScroll ? theme.styles.tableSplitRoot : void 0,
4644
+ ...columnTemplate ? {
4645
+ "--base-table-column-template": columnTemplate
4646
+ } : void 0,
4647
+ ...style
4648
+ }
3553
4649
  }
3554
- }
3555
- ) });
3556
- }
3557
- function BaseTableHeader({
3558
- appearance,
3559
- className,
3560
- classNames,
3561
- style,
3562
- ...headerProps
3563
- }) {
4650
+ ) });
4651
+ }
4652
+ );
4653
+ var BaseTableHeader = react.forwardRef(function BaseTableHeader2({ appearance, className, classNames, style, ...headerProps }, ref) {
3564
4654
  const { layout, splitHeaderRef, theme } = useBaseTableContext(appearance);
3565
4655
  const isSplitScroll = layout === "split-scroll";
4656
+ const setHeaderRef = (node) => {
4657
+ if (splitHeaderRef) splitHeaderRef.current = isSplitScroll ? node : null;
4658
+ assignRef2(ref, node);
4659
+ };
3566
4660
  return /* @__PURE__ */ jsxRuntime.jsx(
3567
4661
  "thead",
3568
4662
  {
3569
4663
  ...headerProps,
3570
- ref: isSplitScroll ? splitHeaderRef : void 0,
4664
+ ref: setHeaderRef,
4665
+ "data-slot": "header",
3571
4666
  className: cn(
3572
4667
  theme.slots.tableHeader,
3573
4668
  isSplitScroll && theme.slots.tableSplitHeader,
@@ -3581,15 +4676,8 @@ function BaseTableHeader({
3581
4676
  }
3582
4677
  }
3583
4678
  );
3584
- }
3585
- function BaseTableBody({
3586
- appearance,
3587
- className,
3588
- classNames,
3589
- onScroll,
3590
- style,
3591
- ...bodyProps
3592
- }) {
4679
+ });
4680
+ var BaseTableBody = react.forwardRef(function BaseTableBody2({ appearance, className, classNames, onScroll, style, ...bodyProps }, ref) {
3593
4681
  const {
3594
4682
  bodyClassName,
3595
4683
  bodyMaxHeight,
@@ -3613,6 +4701,8 @@ function BaseTableBody({
3613
4701
  "tbody",
3614
4702
  {
3615
4703
  ...bodyProps,
4704
+ ref,
4705
+ "data-slot": "body",
3616
4706
  onScroll: handleScroll,
3617
4707
  className: cn(
3618
4708
  theme.slots.tableBody,
@@ -3629,42 +4719,76 @@ function BaseTableBody({
3629
4719
  }
3630
4720
  }
3631
4721
  );
3632
- }
3633
- function BaseTableRow({
3634
- interactive,
3635
- selected,
3636
- disabled,
3637
- appearance,
3638
- className,
3639
- classNames,
3640
- style,
3641
- ...rowProps
3642
- }) {
3643
- const { layout, theme } = useBaseTableContext(appearance);
4722
+ });
4723
+ react.forwardRef(function BaseTableFooter2({ appearance, className, classNames, style, ...footerProps }, ref) {
4724
+ const { layout, splitFooterRef, theme } = useBaseTableContext(appearance);
3644
4725
  const isSplitScroll = layout === "split-scroll";
4726
+ const setFooterRef = (node) => {
4727
+ if (splitFooterRef) splitFooterRef.current = isSplitScroll ? node : null;
4728
+ assignRef2(ref, node);
4729
+ };
3645
4730
  return /* @__PURE__ */ jsxRuntime.jsx(
3646
- "tr",
4731
+ "tfoot",
3647
4732
  {
3648
- ...rowProps,
3649
- "aria-disabled": disabled || void 0,
3650
- "data-state": selected ? "selected" : void 0,
4733
+ ...footerProps,
4734
+ ref: setFooterRef,
4735
+ "data-slot": "footer",
3651
4736
  className: cn(
3652
- theme.slots.tableRow,
3653
- isSplitScroll && theme.slots.tableSplitRow,
3654
- interactive && !disabled && theme.slots.tableRowInteractive,
3655
- selected && theme.slots.tableRowSelected,
3656
- disabled && theme.slots.tableRowDisabled,
4737
+ theme.slots.tableFooter,
4738
+ isSplitScroll && theme.slots.tableSplitFooter,
3657
4739
  classNames?.root,
3658
4740
  className
3659
4741
  ),
3660
4742
  style: {
3661
- ...theme.styles.tableRow,
3662
- ...isSplitScroll ? theme.styles.tableSplitRow : void 0,
4743
+ ...theme.styles.tableFooter,
4744
+ ...isSplitScroll ? theme.styles.tableSplitFooter : void 0,
3663
4745
  ...style
3664
4746
  }
3665
4747
  }
3666
4748
  );
3667
- }
4749
+ });
4750
+ var BaseTableRow = react.forwardRef(
4751
+ function BaseTableRow2({
4752
+ interactive,
4753
+ selected,
4754
+ disabled,
4755
+ appearance,
4756
+ className,
4757
+ classNames,
4758
+ style,
4759
+ ...rowProps
4760
+ }, ref) {
4761
+ assertBoolean("interactive", interactive);
4762
+ assertBoolean("selected", selected);
4763
+ assertBoolean("disabled", disabled);
4764
+ const { layout, theme } = useBaseTableContext(appearance);
4765
+ const isSplitScroll = layout === "split-scroll";
4766
+ return /* @__PURE__ */ jsxRuntime.jsx(
4767
+ "tr",
4768
+ {
4769
+ ...rowProps,
4770
+ ref,
4771
+ "data-slot": "row",
4772
+ "aria-disabled": disabled || void 0,
4773
+ "data-state": selected ? "selected" : void 0,
4774
+ className: cn(
4775
+ theme.slots.tableRow,
4776
+ isSplitScroll && theme.slots.tableSplitRow,
4777
+ interactive && !disabled && theme.slots.tableRowInteractive,
4778
+ selected && theme.slots.tableRowSelected,
4779
+ disabled && theme.slots.tableRowDisabled,
4780
+ classNames?.root,
4781
+ className
4782
+ ),
4783
+ style: {
4784
+ ...theme.styles.tableRow,
4785
+ ...isSplitScroll ? theme.styles.tableSplitRow : void 0,
4786
+ ...style
4787
+ }
4788
+ }
4789
+ );
4790
+ }
4791
+ );
3668
4792
  var BaseTableHead = react.forwardRef(function BaseTableHead2({
3669
4793
  columnId,
3670
4794
  align,
@@ -3695,19 +4819,48 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3695
4819
  onDrop,
3696
4820
  ...headProps
3697
4821
  }, forwardedRef) {
4822
+ assertEnum("head align", align, ["left", "center", "right"]);
4823
+ assertEnum("head verticalAlign", verticalAlign, [
4824
+ "top",
4825
+ "middle",
4826
+ "bottom"
4827
+ ]);
4828
+ assertEnum("head sortDirection", sortDirection, [
4829
+ "asc",
4830
+ "desc",
4831
+ "none"
4832
+ ]);
4833
+ assertBoolean("head sortable", sortable);
4834
+ assertBoolean("head draggable", draggable);
4835
+ assertBoolean("head resizable", resizable);
4836
+ assertOptionalFunction("head onSort", onSort);
4837
+ assertOptionalLabel("head sortLabel", sortLabel);
4838
+ assertOptionalLabel("head dragLabel", dragLabel);
4839
+ assertOptionalLabel("head resizeLabel", resizeLabel);
4840
+ if (columnId !== void 0 && (typeof columnId !== "string" || columnId.trim().length === 0)) {
4841
+ throw new Error(
4842
+ "BaseTable head columnId must be a non-empty string when provided."
4843
+ );
4844
+ }
4845
+ validateCssSizeValue(width, "head width", { stringAllowed: true });
4846
+ validateCssSizeValue(minWidth, "head minWidth");
4847
+ validateCssSizeValue(maxWidth, "head maxWidth");
4848
+ if (minWidth !== void 0 && maxWidth !== void 0 && minWidth > maxWidth) {
4849
+ throw new Error("BaseTable head minWidth cannot be greater than maxWidth.");
4850
+ }
3698
4851
  const tableContext = useBaseTableContext(appearance);
3699
4852
  const { theme } = tableContext;
4853
+ const messages = useMonkeysLocaleMessages().table;
3700
4854
  const isSplitScroll = tableContext.layout === "split-scroll";
3701
4855
  const resolvedAlign = align ?? (isSplitScroll ? "center" : "left");
3702
4856
  const resolvedVerticalAlign = verticalAlign ?? "middle";
3703
4857
  const headRef = react.useRef(null);
4858
+ const resizeCleanupRef = react.useRef(() => {
4859
+ });
4860
+ const [measuredWidth, setMeasuredWidth] = react.useState();
3704
4861
  const setHeadRef = (node) => {
3705
4862
  headRef.current = node;
3706
- if (typeof forwardedRef === "function") {
3707
- forwardedRef(node);
3708
- } else if (forwardedRef) {
3709
- forwardedRef.current = node;
3710
- }
4863
+ assignRef2(forwardedRef, node);
3711
4864
  };
3712
4865
  const controlledWidth = columnId && tableContext.columnSizes?.[columnId] !== void 0 ? tableContext.columnSizes[columnId] : width;
3713
4866
  const canDrag = Boolean(
@@ -3716,9 +4869,16 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3716
4869
  const canResize = Boolean(
3717
4870
  columnId && resizable !== false && (resizable || tableContext.columnResizeEnabled) && tableContext.onColumnSizeChange
3718
4871
  );
4872
+ if (canResize && maxWidth !== void 0 && maxWidth < (minWidth ?? 48)) {
4873
+ throw new Error(
4874
+ "BaseTable resizable head maxWidth cannot be smaller than its effective minWidth."
4875
+ );
4876
+ }
3719
4877
  const interactiveSort = Boolean(sortable || onSort);
3720
4878
  const ariaSort = sortAriaValue(sortDirection);
3721
4879
  const content = hasRenderableNode(label) ? label : children;
4880
+ const hasVisibleSortName = hasRenderableNode(content) || hasRenderableNode(description);
4881
+ const sortAccessibleName = sortLabel ?? (!hasVisibleSortName ? messages.sortColumn({ columnId: columnId?.trim() || void 0 }) : void 0);
3722
4882
  const usesRichHeader = canDrag || hasRenderableNode(icon) || hasRenderableNode(label) || hasRenderableNode(description) || hasRenderableNode(meta) || hasRenderableNode(actions) || hasRenderableNode(trailing) || interactiveSort;
3723
4883
  const renderedContent = usesRichHeader ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(theme.slots.tableHeadContent, classNames?.content), children: [
3724
4884
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(theme.slots.tableHeadMain, classNames?.main), children: [
@@ -3728,9 +4888,32 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3728
4888
  type: "button",
3729
4889
  draggable: true,
3730
4890
  title: dragLabel,
3731
- "aria-label": dragLabel ?? `Drag column ${columnId}`,
4891
+ "aria-label": dragLabel ?? messages.dragColumn({ columnId }),
3732
4892
  className: cn(theme.slots.tableHeadDragHandle, classNames?.dragHandle),
3733
4893
  onClick: (event) => event.stopPropagation(),
4894
+ onKeyDown: (event) => {
4895
+ if (!columnId || !tableContext.columnOrder || event.key !== "ArrowLeft" && event.key !== "ArrowRight") {
4896
+ return;
4897
+ }
4898
+ const currentIndex = tableContext.columnOrder.indexOf(columnId);
4899
+ if (currentIndex < 0) return;
4900
+ const rtl = isRtl(event.currentTarget);
4901
+ const physicalDelta = event.key === "ArrowLeft" ? -1 : 1;
4902
+ const nextIndex = currentIndex + (rtl ? -physicalDelta : physicalDelta);
4903
+ const targetColumnId = tableContext.columnOrder[nextIndex];
4904
+ if (!targetColumnId) return;
4905
+ const nextOrder = getNextColumnOrder(
4906
+ tableContext.columnOrder,
4907
+ columnId,
4908
+ targetColumnId
4909
+ );
4910
+ if (!nextOrder) return;
4911
+ event.preventDefault();
4912
+ tableContext.onColumnOrderChange?.(nextOrder, {
4913
+ columnId,
4914
+ targetColumnId
4915
+ });
4916
+ },
3734
4917
  onDragStart: (event) => {
3735
4918
  event.stopPropagation();
3736
4919
  tableContext.setDraggingColumnId(columnId);
@@ -3751,6 +4934,7 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3751
4934
  type: "button",
3752
4935
  disabled: !onSort,
3753
4936
  title: sortLabel,
4937
+ "aria-label": sortAccessibleName,
3754
4938
  className: cn(theme.slots.tableHeadSortButton, classNames?.sortButton),
3755
4939
  onClick: (event) => {
3756
4940
  event.stopPropagation();
@@ -3827,18 +5011,23 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3827
5011
  tableContext.setDraggingColumnId(void 0);
3828
5012
  };
3829
5013
  const handleResizePointerDown = (event) => {
3830
- if (!canResize || !columnId || !tableContext.onColumnSizeChange) return;
5014
+ if (!canResize || !columnId || !tableContext.onColumnSizeChange || event.button !== 0 && event.pointerType !== "touch") {
5015
+ return;
5016
+ }
3831
5017
  event.preventDefault();
3832
5018
  event.stopPropagation();
5019
+ resizeCleanupRef.current();
3833
5020
  const startX = event.clientX;
3834
- const currentWidth = typeof controlledWidth === "number" ? controlledWidth : headRef.current?.offsetWidth ?? minWidth ?? 96;
5021
+ const currentWidth = currentResizeWidth ?? headRef.current?.offsetWidth ?? minWidth ?? 48;
3835
5022
  const previousWidth = clampWidth2(currentWidth, minWidth, maxWidth);
3836
5023
  const pointerId = event.pointerId;
3837
5024
  const target = event.currentTarget;
3838
- target.setPointerCapture?.(pointerId);
5025
+ const ownerDocument = target.ownerDocument;
5026
+ const rtl = isRtl(target);
3839
5027
  const handlePointerMove = (moveEvent) => {
5028
+ if (moveEvent.pointerId !== pointerId) return;
3840
5029
  const nextWidth = clampWidth2(
3841
- previousWidth + moveEvent.clientX - startX,
5030
+ previousWidth + (rtl ? startX - moveEvent.clientX : moveEvent.clientX - startX),
3842
5031
  minWidth,
3843
5032
  maxWidth
3844
5033
  );
@@ -3849,21 +5038,87 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3849
5038
  maxWidth
3850
5039
  });
3851
5040
  };
3852
- const cleanup = () => {
3853
- target.releasePointerCapture?.(pointerId);
3854
- window.removeEventListener("pointermove", handlePointerMove);
3855
- window.removeEventListener("pointerup", cleanup);
3856
- window.removeEventListener("pointercancel", cleanup);
5041
+ const handleStop = (nextEvent) => {
5042
+ if (nextEvent.pointerId !== pointerId) return;
5043
+ resizeCleanupRef.current();
3857
5044
  };
3858
- window.addEventListener("pointermove", handlePointerMove);
3859
- window.addEventListener("pointerup", cleanup);
3860
- window.addEventListener("pointercancel", cleanup);
5045
+ const handleLostCapture = (nextEvent) => {
5046
+ if (nextEvent.pointerId !== pointerId) return;
5047
+ resizeCleanupRef.current();
5048
+ };
5049
+ resizeCleanupRef.current = () => {
5050
+ ownerDocument.removeEventListener("pointermove", handlePointerMove);
5051
+ ownerDocument.removeEventListener("pointerup", handleStop);
5052
+ ownerDocument.removeEventListener("pointercancel", handleStop);
5053
+ target.removeEventListener("lostpointercapture", handleLostCapture);
5054
+ if (target.hasPointerCapture?.(pointerId)) {
5055
+ target.releasePointerCapture?.(pointerId);
5056
+ }
5057
+ resizeCleanupRef.current = () => {
5058
+ };
5059
+ };
5060
+ setPointerCaptureIfAvailable(target, pointerId);
5061
+ ownerDocument.addEventListener("pointermove", handlePointerMove);
5062
+ ownerDocument.addEventListener("pointerup", handleStop);
5063
+ ownerDocument.addEventListener("pointercancel", handleStop);
5064
+ target.addEventListener("lostpointercapture", handleLostCapture);
5065
+ };
5066
+ const currentResizeWidth = typeof controlledWidth === "number" ? clampWidth2(controlledWidth, minWidth, maxWidth) : measuredWidth;
5067
+ const announcedResizeWidth = currentResizeWidth ?? clampWidth2(minWidth ?? 48, minWidth, maxWidth);
5068
+ const handleResizeKeyDown = (event) => {
5069
+ if (!canResize || !columnId || !tableContext.onColumnSizeChange) return;
5070
+ const rtl = isRtl(event.currentTarget);
5071
+ const previousWidth = currentResizeWidth ?? clampWidth2(
5072
+ headRef.current?.offsetWidth || minWidth || 48,
5073
+ minWidth,
5074
+ maxWidth
5075
+ );
5076
+ let nextWidth;
5077
+ if (event.key === "ArrowLeft") {
5078
+ nextWidth = previousWidth + (rtl ? COLUMN_RESIZE_KEYBOARD_STEP : -COLUMN_RESIZE_KEYBOARD_STEP);
5079
+ }
5080
+ if (event.key === "ArrowRight") {
5081
+ nextWidth = previousWidth + (rtl ? -COLUMN_RESIZE_KEYBOARD_STEP : COLUMN_RESIZE_KEYBOARD_STEP);
5082
+ }
5083
+ if (event.key === "Home" && minWidth !== void 0) nextWidth = minWidth;
5084
+ if (event.key === "End" && maxWidth !== void 0) nextWidth = maxWidth;
5085
+ if (nextWidth === void 0) return;
5086
+ event.preventDefault();
5087
+ event.stopPropagation();
5088
+ tableContext.onColumnSizeChange(
5089
+ columnId,
5090
+ clampWidth2(nextWidth, minWidth, maxWidth),
5091
+ {
5092
+ columnId,
5093
+ previousWidth,
5094
+ minWidth,
5095
+ maxWidth
5096
+ }
5097
+ );
3861
5098
  };
5099
+ react.useEffect(() => {
5100
+ if (typeof controlledWidth === "number") {
5101
+ setMeasuredWidth(void 0);
5102
+ return;
5103
+ }
5104
+ const measured = headRef.current?.getBoundingClientRect().width;
5105
+ if (measured && Number.isFinite(measured)) {
5106
+ const nextWidth = clampWidth2(measured, minWidth, maxWidth);
5107
+ setMeasuredWidth(
5108
+ (current) => current === nextWidth ? current : nextWidth
5109
+ );
5110
+ }
5111
+ }, [controlledWidth, minWidth, maxWidth, canResize]);
5112
+ react.useEffect(() => {
5113
+ if (!canResize) resizeCleanupRef.current();
5114
+ return () => resizeCleanupRef.current();
5115
+ }, [canResize, columnId, tableContext.onColumnSizeChange]);
3862
5116
  return /* @__PURE__ */ jsxRuntime.jsxs(
3863
5117
  "th",
3864
5118
  {
3865
5119
  ...headProps,
3866
5120
  ref: setHeadRef,
5121
+ "data-slot": "head",
3867
5122
  scope: headProps.scope ?? "col",
3868
5123
  "aria-sort": ariaSort,
3869
5124
  className: cn(
@@ -3895,10 +5150,17 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3895
5150
  "button",
3896
5151
  {
3897
5152
  type: "button",
5153
+ role: "separator",
5154
+ "aria-orientation": "vertical",
5155
+ "aria-valuenow": announcedResizeWidth,
5156
+ "aria-valuemin": minWidth ?? 48,
5157
+ "aria-valuemax": maxWidth,
5158
+ "aria-valuetext": `${announcedResizeWidth}px`,
3898
5159
  title: resizeLabel,
3899
- "aria-label": resizeLabel ?? `Resize column ${columnId}`,
5160
+ "aria-label": resizeLabel ?? messages.resizeColumn({ columnId }),
3900
5161
  className: cn(theme.slots.tableHeadResizeHandle, classNames?.resizeHandle),
3901
5162
  onClick: (event) => event.stopPropagation(),
5163
+ onKeyDown: handleResizeKeyDown,
3902
5164
  onPointerDown: handleResizePointerDown
3903
5165
  }
3904
5166
  ) : null
@@ -3906,134 +5168,122 @@ var BaseTableHead = react.forwardRef(function BaseTableHead2({
3906
5168
  }
3907
5169
  );
3908
5170
  });
3909
- function BaseTableCell({
3910
- align = "left",
3911
- appearance,
3912
- className,
3913
- classNames,
3914
- style,
3915
- ...cellProps
3916
- }) {
3917
- const { layout, theme } = useBaseTableContext(appearance);
3918
- const isSplitScroll = layout === "split-scroll";
3919
- return /* @__PURE__ */ jsxRuntime.jsx(
3920
- "td",
3921
- {
3922
- ...cellProps,
3923
- className: cn(
3924
- theme.slots.tableCell,
3925
- isSplitScroll && theme.slots.tableSplitCell,
3926
- align === "center" && theme.slots.tableCellAlignCenter,
3927
- align === "right" && theme.slots.tableCellAlignRight,
3928
- classNames?.root,
3929
- className
3930
- ),
3931
- style: {
3932
- ...theme.styles.tableCell,
3933
- ...isSplitScroll ? theme.styles.tableSplitCell : void 0,
3934
- ...style
5171
+ var BaseTableCell = react.forwardRef(
5172
+ function BaseTableCell2({
5173
+ align = "left",
5174
+ appearance,
5175
+ className,
5176
+ classNames,
5177
+ style,
5178
+ ...cellProps
5179
+ }, ref) {
5180
+ assertEnum("cell align", align, ["left", "center", "right"]);
5181
+ const { layout, theme } = useBaseTableContext(appearance);
5182
+ const isSplitScroll = layout === "split-scroll";
5183
+ return /* @__PURE__ */ jsxRuntime.jsx(
5184
+ "td",
5185
+ {
5186
+ ...cellProps,
5187
+ ref,
5188
+ "data-slot": "cell",
5189
+ className: cn(
5190
+ theme.slots.tableCell,
5191
+ isSplitScroll && theme.slots.tableSplitCell,
5192
+ align === "center" && theme.slots.tableCellAlignCenter,
5193
+ align === "right" && theme.slots.tableCellAlignRight,
5194
+ classNames?.root,
5195
+ className
5196
+ ),
5197
+ style: {
5198
+ ...theme.styles.tableCell,
5199
+ ...isSplitScroll ? theme.styles.tableSplitCell : void 0,
5200
+ ...style
5201
+ }
3935
5202
  }
3936
- }
3937
- );
3938
- }
3939
- function BaseTableEmpty({
3940
- colSpan,
3941
- icon,
3942
- title,
3943
- description,
3944
- actions,
3945
- children,
3946
- appearance,
3947
- className,
3948
- classNames,
3949
- style,
3950
- ...emptyProps
3951
- }) {
3952
- const { layout, theme } = useBaseTableContext(appearance);
3953
- const isSplitScroll = layout === "split-scroll";
3954
- const hasStructuredContent = hasRenderableNode(icon) || hasRenderableNode(title) || hasRenderableNode(description) || hasRenderableNode(actions);
5203
+ );
5204
+ }
5205
+ );
5206
+ react.forwardRef(function BaseTableCaption2({ appearance, className, classNames, style, ...captionProps }, ref) {
5207
+ const { theme } = useBaseTableContext(appearance);
3955
5208
  return /* @__PURE__ */ jsxRuntime.jsx(
3956
- "tr",
5209
+ "caption",
3957
5210
  {
3958
- ...emptyProps,
3959
- className: cn(
3960
- theme.slots.tableEmptyRow,
3961
- isSplitScroll && theme.slots.tableSplitRow,
3962
- classNames?.row,
3963
- className
3964
- ),
5211
+ ...captionProps,
5212
+ ref,
5213
+ "data-slot": "caption",
5214
+ className: cn(theme.slots.tableCaption, classNames?.root, className),
3965
5215
  style: {
3966
- ...theme.styles.tableEmpty,
3967
- ...isSplitScroll ? theme.styles.tableSplitRow : void 0,
5216
+ ...theme.styles.tableCaption,
3968
5217
  ...style
3969
- },
3970
- children: /* @__PURE__ */ jsxRuntime.jsx(
3971
- "td",
3972
- {
3973
- colSpan: Math.max(colSpan, 1),
3974
- className: cn(
3975
- theme.slots.tableEmptyCell,
3976
- isSplitScroll && theme.slots.tableSplitCell,
3977
- classNames?.cell
3978
- ),
3979
- style: isSplitScroll ? { gridColumn: "1 / -1" } : void 0,
3980
- children: hasStructuredContent ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(theme.slots.tableEmptyContent, classNames?.content), children: [
3981
- hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyIcon, classNames?.icon), children: icon }) : null,
3982
- hasRenderableNode(title) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyTitle, classNames?.title), children: title }) : null,
3983
- hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
3984
- "div",
3985
- {
3986
- className: cn(
3987
- theme.slots.tableEmptyDescription,
3988
- classNames?.description
3989
- ),
3990
- children: description
3991
- }
3992
- ) : null,
3993
- hasRenderableNode(actions) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyActions, classNames?.actions), children: actions }) : null
3994
- ] }) : children
3995
- }
3996
- )
5218
+ }
3997
5219
  }
3998
5220
  );
3999
- }
4000
- react.forwardRef(
4001
- function BaseTextarea2({
4002
- invalid = false,
4003
- disabled = false,
4004
- readOnly = false,
5221
+ });
5222
+ var BaseTableEmpty = react.forwardRef(
5223
+ function BaseTableEmpty2({
5224
+ colSpan,
5225
+ icon,
5226
+ title,
5227
+ description,
5228
+ actions,
5229
+ children,
4005
5230
  appearance,
4006
5231
  className,
4007
5232
  classNames,
4008
5233
  style,
4009
- "aria-invalid": nativeAriaInvalid,
4010
- ...textareaProps
5234
+ ...emptyProps
4011
5235
  }, ref) {
4012
- const theme = resolveBaseAppearance(appearance);
5236
+ if (!Number.isSafeInteger(colSpan) || colSpan < 1) {
5237
+ throw new Error("BaseTable empty colSpan must be a positive safe integer.");
5238
+ }
5239
+ const { layout, theme } = useBaseTableContext(appearance);
5240
+ const isSplitScroll = layout === "split-scroll";
5241
+ const hasStructuredContent = hasRenderableNode(icon) || hasRenderableNode(title) || hasRenderableNode(description) || hasRenderableNode(actions);
4013
5242
  return /* @__PURE__ */ jsxRuntime.jsx(
4014
- "textarea",
5243
+ "tr",
4015
5244
  {
4016
- ...textareaProps,
5245
+ ...emptyProps,
4017
5246
  ref,
4018
- disabled,
4019
- readOnly,
4020
- "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
5247
+ "data-slot": "empty-row",
4021
5248
  className: cn(
4022
- theme.slots.controlWrapper,
4023
- theme.slots.controlBase,
4024
- theme.slots.controlTextarea,
4025
- invalid && theme.slots.controlInvalid,
4026
- disabled && theme.slots.controlDisabled,
4027
- readOnly && theme.slots.controlReadOnly,
4028
- classNames?.control,
5249
+ theme.slots.tableEmptyRow,
5250
+ isSplitScroll && theme.slots.tableSplitRow,
5251
+ classNames?.row,
4029
5252
  className
4030
5253
  ),
4031
5254
  style: {
4032
- ...theme.styles.control,
4033
- ...invalid ? theme.styles.controlInvalid : void 0,
4034
- ...disabled ? theme.styles.controlDisabled : void 0,
5255
+ ...theme.styles.tableEmpty,
5256
+ ...isSplitScroll ? theme.styles.tableSplitRow : void 0,
4035
5257
  ...style
4036
- }
5258
+ },
5259
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5260
+ "td",
5261
+ {
5262
+ colSpan,
5263
+ "data-slot": "empty-cell",
5264
+ className: cn(
5265
+ theme.slots.tableEmptyCell,
5266
+ isSplitScroll && theme.slots.tableSplitCell,
5267
+ classNames?.cell
5268
+ ),
5269
+ style: isSplitScroll ? { gridColumn: "1 / -1" } : void 0,
5270
+ children: hasStructuredContent ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(theme.slots.tableEmptyContent, classNames?.content), children: [
5271
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyIcon, classNames?.icon), children: icon }) : null,
5272
+ hasRenderableNode(title) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyTitle, classNames?.title), children: title }) : null,
5273
+ hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
5274
+ "div",
5275
+ {
5276
+ className: cn(
5277
+ theme.slots.tableEmptyDescription,
5278
+ classNames?.description
5279
+ ),
5280
+ children: description
5281
+ }
5282
+ ) : null,
5283
+ hasRenderableNode(actions) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(theme.slots.tableEmptyActions, classNames?.actions), children: actions }) : null
5284
+ ] }) : children
5285
+ }
5286
+ )
4037
5287
  }
4038
5288
  );
4039
5289
  }
@@ -5526,6 +6776,7 @@ function InteractiveTable({
5526
6776
  onFrozenEndColumnCountChange,
5527
6777
  onSort
5528
6778
  }) {
6779
+ const internalLabels = useMonkeysLocaleMessages().workbench.interactiveTable;
5529
6780
  const columnKeySignature = columns.map((column) => column.key).join("");
5530
6781
  const defaultOrder = react.useMemo(
5531
6782
  () => columnKeySignature ? columnKeySignature.split("") : [],
@@ -5563,14 +6814,14 @@ function InteractiveTable({
5563
6814
  const frozenEndOffsets = buildFrozenEndOffsets(orderedColumns, resolvedColumnSizes, resolvedFrozenEndColumnCount);
5564
6815
  const resolvedMinWidth = tableMinWidth ?? Math.max(760, orderedColumns.reduce((total, column) => total + getColumnNumericWidth(column, resolvedColumnSizes), 0));
5565
6816
  const labels = {
5566
- columnActions: columnMenuLabels?.columnActions ?? "Column actions",
5567
- freezeColumn: columnMenuLabels?.freezeColumn ?? "Freeze to left",
5568
- freezeEndColumn: columnMenuLabels?.freezeEndColumn ?? "Freeze to right",
5569
- unfreezeColumn: columnMenuLabels?.unfreezeColumn ?? "Unfreeze from left",
5570
- unfreezeEndColumn: columnMenuLabels?.unfreezeEndColumn ?? "Unfreeze from right",
5571
- unfreezeAllColumns: columnMenuLabels?.unfreezeAllColumns ?? "Unfreeze all columns",
5572
- resetColumnWidth: columnMenuLabels?.resetColumnWidth ?? "Reset column width",
5573
- frozenColumnTitle: columnMenuLabels?.frozenColumnTitle ?? "Frozen column"
6817
+ columnActions: columnMenuLabels?.columnActions ?? internalLabels.columnActions,
6818
+ freezeColumn: columnMenuLabels?.freezeColumn ?? internalLabels.freezeColumn,
6819
+ freezeEndColumn: columnMenuLabels?.freezeEndColumn ?? internalLabels.freezeEndColumn,
6820
+ unfreezeColumn: columnMenuLabels?.unfreezeColumn ?? internalLabels.unfreezeColumn,
6821
+ unfreezeEndColumn: columnMenuLabels?.unfreezeEndColumn ?? internalLabels.unfreezeEndColumn,
6822
+ unfreezeAllColumns: columnMenuLabels?.unfreezeAllColumns ?? internalLabels.unfreezeAllColumns,
6823
+ resetColumnWidth: columnMenuLabels?.resetColumnWidth ?? internalLabels.resetColumnWidth,
6824
+ frozenColumnTitle: columnMenuLabels?.frozenColumnTitle ?? internalLabels.frozenColumnTitle
5574
6825
  };
5575
6826
  const handleColumnOrderChange = react.useCallback((nextOrder, detail) => {
5576
6827
  const normalizedOrder = normalizeColumnOrder2(defaultOrder, nextOrder);