@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.
Files changed (176) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/appHost/NuAppHostProvider.d.ts +6 -0
  4. package/dist/appHost/appHostContext.d.ts +26 -0
  5. package/dist/components/Button/Button.d.ts +13 -0
  6. package/dist/components/Button/index.d.ts +1 -0
  7. package/dist/components/CheckBox/CheckBox.d.ts +14 -0
  8. package/dist/components/CheckBox/index.d.ts +1 -0
  9. package/dist/components/ComboBox/ComboBox.d.ts +23 -0
  10. package/dist/components/ComboBox/index.d.ts +1 -0
  11. package/dist/components/CommandButton/CommandButton.d.ts +17 -0
  12. package/dist/components/CommandButton/index.d.ts +1 -0
  13. package/dist/components/CrtGlitch/CrtGlitch.d.ts +23 -0
  14. package/dist/components/CrtGlitch/index.d.ts +1 -0
  15. package/dist/components/Dashboard/Dashboard.d.ts +25 -0
  16. package/dist/components/Dashboard/index.d.ts +1 -0
  17. package/dist/components/Desktop/Desktop.d.ts +6 -0
  18. package/dist/components/Desktop/index.d.ts +1 -0
  19. package/dist/components/Dropdown/Dropdown.d.ts +19 -0
  20. package/dist/components/Dropdown/index.d.ts +1 -0
  21. package/dist/components/Frame/Frame.d.ts +24 -0
  22. package/dist/components/Frame/index.d.ts +1 -0
  23. package/dist/components/Glyph/NuGlyph.d.ts +6 -0
  24. package/dist/components/Glyph/index.d.ts +1 -0
  25. package/dist/components/Info/Info.d.ts +13 -0
  26. package/dist/components/Info/index.d.ts +1 -0
  27. package/dist/components/ListBox/ListBox.d.ts +23 -0
  28. package/dist/components/ListBox/index.d.ts +1 -0
  29. package/dist/components/ListBox/internals/ListBoxCategoryView.d.ts +6 -0
  30. package/dist/components/ListBox/internals/ListBoxCheckControl.d.ts +8 -0
  31. package/dist/components/ListBox/internals/ListBoxGroupView.d.ts +17 -0
  32. package/dist/components/ListBox/internals/ListBoxItemView.d.ts +18 -0
  33. package/dist/components/ListBox/internals/helpers.d.ts +5 -0
  34. package/dist/components/ListBox/internals/renderLabel.d.ts +2 -0
  35. package/dist/components/ListBox/internals/types.d.ts +27 -0
  36. package/dist/components/ListView/ListView.d.ts +27 -0
  37. package/dist/components/ListView/index.d.ts +1 -0
  38. package/dist/components/ListView/internals/ListViewCheckControl.d.ts +8 -0
  39. package/dist/components/ListView/internals/ListViewRow.d.ts +18 -0
  40. package/dist/components/ListView/internals/helpers.d.ts +5 -0
  41. package/dist/components/ListView/internals/types.d.ts +17 -0
  42. package/dist/components/MainMenu/MainMenu.d.ts +8 -0
  43. package/dist/components/MainMenu/MainMenu.types.d.ts +23 -0
  44. package/dist/components/MainMenu/index.d.ts +3 -0
  45. package/dist/components/MainMenu/internals/MainMenuList.d.ts +12 -0
  46. package/dist/components/MainMenu/menuState.d.ts +40 -0
  47. package/dist/components/MaskedField/MaskedField.d.ts +13 -0
  48. package/dist/components/MaskedField/index.d.ts +2 -0
  49. package/dist/components/MaskedField/textMask.d.ts +8 -0
  50. package/dist/components/Memo/Memo.d.ts +14 -0
  51. package/dist/components/Memo/index.d.ts +1 -0
  52. package/dist/components/PageControl/PageControl.d.ts +20 -0
  53. package/dist/components/PageControl/index.d.ts +1 -0
  54. package/dist/components/Panel/Panel.d.ts +11 -0
  55. package/dist/components/Panel/index.d.ts +1 -0
  56. package/dist/components/PopupMenu/PopupMenu.d.ts +22 -0
  57. package/dist/components/PopupMenu/index.d.ts +2 -0
  58. package/dist/components/PopupMenu/usePopupMenu.d.ts +12 -0
  59. package/dist/components/ProgressBar/ProgressBar.d.ts +17 -0
  60. package/dist/components/ProgressBar/index.d.ts +1 -0
  61. package/dist/components/PropertyGrid/PropertyGrid.d.ts +38 -0
  62. package/dist/components/PropertyGrid/index.d.ts +1 -0
  63. package/dist/components/RadioGroup/RadioButton.d.ts +9 -0
  64. package/dist/components/RadioGroup/RadioGroup.d.ts +21 -0
  65. package/dist/components/RadioGroup/index.d.ts +2 -0
  66. package/dist/components/ReportCell/ReportCell.d.ts +6 -0
  67. package/dist/components/ReportCell/index.d.ts +1 -0
  68. package/dist/components/SearchBox/SearchBox.d.ts +23 -0
  69. package/dist/components/SearchBox/index.d.ts +1 -0
  70. package/dist/components/SpinBox/SpinBox.d.ts +16 -0
  71. package/dist/components/SpinBox/index.d.ts +1 -0
  72. package/dist/components/Splitter/Splitter.d.ts +15 -0
  73. package/dist/components/Splitter/index.d.ts +1 -0
  74. package/dist/components/Stack/Stack.d.ts +13 -0
  75. package/dist/components/Stack/index.d.ts +1 -0
  76. package/dist/components/TextField/TextField.d.ts +12 -0
  77. package/dist/components/TextField/index.d.ts +1 -0
  78. package/dist/components/TickBar/TickBar.d.ts +22 -0
  79. package/dist/components/TickBar/index.d.ts +1 -0
  80. package/dist/components/ToolBar/ToolBar.d.ts +25 -0
  81. package/dist/components/ToolBar/index.d.ts +1 -0
  82. package/dist/components/TreeListView/TreeListView.d.ts +33 -0
  83. package/dist/components/TreeListView/index.d.ts +1 -0
  84. package/dist/components/TreeListView/internals/TreeListViewRow.d.ts +28 -0
  85. package/dist/components/TreeListView/internals/helpers.d.ts +14 -0
  86. package/dist/components/TreeListView/internals/types.d.ts +32 -0
  87. package/dist/components/TreeView/TreeView.d.ts +26 -0
  88. package/dist/components/TreeView/index.d.ts +1 -0
  89. package/dist/components/TreeView/internals/TreeViewItem.d.ts +21 -0
  90. package/dist/components/TreeView/internals/helpers.d.ts +5 -0
  91. package/dist/components/TreeView/internals/types.d.ts +10 -0
  92. package/dist/components/View/NuView.d.ts +10 -0
  93. package/dist/components/View/index.d.ts +1 -0
  94. package/dist/components/Window/StatusBarItem.d.ts +7 -0
  95. package/dist/components/Window/Window.d.ts +41 -0
  96. package/dist/components/Window/WindowTitleButton.d.ts +17 -0
  97. package/dist/components/Window/index.d.ts +5 -0
  98. package/dist/components/Window/internals/WindowStatusBar.d.ts +8 -0
  99. package/dist/components/Window/internals/WindowTitleBar.d.ts +10 -0
  100. package/dist/components/Window/useWindowTitleButtons.d.ts +12 -0
  101. package/dist/components/Window/windowMenuContext.d.ts +3 -0
  102. package/dist/components/_shared/ControlOpener.d.ts +18 -0
  103. package/dist/components/_shared/portalPositioning.d.ts +16 -0
  104. package/dist/components/_shared/slotProps.d.ts +867 -0
  105. package/dist/components/_shared/themePortal.d.ts +2 -0
  106. package/dist/components/_shared/treeData.d.ts +19 -0
  107. package/dist/components/_shared/usePopupPosition.d.ts +40 -0
  108. package/dist/index.cjs +9848 -0
  109. package/dist/index.d.ts +45 -0
  110. package/dist/index.js +9885 -0
  111. package/dist/styles.css +3644 -0
  112. package/dist/theme/NuThemeProvider.d.ts +26 -0
  113. package/dist/theme/themeContext.d.ts +15 -0
  114. package/dist/theme/themes.d.ts +49 -0
  115. package/dist/utils/renderMnemonicText.d.ts +10 -0
  116. package/dist/windowing/AppBarHost.d.ts +6 -0
  117. package/dist/windowing/AppBarItem.d.ts +587 -0
  118. package/dist/windowing/NuWindowProvider.d.ts +9 -0
  119. package/dist/windowing/WindowBar.d.ts +13 -0
  120. package/dist/windowing/dialogHelpers.d.ts +1793 -0
  121. package/dist/windowing/internals/MdiWindowPickerDialog.d.ts +10 -0
  122. package/dist/windowing/mdiMenu.d.ts +3 -0
  123. package/dist/windowing/windowContext.d.ts +18 -0
  124. package/dist/windowing/windowing.constants.d.ts +1 -0
  125. package/dist/windowing/windowing.types.d.ts +54 -0
  126. package/docs/API_REFERENCE.md +150 -0
  127. package/docs/ARCHITECTURE.md +170 -0
  128. package/docs/AppBarHost.md +22 -0
  129. package/docs/AppBarItem.md +22 -0
  130. package/docs/Button.md +24 -0
  131. package/docs/COMPONENT_INDEX.md +64 -0
  132. package/docs/CONTRIBUTOR_GUIDE.md +393 -0
  133. package/docs/CheckBox.md +30 -0
  134. package/docs/ComboBox.md +41 -0
  135. package/docs/CommandButton.md +45 -0
  136. package/docs/CrtGlitch.md +49 -0
  137. package/docs/Dashboard.md +73 -0
  138. package/docs/Desktop.md +27 -0
  139. package/docs/DialogHelpers.md +85 -0
  140. package/docs/Dropdown.md +44 -0
  141. package/docs/Frame.md +38 -0
  142. package/docs/GETTING_STARTED.md +110 -0
  143. package/docs/Glyph.md +29 -0
  144. package/docs/Info.md +51 -0
  145. package/docs/ListBox.md +35 -0
  146. package/docs/ListView.md +62 -0
  147. package/docs/MainMenu.md +36 -0
  148. package/docs/MaskedField.md +124 -0
  149. package/docs/Memo.md +32 -0
  150. package/docs/NuAppHostProvider.md +28 -0
  151. package/docs/NuThemeProvider.md +64 -0
  152. package/docs/NuView.md +58 -0
  153. package/docs/NuWindowProvider.md +81 -0
  154. package/docs/PageControl.md +28 -0
  155. package/docs/Panel.md +23 -0
  156. package/docs/PopupMenu.md +42 -0
  157. package/docs/ProgressBar.md +33 -0
  158. package/docs/PropertyGrid.md +63 -0
  159. package/docs/RadioGroup.md +36 -0
  160. package/docs/ReportCell.md +27 -0
  161. package/docs/SLOT_CUSTOMIZATION.md +85 -0
  162. package/docs/STORYBOOK.md +96 -0
  163. package/docs/SearchBox.md +41 -0
  164. package/docs/SpinBox.md +25 -0
  165. package/docs/Splitter.md +91 -0
  166. package/docs/Stack.md +26 -0
  167. package/docs/StatusBarItem.md +31 -0
  168. package/docs/TOKEN_CHECKLIST.md +122 -0
  169. package/docs/TextField.md +27 -0
  170. package/docs/TickBar.md +57 -0
  171. package/docs/ToolBar.md +51 -0
  172. package/docs/TreeListView.md +84 -0
  173. package/docs/TreeView.md +53 -0
  174. package/docs/Window.md +53 -0
  175. package/docs/WindowBar.md +24 -0
  176. package/package.json +47 -0
@@ -0,0 +1,25 @@
1
+ # SpinBox
2
+
3
+ `SpinBox` is the numeric field with inline decrement and increment controls.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <SpinBox defaultValue={32} label="Cluster size" min={1} max={128} step={1} />
9
+ ```
10
+
11
+ ## Key Props
12
+
13
+ - `label: string`
14
+ - `hint?: string`
15
+ - `value?: number`
16
+ - `defaultValue?: number`
17
+ - `min?: number`
18
+ - `max?: number`
19
+ - `step?: number`
20
+ - `onValueChange?: (value) => void`
21
+
22
+ ## Notes
23
+
24
+ - `ArrowUp` and `ArrowDown` adjust the value.
25
+ - Manual text edits are allowed; invalid draft text is normalized back to the last valid numeric value on blur.
@@ -0,0 +1,91 @@
1
+ # Splitter
2
+
3
+ `Splitter` divides available space into two resizable panes with a draggable separator.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <Splitter
9
+ defaultValue={0.4}
10
+ first={
11
+ <NuView padding="sm">
12
+ <Frame title="Navigator">{/* content */}</Frame>
13
+ </NuView>
14
+ }
15
+ second={
16
+ <NuView padding="sm">
17
+ <Frame title="Inspector">{/* content */}</Frame>
18
+ </NuView>
19
+ }
20
+ />
21
+ ```
22
+
23
+ ## Key Props
24
+
25
+ - `orientation?: "vertical" | "horizontal"`
26
+ - `value?: number`
27
+ - `defaultValue?: number`
28
+ - `onValueChange?: (value: number) => void`
29
+ - `saveId?: string`
30
+ - `min?: number`
31
+ - `max?: number`
32
+ - `first`
33
+ - `second`
34
+
35
+ ## Notes
36
+
37
+ - `vertical` means side-by-side panes with a vertical drag handle.
38
+ - `horizontal` means stacked panes with a horizontal drag handle.
39
+ - `value`, `min`, `max`, and `defaultValue` are ratio-based in the `0..1` range.
40
+ - `saveId` stores the latest ratio in `localStorage` and restores it for uncontrolled usage.
41
+ - Nested splitters work through normal composition; each pane can render another `Splitter`.
42
+ - The separator supports pointer dragging and keyboard resizing with arrow keys, `Home`, and `End`.
43
+
44
+ ## Layout Protocol
45
+
46
+ For splitter cells, the recommended ownership is:
47
+
48
+ `Splitter cell -> NuView -> content`
49
+
50
+ That means:
51
+
52
+ - `Splitter` only divides space.
53
+ - `NuView` owns fill, scroll, and optional padding.
54
+ - The actual content component (`Frame`, `ListView`, custom layout, etc.) lives inside `NuView`.
55
+
56
+ Recommended:
57
+
58
+ ```tsx
59
+ <Splitter
60
+ first={
61
+ <NuView padding="sm">
62
+ <Frame title="Navigator">{/* content */}</Frame>
63
+ </NuView>
64
+ }
65
+ second={
66
+ <NuView scroll="auto">
67
+ <MyPane />
68
+ </NuView>
69
+ }
70
+ />
71
+ ```
72
+
73
+ Avoid using the inverse ownership when the viewport should belong to the cell:
74
+
75
+ ```tsx
76
+ <Frame title="Navigator">
77
+ <NuView>{/* content */}</NuView>
78
+ </Frame>
79
+ ```
80
+
81
+ That pattern makes the frame own the area and the viewport live too deep in the tree, which is usually not what you want in splitter layouts.
82
+
83
+ ## Protocol Note
84
+
85
+ This was introduced after a layout bug in the splitter preview:
86
+
87
+ - `NuView` was living inside `Frame`, instead of owning the splitter cell.
88
+ - `Frame` was being treated like the viewport owner.
89
+ - As a result, scroll behavior and clipping looked wrong for pane-sized content.
90
+
91
+ The fix was to treat `NuView` as the viewport contract and keep `Splitter` itself layout-only.
package/docs/Stack.md ADDED
@@ -0,0 +1,26 @@
1
+ # Stack
2
+
3
+ `Stack` is a small flex layout helper.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <Stack gap="md">
9
+ <TextField label="Target" />
10
+ <Button>Run</Button>
11
+ </Stack>
12
+ ```
13
+
14
+ ## Key Props
15
+
16
+ - `direction?: "row" | "column"`
17
+ - `gap?: "sm" | "md" | "lg"`
18
+ - `align?: "start" | "center" | "end" | "stretch"`
19
+ - `justify?: "start" | "center" | "end" | "space-between" | "space-around"`
20
+ - standard `div` props
21
+
22
+ ## Notes
23
+
24
+ - `align` maps to `align-items`.
25
+ - `justify` maps to `justify-content`.
26
+ - `Stack` is intentionally small, but these two props cover the common row/column alignment cases without dropping to inline styles.
@@ -0,0 +1,31 @@
1
+ # StatusBarItem
2
+
3
+ `StatusBarItem` is a placement helper for window status bars.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <Window
9
+ title="Activity Log"
10
+ statusBar={
11
+ <>
12
+ <StatusBarItem grow>F2 Save F3 Search</StatusBarItem>
13
+ <StatusBarItem align="end">3 warnings</StatusBarItem>
14
+ </>
15
+ }
16
+ >
17
+ <Content />
18
+ </Window>
19
+ ```
20
+
21
+ ## Key Props
22
+
23
+ - `grow?: boolean`
24
+ - `align?: "start" | "center" | "end"`
25
+ - `children`
26
+
27
+ ## Notes
28
+
29
+ - `StatusBarItem` is layout-only.
30
+ - It does not render its own border or segmented chrome.
31
+ - The host controls the visual content inside the item.
@@ -0,0 +1,122 @@
1
+ # Token Checklist
2
+
3
+ Practical checklist for keeping new components visually consistent with the rest of the library.
4
+
5
+ ## Source Of Truth
6
+
7
+ - Runtime theme tokens: [`packages/ui/src/theme/themes.ts`](../packages/ui/src/theme/themes.ts)
8
+ - CSS variable defaults: [`packages/ui/src/variables.less`](../packages/ui/src/variables.less)
9
+
10
+ If a component needs a new reusable visual value, add it there first instead of hardcoding it locally.
11
+
12
+ ## Core Color Tokens
13
+
14
+ - Desktop and shell:
15
+ - `--nu-desktop-bg`
16
+ - `--nu-desktop-pattern`
17
+ - `--nu-color-shell`
18
+ - `--nu-color-app-bg`
19
+ - `--nu-color-app-bg-alt`
20
+ - Chrome and panels:
21
+ - `--nu-color-chrome`
22
+ - `--nu-color-panel`
23
+ - `--nu-color-panel-inset`
24
+ - `--nu-color-title-bg`
25
+ - `--nu-color-title-text`
26
+ - Text:
27
+ - `--nu-text-primary`
28
+ - `--nu-text-muted`
29
+ - `--nu-text-inverse`
30
+ - `--nu-text-accent`
31
+ - `--nu-text-hotkey`
32
+ - Controls:
33
+ - `--nu-color-button-face`
34
+ - `--nu-color-button-face-alt`
35
+ - `--nu-color-button-danger`
36
+ - `--nu-color-button-text`
37
+ - `--nu-color-field-bg`
38
+ - `--nu-color-field-text`
39
+ - Borders, focus, shadow:
40
+ - `--nu-border-light`
41
+ - `--nu-border-dark`
42
+ - `--nu-border-accent`
43
+ - `--nu-shadow-color`
44
+ - `--nu-focus-color`
45
+ - Window overlays:
46
+ - `--nu-window-inactive-overlay`
47
+ - `--nu-window-modal-backdrop`
48
+
49
+ ## Layout And Geometry Tokens
50
+
51
+ - Spacing:
52
+ - `--nu-space-xs`
53
+ - `--nu-space-sm`
54
+ - `--nu-space-md`
55
+ - `--nu-space-lg`
56
+ - `--nu-space-xl`
57
+ - Typography:
58
+ - `--nu-font-body`
59
+ - Shared geometry:
60
+ - `--nu-glyph-cell-size`
61
+ - `--nu-control-height`
62
+ - `--nu-frame-thickness`
63
+ - `--nu-rule-thickness`
64
+ - Button mechanics:
65
+ - `--nu-button-shadow-x`
66
+ - `--nu-button-shadow-y`
67
+ - `--nu-button-shadow-offset-x`
68
+ - `--nu-button-shadow-offset-y`
69
+ - `--nu-button-press-depth-x`
70
+ - `--nu-button-press-depth-y`
71
+ - Window shadow:
72
+ - `--nu-window-shadow-bg`
73
+ - `--nu-window-shadow-offset-x`
74
+ - `--nu-window-shadow-offset-y`
75
+ - Scrollbar:
76
+ - `--nu-scrollbar-track`
77
+ - `--nu-scrollbar-thumb`
78
+ - `--nu-scrollbar-button-bg`
79
+ - `--nu-scrollbar-button-size`
80
+
81
+ ## Checklist For A New Component
82
+
83
+ - Surface:
84
+ - Is the background coming from an existing panel, chrome, button, or field token?
85
+ - Text:
86
+ - Is default text using one of `primary`, `inverse`, `muted`, `accent`, `hotkey`?
87
+ - Focus and selection:
88
+ - Is active/focused state using the same black/yellow system as existing controls?
89
+ - Borders:
90
+ - Are border colors coming from `light`, `dark`, or `accent` tokens?
91
+ - Spacing:
92
+ - Are paddings and gaps based on `--nu-space-*`?
93
+ - Height:
94
+ - If it is a control row, is it aligned to `--nu-control-height`?
95
+ - Glyphs:
96
+ - If it shows an icon/checkmark/caret, is it using `NuGlyph` and the shared glyph cell?
97
+ - Shadows:
98
+ - If it is raised, is it reusing button/window shadow logic instead of inventing a new one?
99
+ - Theme coverage:
100
+ - Would the component still read correctly in `classic`, `amber`, and `phosphor`?
101
+ - Hardcoded values:
102
+ - Are any colors or dimensions local only because they are truly component-specific?
103
+
104
+ ## When To Add A New Token
105
+
106
+ Add a token when:
107
+
108
+ - the value is already repeated in more than one component
109
+ - the value expresses a visual role, not just a one-off tweak
110
+ - the value should vary by theme
111
+
112
+ Do not add a token when:
113
+
114
+ - the value is internal to one component only
115
+ - the value is purely structural and unlikely to be reused
116
+ - the value is still experimental and not yet stable
117
+
118
+ ## Current Gaps To Watch
119
+
120
+ - Some component-specific structural values still live locally in `*.less`.
121
+ - Scrollbar tokens are partially shared, but geometry is still tied to current implementation details.
122
+ - Mnemonic/hotkey color is standardized, but keyboard behavior itself is not tokenized and should stay behavioral, not visual.
@@ -0,0 +1,27 @@
1
+ # TextField
2
+
3
+ `TextField` is the basic text input primitive using the DOS-style bracketed slot.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <TextField
9
+ label="Target volume"
10
+ defaultValue="C:\\SYSTEM"
11
+ hint="Classic Blue is the default theme."
12
+ />
13
+ ```
14
+
15
+ ## Key Props
16
+
17
+ - `label: string`
18
+ - `hint?: string`
19
+ - `debounceMs?: number`
20
+ - `onDebouncedChange?: (value) => void`
21
+ - standard `input` props such as `value`, `defaultValue`, `onChange`, `disabled`
22
+
23
+ ## Notes
24
+
25
+ - The control uses brackets and a dark input slot rather than a conventional bordered web input.
26
+ - `onChange` remains immediate; `onDebouncedChange` is optional and runs after the debounce delay.
27
+ - For masked input, use [MaskedField](./MaskedField.md) instead of overloading `TextField`.
@@ -0,0 +1,57 @@
1
+ # TickBar
2
+
3
+ `TickBar` is a DOS-style slider with keyboard support, pointer dragging, and visible tick marks.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ import { TickBar } from "@deadragdoll/reactnu";
9
+
10
+ function Example() {
11
+ return (
12
+ <TickBar
13
+ hint="Arrow keys adjust the value"
14
+ label="Volume"
15
+ max={100}
16
+ min={0}
17
+ orientation="horizontal"
18
+ step={5}
19
+ value={65}
20
+ />
21
+ );
22
+ }
23
+ ```
24
+
25
+ ## Props
26
+
27
+ - `label?: string`
28
+ - `hint?: string`
29
+ - `min?: number`
30
+ - `max?: number`
31
+ - `step?: number`
32
+ - `orientation?: "horizontal" | "vertical"`
33
+ - `value?: number`
34
+ - `defaultValue?: number`
35
+ - `onValueChange?: (value: number) => void`
36
+ - `tickCount?: number`
37
+ - `showValue?: boolean`
38
+ - `valueRenderer?: (value, min, max) => ReactNode`
39
+ - `disabled?: boolean`
40
+ - `fill?: boolean`
41
+
42
+ ## Behavior
43
+
44
+ - Supports controlled and uncontrolled value flow.
45
+ - Pointer down on the track moves the thumb immediately.
46
+ - Dragging continues while the pointer is captured by the track.
47
+ - `vertical` mode maps `min` to the bottom and `max` to the top.
48
+ - Keyboard:
49
+ - `ArrowLeft`, `ArrowDown` decrement
50
+ - `ArrowRight`, `ArrowUp` increment
51
+ - `PageDown`, `PageUp` move by `step * 10`
52
+ - `Home`, `End` jump to `min` and `max`
53
+ - Values are clamped to `min` / `max` and snapped to `step`.
54
+
55
+ ## Notes
56
+
57
+ - If `tickCount` is omitted, the control derives a reasonable number of visible marks from `min`, `max`, and `step`.
@@ -0,0 +1,51 @@
1
+ # ToolBar
2
+
3
+ `ToolBar` is the compact action strip for command buttons and separators.
4
+
5
+ For the same button behavior outside a toolbar container, use [CommandButton](./CommandButton.md).
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ <ToolBar>
11
+ <ToolButton icon="folder">&Scan</ToolButton>
12
+ <ToolButton icon="star" pressed>
13
+ &Watch
14
+ </ToolButton>
15
+ <ToolSeparator />
16
+ <ToolDropButton
17
+ icon="folder"
18
+ menuItems={[
19
+ { id: "export-map", text: "Export &map" },
20
+ { id: "export-log", text: "Export &log" }
21
+ ]}
22
+ >
23
+ &Export
24
+ </ToolDropButton>
25
+ </ToolBar>
26
+ ```
27
+
28
+ ## Exports
29
+
30
+ - `CommandButton`
31
+ - `ToolBar`
32
+ - `ToolButton`
33
+ - `ToolDropButton`
34
+ - `ToolSeparator`
35
+
36
+ ## Key Props
37
+
38
+ - `fill?: boolean`
39
+ - `wrap?: boolean`
40
+ - `slotStyles`
41
+ - `slotClassNames`
42
+
43
+ ## Notes
44
+
45
+ - `ToolBar` is layout-only and defaults to `fill={true}`.
46
+ - `wrap={true}` lets tools continue on the next row when the container is too narrow.
47
+ - `ToolButton` supports `toggled` for toggle-style tools. `pressed` is kept as a legacy alias through the shared command-button layer.
48
+ - `ToolButton` also supports `icon` and optional `dropdown`.
49
+ - `ToolDropButton` is a convenience wrapper for `ToolButton dropdown`.
50
+ - If `menuItems` are provided, `ToolDropButton` opens `PopupMenu` automatically and reports selection through `onMenuItemSelect`.
51
+ - `ToolSeparator` is decorative and should only be used between tools.
@@ -0,0 +1,84 @@
1
+ # TreeListView
2
+
3
+ `TreeListView` combines a hierarchical tree column with report-style columns.
4
+ The tree geometry stays under component control, while report cells can be
5
+ filled by the host.
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ type Node = TreeListItemBase<Node> & {
11
+ metrics?: {
12
+ humidity: number;
13
+ temperature: number;
14
+ wind: number;
15
+ };
16
+ };
17
+
18
+ const columns: TreeListColumn<Node>[] = [
19
+ { id: "name", title: "&Name", tree: true, width: "24ch" },
20
+ { id: "temp", title: "&Temp", align: "end", width: "9ch" },
21
+ { id: "humidity", title: "&Humidity", align: "end", width: "10ch" }
22
+ ];
23
+
24
+ <TreeListView
25
+ columns={columns}
26
+ data={nodes}
27
+ getCellContent={(itemId, columnId, context) => {
28
+ if (columnId === "temp" && context.item.metrics) {
29
+ return (
30
+ <ReportCell align="end">
31
+ {`${context.item.metrics.temperature.toFixed(1)}C`}
32
+ </ReportCell>
33
+ );
34
+ }
35
+
36
+ return undefined;
37
+ }}
38
+ selectedId={selectedId}
39
+ onItemSelect={(item) => setSelectedId(item.id)}
40
+ onItemCheckChange={(item, checked) => {}}
41
+ />;
42
+ ```
43
+
44
+ ## Key Props
45
+
46
+ - `columns`
47
+ - `data`
48
+ - `getCellContent`
49
+ - `dataVersion`
50
+ - `selectedId`
51
+ - `activeItemId`
52
+ - `defaultActiveItemId`
53
+ - `expandedIds`
54
+ - `defaultExpandedIds`
55
+ - `onItemSelect`
56
+ - `onItemDoubleClick`
57
+ - `onItemCheckChange`
58
+ - `onExpandedIdsChange`
59
+ - `onActiveItemChange`
60
+ - `checkedIds`
61
+ - `uncheckedShape`
62
+
63
+ ## Imperative Handle
64
+
65
+ - `focus()`
66
+ - `scrollToItem(itemId)`
67
+ - `activateItem(itemId)`
68
+ - `expandItem(itemId)`
69
+ - `collapseItem(itemId)`
70
+ - `toggleItemCheck(itemId)`
71
+ - `getActiveItemId()`
72
+
73
+ ## Notes
74
+
75
+ - Mark one column with `tree: true` to host the hierarchy.
76
+ - If no column is marked as tree, the first column is used.
77
+ - Keyboard behavior follows the same pattern as `TreeView`, while columns behave like `ListView`.
78
+ - `getCellContent(itemId, columnId, context)` is the preferred way to populate
79
+ report columns from host data.
80
+ - `dataVersion` is available for live-data scenarios where report content
81
+ changes frequently even if the tree structure itself stays stable.
82
+ - Columns auto-size from visible content by default.
83
+ - `minWidth` sets a lower bound for auto-sized and resized columns.
84
+ - Columns are resizable unless `resizable={false}` is set on a column.
@@ -0,0 +1,53 @@
1
+ # TreeView
2
+
3
+ `TreeView` renders a recursive hierarchy with DOS-style connector geometry.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <TreeView
9
+ data={[
10
+ {
11
+ title: "Drive C:",
12
+ id: "1",
13
+ expanded: true,
14
+ children: [
15
+ { title: "SYSTEM", id: "1-1" },
16
+ { title: "LOGS", id: "1-2", checked: true }
17
+ ]
18
+ }
19
+ ]}
20
+ selectedId={selectedId}
21
+ onItemSelect={(item) => setSelectedId(item.id)}
22
+ onItemCheckChange={(item, checked) => {}}
23
+ />
24
+ ```
25
+
26
+ ## Key Props
27
+
28
+ - `data: TreeItem[]`
29
+ - `selectedId?: string`
30
+ - `expandedIds?: string[]`
31
+ - `defaultExpandedIds?: string[]`
32
+ - `emptyText?: string`
33
+ - `uncheckedShape?: "box" | "none"`
34
+ - `onItemSelect?: (item) => void`
35
+ - `onItemDoubleClick?: (item) => void`
36
+ - `onItemCheckChange?: (item, checked) => void`
37
+ - `onExpandedIdsChange?: (expandedIds) => void`
38
+
39
+ ## Imperative Handle
40
+
41
+ - `focus()`
42
+ - `scrollToItem(itemId)`
43
+ - `activateItem(itemId)`
44
+ - `expandItem(itemId)`
45
+ - `collapseItem(itemId)`
46
+ - `toggleItemCheck(itemId)`
47
+ - `getActiveItemId()`
48
+
49
+ ## Notes
50
+
51
+ - Tree geometry is owned by the component.
52
+ - The host provides item data and optional controlled state.
53
+ - Keyboard navigation supports arrows, `Home`, `End`, `Enter`, and `Space`.
package/docs/Window.md ADDED
@@ -0,0 +1,53 @@
1
+ # Window
2
+
3
+ `Window` is the main floating chrome primitive used for desktop windows and dialogs.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <Window title="Activity Log" mode="window" statusBar="F2 Save">
9
+ <Content />
10
+ </Window>
11
+ ```
12
+
13
+ ```tsx
14
+ <Window
15
+ title="Activity Log"
16
+ mode="window"
17
+ statusBar={
18
+ <>
19
+ <StatusBarItem grow>F2 Save F3 Search Alt+F3 Close</StatusBarItem>
20
+ <StatusBarItem align="end">3 warnings</StatusBarItem>
21
+ </>
22
+ }
23
+ >
24
+ <Content />
25
+ </Window>
26
+ ```
27
+
28
+ ## Key Props
29
+
30
+ - `title: string`
31
+ - `mode?: "dialog" | "window"`
32
+ - `border?: "single" | "double"`
33
+ - `minimized?: boolean`
34
+ - `maximized?: boolean`
35
+ - `closeable?: boolean`
36
+ - `draggable?: boolean`
37
+ - `resizable?: boolean`
38
+ - `scrollable?: boolean`
39
+ - `statusBar?: ReactNode`
40
+ - `titleButtons?: WindowTitleButtonDefinition[]`
41
+ - `onClose?()`
42
+ - `onToggleMinimized?()`
43
+ - `onToggleMaximized?()`
44
+ - `onPositionChange?(position)`
45
+ - `onSizeChange?(size)`
46
+ - `onActivate?()`
47
+
48
+ ## Notes
49
+
50
+ - Drag and resize are implemented with pointer events and local DOM updates for smoother motion.
51
+ - The public `WindowTitleButton` and `useWindowTitleButtons()` helpers support custom title-bar controls.
52
+ - `StatusBarItem` only provides placement semantics (`grow`, `align`) and does not enforce its own border or chrome.
53
+ - Plain string `statusBar` still works for simple status lines.
@@ -0,0 +1,24 @@
1
+ # WindowBar
2
+
3
+ `WindowBar` renders open windows in the desktop app bar.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ <WindowBar
9
+ items={windowManager.windows}
10
+ onActivateWindow={(id) => windowManager.activateWindow(id)}
11
+ />
12
+ ```
13
+
14
+ ## Behavior
15
+
16
+ - Shows open windows in creation order
17
+ - Marks the active window
18
+ - Groups windows by `domain`
19
+ - Opens a picker dialog when a grouped domain is clicked
20
+
21
+ ## Notes
22
+
23
+ - Grouping is driven by `NuManagedWindowDefinition.domain`.
24
+ - Grouped pickers use the shared MDI-style window picker dialog logic.
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@deadragdoll/reactnu",
3
+ "version": "0.1.9",
4
+ "private": false,
5
+ "description": "React components with a precise DOS-era utility interface.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ },
17
+ "./styles.css": "./dist/styles.css"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "docs",
22
+ "README.md",
23
+ "LICENSE"
24
+ ],
25
+ "keywords": [
26
+ "react",
27
+ "typescript",
28
+ "component-library",
29
+ "dos",
30
+ "norton-utilities"
31
+ ],
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "scripts": {
36
+ "prepack": "node scripts/prepare-package-docs.mjs && npm run build",
37
+ "postpack": "node scripts/prepare-package-docs.mjs --clean",
38
+ "build:styles": "mkdir -p dist && lessc src/globals.less dist/styles.css && prettier --write dist/styles.css",
39
+ "watch:styles": "mkdir -p dist && lessc --watch src/globals.less dist/styles.css",
40
+ "build": "tsup src/index.ts --clean --tsconfig tsconfig.json --format esm,cjs --external react,react-dom && tsc -p tsconfig.build.json && npm run build:styles",
41
+ "dev": "npm run build:styles && tsup src/index.ts --watch --tsconfig tsconfig.json --format esm,cjs --external react,react-dom"
42
+ },
43
+ "peerDependencies": {
44
+ "react": "^19.2.0",
45
+ "react-dom": "^19.2.0"
46
+ }
47
+ }