init
This commit is contained in:
commit
a5bd51d572
25 changed files with 3198 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules/
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# supMDX-nav
|
||||
Nav component for supMDX
|
15
dist/Nav.d.ts
vendored
Normal file
15
dist/Nav.d.ts
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import type { NavEntryInfo } from './NavEntry';
|
||||
import { HeadingInfo } from './NavBase';
|
||||
import { NavHeaderConfig } from './NavHeader';
|
||||
export type NavConfig = {
|
||||
site: NavHeaderConfig;
|
||||
nav: NavEntryInfo[];
|
||||
};
|
||||
export type NavProps = {
|
||||
children?: React.ReactNode;
|
||||
headings: HeadingInfo[];
|
||||
pathname: string;
|
||||
config: NavConfig;
|
||||
};
|
||||
export declare function Nav({ config, children, ...props }: NavProps): JSX.Element;
|
26
dist/Nav.jsx
vendored
Normal file
26
dist/Nav.jsx
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
"use strict";
|
||||
'use client';
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var react_1 = require("react");
|
||||
var NavBase_1 = require("./NavBase");
|
||||
var NavHeader_1 = require("./NavHeader");
|
||||
function Nav(_a) {
|
||||
var config = _a.config, children = _a.children, props = __rest(_a, ["config", "children"]);
|
||||
var _b = (0, react_1.useState)(false), navFold = _b[0], setNavFold = _b[1];
|
||||
return (<NavBase_1.NavBase className={navFold ? 'open' : ''} entries={config.nav} {...props}>
|
||||
<NavHeader_1.NavHeader config={config.site} onToggleFold={function () { return setNavFold(function (e) { return !e; }); }}/>
|
||||
{children}
|
||||
</NavBase_1.NavBase>);
|
||||
}
|
||||
exports.default = Nav;
|
15
dist/NavBase.d.ts
vendored
Normal file
15
dist/NavBase.d.ts
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import { NavEntryInfo } from './NavEntry';
|
||||
export type HeadingInfo = {
|
||||
tagName: string;
|
||||
label: string;
|
||||
id: string;
|
||||
};
|
||||
export type NavBaseProps = {
|
||||
children?: React.ReactNode;
|
||||
headings: HeadingInfo[];
|
||||
pathname: string;
|
||||
entries: NavEntryInfo[];
|
||||
className?: string;
|
||||
};
|
||||
export declare function NavBase({ children, headings, pathname, entries, className, }: NavBaseProps): JSX.Element;
|
22
dist/NavBase.jsx
vendored
Normal file
22
dist/NavBase.jsx
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
'use client';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NavBase = void 0;
|
||||
var NavEntry_1 = require("./NavEntry");
|
||||
function NavBase(_a) {
|
||||
var children = _a.children, headings = _a.headings, pathname = _a.pathname, entries = _a.entries, className = _a.className;
|
||||
var headingsJSX = <ul className=''>{headings.map(function (_a) {
|
||||
var label = _a.label, id = _a.id;
|
||||
return <li key={id}>
|
||||
<a href={'#' + id}>{label}</a>
|
||||
</li>;
|
||||
})}</ul>;
|
||||
return <nav className={className}>
|
||||
{children}
|
||||
<div className='nav-root'>
|
||||
{entries.map(function (entry) { return <NavEntry_1.NavEntry key={entry.link} entry={entry} dir={'/'} here={pathname}/>; })}
|
||||
{headingsJSX}
|
||||
</div>
|
||||
</nav>;
|
||||
}
|
||||
exports.NavBase = NavBase;
|
12
dist/NavEntry.d.ts
vendored
Normal file
12
dist/NavEntry.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
/// <reference types="react" />
|
||||
export type NavEntryInfo = {
|
||||
label: string;
|
||||
link: string;
|
||||
children?: NavEntryInfo[];
|
||||
};
|
||||
export declare function NavEntry<Body>({ entry: { label, link, children }, dir, here, children: childrenJSX, }: {
|
||||
entry: NavEntryInfo;
|
||||
dir: string;
|
||||
here: string;
|
||||
children?: Body;
|
||||
}): JSX.Element;
|
25
dist/NavEntry.jsx
vendored
Normal file
25
dist/NavEntry.jsx
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
"use strict";
|
||||
'use client';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NavEntry = void 0;
|
||||
var react_1 = require("react");
|
||||
var link_1 = require("next/link");
|
||||
function NavEntry(_a) {
|
||||
var _b = _a.entry, label = _b.label, link = _b.link, children = _b.children, dir = _a.dir, here = _a.here, childrenJSX = _a.children;
|
||||
var href = dir + link;
|
||||
var isHere = href.replace(/\/$/, '') === here; // remove trailing slash
|
||||
var isRHere = isHere || here.startsWith(href); // here or is children
|
||||
var _c = (0, react_1.useState)(isRHere), toggle = _c[0], setToggle = _c[1];
|
||||
var entryCls = 'nav-entry' + (isHere ? ' nav-here' : '');
|
||||
return (children === null || children === void 0 ? void 0 : children.length) ? <div className={'nav-dir' + (toggle ? ' nav-fold-open' : '')}><>
|
||||
<div className={entryCls}>
|
||||
<link_1.default href={href}>{label}</link_1.default>
|
||||
<svg viewBox="0 0 8 8" onClick={function () { return setToggle(function (e) { return !e; }); }}><polyline points="6 3 4 5 2 3"></polyline></svg>
|
||||
</div>
|
||||
{isHere ? childrenJSX : <></>}
|
||||
<div className='nav-dir-child'>{children.map(function (entry) { return <NavEntry key={entry.link} entry={entry} dir={href} here={here}>{childrenJSX}</NavEntry>; })}</div>
|
||||
</></div> : <div className={entryCls}>
|
||||
<link_1.default href={href}>{label}</link_1.default>
|
||||
</div>;
|
||||
}
|
||||
exports.NavEntry = NavEntry;
|
16
dist/NavHeader.d.ts
vendored
Normal file
16
dist/NavHeader.d.ts
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
/// <reference types="react" />
|
||||
export type NavHeaderConfig = {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
icon?: string | {
|
||||
href: string;
|
||||
alt?: string;
|
||||
size?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
};
|
||||
export declare function NavHeader({ config, onToggleFold }: {
|
||||
config: NavHeaderConfig;
|
||||
onToggleFold?: () => void;
|
||||
}): JSX.Element;
|
22
dist/NavHeader.jsx
vendored
Normal file
22
dist/NavHeader.jsx
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
'use client';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NavHeader = void 0;
|
||||
var link_1 = require("next/link");
|
||||
function NavHeader(_a) {
|
||||
var _b, _c, _d, _e, _f;
|
||||
var config = _a.config, onToggleFold = _a.onToggleFold;
|
||||
var title = config.title, subtitle = config.subtitle, icon0 = config.icon;
|
||||
var icon = typeof icon0 === 'string' ? { href: icon0 } : icon0;
|
||||
return <header>
|
||||
<link_1.default href="/" id="icon-link">
|
||||
<img className="icon" src={icon === null || icon === void 0 ? void 0 : icon.href} alt={(_b = icon === null || icon === void 0 ? void 0 : icon.alt) !== null && _b !== void 0 ? _b : 'icon'} width={(_d = (_c = icon === null || icon === void 0 ? void 0 : icon.width) !== null && _c !== void 0 ? _c : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _d !== void 0 ? _d : 96} height={(_f = (_e = icon === null || icon === void 0 ? void 0 : icon.height) !== null && _e !== void 0 ? _e : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _f !== void 0 ? _f : 96}/>
|
||||
<div className="icon-text">
|
||||
<div>{title}</div>
|
||||
<div>{subtitle}</div>
|
||||
</div>
|
||||
</link_1.default>
|
||||
<div className="menu-toggle" onClick={onToggleFold}/>
|
||||
</header>;
|
||||
}
|
||||
exports.NavHeader = NavHeader;
|
4
dist/index.d.ts
vendored
Normal file
4
dist/index.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
export * from './Nav';
|
||||
export * from './NavBase';
|
||||
export * from './NavEntry';
|
||||
export * from './NavHeader';
|
97
dist/index.esm.js
vendored
Normal file
97
dist/index.esm.js
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
var __assign = function() {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
|
||||
function __rest(s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function NavEntry(_a) {
|
||||
var _b = _a.entry, label = _b.label, link = _b.link, children = _b.children, dir = _a.dir, here = _a.here, childrenJSX = _a.children;
|
||||
var href = dir + link;
|
||||
var isHere = href.replace(/\/$/, '') === here; // remove trailing slash
|
||||
var isRHere = isHere || here.startsWith(href); // here or is children
|
||||
var _c = useState(isRHere), toggle = _c[0], setToggle = _c[1];
|
||||
var entryCls = 'nav-entry' + (isHere ? ' nav-here' : '');
|
||||
return (children === null || children === void 0 ? void 0 : children.length) ? React.createElement("div", { className: 'nav-dir' + (toggle ? ' nav-fold-open' : '') },
|
||||
React.createElement(React.Fragment, null,
|
||||
React.createElement("div", { className: entryCls },
|
||||
React.createElement(Link, { href: href }, label),
|
||||
React.createElement("svg", { viewBox: "0 0 8 8", onClick: function () { return setToggle(function (e) { return !e; }); } },
|
||||
React.createElement("polyline", { points: "6 3 4 5 2 3" }))),
|
||||
isHere ? childrenJSX : React.createElement(React.Fragment, null),
|
||||
React.createElement("div", { className: 'nav-dir-child' }, children.map(function (entry) { return React.createElement(NavEntry, { key: entry.link, entry: entry, dir: href, here: here }, childrenJSX); })))) : React.createElement("div", { className: entryCls },
|
||||
React.createElement(Link, { href: href }, label));
|
||||
}
|
||||
|
||||
function NavBase(_a) {
|
||||
var children = _a.children, headings = _a.headings, pathname = _a.pathname, entries = _a.entries, className = _a.className;
|
||||
var headingsJSX = React.createElement("ul", { className: "" }, headings.map(function (_a) {
|
||||
var label = _a.label, id = _a.id;
|
||||
return React.createElement("li", { key: id },
|
||||
React.createElement("a", { href: '#' + id }, label));
|
||||
}));
|
||||
return React.createElement("nav", { className: className },
|
||||
children,
|
||||
React.createElement("div", { className: "nav-root" },
|
||||
entries.map(function (entry) { return React.createElement(NavEntry, { key: entry.link, entry: entry, dir: '/', here: pathname }); }),
|
||||
headingsJSX));
|
||||
}
|
||||
|
||||
function NavHeader(_a) {
|
||||
var _b, _c, _d, _e, _f;
|
||||
var config = _a.config, onToggleFold = _a.onToggleFold;
|
||||
var title = config.title, subtitle = config.subtitle, icon0 = config.icon;
|
||||
var icon = typeof icon0 === 'string' ? { href: icon0 } : icon0;
|
||||
return React.createElement("header", null,
|
||||
React.createElement(Link, { href: "/", id: "icon-link" },
|
||||
(icon === null || icon === void 0 ? void 0 : icon.href) && React.createElement("img", { className: "icon", src: icon === null || icon === void 0 ? void 0 : icon.href, alt: (_b = icon === null || icon === void 0 ? void 0 : icon.alt) !== null && _b !== void 0 ? _b : 'icon', width: (_d = (_c = icon === null || icon === void 0 ? void 0 : icon.width) !== null && _c !== void 0 ? _c : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _d !== void 0 ? _d : 96, height: (_f = (_e = icon === null || icon === void 0 ? void 0 : icon.height) !== null && _e !== void 0 ? _e : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _f !== void 0 ? _f : 96 }),
|
||||
React.createElement("div", { className: "icon-text" },
|
||||
React.createElement("div", null, title),
|
||||
React.createElement("div", null, subtitle))),
|
||||
React.createElement("div", { className: "menu-toggle", onClick: onToggleFold }));
|
||||
}
|
||||
|
||||
function Nav(_a) {
|
||||
var config = _a.config, children = _a.children, props = __rest(_a, ["config", "children"]);
|
||||
var _b = useState(false), navFold = _b[0], setNavFold = _b[1];
|
||||
return (React.createElement(NavBase, __assign({ className: navFold ? 'open' : '', entries: config.nav }, props),
|
||||
React.createElement(NavHeader, { config: config.site, onToggleFold: function () { return setNavFold(function (e) { return !e; }); } }),
|
||||
children));
|
||||
}
|
||||
|
||||
export { Nav, NavBase, NavEntry, NavHeader };
|
||||
//# sourceMappingURL=index.esm.js.map
|
1
dist/index.esm.js.map
vendored
Normal file
1
dist/index.esm.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
102
dist/index.js
vendored
Normal file
102
dist/index.js
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Link = require('next/link');
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
var __assign = function() {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
|
||||
function __rest(s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function NavEntry(_a) {
|
||||
var _b = _a.entry, label = _b.label, link = _b.link, children = _b.children, dir = _a.dir, here = _a.here, childrenJSX = _a.children;
|
||||
var href = dir + link;
|
||||
var isHere = href.replace(/\/$/, '') === here; // remove trailing slash
|
||||
var isRHere = isHere || here.startsWith(href); // here or is children
|
||||
var _c = React.useState(isRHere), toggle = _c[0], setToggle = _c[1];
|
||||
var entryCls = 'nav-entry' + (isHere ? ' nav-here' : '');
|
||||
return (children === null || children === void 0 ? void 0 : children.length) ? React.createElement("div", { className: 'nav-dir' + (toggle ? ' nav-fold-open' : '') },
|
||||
React.createElement(React.Fragment, null,
|
||||
React.createElement("div", { className: entryCls },
|
||||
React.createElement(Link, { href: href }, label),
|
||||
React.createElement("svg", { viewBox: "0 0 8 8", onClick: function () { return setToggle(function (e) { return !e; }); } },
|
||||
React.createElement("polyline", { points: "6 3 4 5 2 3" }))),
|
||||
isHere ? childrenJSX : React.createElement(React.Fragment, null),
|
||||
React.createElement("div", { className: 'nav-dir-child' }, children.map(function (entry) { return React.createElement(NavEntry, { key: entry.link, entry: entry, dir: href, here: here }, childrenJSX); })))) : React.createElement("div", { className: entryCls },
|
||||
React.createElement(Link, { href: href }, label));
|
||||
}
|
||||
|
||||
function NavBase(_a) {
|
||||
var children = _a.children, headings = _a.headings, pathname = _a.pathname, entries = _a.entries, className = _a.className;
|
||||
var headingsJSX = React.createElement("ul", { className: "" }, headings.map(function (_a) {
|
||||
var label = _a.label, id = _a.id;
|
||||
return React.createElement("li", { key: id },
|
||||
React.createElement("a", { href: '#' + id }, label));
|
||||
}));
|
||||
return React.createElement("nav", { className: className },
|
||||
children,
|
||||
React.createElement("div", { className: "nav-root" },
|
||||
entries.map(function (entry) { return React.createElement(NavEntry, { key: entry.link, entry: entry, dir: '/', here: pathname }); }),
|
||||
headingsJSX));
|
||||
}
|
||||
|
||||
function NavHeader(_a) {
|
||||
var _b, _c, _d, _e, _f;
|
||||
var config = _a.config, onToggleFold = _a.onToggleFold;
|
||||
var title = config.title, subtitle = config.subtitle, icon0 = config.icon;
|
||||
var icon = typeof icon0 === 'string' ? { href: icon0 } : icon0;
|
||||
return React.createElement("header", null,
|
||||
React.createElement(Link, { href: "/", id: "icon-link" },
|
||||
(icon === null || icon === void 0 ? void 0 : icon.href) && React.createElement("img", { className: "icon", src: icon === null || icon === void 0 ? void 0 : icon.href, alt: (_b = icon === null || icon === void 0 ? void 0 : icon.alt) !== null && _b !== void 0 ? _b : 'icon', width: (_d = (_c = icon === null || icon === void 0 ? void 0 : icon.width) !== null && _c !== void 0 ? _c : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _d !== void 0 ? _d : 96, height: (_f = (_e = icon === null || icon === void 0 ? void 0 : icon.height) !== null && _e !== void 0 ? _e : icon === null || icon === void 0 ? void 0 : icon.size) !== null && _f !== void 0 ? _f : 96 }),
|
||||
React.createElement("div", { className: "icon-text" },
|
||||
React.createElement("div", null, title),
|
||||
React.createElement("div", null, subtitle))),
|
||||
React.createElement("div", { className: "menu-toggle", onClick: onToggleFold }));
|
||||
}
|
||||
|
||||
function Nav(_a) {
|
||||
var config = _a.config, children = _a.children, props = __rest(_a, ["config", "children"]);
|
||||
var _b = React.useState(false), navFold = _b[0], setNavFold = _b[1];
|
||||
return (React.createElement(NavBase, __assign({ className: navFold ? 'open' : '', entries: config.nav }, props),
|
||||
React.createElement(NavHeader, { config: config.site, onToggleFold: function () { return setNavFold(function (e) { return !e; }); } }),
|
||||
children));
|
||||
}
|
||||
|
||||
exports.Nav = Nav;
|
||||
exports.NavBase = NavBase;
|
||||
exports.NavEntry = NavEntry;
|
||||
exports.NavHeader = NavHeader;
|
||||
//# sourceMappingURL=index.js.map
|
1
dist/index.js.map
vendored
Normal file
1
dist/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
20
dist/index.jsx
vendored
Normal file
20
dist/index.jsx
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./Nav"), exports);
|
||||
__exportStar(require("./NavBase"), exports);
|
||||
__exportStar(require("./NavEntry"), exports);
|
||||
__exportStar(require("./NavHeader"), exports);
|
49
package.json
Normal file
49
package.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "@sup39/mdx-nav",
|
||||
"version": "0.1.0",
|
||||
"author": "sup39 <dev@sup39.dev>",
|
||||
"repository": "github.com:sup39/supMDX-nav",
|
||||
"description": "Nav component for supMDX",
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.esm.js",
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"lint": "eslint --ext .ts --ext .tsx src/",
|
||||
"pre-commit:add": "git add -u"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"env": {
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"@sup39/typescript"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.12",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-typescript": "^11.0.0",
|
||||
"@sup39/eslint-config-typescript": "^0.1.5",
|
||||
"@types/react": "^18.0.28",
|
||||
"eslint": "^8.34.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"rollup": "^3.15.0",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"build",
|
||||
"pre-commit:add"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"next": "^13",
|
||||
"react": "^18"
|
||||
}
|
||||
}
|
32
rollup.config.mjs
Normal file
32
rollup.config.mjs
Normal file
|
@ -0,0 +1,32 @@
|
|||
import typescript from '@rollup/plugin-typescript';
|
||||
import babel from '@rollup/plugin-babel';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
input: 'src/index.tsx',
|
||||
output: [
|
||||
{
|
||||
file: 'dist/index.js',
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
{
|
||||
file: 'dist/index.esm.js',
|
||||
format: 'esm',
|
||||
sourcemap: true,
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
resolve(),
|
||||
typescript(),
|
||||
babel({
|
||||
babelHelpers: 'bundled',
|
||||
presets: [
|
||||
['@babel/preset-env', {targets: {node: 'current'}}],
|
||||
'@babel/preset-react',
|
||||
],
|
||||
exclude: 'node_modules/**',
|
||||
}),
|
||||
],
|
||||
external: ['react', 'react-dom', 'next/link'],
|
||||
};
|
25
src/Nav.tsx
Normal file
25
src/Nav.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import React, {useState} from 'react';
|
||||
import type {NavEntryInfo} from './NavEntry';
|
||||
import {NavBase, HeadingInfo} from './NavBase';
|
||||
import {NavHeader, NavHeaderConfig} from './NavHeader';
|
||||
|
||||
export type NavConfig = {
|
||||
site: NavHeaderConfig
|
||||
nav: NavEntryInfo[]
|
||||
}
|
||||
export type NavProps = {
|
||||
children?: React.ReactNode
|
||||
headings: HeadingInfo[]
|
||||
pathname: string
|
||||
config: NavConfig
|
||||
};
|
||||
|
||||
export function Nav({config, children, ...props}: NavProps) {
|
||||
const [navFold, setNavFold] = useState(false);
|
||||
return (
|
||||
<NavBase className={navFold ? 'open' : ''} entries={config.nav} {...props}>
|
||||
<NavHeader config={config.site} onToggleFold={()=>setNavFold(e=>!e)} />
|
||||
{children}
|
||||
</NavBase>
|
||||
);
|
||||
}
|
31
src/NavBase.tsx
Normal file
31
src/NavBase.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import {NavEntry, NavEntryInfo} from './NavEntry';
|
||||
|
||||
export type HeadingInfo = {
|
||||
tagName: string;
|
||||
label: string;
|
||||
id: string;
|
||||
};
|
||||
export type NavBaseProps = {
|
||||
children?: React.ReactNode
|
||||
headings: HeadingInfo[]
|
||||
pathname: string
|
||||
entries: NavEntryInfo[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function NavBase({
|
||||
children, headings, pathname, entries, className,
|
||||
}: NavBaseProps) {
|
||||
const headingsJSX = <ul className="">{headings.map(({label, id}) => <li key={id}>
|
||||
<a href={'#'+id}>{label}</a>
|
||||
</li>)}</ul>;
|
||||
|
||||
return <nav className={className}>
|
||||
{children}
|
||||
<div className="nav-root">
|
||||
{entries.map(entry => <NavEntry key={entry.link} entry={entry} dir={'/'} here={pathname} />)}
|
||||
{headingsJSX}
|
||||
</div>
|
||||
</nav>;
|
||||
}
|
30
src/NavEntry.tsx
Normal file
30
src/NavEntry.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React, {useState} from 'react';
|
||||
import Link from 'next/link';
|
||||
export type NavEntryInfo = {
|
||||
label: string
|
||||
link: string
|
||||
children?: NavEntryInfo[]
|
||||
};
|
||||
|
||||
export function NavEntry<Body, >({
|
||||
entry: {label, link, children}, dir, here, children: childrenJSX,
|
||||
}: {entry: NavEntryInfo, dir: string, here: string, children?: Body}) {
|
||||
const href = dir+link;
|
||||
const isHere = href.replace(/\/$/, '')===here; // remove trailing slash
|
||||
const isRHere = isHere || here.startsWith(href); // here or is children
|
||||
|
||||
const [toggle, setToggle] = useState(isRHere);
|
||||
const entryCls = 'nav-entry'+(isHere ? ' nav-here' : '');
|
||||
return children?.length ? <div className={'nav-dir'+(toggle ? ' nav-fold-open' : '')}><>
|
||||
<div className={entryCls}>
|
||||
<Link href={href}>{label}</Link>
|
||||
<svg viewBox="0 0 8 8" onClick={()=>setToggle(e=>!e)}><polyline points="6 3 4 5 2 3"></polyline></svg>
|
||||
</div>
|
||||
{isHere ? childrenJSX : <></>}
|
||||
<div className='nav-dir-child'>{
|
||||
children.map(entry => <NavEntry key={entry.link} entry={entry} dir={href} here={here}>{childrenJSX}</NavEntry>)
|
||||
}</div>
|
||||
</></div> : <div className={entryCls}>
|
||||
<Link href={href}>{label}</Link>
|
||||
</div>;
|
||||
}
|
37
src/NavHeader.tsx
Normal file
37
src/NavHeader.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export type NavHeaderConfig = {
|
||||
title: string
|
||||
subtitle?: string
|
||||
icon?: string | {
|
||||
href: string
|
||||
alt?: string
|
||||
size?: number
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
};
|
||||
|
||||
export function NavHeader({config, onToggleFold}: {
|
||||
config: NavHeaderConfig
|
||||
onToggleFold?: ()=>void
|
||||
}) {
|
||||
const {title, subtitle, icon: icon0} = config;
|
||||
const icon = typeof icon0 === 'string' ? {href: icon0} : icon0;
|
||||
return <header>
|
||||
<Link href="/" id="icon-link">
|
||||
{icon?.href && <img className="icon"
|
||||
src={icon?.href}
|
||||
alt={icon?.alt ?? 'icon'}
|
||||
width={icon?.width ?? icon?.size ?? 96}
|
||||
height={icon?.height ?? icon?.size ?? 96}
|
||||
/>}
|
||||
<div className="icon-text">
|
||||
<div>{title}</div>
|
||||
<div>{subtitle}</div>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="menu-toggle" onClick={onToggleFold} />
|
||||
</header>;
|
||||
}
|
4
src/index.tsx
Normal file
4
src/index.tsx
Normal file
|
@ -0,0 +1,4 @@
|
|||
export * from './Nav';
|
||||
export * from './NavBase';
|
||||
export * from './NavEntry';
|
||||
export * from './NavHeader';
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "es6",
|
||||
"outDir": "dist",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts",
|
||||
"src/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue