@deadragdoll/reactnu 0.1.30 → 0.1.52

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/styles.css CHANGED
@@ -8,10 +8,12 @@
8
8
  --nu-color-panel: #6262e3;
9
9
  --nu-color-panel-inset: #6262e3;
10
10
  --nu-color-title-bg: #ffffff;
11
+ --nu-color-menu: #ffffff;
11
12
  --nu-color-title-text: #1f36bc;
12
13
  --nu-text-primary: #ffffff;
13
14
  --nu-text-muted: #dfe3ff;
14
15
  --nu-text-inverse: #000000;
16
+ --nu-main-menu-text: #000000;
15
17
  --nu-text-accent: #ffff55;
16
18
  --nu-text-hotkey: #ff5555;
17
19
  --nu-color-button-face: #ffffff;
@@ -48,6 +50,9 @@
48
50
  --nu-window-shadow-bg: rgba(0, 0, 0, 0.38);
49
51
  --nu-window-shadow-offset-x: 1ch;
50
52
  --nu-window-shadow-offset-y: 1em;
53
+ --nu-window-title-controls-width: 7.8ch;
54
+ --nu-window-title-height: calc(1em + 3px);
55
+ --nu-window-status-height: 1.35rem;
51
56
  --nu-window-inactive-overlay: rgba(0, 0, 0, 0.22);
52
57
  --nu-window-inactive-border: color-mix(
53
58
  in srgb,
@@ -55,10 +60,32 @@
55
60
  var(--nu-border-dark)
56
61
  );
57
62
  --nu-window-modal-backdrop: rgba(0, 0, 0, 0.32);
63
+ --nu-app-bar-height: 2.1rem;
64
+ --nu-app-bar-padding: 0.2rem 0.35rem;
58
65
  --nu-scrollbar-track: transparent;
59
66
  --nu-scrollbar-thumb: var(--nu-color-button-face);
60
67
  --nu-scrollbar-button-bg: var(--nu-color-button-face);
61
68
  --nu-scrollbar-button-size: 0.875rem;
69
+ --nu-icon-grid-icon-background: transparent;
70
+ --nu-icon-grid-icon-border-color: transparent;
71
+ --nu-icon-grid-icon-border-style: solid;
72
+ --nu-icon-grid-icon-opacity: 1;
73
+ --nu-icon-grid-icon-selected-background: var(--nu-color-title-bg);
74
+ --nu-icon-grid-icon-inactive-selected-background: color-mix(
75
+ in srgb,
76
+ var(--nu-icon-grid-icon-selected-background) 65%,
77
+ var(--nu-color-app-bg-alt)
78
+ );
79
+ --nu-icon-grid-icon-selected-border-color: var(--nu-focus-color);
80
+ --nu-icon-grid-icon-selected-border-style: solid;
81
+ --nu-icon-grid-icon-selected-opacity: 1;
82
+ --nu-icon-grid-icon-focus-background: var(--nu-color-title-bg);
83
+ --nu-icon-grid-icon-focus-border-color: var(--nu-focus-color);
84
+ --nu-icon-grid-icon-focus-border-style: solid;
85
+ --nu-icon-grid-icon-focus-opacity: 1;
86
+ --nu-icon-grid-icon-disabled-opacity: 0.6;
87
+ --nu-icon-grid-icon-drag-opacity: 0.35;
88
+ --nu-icon-grid-icon-drag-preview-opacity: 0.85;
62
89
  --nu-scrollbar-arrow-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpolygon points='8,2 1,12 15,12' fill='black'/%3E%3C/svg%3E");
63
90
  --nu-scrollbar-arrow-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpolygon points='1,4 15,4 8,14' fill='black'/%3E%3C/svg%3E");
64
91
  --nu-scrollbar-arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpolygon points='2,8 12,1 12,15' fill='black'/%3E%3C/svg%3E");
@@ -559,7 +586,13 @@
559
586
  width: 6rem;
560
587
  height: 6rem;
561
588
  padding: 0.25rem;
562
- border: 1px solid transparent;
589
+ border: 1px var(--nu-icon-grid-icon-border-style)
590
+ var(--nu-icon-grid-icon-border-color);
591
+ --nu-icon-grid-icon-current-background: var(--nu-icon-grid-icon-background);
592
+ --nu-icon-grid-icon-current-background-opacity: var(
593
+ --nu-icon-grid-icon-opacity
594
+ );
595
+ isolation: isolate;
563
596
  background: transparent;
564
597
  color: var(--nu-text-primary);
565
598
  font: inherit;
@@ -568,19 +601,43 @@
568
601
  cursor: default;
569
602
  touch-action: none;
570
603
  }
571
- .nu-icon-grid__icon:focus-visible,
604
+ .nu-icon-grid__icon::before {
605
+ content: "";
606
+ position: absolute;
607
+ z-index: -1;
608
+ inset: 0;
609
+ background: var(--nu-icon-grid-icon-current-background);
610
+ opacity: var(--nu-icon-grid-icon-current-background-opacity);
611
+ pointer-events: none;
612
+ }
572
613
  .nu-icon-grid__icon[data-selected] {
573
- border-color: var(--nu-border-light);
574
- outline: 1px solid var(--nu-border-dark);
575
- outline-offset: -3px;
576
- background: var(--nu-color-title-bg);
614
+ --nu-icon-grid-icon-current-background: var(
615
+ --nu-icon-grid-icon-selected-background
616
+ );
617
+ --nu-icon-grid-icon-current-background-opacity: var(
618
+ --nu-icon-grid-icon-selected-opacity
619
+ );
620
+ border-color: var(--nu-icon-grid-icon-selected-border-color);
621
+ border-style: var(--nu-icon-grid-icon-selected-border-style);
622
+ color: var(--nu-text-inverse);
623
+ }
624
+ .nu-icon-grid__icon:focus {
625
+ --nu-icon-grid-icon-current-background: var(
626
+ --nu-icon-grid-icon-focus-background
627
+ );
628
+ --nu-icon-grid-icon-current-background-opacity: var(
629
+ --nu-icon-grid-icon-focus-opacity
630
+ );
631
+ border-color: var(--nu-icon-grid-icon-focus-border-color);
632
+ border-style: var(--nu-icon-grid-icon-focus-border-style);
577
633
  color: var(--nu-text-inverse);
578
634
  }
579
635
  .nu-icon-grid__icon[data-dragging] {
580
636
  z-index: 1;
637
+ opacity: var(--nu-icon-grid-icon-drag-opacity);
581
638
  }
582
639
  .nu-icon-grid__icon:disabled {
583
- opacity: 0.6;
640
+ opacity: var(--nu-icon-grid-icon-disabled-opacity);
584
641
  }
585
642
  .nu-icon-grid__glyph {
586
643
  display: inline-flex;
@@ -609,6 +666,18 @@
609
666
  -webkit-line-clamp: 2;
610
667
  line-clamp: 2;
611
668
  }
669
+ .nu-window:not([data-active]) .nu-icon-grid__icon[data-selected],
670
+ .nu-window:not([data-active]) .nu-icon-grid__icon:focus {
671
+ --nu-icon-grid-icon-current-background: var(
672
+ --nu-icon-grid-icon-inactive-selected-background
673
+ );
674
+ --nu-icon-grid-icon-current-background-opacity: var(
675
+ --nu-icon-grid-icon-selected-opacity
676
+ );
677
+ border-color: var(--nu-icon-grid-icon-selected-border-color);
678
+ border-style: var(--nu-icon-grid-icon-selected-border-style);
679
+ color: var(--nu-text-inverse);
680
+ }
612
681
  .nu-listbox {
613
682
  flex: 1 1 auto;
614
683
  align-self: stretch;
@@ -973,8 +1042,8 @@
973
1042
  position: relative;
974
1043
  z-index: 1100;
975
1044
  min-width: 0;
976
- background: var(--nu-color-title-bg);
977
- color: var(--nu-text-inverse);
1045
+ background: var(--nu-color-menu);
1046
+ color: var(--nu-main-menu-text);
978
1047
  font-family: var(--nu-font-body);
979
1048
  }
980
1049
  .nu-main-menu__bar {
@@ -1048,8 +1117,8 @@
1048
1117
  min-width: 13rem;
1049
1118
  padding: 0.2rem 0;
1050
1119
  border: 1px solid var(--nu-border-dark);
1051
- background: var(--nu-color-button-face);
1052
- color: var(--nu-text-inverse);
1120
+ background: var(--nu-color-menu);
1121
+ color: var(--nu-main-menu-text);
1053
1122
  }
1054
1123
  .nu-main-menu__popup--submenu {
1055
1124
  position: relative;
@@ -1100,10 +1169,11 @@
1100
1169
  justify-content: center;
1101
1170
  inline-size: var(--nu-glyph-cell-size);
1102
1171
  block-size: var(--nu-glyph-cell-size);
1103
- background: var(--nu-color-button-face);
1172
+ border: 1px solid var(--nu-border-dark);
1173
+ background: transparent;
1104
1174
  }
1105
1175
  .nu-main-menu__check-box[data-unchecked-shape="none"] {
1106
- background: transparent;
1176
+ border-color: transparent;
1107
1177
  }
1108
1178
  .nu-main-menu__label {
1109
1179
  min-width: 0;
@@ -1113,7 +1183,7 @@
1113
1183
  }
1114
1184
  .nu-main-menu__shortcut {
1115
1185
  margin-left: 1rem;
1116
- color: var(--nu-text-inverse);
1186
+ color: var(--nu-main-menu-text);
1117
1187
  }
1118
1188
  .nu-main-menu__item--open .nu-main-menu__shortcut,
1119
1189
  .nu-main-menu__item:not(.nu-main-menu__item--disabled):hover
@@ -3384,8 +3454,6 @@
3384
3454
  padding: var(--nu-space-lg);
3385
3455
  }
3386
3456
  .nu-window {
3387
- --nu-window-title-controls-width: 7.8ch;
3388
- --nu-window-title-height: calc(1em + 3px);
3389
3457
  position: relative;
3390
3458
  display: flex;
3391
3459
  flex-direction: column;
@@ -3570,7 +3638,7 @@
3570
3638
  align-items: center;
3571
3639
  justify-content: space-between;
3572
3640
  gap: var(--nu-space-md);
3573
- min-height: 1.35rem;
3641
+ min-height: var(--nu-window-status-height);
3574
3642
  padding: 0 0.45rem;
3575
3643
  background: var(--nu-color-title-bg);
3576
3644
  color: var(--nu-color-title-text);
@@ -3667,8 +3735,8 @@ button.nu-app-bar-item:focus-visible {
3667
3735
  display: flex;
3668
3736
  align-items: center;
3669
3737
  gap: 0.35rem;
3670
- min-height: 2.1rem;
3671
- padding: 0.2rem 0.35rem;
3738
+ min-height: var(--nu-app-bar-height);
3739
+ padding: var(--nu-app-bar-padding);
3672
3740
  background: var(--nu-color-shell);
3673
3741
  box-shadow: inset 0 1px 0 var(--nu-border-light);
3674
3742
  pointer-events: auto;
@@ -1,4 +1,4 @@
1
- import { PropsWithChildren } from "react";
1
+ import { CSSProperties, PropsWithChildren } from "react";
2
2
  import { NuCrtGlitchProps } from "../components/CrtGlitch";
3
3
  import { NuDesktopPatternMode, NuThemeDefinition, NuThemeName } from "./themes";
4
4
  type NuThemeProviderProps = PropsWithChildren<{
@@ -20,7 +20,8 @@ type NuThemeProviderProps = PropsWithChildren<{
20
20
  onDesktopPatternModeChange?: (desktopPatternMode: NuDesktopPatternMode) => void;
21
21
  onFontFamilyChange?: (fontFamily: string) => void;
22
22
  onFontSizeChange?: (fontSize: number) => void;
23
+ style?: CSSProperties;
23
24
  theme?: NuThemeName | NuThemeDefinition;
24
25
  }>;
25
- export declare function NuThemeProvider({ children, className, crtGlitch, defaultDesktopPatternMode, defaultFontFamily, defaultFontSize, defaultTheme, desktopPatternMode, fontFamily, fontSize, onDesktopPatternModeChange, onFontFamilyChange, onFontSizeChange, onThemeChange, theme }: NuThemeProviderProps): import("react/jsx-runtime").JSX.Element;
26
+ export declare function NuThemeProvider({ children, className, crtGlitch, defaultDesktopPatternMode, defaultFontFamily, defaultFontSize, defaultTheme, desktopPatternMode, fontFamily, fontSize, onDesktopPatternModeChange, onFontFamilyChange, onFontSizeChange, onThemeChange, style, theme }: NuThemeProviderProps): import("react/jsx-runtime").JSX.Element;
26
27
  export {};
@@ -10,10 +10,12 @@ export type NuThemeTokens = {
10
10
  panelBackground: string;
11
11
  panelInsetBackground: string;
12
12
  titleBackground: string;
13
+ menuBackground: string;
13
14
  titleText: string;
14
15
  textPrimary: string;
15
16
  textMuted: string;
16
17
  textInverse: string;
18
+ mainMenuText: string;
17
19
  textAccent: string;
18
20
  textHotkey: string;
19
21
  buttonFace: string;
@@ -21,6 +21,10 @@ See: [Slot Customization](./SLOT_CUSTOMIZATION.md)
21
21
 
22
22
  - `NuThemeProvider`
23
23
  docs: [NuThemeProvider](./NuThemeProvider.md)
24
+ - `NuDragDropProvider`
25
+ coordinates application-owned transfers among `NuIconGrid`, `ListBox`, and
26
+ `TreeListView`
27
+ docs: [NuDragDropProvider](./NuDragDropProvider.md)
24
28
  - `NuDesktop`
25
29
  docs: [Desktop](./Desktop.md)
26
30
  - `Dashboard`
@@ -41,6 +45,9 @@ See: [Slot Customization](./SLOT_CUSTOMIZATION.md)
41
45
  also exposes `showMessageBox(...)` and `showInputBox(...)`
42
46
  - `useNuIconManager()`
43
47
  manages icons inside a `NuIconProvider`
48
+ - `useNuDragDrop()`
49
+ internal integration hook for custom shared drag sources and targets; most
50
+ applications should use component props from [Shared Drag and Drop](./NuDragDropProvider.md)
44
51
  - `usePopupMenu()`
45
52
  anchor/open helper for `PopupMenu`
46
53
  - `useWindowMenu()`
@@ -91,6 +98,8 @@ See: [Slot Customization](./SLOT_CUSTOMIZATION.md)
91
98
  docs: [TreeView](./TreeView.md)
92
99
  - `TreeListView`
93
100
  docs: [TreeListView](./TreeListView.md)
101
+ - Shared drag-and-drop contract
102
+ docs: [NuDragDropProvider](./NuDragDropProvider.md)
94
103
 
95
104
  ## Layout And Surfaces
96
105
 
@@ -8,6 +8,7 @@
8
8
  - [Contributor Guide](./CONTRIBUTOR_GUIDE.md)
9
9
  - [Slot Customization](./SLOT_CUSTOMIZATION.md)
10
10
  - [Storybook](./STORYBOOK.md)
11
+ - [Shared Drag and Drop](./NuDragDropProvider.md)
11
12
 
12
13
  ## Core Components
13
14
 
@@ -57,6 +58,7 @@
57
58
 
58
59
  ## Providers
59
60
 
61
+ - [NuDragDropProvider](./NuDragDropProvider.md)
60
62
  - [NuThemeProvider](./NuThemeProvider.md)
61
63
  - [NuAppHostProvider](./NuAppHostProvider.md)
62
64
 
@@ -49,7 +49,8 @@ export function App() {
49
49
  ## Recommended Order
50
50
 
51
51
  1. `NuThemeProvider`
52
- 2. `NuDesktop`
52
+ 2. `NuDragDropProvider` when ListBox, TreeListView, or IconGrid need to exchange items
53
+ 3. `NuDesktop`
53
54
  3. host-driven `appBar`
54
55
  4. workspace content
55
56
  5. open windows through `useNuWindowManager()`
package/docs/IconGrid.md CHANGED
@@ -61,6 +61,21 @@ function Applications() {
61
61
  - `defaultArrangeMode="columns" | "rows" | "name"` arranges seeded icons
62
62
  once, after the grid measures a non-zero available area. This prevents icons
63
63
  from initially landing outside a bounded `Window`.
64
+ - `dropTarget` makes a grid eligible as a non-interactive drop surface when it
65
+ sits behind other content. Pair it with `accepts(icon)` to filter incoming
66
+ icons before `onIconDrop` runs. This is useful for a full desktop target that
67
+ uses `pointer-events: none` and therefore does not interfere with the
68
+ desktop's own controls.
69
+ - Drag an icon to another `NuIconGrid`, including one in a different managed
70
+ window, to transfer it between providers. `onIconDrop(icon, context)` runs on
71
+ the target first and may return `false` to reject the transfer;
72
+ `onIconMoveOut(icon, context)` runs on the source after a successful transfer.
73
+ `context` exposes both managers, grids, and the target `position`.
74
+ - Within `NuDragDropProvider`, use `acceptsDrop(item)` and `onDrop(item,
75
+ context)` to accept application-defined items from `ListBox` or
76
+ `TreeListView`. `onDragOut(item)` runs when an icon is accepted by one of
77
+ those non-icon targets. The existing `accepts(icon)` API remains specific to
78
+ icon-to-icon transfers.
64
79
 
65
80
  `useNuIconManager()`
66
81
 
@@ -70,12 +85,24 @@ function Applications() {
70
85
  - `arrangeIcons("columns" | "rows" | "name")` lays out the current icons.
71
86
 
72
87
  Each icon can have `onClick`, `onDoubleClick`, `onContextMenu`,
73
- `onPositionChange`, and its own `contextMenuItems`.
88
+ `onPositionChange`, its own `contextMenuItems`, and an application-defined
89
+ `payload` that is preserved during a cross-grid transfer.
90
+
91
+ ## Theme tokens
92
+
93
+ The default, selected, and focus IconGrid states each expose `background`,
94
+ `border-color`, `border-style`, and `opacity` values under the
95
+ `--nu-icon-grid-icon-*` prefix. The resting background defaults to
96
+ `transparent`; those opacity values affect only the background fill. Drag,
97
+ drag-preview, and disabled opacity also have dedicated
98
+ tokens. In an inactive managed window, the selected border remains visible
99
+ while `--nu-icon-grid-icon-inactive-selected-background` supplies a calmer
100
+ fill.
74
101
 
75
102
  ## Interaction and accessibility
76
103
 
77
- - Drag icons to move them inside the grid; their resulting positions remain in
78
- the provider for the lifetime of that provider.
104
+ - Drag icons to move them inside the grid, or onto another icon grid to transfer
105
+ them. A duplicate ID or a non-grid target leaves the source icon in place.
79
106
  - A click selects an icon. Enter and Space activate its normal button action.
80
107
  - Right-click opens the icon menu; `Shift+F10` and the Context Menu key open it
81
108
  from the keyboard.
package/docs/ListBox.md CHANGED
@@ -20,6 +20,11 @@
20
20
  - `checkedIds?: string[]`
21
21
  - `onItemCheckChange?: (item, group, checked) => void`
22
22
  - `onItemDoubleClick?: (item, group) => void`
23
+ - `onPopupMenu?: (event, item, group) => void`
24
+ - `getDragItem?: (item, group) => NuDragDropItem | false`
25
+ - `onItemDragOut?: (item, group) => void`
26
+ - `acceptsDrop?: (item) => boolean`
27
+ - `onDrop?: (item, context) => boolean | void`
23
28
  - `rightCheckBox?: boolean`
24
29
  - `emptyText?: string`
25
30
 
@@ -33,3 +38,9 @@
33
38
  ## Notes
34
39
 
35
40
  - The same data format supports both grouped and flat lists by using `category: null`.
41
+ - Right-clicking an enabled item activates it, prevents the browser context menu,
42
+ and calls `onPopupMenu`. Use the event coordinates to open an application-owned
43
+ `PopupMenu` or another contextual action surface.
44
+ - Inside `NuDragDropProvider`, `getDragItem` makes rows draggable. The
45
+ application decides accepted data in `acceptsDrop` and updates its collection
46
+ in `onDrop` / `onItemDragOut`.
@@ -0,0 +1,43 @@
1
+ # NuDragDropProvider
2
+
3
+ `NuDragDropProvider` coordinates pointer drag-and-drop between `NuIconGrid`,
4
+ `ListBox`, and `TreeListView`. It carries an application-defined item; it does
5
+ not mutate the host application's list or tree data.
6
+
7
+ ```tsx
8
+ <NuDragDropProvider>
9
+ <ListBox
10
+ data={receivers}
11
+ getDragItem={(item, group) => ({
12
+ type: "receiver",
13
+ id: String(item.id),
14
+ data: { group: group.category?.text ?? "ungrouped", receiver: item }
15
+ })}
16
+ onItemDragOut={(item) => removeReceiver(String(item.id))}
17
+ />
18
+ <TreeListView
19
+ acceptsDrop={(drag) => drag.type === "receiver"}
20
+ columns={columns}
21
+ data={groups}
22
+ onDrop={(drag) => {
23
+ assignReceiverToSelectedGroup(drag.data);
24
+ }}
25
+ />
26
+ </NuDragDropProvider>
27
+ ```
28
+
29
+ ## Contract
30
+
31
+ - A source uses `getDragItem` to opt a displayed item into dragging. Return a
32
+ stable `type`, an ID, and any host payload in `data`.
33
+ - A target uses `acceptsDrop(item)` to filter drag item types and `onDrop` to
34
+ perform its own state update. Returning `false` rejects the transfer.
35
+ - `onItemDragOut` / `onDragOut` run only after a target accepted the item;
36
+ remove or update the source data there.
37
+ - `NuIconGrid` keeps `accepts(icon)`, `onIconDrop`, and `onIconMoveOut` for
38
+ its existing icon-to-icon transfer. Its `acceptsDrop` and `onDrop` receive
39
+ non-icon shared drag items.
40
+
41
+ Wrap every source and target that should interact in the same provider. A
42
+ fallback coordinator preserves existing unwrapped IconGrid transfers, but a
43
+ provider gives the application an explicit DnD scope.
@@ -47,6 +47,8 @@ Supported props:
47
47
  - `onFontSizeChange?: (fontSize) => void`
48
48
  - `crtGlitch?: boolean | NuCrtGlitchProps`
49
49
  enables the ambient CRT-glitch effect (see [CrtGlitch](./CrtGlitch.md)). `true` uses its defaults; pass an options object to tune them. Defaults to `false` — opt-in.
50
+ - `style?: CSSProperties`
51
+ applies scoped CSS custom-property overrides after the resolved theme tokens. Popup portals mirror the computed values from the theme root.
50
52
 
51
53
  `useNuTheme()` exposes:
52
54
 
@@ -61,7 +63,7 @@ Supported props:
61
63
 
62
64
  - Built-in themes are `classic` (default), `amber`, `phosphor`, `midnight`, and
63
65
  `grayscale`.
64
- - `midnight` is a restrained dark blue-gray palette with pale chrome and yellow focus accents.
66
+ - `midnight` is a dark slate-blue palette with blue chrome and a burnt-orange focus accent.
65
67
  - `grayscale` is a high-contrast monochrome monitor palette. Semantic button variants use brightness rather than hue.
66
68
  - Theme tokens drive desktop, windowing, controls, selection, and inactive overlays.
67
69
  - Provider typography affects preview content, managed windows, dialogs, menus, and popup portals rendered inside the theme scope.
@@ -54,6 +54,11 @@ const columns: TreeListColumn<Node>[] = [
54
54
  - `defaultExpandedIds`
55
55
  - `onItemSelect`
56
56
  - `onItemDoubleClick`
57
+ - `onPopupMenu`
58
+ - `getDragItem`
59
+ - `onItemDragOut`
60
+ - `acceptsDrop`
61
+ - `onDrop`
57
62
  - `onItemCheckChange`
58
63
  - `onExpandedIdsChange`
59
64
  - `onActiveItemChange`
@@ -82,3 +87,10 @@ const columns: TreeListColumn<Node>[] = [
82
87
  - Columns auto-size from visible content by default.
83
88
  - `minWidth` sets a lower bound for auto-sized and resized columns.
84
89
  - Columns are resizable unless `resizable={false}` is set on a column.
90
+ - Right-clicking an enabled row activates it and calls
91
+ `onPopupMenu(event, item, context)`. `context` has the same `depth`, `isLeaf`,
92
+ `item`, and `rowIndex` fields as `getCellContent`; the host owns rendering the
93
+ resulting menu.
94
+ - Inside `NuDragDropProvider`, rows may produce shared drag items through
95
+ `getDragItem`; the host filters and applies incoming items with
96
+ `acceptsDrop` and `onDrop`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deadragdoll/reactnu",
3
- "version": "0.1.30",
3
+ "version": "0.1.52",
4
4
  "private": false,
5
5
  "description": "React components with a precise DOS-era utility interface.",
6
6
  "license": "MIT",