@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/README.md +2 -0
- package/dist/components/DragDrop/NuDragDropProvider.d.ts +46 -0
- package/dist/components/DragDrop/index.d.ts +1 -0
- package/dist/components/IconGrid/IconGrid.types.d.ts +9 -0
- package/dist/components/IconGrid/NuIconGrid.d.ts +18 -3
- package/dist/components/ListBox/ListBox.d.ts +13 -3
- package/dist/components/ListBox/internals/ListBoxGroupView.d.ts +6 -1
- package/dist/components/ListBox/internals/ListBoxItemView.d.ts +6 -1
- package/dist/components/TreeListView/TreeListView.d.ts +14 -4
- package/dist/components/TreeListView/internals/TreeListViewRow.d.ts +7 -2
- package/dist/index.cjs +1228 -756
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1033 -559
- package/dist/styles.css +87 -19
- package/dist/theme/NuThemeProvider.d.ts +3 -2
- package/dist/theme/themes.d.ts +2 -0
- package/docs/API_REFERENCE.md +9 -0
- package/docs/COMPONENT_INDEX.md +2 -0
- package/docs/GETTING_STARTED.md +2 -1
- package/docs/IconGrid.md +30 -3
- package/docs/ListBox.md +11 -0
- package/docs/NuDragDropProvider.md +43 -0
- package/docs/NuThemeProvider.md +3 -1
- package/docs/TreeListView.md +12 -0
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
background: var(
|
|
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:
|
|
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-
|
|
977
|
-
color: var(--nu-text
|
|
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-
|
|
1052
|
-
color: var(--nu-text
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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:
|
|
3671
|
-
padding:
|
|
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 {};
|
package/dist/theme/themes.d.ts
CHANGED
|
@@ -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;
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -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
|
|
package/docs/COMPONENT_INDEX.md
CHANGED
|
@@ -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
|
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -49,7 +49,8 @@ export function App() {
|
|
|
49
49
|
## Recommended Order
|
|
50
50
|
|
|
51
51
|
1. `NuThemeProvider`
|
|
52
|
-
2. `
|
|
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`,
|
|
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
|
|
78
|
-
|
|
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.
|
package/docs/NuThemeProvider.md
CHANGED
|
@@ -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
|
|
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.
|
package/docs/TreeListView.md
CHANGED
|
@@ -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`.
|