@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,85 @@
|
|
|
1
|
+
# Dialog Helpers
|
|
2
|
+
|
|
3
|
+
`useNuWindowManager()` includes two async helper dialogs built on top of the managed window layer:
|
|
4
|
+
|
|
5
|
+
- `showMessageBox(options)`
|
|
6
|
+
- `showInputBox(options)`
|
|
7
|
+
|
|
8
|
+
Both helpers open managed dialogs and resolve through a `Promise`.
|
|
9
|
+
|
|
10
|
+
## MessageBox
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
const windowManager = useNuWindowManager();
|
|
14
|
+
|
|
15
|
+
const result = await windowManager.showMessageBox({
|
|
16
|
+
title: "Diagnostics",
|
|
17
|
+
message: "Continue with the maintenance pass?",
|
|
18
|
+
kind: "info",
|
|
19
|
+
preset: "yes-no-cancel"
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Supported options:
|
|
24
|
+
|
|
25
|
+
- `title?: string`
|
|
26
|
+
- `message: ReactNode`
|
|
27
|
+
- `kind?: "normal" | "info" | "error"`
|
|
28
|
+
- `preset?: "ok" | "ok-cancel" | "yes-no" | "yes-no-cancel"`
|
|
29
|
+
- `yes?: boolean`
|
|
30
|
+
- `no?: boolean`
|
|
31
|
+
- `cancel?: boolean`
|
|
32
|
+
- `ok?: boolean`
|
|
33
|
+
- `yesLabel?: string`
|
|
34
|
+
- `noLabel?: string`
|
|
35
|
+
- `cancelLabel?: string`
|
|
36
|
+
- `okLabel?: string`
|
|
37
|
+
- `appModal?: boolean`
|
|
38
|
+
- `domain?: string`
|
|
39
|
+
- `style?: CSSProperties`
|
|
40
|
+
|
|
41
|
+
Result type:
|
|
42
|
+
|
|
43
|
+
- `"ok" | "yes" | "no" | "cancel"`
|
|
44
|
+
|
|
45
|
+
Notes:
|
|
46
|
+
|
|
47
|
+
- If no buttons are specified, `MessageBox` falls back to `OK`.
|
|
48
|
+
- `preset` provides the starting button set, but explicit button flags still override it.
|
|
49
|
+
- Button labels can be overridden without changing the result values.
|
|
50
|
+
- If the dialog is closed through the title bar, the helper resolves to the best dismiss result for the configured buttons.
|
|
51
|
+
|
|
52
|
+
## InputBox
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
const windowManager = useNuWindowManager();
|
|
56
|
+
|
|
57
|
+
const value = await windowManager.showInputBox({
|
|
58
|
+
title: "Archive Report",
|
|
59
|
+
label: "Target path",
|
|
60
|
+
defaultValue: "C:\\LOGS\\SURFACE.MAP",
|
|
61
|
+
hint: "Type the report path and confirm."
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Supported options:
|
|
66
|
+
|
|
67
|
+
- `title?: string`
|
|
68
|
+
- `label: string`
|
|
69
|
+
- `defaultValue?: string`
|
|
70
|
+
- `placeholder?: string`
|
|
71
|
+
- `hint?: string`
|
|
72
|
+
- `okLabel?: string`
|
|
73
|
+
- `cancelLabel?: string`
|
|
74
|
+
- `appModal?: boolean`
|
|
75
|
+
- `domain?: string`
|
|
76
|
+
- `style?: CSSProperties`
|
|
77
|
+
|
|
78
|
+
Result type:
|
|
79
|
+
|
|
80
|
+
- `string | null`
|
|
81
|
+
|
|
82
|
+
Notes:
|
|
83
|
+
|
|
84
|
+
- `null` means the dialog was cancelled or closed.
|
|
85
|
+
- `InputBox` uses the same managed dialog layer as all other windowed UI.
|
package/docs/Dropdown.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Dropdown
|
|
2
|
+
|
|
3
|
+
`Dropdown` is a select-like control built from a compact DOS-style field and a popup `ListBox`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Dropdown
|
|
9
|
+
label="Run profile"
|
|
10
|
+
value={profileId}
|
|
11
|
+
onValueChange={(nextValue) => setProfileId(nextValue)}
|
|
12
|
+
data={[
|
|
13
|
+
{
|
|
14
|
+
category: null,
|
|
15
|
+
items: [
|
|
16
|
+
{ id: "default", name: { text: "DEFAULT.NU" } },
|
|
17
|
+
{ id: "repair", name: { text: "REPAIR.NU" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]}
|
|
21
|
+
/>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Key Props
|
|
25
|
+
|
|
26
|
+
- `label: string`
|
|
27
|
+
- `data: ListBoxGroup[]`
|
|
28
|
+
- `value?: string`
|
|
29
|
+
- `defaultValue?: string`
|
|
30
|
+
- `onValueChange?: (value, item, group) => void`
|
|
31
|
+
- `placeholder?: string`
|
|
32
|
+
- `hint?: string`
|
|
33
|
+
- `disabled?: boolean`
|
|
34
|
+
- `slotClassNames?` / `slotStyles?` for internal surface customization
|
|
35
|
+
|
|
36
|
+
## Keyboard
|
|
37
|
+
|
|
38
|
+
- `ArrowUp` / `ArrowDown` change the value while closed
|
|
39
|
+
- `Enter` / `Space` open the list
|
|
40
|
+
|
|
41
|
+
## Notes
|
|
42
|
+
|
|
43
|
+
- The popup width is clamped to the width of the closed control.
|
|
44
|
+
- This component is intentionally select-like; searchable combo-box behavior should live in a separate component.
|
package/docs/Frame.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Frame
|
|
2
|
+
|
|
3
|
+
`Frame` is a lightweight container with a simple border and optional title.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Frame title="Commands">
|
|
9
|
+
<ListBox data={groups} />
|
|
10
|
+
</Frame>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Key Props
|
|
14
|
+
|
|
15
|
+
- `fill?: boolean`
|
|
16
|
+
- `title?: string`
|
|
17
|
+
- `titleStart?: ReactNode`
|
|
18
|
+
- `titleContent?: ReactNode`
|
|
19
|
+
- `titleEnd?: ReactNode`
|
|
20
|
+
- `titleProps?: { background?: string; color?: string; borderColor?: string }`
|
|
21
|
+
- `titleStyle?: CSSProperties`
|
|
22
|
+
- `contentStyle?: CSSProperties`
|
|
23
|
+
- `variant?: "outline" | "title-bar"`
|
|
24
|
+
- `titleAlign?: "start" | "center" | "end"`
|
|
25
|
+
- `titleBold?: boolean`
|
|
26
|
+
- `children`
|
|
27
|
+
|
|
28
|
+
## Notes
|
|
29
|
+
|
|
30
|
+
- `fill` defaults to `true`, so `Frame` stretches naturally inside flex/grid parents and also fills block-style hosts such as window bodies.
|
|
31
|
+
- `outline` keeps the title floating over the top border.
|
|
32
|
+
- `title-bar` renders a solid title strip across the full width.
|
|
33
|
+
- `titleProps` controls frame chrome around the title area: title background, title text color, and frame border color.
|
|
34
|
+
- `titleStyle` and `contentStyle` remain available for additional local overrides without creating a separate Frame variant.
|
|
35
|
+
- `title` remains a shorthand for simple text titles.
|
|
36
|
+
- `titleContent` lets you replace the center title payload with custom markup.
|
|
37
|
+
- `titleStart` and `titleEnd` let you place custom controls or indicators on the left and right of the title shell.
|
|
38
|
+
- if only `titleStart` or `titleEnd` is provided, `Frame` renders just that fragment without a default text title.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide shows the recommended host setup for a ReactNU application.
|
|
4
|
+
|
|
5
|
+
## Recommended Shell
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import {
|
|
9
|
+
AppBarHost,
|
|
10
|
+
AppBarItem,
|
|
11
|
+
NuDesktop,
|
|
12
|
+
NuThemeProvider,
|
|
13
|
+
NuView,
|
|
14
|
+
WindowBar,
|
|
15
|
+
useNuWindowManager
|
|
16
|
+
} from "@deadragdoll/reactnu";
|
|
17
|
+
|
|
18
|
+
function ShellAppBar() {
|
|
19
|
+
const windowManager = useNuWindowManager();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<AppBarHost>
|
|
23
|
+
<WindowBar
|
|
24
|
+
items={windowManager.windows.map((windowEntry) => ({
|
|
25
|
+
active: windowEntry.active,
|
|
26
|
+
domain: windowEntry.domain,
|
|
27
|
+
id: windowEntry.id,
|
|
28
|
+
minimized: windowEntry.minimized,
|
|
29
|
+
title: windowEntry.title
|
|
30
|
+
}))}
|
|
31
|
+
onActivateWindow={windowManager.activateWindow}
|
|
32
|
+
/>
|
|
33
|
+
<AppBarItem alignment="end">12:40</AppBarItem>
|
|
34
|
+
</AppBarHost>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function App() {
|
|
39
|
+
return (
|
|
40
|
+
<NuThemeProvider>
|
|
41
|
+
<NuDesktop appBar={<ShellAppBar />}>
|
|
42
|
+
<NuView padding="md">Workspace content</NuView>
|
|
43
|
+
</NuDesktop>
|
|
44
|
+
</NuThemeProvider>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Recommended Order
|
|
50
|
+
|
|
51
|
+
1. `NuThemeProvider`
|
|
52
|
+
2. `NuDesktop`
|
|
53
|
+
3. host-driven `appBar`
|
|
54
|
+
4. workspace content
|
|
55
|
+
5. open windows through `useNuWindowManager()`
|
|
56
|
+
|
|
57
|
+
## Opening A Window
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { Button, useNuWindowManager } from "@deadragdoll/reactnu";
|
|
61
|
+
|
|
62
|
+
function Launcher() {
|
|
63
|
+
const windowManager = useNuWindowManager();
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Button
|
|
67
|
+
onClick={() =>
|
|
68
|
+
windowManager.openWindow({
|
|
69
|
+
title: "Inspector",
|
|
70
|
+
content: <div>Window content</div>
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
&Open inspector
|
|
75
|
+
</Button>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Opening A Dialog
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
windowManager.openDialog({
|
|
84
|
+
title: "Confirm",
|
|
85
|
+
content: ({ close }) => <Button onClick={close}>&Close</Button>
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Recommended Folder Shape
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
src/
|
|
93
|
+
app/
|
|
94
|
+
App.tsx
|
|
95
|
+
DesktopAppBar.tsx
|
|
96
|
+
DesktopMenu.tsx
|
|
97
|
+
windows/
|
|
98
|
+
InspectorWindow.tsx
|
|
99
|
+
ReportWindow.tsx
|
|
100
|
+
dialogs/
|
|
101
|
+
ConfirmDialog.tsx
|
|
102
|
+
views/
|
|
103
|
+
DashboardView.tsx
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Notes
|
|
107
|
+
|
|
108
|
+
- `NuDesktop` already creates the app host and window manager layers.
|
|
109
|
+
- `WindowBar` is host-owned. It is not injected automatically.
|
|
110
|
+
- Use `NuView` whenever a pane or cell needs to own scrolling explicitly.
|
package/docs/Glyph.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Glyph
|
|
2
|
+
|
|
3
|
+
`NuGlyph` is the reusable icon primitive for small UI symbols.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<NuGlyph name="window-close" />
|
|
9
|
+
<NuGlyph name="dropdown-arrow" />
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Key Props
|
|
13
|
+
|
|
14
|
+
- `name: NuGlyphName`
|
|
15
|
+
- standard `span` props such as `className`
|
|
16
|
+
|
|
17
|
+
## Current Glyph Set
|
|
18
|
+
|
|
19
|
+
- `check-fill`
|
|
20
|
+
- `dropdown-arrow`
|
|
21
|
+
- `window-close`
|
|
22
|
+
- `window-maximize`
|
|
23
|
+
- `window-minimize`
|
|
24
|
+
- `window-resize`
|
|
25
|
+
- `window-restore`
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- New control-specific symbols should be added here instead of being redrawn ad hoc in component styles.
|
package/docs/Info.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Info
|
|
2
|
+
|
|
3
|
+
`Info` is a lightweight fill-container for informational copy. It does not add window chrome or borders; it pairs with `InfoAccent` for inline highlighted fragments.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Info>
|
|
9
|
+
Hello, you must <InfoAccent>Accept</InfoAccent> the rules before continuing.
|
|
10
|
+
</Info>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Custom accent:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<Info accentColor="#ffffff">
|
|
17
|
+
Current profile: <InfoAccent>DEFAULT.NU</InfoAccent>
|
|
18
|
+
</Info>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Formatting flags:
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
<Info>
|
|
25
|
+
For bar
|
|
26
|
+
<InfoAccent bold italic underline upper>
|
|
27
|
+
baz
|
|
28
|
+
</InfoAccent>
|
|
29
|
+
HelloWorld
|
|
30
|
+
</Info>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Key Props
|
|
34
|
+
|
|
35
|
+
- `fill?: boolean`
|
|
36
|
+
- `accentColor?: CSSProperties["color"]`
|
|
37
|
+
- standard `div` props such as `className`, `style`, `children`
|
|
38
|
+
|
|
39
|
+
`InfoAccent` props:
|
|
40
|
+
|
|
41
|
+
- `bold?: boolean`
|
|
42
|
+
- `italic?: boolean`
|
|
43
|
+
- `underline?: boolean`
|
|
44
|
+
- `upper?: boolean`
|
|
45
|
+
- standard `span` props such as `className`, `style`, `children`
|
|
46
|
+
|
|
47
|
+
## Notes
|
|
48
|
+
|
|
49
|
+
- `fill` defaults to `true`, so `Info` stretches with its parent container.
|
|
50
|
+
- `InfoAccent` is the intended inline emphasis API for `Info`.
|
|
51
|
+
- `accentColor` is inherited by nested `InfoAccent` fragments.
|
package/docs/ListBox.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# ListBox
|
|
2
|
+
|
|
3
|
+
`ListBox` is the main scrollable selection surface for grouped or flat item collections.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<ListBox
|
|
9
|
+
data={groups}
|
|
10
|
+
selectedId={selectedId}
|
|
11
|
+
onItemSelect={(item) => setSelectedId(item.id ?? "")}
|
|
12
|
+
/>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Key Props
|
|
16
|
+
|
|
17
|
+
- `data: ListBoxGroup[]`
|
|
18
|
+
- `selectedId?: string`
|
|
19
|
+
- `onItemSelect?: (item, group) => void`
|
|
20
|
+
- `checkedIds?: string[]`
|
|
21
|
+
- `onItemCheckChange?: (item, group, checked) => void`
|
|
22
|
+
- `onItemDoubleClick?: (item, group) => void`
|
|
23
|
+
- `rightCheckBox?: boolean`
|
|
24
|
+
- `emptyText?: string`
|
|
25
|
+
|
|
26
|
+
## Keyboard
|
|
27
|
+
|
|
28
|
+
- `ArrowUp` / `ArrowDown`
|
|
29
|
+
- `Home` / `End`
|
|
30
|
+
- `Enter`
|
|
31
|
+
- `Space` for check toggling
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
- The same data format supports both grouped and flat lists by using `category: null`.
|
package/docs/ListView.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# ListView
|
|
2
|
+
|
|
3
|
+
`ListView` renders a report-style list with columns, row selection, optional checkboxes, and per-column custom cell renderers.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
type Row = ListViewRowBase & {
|
|
9
|
+
name: string;
|
|
10
|
+
size: string;
|
|
11
|
+
type: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const columns: ListViewColumn<Row>[] = [
|
|
15
|
+
{ id: "name", title: "&Name", field: "name", width: "18ch" },
|
|
16
|
+
{ id: "type", title: "&Type", field: "type", width: "10ch" },
|
|
17
|
+
{ id: "size", title: "&Size", field: "size", align: "end", width: "8ch" }
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
<ListView
|
|
21
|
+
columns={columns}
|
|
22
|
+
data={rows}
|
|
23
|
+
activeRowId={activeRowId}
|
|
24
|
+
onActiveRowChange={(row) => setActiveRowId(row.id)}
|
|
25
|
+
selectedId={selectedId}
|
|
26
|
+
showCheckBox
|
|
27
|
+
checkedIds={checkedIds}
|
|
28
|
+
onRowSelect={(row) => setSelectedId(row.id)}
|
|
29
|
+
onRowCheckChange={(row, checked) => {}}
|
|
30
|
+
/>;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Key Props
|
|
34
|
+
|
|
35
|
+
- `columns`
|
|
36
|
+
- `data`
|
|
37
|
+
- `activeRowId`
|
|
38
|
+
- `defaultActiveRowId`
|
|
39
|
+
- `onActiveRowChange`
|
|
40
|
+
- `selectedId`
|
|
41
|
+
- `onRowSelect`
|
|
42
|
+
- `onRowDoubleClick`
|
|
43
|
+
- `showCheckBox`
|
|
44
|
+
- `checkedIds`
|
|
45
|
+
- `onRowCheckChange`
|
|
46
|
+
- `uncheckedShape`
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- Keyboard navigation follows the same pattern as other list-like controls.
|
|
51
|
+
- Column titles support `&` mnemonic markup.
|
|
52
|
+
- A column can use `field` for simple value rendering or `renderCell` for custom content.
|
|
53
|
+
|
|
54
|
+
## Imperative Handle
|
|
55
|
+
|
|
56
|
+
`ListView` also supports `ref` with:
|
|
57
|
+
|
|
58
|
+
- `focus()`
|
|
59
|
+
- `scrollToRow(rowId)`
|
|
60
|
+
- `activateRow(rowId)`
|
|
61
|
+
- `toggleRowCheck(rowId)`
|
|
62
|
+
- `getActiveRowId()`
|
package/docs/MainMenu.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MainMenu
|
|
2
|
+
|
|
3
|
+
`MainMenu` is the classic top application menu bar with nested submenus.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<MainMenu items={menuItems} />
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Props
|
|
12
|
+
|
|
13
|
+
- `items: MainMenuNode[]`
|
|
14
|
+
- `onItemSelect?: (item) => void`
|
|
15
|
+
|
|
16
|
+
## Menu Model
|
|
17
|
+
|
|
18
|
+
- `MainMenuItem`
|
|
19
|
+
- `id`
|
|
20
|
+
- `text`
|
|
21
|
+
- `hotkey?`
|
|
22
|
+
- `shortcut?`
|
|
23
|
+
- `checked?`
|
|
24
|
+
- `disabled?`
|
|
25
|
+
- `hidden?`
|
|
26
|
+
- `items?`
|
|
27
|
+
- `onSelect?`
|
|
28
|
+
- `MainMenuDivider`
|
|
29
|
+
- `id`
|
|
30
|
+
- `type: "divider"`
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- Top-level dropdowns open below their root items.
|
|
35
|
+
- Nested submenus open to the right.
|
|
36
|
+
- Active and hovered items use the same black selection pattern used elsewhere in the library.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# MaskedField
|
|
2
|
+
|
|
3
|
+
`MaskedField` is a bracketed single-line input with a readable mask grammar and built-in invalid feedback.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<MaskedField
|
|
9
|
+
label="Dial prefix"
|
|
10
|
+
mask="+(D)"
|
|
11
|
+
defaultValue="7"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<MaskedField
|
|
15
|
+
label="Recovery code"
|
|
16
|
+
mask="(D3-D2-D2)"
|
|
17
|
+
defaultValue="1234567"
|
|
18
|
+
hint="Fixed literals stay inline with the mask."
|
|
19
|
+
/>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Key Props
|
|
23
|
+
|
|
24
|
+
- `label: string`
|
|
25
|
+
- `mask: string`
|
|
26
|
+
- `hint?: string`
|
|
27
|
+
- `debounceMs?: number`
|
|
28
|
+
- `onDebouncedChange?: (value) => void`
|
|
29
|
+
- `slotClassNames?` / `slotStyles?` for internal surface customization
|
|
30
|
+
- standard `input` props such as `value`, `defaultValue`, `onChange`, `disabled`
|
|
31
|
+
|
|
32
|
+
## Immediate And Debounced Flow
|
|
33
|
+
|
|
34
|
+
- `onChange` stays immediate and should drive live state in the host.
|
|
35
|
+
- `onDebouncedChange` is optional and runs after `debounceMs`.
|
|
36
|
+
- If you need to show current validity right away, use your controlled `value` together with `getMaskedFieldState(mask, value)`.
|
|
37
|
+
|
|
38
|
+
## Mask Syntax
|
|
39
|
+
|
|
40
|
+
- `D` = one digit
|
|
41
|
+
- `A` = one letter
|
|
42
|
+
- `D*` = zero or more digits
|
|
43
|
+
- `A*` = zero or more letters
|
|
44
|
+
- `D3` = exactly three digits
|
|
45
|
+
- `A2` = exactly two letters
|
|
46
|
+
- `D3+` = three or more digits
|
|
47
|
+
- `A4+` = four or more letters
|
|
48
|
+
- any other character is treated as a literal
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
|
|
52
|
+
- `+(D)`
|
|
53
|
+
- `(D3)`
|
|
54
|
+
- `(D3-D2-D2)`
|
|
55
|
+
- `A3-D3`
|
|
56
|
+
|
|
57
|
+
## Validation
|
|
58
|
+
|
|
59
|
+
- The field filters incoming text through the mask and auto-inserts literals when enough token content exists.
|
|
60
|
+
- If the current value is incomplete for the mask, the field turns red with yellow text.
|
|
61
|
+
- Empty value stays neutral, so a fresh field does not start in an error state.
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- `MaskedField` is intentionally separate from `TextField`, so plain text inputs stay simple.
|
|
66
|
+
- Unbounded segments such as `D*` and `D3+` are best used as the final variable part of the mask. That keeps formatting deterministic.
|
|
67
|
+
|
|
68
|
+
## Current Scope
|
|
69
|
+
|
|
70
|
+
For the current library stage, `MaskedField` is considered production-ready for:
|
|
71
|
+
|
|
72
|
+
- fixed masks with literals
|
|
73
|
+
- short operational codes
|
|
74
|
+
- dial prefixes
|
|
75
|
+
- serial-like identifiers
|
|
76
|
+
- numeric masks with immediate invalid feedback
|
|
77
|
+
- host flows where live state and debounced state are both useful
|
|
78
|
+
|
|
79
|
+
The current implementation deliberately stops short of advanced editor-like caret management.
|
|
80
|
+
|
|
81
|
+
## Final-State Roadmap
|
|
82
|
+
|
|
83
|
+
If we continue this control toward a fuller final state, the main work areas are:
|
|
84
|
+
|
|
85
|
+
1. Caret and selection behavior.
|
|
86
|
+
File: [packages/ui/src/components/MaskedField/MaskedField.tsx](/home/code4bones/Devs/coding/ReactNU/packages/ui/src/components/MaskedField/MaskedField.tsx)
|
|
87
|
+
This is where cursor preservation, middle-of-string edits, backspace-over-literals, and paste normalization should be finished.
|
|
88
|
+
|
|
89
|
+
2. Mask grammar and formatting engine.
|
|
90
|
+
File: [packages/ui/src/components/MaskedField/textMask.ts](/home/code4bones/Devs/coding/ReactNU/packages/ui/src/components/MaskedField/textMask.ts)
|
|
91
|
+
This is the place to extend token kinds, add richer rules like hex/alnum/upper/lower, or tighten behavior for unbounded segments.
|
|
92
|
+
|
|
93
|
+
3. Public state contract.
|
|
94
|
+
Files:
|
|
95
|
+
[packages/ui/src/components/MaskedField/MaskedField.tsx](/home/code4bones/Devs/coding/ReactNU/packages/ui/src/components/MaskedField/MaskedField.tsx)
|
|
96
|
+
[packages/ui/src/components/MaskedField/index.ts](/home/code4bones/Devs/coding/ReactNU/packages/ui/src/components/MaskedField/index.ts)
|
|
97
|
+
If we need a stronger final API, this is where to add explicit exports such as `MaskedFieldState`, `onValidityChange`, or `onMaskComplete`.
|
|
98
|
+
|
|
99
|
+
4. Visual invalid and pending states.
|
|
100
|
+
File: [packages/ui/src/components/MaskedField/MaskedField.less](/home/code4bones/Devs/coding/ReactNU/packages/ui/src/components/MaskedField/MaskedField.less)
|
|
101
|
+
This is the right place for any future visual split between `pending`, `invalid`, and `complete`, or for adding a dedicated state marker.
|
|
102
|
+
|
|
103
|
+
5. Real usage regression coverage.
|
|
104
|
+
File: [apps/sandbox/src/DemoApp.tsx](/home/code4bones/Devs/coding/ReactNU/apps/sandbox/src/DemoApp.tsx)
|
|
105
|
+
The dedicated `Masked Field` demo window should stay the proving ground for new mask forms, paste flows, and live host-state scenarios.
|
|
106
|
+
|
|
107
|
+
## Recommended Next Improvements
|
|
108
|
+
|
|
109
|
+
These are the best-practice upgrades worth doing later, but not required right now:
|
|
110
|
+
|
|
111
|
+
- preserve caret position during reformatting
|
|
112
|
+
- add `onValidityChange`
|
|
113
|
+
- add `onMaskComplete`
|
|
114
|
+
- export a typed `MaskedFieldState`
|
|
115
|
+
- introduce richer token families only when a real use case appears
|
|
116
|
+
|
|
117
|
+
## Non-Goals For Now
|
|
118
|
+
|
|
119
|
+
These are intentionally out of scope for the current version:
|
|
120
|
+
|
|
121
|
+
- regex-style masks
|
|
122
|
+
- full parser-expression language
|
|
123
|
+
- locale-aware date/number semantics
|
|
124
|
+
- aggressive auto-correction beyond the current readable token model
|
package/docs/Memo.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Memo
|
|
2
|
+
|
|
3
|
+
`Memo` renders an editable multiline text area that fills its parent by default.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Memo
|
|
9
|
+
content={`Operator note:
|
|
10
|
+
Check drive map before running repair.`}
|
|
11
|
+
/>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Key Props
|
|
15
|
+
|
|
16
|
+
- `content?: string`
|
|
17
|
+
- `value?: string`
|
|
18
|
+
- `defaultValue?: string`
|
|
19
|
+
- `onValueChange?: (value: string) => void`
|
|
20
|
+
- `fill?: boolean`
|
|
21
|
+
- `scroll?: "auto" | "x" | "y" | "both" | "hidden"`
|
|
22
|
+
- `background?: CSSProperties["background"]`
|
|
23
|
+
- `focusBackground?: CSSProperties["background"]`
|
|
24
|
+
- `focusTextColor?: CSSProperties["color"]`
|
|
25
|
+
- `textColor?: CSSProperties["color"]`
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- `Memo` uses a native `textarea` and preserves line breaks.
|
|
30
|
+
- By default it uses a sand-colored background and black text.
|
|
31
|
+
- `content` works as convenient initial text for uncontrolled usage.
|
|
32
|
+
- Focus colors are configurable and default to the same surface colors unless overridden.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# NuAppHostProvider
|
|
2
|
+
|
|
3
|
+
`NuAppHostProvider` owns the application-level main menu state.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<NuAppHostProvider>
|
|
9
|
+
<NuDesktop appBar={<AppBar />}>
|
|
10
|
+
<App />
|
|
11
|
+
</NuDesktop>
|
|
12
|
+
</NuAppHostProvider>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Related API
|
|
16
|
+
|
|
17
|
+
Use `useAppHostMenu()` to access:
|
|
18
|
+
|
|
19
|
+
- `mainMenu`
|
|
20
|
+
- `setMainMenu(...)`
|
|
21
|
+
- `setMenuFlags(id, flags)`
|
|
22
|
+
- `setMenuItem(id, patch)`
|
|
23
|
+
- `setSubmenuTree(id, items)`
|
|
24
|
+
|
|
25
|
+
## Notes
|
|
26
|
+
|
|
27
|
+
- `NuDesktop` expects to live inside this provider.
|
|
28
|
+
- The app host menu layer also receives the MDI bridge used by the `mdi.host` menu slot.
|