@evolution-james/evolution-theme-engine 1.0.0 → 1.0.1
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.md +33 -1
- package/dist/components/ThemeNavBar.js +55 -9
- package/dist/styles/themes.css +1 -0
- package/package.json +1 -1
- package/src/components/ThemeNavBar.jsx +56 -11
- package/src/styles/themes.css +1 -0
package/README.md
CHANGED
|
@@ -74,7 +74,33 @@ function MyHeader() {
|
|
|
74
74
|
|
|
75
75
|
Use this when you want a complete, ready-made navbar with the theme selector pre-rendered inside it.
|
|
76
76
|
|
|
77
|
+
**Multi-page app** (standard `<a>` tags, full navigation):
|
|
78
|
+
|
|
79
|
+
```jsx
|
|
80
|
+
import { ThemeNavBar } from '@evolution-james/evolution-theme-engine';
|
|
81
|
+
|
|
82
|
+
function App() {
|
|
83
|
+
return (
|
|
84
|
+
<>
|
|
85
|
+
<ThemeNavBar
|
|
86
|
+
title="My App"
|
|
87
|
+
titleHref="/"
|
|
88
|
+
links={[
|
|
89
|
+
{ label: 'Home', href: '/' },
|
|
90
|
+
{ label: 'About', href: '/about' },
|
|
91
|
+
{ label: 'Contact', href: '/contact' },
|
|
92
|
+
]}
|
|
93
|
+
/>
|
|
94
|
+
{/* rest of your app */}
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Single-page app with React Router** (no page refreshes):
|
|
101
|
+
|
|
77
102
|
```jsx
|
|
103
|
+
import { Link } from 'react-router-dom';
|
|
78
104
|
import { ThemeNavBar } from '@evolution-james/evolution-theme-engine';
|
|
79
105
|
|
|
80
106
|
function App() {
|
|
@@ -82,11 +108,15 @@ function App() {
|
|
|
82
108
|
<>
|
|
83
109
|
<ThemeNavBar
|
|
84
110
|
title="My App"
|
|
111
|
+
titleHref="/"
|
|
85
112
|
links={[
|
|
86
113
|
{ label: 'Home', href: '/' },
|
|
87
114
|
{ label: 'About', href: '/about' },
|
|
88
115
|
{ label: 'Contact', href: '/contact' },
|
|
89
116
|
]}
|
|
117
|
+
renderLink={(props) => (
|
|
118
|
+
<Link to={props.href} className={props.className}>{props.children}</Link>
|
|
119
|
+
)}
|
|
90
120
|
/>
|
|
91
121
|
{/* rest of your app */}
|
|
92
122
|
</>
|
|
@@ -318,7 +348,9 @@ registerTheme('ocean', {
|
|
|
318
348
|
| Prop | Type | Default | Description |
|
|
319
349
|
|---|---|---|---|
|
|
320
350
|
| `title` | `string` | `'My App'` | Brand text shown on the left of the navbar. |
|
|
321
|
-
| `
|
|
351
|
+
| `titleHref` | `string` | `undefined` | If provided, the brand text becomes a link pointing to this URL. Omit to render a plain `<span>`. |
|
|
352
|
+
| `links` | `Array<{ label, href, onClick? }>` | Placeholder links | Navigation links rendered in the center. If an entry includes `onClick`, the default browser navigation is prevented and `onClick` is called instead — use this for SPA navigation (e.g. React Router's `navigate()`). |
|
|
353
|
+
| `renderLink` | `(props) => ReactNode` | `undefined` | Render prop for full control over link rendering. `props` contains `href`, `children`, and `className`. Applied to both the title link and all nav links. Use this for React Router: return `<Link to={props.href} className={props.className}>{props.children}</Link>`. Takes precedence over individual `onClick` handlers. |
|
|
322
354
|
| `themes` | `object` | All 5 built-in themes | Forwarded to the internal `<ThemeSelector>`. |
|
|
323
355
|
| `className` | `string` | `''` | Extra CSS classes added to the `<nav>` (alongside `etn-navbar`). |
|
|
324
356
|
| `style` | `object` | `{}` | Inline styles for the `<nav>`. |
|
|
@@ -28,11 +28,24 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
28
28
|
* title (string) — Brand/title text shown on the
|
|
29
29
|
* left side of the navbar.
|
|
30
30
|
* Defaults to 'My App'.
|
|
31
|
+
* titleHref (string) — If provided, wraps the brand
|
|
32
|
+
* text in a link pointing to this
|
|
33
|
+
* URL. Omit to render a plain <span>.
|
|
31
34
|
* links (Array<object>) — Navigation links rendered to
|
|
32
35
|
* the right of the title. Each
|
|
33
|
-
* entry: { label, href }.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
+
* entry: { label, href, onClick? }.
|
|
37
|
+
* If onClick is provided, the default
|
|
38
|
+
* browser navigation is prevented and
|
|
39
|
+
* onClick is called instead — use this
|
|
40
|
+
* for programmatic SPA navigation.
|
|
41
|
+
* Defaults to a few placeholder links.
|
|
42
|
+
* renderLink (function) — Optional render prop for full
|
|
43
|
+
* control over link rendering. Useful
|
|
44
|
+
* for React Router: pass a function
|
|
45
|
+
* ({ href, children, className }) =>
|
|
46
|
+
* ReactNode and return a <Link>
|
|
47
|
+
* component. Applied to both the
|
|
48
|
+
* title link and all nav links.
|
|
36
49
|
* themes (object) — Forwarded to <ThemeSelector>.
|
|
37
50
|
* Defaults to all 5 built-in themes.
|
|
38
51
|
* className (string) — Extra class(es) added to the
|
|
@@ -40,15 +53,29 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
40
53
|
* 'etn-navbar'.
|
|
41
54
|
* style (object) — Inline styles for the root <nav>.
|
|
42
55
|
*
|
|
43
|
-
* Usage:
|
|
44
|
-
*
|
|
56
|
+
* Usage — plain HTML (multi-page app):
|
|
57
|
+
* <ThemeNavBar
|
|
58
|
+
* title="My Cool App"
|
|
59
|
+
* titleHref="/"
|
|
60
|
+
* links={[
|
|
61
|
+
* { label: 'Home', href: '/' },
|
|
62
|
+
* { label: 'About', href: '/about' },
|
|
63
|
+
* ]}
|
|
64
|
+
* />
|
|
65
|
+
*
|
|
66
|
+
* Usage — React Router (SPA, no page refreshes):
|
|
67
|
+
* import { Link } from 'react-router-dom';
|
|
45
68
|
*
|
|
46
69
|
* <ThemeNavBar
|
|
47
70
|
* title="My Cool App"
|
|
71
|
+
* titleHref="/"
|
|
48
72
|
* links={[
|
|
49
73
|
* { label: 'Home', href: '/' },
|
|
50
74
|
* { label: 'About', href: '/about' },
|
|
51
75
|
* ]}
|
|
76
|
+
* renderLink={(props) => (
|
|
77
|
+
* <Link to={props.href} className={props.className}>{props.children}</Link>
|
|
78
|
+
* )}
|
|
52
79
|
* />
|
|
53
80
|
* ============================================================
|
|
54
81
|
*/
|
|
@@ -66,28 +93,47 @@ var DEFAULT_LINKS = [{
|
|
|
66
93
|
function ThemeNavBar(_ref) {
|
|
67
94
|
var _ref$title = _ref.title,
|
|
68
95
|
title = _ref$title === void 0 ? 'My App' : _ref$title,
|
|
96
|
+
titleHref = _ref.titleHref,
|
|
69
97
|
_ref$links = _ref.links,
|
|
70
98
|
links = _ref$links === void 0 ? DEFAULT_LINKS : _ref$links,
|
|
71
99
|
themes = _ref.themes,
|
|
72
100
|
_ref$className = _ref.className,
|
|
73
101
|
className = _ref$className === void 0 ? '' : _ref$className,
|
|
74
102
|
_ref$style = _ref.style,
|
|
75
|
-
style = _ref$style === void 0 ? {} : _ref$style
|
|
103
|
+
style = _ref$style === void 0 ? {} : _ref$style,
|
|
104
|
+
renderLink = _ref.renderLink;
|
|
76
105
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("nav", {
|
|
77
106
|
className: "etn-navbar".concat(className ? " ".concat(className) : ''),
|
|
78
107
|
style: style,
|
|
79
|
-
children: [
|
|
108
|
+
children: [titleHref ? renderLink ? renderLink({
|
|
109
|
+
href: titleHref,
|
|
110
|
+
children: title,
|
|
111
|
+
className: 'etn-navbar-brand'
|
|
112
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
|
|
113
|
+
href: titleHref,
|
|
114
|
+
className: "etn-navbar-brand",
|
|
115
|
+
children: title
|
|
116
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
80
117
|
className: "etn-navbar-brand",
|
|
81
118
|
children: title
|
|
82
119
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
|
|
83
120
|
className: "etn-navbar-links",
|
|
84
121
|
children: links.map(function (_ref2) {
|
|
85
122
|
var label = _ref2.label,
|
|
86
|
-
href = _ref2.href
|
|
123
|
+
href = _ref2.href,
|
|
124
|
+
onClick = _ref2.onClick;
|
|
87
125
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
88
|
-
children:
|
|
126
|
+
children: renderLink ? renderLink({
|
|
127
|
+
href: href,
|
|
128
|
+
children: label,
|
|
129
|
+
className: 'etn-navbar-link'
|
|
130
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
|
|
89
131
|
href: href,
|
|
90
132
|
className: "etn-navbar-link",
|
|
133
|
+
onClick: onClick ? function (e) {
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
onClick(e);
|
|
136
|
+
} : undefined,
|
|
91
137
|
children: label
|
|
92
138
|
})
|
|
93
139
|
}, label);
|
package/dist/styles/themes.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolution-james/evolution-theme-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A plug-and-play React theme engine with CSS variable-based theming, localStorage persistence, and optional navbar component.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -19,11 +19,24 @@
|
|
|
19
19
|
* title (string) — Brand/title text shown on the
|
|
20
20
|
* left side of the navbar.
|
|
21
21
|
* Defaults to 'My App'.
|
|
22
|
+
* titleHref (string) — If provided, wraps the brand
|
|
23
|
+
* text in a link pointing to this
|
|
24
|
+
* URL. Omit to render a plain <span>.
|
|
22
25
|
* links (Array<object>) — Navigation links rendered to
|
|
23
26
|
* the right of the title. Each
|
|
24
|
-
* entry: { label, href }.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
+
* entry: { label, href, onClick? }.
|
|
28
|
+
* If onClick is provided, the default
|
|
29
|
+
* browser navigation is prevented and
|
|
30
|
+
* onClick is called instead — use this
|
|
31
|
+
* for programmatic SPA navigation.
|
|
32
|
+
* Defaults to a few placeholder links.
|
|
33
|
+
* renderLink (function) — Optional render prop for full
|
|
34
|
+
* control over link rendering. Useful
|
|
35
|
+
* for React Router: pass a function
|
|
36
|
+
* ({ href, children, className }) =>
|
|
37
|
+
* ReactNode and return a <Link>
|
|
38
|
+
* component. Applied to both the
|
|
39
|
+
* title link and all nav links.
|
|
27
40
|
* themes (object) — Forwarded to <ThemeSelector>.
|
|
28
41
|
* Defaults to all 5 built-in themes.
|
|
29
42
|
* className (string) — Extra class(es) added to the
|
|
@@ -31,15 +44,29 @@
|
|
|
31
44
|
* 'etn-navbar'.
|
|
32
45
|
* style (object) — Inline styles for the root <nav>.
|
|
33
46
|
*
|
|
34
|
-
* Usage:
|
|
35
|
-
*
|
|
47
|
+
* Usage — plain HTML (multi-page app):
|
|
48
|
+
* <ThemeNavBar
|
|
49
|
+
* title="My Cool App"
|
|
50
|
+
* titleHref="/"
|
|
51
|
+
* links={[
|
|
52
|
+
* { label: 'Home', href: '/' },
|
|
53
|
+
* { label: 'About', href: '/about' },
|
|
54
|
+
* ]}
|
|
55
|
+
* />
|
|
56
|
+
*
|
|
57
|
+
* Usage — React Router (SPA, no page refreshes):
|
|
58
|
+
* import { Link } from 'react-router-dom';
|
|
36
59
|
*
|
|
37
60
|
* <ThemeNavBar
|
|
38
61
|
* title="My Cool App"
|
|
62
|
+
* titleHref="/"
|
|
39
63
|
* links={[
|
|
40
64
|
* { label: 'Home', href: '/' },
|
|
41
65
|
* { label: 'About', href: '/about' },
|
|
42
66
|
* ]}
|
|
67
|
+
* renderLink={(props) => (
|
|
68
|
+
* <Link to={props.href} className={props.className}>{props.children}</Link>
|
|
69
|
+
* )}
|
|
43
70
|
* />
|
|
44
71
|
* ============================================================
|
|
45
72
|
*/
|
|
@@ -55,26 +82,44 @@ const DEFAULT_LINKS = [
|
|
|
55
82
|
|
|
56
83
|
export function ThemeNavBar({
|
|
57
84
|
title = 'My App',
|
|
85
|
+
titleHref,
|
|
58
86
|
links = DEFAULT_LINKS,
|
|
59
87
|
themes,
|
|
60
88
|
className = '',
|
|
61
89
|
style = {},
|
|
90
|
+
renderLink,
|
|
62
91
|
}) {
|
|
63
92
|
return (
|
|
64
93
|
<nav
|
|
65
94
|
className={`etn-navbar${className ? ` ${className}` : ''}`}
|
|
66
95
|
style={style}
|
|
67
96
|
>
|
|
68
|
-
{/* Left side: brand/title */}
|
|
69
|
-
|
|
97
|
+
{/* Left side: brand/title — link if titleHref is set, plain span otherwise */}
|
|
98
|
+
{titleHref ? (
|
|
99
|
+
renderLink ? (
|
|
100
|
+
renderLink({ href: titleHref, children: title, className: 'etn-navbar-brand' })
|
|
101
|
+
) : (
|
|
102
|
+
<a href={titleHref} className="etn-navbar-brand">{title}</a>
|
|
103
|
+
)
|
|
104
|
+
) : (
|
|
105
|
+
<span className="etn-navbar-brand">{title}</span>
|
|
106
|
+
)}
|
|
70
107
|
|
|
71
108
|
{/* Center: navigation links */}
|
|
72
109
|
<ul className="etn-navbar-links">
|
|
73
|
-
{links.map(({ label, href }) => (
|
|
110
|
+
{links.map(({ label, href, onClick }) => (
|
|
74
111
|
<li key={label}>
|
|
75
|
-
|
|
76
|
-
{label}
|
|
77
|
-
|
|
112
|
+
{renderLink ? (
|
|
113
|
+
renderLink({ href, children: label, className: 'etn-navbar-link' })
|
|
114
|
+
) : (
|
|
115
|
+
<a
|
|
116
|
+
href={href}
|
|
117
|
+
className="etn-navbar-link"
|
|
118
|
+
onClick={onClick ? (e) => { e.preventDefault(); onClick(e); } : undefined}
|
|
119
|
+
>
|
|
120
|
+
{label}
|
|
121
|
+
</a>
|
|
122
|
+
)}
|
|
78
123
|
</li>
|
|
79
124
|
))}
|
|
80
125
|
</ul>
|