@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,393 @@
|
|
|
1
|
+
# Contributor Guide
|
|
2
|
+
|
|
3
|
+
This guide is for developers and coding agents who need to extend ReactNU or integrate it into a host application without reverse-engineering the source tree first.
|
|
4
|
+
|
|
5
|
+
It is intentionally practical.
|
|
6
|
+
|
|
7
|
+
## What ReactNU Is
|
|
8
|
+
|
|
9
|
+
ReactNU is a React + TypeScript component library with a Norton Utilities / DOS-era visual language.
|
|
10
|
+
|
|
11
|
+
The target qualities are:
|
|
12
|
+
|
|
13
|
+
- crisp geometry
|
|
14
|
+
- dense information layout
|
|
15
|
+
- keyboard-first interaction
|
|
16
|
+
- strong visual hierarchy
|
|
17
|
+
- predictable controlled/uncontrolled behavior
|
|
18
|
+
- reusable host shell composition
|
|
19
|
+
|
|
20
|
+
ReactNU is not a novelty retro skin. It is a reusable UI system that happens to use a DOS-style visual grammar.
|
|
21
|
+
|
|
22
|
+
## Recommended Mental Model
|
|
23
|
+
|
|
24
|
+
Think in layers:
|
|
25
|
+
|
|
26
|
+
1. Theme and desktop tokens
|
|
27
|
+
2. Low-level controls
|
|
28
|
+
3. Composed surfaces
|
|
29
|
+
4. Window and dialog orchestration
|
|
30
|
+
5. Host application composition
|
|
31
|
+
|
|
32
|
+
That means:
|
|
33
|
+
|
|
34
|
+
- a control should not guess desktop ownership
|
|
35
|
+
- a dialog should not guess app-shell structure
|
|
36
|
+
- popup geometry should not guess multiple coordinate systems
|
|
37
|
+
- the host should explicitly own workflow composition
|
|
38
|
+
|
|
39
|
+
## First Files To Read
|
|
40
|
+
|
|
41
|
+
If you are new to the repo, read in this order:
|
|
42
|
+
|
|
43
|
+
1. [Getting Started](./GETTING_STARTED.md)
|
|
44
|
+
2. [Architecture](./ARCHITECTURE.md)
|
|
45
|
+
3. [API Reference](./API_REFERENCE.md)
|
|
46
|
+
4. [Slot Customization](./SLOT_CUSTOMIZATION.md)
|
|
47
|
+
5. [Storybook](./STORYBOOK.md)
|
|
48
|
+
|
|
49
|
+
If you are working on windowing or popup behavior, also read:
|
|
50
|
+
|
|
51
|
+
6. [NuWindowProvider](./NuWindowProvider.md)
|
|
52
|
+
7. [Dialog Helpers](./DialogHelpers.md)
|
|
53
|
+
8. [Desktop](./Desktop.md)
|
|
54
|
+
|
|
55
|
+
## Host Composition Patterns
|
|
56
|
+
|
|
57
|
+
### Full Desktop Shell
|
|
58
|
+
|
|
59
|
+
Use this when you want:
|
|
60
|
+
|
|
61
|
+
- main menu
|
|
62
|
+
- workspace area
|
|
63
|
+
- app bar
|
|
64
|
+
- managed windows
|
|
65
|
+
- desktop-level modal behavior
|
|
66
|
+
|
|
67
|
+
Recommended ownership:
|
|
68
|
+
|
|
69
|
+
`NuThemeProvider -> NuDesktop -> workspace content -> managed windows`
|
|
70
|
+
|
|
71
|
+
Typical example:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<NuThemeProvider>
|
|
75
|
+
<NuDesktop appBar={<ShellAppBar />}>
|
|
76
|
+
<Dashboard items={...} />
|
|
77
|
+
</NuDesktop>
|
|
78
|
+
</NuThemeProvider>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Bounded Window Host
|
|
82
|
+
|
|
83
|
+
Use this when you need:
|
|
84
|
+
|
|
85
|
+
- managed dialogs or windows
|
|
86
|
+
- modal layering
|
|
87
|
+
- `useNuWindowManager()`
|
|
88
|
+
- but not the full desktop shell
|
|
89
|
+
|
|
90
|
+
This is especially useful for:
|
|
91
|
+
|
|
92
|
+
- Storybook stories
|
|
93
|
+
- focused demo surfaces
|
|
94
|
+
- embedded host panels
|
|
95
|
+
|
|
96
|
+
Typical example:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<div style={{ position: "relative", height: "40rem", overflow: "hidden" }}>
|
|
100
|
+
<NuWindowProvider renderAppBar={false}>
|
|
101
|
+
<DialogLauncherSurface />
|
|
102
|
+
</NuWindowProvider>
|
|
103
|
+
</div>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Do Not Mix These Accidentally
|
|
107
|
+
|
|
108
|
+
Common mistake:
|
|
109
|
+
|
|
110
|
+
- using `NuDesktop` when a bounded `NuWindowProvider` is enough
|
|
111
|
+
|
|
112
|
+
Symptoms:
|
|
113
|
+
|
|
114
|
+
- content appears to escape the preview region
|
|
115
|
+
- dialogs reposition the whole preview unexpectedly
|
|
116
|
+
- fullscreen/fixed desktop semantics leak into Storybook
|
|
117
|
+
|
|
118
|
+
## Theme Ownership
|
|
119
|
+
|
|
120
|
+
Theme state belongs to `NuThemeProvider`.
|
|
121
|
+
|
|
122
|
+
Current provider-level host settings include:
|
|
123
|
+
|
|
124
|
+
- theme
|
|
125
|
+
- font family
|
|
126
|
+
- font size
|
|
127
|
+
- desktop pattern mode
|
|
128
|
+
|
|
129
|
+
Prefer changing typography and desktop surface through the provider, not through ad-hoc DOM overrides.
|
|
130
|
+
|
|
131
|
+
## Popup And Menu Contract
|
|
132
|
+
|
|
133
|
+
Popup-like controls currently follow this contract:
|
|
134
|
+
|
|
135
|
+
- popup renders into `document.body`
|
|
136
|
+
- popup position is measured from `getBoundingClientRect()`
|
|
137
|
+
- popup receives theme vars from the nearest `.nu-theme-root`
|
|
138
|
+
|
|
139
|
+
Why:
|
|
140
|
+
|
|
141
|
+
- viewport coordinates stay stable
|
|
142
|
+
- Storybook and sandbox use the same geometry model
|
|
143
|
+
- popup visuals still inherit theme and typography
|
|
144
|
+
|
|
145
|
+
If a popup appears correct in sandbox but not in Storybook, first suspect host composition or portal assumptions, not the control API.
|
|
146
|
+
|
|
147
|
+
## Shared Internal Primitive Rule
|
|
148
|
+
|
|
149
|
+
When two controls share the same visual part, do not duplicate the implementation casually.
|
|
150
|
+
|
|
151
|
+
Preferred order:
|
|
152
|
+
|
|
153
|
+
1. shared LESS primitive if only chrome/geometry is shared
|
|
154
|
+
2. shared internal JSX primitive if markup/behavior is mostly shared
|
|
155
|
+
3. public component only if the thing has independent public meaning
|
|
156
|
+
|
|
157
|
+
Current example:
|
|
158
|
+
|
|
159
|
+
- `ControlOpener`
|
|
160
|
+
internal primitive shared by `Dropdown` and `ComboBox`
|
|
161
|
+
|
|
162
|
+
This keeps:
|
|
163
|
+
|
|
164
|
+
- glyph metrics
|
|
165
|
+
- opener width
|
|
166
|
+
- border
|
|
167
|
+
- background
|
|
168
|
+
- browser button reset behavior
|
|
169
|
+
|
|
170
|
+
in one place.
|
|
171
|
+
|
|
172
|
+
## Slot Customization Contract
|
|
173
|
+
|
|
174
|
+
Preferred internal customization API:
|
|
175
|
+
|
|
176
|
+
- `slotStyles`
|
|
177
|
+
- `slotClassNames`
|
|
178
|
+
|
|
179
|
+
Use:
|
|
180
|
+
|
|
181
|
+
- `className` / `style` for root
|
|
182
|
+
- `slot*` props for meaningful internal surfaces
|
|
183
|
+
|
|
184
|
+
Examples of good slot names:
|
|
185
|
+
|
|
186
|
+
- `root`
|
|
187
|
+
- `label`
|
|
188
|
+
- `title`
|
|
189
|
+
- `body`
|
|
190
|
+
- `popup`
|
|
191
|
+
- `listbox`
|
|
192
|
+
- `input`
|
|
193
|
+
- `field`
|
|
194
|
+
- `hint`
|
|
195
|
+
|
|
196
|
+
Avoid inventing new one-off props for every surface if a control already supports slot customization.
|
|
197
|
+
|
|
198
|
+
## Controlled / Uncontrolled Guidance
|
|
199
|
+
|
|
200
|
+
Use normal React contracts unless there is a strong reason not to.
|
|
201
|
+
|
|
202
|
+
Prefer:
|
|
203
|
+
|
|
204
|
+
- `value`
|
|
205
|
+
- `defaultValue`
|
|
206
|
+
- `onValueChange`
|
|
207
|
+
|
|
208
|
+
or for stateful booleans:
|
|
209
|
+
|
|
210
|
+
- `open`
|
|
211
|
+
- `defaultOpen`
|
|
212
|
+
- `onOpenChange`
|
|
213
|
+
|
|
214
|
+
For text-like controls:
|
|
215
|
+
|
|
216
|
+
- do not blur or steal focus during normal typing paths
|
|
217
|
+
- especially for editable popup controls like `ComboBox` and `SearchBox`
|
|
218
|
+
|
|
219
|
+
## Keyboard And Focus Rules
|
|
220
|
+
|
|
221
|
+
ReactNU is intentionally keyboard-forward.
|
|
222
|
+
|
|
223
|
+
Baseline expectations for interactive controls:
|
|
224
|
+
|
|
225
|
+
- visible focus
|
|
226
|
+
- sane tab order
|
|
227
|
+
- escape paths for overlays
|
|
228
|
+
- predictable arrow-key semantics where relevant
|
|
229
|
+
|
|
230
|
+
If a control opens a popup while still being text-editable:
|
|
231
|
+
|
|
232
|
+
- typing must stay on the input
|
|
233
|
+
- popup focus transfer should happen only on explicit navigation behavior
|
|
234
|
+
|
|
235
|
+
## Window And Dialog Guidance
|
|
236
|
+
|
|
237
|
+
Use `openWindow(...)` for document/tool windows.
|
|
238
|
+
|
|
239
|
+
Use `openDialog(...)` for managed dialogs that still use the normal window manager.
|
|
240
|
+
|
|
241
|
+
Use helper dialogs when you want standard system prompts:
|
|
242
|
+
|
|
243
|
+
- `showMessageBox(...)`
|
|
244
|
+
- `showInputBox(...)`
|
|
245
|
+
|
|
246
|
+
Helper dialogs already own:
|
|
247
|
+
|
|
248
|
+
- centered footer buttons
|
|
249
|
+
- standard sizing
|
|
250
|
+
- title defaults
|
|
251
|
+
- error/info tone behavior
|
|
252
|
+
|
|
253
|
+
If you build a custom dialog manually through `openDialog(...)`, you own its internal layout. That includes button centering.
|
|
254
|
+
|
|
255
|
+
## Storybook Rules
|
|
256
|
+
|
|
257
|
+
Storybook is not the sandbox.
|
|
258
|
+
|
|
259
|
+
Use Storybook for:
|
|
260
|
+
|
|
261
|
+
- isolated control review
|
|
262
|
+
- prop and slot examples
|
|
263
|
+
- theme/font variation
|
|
264
|
+
- narrow interaction checks
|
|
265
|
+
|
|
266
|
+
Use sandbox for:
|
|
267
|
+
|
|
268
|
+
- free-form desktop workflows
|
|
269
|
+
- multiple windows over time
|
|
270
|
+
- broader integration exercises
|
|
271
|
+
|
|
272
|
+
### Storybook Window Stories
|
|
273
|
+
|
|
274
|
+
Use:
|
|
275
|
+
|
|
276
|
+
- direct `Window` stories for static shell inspection
|
|
277
|
+
- bounded `NuWindowProvider` stories for managed dialogs/windows
|
|
278
|
+
- full `NuDesktop` only for shell-level stories
|
|
279
|
+
|
|
280
|
+
### Storybook Layout Density
|
|
281
|
+
|
|
282
|
+
Avoid giant empty canvases for small controls.
|
|
283
|
+
|
|
284
|
+
Preferred:
|
|
285
|
+
|
|
286
|
+
- wrap demos in titled panels
|
|
287
|
+
- keep compact controls content-sized
|
|
288
|
+
- use bounded desktop surfaces for desktop-like stories
|
|
289
|
+
|
|
290
|
+
## Sandbox Rules
|
|
291
|
+
|
|
292
|
+
Sandbox is allowed to be richer and more workflow-driven than Storybook.
|
|
293
|
+
|
|
294
|
+
But avoid turning sandbox code into hidden library architecture.
|
|
295
|
+
|
|
296
|
+
Good sandbox usage:
|
|
297
|
+
|
|
298
|
+
- realistic host composition
|
|
299
|
+
- test launchers
|
|
300
|
+
- theme switching
|
|
301
|
+
- live windowing flows
|
|
302
|
+
|
|
303
|
+
Bad sandbox usage:
|
|
304
|
+
|
|
305
|
+
- solving library bugs only in sandbox CSS
|
|
306
|
+
- encoding internal library assumptions in demo-only hacks
|
|
307
|
+
|
|
308
|
+
## Common Pitfalls
|
|
309
|
+
|
|
310
|
+
### 1. Mixing Portal Roots And Viewport Coordinates
|
|
311
|
+
|
|
312
|
+
If popup position is measured from `getBoundingClientRect()`, do not render the popup into an arbitrary local root unless the whole component is built around local coordinates.
|
|
313
|
+
|
|
314
|
+
### 2. Browser Button Defaults
|
|
315
|
+
|
|
316
|
+
If a shared primitive can render as a real `button`, neutralize browser defaults explicitly:
|
|
317
|
+
|
|
318
|
+
- `font: inherit`
|
|
319
|
+
- `line-height: 1`
|
|
320
|
+
- `appearance: none`
|
|
321
|
+
|
|
322
|
+
Otherwise glyphs and geometry drift even when the SVG is the same.
|
|
323
|
+
|
|
324
|
+
### 3. Hidden Stretch From Flex/Grid Parents
|
|
325
|
+
|
|
326
|
+
If shadows or chrome look detached, check whether the parent is stretching the child unexpectedly.
|
|
327
|
+
|
|
328
|
+
### 4. Storybook Isolates Bugs Differently
|
|
329
|
+
|
|
330
|
+
If behavior differs between sandbox and Storybook:
|
|
331
|
+
|
|
332
|
+
- inspect the host first
|
|
333
|
+
- inspect portal root and positioning rules second
|
|
334
|
+
- only then change the component internals
|
|
335
|
+
|
|
336
|
+
## Checklist For A New Control
|
|
337
|
+
|
|
338
|
+
Before adding a new control:
|
|
339
|
+
|
|
340
|
+
1. Decide whether it is a real public component or only an internal primitive.
|
|
341
|
+
2. Check whether an existing control or shared layer already solves most of it.
|
|
342
|
+
3. Define the public API in controlled/uncontrolled terms.
|
|
343
|
+
4. Define keyboard behavior.
|
|
344
|
+
5. Define focus behavior.
|
|
345
|
+
6. Define slot surfaces.
|
|
346
|
+
7. Add Storybook coverage.
|
|
347
|
+
8. Add sandbox coverage if the control is workflow-heavy.
|
|
348
|
+
9. Run the narrowest meaningful checks.
|
|
349
|
+
|
|
350
|
+
## Checklist For Updating An Existing Control
|
|
351
|
+
|
|
352
|
+
1. Read the current docs page.
|
|
353
|
+
2. Read the component implementation.
|
|
354
|
+
3. Check whether Storybook and sandbox both cover the control.
|
|
355
|
+
4. Prefer a small change.
|
|
356
|
+
5. If two controls share the same fix, look for a shared primitive/helper.
|
|
357
|
+
6. Update docs if the rule becomes architectural.
|
|
358
|
+
|
|
359
|
+
## Checklist For Popup Controls
|
|
360
|
+
|
|
361
|
+
1. Confirm anchor measurement surface.
|
|
362
|
+
2. Confirm portal root.
|
|
363
|
+
3. Confirm theme inheritance in the popup.
|
|
364
|
+
4. Confirm width contract:
|
|
365
|
+
- whole control
|
|
366
|
+
- field only
|
|
367
|
+
- custom width
|
|
368
|
+
5. Confirm focus path:
|
|
369
|
+
- editable input stays editable
|
|
370
|
+
- menu/list can still be navigated intentionally
|
|
371
|
+
|
|
372
|
+
## Checklist For Window/Dialog Stories
|
|
373
|
+
|
|
374
|
+
1. Decide whether the story needs full `NuDesktop`.
|
|
375
|
+
2. If not, prefer bounded `NuWindowProvider`.
|
|
376
|
+
3. Keep the preview area explicitly sized.
|
|
377
|
+
4. Avoid desktop-only CSS classes on standalone window hosts.
|
|
378
|
+
5. Test helper dialogs and custom dialogs separately.
|
|
379
|
+
|
|
380
|
+
## Current Internal Conventions Worth Preserving
|
|
381
|
+
|
|
382
|
+
- body portals for popup-like controls
|
|
383
|
+
- provider-owned typography and desktop pattern
|
|
384
|
+
- slot-based internal customization
|
|
385
|
+
- shared internal primitives for repeated chrome
|
|
386
|
+
- bounded Storybook hosts for dialog/window examples
|
|
387
|
+
- explicit scroll ownership
|
|
388
|
+
|
|
389
|
+
## If You Are Unsure
|
|
390
|
+
|
|
391
|
+
Choose the smallest rule-preserving change.
|
|
392
|
+
|
|
393
|
+
If a fix only works in sandbox or only works in Storybook, it is probably not finished.
|
package/docs/CheckBox.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# CheckBox
|
|
2
|
+
|
|
3
|
+
`CheckBox` renders a DOS-style checkbox with optional hint text.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<CheckBox
|
|
9
|
+
checked={enabled}
|
|
10
|
+
hint="Verify structure before commit."
|
|
11
|
+
label="&Verify structure"
|
|
12
|
+
onCheckedChange={(nextChecked) => setEnabled(nextChecked)}
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Key Props
|
|
17
|
+
|
|
18
|
+
- `label: string`
|
|
19
|
+
- `checked?: boolean`
|
|
20
|
+
- `defaultChecked?: boolean`
|
|
21
|
+
- `hint?: string`
|
|
22
|
+
- `disabled?: boolean`
|
|
23
|
+
- `uncheckedShape?: "box" | "none"`
|
|
24
|
+
- `onCheckedChange?: (checked, event) => void`
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- Supports controlled and uncontrolled usage.
|
|
29
|
+
- Label mnemonic highlighting follows the `&` marker convention.
|
|
30
|
+
- `uncheckedShape` controls whether the empty box is shown when unchecked.
|
package/docs/ComboBox.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ComboBox
|
|
2
|
+
|
|
3
|
+
`ComboBox` is the editable select control. It combines a text input with a filtered list popup.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<ComboBox
|
|
9
|
+
data={[
|
|
10
|
+
{
|
|
11
|
+
category: null,
|
|
12
|
+
items: [
|
|
13
|
+
{ id: "default", name: { text: "DEFAULT.NU" } },
|
|
14
|
+
{ id: "repair", name: { text: "REPAIR.NU" } }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
]}
|
|
18
|
+
label="Run profile"
|
|
19
|
+
/>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Key Props
|
|
23
|
+
|
|
24
|
+
- `data: ListBoxGroup[]`
|
|
25
|
+
- `label: string`
|
|
26
|
+
- `hint?: string`
|
|
27
|
+
- `value?: string`
|
|
28
|
+
- `defaultValue?: string`
|
|
29
|
+
- `inputValue?: string`
|
|
30
|
+
- `defaultInputValue?: string`
|
|
31
|
+
- `onValueChange?: (value, item, group) => void`
|
|
32
|
+
- `onInputValueChange?: (value) => void`
|
|
33
|
+
- `slotClassNames?` / `slotStyles?` for internal surface customization
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- Typing filters the popup list by item text.
|
|
38
|
+
- `Enter` commits the first filtered match.
|
|
39
|
+
- `ArrowDown` opens the popup.
|
|
40
|
+
- `ComboBox` is intentionally separate from `Dropdown`, which stays non-editable.
|
|
41
|
+
- For async or database-backed lookup, use [SearchBox](./SearchBox.md) instead of overloading `ComboBox`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# CommandButton
|
|
2
|
+
|
|
3
|
+
`CommandButton` is the standalone command-style button that shares the same interaction model and compact chrome as `ToolButton`, but does not require a `ToolBar` container.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<CommandButton icon="gear">&Run</CommandButton>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
With popup menu:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<CommandButton
|
|
15
|
+
icon="folder"
|
|
16
|
+
menuItems={[
|
|
17
|
+
{ id: "export-map", text: "Export &map" },
|
|
18
|
+
{ id: "export-log", text: "Export &log" }
|
|
19
|
+
]}
|
|
20
|
+
>
|
|
21
|
+
&Export
|
|
22
|
+
</CommandButton>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Key Props
|
|
26
|
+
|
|
27
|
+
- `icon?: NuGlyphName | ReactNode`
|
|
28
|
+
- `toggled?: boolean`
|
|
29
|
+
- `pressed?: boolean`
|
|
30
|
+
- `dropdown?: boolean`
|
|
31
|
+
- `menuItems?: MainMenuNode[]`
|
|
32
|
+
- `onMenuItemSelect?: (item: MainMenuItem) => void`
|
|
33
|
+
- `uncheckedShape?: "box" | "none"`
|
|
34
|
+
- `slotStyles`
|
|
35
|
+
- `slotClassNames`
|
|
36
|
+
- normal button props such as `onClick`, `disabled`, `type`
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
- if `menuItems` are provided, `CommandButton` opens `PopupMenu` automatically
|
|
41
|
+
- `dropdown` only controls the caret visual
|
|
42
|
+
- `menuItems` controls the actual popup behavior
|
|
43
|
+
- `toggled` is the preferred toggle-state prop name
|
|
44
|
+
- `pressed` remains supported as a legacy alias
|
|
45
|
+
- `ToolButton` and `ToolDropButton` are thin wrappers over the same command-button behavior
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# CrtGlitch
|
|
2
|
+
|
|
3
|
+
`NuCrtGlitch` is an opt-in ambient effect. It periodically applies a brief RGB-split/warp distortion to a single, randomly chosen control on the page — meant to be caught in peripheral vision, not watched directly.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Recommended — enable through the theme provider:
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<NuThemeProvider crtGlitch>
|
|
11
|
+
<NuDesktop appBar={<AppBar />}>
|
|
12
|
+
<App />
|
|
13
|
+
</NuDesktop>
|
|
14
|
+
</NuThemeProvider>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
With options:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<NuThemeProvider crtGlitch={{ intervalMs: 5000, topLevelRatio: 0.5 }}>
|
|
21
|
+
<App />
|
|
22
|
+
</NuThemeProvider>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Standalone, if not using `NuThemeProvider`'s `crtGlitch` prop:
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<NuCrtGlitch />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Key Props
|
|
32
|
+
|
|
33
|
+
- `enabled?: boolean`
|
|
34
|
+
default `true`. When `false`, the filter definitions stay mounted but inert — no pulses fire.
|
|
35
|
+
- `intervalMs?: number`
|
|
36
|
+
default `3000`. Average gap between pulses. The actual gap is jittered (0.6x-1.6x of this value) so pulses never fall into a detectable fixed cadence.
|
|
37
|
+
- `durationMs?: number`
|
|
38
|
+
default `2500`. Average length of a single pulse. Also jittered per pulse (0.7x-1.4x).
|
|
39
|
+
- `targetSelector?: string`
|
|
40
|
+
CSS selector for the pool of small leaf-control candidates (buttons, checkboxes, glyphs, rows...). Defaults to controls scoped under an open, non-minimized `.nu-window`.
|
|
41
|
+
- `topLevelRatio?: number`
|
|
42
|
+
default `1/3`. Fraction of pulses that target a whole open window instead of a small leaf control. Falls back to whichever pool actually has candidates if the rolled pool is empty (e.g. no windows open yet).
|
|
43
|
+
|
|
44
|
+
## Notes
|
|
45
|
+
|
|
46
|
+
- Opt-in and silent between pulses — the component only renders a hidden SVG `<filter>` definition, nothing visible on its own.
|
|
47
|
+
- No two pulses share the same noise seed, offsets, duration, or gap, so nothing about the effect repeats often enough to read as decorative.
|
|
48
|
+
- Designed to feel like a real, subtle fault rather than a demo effect: small controls glitch far more often than whole windows (see `topLevelRatio`), and offsets/intensity are re-rolled every pulse.
|
|
49
|
+
- Mount once, anywhere under `NuThemeProvider` (or once via the `crtGlitch` prop). A second instance is wasteful, not harmful.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Dashboard
|
|
2
|
+
|
|
3
|
+
`Dashboard` is a full-workspace static layout surface for persistent desktop content that lives behind managed windows inside `NuDesktop`.
|
|
4
|
+
|
|
5
|
+
It supports two static layout modes:
|
|
6
|
+
|
|
7
|
+
- `grid`: explicit CSS grid placement
|
|
8
|
+
- `lanes`: independent vertical columns
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
<Dashboard
|
|
14
|
+
gap={12}
|
|
15
|
+
laneCount={2}
|
|
16
|
+
items={[
|
|
17
|
+
{
|
|
18
|
+
id: "system",
|
|
19
|
+
lane: 1,
|
|
20
|
+
minHeight: "18rem",
|
|
21
|
+
content: <Panel title="System Core">...</Panel>
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "tools",
|
|
25
|
+
lane: 2,
|
|
26
|
+
minHeight: "18rem",
|
|
27
|
+
content: <Panel title="Workspace Tools">...</Panel>
|
|
28
|
+
}
|
|
29
|
+
]}
|
|
30
|
+
layout="lanes"
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Key Props
|
|
35
|
+
|
|
36
|
+
- `items: DashboardItem[]`
|
|
37
|
+
- `columnCount?: number`
|
|
38
|
+
- `layout?: "grid" | "lanes"`
|
|
39
|
+
- `laneCount?: number`
|
|
40
|
+
- `gap?: number`
|
|
41
|
+
- `fill?: boolean`
|
|
42
|
+
|
|
43
|
+
## DashboardItem
|
|
44
|
+
|
|
45
|
+
Each item describes static CSS grid placement plus render content:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
type DashboardItem = {
|
|
49
|
+
id: string | number;
|
|
50
|
+
lane?: number;
|
|
51
|
+
column?: string;
|
|
52
|
+
row?: string;
|
|
53
|
+
columnSpan?: number;
|
|
54
|
+
rowSpan?: number;
|
|
55
|
+
width?: string;
|
|
56
|
+
maxWidth?: string;
|
|
57
|
+
minWidth?: string;
|
|
58
|
+
minHeight?: string;
|
|
59
|
+
content: ReactNode;
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- `Dashboard` is a static layout surface, not a drag-and-resize layout engine.
|
|
66
|
+
- Managed `Window` instances still render above it through `NuWindowProvider`.
|
|
67
|
+
- Use it for always-present workspace panels, launch surfaces, inspectors, and dashboard-like control rooms.
|
|
68
|
+
- The control defaults to `fill`, so it is suitable as the direct child of `NuDesktop`.
|
|
69
|
+
- Grid rows use normal CSS content sizing, so panel height follows the child content unless you set explicit `minHeight`.
|
|
70
|
+
- `lanes` mode is useful when each column should stack by its own height, without waiting for taller cells in neighboring columns.
|
|
71
|
+
- In `lanes` mode you can also give an item an explicit `width` or `maxWidth` to avoid stretching it across the full lane.
|
|
72
|
+
- Panel content should usually be another ReactNU surface such as `Panel`, `Frame`, or `NuView`.
|
|
73
|
+
- If a product needs interactive rearrangement, `panelgrid` should be used directly by the host rather than hidden behind `Dashboard`.
|
package/docs/Desktop.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Desktop
|
|
2
|
+
|
|
3
|
+
`NuDesktop` is the top-level desktop shell. It renders a fixed full-screen workspace with three rows:
|
|
4
|
+
|
|
5
|
+
1. top menu area
|
|
6
|
+
2. central workspace
|
|
7
|
+
3. bottom app bar area
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<NuDesktop appBar={<SandboxAppBar />}>
|
|
13
|
+
<App />
|
|
14
|
+
</NuDesktop>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Key Props
|
|
18
|
+
|
|
19
|
+
- `children`
|
|
20
|
+
- `appBar?: ReactNode`
|
|
21
|
+
- `appBarContent?: ReactNode`
|
|
22
|
+
- standard `div` props
|
|
23
|
+
|
|
24
|
+
## Notes
|
|
25
|
+
|
|
26
|
+
- The desktop owns the browser viewport and is intended to behave like a bounded screen.
|
|
27
|
+
- `appBarContent` is kept as a compatibility alias, but `appBar` is the preferred entry point.
|