@deadragdoll/reactnu 0.1.24 → 0.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -945,6 +945,7 @@ function ListBoxItemViewInner({
945
945
  item,
946
946
  itemId,
947
947
  onActivate,
948
+ onPopupMenu,
948
949
  onDoubleClick,
949
950
  onToggleCheck,
950
951
  registerItemRef,
@@ -963,6 +964,9 @@ function ListBoxItemViewInner({
963
964
  onDoubleClick?.(item, group);
964
965
  }
965
966
  }
967
+ function handleContextMenu(event) {
968
+ onPopupMenu?.(event, item, group, itemId);
969
+ }
966
970
  function handleToggleCheck() {
967
971
  onToggleCheck(itemId);
968
972
  }
@@ -991,6 +995,7 @@ function ListBoxItemViewInner({
991
995
  ].filter(Boolean).join(" "),
992
996
  id: itemId,
993
997
  onClick: handleActivate,
998
+ onContextMenu: onPopupMenu ? handleContextMenu : void 0,
994
999
  onDoubleClick: handleDoubleClick,
995
1000
  ref: (node) => registerItemRef(itemId, node),
996
1001
  role: "option",
@@ -1016,6 +1021,7 @@ function ListBoxGroupView({
1016
1021
  listboxId,
1017
1022
  onActivateItem,
1018
1023
  onDoubleClickItem,
1024
+ onPopupMenuItem,
1019
1025
  onToggleItemCheck,
1020
1026
  registerItemRef,
1021
1027
  resolvedActiveId,
@@ -1047,6 +1053,7 @@ function ListBoxGroupView({
1047
1053
  itemId,
1048
1054
  onActivate: onActivateItem,
1049
1055
  onDoubleClick: onDoubleClickItem,
1056
+ onPopupMenu: onPopupMenuItem,
1050
1057
  onToggleCheck: onToggleItemCheck,
1051
1058
  registerItemRef,
1052
1059
  rightCheckBox,
@@ -1065,6 +1072,7 @@ function ListBoxInner({
1065
1072
  data,
1066
1073
  checkedIds,
1067
1074
  emptyText = "No items",
1075
+ onPopupMenu,
1068
1076
  onItemCheckChange,
1069
1077
  onItemDoubleClick,
1070
1078
  onItemSelect,
@@ -1124,6 +1132,18 @@ function ListBoxInner({
1124
1132
  },
1125
1133
  [activateItem, selectableItems]
1126
1134
  );
1135
+ const handleItemPopupMenu = useCallback2(
1136
+ (event, item, group, itemId) => {
1137
+ if (item.disabled || !onPopupMenu) {
1138
+ return;
1139
+ }
1140
+ event.preventDefault();
1141
+ event.stopPropagation();
1142
+ activateItem(item, group, itemId);
1143
+ onPopupMenu(event, item, group);
1144
+ },
1145
+ [activateItem, onPopupMenu]
1146
+ );
1127
1147
  function moveActive(direction) {
1128
1148
  if (selectableItems.length === 0) {
1129
1149
  return;
@@ -1244,6 +1264,7 @@ function ListBoxInner({
1244
1264
  listboxId,
1245
1265
  onActivateItem: activateItem,
1246
1266
  onDoubleClickItem: onItemDoubleClick,
1267
+ onPopupMenuItem: handleItemPopupMenu,
1247
1268
  onToggleItemCheck: toggleItemCheck,
1248
1269
  registerItemRef,
1249
1270
  resolvedActiveId,
@@ -1933,8 +1954,6 @@ function WindowInner({
1933
1954
  return;
1934
1955
  }
1935
1956
  onActivate?.();
1936
- event.preventDefault();
1937
- event.stopPropagation();
1938
1957
  }
1939
1958
  function handleTitlePointerDown(event) {
1940
1959
  onActivate?.();
@@ -4271,6 +4290,7 @@ function InfoAccent({
4271
4290
 
4272
4291
  // src/components/IconGrid/NuIconGrid.tsx
4273
4292
  import {
4293
+ useEffect as useEffect8,
4274
4294
  useLayoutEffect as useLayoutEffect4,
4275
4295
  useMemo as useMemo8,
4276
4296
  useRef as useRef9,
@@ -4454,7 +4474,7 @@ function PopupMenu({
4454
4474
  ref: rootRef,
4455
4475
  style: {
4456
4476
  ...getThemePortalStyle(
4457
- anchor?.type === "element" ? anchor.element : null
4477
+ anchor.type === "element" ? anchor.element : anchor.themeSource ?? null
4458
4478
  ),
4459
4479
  ...styleProp,
4460
4480
  left: 0,
@@ -4487,8 +4507,9 @@ function usePopupMenu() {
4487
4507
  function close() {
4488
4508
  setOpen(false);
4489
4509
  }
4490
- function openAtPoint(x, y) {
4510
+ function openAtPoint(x, y, themeSource) {
4491
4511
  setAnchor({
4512
+ themeSource,
4492
4513
  type: "point",
4493
4514
  x,
4494
4515
  y
@@ -4507,7 +4528,7 @@ function usePopupMenu() {
4507
4528
  }
4508
4529
  function openFromContextMenu(event) {
4509
4530
  event.preventDefault();
4510
- openAtPoint(event.clientX, event.clientY);
4531
+ openAtPoint(event.clientX, event.clientY, event.currentTarget);
4511
4532
  }
4512
4533
  return {
4513
4534
  anchor,
@@ -4541,6 +4562,7 @@ function useNuIconGridContext() {
4541
4562
  // src/components/IconGrid/NuIconGrid.tsx
4542
4563
  import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
4543
4564
  var DRAG_THRESHOLD = 3;
4565
+ var gridRegistrations = /* @__PURE__ */ new Map();
4544
4566
  function clamp2(value, minimum, maximum) {
4545
4567
  return Math.min(Math.max(value, minimum), maximum);
4546
4568
  }
@@ -4550,11 +4572,85 @@ function resolveIconContextMenuItems(source, icon) {
4550
4572
  function resolveGridContextMenuItems(source, manager) {
4551
4573
  return typeof source === "function" ? source(manager) : source ?? [];
4552
4574
  }
4553
- function NuIconGridItem({ gridElement, icon }) {
4575
+ function findGridRegistrationAtPoint(clientX, clientY) {
4576
+ const target = document.elementFromPoint(clientX, clientY);
4577
+ const gridElement = target?.closest(".nu-icon-grid");
4578
+ if (gridElement) {
4579
+ return gridRegistrations.get(gridElement);
4580
+ }
4581
+ if (target?.closest(".nu-window")) {
4582
+ return void 0;
4583
+ }
4584
+ return Array.from(gridRegistrations.values()).reverse().find((registration) => {
4585
+ if (!registration.dropTarget) {
4586
+ return false;
4587
+ }
4588
+ const rect = registration.element.getBoundingClientRect();
4589
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
4590
+ });
4591
+ }
4592
+ function getTransferredPosition(targetGrid, iconElement, clientX, clientY) {
4593
+ const targetRect = targetGrid.getBoundingClientRect();
4594
+ const iconRect = iconElement.getBoundingClientRect();
4595
+ return {
4596
+ x: Math.round(
4597
+ clamp2(
4598
+ clientX - targetRect.left - iconRect.width / 2,
4599
+ 0,
4600
+ Math.max(0, targetRect.width - iconRect.width)
4601
+ )
4602
+ ),
4603
+ y: Math.round(
4604
+ clamp2(
4605
+ clientY - targetRect.top - iconRect.height / 2,
4606
+ 0,
4607
+ Math.max(0, targetRect.height - iconRect.height)
4608
+ )
4609
+ )
4610
+ };
4611
+ }
4612
+ function createDragPreview(iconElement) {
4613
+ const rect = iconElement.getBoundingClientRect();
4614
+ const preview = iconElement.cloneNode(true);
4615
+ preview.removeAttribute("id");
4616
+ preview.setAttribute("aria-hidden", "true");
4617
+ preview.setAttribute("disabled", "");
4618
+ preview.setAttribute("tabindex", "-1");
4619
+ Object.assign(preview.style, {
4620
+ height: `${rect.height}px`,
4621
+ left: `${rect.left}px`,
4622
+ margin: "0",
4623
+ opacity: window.getComputedStyle(iconElement).getPropertyValue("--nu-icon-grid-icon-drag-preview-opacity").trim() || "0.85",
4624
+ pointerEvents: "none",
4625
+ position: "fixed",
4626
+ top: `${rect.top}px`,
4627
+ width: `${rect.width}px`,
4628
+ zIndex: "2147483647"
4629
+ });
4630
+ const themeStyle = getThemePortalStyle(iconElement);
4631
+ Object.entries(themeStyle ?? {}).forEach(([property, value]) => {
4632
+ if (value !== void 0) {
4633
+ preview.style.setProperty(property, String(value));
4634
+ }
4635
+ });
4636
+ document.body.append(preview);
4637
+ return preview;
4638
+ }
4639
+ function moveDragPreview(preview, iconElement, clientX, clientY) {
4640
+ const rect = iconElement.getBoundingClientRect();
4641
+ preview.style.left = `${Math.round(clientX - rect.width / 2)}px`;
4642
+ preview.style.top = `${Math.round(clientY - rect.height / 2)}px`;
4643
+ }
4644
+ function NuIconGridItem({
4645
+ gridElement,
4646
+ icon,
4647
+ onIconMoveOut
4648
+ }) {
4554
4649
  const manager = useNuIconGridContext();
4555
4650
  const contextMenu = usePopupMenu();
4556
4651
  const dragStartRef = useRef9(void 0);
4557
4652
  const isDraggingRef = useRef9(false);
4653
+ const dragPreviewRef = useRef9(null);
4558
4654
  const [isDragging, setIsDragging] = useState15(false);
4559
4655
  const suppressClickRef = useRef9(false);
4560
4656
  const latestPositionRef = useRef9(icon.position);
@@ -4562,6 +4658,11 @@ function NuIconGridItem({ gridElement, icon }) {
4562
4658
  icon.contextMenuItems,
4563
4659
  icon
4564
4660
  );
4661
+ function removeDragPreview() {
4662
+ dragPreviewRef.current?.remove();
4663
+ dragPreviewRef.current = null;
4664
+ }
4665
+ useEffect8(() => removeDragPreview, []);
4565
4666
  function handlePointerDown(event) {
4566
4667
  if (event.button !== 0 || icon.disabled) {
4567
4668
  return;
@@ -4587,8 +4688,19 @@ function NuIconGridItem({ gridElement, icon }) {
4587
4688
  if (!isDraggingRef.current && Math.max(Math.abs(deltaX), Math.abs(deltaY)) < DRAG_THRESHOLD) {
4588
4689
  return;
4589
4690
  }
4590
- isDraggingRef.current = true;
4591
- setIsDragging(true);
4691
+ if (!isDraggingRef.current) {
4692
+ isDraggingRef.current = true;
4693
+ setIsDragging(true);
4694
+ dragPreviewRef.current = createDragPreview(event.currentTarget);
4695
+ }
4696
+ if (dragPreviewRef.current) {
4697
+ moveDragPreview(
4698
+ dragPreviewRef.current,
4699
+ event.currentTarget,
4700
+ event.clientX,
4701
+ event.clientY
4702
+ );
4703
+ }
4592
4704
  const gridRect = gridElement.getBoundingClientRect();
4593
4705
  const iconRect = event.currentTarget.getBoundingClientRect();
4594
4706
  const position = {
@@ -4608,7 +4720,6 @@ function NuIconGridItem({ gridElement, icon }) {
4608
4720
  )
4609
4721
  };
4610
4722
  latestPositionRef.current = position;
4611
- manager.moveIcon(icon.id, position);
4612
4723
  }
4613
4724
  function finishDragging(event) {
4614
4725
  const dragStart = dragStartRef.current;
@@ -4619,16 +4730,56 @@ function NuIconGridItem({ gridElement, icon }) {
4619
4730
  event.currentTarget.releasePointerCapture(event.pointerId);
4620
4731
  }
4621
4732
  dragStartRef.current = void 0;
4733
+ removeDragPreview();
4622
4734
  if (!isDraggingRef.current) {
4623
4735
  return;
4624
4736
  }
4625
4737
  suppressClickRef.current = true;
4626
4738
  isDraggingRef.current = false;
4627
4739
  setIsDragging(false);
4628
- icon.onPositionChange?.(latestPositionRef.current, {
4629
- ...icon,
4630
- position: latestPositionRef.current
4631
- });
4740
+ if (event.type === "pointercancel" || !gridElement) {
4741
+ return;
4742
+ }
4743
+ const targetRegistration = findGridRegistrationAtPoint(
4744
+ event.clientX,
4745
+ event.clientY
4746
+ );
4747
+ if (!targetRegistration) {
4748
+ return;
4749
+ }
4750
+ if (targetRegistration.element === gridElement) {
4751
+ manager.moveIcon(icon.id, latestPositionRef.current);
4752
+ icon.onPositionChange?.(latestPositionRef.current, {
4753
+ ...icon,
4754
+ position: latestPositionRef.current
4755
+ });
4756
+ return;
4757
+ }
4758
+ if (!targetRegistration.manager.icons.some(
4759
+ (targetIcon) => targetIcon.id === icon.id
4760
+ )) {
4761
+ const position = getTransferredPosition(
4762
+ targetRegistration.element,
4763
+ event.currentTarget,
4764
+ event.clientX,
4765
+ event.clientY
4766
+ );
4767
+ const transferredIcon = { ...icon, position };
4768
+ const context = {
4769
+ position,
4770
+ source: manager,
4771
+ sourceGrid: gridElement,
4772
+ target: targetRegistration.manager,
4773
+ targetGrid: targetRegistration.element
4774
+ };
4775
+ if (targetRegistration.accepts?.(transferredIcon) !== false && targetRegistration.onIconDrop?.(transferredIcon, context) !== false) {
4776
+ targetRegistration.manager.addIcon(transferredIcon);
4777
+ targetRegistration.manager.selectIcon(transferredIcon.id);
4778
+ manager.removeIcon(icon.id);
4779
+ onIconMoveOut?.(transferredIcon, context);
4780
+ return;
4781
+ }
4782
+ }
4632
4783
  }
4633
4784
  function handleClick(event) {
4634
4785
  if (suppressClickRef.current) {
@@ -4647,7 +4798,7 @@ function NuIconGridItem({ gridElement, icon }) {
4647
4798
  return;
4648
4799
  }
4649
4800
  event.preventDefault();
4650
- contextMenu.openAtPoint(event.clientX, event.clientY);
4801
+ contextMenu.openAtPoint(event.clientX, event.clientY, event.currentTarget);
4651
4802
  }
4652
4803
  function handleKeyDown(event) {
4653
4804
  if (event.key !== "ContextMenu" && !(event.key === "F10" && event.shiftKey) || contextMenuItems.length === 0) {
@@ -4694,9 +4845,13 @@ function NuIconGridItem({ gridElement, icon }) {
4694
4845
  ] });
4695
4846
  }
4696
4847
  function NuIconGrid({
4848
+ accepts,
4697
4849
  className,
4698
4850
  contextMenuItems: contextMenuItemsSource,
4699
4851
  defaultArrangeMode,
4852
+ dropTarget = false,
4853
+ onIconDrop,
4854
+ onIconMoveOut,
4700
4855
  onContextMenu,
4701
4856
  onPointerDown,
4702
4857
  ...props
@@ -4732,6 +4887,21 @@ function NuIconGrid({
4732
4887
  resizeObserver.observe(gridElement);
4733
4888
  return () => resizeObserver.disconnect();
4734
4889
  }, [arrangeIcons, defaultArrangeMode, gridElement, setGridSize]);
4890
+ useLayoutEffect4(() => {
4891
+ if (!gridElement) {
4892
+ return;
4893
+ }
4894
+ gridRegistrations.set(gridElement, {
4895
+ accepts,
4896
+ dropTarget,
4897
+ element: gridElement,
4898
+ manager,
4899
+ onIconDrop
4900
+ });
4901
+ return () => {
4902
+ gridRegistrations.delete(gridElement);
4903
+ };
4904
+ }, [accepts, dropTarget, gridElement, manager, onIconDrop]);
4735
4905
  function handleContextMenu(event) {
4736
4906
  onContextMenu?.(event);
4737
4907
  if (event.defaultPrevented || contextMenuItems.length === 0) {
@@ -4739,7 +4909,7 @@ function NuIconGrid({
4739
4909
  }
4740
4910
  event.preventDefault();
4741
4911
  manager.selectIcon(null);
4742
- contextMenu.openAtPoint(event.clientX, event.clientY);
4912
+ contextMenu.openAtPoint(event.clientX, event.clientY, event.currentTarget);
4743
4913
  }
4744
4914
  return /* @__PURE__ */ jsxs20(
4745
4915
  "div",
@@ -4760,7 +4930,15 @@ function NuIconGrid({
4760
4930
  ref: setGridElement,
4761
4931
  role: "group",
4762
4932
  children: [
4763
- manager.icons.map((icon) => /* @__PURE__ */ jsx35(NuIconGridItem, { gridElement, icon }, icon.id)),
4933
+ manager.icons.map((icon) => /* @__PURE__ */ jsx35(
4934
+ NuIconGridItem,
4935
+ {
4936
+ gridElement,
4937
+ icon,
4938
+ onIconMoveOut
4939
+ },
4940
+ icon.id
4941
+ )),
4764
4942
  /* @__PURE__ */ jsx35(
4765
4943
  PopupMenu,
4766
4944
  {
@@ -4935,7 +5113,7 @@ function NuIconProvider({
4935
5113
 
4936
5114
  // src/components/ComboBox/ComboBox.tsx
4937
5115
  import {
4938
- useEffect as useEffect8,
5116
+ useEffect as useEffect9,
4939
5117
  useId as useId5,
4940
5118
  useMemo as useMemo10,
4941
5119
  useRef as useRef11,
@@ -5026,7 +5204,7 @@ function ComboBox({
5026
5204
  );
5027
5205
  const popupRoot = typeof document === "undefined" ? null : resolveComboBoxPortalRoot();
5028
5206
  const [themePortalStyle, setThemePortalStyle] = useState17(() => void 0);
5029
- useEffect8(() => {
5207
+ useEffect9(() => {
5030
5208
  if (!open) {
5031
5209
  return;
5032
5210
  }
@@ -5385,7 +5563,7 @@ function CommandButton({
5385
5563
  }
5386
5564
 
5387
5565
  // src/components/CrtGlitch/CrtGlitch.tsx
5388
- import { useEffect as useEffect9, useId as useId6, useRef as useRef12 } from "react";
5566
+ import { useEffect as useEffect10, useId as useId6, useRef as useRef12 } from "react";
5389
5567
  import { jsx as jsx39, jsxs as jsxs23 } from "react/jsx-runtime";
5390
5568
  var DEFAULT_INTERVAL_MS = 3e3;
5391
5569
  var DEFAULT_DURATION_MS = 2500;
@@ -5418,7 +5596,7 @@ function NuCrtGlitch({
5418
5596
  const bOffsetRef = useRef12(null);
5419
5597
  const rafRef = useRef12(null);
5420
5598
  const targetElRef = useRef12(null);
5421
- useEffect9(() => {
5599
+ useEffect10(() => {
5422
5600
  if (!enabled) {
5423
5601
  return;
5424
5602
  }
@@ -5593,7 +5771,7 @@ function NuCrtGlitch({
5593
5771
  import {
5594
5772
  forwardRef as forwardRef2,
5595
5773
  useCallback as useCallback6,
5596
- useEffect as useEffect10,
5774
+ useEffect as useEffect11,
5597
5775
  useImperativeHandle as useImperativeHandle2,
5598
5776
  useMemo as useMemo11,
5599
5777
  useRef as useRef13,
@@ -5793,7 +5971,7 @@ function ListViewInner({
5793
5971
  );
5794
5972
  return [checkboxColumn, ...dataColumns].filter(Boolean).join(" ");
5795
5973
  }, [columns, showCheckBox]);
5796
- useEffect10(() => {
5974
+ useEffect11(() => {
5797
5975
  if (!resolvedActiveRowId) {
5798
5976
  return;
5799
5977
  }
@@ -5987,7 +6165,7 @@ var ListView = forwardRef2(ListViewInner);
5987
6165
 
5988
6166
  // src/components/MaskedField/MaskedField.tsx
5989
6167
  import {
5990
- useEffect as useEffect11,
6168
+ useEffect as useEffect12,
5991
6169
  useId as useId7,
5992
6170
  useMemo as useMemo12,
5993
6171
  useRef as useRef14,
@@ -6193,7 +6371,7 @@ function MaskedField({
6193
6371
  () => props.inputMode === void 0 ? getTextMaskInputMode(mask) : void 0,
6194
6372
  [mask, props.inputMode]
6195
6373
  );
6196
- useEffect11(() => {
6374
+ useEffect12(() => {
6197
6375
  if (!onDebouncedChange) {
6198
6376
  return;
6199
6377
  }
@@ -7201,7 +7379,7 @@ function ReportCell({
7201
7379
 
7202
7380
  // src/components/SearchBox/SearchBox.tsx
7203
7381
  import {
7204
- useEffect as useEffect12,
7382
+ useEffect as useEffect13,
7205
7383
  useId as useId12,
7206
7384
  useMemo as useMemo15,
7207
7385
  useRef as useRef17,
@@ -7278,7 +7456,7 @@ function SearchBox({
7278
7456
  );
7279
7457
  const popupRoot = typeof document === "undefined" ? null : resolveSearchBoxPortalRoot();
7280
7458
  const [themePortalStyle, setThemePortalStyle] = useState25(() => void 0);
7281
- useEffect12(() => {
7459
+ useEffect13(() => {
7282
7460
  if (disabled) {
7283
7461
  return;
7284
7462
  }
@@ -7310,7 +7488,7 @@ function SearchBox({
7310
7488
  popupRef,
7311
7489
  portalRoot: popupRoot
7312
7490
  });
7313
- useEffect12(() => {
7491
+ useEffect13(() => {
7314
7492
  if (disabled || !open) {
7315
7493
  return;
7316
7494
  }
@@ -7692,7 +7870,7 @@ function SpinBox({
7692
7870
 
7693
7871
  // src/components/Splitter/Splitter.tsx
7694
7872
  import {
7695
- useEffect as useEffect13,
7873
+ useEffect as useEffect14,
7696
7874
  useId as useId14,
7697
7875
  useRef as useRef18,
7698
7876
  useState as useState27
@@ -7741,13 +7919,13 @@ function Splitter({
7741
7919
  );
7742
7920
  const firstPaneId = useId14();
7743
7921
  const secondPaneId = useId14();
7744
- useEffect13(() => {
7922
+ useEffect14(() => {
7745
7923
  if (!storageKey || typeof window === "undefined") {
7746
7924
  return;
7747
7925
  }
7748
7926
  window.localStorage.setItem(storageKey, String(activeValue));
7749
7927
  }, [activeValue, storageKey]);
7750
- useEffect13(() => {
7928
+ useEffect14(() => {
7751
7929
  return () => {
7752
7930
  if (dragFrameRef.current !== null) {
7753
7931
  window.cancelAnimationFrame(dragFrameRef.current);
@@ -7896,7 +8074,7 @@ function Splitter({
7896
8074
 
7897
8075
  // src/components/TickBar/TickBar.tsx
7898
8076
  import {
7899
- useEffect as useEffect14,
8077
+ useEffect as useEffect15,
7900
8078
  useId as useId15,
7901
8079
  useMemo as useMemo17,
7902
8080
  useRef as useRef19,
@@ -7962,7 +8140,7 @@ function TickBar({
7962
8140
  );
7963
8141
  }, [min, safeMax, safeStep, tickCount]);
7964
8142
  const renderedValue = valueRenderer ? valueRenderer(resolvedValue, min, safeMax) : String(resolvedValue);
7965
- useEffect14(() => {
8143
+ useEffect15(() => {
7966
8144
  if (!dragging) {
7967
8145
  return;
7968
8146
  }
@@ -8278,7 +8456,7 @@ function ToolSeparator({ className, ...props }) {
8278
8456
  import {
8279
8457
  forwardRef as forwardRef3,
8280
8458
  useCallback as useCallback7,
8281
- useEffect as useEffect15,
8459
+ useEffect as useEffect16,
8282
8460
  useId as useId16,
8283
8461
  useImperativeHandle as useImperativeHandle3,
8284
8462
  useMemo as useMemo18,
@@ -8647,7 +8825,7 @@ function TreeViewInner({
8647
8825
  const resolvedSelectedId = derivedSelectedId && selectableItems.some((entry) => entry.itemId === derivedSelectedId) ? derivedSelectedId : selectableItems[0]?.itemId ?? null;
8648
8826
  const [activeId, setActiveId] = useState29(resolvedSelectedId);
8649
8827
  const resolvedActiveId = activeId && selectableItems.some((entry) => entry.itemId === activeId) ? activeId : resolvedSelectedId;
8650
- useEffect15(() => {
8828
+ useEffect16(() => {
8651
8829
  if (!resolvedActiveId) {
8652
8830
  return;
8653
8831
  }
@@ -8894,7 +9072,7 @@ var TreeView = forwardRef3(TreeViewInner);
8894
9072
  import {
8895
9073
  forwardRef as forwardRef4,
8896
9074
  useCallback as useCallback8,
8897
- useEffect as useEffect16,
9075
+ useEffect as useEffect17,
8898
9076
  useId as useId17,
8899
9077
  useImperativeHandle as useImperativeHandle4,
8900
9078
  useLayoutEffect as useLayoutEffect5,
@@ -9041,6 +9219,7 @@ function TreeListViewRowInner({
9041
9219
  item,
9042
9220
  onActivateItem,
9043
9221
  onDoubleClickItem,
9222
+ onPopupMenuItem,
9044
9223
  onToggleItemCheck,
9045
9224
  onToggleItemExpanded,
9046
9225
  originOffset,
@@ -9079,6 +9258,17 @@ function TreeListViewRowInner({
9079
9258
  }
9080
9259
  onDoubleClickItem?.(item);
9081
9260
  }
9261
+ function handleContextMenu(event) {
9262
+ if (item.disabled) {
9263
+ return;
9264
+ }
9265
+ onPopupMenuItem?.(event, item, {
9266
+ depth,
9267
+ isLeaf: !hasChildren,
9268
+ item,
9269
+ rowIndex
9270
+ });
9271
+ }
9082
9272
  function handleToggleExpanded(event) {
9083
9273
  event.stopPropagation();
9084
9274
  if (item.disabled || !hasChildren) {
@@ -9112,6 +9302,7 @@ function TreeListViewRowInner({
9112
9302
  ].filter(Boolean).join(" "),
9113
9303
  id: `${treeId}-${itemId}`,
9114
9304
  onClick: handleActivate,
9305
+ onContextMenu: onPopupMenuItem ? handleContextMenu : void 0,
9115
9306
  onDoubleClick: handleDoubleClick,
9116
9307
  ref: (node) => registerItemRef(itemId, node),
9117
9308
  role: "row",
@@ -9260,6 +9451,7 @@ function TreeListViewRowInner({
9260
9451
  item: child,
9261
9452
  onActivateItem,
9262
9453
  onDoubleClickItem,
9454
+ onPopupMenuItem,
9263
9455
  onToggleItemCheck,
9264
9456
  onToggleItemExpanded,
9265
9457
  originOffset: originOffset + leadOffset,
@@ -9281,7 +9473,7 @@ function areTreeListViewRowPropsEqual(previousProps, nextProps) {
9281
9473
  return !didActivePathChange && !didSelectedPathChange && previousProps.checkedIds === nextProps.checkedIds && previousProps.columns === nextProps.columns && previousProps.depth === nextProps.depth && previousProps.expandedIdSet === nextProps.expandedIdSet && previousProps.getCellContent === nextProps.getCellContent && areTreeListGuideArraysEqual(previousProps.guideMask, nextProps.guideMask) && areTreeListGuideArraysEqual(
9282
9474
  previousProps.guideOffsets,
9283
9475
  nextProps.guideOffsets
9284
- ) && previousProps.hasNextSibling === nextProps.hasNextSibling && previousProps.item === nextProps.item && previousProps.onActivateItem === nextProps.onActivateItem && previousProps.onDoubleClickItem === nextProps.onDoubleClickItem && previousProps.onToggleItemCheck === nextProps.onToggleItemCheck && previousProps.onToggleItemExpanded === nextProps.onToggleItemExpanded && previousProps.originOffset === nextProps.originOffset && previousProps.registerItemRef === nextProps.registerItemRef && previousProps.rowIndexMap === nextProps.rowIndexMap && previousProps.templateColumns === nextProps.templateColumns && previousProps.treeColumnId === nextProps.treeColumnId && previousProps.treeId === nextProps.treeId && previousProps.uncheckedShape === nextProps.uncheckedShape;
9476
+ ) && previousProps.hasNextSibling === nextProps.hasNextSibling && previousProps.item === nextProps.item && previousProps.onActivateItem === nextProps.onActivateItem && previousProps.onDoubleClickItem === nextProps.onDoubleClickItem && previousProps.onPopupMenuItem === nextProps.onPopupMenuItem && previousProps.onToggleItemCheck === nextProps.onToggleItemCheck && previousProps.onToggleItemExpanded === nextProps.onToggleItemExpanded && previousProps.originOffset === nextProps.originOffset && previousProps.registerItemRef === nextProps.registerItemRef && previousProps.rowIndexMap === nextProps.rowIndexMap && previousProps.templateColumns === nextProps.templateColumns && previousProps.treeColumnId === nextProps.treeColumnId && previousProps.treeId === nextProps.treeId && previousProps.uncheckedShape === nextProps.uncheckedShape;
9285
9477
  }
9286
9478
  var TreeListViewRow = memo5(
9287
9479
  TreeListViewRowInner,
@@ -9295,6 +9487,7 @@ function TreeListViewInner({
9295
9487
  checkedIds,
9296
9488
  className,
9297
9489
  columns,
9490
+ onPopupMenu,
9298
9491
  data,
9299
9492
  dataVersion,
9300
9493
  defaultActiveItemId,
@@ -9371,7 +9564,7 @@ function TreeListViewInner({
9371
9564
  ),
9372
9565
  [visibleItems]
9373
9566
  );
9374
- useEffect16(() => {
9567
+ useEffect17(() => {
9375
9568
  if (!resolvedActiveItemId) {
9376
9569
  return;
9377
9570
  }
@@ -9425,7 +9618,7 @@ function TreeListViewInner({
9425
9618
  return didChange ? nextWidths : currentWidths;
9426
9619
  });
9427
9620
  }, [columns, userColumnWidths, visibleItems]);
9428
- useEffect16(() => {
9621
+ useEffect17(() => {
9429
9622
  return () => {
9430
9623
  if (resizeFrameRef.current !== null) {
9431
9624
  window.cancelAnimationFrame(resizeFrameRef.current);
@@ -9464,6 +9657,18 @@ function TreeListViewInner({
9464
9657
  },
9465
9658
  [onItemSelect, selectedId, updateActiveItem]
9466
9659
  );
9660
+ const handleItemPopupMenu = useCallback8(
9661
+ (event, item, context) => {
9662
+ if (item.disabled || !onPopupMenu) {
9663
+ return;
9664
+ }
9665
+ event.preventDefault();
9666
+ event.stopPropagation();
9667
+ activateEntry(item, item.id);
9668
+ onPopupMenu(event, item, context);
9669
+ },
9670
+ [activateEntry, onPopupMenu]
9671
+ );
9467
9672
  const activateResolvedItem = useCallback8(
9468
9673
  (itemId) => {
9469
9674
  if (!itemId) {
@@ -9769,6 +9974,7 @@ function TreeListViewInner({
9769
9974
  item,
9770
9975
  onActivateItem: activateEntry,
9771
9976
  onDoubleClickItem: onItemDoubleClick ? handleItemDoubleClick : void 0,
9977
+ onPopupMenuItem: handleItemPopupMenu,
9772
9978
  onToggleItemCheck: handleItemCheckChange,
9773
9979
  onToggleItemExpanded: setExpandedState,
9774
9980
  originOffset: 0,
@@ -9810,10 +10016,12 @@ var classicTheme = {
9810
10016
  panelBackground: "#6262e3",
9811
10017
  panelInsetBackground: "#6262e3",
9812
10018
  titleBackground: "#ffffff",
10019
+ menuBackground: "#ffffff",
9813
10020
  titleText: "#1f36bc",
9814
10021
  textPrimary: "#ffffff",
9815
10022
  textMuted: "#dfe3ff",
9816
10023
  textInverse: "#000000",
10024
+ mainMenuText: "#000000",
9817
10025
  textAccent: "#ffff55",
9818
10026
  textHotkey: "#ff5555",
9819
10027
  buttonFace: "#ffffff",
@@ -9846,10 +10054,12 @@ var amberTheme = {
9846
10054
  panelBackground: "#4b2b00",
9847
10055
  panelInsetBackground: "#382000",
9848
10056
  titleBackground: "#ffd28f",
10057
+ menuBackground: "#ffd28f",
9849
10058
  titleText: "#4b2b00",
9850
10059
  textPrimary: "#ffd28f",
9851
10060
  textMuted: "#d6b57a",
9852
10061
  textInverse: "#201000",
10062
+ mainMenuText: "#201000",
9853
10063
  textAccent: "#fff27a",
9854
10064
  textHotkey: "#ff5f00",
9855
10065
  buttonFace: "#ffd28f",
@@ -9882,10 +10092,12 @@ var phosphorTheme = {
9882
10092
  panelBackground: "#11351a",
9883
10093
  panelInsetBackground: "#0d2813",
9884
10094
  titleBackground: "#b7ffbf",
10095
+ menuBackground: "#b7ffbf",
9885
10096
  titleText: "#0b2310",
9886
10097
  textPrimary: "#b7ffbf",
9887
10098
  textMuted: "#8ed39a",
9888
10099
  textInverse: "#061208",
10100
+ mainMenuText: "#061208",
9889
10101
  textAccent: "#f7ff7a",
9890
10102
  textHotkey: "#ff6f6f",
9891
10103
  buttonFace: "#b7ffbf",
@@ -9918,10 +10130,12 @@ var midnightTheme = {
9918
10130
  panelBackground: "#17273b",
9919
10131
  panelInsetBackground: "#111e2e",
9920
10132
  titleBackground: "#d4dde8",
10133
+ menuBackground: "#d4dde8",
9921
10134
  titleText: "#14233a",
9922
10135
  textPrimary: "#e6edf7",
9923
10136
  textMuted: "#aebdcd",
9924
10137
  textInverse: "#0b1220",
10138
+ mainMenuText: "#0b1220",
9925
10139
  textAccent: "#ffd166",
9926
10140
  textHotkey: "#ff7171",
9927
10141
  buttonFace: "#d4dde8",
@@ -9941,11 +10155,50 @@ var midnightTheme = {
9941
10155
  windowModalBackdrop: "rgb(7 12 20 / 0.48)"
9942
10156
  }
9943
10157
  };
10158
+ var grayscaleTheme = {
10159
+ name: "grayscale",
10160
+ label: "Grayscale Monitor",
10161
+ tokens: {
10162
+ desktopBackground: "#808080",
10163
+ desktopPattern: "rgb(0 0 0 / 0.3)",
10164
+ shellBackground: "#202020",
10165
+ appBackground: "#3f3f3f",
10166
+ appBackgroundAlt: "#2b2b2b",
10167
+ chromeBackground: "#727272",
10168
+ panelBackground: "#3f3f3f",
10169
+ panelInsetBackground: "#343434",
10170
+ titleBackground: "#262626",
10171
+ menuBackground: "#262626",
10172
+ titleText: "#d0d0d0",
10173
+ textPrimary: "#c8c8c8",
10174
+ textMuted: "#969696",
10175
+ textInverse: "#d0d0d0",
10176
+ mainMenuText: "#d0d0d0",
10177
+ textAccent: "#e0e0e0",
10178
+ textHotkey: "#ffffff",
10179
+ buttonFace: "#5b5b5b",
10180
+ buttonFaceAlt: "#414141",
10181
+ buttonDanger: "#303030",
10182
+ buttonSuccess: "#6b6b6b",
10183
+ buttonText: "#d0d0d0",
10184
+ fieldBackground: "#0e0e0e",
10185
+ fieldText: "#d8d8d8",
10186
+ borderLight: "#c7c7c7",
10187
+ borderDark: "#000000",
10188
+ borderAccent: "#ffffff",
10189
+ shadowColor: "#000000",
10190
+ panelShadowColor: "rgb(0 0 0 / 0.5)",
10191
+ focusColor: "#ffffff",
10192
+ windowInactiveOverlay: "rgb(0 0 0 / 0.34)",
10193
+ windowModalBackdrop: "rgb(0 0 0 / 0.5)"
10194
+ }
10195
+ };
9944
10196
  var nuThemes = {
9945
10197
  classic: classicTheme,
9946
10198
  amber: amberTheme,
9947
10199
  phosphor: phosphorTheme,
9948
- midnight: midnightTheme
10200
+ midnight: midnightTheme,
10201
+ grayscale: grayscaleTheme
9949
10202
  };
9950
10203
  function isNuThemeName(value) {
9951
10204
  return value in nuThemes;
@@ -9964,10 +10217,12 @@ function getNuThemeStyle(theme) {
9964
10217
  "--nu-color-panel": theme.tokens.panelBackground,
9965
10218
  "--nu-color-panel-inset": theme.tokens.panelInsetBackground,
9966
10219
  "--nu-color-title-bg": theme.tokens.titleBackground,
10220
+ "--nu-color-menu": theme.tokens.menuBackground,
9967
10221
  "--nu-color-title-text": theme.tokens.titleText,
9968
10222
  "--nu-text-primary": theme.tokens.textPrimary,
9969
10223
  "--nu-text-muted": theme.tokens.textMuted,
9970
10224
  "--nu-text-inverse": theme.tokens.textInverse,
10225
+ "--nu-main-menu-text": theme.tokens.mainMenuText,
9971
10226
  "--nu-text-accent": theme.tokens.textAccent,
9972
10227
  "--nu-text-hotkey": theme.tokens.textHotkey,
9973
10228
  "--nu-color-button-face": theme.tokens.buttonFace,
@@ -10051,6 +10306,7 @@ function NuThemeProvider({
10051
10306
  onFontFamilyChange,
10052
10307
  onFontSizeChange,
10053
10308
  onThemeChange,
10309
+ style,
10054
10310
  theme
10055
10311
  }) {
10056
10312
  const generatedId = useId18();
@@ -10136,7 +10392,8 @@ function NuThemeProvider({
10136
10392
  ...getNuThemeStyle(resolvedTheme),
10137
10393
  "--nu-font-body": resolvedFontFamily,
10138
10394
  fontFamily: resolvedFontFamily,
10139
- fontSize: `${resolvedFontSize}px`
10395
+ fontSize: `${resolvedFontSize}px`,
10396
+ ...style
10140
10397
  },
10141
10398
  children: [
10142
10399
  crtGlitch ? /* @__PURE__ */ jsx61(NuCrtGlitch, { ...typeof crtGlitch === "object" ? crtGlitch : {} }) : null,