nfx-ui 0.28.0 → 0.29.0
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/README.en.md +12 -0
- package/README.md +4 -111
- package/dist/themes/index.css +1 -1
- package/package.json +1 -1
- package/src/themes/index.css +52 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# NFX-UI
|
|
2
|
+
|
|
3
|
+
[中文](README.md)
|
|
4
|
+
|
|
5
|
+
Shared React library for NebulaForgeX (theme, i18n, hooks). **Not** a standalone site. Hosts: Identity, Vault, News, Storages, Documentation.
|
|
6
|
+
|
|
7
|
+
Exports and host wiring: [NFX-Documentation chapter 7](https://github.com/NebulaForgeX/NFX-Documentation/blob/main/books/en/chapter-07-nfx-ui.md). Current **0.29.0**; hosts pin exactly `"nfx-ui": "0.29.0"`. No `file:` dual path.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
```
|
package/README.md
CHANGED
|
@@ -1,119 +1,12 @@
|
|
|
1
|
-
# NFX-UI
|
|
1
|
+
# NFX-UI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](README.en.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
NebulaForgeX 共享 React 库(主题、i18n、hooks)。**不是**独立站点。宿主:Identity、Vault、News、Storages、Documentation。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
宿主:Identity、Vault、Documentation、Storages。不含 LSR / PQTTEC / SJGZ。
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Install / 安装
|
|
14
|
-
|
|
15
|
-
Host apps use the local package:
|
|
16
|
-
|
|
17
|
-
宿主使用本地包:
|
|
18
|
-
|
|
19
|
-
```json
|
|
20
|
-
"nfx-ui": "file:../../NFX-UI"
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Peer versions follow PulsoLink-WEB (do not `ncu` past them independently):
|
|
24
|
-
|
|
25
|
-
对等依赖版本对齐 PulsoLink-WEB(不要单独 `ncu` 越过):
|
|
26
|
-
|
|
27
|
-
- `react` / `react-dom` `^19.2.8`
|
|
28
|
-
- `react-router` `^8.3.1` (not `react-router-dom`)
|
|
29
|
-
- `@radix-ui/themes` `^3.3.0`, `radix-ui` `^1.6.7`, `@radix-ui/react-icons` `^1.3.2`
|
|
30
|
-
- `lucide-react` `^1.41.0`
|
|
31
|
-
- `vite` `^8.2.2`, `typescript` `~6.0.3`
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## Host bootstrap / 宿主接入
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
import { LanguageEnum } from "nfx-ui/enums";
|
|
39
|
-
import { LanguageProvider, ThemeProvider, ModalProvider } from "nfx-ui/providers";
|
|
40
|
-
import { LayoutFrame, LayoutProvider, Sidebar, Header, Main, PageFrame } from "nfx-ui/layouts";
|
|
41
|
-
import { PreferencesPopover, ThemeSettings, PageHeader, EmptyState } from "nfx-ui/components";
|
|
42
|
-
import { usePreferenceStore } from "nfx-ui/stores";
|
|
43
|
-
import { configurePreferenceSync, useSyncPreference, useApplyPreferenceOnLoad } from "nfx-ui/hooks";
|
|
44
|
-
import { showInfo, showError, showSuccess, showConfirm } from "nfx-ui/stores";
|
|
45
|
-
import "@radix-ui/themes/styles.css";
|
|
46
|
-
import "nfx-ui/themes/fonts";
|
|
47
|
-
import "nfx-ui/themes/styles.css";
|
|
48
|
-
|
|
49
|
-
export function App() {
|
|
50
|
-
return (
|
|
51
|
-
<LanguageProvider getBuiltinBundles={getBuiltinI18nBundles}>
|
|
52
|
-
<ThemeProvider>
|
|
53
|
-
<LayoutProvider>
|
|
54
|
-
<ModalProvider>
|
|
55
|
-
<LayoutFrame items={menuItems}>{/* pages */}</LayoutFrame>
|
|
56
|
-
</ModalProvider>
|
|
57
|
-
</LayoutProvider>
|
|
58
|
-
</ThemeProvider>
|
|
59
|
-
</LanguageProvider>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
- `ThemeProvider` does **not** take `defaultTheme`. Theme lives on preference: `{ accent, gray, appearance, radius, scaling, panelBackground, fontFamily }`.
|
|
65
|
-
- `ThemeProvider` **不再**接收 `defaultTheme`。主题在 preference 的 theme 对象上。
|
|
66
|
-
- Fonts: import `"nfx-ui/themes/fonts"` (source, not bundled into every lib entry).
|
|
67
|
-
- 字体:`"nfx-ui/themes/fonts"`(源码入口,不要打进每个 lib chunk)。
|
|
68
|
-
- Page chrome: `PageFrame` + `PageHeader` (`icon` is required) + Radix `Card` / `Flex` / `Button` / `TextField`.
|
|
69
|
-
- 页面壳:`PageFrame` + `PageHeader`(必须有 `icon`)+ Radix 原语。
|
|
70
|
-
- Auth screens copy PulsoLink `AuthShell`. Theme/language UI is `PreferencesPopover` / `ThemeSettings`.
|
|
71
|
-
- 登录页拷 PulsoLink `AuthShell`。主题/语言用 `PreferencesPopover` / `ThemeSettings`。
|
|
72
|
-
- Queries: `useUnifiedQuery` / `useUnifiedInfiniteQuery` from `nfx-ui/hooks` (or `nfx-ui/utils`). Pages never call axios.
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
import { Button, TextField, Flex, Card } from "@radix-ui/themes";
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Modules / 模块
|
|
81
|
-
|
|
82
|
-
| Module | Contents |
|
|
83
|
-
|--------|----------|
|
|
84
|
-
| **enums** | Language, appearance, accent, radius, dashboard background |
|
|
85
|
-
| **providers** | ThemeProvider, LanguageProvider, ModalProvider |
|
|
86
|
-
| **themes** | Radix mappings, fonts, CSS |
|
|
87
|
-
| **languages** | i18n init, createI18nResources, labels |
|
|
88
|
-
| **layouts** | LayoutFrame, Sidebar (`react-pro-sidebar`), Header, Main, PageFrame, UserTopBar |
|
|
89
|
-
| **components** | PreferencesPopover, ThemeSettings, PageHeader, EmptyState, LucideIcon, Logo, VirtualList + Radix re-exports |
|
|
90
|
-
| **stores** | preference + modal (`showInfo` / `showSuccess` / `showError` / `showConfirm` / `showLoading`) |
|
|
91
|
-
| **hooks** | useUnifiedQuery, useSyncPreference, useApplyPreferenceOnLoad, configurePreferenceSync |
|
|
92
|
-
| **animations** | WaveBackground, ECGLoading, TruckLoading, … |
|
|
93
|
-
| **types / utils / constants** | Shared types and helpers |
|
|
94
|
-
|
|
95
|
-
`useTheme().setTheme` takes `Partial<ResolvedThemePreference>`. Preference persist key is `nfx-preference`.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Development / 开发
|
|
100
|
-
|
|
101
|
-
This repo is library-only. Build with `npm run build`. Output in `dist/`. Font CSS must not be injected into every lib entry.
|
|
102
|
-
|
|
103
|
-
本仓库仅库模式。`npm run build` 输出到 `dist/`。字体 CSS 不得注入每个入口。
|
|
7
|
+
接入与真实导出:[NFX-Documentation 第七章](https://github.com/NebulaForgeX/NFX-Documentation/blob/main/books/zh/chapter-07-nfx-ui.md)。当前 **0.29.0**,宿主精确钉 `"nfx-ui": "0.29.0"`。不要 `file:` 双路径。
|
|
104
8
|
|
|
105
9
|
```bash
|
|
106
10
|
npm install
|
|
107
11
|
npm run build
|
|
108
|
-
npm run lint
|
|
109
12
|
```
|
|
110
|
-
|
|
111
|
-
Test via host `file:../../NFX-UI`. Do not modify `Example/` (CityPulso PulsoLink is source of truth only).
|
|
112
|
-
|
|
113
|
-
用宿主 `file:../../NFX-UI` 验证。不要改 `Example/`(CityPulso PulsoLink 只作对照源)。
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## License
|
|
118
|
-
|
|
119
|
-
[MIT](LICENSE)
|
package/dist/themes/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth;scrollbar-gutter:stable;width:100%;min-height:100%}body{text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;min-height:100vh;margin:0}#root{min-height:100vh}main,section,article,aside,header,footer,nav{display:block}main{min-height:100%}h1,h2,h3,h4,h5,h6,p{margin:0}em,i{font-style:italic}abbr[title]{cursor:help;text-underline-offset:.18em;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}address{font-style:normal}blockquote{margin:0}sub,sup{vertical-align:baseline;position:relative}sub{bottom:-.25em}sup{top:-.5em}code,kbd,samp{padding:.12em .32em}pre{margin:0;overflow:auto}pre code{color:inherit;background:0 0;padding:0}a{text-decoration:none;transition:color .12s cubic-bezier(.2,0,0,1),opacity .12s cubic-bezier(.2,0,0,1)}a:focus-visible{outline:none}ul,ol,li,dl,dd{margin:0}img,picture,video,canvas,svg{max-width:100%;display:block}img{-webkit-user-select:none;user-select:none}svg{flex-shrink:0}audio{width:100%}iframe{border:0;max-width:100%;display:block}figure{margin:0}button,input,textarea,select{font:inherit;color:inherit}dialog:not(.rt-DialogContent){border:none}table{border-collapse:collapse;border-spacing:0;width:100%}caption,th,td{text-align:left}hr{border:none;height:1px;margin:0}fieldset{border:0;min-width:0;margin:0;padding:0}legend{padding:0}summary{cursor:pointer}progress,meter{width:100%}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{border-radius:999px}[hidden]{display:none!important}:focus-visible{outline:none}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:before,:after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}.radix-themes{--heading-font-family:var(--default-font-family);--strong-font-family:var(--default-font-family);--em-font-family:var(--default-font-family);--quote-font-family:var(--default-font-family);--radius-chip:max(var(--radius-3), var(--radius-full));--radius-icon:max(var(--radius-4), var(--radius-full))}.radix-themes .rt-BaseTabListTriggerInner,.radix-themes .rt-BaseTabListTriggerInnerHidden,.radix-themes .rt-TabsTriggerInner{border-radius:max(var(--tab-inner-border-radius), var(--radius-full))!important}.radix-themes[data-radius=full] .rt-Card{--card-border-radius:var(--radius-6)}.radix-themes,.radix-themes[data-font-family=system]{--default-font-family:system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif}.radix-themes[data-font-family=ibm-plex]{--default-font-family:"IBM Plex Sans", "IBM Plex Sans SC", "Noto Sans SC", "Noto Sans TC", system-ui, sans-serif}.radix-themes[data-font-family=noto]{--default-font-family:"Noto Sans", "Noto Sans SC", "Noto Sans TC", sans-serif}.radix-themes[data-font-family=source-sans]{--default-font-family:"Source Sans 3", "Source Han Sans SC", "Noto Sans SC", "Noto Sans TC", sans-serif}.radix-themes{--color-primary:var(--accent-9);--color-primary-hover:var(--accent-10);--color-primary-light:var(--accent-4);--color-primary-bg:var(--accent-3);--color-primary-fg:var(--accent-contrast);--color-success:var(--green-9);--color-success-light:var(--green-4);--color-info:var(--blue-9);--color-info-light:var(--blue-4);--color-warning:var(--amber-9);--color-warning-light:var(--amber-4);--color-danger:var(--red-9);--color-error:var(--red-9);--color-danger-light:var(--red-4);--color-bg:var(--color-background);--color-bg-1:var(--color-background);--color-bg-2:var(--color-panel-solid);--color-bg-3:var(--gray-3);--color-bg-4:var(--gray-4);--color-bg-secondary:var(--gray-2);--color-border:var(--gray-6);--color-border-2:var(--gray-5);--color-border-3:var(--gray-6);--color-border-4:var(--gray-7);--color-border-5:var(--gray-8);--color-border-hover:var(--gray-8);--color-fg:var(--gray-11);--color-fg-text:var(--gray-12);--color-fg-heading:var(--gray-12);--color-fg-highlight:var(--accent-11);--color-fg-muted:var(--gray-10);--color-fg-on-primary:var(--accent-contrast);--color-separator:var(--gray-6);--color-overlay:var(--black-a6);--color-shadow:var(--gray-a4);--color-ring:var(--accent-8)}
|
|
1
|
+
*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth;scrollbar-gutter:stable;width:100%;min-height:100%}body{text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;min-height:100vh;margin:0}#root{min-height:100vh}main,section,article,aside,header,footer,nav{display:block}main{min-height:100%}h1,h2,h3,h4,h5,h6,p{margin:0}em,i{font-style:italic}abbr[title]{cursor:help;text-underline-offset:.18em;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}address{font-style:normal}blockquote{margin:0}sub,sup{vertical-align:baseline;position:relative}sub{bottom:-.25em}sup{top:-.5em}code,kbd,samp{padding:.12em .32em}pre{margin:0;overflow:auto}pre code{color:inherit;background:0 0;padding:0}a{text-decoration:none;transition:color .12s cubic-bezier(.2,0,0,1),opacity .12s cubic-bezier(.2,0,0,1)}a:focus-visible{outline:none}ul,ol,li,dl,dd{margin:0}img,picture,video,canvas,svg{max-width:100%;display:block}img{-webkit-user-select:none;user-select:none}svg{flex-shrink:0}audio{width:100%}iframe{border:0;max-width:100%;display:block}figure{margin:0}button,input,textarea,select{font:inherit;color:inherit}dialog:not(.rt-DialogContent){border:none}table{border-collapse:collapse;border-spacing:0;width:100%}caption,th,td{text-align:left}hr{border:none;height:1px;margin:0}fieldset{border:0;min-width:0;margin:0;padding:0}legend{padding:0}summary{cursor:pointer}progress,meter{width:100%}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{border-radius:999px}[hidden]{display:none!important}:focus-visible{outline:none}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:before,:after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}.radix-themes{--heading-font-family:var(--default-font-family);--strong-font-family:var(--default-font-family);--em-font-family:var(--default-font-family);--quote-font-family:var(--default-font-family);--radius-chip:max(var(--radius-3), var(--radius-full));--radius-icon:max(var(--radius-4), var(--radius-full))}.radix-themes .rt-BaseTabListTriggerInner,.radix-themes .rt-BaseTabListTriggerInnerHidden,.radix-themes .rt-TabsTriggerInner{border-radius:max(var(--tab-inner-border-radius), var(--radius-full))!important}.radix-themes .rt-BaseTabListTrigger:before{content:"";background-color:var(--accent-indicator);transform-origin:50%;pointer-events:none;height:2px;transition:transform .22s cubic-bezier(.22,1,.36,1);position:absolute;bottom:0;left:0;right:0;transform:scaleX(0)}.radix-themes .rt-BaseTabListTrigger[data-state=active]:before,.radix-themes .rt-BaseTabListTrigger[data-active]:before{transform:scaleX(1)}.radix-themes .rt-BaseTabListTrigger[data-state=active] .rt-BaseTabListTriggerInner,.radix-themes .rt-BaseTabListTrigger[data-active] .rt-BaseTabListTriggerInner{font-weight:var(--font-weight-bold);background-color:#0000}@media (hover:hover){.radix-themes .rt-BaseTabListTrigger:hover:before{transform:scaleX(1)}.radix-themes :where(.rt-BaseTabListTrigger:hover:not([data-state=active]):not([data-active])) :where(.rt-BaseTabListTriggerInner){background-color:var(--accent-a3);color:var(--accent-11)}.radix-themes .rt-BaseTabListTrigger[data-state=active]:hover .rt-BaseTabListTriggerInner,.radix-themes .rt-BaseTabListTrigger[data-active]:hover .rt-BaseTabListTriggerInner{background-color:#0000}}@media (prefers-reduced-motion:reduce){.radix-themes .rt-BaseTabListTrigger:before{transition:none}}.radix-themes[data-radius=full] .rt-Card{--card-border-radius:var(--radius-6)}.radix-themes,.radix-themes[data-font-family=system]{--default-font-family:system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif}.radix-themes[data-font-family=ibm-plex]{--default-font-family:"IBM Plex Sans", "IBM Plex Sans SC", "Noto Sans SC", "Noto Sans TC", system-ui, sans-serif}.radix-themes[data-font-family=noto]{--default-font-family:"Noto Sans", "Noto Sans SC", "Noto Sans TC", sans-serif}.radix-themes[data-font-family=source-sans]{--default-font-family:"Source Sans 3", "Source Han Sans SC", "Noto Sans SC", "Noto Sans TC", sans-serif}.radix-themes{--color-primary:var(--accent-9);--color-primary-hover:var(--accent-10);--color-primary-light:var(--accent-4);--color-primary-bg:var(--accent-3);--color-primary-fg:var(--accent-contrast);--color-success:var(--green-9);--color-success-light:var(--green-4);--color-info:var(--blue-9);--color-info-light:var(--blue-4);--color-warning:var(--amber-9);--color-warning-light:var(--amber-4);--color-danger:var(--red-9);--color-error:var(--red-9);--color-danger-light:var(--red-4);--color-bg:var(--color-background);--color-bg-1:var(--color-background);--color-bg-2:var(--color-panel-solid);--color-bg-3:var(--gray-3);--color-bg-4:var(--gray-4);--color-bg-secondary:var(--gray-2);--color-border:var(--gray-6);--color-border-2:var(--gray-5);--color-border-3:var(--gray-6);--color-border-4:var(--gray-7);--color-border-5:var(--gray-8);--color-border-hover:var(--gray-8);--color-fg:var(--gray-11);--color-fg-text:var(--gray-12);--color-fg-heading:var(--gray-12);--color-fg-highlight:var(--accent-11);--color-fg-muted:var(--gray-10);--color-fg-on-primary:var(--accent-contrast);--color-separator:var(--gray-6);--color-overlay:var(--black-a6);--color-shadow:var(--gray-a4);--color-ring:var(--accent-8)}
|
package/package.json
CHANGED
package/src/themes/index.css
CHANGED
|
@@ -319,6 +319,58 @@ meter {
|
|
|
319
319
|
border-radius: max(var(--tab-inner-border-radius), var(--radius-full)) !important;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
/*
|
|
323
|
+
* Tabs hover: PulsoLink-WEB pattern. Radix paints both the active underline
|
|
324
|
+
* (::before) and TabsTriggerInner, which reads as two color layers. Keep the
|
|
325
|
+
* bar; only fill the inner on inactive hover. Active hover stays underline-only.
|
|
326
|
+
*/
|
|
327
|
+
.radix-themes .rt-BaseTabListTrigger::before {
|
|
328
|
+
content: "";
|
|
329
|
+
height: 2px;
|
|
330
|
+
position: absolute;
|
|
331
|
+
bottom: 0;
|
|
332
|
+
left: 0;
|
|
333
|
+
right: 0;
|
|
334
|
+
background-color: var(--accent-indicator);
|
|
335
|
+
transform: scaleX(0);
|
|
336
|
+
transform-origin: center;
|
|
337
|
+
transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
|
|
338
|
+
pointer-events: none;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.radix-themes .rt-BaseTabListTrigger[data-state="active"]::before,
|
|
342
|
+
.radix-themes .rt-BaseTabListTrigger[data-active]::before {
|
|
343
|
+
transform: scaleX(1);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.radix-themes .rt-BaseTabListTrigger[data-state="active"] .rt-BaseTabListTriggerInner,
|
|
347
|
+
.radix-themes .rt-BaseTabListTrigger[data-active] .rt-BaseTabListTriggerInner {
|
|
348
|
+
font-weight: var(--font-weight-bold);
|
|
349
|
+
background-color: transparent;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@media (hover: hover) {
|
|
353
|
+
.radix-themes .rt-BaseTabListTrigger:hover::before {
|
|
354
|
+
transform: scaleX(1);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.radix-themes :where(.rt-BaseTabListTrigger:hover:not([data-state="active"]):not([data-active])) :where(.rt-BaseTabListTriggerInner) {
|
|
358
|
+
background-color: var(--accent-a3);
|
|
359
|
+
color: var(--accent-11);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.radix-themes .rt-BaseTabListTrigger[data-state="active"]:hover .rt-BaseTabListTriggerInner,
|
|
363
|
+
.radix-themes .rt-BaseTabListTrigger[data-active]:hover .rt-BaseTabListTriggerInner {
|
|
364
|
+
background-color: transparent;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
@media (prefers-reduced-motion: reduce) {
|
|
369
|
+
.radix-themes .rt-BaseTabListTrigger::before {
|
|
370
|
+
transition: none;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
322
374
|
.radix-themes[data-radius="full"] .rt-Card {
|
|
323
375
|
--card-border-radius: var(--radius-6);
|
|
324
376
|
}
|