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