@deadragdoll/reactnu 0.1.9
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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/appHost/NuAppHostProvider.d.ts +6 -0
- package/dist/appHost/appHostContext.d.ts +26 -0
- package/dist/components/Button/Button.d.ts +13 -0
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/CheckBox/CheckBox.d.ts +14 -0
- package/dist/components/CheckBox/index.d.ts +1 -0
- package/dist/components/ComboBox/ComboBox.d.ts +23 -0
- package/dist/components/ComboBox/index.d.ts +1 -0
- package/dist/components/CommandButton/CommandButton.d.ts +17 -0
- package/dist/components/CommandButton/index.d.ts +1 -0
- package/dist/components/CrtGlitch/CrtGlitch.d.ts +23 -0
- package/dist/components/CrtGlitch/index.d.ts +1 -0
- package/dist/components/Dashboard/Dashboard.d.ts +25 -0
- package/dist/components/Dashboard/index.d.ts +1 -0
- package/dist/components/Desktop/Desktop.d.ts +6 -0
- package/dist/components/Desktop/index.d.ts +1 -0
- package/dist/components/Dropdown/Dropdown.d.ts +19 -0
- package/dist/components/Dropdown/index.d.ts +1 -0
- package/dist/components/Frame/Frame.d.ts +24 -0
- package/dist/components/Frame/index.d.ts +1 -0
- package/dist/components/Glyph/NuGlyph.d.ts +6 -0
- package/dist/components/Glyph/index.d.ts +1 -0
- package/dist/components/Info/Info.d.ts +13 -0
- package/dist/components/Info/index.d.ts +1 -0
- package/dist/components/ListBox/ListBox.d.ts +23 -0
- package/dist/components/ListBox/index.d.ts +1 -0
- package/dist/components/ListBox/internals/ListBoxCategoryView.d.ts +6 -0
- package/dist/components/ListBox/internals/ListBoxCheckControl.d.ts +8 -0
- package/dist/components/ListBox/internals/ListBoxGroupView.d.ts +17 -0
- package/dist/components/ListBox/internals/ListBoxItemView.d.ts +18 -0
- package/dist/components/ListBox/internals/helpers.d.ts +5 -0
- package/dist/components/ListBox/internals/renderLabel.d.ts +2 -0
- package/dist/components/ListBox/internals/types.d.ts +27 -0
- package/dist/components/ListView/ListView.d.ts +27 -0
- package/dist/components/ListView/index.d.ts +1 -0
- package/dist/components/ListView/internals/ListViewCheckControl.d.ts +8 -0
- package/dist/components/ListView/internals/ListViewRow.d.ts +18 -0
- package/dist/components/ListView/internals/helpers.d.ts +5 -0
- package/dist/components/ListView/internals/types.d.ts +17 -0
- package/dist/components/MainMenu/MainMenu.d.ts +8 -0
- package/dist/components/MainMenu/MainMenu.types.d.ts +23 -0
- package/dist/components/MainMenu/index.d.ts +3 -0
- package/dist/components/MainMenu/internals/MainMenuList.d.ts +12 -0
- package/dist/components/MainMenu/menuState.d.ts +40 -0
- package/dist/components/MaskedField/MaskedField.d.ts +13 -0
- package/dist/components/MaskedField/index.d.ts +2 -0
- package/dist/components/MaskedField/textMask.d.ts +8 -0
- package/dist/components/Memo/Memo.d.ts +14 -0
- package/dist/components/Memo/index.d.ts +1 -0
- package/dist/components/PageControl/PageControl.d.ts +20 -0
- package/dist/components/PageControl/index.d.ts +1 -0
- package/dist/components/Panel/Panel.d.ts +11 -0
- package/dist/components/Panel/index.d.ts +1 -0
- package/dist/components/PopupMenu/PopupMenu.d.ts +22 -0
- package/dist/components/PopupMenu/index.d.ts +2 -0
- package/dist/components/PopupMenu/usePopupMenu.d.ts +12 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +17 -0
- package/dist/components/ProgressBar/index.d.ts +1 -0
- package/dist/components/PropertyGrid/PropertyGrid.d.ts +38 -0
- package/dist/components/PropertyGrid/index.d.ts +1 -0
- package/dist/components/RadioGroup/RadioButton.d.ts +9 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +21 -0
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/ReportCell/ReportCell.d.ts +6 -0
- package/dist/components/ReportCell/index.d.ts +1 -0
- package/dist/components/SearchBox/SearchBox.d.ts +23 -0
- package/dist/components/SearchBox/index.d.ts +1 -0
- package/dist/components/SpinBox/SpinBox.d.ts +16 -0
- package/dist/components/SpinBox/index.d.ts +1 -0
- package/dist/components/Splitter/Splitter.d.ts +15 -0
- package/dist/components/Splitter/index.d.ts +1 -0
- package/dist/components/Stack/Stack.d.ts +13 -0
- package/dist/components/Stack/index.d.ts +1 -0
- package/dist/components/TextField/TextField.d.ts +12 -0
- package/dist/components/TextField/index.d.ts +1 -0
- package/dist/components/TickBar/TickBar.d.ts +22 -0
- package/dist/components/TickBar/index.d.ts +1 -0
- package/dist/components/ToolBar/ToolBar.d.ts +25 -0
- package/dist/components/ToolBar/index.d.ts +1 -0
- package/dist/components/TreeListView/TreeListView.d.ts +33 -0
- package/dist/components/TreeListView/index.d.ts +1 -0
- package/dist/components/TreeListView/internals/TreeListViewRow.d.ts +28 -0
- package/dist/components/TreeListView/internals/helpers.d.ts +14 -0
- package/dist/components/TreeListView/internals/types.d.ts +32 -0
- package/dist/components/TreeView/TreeView.d.ts +26 -0
- package/dist/components/TreeView/index.d.ts +1 -0
- package/dist/components/TreeView/internals/TreeViewItem.d.ts +21 -0
- package/dist/components/TreeView/internals/helpers.d.ts +5 -0
- package/dist/components/TreeView/internals/types.d.ts +10 -0
- package/dist/components/View/NuView.d.ts +10 -0
- package/dist/components/View/index.d.ts +1 -0
- package/dist/components/Window/StatusBarItem.d.ts +7 -0
- package/dist/components/Window/Window.d.ts +41 -0
- package/dist/components/Window/WindowTitleButton.d.ts +17 -0
- package/dist/components/Window/index.d.ts +5 -0
- package/dist/components/Window/internals/WindowStatusBar.d.ts +8 -0
- package/dist/components/Window/internals/WindowTitleBar.d.ts +10 -0
- package/dist/components/Window/useWindowTitleButtons.d.ts +12 -0
- package/dist/components/Window/windowMenuContext.d.ts +3 -0
- package/dist/components/_shared/ControlOpener.d.ts +18 -0
- package/dist/components/_shared/portalPositioning.d.ts +16 -0
- package/dist/components/_shared/slotProps.d.ts +867 -0
- package/dist/components/_shared/themePortal.d.ts +2 -0
- package/dist/components/_shared/treeData.d.ts +19 -0
- package/dist/components/_shared/usePopupPosition.d.ts +40 -0
- package/dist/index.cjs +9848 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +9885 -0
- package/dist/styles.css +3644 -0
- package/dist/theme/NuThemeProvider.d.ts +26 -0
- package/dist/theme/themeContext.d.ts +15 -0
- package/dist/theme/themes.d.ts +49 -0
- package/dist/utils/renderMnemonicText.d.ts +10 -0
- package/dist/windowing/AppBarHost.d.ts +6 -0
- package/dist/windowing/AppBarItem.d.ts +587 -0
- package/dist/windowing/NuWindowProvider.d.ts +9 -0
- package/dist/windowing/WindowBar.d.ts +13 -0
- package/dist/windowing/dialogHelpers.d.ts +1793 -0
- package/dist/windowing/internals/MdiWindowPickerDialog.d.ts +10 -0
- package/dist/windowing/mdiMenu.d.ts +3 -0
- package/dist/windowing/windowContext.d.ts +18 -0
- package/dist/windowing/windowing.constants.d.ts +1 -0
- package/dist/windowing/windowing.types.d.ts +54 -0
- package/docs/API_REFERENCE.md +150 -0
- package/docs/ARCHITECTURE.md +170 -0
- package/docs/AppBarHost.md +22 -0
- package/docs/AppBarItem.md +22 -0
- package/docs/Button.md +24 -0
- package/docs/COMPONENT_INDEX.md +64 -0
- package/docs/CONTRIBUTOR_GUIDE.md +393 -0
- package/docs/CheckBox.md +30 -0
- package/docs/ComboBox.md +41 -0
- package/docs/CommandButton.md +45 -0
- package/docs/CrtGlitch.md +49 -0
- package/docs/Dashboard.md +73 -0
- package/docs/Desktop.md +27 -0
- package/docs/DialogHelpers.md +85 -0
- package/docs/Dropdown.md +44 -0
- package/docs/Frame.md +38 -0
- package/docs/GETTING_STARTED.md +110 -0
- package/docs/Glyph.md +29 -0
- package/docs/Info.md +51 -0
- package/docs/ListBox.md +35 -0
- package/docs/ListView.md +62 -0
- package/docs/MainMenu.md +36 -0
- package/docs/MaskedField.md +124 -0
- package/docs/Memo.md +32 -0
- package/docs/NuAppHostProvider.md +28 -0
- package/docs/NuThemeProvider.md +64 -0
- package/docs/NuView.md +58 -0
- package/docs/NuWindowProvider.md +81 -0
- package/docs/PageControl.md +28 -0
- package/docs/Panel.md +23 -0
- package/docs/PopupMenu.md +42 -0
- package/docs/ProgressBar.md +33 -0
- package/docs/PropertyGrid.md +63 -0
- package/docs/RadioGroup.md +36 -0
- package/docs/ReportCell.md +27 -0
- package/docs/SLOT_CUSTOMIZATION.md +85 -0
- package/docs/STORYBOOK.md +96 -0
- package/docs/SearchBox.md +41 -0
- package/docs/SpinBox.md +25 -0
- package/docs/Splitter.md +91 -0
- package/docs/Stack.md +26 -0
- package/docs/StatusBarItem.md +31 -0
- package/docs/TOKEN_CHECKLIST.md +122 -0
- package/docs/TextField.md +27 -0
- package/docs/TickBar.md +57 -0
- package/docs/ToolBar.md +51 -0
- package/docs/TreeListView.md +84 -0
- package/docs/TreeView.md +53 -0
- package/docs/Window.md +53 -0
- package/docs/WindowBar.md +24 -0
- package/package.json +47 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# NuThemeProvider
|
|
2
|
+
|
|
3
|
+
`NuThemeProvider` applies design tokens for the active visual theme.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<NuThemeProvider>
|
|
9
|
+
<NuDesktop appBar={<AppBar />}>
|
|
10
|
+
<App />
|
|
11
|
+
</NuDesktop>
|
|
12
|
+
</NuThemeProvider>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Typography can also be configured at the provider level:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<NuThemeProvider
|
|
19
|
+
defaultFontFamily={'"Comic Sans MS", "Comic Sans", cursive'}
|
|
20
|
+
defaultFontSize={16}
|
|
21
|
+
>
|
|
22
|
+
<App />
|
|
23
|
+
</NuThemeProvider>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Related API
|
|
27
|
+
|
|
28
|
+
- `useNuTheme()`
|
|
29
|
+
- `nuThemes`
|
|
30
|
+
- `resolveNuTheme(...)`
|
|
31
|
+
- `isNuThemeName(...)`
|
|
32
|
+
|
|
33
|
+
## Provider Typography
|
|
34
|
+
|
|
35
|
+
`NuThemeProvider` now owns both theme tokens and base typography for the full UI tree.
|
|
36
|
+
|
|
37
|
+
Supported props:
|
|
38
|
+
|
|
39
|
+
- `desktopPatternMode?: "dot-grid" | "dense-dots" | "coarse-dots" | "grid" | "solid"`
|
|
40
|
+
- `defaultDesktopPatternMode?: ...`
|
|
41
|
+
- `onDesktopPatternModeChange?: (mode) => void`
|
|
42
|
+
- `fontFamily?: string`
|
|
43
|
+
- `defaultFontFamily?: string`
|
|
44
|
+
- `onFontFamilyChange?: (fontFamily) => void`
|
|
45
|
+
- `fontSize?: number`
|
|
46
|
+
- `defaultFontSize?: number`
|
|
47
|
+
- `onFontSizeChange?: (fontSize) => void`
|
|
48
|
+
- `crtGlitch?: boolean | NuCrtGlitchProps`
|
|
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
|
+
|
|
51
|
+
`useNuTheme()` exposes:
|
|
52
|
+
|
|
53
|
+
- `desktopPatternMode`
|
|
54
|
+
- `fontFamily`
|
|
55
|
+
- `fontSize`
|
|
56
|
+
- `setDesktopPatternMode(...)`
|
|
57
|
+
- `setFontFamily(...)`
|
|
58
|
+
- `setFontSize(...)`
|
|
59
|
+
|
|
60
|
+
## Notes
|
|
61
|
+
|
|
62
|
+
- The default theme is the classic DOS/Norton-inspired palette.
|
|
63
|
+
- Theme tokens drive desktop, windowing, controls, selection, and inactive overlays.
|
|
64
|
+
- Provider typography affects preview content, managed windows, dialogs, menus, and popup portals rendered inside the theme scope.
|
package/docs/NuView.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# NuView
|
|
2
|
+
|
|
3
|
+
`NuView` is a generic fill-and-scroll container for hosting content inside frames, panes, dialogs, and splitter cells.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<NuView padding="sm">
|
|
9
|
+
<Frame title="Inspector">
|
|
10
|
+
<Stack gap="md">{/* content */}</Stack>
|
|
11
|
+
</Frame>
|
|
12
|
+
</NuView>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Key Props
|
|
16
|
+
|
|
17
|
+
- `fill?: boolean`
|
|
18
|
+
- `scroll?: "auto" | "x" | "y" | "both" | "hidden"`
|
|
19
|
+
- `padding?: "none" | "sm" | "md" | "lg"`
|
|
20
|
+
|
|
21
|
+
## Notes
|
|
22
|
+
|
|
23
|
+
- `fill` defaults to `true`, so `NuView` expands to the available area in common pane/frame layouts.
|
|
24
|
+
- `NuView` is the place where host code should declare scroll behavior, instead of relying on incidental overflow from parent containers.
|
|
25
|
+
- It is intended to simplify content composition inside `Splitter`, `Frame`, `Window`, and similar layout shells.
|
|
26
|
+
|
|
27
|
+
## Recommended Ownership
|
|
28
|
+
|
|
29
|
+
`NuView` should usually own the viewport area.
|
|
30
|
+
|
|
31
|
+
Good fit:
|
|
32
|
+
|
|
33
|
+
- splitter cells
|
|
34
|
+
- resizable panes
|
|
35
|
+
- frame-like shells inside windows
|
|
36
|
+
- any place where the host wants one explicit scroll/fill container
|
|
37
|
+
|
|
38
|
+
Typical pattern:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<NuView scroll="auto" padding="sm">
|
|
42
|
+
<Frame title="Status">{/* content */}</Frame>
|
|
43
|
+
</NuView>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This is especially important in `Splitter` layouts, where `NuView` should sit directly inside the pane and define how that pane scrolls.
|
|
47
|
+
|
|
48
|
+
## Protocol Note
|
|
49
|
+
|
|
50
|
+
During splitter integration we hit a concrete bug:
|
|
51
|
+
|
|
52
|
+
- `NuView` was implemented too deep in the tree.
|
|
53
|
+
- It did not own the pane viewport.
|
|
54
|
+
- Scroll behavior looked wrong because the pane owner and the viewport owner were different components.
|
|
55
|
+
|
|
56
|
+
The current rule is:
|
|
57
|
+
|
|
58
|
+
`pane -> NuView -> content`
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# NuWindowProvider
|
|
2
|
+
|
|
3
|
+
`NuWindowProvider` is the window manager for the desktop shell.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<NuWindowProvider>
|
|
9
|
+
<Workspace />
|
|
10
|
+
</NuWindowProvider>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Main API
|
|
14
|
+
|
|
15
|
+
Use `useNuWindowManager()` to access:
|
|
16
|
+
|
|
17
|
+
- `openWindow(definition)`
|
|
18
|
+
- `openDialog(definition)`
|
|
19
|
+
- `showMessageBox(options)`
|
|
20
|
+
- `showInputBox(options)`
|
|
21
|
+
- `closeWindow(id)`
|
|
22
|
+
- `updateWindow(id, patch)`
|
|
23
|
+
- `activateWindow(id)`
|
|
24
|
+
- `bringToFront(id)`
|
|
25
|
+
- `toggleWindowMinimized(id)`
|
|
26
|
+
- `toggleWindowMaximized(id)`
|
|
27
|
+
- `closeAll()`
|
|
28
|
+
- `windows`
|
|
29
|
+
|
|
30
|
+
## Managed Window Persistence
|
|
31
|
+
|
|
32
|
+
`NuManagedWindowDefinition` also supports:
|
|
33
|
+
|
|
34
|
+
- `onOpen?: () => NuManagedWindowSnapshot | void`
|
|
35
|
+
- `onClose?: (snapshot: NuManagedWindowSnapshot) => boolean | void`
|
|
36
|
+
|
|
37
|
+
This lets the host save and restore window geometry:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
let savedWindowState: NuManagedWindowSnapshot | undefined;
|
|
41
|
+
|
|
42
|
+
windowManager.openWindow({
|
|
43
|
+
title: "Inspector",
|
|
44
|
+
content: <Inspector />,
|
|
45
|
+
onOpen: () => savedWindowState,
|
|
46
|
+
onClose: (snapshot) => {
|
|
47
|
+
savedWindowState = snapshot;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Helper Dialogs
|
|
54
|
+
|
|
55
|
+
The same manager also provides async helper dialogs:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const result = await windowManager.showMessageBox({
|
|
59
|
+
title: "Diagnostics",
|
|
60
|
+
message: "Continue with the maintenance pass?",
|
|
61
|
+
kind: "info",
|
|
62
|
+
yes: true,
|
|
63
|
+
no: true
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const value = await windowManager.showInputBox({
|
|
67
|
+
title: "Archive Report",
|
|
68
|
+
label: "Target path",
|
|
69
|
+
defaultValue: "C:\\LOGS\\SURFACE.MAP"
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See [Dialog Helpers](./DialogHelpers.md) for the full option list.
|
|
74
|
+
|
|
75
|
+
## Notes
|
|
76
|
+
|
|
77
|
+
- Supports app-modal and owner-modal dialogs.
|
|
78
|
+
- Keeps window list order stable for app-bar display while still maintaining a separate visual z-stack.
|
|
79
|
+
- `onOpen` is applied when the managed window record is created.
|
|
80
|
+
- `onClose` receives the latest saved geometry and `maximized/minimized` state.
|
|
81
|
+
- Returning `false` from `onClose` vetoes the close request.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# PageControl
|
|
2
|
+
|
|
3
|
+
`PageControl` is the tabbed page surface for switching between compact tool panels inside the same window.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<PageControl
|
|
9
|
+
pages={[
|
|
10
|
+
{ id: "summary", label: "&Summary", content: <SummaryPanel /> },
|
|
11
|
+
{ id: "detail", label: "&Detail", content: <DetailPanel /> }
|
|
12
|
+
]}
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Key Props
|
|
17
|
+
|
|
18
|
+
- `pages: PageControlPage[]`
|
|
19
|
+
- `activePageId?: string`
|
|
20
|
+
- `defaultActivePageId?: string`
|
|
21
|
+
- `onActivePageChange?: (page) => void`
|
|
22
|
+
- `fill?: boolean`
|
|
23
|
+
|
|
24
|
+
## Notes
|
|
25
|
+
|
|
26
|
+
- The component supports controlled and uncontrolled page selection.
|
|
27
|
+
- Keyboard navigation includes `Left/Right`, `Up/Down`, `Home`, and `End`.
|
|
28
|
+
- `Tabs` is exported as an alias of `PageControl`.
|
package/docs/Panel.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Panel
|
|
2
|
+
|
|
3
|
+
`Panel` is a heavier container surface for primary application regions.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Panel title="System Core" footer="F1 Help" inset>
|
|
9
|
+
<Content />
|
|
10
|
+
</Panel>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Key Props
|
|
14
|
+
|
|
15
|
+
- `title?: string`
|
|
16
|
+
- `footer?: string`
|
|
17
|
+
- `inset?: boolean`
|
|
18
|
+
- `children`
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
- `Panel` is the main raised surface.
|
|
23
|
+
- `inset` is useful for denser workspace-like regions inside a larger shell.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# PopupMenu
|
|
2
|
+
|
|
3
|
+
`PopupMenu` is a context-style menu surface built on the same menu item model as `MainMenu`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
const popupMenu = usePopupMenu();
|
|
9
|
+
|
|
10
|
+
<Button onClick={popupMenu.openFromClick}>Open popup</Button>
|
|
11
|
+
<PopupMenu
|
|
12
|
+
anchor={popupMenu.anchor}
|
|
13
|
+
open={popupMenu.open}
|
|
14
|
+
onOpenChange={popupMenu.setOpen}
|
|
15
|
+
items={items}
|
|
16
|
+
/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Key Props
|
|
20
|
+
|
|
21
|
+
- `items: MainMenuNode[]`
|
|
22
|
+
- `anchor: PopupMenuAnchor | null`
|
|
23
|
+
- `open?: boolean`
|
|
24
|
+
- `defaultOpen?: boolean`
|
|
25
|
+
- `onOpenChange?: (open) => void`
|
|
26
|
+
- `onItemSelect?: (item) => void`
|
|
27
|
+
|
|
28
|
+
## Related Hook
|
|
29
|
+
|
|
30
|
+
- `usePopupMenu()`
|
|
31
|
+
- `anchor`
|
|
32
|
+
- `open`
|
|
33
|
+
- `setOpen`
|
|
34
|
+
- `close()`
|
|
35
|
+
- `openAtPoint(x, y)`
|
|
36
|
+
- `openAtElement(element)`
|
|
37
|
+
- `openFromClick(event)`
|
|
38
|
+
- `openFromContextMenu(event)`
|
|
39
|
+
|
|
40
|
+
## Notes
|
|
41
|
+
|
|
42
|
+
- Popup menus render through a portal and are not clipped by local overflow containers.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ProgressBar
|
|
2
|
+
|
|
3
|
+
`ProgressBar` renders a DOS-style determinate or indeterminate progress indicator.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<ProgressBar
|
|
9
|
+
label="Surface scan"
|
|
10
|
+
value={42}
|
|
11
|
+
max={100}
|
|
12
|
+
hint="Scanning allocation map"
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Key Props
|
|
17
|
+
|
|
18
|
+
- `value?: number`
|
|
19
|
+
- `min?: number`
|
|
20
|
+
- `max?: number`
|
|
21
|
+
- `indeterminate?: boolean`
|
|
22
|
+
- `showValue?: boolean`
|
|
23
|
+
- `label?: string`
|
|
24
|
+
- `hint?: string`
|
|
25
|
+
- `trackBackground?: CSSProperties["background"]`
|
|
26
|
+
- `valueRenderer?: (percent, value, min, max) => ReactNode`
|
|
27
|
+
|
|
28
|
+
## Notes
|
|
29
|
+
|
|
30
|
+
- `value` is clamped to the `min..max` range.
|
|
31
|
+
- `showValue` controls the right-side textual progress output.
|
|
32
|
+
- `indeterminate` ignores `aria-valuenow` and animates the fill instead.
|
|
33
|
+
- `trackBackground` lets the host override the progress track background while keeping the fill white.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# PropertyGrid
|
|
2
|
+
|
|
3
|
+
`PropertyGrid` is the hierarchical inspector surface for labeled settings, expandable groups, and embedded editors.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<PropertyGrid
|
|
9
|
+
entries={[
|
|
10
|
+
{ id: "general", type: "section", title: "&General" },
|
|
11
|
+
{
|
|
12
|
+
id: "target",
|
|
13
|
+
label: "&Target",
|
|
14
|
+
content: <TextField label="Target" defaultValue="C:\\SYSTEM" />
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "rect",
|
|
18
|
+
type: "group",
|
|
19
|
+
label: "&Box",
|
|
20
|
+
summary: <>Rect(0,0,10,20)</>,
|
|
21
|
+
children: [
|
|
22
|
+
{
|
|
23
|
+
id: "top",
|
|
24
|
+
label: "&Top",
|
|
25
|
+
content: <SpinBox label="Top" value={0} />
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
]}
|
|
30
|
+
/>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Key Props
|
|
34
|
+
|
|
35
|
+
- `entries: PropertyGridEntry[]`
|
|
36
|
+
- `labelWidth?: string`
|
|
37
|
+
- `fill?: boolean`
|
|
38
|
+
- `bordered?: boolean`
|
|
39
|
+
- `activeId?: string`
|
|
40
|
+
- `defaultActiveId?: string`
|
|
41
|
+
- `onActiveIdChange?: (activeId) => void`
|
|
42
|
+
- `expandedIds?: string[]`
|
|
43
|
+
- `defaultExpandedIds?: string[]`
|
|
44
|
+
- `onExpandedIdsChange?: (expandedIds) => void`
|
|
45
|
+
|
|
46
|
+
## Notes
|
|
47
|
+
|
|
48
|
+
- Use section rows to break long inspectors into logical blocks.
|
|
49
|
+
- Group rows provide expandable hierarchy with a summary cell on the right.
|
|
50
|
+
- Nested groups can be arbitrarily deep. A common pattern is a collapsed summary row like `Rect(0,0,10,20)` that expands into leaf editors such as `Top`, `Left`, `Width`, and `Height`.
|
|
51
|
+
- Item rows accept arbitrary React content in the value column.
|
|
52
|
+
- Clicking an item key activates the editor in the value column. For checkbox-like editors, the key click also toggles the value.
|
|
53
|
+
- Keyboard navigation now follows inspector-style semantics:
|
|
54
|
+
- `Up` / `Down` move between rows
|
|
55
|
+
- `Home` / `End` jump to the first or last interactive row
|
|
56
|
+
- `Right` expands a group or activates the current item editor
|
|
57
|
+
- `Left` collapses the current group or moves focus to the parent group
|
|
58
|
+
- `Enter` / `Space` toggle a group or activate the current item editor
|
|
59
|
+
- Item keys use the same white-surface / inverse-text treatment as the rest of the library's menu-like key slots.
|
|
60
|
+
- Group keys use the inactive-button surface, so expandable branches are visually distinct from leaf properties.
|
|
61
|
+
- Borders are optional through `bordered`; the default presentation is borderless.
|
|
62
|
+
- Embedded ReactNU field controls have their internal top labels visually suppressed inside the property cell, because the grid already owns the left label column.
|
|
63
|
+
- `PropertyGrid` is already suitable as a practical inspector surface, but it is still not a full schema engine. The next logical expansion would be deeper in-place editing semantics and richer nested property schemas.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# RadioGroup
|
|
2
|
+
|
|
3
|
+
`RadioGroup` renders a set of DOS-style radio options with one active value.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<RadioGroup
|
|
9
|
+
label="&Boot mode"
|
|
10
|
+
hint="Choose the recovery startup profile."
|
|
11
|
+
options={[
|
|
12
|
+
{ label: "&Safe mode", value: "safe" },
|
|
13
|
+
{ label: "&Network mode", value: "network" },
|
|
14
|
+
{ label: "&Full diagnostics", value: "full" }
|
|
15
|
+
]}
|
|
16
|
+
value={bootMode}
|
|
17
|
+
onValueChange={setBootMode}
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Key Props
|
|
22
|
+
|
|
23
|
+
- `label?: string`
|
|
24
|
+
- `hint?: string`
|
|
25
|
+
- `name?: string`
|
|
26
|
+
- `options: Array<{ label, value, disabled?, hint? }>`
|
|
27
|
+
- `value?: string`
|
|
28
|
+
- `defaultValue?: string`
|
|
29
|
+
- `onValueChange?: (value) => void`
|
|
30
|
+
- `slotClassNames?` / `slotStyles?` for group-level customization
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- Supports controlled and uncontrolled usage.
|
|
35
|
+
- `RadioButton` is also available as a lower-level building block.
|
|
36
|
+
- Mnemonic highlighting follows the `&` marker convention.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# ReportCell
|
|
2
|
+
|
|
3
|
+
`ReportCell` is a lightweight helper for report-style table cells.
|
|
4
|
+
|
|
5
|
+
It is intentionally optional. Host code can return plain text or any custom
|
|
6
|
+
`ReactNode`, but `ReportCell` keeps alignment and tone consistent for
|
|
7
|
+
`ListView` and `TreeListView`-style columns.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<ReportCell align="end" tone="muted">
|
|
13
|
+
44 KB
|
|
14
|
+
</ReportCell>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
- `align?: "start" | "center" | "end"`
|
|
20
|
+
- `tone?: "default" | "muted" | "accent" | "danger" | "success"`
|
|
21
|
+
|
|
22
|
+
## Notes
|
|
23
|
+
|
|
24
|
+
- `ReportCell` does not own column sizing.
|
|
25
|
+
- It is a content helper, not a container control.
|
|
26
|
+
- Use it when host-provided cells should still follow the library's report
|
|
27
|
+
alignment and color language.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Slot Customization
|
|
2
|
+
|
|
3
|
+
ReactNU components are moving to a shared internal customization contract:
|
|
4
|
+
|
|
5
|
+
- `slotStyles`
|
|
6
|
+
- `slotClassNames`
|
|
7
|
+
|
|
8
|
+
This is the preferred way to override internal surfaces without rewriting a component.
|
|
9
|
+
|
|
10
|
+
## Shape
|
|
11
|
+
|
|
12
|
+
Typical usage:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
<Frame
|
|
16
|
+
slotStyles={{
|
|
17
|
+
title: { background: "black", color: "yellow" },
|
|
18
|
+
body: { background: "#6262e3" }
|
|
19
|
+
}}
|
|
20
|
+
slotClassNames={{
|
|
21
|
+
root: "my-frame",
|
|
22
|
+
title: "my-frame-title"
|
|
23
|
+
}}
|
|
24
|
+
title="Target Controls"
|
|
25
|
+
/>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Rules
|
|
29
|
+
|
|
30
|
+
- `className` and `style` still target the component root.
|
|
31
|
+
- `slotClassNames` and `slotStyles` target internal named slots.
|
|
32
|
+
- Slot names should be literal and structural:
|
|
33
|
+
- `root`
|
|
34
|
+
- `label`
|
|
35
|
+
- `body`
|
|
36
|
+
- `title`
|
|
37
|
+
- `input`
|
|
38
|
+
- `hint`
|
|
39
|
+
- `popup`
|
|
40
|
+
- `listbox`
|
|
41
|
+
- Component-specific legacy props such as `titleStyle` or `contentStyle` may still exist for compatibility, but new work should prefer slot-based customization.
|
|
42
|
+
|
|
43
|
+
## Internal Primitive Rule
|
|
44
|
+
|
|
45
|
+
Slot customization does not replace shared internal primitives.
|
|
46
|
+
|
|
47
|
+
If two controls share the same internal visual part, prefer:
|
|
48
|
+
|
|
49
|
+
- one shared internal primitive
|
|
50
|
+
- plus slot customization on top of that primitive
|
|
51
|
+
|
|
52
|
+
instead of:
|
|
53
|
+
|
|
54
|
+
- separate duplicated markup
|
|
55
|
+
- separate duplicated LESS
|
|
56
|
+
- followed by two independent slot APIs
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
|
|
60
|
+
- `Dropdown` and `ComboBox` share the internal `ControlOpener` primitive
|
|
61
|
+
- each control still exposes its own slot names around that primitive
|
|
62
|
+
|
|
63
|
+
## Current Direction
|
|
64
|
+
|
|
65
|
+
This contract is now the standard for new and updated controls.
|
|
66
|
+
|
|
67
|
+
The first wave already covers the main surface and control layer:
|
|
68
|
+
|
|
69
|
+
- `Frame`
|
|
70
|
+
- `Panel`
|
|
71
|
+
- `Button`
|
|
72
|
+
- `PageControl`
|
|
73
|
+
- `ToolBar`
|
|
74
|
+
- `ProgressBar`
|
|
75
|
+
- `TickBar`
|
|
76
|
+
- `TextField`
|
|
77
|
+
- `SpinBox`
|
|
78
|
+
- `CheckBox`
|
|
79
|
+
|
|
80
|
+
Additional controls should follow the same pattern as they are touched, instead of inventing one-off prop names.
|
|
81
|
+
|
|
82
|
+
When extending a component:
|
|
83
|
+
|
|
84
|
+
- add slots only for meaningful structural surfaces
|
|
85
|
+
- do not expose every nested implementation detail as a slot unless it is a real customization surface
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Storybook
|
|
2
|
+
|
|
3
|
+
ReactNU now ships with a dedicated Storybook layer for component coverage, visual regression review, and API exploration.
|
|
4
|
+
|
|
5
|
+
## Scripts
|
|
6
|
+
|
|
7
|
+
- `npm run storybook`
|
|
8
|
+
starts Storybook in dev mode
|
|
9
|
+
- `npm run build-storybook`
|
|
10
|
+
produces a static build in `storybook-static/`
|
|
11
|
+
|
|
12
|
+
## Global Toolbars
|
|
13
|
+
|
|
14
|
+
The Storybook preview exposes provider-level globals for:
|
|
15
|
+
|
|
16
|
+
- theme
|
|
17
|
+
- font family
|
|
18
|
+
- font size
|
|
19
|
+
- desktop pattern mode
|
|
20
|
+
|
|
21
|
+
These are wired through `NuThemeProvider`, so stories can be checked under the same typography and desktop-surface conditions as the sandbox.
|
|
22
|
+
|
|
23
|
+
## Host Composition Rules
|
|
24
|
+
|
|
25
|
+
Storybook uses more than one kind of host on purpose.
|
|
26
|
+
|
|
27
|
+
Use a bounded surface with direct components when you only need:
|
|
28
|
+
|
|
29
|
+
- isolated control review
|
|
30
|
+
- static window chrome
|
|
31
|
+
- local layout examples
|
|
32
|
+
|
|
33
|
+
Use `NuWindowProvider` in a bounded container when you need:
|
|
34
|
+
|
|
35
|
+
- managed windows
|
|
36
|
+
- helper dialogs
|
|
37
|
+
- modal layering
|
|
38
|
+
- `useNuWindowManager()` flows
|
|
39
|
+
|
|
40
|
+
Use full `NuDesktop` only when the story is explicitly about:
|
|
41
|
+
|
|
42
|
+
- desktop shell composition
|
|
43
|
+
- menu/app-bar integration
|
|
44
|
+
- fixed desktop semantics
|
|
45
|
+
|
|
46
|
+
This distinction matters because `NuDesktop` is intentionally fullscreen/fixed by nature, while many Storybook stories need a bounded preview host.
|
|
47
|
+
|
|
48
|
+
## Coverage Goals
|
|
49
|
+
|
|
50
|
+
The current Storybook covers the main package surfaces:
|
|
51
|
+
|
|
52
|
+
- theming and slot customization
|
|
53
|
+
- buttons and event feedback
|
|
54
|
+
- input controls
|
|
55
|
+
- selectors and async lookup
|
|
56
|
+
- toolbar and page control navigation
|
|
57
|
+
- list and tree controls
|
|
58
|
+
- property inspector layout
|
|
59
|
+
- surface/layout primitives
|
|
60
|
+
- direct desktop and window chrome
|
|
61
|
+
|
|
62
|
+
## Why Storybook Exists Alongside Sandbox
|
|
63
|
+
|
|
64
|
+
The sandbox remains the free-form integration lab.
|
|
65
|
+
|
|
66
|
+
Storybook serves a different role:
|
|
67
|
+
|
|
68
|
+
- isolated component review
|
|
69
|
+
- prop and event exploration
|
|
70
|
+
- theme/font regression checks
|
|
71
|
+
- docs-friendly usage examples
|
|
72
|
+
- easier review of slot-level customization
|
|
73
|
+
|
|
74
|
+
## Current Scope
|
|
75
|
+
|
|
76
|
+
Storybook is intended to show:
|
|
77
|
+
|
|
78
|
+
- how a control behaves on its own
|
|
79
|
+
- how it behaves under different theme and typography settings
|
|
80
|
+
- how slot overrides affect internal surfaces
|
|
81
|
+
|
|
82
|
+
The sandbox still remains the better place for:
|
|
83
|
+
|
|
84
|
+
- long-lived desktop workflows
|
|
85
|
+
- managed window orchestration
|
|
86
|
+
- complex multi-control interaction sequences
|
|
87
|
+
|
|
88
|
+
## Popup Story Guidance
|
|
89
|
+
|
|
90
|
+
Popup-like controls in Storybook should follow the same contract as the library runtime:
|
|
91
|
+
|
|
92
|
+
- popup rendered into `document.body`
|
|
93
|
+
- popup themed from the nearest `.nu-theme-root`
|
|
94
|
+
- geometry measured from the visible anchor
|
|
95
|
+
|
|
96
|
+
If a popup appears correct in sandbox but drifts in Storybook, treat that first as a host-composition issue rather than immediately changing the control API.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# SearchBox
|
|
2
|
+
|
|
3
|
+
`SearchBox` is the async lookup control for remote or database-backed search.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<SearchBox
|
|
9
|
+
dataProvider={(query) => fetchStations(query)}
|
|
10
|
+
getItemId={(item) => item.id}
|
|
11
|
+
getItemText={(item) => item.name}
|
|
12
|
+
label="Station search"
|
|
13
|
+
onItemSelect={(item) => setSelectedStation(item)}
|
|
14
|
+
/>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Key Props
|
|
18
|
+
|
|
19
|
+
- `dataProvider: (query) => Promise<T[]>`
|
|
20
|
+
- `getItemId: (item, index) => string`
|
|
21
|
+
- `getItemText: (item) => string`
|
|
22
|
+
- `getItemDetails?: (item) => ReactNode`
|
|
23
|
+
- `getItemDisabled?: (item) => boolean`
|
|
24
|
+
- `label: string`
|
|
25
|
+
- `hint?: string`
|
|
26
|
+
- `query?: string`
|
|
27
|
+
- `defaultQuery?: string`
|
|
28
|
+
- `onQueryChange?: (query) => void`
|
|
29
|
+
- `onItemSelect?: (item) => void`
|
|
30
|
+
- `debounceMs?: number`
|
|
31
|
+
- `minQueryLength?: number`
|
|
32
|
+
- `loadingText?: string`
|
|
33
|
+
- `emptyText?: string`
|
|
34
|
+
- `errorText?: string`
|
|
35
|
+
|
|
36
|
+
## Notes
|
|
37
|
+
|
|
38
|
+
- `SearchBox` is intentionally separate from `ComboBox`.
|
|
39
|
+
- Use `ComboBox` for local editable lists.
|
|
40
|
+
- Use `SearchBox` when results come from an async provider such as a database or remote service.
|
|
41
|
+
- The input remains the focus owner; `Enter` commits the first result when available.
|