@deadragdoll/reactnu 0.1.52 → 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/MainMenu/MainMenu.types.d.ts +3 -0
- package/dist/components/Window/Window.d.ts +8 -2
- package/dist/components/Window/internals/WindowTitleBar.d.ts +3 -2
- package/dist/index.cjs +88 -43
- package/dist/index.js +184 -139
- package/dist/styles.css +40 -2
- package/dist/windowing/WindowBar.d.ts +2 -0
- package/dist/windowing/windowing.types.d.ts +10 -0
- package/docs/MainMenu.md +1 -0
- package/docs/NuWindowProvider.md +72 -0
- package/docs/Window.md +19 -0
- package/docs/WindowBar.md +3 -0
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
--nu-window-shadow-offset-x: 1ch;
|
|
52
52
|
--nu-window-shadow-offset-y: 1em;
|
|
53
53
|
--nu-window-title-controls-width: 7.8ch;
|
|
54
|
+
--nu-window-title-icon-width: 1em;
|
|
54
55
|
--nu-window-title-height: calc(1em + 3px);
|
|
55
56
|
--nu-window-status-height: 1.35rem;
|
|
56
57
|
--nu-window-inactive-overlay: rgba(0, 0, 0, 0.22);
|
|
@@ -1092,7 +1093,7 @@
|
|
|
1092
1093
|
padding: 0 0.65rem;
|
|
1093
1094
|
}
|
|
1094
1095
|
.nu-main-menu__item--submenu .nu-main-menu__item-button {
|
|
1095
|
-
grid-template-columns: 1.1rem 1fr auto 0.8rem;
|
|
1096
|
+
grid-template-columns: 1.1rem var(--nu-glyph-cell-size) 1fr auto 0.8rem;
|
|
1096
1097
|
gap: 0.45rem;
|
|
1097
1098
|
width: 100%;
|
|
1098
1099
|
min-width: 13rem;
|
|
@@ -1175,6 +1176,14 @@
|
|
|
1175
1176
|
.nu-main-menu__check-box[data-unchecked-shape="none"] {
|
|
1176
1177
|
border-color: transparent;
|
|
1177
1178
|
}
|
|
1179
|
+
.nu-main-menu__icon {
|
|
1180
|
+
display: inline-flex;
|
|
1181
|
+
align-items: center;
|
|
1182
|
+
justify-content: center;
|
|
1183
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
1184
|
+
block-size: var(--nu-glyph-cell-size);
|
|
1185
|
+
color: currentColor;
|
|
1186
|
+
}
|
|
1178
1187
|
.nu-main-menu__label {
|
|
1179
1188
|
min-width: 0;
|
|
1180
1189
|
}
|
|
@@ -3520,7 +3529,8 @@
|
|
|
3520
3529
|
align-items: center;
|
|
3521
3530
|
justify-content: center;
|
|
3522
3531
|
min-height: var(--nu-window-title-height);
|
|
3523
|
-
padding: 0 var(--nu-window-title-controls-width) 0
|
|
3532
|
+
padding: 0 var(--nu-window-title-controls-width) 0
|
|
3533
|
+
calc(0.45rem + var(--nu-window-title-icon-width));
|
|
3524
3534
|
background: var(--nu-color-title-bg);
|
|
3525
3535
|
color: var(--nu-color-title-text);
|
|
3526
3536
|
line-height: 1;
|
|
@@ -3534,6 +3544,24 @@
|
|
|
3534
3544
|
text-overflow: ellipsis;
|
|
3535
3545
|
white-space: nowrap;
|
|
3536
3546
|
}
|
|
3547
|
+
.nu-window__title-icon {
|
|
3548
|
+
position: absolute;
|
|
3549
|
+
top: 0;
|
|
3550
|
+
bottom: 0;
|
|
3551
|
+
left: 0.35rem;
|
|
3552
|
+
display: inline-flex;
|
|
3553
|
+
align-items: center;
|
|
3554
|
+
justify-content: center;
|
|
3555
|
+
width: var(--nu-window-title-icon-width);
|
|
3556
|
+
overflow: hidden;
|
|
3557
|
+
color: inherit;
|
|
3558
|
+
}
|
|
3559
|
+
.nu-window__title-icon > svg,
|
|
3560
|
+
.nu-window__title-icon > img {
|
|
3561
|
+
display: block;
|
|
3562
|
+
max-width: 100%;
|
|
3563
|
+
max-height: calc(var(--nu-window-title-height) - 2px);
|
|
3564
|
+
}
|
|
3537
3565
|
.nu-window__title-controls {
|
|
3538
3566
|
position: absolute;
|
|
3539
3567
|
top: 0;
|
|
@@ -3726,6 +3754,16 @@ button.nu-app-bar-item:focus-visible {
|
|
|
3726
3754
|
outline: none;
|
|
3727
3755
|
box-shadow: none;
|
|
3728
3756
|
}
|
|
3757
|
+
.nu-window-bar__icon {
|
|
3758
|
+
display: inline-flex;
|
|
3759
|
+
align-items: center;
|
|
3760
|
+
justify-content: center;
|
|
3761
|
+
flex: none;
|
|
3762
|
+
inline-size: var(--nu-glyph-cell-size);
|
|
3763
|
+
block-size: var(--nu-glyph-cell-size);
|
|
3764
|
+
margin-inline-end: 0.6ch;
|
|
3765
|
+
color: inherit;
|
|
3766
|
+
}
|
|
3729
3767
|
.nu-app-bar-host {
|
|
3730
3768
|
position: absolute;
|
|
3731
3769
|
right: 0;
|
|
@@ -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/MainMenu.md
CHANGED
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/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.
|