@riebeckite/plugin-navigation 0.0.27 → 0.0.29
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 -15
- package/README_ja.md +39 -20
- package/dist/components/site-nav.d.ts +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -0
- package/package.json +7 -5
- package/style.css +110 -0
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
Site navigation as a Riebeckite plugin. `navigation()` derives the primary
|
|
6
6
|
navigation from the notes already in the vault, so an existing Obsidian vault
|
|
7
7
|
becomes navigable with no Riebeckite-specific file and no required frontmatter.
|
|
8
|
-
The plugin owns the navigation *model
|
|
9
|
-
owns placement — where each rendered
|
|
8
|
+
The plugin owns the navigation *model*, rendered UI, and interaction styling;
|
|
9
|
+
the Site owns placement — where each rendered navigation appears.
|
|
10
10
|
|
|
11
11
|
[日本語](./README_ja.md)
|
|
12
12
|
|
|
@@ -56,23 +56,32 @@ site without navigation keeps working.
|
|
|
56
56
|
|
|
57
57
|
### Rendering
|
|
58
58
|
|
|
59
|
-
`SiteNav` renders a resolved tree as a `<nav>` landmark with nested lists.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
`SiteNav` renders a resolved tree as a `<nav>` landmark with nested lists.
|
|
60
|
+
`MobileSiteNav` renders its compact `<details>` menu. The plugin owns both
|
|
61
|
+
components' `rb-nav` UI — list flow, links, nested menus, focus treatment, and
|
|
62
|
+
the mobile panel — in its own `style.css`, loaded through the generated plugin
|
|
63
|
+
styles. The Site places the component roots in its own layout wrappers; it must
|
|
64
|
+
not style `rb-nav` descendants or construct the mobile menu markup:
|
|
65
65
|
|
|
66
66
|
```tsx
|
|
67
|
-
import { SiteNav } from "@riebeckite/plugin-navigation";
|
|
67
|
+
import { MobileSiteNav, SiteNav } from "@riebeckite/plugin-navigation";
|
|
68
68
|
|
|
69
69
|
<header class="site-header rb-site-header">
|
|
70
70
|
<a href="/" class="site-header__home rb-site-header__home">My Site</a>
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
<div class="site-header__primary-navigation">
|
|
72
|
+
<SiteNav
|
|
73
|
+
items={primary}
|
|
74
|
+
path={c.req.path}
|
|
75
|
+
language={c.get("htmlLanguage")}
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="site-header__mobile-navigation">
|
|
79
|
+
<MobileSiteNav
|
|
80
|
+
items={primary}
|
|
81
|
+
path={c.req.path}
|
|
82
|
+
language={c.get("htmlLanguage")}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
76
85
|
</header>;
|
|
77
86
|
```
|
|
78
87
|
|
|
@@ -82,6 +91,14 @@ active item, so unlocalized authored hrefs still match localized pages. Pass
|
|
|
82
91
|
`localizeHref` to rewrite hrefs for the current language, `label` to change the
|
|
83
92
|
landmark label, and `class`/`className` to extend the `<nav>` classes.
|
|
84
93
|
|
|
94
|
+
For an intentional root-level visual override, set these public custom
|
|
95
|
+
properties on the `SiteNav` root or a wrapper: `--rb-nav-gap`,
|
|
96
|
+
`--rb-nav-list-flex-wrap`, `--rb-nav-list-justify-content`,
|
|
97
|
+
`--rb-nav-item-display`, `--rb-nav-item-padding`,
|
|
98
|
+
`--rb-nav-item-font-family`, `--rb-nav-item-font-size`,
|
|
99
|
+
`--rb-nav-item-font-weight`, `--rb-nav-item-letter-spacing`, and
|
|
100
|
+
`--rb-nav-item-text-transform`. Do not select `rb-nav` descendants.
|
|
101
|
+
|
|
85
102
|
## Authored navigation
|
|
86
103
|
|
|
87
104
|
Automated derivation cannot express everything, and some sites curate their
|
|
@@ -140,8 +157,9 @@ tab.
|
|
|
140
157
|
the model, or `null`
|
|
141
158
|
- `validateNavigationOptions(options)` — option validation
|
|
142
159
|
- `SiteNav` — render a resolved tree with the standard `rb-nav` structure
|
|
160
|
+
- `MobileSiteNav` — render the plugin-owned compact navigation menu
|
|
143
161
|
- Types: `NavigationItem`, `NavigationOptions`, `NavigationSource`,
|
|
144
|
-
`SiteNavigation`, `SiteNavProps`
|
|
162
|
+
`SiteNavigation`, `SiteNavProps`, `MobileSiteNavProps`
|
|
145
163
|
|
|
146
164
|
## Limitations
|
|
147
165
|
|
package/README_ja.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
サイトナビゲーションを提供する Riebeckite プラグインです。`navigation()` は
|
|
6
6
|
Vault にすでにあるノートから主要ナビゲーションを導出します。Riebeckite 専用の
|
|
7
7
|
ファイルも必須 frontmatter も不要なので、既存の Obsidian Vault をそのまま
|
|
8
|
-
|
|
8
|
+
公開できます。ナビゲーションの「モデル」、UI、操作に関わるスタイルはプラグインが持ち、
|
|
9
9
|
配置は Site が担当します。
|
|
10
10
|
|
|
11
11
|
[English](./README.md)
|
|
@@ -57,22 +57,32 @@ const secondary = model?.secondary ?? [];
|
|
|
57
57
|
### 描画
|
|
58
58
|
|
|
59
59
|
`SiteNav` は解決済みのツリーを `<nav>` ランドマークとネストしたリストとして
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
描画し、`MobileSiteNav` はコンパクトな `<details>` メニューを描画します。子の
|
|
61
|
+
再帰描画、現在パスの判定、言語を考慮した正規化、外部リンクの扱い、`aria-current`
|
|
62
|
+
に加え、リスト・リンク・子メニュー・フォーカス表示・モバイルパネルの `rb-nav` UI は
|
|
63
|
+
プラグインが自身の `style.css` で担当します(自動生成される plugin styles 経由で
|
|
64
|
+
読み込まれます)。Site はコンポーネントの root を独自のレイアウト用ラッパーに置き、
|
|
65
|
+
`rb-nav` の子要素をスタイルしたりモバイルメニューのマークアップを組み立てたりしません。
|
|
65
66
|
|
|
66
67
|
```tsx
|
|
67
|
-
import { SiteNav } from "@riebeckite/plugin-navigation";
|
|
68
|
+
import { MobileSiteNav, SiteNav } from "@riebeckite/plugin-navigation";
|
|
68
69
|
|
|
69
70
|
<header class="site-header rb-site-header">
|
|
70
71
|
<a href="/" class="site-header__home rb-site-header__home">My Site</a>
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
<div class="site-header__primary-navigation">
|
|
73
|
+
<SiteNav
|
|
74
|
+
items={primary}
|
|
75
|
+
path={c.req.path}
|
|
76
|
+
language={c.get("htmlLanguage")}
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="site-header__mobile-navigation">
|
|
80
|
+
<MobileSiteNav
|
|
81
|
+
items={primary}
|
|
82
|
+
path={c.req.path}
|
|
83
|
+
language={c.get("htmlLanguage")}
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
76
86
|
</header>;
|
|
77
87
|
```
|
|
78
88
|
|
|
@@ -83,6 +93,14 @@ import { SiteNav } from "@riebeckite/plugin-navigation";
|
|
|
83
93
|
`label` でランドマークのラベルを、`class` / `className` で `<nav>` のクラスを
|
|
84
94
|
拡張できます。
|
|
85
95
|
|
|
96
|
+
root レベルで意図的に見た目を上書きする場合は、`SiteNav` の root またはラッパーに
|
|
97
|
+
次の公開カスタムプロパティを指定します。`--rb-nav-gap`、
|
|
98
|
+
`--rb-nav-list-flex-wrap`、`--rb-nav-list-justify-content`、
|
|
99
|
+
`--rb-nav-item-display`、`--rb-nav-item-padding`、
|
|
100
|
+
`--rb-nav-item-font-family`、`--rb-nav-item-font-size`、
|
|
101
|
+
`--rb-nav-item-font-weight`、`--rb-nav-item-letter-spacing`、
|
|
102
|
+
`--rb-nav-item-text-transform` です。`rb-nav` の子要素は選択しません。
|
|
103
|
+
|
|
86
104
|
## 手書きナビゲーション
|
|
87
105
|
|
|
88
106
|
自動導出ですべてを表現できるわけではなく、リンクを意図的に整えたいサイトも
|
|
@@ -133,16 +151,17 @@ navigation({
|
|
|
133
151
|
|
|
134
152
|
## エクスポート
|
|
135
153
|
|
|
136
|
-
- `navigation(options?)
|
|
137
|
-
- `navigationPlugin
|
|
138
|
-
- `NAVIGATION_PLUGIN_NAME
|
|
139
|
-
- `buildNavigation(entries, options?)
|
|
140
|
-
- `resolveSiteNavigation(config, manifest)
|
|
154
|
+
- `navigation(options?)`:プラグインファクトリ
|
|
155
|
+
- `navigationPlugin`:`navigation` のエイリアス
|
|
156
|
+
- `NAVIGATION_PLUGIN_NAME`:プラグイン名 `"navigation"`
|
|
157
|
+
- `buildNavigation(entries, options?)`:マニフェストエントリからモデルを構築する
|
|
158
|
+
- `resolveSiteNavigation(config, manifest)`:有効なプラグインを見つけてモデルを
|
|
141
159
|
構築する。なければ `null`
|
|
142
|
-
- `validateNavigationOptions(options)
|
|
143
|
-
- `SiteNav
|
|
160
|
+
- `validateNavigationOptions(options)`:オプションの検証
|
|
161
|
+
- `SiteNav`:解決済みツリーを標準の `rb-nav` 構造で描画する
|
|
162
|
+
- `MobileSiteNav`:プラグイン所有のコンパクトなナビゲーションメニューを描画する
|
|
144
163
|
- 型: `NavigationItem`, `NavigationOptions`, `NavigationSource`,
|
|
145
|
-
`SiteNavigation`, `SiteNavProps`
|
|
164
|
+
`SiteNavigation`, `SiteNavProps`, `MobileSiteNavProps`
|
|
146
165
|
|
|
147
166
|
## 制約
|
|
148
167
|
|
|
@@ -19,6 +19,9 @@ export type SiteNavProps = {
|
|
|
19
19
|
readonly className?: string;
|
|
20
20
|
readonly omitHome?: boolean;
|
|
21
21
|
};
|
|
22
|
+
export type MobileSiteNavProps = SiteNavProps & {
|
|
23
|
+
readonly menuLabel?: string;
|
|
24
|
+
};
|
|
22
25
|
/**
|
|
23
26
|
* Renders a resolved navigation tree as a `<nav>` landmark with nested lists.
|
|
24
27
|
*
|
|
@@ -28,3 +31,4 @@ export type SiteNavProps = {
|
|
|
28
31
|
* where each tree is rendered.
|
|
29
32
|
*/
|
|
30
33
|
export declare function SiteNav(props: SiteNavProps): import("hono/jsx/jsx-dev-runtime").JSX.Element;
|
|
34
|
+
export declare function MobileSiteNav(props: MobileSiteNavProps): import("hono/jsx/jsx-dev-runtime").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { NavigationOptions } from "./src/types.js";
|
|
2
|
-
export type { SiteNavProps } from "./components/site-nav.js";
|
|
3
|
-
export { SiteNav } from "./components/site-nav.js";
|
|
2
|
+
export type { MobileSiteNavProps, SiteNavProps, } from "./components/site-nav.js";
|
|
3
|
+
export { MobileSiteNav, SiteNav } from "./components/site-nav.js";
|
|
4
4
|
export { buildNavigation, NAVIGATION_PLUGIN_NAME, resolveSiteNavigation, } from "./src/navigation.js";
|
|
5
5
|
export type { NavigationItem, NavigationOptions, NavigationSource, SiteNavigation, } from "./src/types.js";
|
|
6
6
|
export declare function navigation(options?: NavigationOptions): import("@riebeckite/core").RiebeckitePlugin<NavigationOptions>;
|
package/dist/index.js
CHANGED
|
@@ -191,6 +191,13 @@ function SiteNav(props) {
|
|
|
191
191
|
}
|
|
192
192
|
);
|
|
193
193
|
}
|
|
194
|
+
function MobileSiteNav(props) {
|
|
195
|
+
const { menuLabel = "Menu", ...siteNavProps } = props;
|
|
196
|
+
return /* @__PURE__ */ jsxs("details", { class: "rb-nav__mobile", children: [
|
|
197
|
+
/* @__PURE__ */ jsx("summary", { class: "rb-nav__toggle", children: menuLabel }),
|
|
198
|
+
/* @__PURE__ */ jsx(SiteNav, { ...siteNavProps })
|
|
199
|
+
] });
|
|
200
|
+
}
|
|
194
201
|
function NavigationItems(props) {
|
|
195
202
|
return /* @__PURE__ */ jsx("ul", { class: props.nested ? "rb-nav__list rb-nav__children" : "rb-nav__list", children: props.items.map((item) => /* @__PURE__ */ jsx(
|
|
196
203
|
NavigationItemView,
|
|
@@ -267,6 +274,7 @@ function navigation(options = {}) {
|
|
|
267
274
|
}
|
|
268
275
|
var navigationPlugin = navigation;
|
|
269
276
|
export {
|
|
277
|
+
MobileSiteNav,
|
|
270
278
|
NAVIGATION_PLUGIN_NAME,
|
|
271
279
|
SiteNav,
|
|
272
280
|
buildNavigation,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-navigation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"hono": "^4.12.25",
|
|
19
|
-
"@riebeckite/core": "0.0.
|
|
20
|
-
"@riebeckite/ui": "0.0.
|
|
19
|
+
"@riebeckite/core": "0.0.29",
|
|
20
|
+
"@riebeckite/ui": "0.0.29"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
+
"puppeteer": "^25.11.0",
|
|
23
24
|
"tsx": "^4.22.4",
|
|
24
|
-
"@riebeckite/test": "0.0.
|
|
25
|
+
"@riebeckite/test": "0.0.29"
|
|
25
26
|
},
|
|
26
27
|
"publishConfig": {
|
|
27
28
|
"access": "public"
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
],
|
|
57
58
|
"scripts": {
|
|
58
59
|
"build": "node ../../../scripts/build_package.mjs",
|
|
59
|
-
"test": "node --import tsx --test \"test/*.test.ts\""
|
|
60
|
+
"test": "node --import tsx --test \"test/*.test.ts\"",
|
|
61
|
+
"test:browser": "node --import tsx --test \"test/browser/*.test.ts\""
|
|
60
62
|
}
|
|
61
63
|
}
|
package/style.css
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
@layer components {
|
|
2
|
+
.rb-nav {
|
|
3
|
+
color: var(--rb-color-ink);
|
|
4
|
+
}
|
|
5
|
+
|
|
2
6
|
.rb-nav > .rb-nav__list,
|
|
3
7
|
.rb-nav__children {
|
|
4
8
|
margin: 0;
|
|
@@ -6,7 +10,12 @@
|
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
.rb-nav > .rb-nav__list {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: var(--rb-nav-gap, var(--rb-space-3, 1.5rem));
|
|
9
16
|
padding: 0;
|
|
17
|
+
flex-wrap: var(--rb-nav-list-flex-wrap, nowrap);
|
|
18
|
+
justify-content: var(--rb-nav-list-justify-content, flex-start);
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
.rb-nav__item {
|
|
@@ -19,6 +28,13 @@
|
|
|
19
28
|
top: 100%;
|
|
20
29
|
left: 0;
|
|
21
30
|
min-width: max-content;
|
|
31
|
+
padding: var(--rb-space-2, 1rem);
|
|
32
|
+
background: var(--rb-color-surface);
|
|
33
|
+
border: 1px solid var(--rb-color-border);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.rb-nav__children {
|
|
37
|
+
z-index: 50;
|
|
22
38
|
}
|
|
23
39
|
|
|
24
40
|
.rb-nav__item:hover > .rb-nav__children,
|
|
@@ -26,4 +42,98 @@
|
|
|
26
42
|
display: flex;
|
|
27
43
|
flex-direction: column;
|
|
28
44
|
}
|
|
45
|
+
|
|
46
|
+
.rb-nav__link {
|
|
47
|
+
display: var(--rb-nav-item-display, inline);
|
|
48
|
+
padding: var(--rb-nav-item-padding, 0);
|
|
49
|
+
color: inherit;
|
|
50
|
+
font-family: var(--rb-nav-item-font-family, inherit);
|
|
51
|
+
font-size: var(--rb-nav-item-font-size, inherit);
|
|
52
|
+
font-weight: var(--rb-nav-item-font-weight, inherit);
|
|
53
|
+
letter-spacing: var(--rb-nav-item-letter-spacing, normal);
|
|
54
|
+
text-decoration: none;
|
|
55
|
+
text-transform: var(--rb-nav-item-text-transform, none);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.rb-nav__label {
|
|
59
|
+
display: var(--rb-nav-item-display, inline);
|
|
60
|
+
padding: var(--rb-nav-item-padding, 0);
|
|
61
|
+
font-family: var(--rb-nav-item-font-family, inherit);
|
|
62
|
+
font-size: var(--rb-nav-item-font-size, inherit);
|
|
63
|
+
font-weight: var(--rb-nav-item-font-weight, inherit);
|
|
64
|
+
letter-spacing: var(--rb-nav-item-letter-spacing, normal);
|
|
65
|
+
text-transform: var(--rb-nav-item-text-transform, none);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rb-nav__link:hover,
|
|
69
|
+
.rb-nav__link:focus-visible,
|
|
70
|
+
.rb-nav__link--active {
|
|
71
|
+
color: var(--rb-color-accent);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.rb-nav__link:focus-visible,
|
|
75
|
+
.rb-nav__toggle:focus-visible {
|
|
76
|
+
outline: 2px solid var(--rb-color-accent);
|
|
77
|
+
outline-offset: 2px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.rb-nav__mobile {
|
|
81
|
+
position: relative;
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.rb-nav__toggle {
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@media (min-width: 30.001rem) and (max-width: 48rem) {
|
|
90
|
+
.rb-nav > .rb-nav__list {
|
|
91
|
+
flex-wrap: wrap;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@media (max-width: 30rem) {
|
|
96
|
+
.rb-nav__mobile {
|
|
97
|
+
display: block;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.rb-nav__mobile > .rb-nav {
|
|
101
|
+
position: absolute;
|
|
102
|
+
z-index: 10;
|
|
103
|
+
top: calc(100% + var(--rb-space-2, 1rem));
|
|
104
|
+
right: 0;
|
|
105
|
+
min-width: var(--rb-nav-menu-min-width, 12rem);
|
|
106
|
+
max-width: calc(100vw - 2rem);
|
|
107
|
+
padding: var(--rb-space-3, 1.5rem);
|
|
108
|
+
background: var(--rb-color-surface);
|
|
109
|
+
border: 1px solid var(--rb-color-border);
|
|
110
|
+
box-shadow: 0 4px 12px
|
|
111
|
+
color-mix(in oklab, var(--rb-color-ink) 14%, transparent);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.rb-nav__mobile .rb-nav__list,
|
|
115
|
+
.rb-nav__mobile .rb-nav__children {
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
align-items: flex-start;
|
|
119
|
+
gap: var(--rb-space-2, 1rem);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.rb-nav__mobile .rb-nav__list {
|
|
123
|
+
padding: 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.rb-nav__mobile .rb-nav__children {
|
|
127
|
+
position: static;
|
|
128
|
+
margin-top: var(--rb-space-2, 1rem);
|
|
129
|
+
padding: 0;
|
|
130
|
+
background: transparent;
|
|
131
|
+
border: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.rb-nav__mobile .rb-nav__link,
|
|
135
|
+
.rb-nav__mobile .rb-nav__label {
|
|
136
|
+
overflow-wrap: anywhere;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
29
139
|
}
|