@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 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
- | `links` | `Array<{ label, href }>` | Placeholder links | Navigation links rendered in the center. |
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
- * Defaults to a few placeholder
35
- * links.
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
- * import { ThemeNavBar } from 'evolution-theme-engine';
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: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
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: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
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);
@@ -219,6 +219,7 @@ html {
219
219
  font-size: 1.1rem;
220
220
  font-weight: 700;
221
221
  color: var(--color-text);
222
+ text-decoration: none;
222
223
  white-space: nowrap;
223
224
  flex-shrink: 0;
224
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolution-james/evolution-theme-engine",
3
- "version": "1.0.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
- * Defaults to a few placeholder
26
- * links.
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
- * import { ThemeNavBar } from 'evolution-theme-engine';
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
- <span className="etn-navbar-brand">{title}</span>
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
- <a href={href} className="etn-navbar-link">
76
- {label}
77
- </a>
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>
@@ -219,6 +219,7 @@ html {
219
219
  font-size: 1.1rem;
220
220
  font-weight: 700;
221
221
  color: var(--color-text);
222
+ text-decoration: none;
222
223
  white-space: nowrap;
223
224
  flex-shrink: 0;
224
225
  }