@deadragdoll/reactnu 0.1.52 → 0.1.73
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/components/MainMenu/MainMenu.types.d.ts +11 -1
- package/dist/components/MainMenu/internals/MainMenuSubmenuShell.d.ts +7 -0
- package/dist/components/Spacer/Spacer.d.ts +7 -0
- package/dist/components/Spacer/index.d.ts +1 -0
- package/dist/components/ToolBar/ToolBar.d.ts +6 -2
- package/dist/components/Window/Window.d.ts +8 -2
- package/dist/components/Window/internals/WindowTitleBar.d.ts +3 -2
- package/dist/index.cjs +976 -846
- package/dist/index.d.ts +1 -0
- package/dist/index.js +777 -649
- package/dist/styles.css +119 -10
- package/dist/windowing/AppBarItem.d.ts +1 -1
- package/dist/windowing/WindowBar.d.ts +2 -0
- package/dist/windowing/windowing.types.d.ts +10 -0
- package/docs/API_REFERENCE.md +2 -0
- package/docs/COMPONENT_INDEX.md +1 -0
- package/docs/MainMenu.md +12 -1
- package/docs/NuWindowProvider.md +72 -0
- package/docs/PopupMenu.md +2 -0
- package/docs/Spacer.md +41 -0
- package/docs/StatusBarItem.md +1 -0
- package/docs/TOKEN_CHECKLIST.md +9 -0
- package/docs/ToolBar.md +15 -2
- package/docs/Window.md +19 -0
- package/docs/WindowBar.md +3 -0
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
--nu-color-button-face-alt: #c7c7c7;
|
|
21
21
|
--nu-color-button-danger: #c84d4d;
|
|
22
22
|
--nu-color-button-success: #188f3b;
|
|
23
|
+
--nu-text-danger: #c84d4d;
|
|
24
|
+
--nu-text-success: #188f3b;
|
|
23
25
|
--nu-color-button-text: #000000;
|
|
24
26
|
--nu-color-field-bg: #000000;
|
|
25
27
|
--nu-color-field-text: #ffffff;
|
|
@@ -47,10 +49,22 @@
|
|
|
47
49
|
--nu-button-press-depth-y: 0.1em;
|
|
48
50
|
--nu-frame-thickness: 2px;
|
|
49
51
|
--nu-rule-thickness: 1px;
|
|
52
|
+
--nu-toolbar-background: var(--nu-color-panel);
|
|
53
|
+
--nu-toolbar-inset: 0.2ch;
|
|
54
|
+
--nu-toolbar-border-color: var(--nu-border-dark);
|
|
55
|
+
--nu-toolbar-border-style: solid;
|
|
56
|
+
--nu-toolbar-border-width: var(--nu-rule-thickness);
|
|
57
|
+
--nu-toolbar-separator-color: var(--nu-border-dark);
|
|
58
|
+
--nu-toolbar-separator-style: solid;
|
|
59
|
+
--nu-toolbar-separator-width: var(--nu-rule-thickness);
|
|
60
|
+
--nu-menu-divider-color: var(--nu-border-dark);
|
|
61
|
+
--nu-menu-divider-style: solid;
|
|
62
|
+
--nu-menu-divider-width: var(--nu-rule-thickness);
|
|
50
63
|
--nu-window-shadow-bg: rgba(0, 0, 0, 0.38);
|
|
51
64
|
--nu-window-shadow-offset-x: 1ch;
|
|
52
65
|
--nu-window-shadow-offset-y: 1em;
|
|
53
66
|
--nu-window-title-controls-width: 7.8ch;
|
|
67
|
+
--nu-window-title-icon-width: 1em;
|
|
54
68
|
--nu-window-title-height: calc(1em + 3px);
|
|
55
69
|
--nu-window-status-height: 1.35rem;
|
|
56
70
|
--nu-window-inactive-overlay: rgba(0, 0, 0, 0.22);
|
|
@@ -1085,20 +1099,23 @@
|
|
|
1085
1099
|
.nu-main-menu__item-button:disabled {
|
|
1086
1100
|
cursor: default;
|
|
1087
1101
|
}
|
|
1088
|
-
.nu-main-menu__item--root .nu-main-menu__item-button {
|
|
1102
|
+
.nu-main-menu__item--root > .nu-main-menu__item-button {
|
|
1089
1103
|
display: inline-flex;
|
|
1090
1104
|
align-items: center;
|
|
1091
1105
|
min-height: 1.4rem;
|
|
1092
1106
|
padding: 0 0.65rem;
|
|
1093
1107
|
}
|
|
1094
1108
|
.nu-main-menu__item--submenu .nu-main-menu__item-button {
|
|
1095
|
-
grid-template-columns:
|
|
1109
|
+
grid-template-columns: minmax(max-content, 1fr) max-content 0.8rem;
|
|
1096
1110
|
gap: 0.45rem;
|
|
1097
1111
|
width: 100%;
|
|
1098
1112
|
min-width: 13rem;
|
|
1099
1113
|
min-height: 1.35rem;
|
|
1100
1114
|
padding: 0 0.55rem;
|
|
1101
1115
|
}
|
|
1116
|
+
.nu-main-menu__item--submenu .nu-main-menu__item-button[data-has-leading] {
|
|
1117
|
+
grid-template-columns: auto minmax(max-content, 1fr) max-content 0.8rem;
|
|
1118
|
+
}
|
|
1102
1119
|
.nu-main-menu__item--open > .nu-main-menu__item-button {
|
|
1103
1120
|
background: var(--nu-color-field-bg);
|
|
1104
1121
|
color: var(--nu-text-primary);
|
|
@@ -1146,14 +1163,23 @@
|
|
|
1146
1163
|
top: calc(100% - 1px);
|
|
1147
1164
|
left: 0;
|
|
1148
1165
|
}
|
|
1166
|
+
.nu-main-menu__submenu-shell--root[data-open-left] {
|
|
1167
|
+
right: 0;
|
|
1168
|
+
left: auto;
|
|
1169
|
+
}
|
|
1149
1170
|
.nu-main-menu__submenu-shell--submenu {
|
|
1150
1171
|
top: -0.2rem;
|
|
1151
1172
|
left: calc(100% - 1px);
|
|
1152
1173
|
}
|
|
1174
|
+
.nu-main-menu__submenu-shell--submenu[data-open-left] {
|
|
1175
|
+
right: calc(100% - 1px);
|
|
1176
|
+
left: auto;
|
|
1177
|
+
}
|
|
1153
1178
|
.nu-main-menu__divider {
|
|
1154
|
-
height:
|
|
1179
|
+
height: 0;
|
|
1155
1180
|
margin: 0.18rem 0.55rem;
|
|
1156
|
-
|
|
1181
|
+
border-block-start: var(--nu-menu-divider-width) var(--nu-menu-divider-style)
|
|
1182
|
+
var(--nu-menu-divider-color);
|
|
1157
1183
|
}
|
|
1158
1184
|
.nu-main-menu__check {
|
|
1159
1185
|
display: inline-flex;
|
|
@@ -1163,6 +1189,13 @@
|
|
|
1163
1189
|
block-size: var(--nu-glyph-cell-size);
|
|
1164
1190
|
color: var(--nu-text-hotkey);
|
|
1165
1191
|
}
|
|
1192
|
+
.nu-main-menu__leading {
|
|
1193
|
+
display: inline-flex;
|
|
1194
|
+
align-items: center;
|
|
1195
|
+
justify-content: center;
|
|
1196
|
+
gap: 0.25rem;
|
|
1197
|
+
grid-column: 1;
|
|
1198
|
+
}
|
|
1166
1199
|
.nu-main-menu__check-box {
|
|
1167
1200
|
display: inline-flex;
|
|
1168
1201
|
align-items: center;
|
|
@@ -1175,24 +1208,49 @@
|
|
|
1175
1208
|
.nu-main-menu__check-box[data-unchecked-shape="none"] {
|
|
1176
1209
|
border-color: transparent;
|
|
1177
1210
|
}
|
|
1211
|
+
.nu-main-menu__icon {
|
|
1212
|
+
display: inline-flex;
|
|
1213
|
+
align-items: center;
|
|
1214
|
+
justify-content: center;
|
|
1215
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
1216
|
+
block-size: var(--nu-glyph-cell-size);
|
|
1217
|
+
color: currentColor;
|
|
1218
|
+
}
|
|
1219
|
+
.nu-main-menu__icon > svg {
|
|
1220
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
1221
|
+
block-size: var(--nu-glyph-cell-size);
|
|
1222
|
+
}
|
|
1178
1223
|
.nu-main-menu__label {
|
|
1179
1224
|
min-width: 0;
|
|
1225
|
+
grid-column: 1;
|
|
1226
|
+
}
|
|
1227
|
+
.nu-main-menu__item-button[data-has-leading] .nu-main-menu__label {
|
|
1228
|
+
grid-column: 2;
|
|
1180
1229
|
}
|
|
1181
1230
|
.nu-main-menu__hotkey {
|
|
1182
1231
|
color: var(--nu-text-hotkey);
|
|
1183
1232
|
}
|
|
1184
1233
|
.nu-main-menu__shortcut {
|
|
1234
|
+
grid-column: 2;
|
|
1235
|
+
justify-self: end;
|
|
1185
1236
|
margin-left: 1rem;
|
|
1186
1237
|
color: var(--nu-main-menu-text);
|
|
1187
1238
|
}
|
|
1239
|
+
.nu-main-menu__item-button[data-has-leading] .nu-main-menu__shortcut {
|
|
1240
|
+
grid-column: 3;
|
|
1241
|
+
}
|
|
1188
1242
|
.nu-main-menu__item--open .nu-main-menu__shortcut,
|
|
1189
1243
|
.nu-main-menu__item:not(.nu-main-menu__item--disabled):hover
|
|
1190
1244
|
.nu-main-menu__shortcut {
|
|
1191
1245
|
color: currentColor;
|
|
1192
1246
|
}
|
|
1193
1247
|
.nu-main-menu__submenu-arrow {
|
|
1248
|
+
grid-column: 3;
|
|
1194
1249
|
justify-self: end;
|
|
1195
1250
|
}
|
|
1251
|
+
.nu-main-menu__item-button[data-has-leading] .nu-main-menu__submenu-arrow {
|
|
1252
|
+
grid-column: 4;
|
|
1253
|
+
}
|
|
1196
1254
|
.nu-masked-field {
|
|
1197
1255
|
display: grid;
|
|
1198
1256
|
gap: var(--nu-space-xs);
|
|
@@ -1798,10 +1856,10 @@
|
|
|
1798
1856
|
color: var(--nu-text-accent);
|
|
1799
1857
|
}
|
|
1800
1858
|
.nu-report-cell--danger {
|
|
1801
|
-
color: var(--nu-text-
|
|
1859
|
+
color: var(--nu-text-danger);
|
|
1802
1860
|
}
|
|
1803
1861
|
.nu-report-cell--success {
|
|
1804
|
-
color: var(--nu-text-
|
|
1862
|
+
color: var(--nu-text-success);
|
|
1805
1863
|
}
|
|
1806
1864
|
.nu-search-box {
|
|
1807
1865
|
display: grid;
|
|
@@ -1890,6 +1948,13 @@
|
|
|
1890
1948
|
color: var(--nu-text-muted);
|
|
1891
1949
|
font-size: 0.75rem;
|
|
1892
1950
|
}
|
|
1951
|
+
.nu-spacer {
|
|
1952
|
+
display: block;
|
|
1953
|
+
flex: 1 1 auto;
|
|
1954
|
+
min-width: 0;
|
|
1955
|
+
min-height: 0;
|
|
1956
|
+
pointer-events: none;
|
|
1957
|
+
}
|
|
1893
1958
|
.nu-spin-box {
|
|
1894
1959
|
display: grid;
|
|
1895
1960
|
gap: var(--nu-space-xs);
|
|
@@ -2378,7 +2443,11 @@
|
|
|
2378
2443
|
gap: 0.5ch;
|
|
2379
2444
|
min-width: 0;
|
|
2380
2445
|
min-height: 0;
|
|
2381
|
-
|
|
2446
|
+
overflow: clip;
|
|
2447
|
+
padding: var(--nu-toolbar-inset);
|
|
2448
|
+
border: var(--nu-toolbar-border-width) var(--nu-toolbar-border-style)
|
|
2449
|
+
var(--nu-toolbar-border-color);
|
|
2450
|
+
background: var(--nu-toolbar-background);
|
|
2382
2451
|
font-family: var(--nu-font-body);
|
|
2383
2452
|
}
|
|
2384
2453
|
.nu-toolbar[data-fill] {
|
|
@@ -2424,6 +2493,16 @@
|
|
|
2424
2493
|
opacity: 0.6;
|
|
2425
2494
|
cursor: not-allowed;
|
|
2426
2495
|
}
|
|
2496
|
+
.nu-toolbar__static {
|
|
2497
|
+
display: inline-flex;
|
|
2498
|
+
align-items: center;
|
|
2499
|
+
justify-content: center;
|
|
2500
|
+
flex: none;
|
|
2501
|
+
}
|
|
2502
|
+
.nu-toolbar__static > svg {
|
|
2503
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
2504
|
+
block-size: var(--nu-glyph-cell-size);
|
|
2505
|
+
}
|
|
2427
2506
|
.nu-toolbar__button-icon,
|
|
2428
2507
|
.nu-toolbar__button-caret {
|
|
2429
2508
|
display: inline-flex;
|
|
@@ -2439,10 +2518,11 @@
|
|
|
2439
2518
|
padding-left: 0.55ch;
|
|
2440
2519
|
}
|
|
2441
2520
|
.nu-toolbar__separator {
|
|
2442
|
-
width:
|
|
2521
|
+
width: 0;
|
|
2443
2522
|
align-self: stretch;
|
|
2444
2523
|
margin: 0 0.35ch;
|
|
2445
|
-
|
|
2524
|
+
border-inline-start: var(--nu-toolbar-separator-width)
|
|
2525
|
+
var(--nu-toolbar-separator-style) var(--nu-toolbar-separator-color);
|
|
2446
2526
|
}
|
|
2447
2527
|
.nu-toolbar[data-wrap] .nu-toolbar__separator {
|
|
2448
2528
|
min-height: 1em;
|
|
@@ -3520,7 +3600,8 @@
|
|
|
3520
3600
|
align-items: center;
|
|
3521
3601
|
justify-content: center;
|
|
3522
3602
|
min-height: var(--nu-window-title-height);
|
|
3523
|
-
padding: 0 var(--nu-window-title-controls-width) 0
|
|
3603
|
+
padding: 0 var(--nu-window-title-controls-width) 0
|
|
3604
|
+
calc(0.45rem + var(--nu-window-title-icon-width));
|
|
3524
3605
|
background: var(--nu-color-title-bg);
|
|
3525
3606
|
color: var(--nu-color-title-text);
|
|
3526
3607
|
line-height: 1;
|
|
@@ -3534,6 +3615,24 @@
|
|
|
3534
3615
|
text-overflow: ellipsis;
|
|
3535
3616
|
white-space: nowrap;
|
|
3536
3617
|
}
|
|
3618
|
+
.nu-window__title-icon {
|
|
3619
|
+
position: absolute;
|
|
3620
|
+
top: 0;
|
|
3621
|
+
bottom: 0;
|
|
3622
|
+
left: 0.35rem;
|
|
3623
|
+
display: inline-flex;
|
|
3624
|
+
align-items: center;
|
|
3625
|
+
justify-content: center;
|
|
3626
|
+
width: var(--nu-window-title-icon-width);
|
|
3627
|
+
overflow: hidden;
|
|
3628
|
+
color: inherit;
|
|
3629
|
+
}
|
|
3630
|
+
.nu-window__title-icon > svg,
|
|
3631
|
+
.nu-window__title-icon > img {
|
|
3632
|
+
display: block;
|
|
3633
|
+
max-width: 100%;
|
|
3634
|
+
max-height: calc(var(--nu-window-title-height) - 2px);
|
|
3635
|
+
}
|
|
3537
3636
|
.nu-window__title-controls {
|
|
3538
3637
|
position: absolute;
|
|
3539
3638
|
top: 0;
|
|
@@ -3726,6 +3825,16 @@ button.nu-app-bar-item:focus-visible {
|
|
|
3726
3825
|
outline: none;
|
|
3727
3826
|
box-shadow: none;
|
|
3728
3827
|
}
|
|
3828
|
+
.nu-window-bar__icon {
|
|
3829
|
+
display: inline-flex;
|
|
3830
|
+
align-items: center;
|
|
3831
|
+
justify-content: center;
|
|
3832
|
+
flex: none;
|
|
3833
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
3834
|
+
block-size: var(--nu-glyph-cell-size);
|
|
3835
|
+
margin-inline-end: 0.6ch;
|
|
3836
|
+
color: inherit;
|
|
3837
|
+
}
|
|
3729
3838
|
.nu-app-bar-host {
|
|
3730
3839
|
position: absolute;
|
|
3731
3840
|
right: 0;
|
|
@@ -15,7 +15,7 @@ type AppBarItemStaticProps = AppBarItemBaseProps & Omit<HTMLAttributes<HTMLDivEl
|
|
|
15
15
|
export type AppBarItemProps = AppBarItemButtonProps | AppBarItemStaticProps;
|
|
16
16
|
export declare function AppBarItem(props: AppBarItemProps): import("react").DetailedReactHTMLElement<{
|
|
17
17
|
className: string;
|
|
18
|
-
type: "button" | "
|
|
18
|
+
type: "button" | "reset" | "submit";
|
|
19
19
|
defaultChecked?: boolean | undefined | undefined;
|
|
20
20
|
defaultValue?: string | number | readonly string[] | undefined;
|
|
21
21
|
suppressContentEditableWarning?: boolean | undefined | undefined;
|
|
@@ -11,6 +11,10 @@ export type NuManagedWindowSnapshot = {
|
|
|
11
11
|
width?: number;
|
|
12
12
|
};
|
|
13
13
|
export type NuManagedWindowDefinition = {
|
|
14
|
+
/** Windows with the same value share their active/inactive chrome state. */
|
|
15
|
+
activationGroup?: string;
|
|
16
|
+
/** Locks pointer resizing to this width / height ratio and disables maximize. */
|
|
17
|
+
aspectRatio?: number;
|
|
14
18
|
appModal?: boolean;
|
|
15
19
|
bodyClassName?: string;
|
|
16
20
|
border?: WindowBorder;
|
|
@@ -18,7 +22,13 @@ export type NuManagedWindowDefinition = {
|
|
|
18
22
|
closeable?: boolean;
|
|
19
23
|
content: ReactNode | ((controls: NuManagedWindowControls) => ReactNode);
|
|
20
24
|
domain?: string;
|
|
25
|
+
/** Decorative visual rendered in the fixed left title-bar slot. */
|
|
26
|
+
icon?: ReactNode;
|
|
21
27
|
maximizable?: boolean;
|
|
28
|
+
/** Minimum rendered height and resize bound for this window. */
|
|
29
|
+
minHeight?: CSSProperties["minHeight"];
|
|
30
|
+
/** Minimum rendered width and resize bound for this window. */
|
|
31
|
+
minWidth?: CSSProperties["minWidth"];
|
|
22
32
|
modal?: boolean | string;
|
|
23
33
|
minimizable?: boolean;
|
|
24
34
|
mode?: WindowMode;
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -115,6 +115,8 @@ See: [Slot Customization](./SLOT_CUSTOMIZATION.md)
|
|
|
115
115
|
docs: [Splitter](./Splitter.md)
|
|
116
116
|
- `Stack`
|
|
117
117
|
docs: [Stack](./Stack.md)
|
|
118
|
+
- `Spacer`
|
|
119
|
+
docs: [Spacer](./Spacer.md)
|
|
118
120
|
- `ToolBar`, `ToolButton`, `ToolSeparator`
|
|
119
121
|
docs: [ToolBar](./ToolBar.md)
|
|
120
122
|
|
package/docs/COMPONENT_INDEX.md
CHANGED
package/docs/MainMenu.md
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
- `MainMenuItem`
|
|
19
19
|
- `id`
|
|
20
20
|
- `text`
|
|
21
|
+
- `icon?: ReactNode` — decorative icon in a popup menu row
|
|
21
22
|
- `hotkey?`
|
|
22
23
|
- `shortcut?`
|
|
23
24
|
- `checked?`
|
|
@@ -28,9 +29,19 @@
|
|
|
28
29
|
- `MainMenuDivider`
|
|
29
30
|
- `id`
|
|
30
31
|
- `type: "divider"`
|
|
32
|
+
- `MainMenuSpacer`
|
|
33
|
+
- `id`
|
|
34
|
+
- `type: "spacer"`
|
|
35
|
+
- Valid at the root level only; pushes following menu items to the right.
|
|
31
36
|
|
|
32
37
|
## Notes
|
|
33
38
|
|
|
34
39
|
- Top-level dropdowns open below their root items.
|
|
35
|
-
- Nested submenus open to the right
|
|
40
|
+
- Nested submenus open to the right by default and automatically open to the
|
|
41
|
+
left only when their right edge would leave the viewport.
|
|
36
42
|
- Active and hovered items use the same black selection pattern used elsewhere in the library.
|
|
43
|
+
- Popup-menu dividers use `--nu-menu-divider-color`,
|
|
44
|
+
`--nu-menu-divider-style`, and `--nu-menu-divider-width`.
|
|
45
|
+
- Use `{ id: "main-menu-spacer", type: "spacer" }` between root menu items to
|
|
46
|
+
align the following menu group to the opposite edge. Their dropdowns choose
|
|
47
|
+
the viewport-facing side when opened.
|
package/docs/NuWindowProvider.md
CHANGED
|
@@ -50,6 +50,78 @@ windowManager.openWindow({
|
|
|
50
50
|
});
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
## Title Icons
|
|
54
|
+
|
|
55
|
+
`openWindow(...)` and `openDialog(...)` accept `icon?: ReactNode`. It renders in
|
|
56
|
+
the fixed left title-bar slot, so managed dialogs use the same chrome as regular
|
|
57
|
+
windows. The same icon is reused in the minimized AppBar item, the MDI
|
|
58
|
+
`Window` menu, and the `Pick...` dialog.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
windowManager.openDialog({
|
|
62
|
+
content: <NetworkSettings />,
|
|
63
|
+
icon: <NuGlyph name="gear" />,
|
|
64
|
+
title: "Network settings"
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Fixed Aspect Ratio
|
|
69
|
+
|
|
70
|
+
Set a positive `aspectRatio` (width / height) for image, video, map, or other
|
|
71
|
+
fixed-ratio content. Pointer resizing keeps the ratio, combines `minWidth` and
|
|
72
|
+
`minHeight` into a ratio-consistent minimum, and disables maximizing the
|
|
73
|
+
managed window.
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
windowManager.openWindow({
|
|
77
|
+
aspectRatio: 178 / 704,
|
|
78
|
+
content: <VirtualRemote />,
|
|
79
|
+
minWidth: "11rem",
|
|
80
|
+
style: { height: "50rem", width: "13rem" },
|
|
81
|
+
title: "Remote"
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Linked Activation
|
|
86
|
+
|
|
87
|
+
Set the same `activationGroup` on managed windows that represent one logical
|
|
88
|
+
workspace. Activating either one gives every visible member of that group the
|
|
89
|
+
active window chrome. Activating a window outside the group makes all members
|
|
90
|
+
inactive again. This only links activation visuals; it does not dock, move, or
|
|
91
|
+
resize the windows together.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
windowManager.openWindow({
|
|
95
|
+
activationGroup: "receiver-42",
|
|
96
|
+
content: <ReceiverOverview />,
|
|
97
|
+
title: "Receiver overview"
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
windowManager.openWindow({
|
|
101
|
+
activationGroup: "receiver-42",
|
|
102
|
+
content: <ReceiverDiagnostics />,
|
|
103
|
+
title: "Receiver diagnostics"
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
App-modal dialogs remain the sole active surface while open, regardless of an
|
|
108
|
+
activation group.
|
|
109
|
+
|
|
110
|
+
## Size Limits
|
|
111
|
+
|
|
112
|
+
Managed windows accept `minWidth` and `minHeight` directly. They override the
|
|
113
|
+
provider's default minimum width (`26rem` for a window and `22rem` for a
|
|
114
|
+
dialog) and constrain pointer resizing as well as CSS layout.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
windowManager.openWindow({
|
|
118
|
+
content: <CompactLog />,
|
|
119
|
+
minHeight: "10rem",
|
|
120
|
+
minWidth: "18rem",
|
|
121
|
+
title: "Compact log"
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
53
125
|
## Helper Dialogs
|
|
54
126
|
|
|
55
127
|
The same manager also provides async helper dialogs:
|
package/docs/PopupMenu.md
CHANGED
|
@@ -40,6 +40,8 @@ const popupMenu = usePopupMenu();
|
|
|
40
40
|
## Notes
|
|
41
41
|
|
|
42
42
|
- Popup menus render through a portal and are not clipped by local overflow containers.
|
|
43
|
+
- Nested popup-menu levels open to the right by default and flip left only when
|
|
44
|
+
they would overflow the viewport.
|
|
43
45
|
- `openFromContextMenu(event)` carries the event target into the portal, so
|
|
44
46
|
context menus inherit tokens from the nearest `NuThemeProvider`. Pass the
|
|
45
47
|
optional `themeSource` to `openAtPoint(...)` when opening one manually.
|
package/docs/Spacer.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Spacer
|
|
2
|
+
|
|
3
|
+
`Spacer` fills unused space in a flex layout, moving all following controls to
|
|
4
|
+
the opposite edge. It is decorative and is hidden from assistive technology.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```tsx
|
|
9
|
+
<ToolBar>
|
|
10
|
+
<ToolButton>&Open</ToolButton>
|
|
11
|
+
<Spacer />
|
|
12
|
+
<ToolButton>&Help</ToolButton>
|
|
13
|
+
</ToolBar>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
It works in `ToolBar`, `Stack direction="row"`, and a window `statusBar`:
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
<Window
|
|
20
|
+
statusBar={
|
|
21
|
+
<>
|
|
22
|
+
<StatusBarItem>F2 Save</StatusBarItem>
|
|
23
|
+
<Spacer />
|
|
24
|
+
<StatusBarItem>Ready</StatusBarItem>
|
|
25
|
+
</>
|
|
26
|
+
}
|
|
27
|
+
title="Editor"
|
|
28
|
+
/>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For a root `MainMenu`, use the menu model equivalent:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const items: MainMenuNode[] = [
|
|
35
|
+
{ id: "file", text: "&File" },
|
|
36
|
+
{ id: "window", text: "&Window" },
|
|
37
|
+
{ id: "menu-spacer", type: "spacer" },
|
|
38
|
+
{ id: "profile", text: "&Profile" },
|
|
39
|
+
{ id: "about", text: "&About" }
|
|
40
|
+
];
|
|
41
|
+
```
|
package/docs/StatusBarItem.md
CHANGED
package/docs/TOKEN_CHECKLIST.md
CHANGED
|
@@ -61,6 +61,15 @@ If a component needs a new reusable visual value, add it there first instead of
|
|
|
61
61
|
- `--nu-control-height`
|
|
62
62
|
- `--nu-frame-thickness`
|
|
63
63
|
- `--nu-rule-thickness`
|
|
64
|
+
- Toolbar and menu dividers:
|
|
65
|
+
- `--nu-toolbar-background`
|
|
66
|
+
- `--nu-toolbar-inset`
|
|
67
|
+
- `--nu-toolbar-border-color`, `--nu-toolbar-border-style`,
|
|
68
|
+
`--nu-toolbar-border-width`
|
|
69
|
+
- `--nu-toolbar-separator-color`, `--nu-toolbar-separator-style`,
|
|
70
|
+
`--nu-toolbar-separator-width`
|
|
71
|
+
- `--nu-menu-divider-color`, `--nu-menu-divider-style`,
|
|
72
|
+
`--nu-menu-divider-width`
|
|
64
73
|
- Button mechanics:
|
|
65
74
|
- `--nu-button-shadow-x`
|
|
66
75
|
- `--nu-button-shadow-y`
|
package/docs/ToolBar.md
CHANGED
|
@@ -7,12 +7,13 @@ For the same button behavior outside a toolbar container, use [CommandButton](./
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
9
|
```tsx
|
|
10
|
-
<ToolBar>
|
|
10
|
+
<ToolBar startContent={<NuGlyph aria-hidden name="folder" />}>
|
|
11
11
|
<ToolButton icon="folder">&Scan</ToolButton>
|
|
12
12
|
<ToolButton icon="star" pressed>
|
|
13
13
|
&Watch
|
|
14
14
|
</ToolButton>
|
|
15
15
|
<ToolSeparator />
|
|
16
|
+
<Spacer />
|
|
16
17
|
<ToolDropButton
|
|
17
18
|
icon="folder"
|
|
18
19
|
menuItems={[
|
|
@@ -32,20 +33,32 @@ For the same button behavior outside a toolbar container, use [CommandButton](./
|
|
|
32
33
|
- `ToolButton`
|
|
33
34
|
- `ToolDropButton`
|
|
34
35
|
- `ToolSeparator`
|
|
36
|
+
- `Spacer`
|
|
35
37
|
|
|
36
38
|
## Key Props
|
|
37
39
|
|
|
38
40
|
- `fill?: boolean`
|
|
39
41
|
- `wrap?: boolean`
|
|
42
|
+
- `startContent?: ReactNode`
|
|
43
|
+
- `endContent?: ReactNode`
|
|
40
44
|
- `slotStyles`
|
|
41
45
|
- `slotClassNames`
|
|
42
46
|
|
|
43
47
|
## Notes
|
|
44
48
|
|
|
45
|
-
- `ToolBar`
|
|
49
|
+
- `ToolBar` defaults to `fill={true}` and uses `--nu-toolbar-background` for
|
|
50
|
+
its surface.
|
|
51
|
+
- `startContent` and `endContent` render static React content before and after
|
|
52
|
+
the controls. Use them for decorative icons or compact status text, not for
|
|
53
|
+
actions that need toolbar keyboard semantics.
|
|
46
54
|
- `wrap={true}` lets tools continue on the next row when the container is too narrow.
|
|
47
55
|
- `ToolButton` supports `toggled` for toggle-style tools. `pressed` is kept as a legacy alias through the shared command-button layer.
|
|
48
56
|
- `ToolButton` also supports `icon` and optional `dropdown`.
|
|
49
57
|
- `ToolDropButton` is a convenience wrapper for `ToolButton dropdown`.
|
|
50
58
|
- If `menuItems` are provided, `ToolDropButton` opens `PopupMenu` automatically and reports selection through `onMenuItemSelect`.
|
|
51
59
|
- `ToolSeparator` is decorative and should only be used between tools.
|
|
60
|
+
- Toolbar chrome is themeable through `--nu-toolbar-border-color`,
|
|
61
|
+
`--nu-toolbar-border-style`, and `--nu-toolbar-border-width`; separators
|
|
62
|
+
use the corresponding `--nu-toolbar-separator-*` tokens.
|
|
63
|
+
- `--nu-toolbar-inset` controls Toolbar padding on all four sides.
|
|
64
|
+
- `Spacer` fills free space and moves following tools to the opposite edge.
|
package/docs/Window.md
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
14
|
<Window
|
|
15
|
+
icon={<NuGlyph name="folder" />}
|
|
15
16
|
title="Activity Log"
|
|
16
17
|
mode="window"
|
|
17
18
|
statusBar={
|
|
@@ -30,11 +31,16 @@
|
|
|
30
31
|
- `title: string`
|
|
31
32
|
- `mode?: "dialog" | "window"`
|
|
32
33
|
- `border?: "single" | "double"`
|
|
34
|
+
- `icon?: ReactNode` — decorative visual in the fixed left title-bar slot
|
|
33
35
|
- `minimized?: boolean`
|
|
34
36
|
- `maximized?: boolean`
|
|
35
37
|
- `closeable?: boolean`
|
|
36
38
|
- `draggable?: boolean`
|
|
37
39
|
- `resizable?: boolean`
|
|
40
|
+
- `aspectRatio?: number` — positive width / height ratio; locks pointer resize
|
|
41
|
+
and suppresses the maximize control
|
|
42
|
+
- `minWidth?: number | string` — defaults to `240px` for a standalone window
|
|
43
|
+
- `minHeight?: number | string` — defaults to `120px` for a standalone window
|
|
38
44
|
- `scrollable?: boolean`
|
|
39
45
|
- `statusBar?: ReactNode`
|
|
40
46
|
- `titleButtons?: WindowTitleButtonDefinition[]`
|
|
@@ -45,9 +51,22 @@
|
|
|
45
51
|
- `onSizeChange?(size)`
|
|
46
52
|
- `onActivate?()`
|
|
47
53
|
|
|
54
|
+
`activationGroup?: string` is available on a managed window definition passed
|
|
55
|
+
to `useNuWindowManager().openWindow(...)`; it is resolved by
|
|
56
|
+
`NuWindowProvider`, rather than by a standalone `Window` instance. See
|
|
57
|
+
[NuWindowProvider](./NuWindowProvider.md#linked-activation).
|
|
58
|
+
|
|
48
59
|
## Notes
|
|
49
60
|
|
|
50
61
|
- Drag and resize are implemented with pointer events and local DOM updates for smoother motion.
|
|
51
62
|
- The public `WindowTitleButton` and `useWindowTitleButtons()` helpers support custom title-bar controls.
|
|
63
|
+
- The left title-bar slot is always reserved. Pass `icon` to show a `NuGlyph`,
|
|
64
|
+
Font Awesome icon, SVG, or another React node without shifting the title.
|
|
52
65
|
- `StatusBarItem` only provides placement semantics (`grow`, `align`) and does not enforce its own border or chrome.
|
|
53
66
|
- Plain string `statusBar` still works for simple status lines.
|
|
67
|
+
- `minWidth` and `minHeight` are applied as CSS limits and as the lower bounds
|
|
68
|
+
for pointer resizing. A managed window may also specify them in its
|
|
69
|
+
`openWindow(...)` definition.
|
|
70
|
+
- With `aspectRatio`, resizing follows whichever pointer axis has the greater
|
|
71
|
+
ratio-adjusted movement. The other dimension is derived from the ratio, and
|
|
72
|
+
the effective minimum remains ratio-consistent.
|
package/docs/WindowBar.md
CHANGED
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
- Marks the active window
|
|
18
18
|
- Groups windows by `domain`
|
|
19
19
|
- Opens a picker dialog when a grouped domain is clicked
|
|
20
|
+
- Shows each managed window's `icon` beside its title; grouped entries use the
|
|
21
|
+
active window's icon when one is available
|
|
20
22
|
|
|
21
23
|
## Notes
|
|
22
24
|
|
|
23
25
|
- Grouping is driven by `NuManagedWindowDefinition.domain`.
|
|
24
26
|
- Grouped pickers use the shared MDI-style window picker dialog logic.
|
|
27
|
+
- The MDI `Window` menu and `Pick...` dialog reuse the same managed-window icon.
|