for-humanity 0.4.4 → 0.6.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.
Files changed (85) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +6 -5
  3. package/dist/browser.js +39 -0
  4. package/dist/cli.css +350 -262
  5. package/dist/cli.js +1174 -364
  6. package/package.json +8 -11
  7. package/src/component/widget/{shell → cursor-face}/_constant/cursor-face.ts +5 -0
  8. package/src/component/widget/cursor-face/wg-cursor-face.css +15 -0
  9. package/src/component/widget/cursor-face/wg-cursor-face.tsx +153 -0
  10. package/src/component/widget/navigation/_constant/navigation-data-schema.ts +35 -0
  11. package/src/component/widget/navigation/_constant/navigation.ts +9 -0
  12. package/src/component/widget/navigation/_function/restore-navigation-scroll.ts +59 -0
  13. package/src/{content → component/widget/navigation/_function}/to-doc-groups/_to-doc-branches.ts +2 -2
  14. package/src/{content → component/widget/navigation/_function}/to-doc-groups/_to-doc-group-branches.ts +3 -3
  15. package/src/{content → component/widget/navigation/_function}/to-doc-groups/to-doc-groups.ts +1 -1
  16. package/src/component/widget/navigation/_function/to-navigation-branch-id.ts +6 -0
  17. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts +14 -0
  18. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts +14 -0
  19. package/src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts +25 -0
  20. package/src/component/widget/navigation/_function/to-navigation-json.ts +8 -0
  21. package/src/component/widget/{shell → navigation}/_function/to-toc-groups.ts +2 -2
  22. package/src/{type → component/widget/navigation/_type}/doc-group.ts +1 -1
  23. package/src/component/widget/navigation/_type/navigation-data.ts +83 -0
  24. package/src/component/widget/navigation/_type/navigation-focus-snapshot.ts +21 -0
  25. package/src/component/widget/navigation/_wg-navigation-branch-toggle.css +28 -0
  26. package/src/component/widget/navigation/_wg-navigation-branch-toggle.tsx +48 -0
  27. package/src/component/widget/{shell/_wg-shell-nav-list.css → navigation/_wg-navigation-nav-list.css} +24 -16
  28. package/src/component/widget/navigation/_wg-navigation-nav-list.tsx +106 -0
  29. package/src/component/widget/{shell/_wg-shell-nav.css → navigation/_wg-navigation-nav.css} +9 -3
  30. package/src/component/widget/navigation/_wg-navigation-nav.tsx +43 -0
  31. package/src/component/widget/navigation/_wg-navigation-scroll.tsx +117 -0
  32. package/src/component/widget/{shell/_wg-shell-toc.css → navigation/_wg-navigation-toc.css} +39 -24
  33. package/src/component/widget/navigation/_wg-navigation-toc.tsx +155 -0
  34. package/src/component/widget/navigation/wg-navigation.css +282 -0
  35. package/src/component/widget/navigation/wg-navigation.tsx +479 -0
  36. package/src/component/widget/prose/_function/rehype-sections/rehype-sections.ts +1 -1
  37. package/src/component/widget/shell/wg-shell.css +13 -269
  38. package/src/component/widget/shell/wg-shell.tsx +16 -97
  39. package/src/component/widget/shell-controls/wg-shell-controls.css +4 -0
  40. package/src/component/widget/shell-controls/wg-shell-controls.tsx +170 -0
  41. package/src/constant/asset.ts +0 -5
  42. package/src/constant/copy.ts +5 -0
  43. package/src/entry/browser/browser.tsx +22 -0
  44. package/src/entry/cli/_constant/crawling.ts +14 -0
  45. package/src/{app.tsx → entry/cli/_function/create-app.tsx} +6 -6
  46. package/src/{dev.ts → entry/cli/_function/create-dev-app.ts} +9 -1
  47. package/src/{content → entry/cli/_function/create-processor}/create-processor.ts +3 -3
  48. package/src/{content → entry/cli/_function}/read-docs.ts +21 -2
  49. package/src/{content → entry/cli/_function}/read-home.ts +1 -1
  50. package/src/entry/cli/_function/to-crawling-app.ts +42 -0
  51. package/src/{content/read-docs.test.ts → entry/cli/cli.test.ts} +211 -31
  52. package/src/{cli.ts → entry/cli/cli.ts} +31 -15
  53. package/src/store/navigation/_constant/tree.ts +6 -0
  54. package/src/store/navigation/create-navigation-stores.test.ts +92 -0
  55. package/src/store/navigation/create-navigation-stores.ts +73 -0
  56. package/src/store/navigation/navigation-state.ts +46 -0
  57. package/src/store/navigation/navigation-storage.ts +14 -0
  58. package/src/store/navigation/to-navigation-scroll-state.ts +42 -0
  59. package/src/store/navigation/to-navigation-tree-state.ts +19 -0
  60. package/src/store/navigation/use-navigation-tree-store.ts +12 -0
  61. package/src/style/token.css +3 -2
  62. package/src/type/doc-content.ts +1 -1
  63. package/src/type/doc-file-data.ts +1 -1
  64. package/src/{component/widget/shell/_type → type}/doc-outline.ts +1 -1
  65. package/src/type/site-assets.ts +2 -2
  66. package/src/type/site-config.ts +10 -1
  67. package/dist/client.js +0 -7
  68. package/src/client.ts +0 -335
  69. package/src/component/widget/shell/_constant/navigation.ts +0 -9
  70. package/src/component/widget/shell/_function/bind-mobile-navigation.ts +0 -147
  71. package/src/component/widget/shell/_function/bind-navigation-overflow.ts +0 -47
  72. package/src/component/widget/shell/_function/bind-navigation-scroll.ts +0 -84
  73. package/src/component/widget/shell/_function/restore-navigation-scroll.ts +0 -47
  74. package/src/component/widget/shell/_wg-shell-nav-list.tsx +0 -87
  75. package/src/component/widget/shell/_wg-shell-nav.tsx +0 -49
  76. package/src/component/widget/shell/_wg-shell-toc.tsx +0 -57
  77. /package/src/{constant → component/widget/navigation/_constant}/locale.ts +0 -0
  78. /package/src/component/widget/{shell → navigation}/_constant/reading-line.ts +0 -0
  79. /package/src/{type → component/widget/navigation/_type}/doc-branch.ts +0 -0
  80. /package/src/component/widget/{shell → navigation}/_type/toc-group.ts +0 -0
  81. /package/src/{constant → entry/cli/_constant}/cli.ts +0 -0
  82. /package/src/{content/rehype-assets.ts → entry/cli/_function/create-processor/_rehype-assets.ts} +0 -0
  83. /package/src/{content/rehype-heading-ids.ts → entry/cli/_function/create-processor/_rehype-heading-ids.ts} +0 -0
  84. /package/src/{content/remark-report.ts → entry/cli/_function/create-processor/_remark-report.ts} +0 -0
  85. /package/src/{component/widget/prose/_type → type}/doc-section.ts +0 -0
@@ -1,13 +1,13 @@
1
1
  /*
2
2
  * 재귀 문서 목록 · 단계별 가지와 조상 경로의 1px 트리
3
3
  */
4
- .wg_shellNavList__root {
4
+ .wg_navigationNavList__root {
5
5
  margin: 0 0 0 var(--app-space-tree-inset);
6
6
  padding: 0;
7
7
  list-style: none;
8
8
  }
9
9
 
10
- .wg_shellNavList__branch {
10
+ .wg_navigationNavList__branch {
11
11
  /* 하위 묶음도 문서와 같은 첫 줄 기준으로 가지 연결 */
12
12
  position: relative;
13
13
  display: block;
@@ -28,7 +28,7 @@
28
28
  }
29
29
  }
30
30
 
31
- .wg_shellNavList__link {
31
+ .wg_navigationNavList__link {
32
32
  /* 가로 가지는 링크 첫 줄 기준 · 여러 줄 제목에서도 연결 위치 유지 */
33
33
  position: relative;
34
34
  display: block;
@@ -68,7 +68,7 @@
68
68
  }
69
69
  }
70
70
 
71
- .wg_shellNavList__link--active {
71
+ .wg_navigationNavList__link--active {
72
72
  color: var(--app-color-link);
73
73
  font-weight: var(--app-font-weight-active);
74
74
 
@@ -77,13 +77,21 @@
77
77
  }
78
78
  }
79
79
 
80
- .wg_shellNavList__item {
80
+ .wg_navigationNavList__item {
81
81
  /* 하위 목록을 포함해 다음 형제까지 줄기 연결 */
82
82
  display: flow-root;
83
83
 
84
84
  /* 세로 줄기는 각 항목 기준 · 마지막 항목의 첫 줄 가운데에서 종료 */
85
85
  position: relative;
86
86
 
87
+ &:has(> .wg_navigationBranchToggle__root) > .wg_navigationNavList__link {
88
+ padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
89
+ }
90
+
91
+ &:has(> .wg_navigationBranchToggle__root) > .wg_navigationNavList__branch {
92
+ padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
93
+ }
94
+
87
95
  &::before {
88
96
  position: absolute;
89
97
  top: 0;
@@ -119,53 +127,53 @@
119
127
  }
120
128
 
121
129
  /* 뒤 항목까지의 세로 경로 · 같은 목록의 형제 안에서만 연결 */
122
- &:where(:has(~ .wg_shellNavList__item:hover))::before {
130
+ &:where(:has(~ .wg_navigationNavList__item:hover))::before {
123
131
  border-left-color: var(--app-color-link);
124
132
  }
125
133
 
126
- &:where(:has(~ .wg_shellNavList__item :focus-visible))::before {
134
+ &:where(:has(~ .wg_navigationNavList__item :focus-visible))::before {
127
135
  border-left-color: var(--app-color-link);
128
136
  }
129
137
 
130
- & > .wg_shellNavList__root {
138
+ & > .wg_navigationNavList__root {
131
139
  margin-left: var(--app-space-tree-indent);
132
140
  }
133
141
 
134
142
  /* 하위 문서를 탐색할 때 조상 묶음의 가지도 함께 연결 */
135
- &:where(:hover) > .wg_shellNavList__branch::before {
143
+ &:where(:hover) > .wg_navigationNavList__branch::before {
136
144
  border-top-color: var(--app-color-link);
137
145
  }
138
146
 
139
- &:where(:has(:focus-visible)) > .wg_shellNavList__branch::before {
147
+ &:where(:has(:focus-visible)) > .wg_navigationNavList__branch::before {
140
148
  border-top-color: var(--app-color-link);
141
149
  }
142
150
 
143
151
  /* 자식 문서를 탐색할 때 클릭 가능한 부모 문서의 가지도 연결 */
144
- &:where(:hover) > .wg_shellNavList__link::before {
152
+ &:where(:hover) > .wg_navigationNavList__link::before {
145
153
  border-top-color: var(--app-color-link);
146
154
  }
147
155
 
148
- &:where(:has(:focus-visible)) > .wg_shellNavList__link::before {
156
+ &:where(:has(:focus-visible)) > .wg_navigationNavList__link::before {
149
157
  border-top-color: var(--app-color-link);
150
158
  }
151
159
  }
152
160
 
153
- .wg_shellNavList__item--trail {
161
+ .wg_navigationNavList__item--trail {
154
162
  &::before {
155
163
  border-left-color: var(--app-color-link);
156
164
  }
157
165
  }
158
166
 
159
- .wg_shellNavList__item--current {
167
+ .wg_navigationNavList__item--current {
160
168
  &::after {
161
169
  border-left-color: var(--app-color-link);
162
170
  }
163
171
 
164
- & > .wg_shellNavList__branch::before {
172
+ & > .wg_navigationNavList__branch::before {
165
173
  border-top-color: var(--app-color-link);
166
174
  }
167
175
 
168
- & > .wg_shellNavList__link::before {
176
+ & > .wg_navigationNavList__link::before {
169
177
  border-top-color: var(--app-color-link);
170
178
  }
171
179
  }
@@ -0,0 +1,106 @@
1
+ import clsx from "clsx";
2
+ import {Fragment} from "hono/jsx";
3
+ import {toNavigationBranchId} from "@/component/widget/navigation/_function/to-navigation-branch-id";
4
+ import type {NavigationGroup} from "@/component/widget/navigation/_type/navigation-data";
5
+ import {WgNavigationBranchToggle} from "@/component/widget/navigation/_wg-navigation-branch-toggle";
6
+ import "./_wg-navigation-nav-list.css";
7
+
8
+ /**
9
+ * 한 단계의 문서 목록과 하위 묶음 · 재귀에서도 같은 탐색 표현 유지
10
+ */
11
+ export interface WgNavigationNavListProps {
12
+ /**
13
+ * 현재 단계의 문서와 하위 묶음
14
+ */
15
+ group: NavigationGroup;
16
+ /**
17
+ * 사용자가 접은 가지
18
+ */
19
+ collapsed: Record<string, boolean>;
20
+ /**
21
+ * 브라우저에서 가지 선택 변경
22
+ */
23
+ onToggle?: (key: string) => void;
24
+ /**
25
+ * 부모 버튼과 연결할 가지 키 · 루트 묶음·문서 모두 같은 규칙 사용
26
+ */
27
+ branchKey: string;
28
+ }
29
+
30
+ export const WgNavigationNavList = (props: WgNavigationNavListProps) => {
31
+ const entries = [
32
+ ...props.group.docs.map((doc) => {
33
+ const active = doc.active;
34
+ return {kind: "document" as const, key: `doc:${doc.id}`, doc, active, current: doc.current};
35
+ }),
36
+ ...props.group.groups.map((group) => ({
37
+ kind: "group" as const,
38
+ key: `group:${JSON.stringify(group.path)}`,
39
+ group,
40
+ current: group.current,
41
+ })),
42
+ ];
43
+ const currentIndex = entries.findIndex((entry) => entry.current);
44
+
45
+ return (
46
+ <ul
47
+ className={clsx("wg_navigationNavList__root")}
48
+ aria-label={props.group.name}
49
+ id={toNavigationBranchId(props.branchKey)}
50
+ hidden={props.collapsed[props.branchKey] === true}
51
+ >
52
+ {/**
53
+ * 현재 경로 앞의 줄기와 도착 가지 · 문서 링크는 원래 파일 URL 사용
54
+ */}
55
+ {entries.map((entry, index) => (
56
+ <li
57
+ className={clsx("wg_navigationNavList__item", {
58
+ "wg_navigationNavList__item--trail": index < currentIndex,
59
+ "wg_navigationNavList__item--current": entry.current,
60
+ })}
61
+ key={entry.key}
62
+ >
63
+ {/**
64
+ * 문서 링크 · 부모도 독립 페이지, 현재 한 문서에만 페이지 상태 부여
65
+ */}
66
+ {entry.kind === "document" && (
67
+ <Fragment>
68
+ <a
69
+ className={clsx("wg_navigationNavList__link", {"wg_navigationNavList__link--active": entry.active})}
70
+ href={`/${entry.doc.id}/`}
71
+ title={entry.doc.label}
72
+ aria-current={entry.active ? "page" : undefined}
73
+ >
74
+ {entry.doc.name}
75
+ </a>
76
+ {/**
77
+ * 하위 문서 · 부모 아래에서도 기존 목록의 들여쓰기와 키보드 이동 유지
78
+ */}
79
+ {entry.doc.children.length > 0 && (
80
+ <WgNavigationBranchToggle branchKey={entry.key} label={entry.doc.name} collapsed={props.collapsed} onToggle={props.onToggle} />
81
+ )}
82
+ {entry.doc.children.length > 0 && (
83
+ <WgNavigationNavList
84
+ group={{name: entry.doc.name, path: props.group.path, current: entry.current, docs: entry.doc.children, groups: []}}
85
+ collapsed={props.collapsed}
86
+ onToggle={props.onToggle}
87
+ branchKey={entry.key}
88
+ />
89
+ )}
90
+ </Fragment>
91
+ )}
92
+ {/**
93
+ * 하위 묶음 · 같은 목록을 재귀로 이어 깊이에 따라 들여쓰기
94
+ */}
95
+ {entry.kind === "group" && (
96
+ <Fragment>
97
+ <span className={clsx("wg_navigationNavList__branch")}>{entry.group.name}</span>
98
+ <WgNavigationBranchToggle branchKey={entry.key} label={entry.group.name} collapsed={props.collapsed} onToggle={props.onToggle} />
99
+ <WgNavigationNavList group={entry.group} collapsed={props.collapsed} onToggle={props.onToggle} branchKey={entry.key} />
100
+ </Fragment>
101
+ )}
102
+ </li>
103
+ ))}
104
+ </ul>
105
+ );
106
+ };
@@ -1,21 +1,27 @@
1
1
  /*
2
2
  * 읽는 순서의 문서 목록 · 작은 회색 묶음과 링크색 문서
3
3
  */
4
- .wg_shellNav__root {
4
+ .wg_navigationNav__root {
5
5
  font-size: var(--app-font-size-dense);
6
6
  line-height: var(--app-line-height-tight);
7
7
  }
8
8
 
9
- .wg_shellNav__docs {
9
+ .wg_navigationNav__docs {
10
10
  display: flex;
11
11
  flex-direction: column;
12
12
  gap: var(--app-space-stack);
13
13
  }
14
14
 
15
- .wg_shellNav__group {
15
+ .wg_navigationNav__group {
16
+ padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
16
17
  margin: 0 0 4px;
17
18
  color: var(--app-color-text-muted);
18
19
  font-size: var(--app-font-size-group);
19
20
  line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
20
21
  text-box: trim-start cap alphabetic;
21
22
  }
23
+
24
+ .wg_navigationNav__docGroup {
25
+ /* 묶음 접기 버튼의 첫 행 기준 */
26
+ position: relative;
27
+ }
@@ -0,0 +1,43 @@
1
+ import clsx from "clsx";
2
+ import type {NavigationGroup} from "@/component/widget/navigation/_type/navigation-data";
3
+ import {WgNavigationBranchToggle} from "@/component/widget/navigation/_wg-navigation-branch-toggle";
4
+ import {WgNavigationNavList} from "@/component/widget/navigation/_wg-navigation-nav-list";
5
+ import {copy_nav_aria_label} from "@/constant/copy";
6
+ import "./_wg-navigation-nav.css";
7
+
8
+ /**
9
+ * 서버·브라우저가 공유하는 문서 트리
10
+ */
11
+ export interface WgNavigationNavProps {
12
+ /**
13
+ * 본문을 제외한 읽는 순서의 문서 묶음
14
+ */
15
+ groups: NavigationGroup[];
16
+ /**
17
+ * 사용자가 접은 가지
18
+ */
19
+ collapsed: Record<string, boolean>;
20
+ /**
21
+ * 브라우저에서 가지 선택 변경 · 서버 출력에서는 생략
22
+ */
23
+ onToggle?: (key: string) => void;
24
+ }
25
+
26
+ export const WgNavigationNav = (props: WgNavigationNavProps) => {
27
+ return (
28
+ <nav className={clsx("wg_navigationNav__root")} aria-label={copy_nav_aria_label}>
29
+ {/**
30
+ * 문서 이동 · 클릭하지 않는 묶음과 독립 문서
31
+ */}
32
+ <div className={clsx("wg_navigationNav__docs")}>
33
+ {props.groups.map((group) => (
34
+ <section className={clsx("wg_navigationNav__docGroup")} key={JSON.stringify(group.path)} aria-label={group.name}>
35
+ <div className={clsx("wg_navigationNav__group")}>{group.name}</div>
36
+ <WgNavigationBranchToggle branchKey={`group:${JSON.stringify(group.path)}`} label={group.name} collapsed={props.collapsed} onToggle={props.onToggle} />
37
+ <WgNavigationNavList group={group} branchKey={`group:${JSON.stringify(group.path)}`} collapsed={props.collapsed} onToggle={props.onToggle} />
38
+ </section>
39
+ ))}
40
+ </div>
41
+ </nav>
42
+ );
43
+ };
@@ -0,0 +1,117 @@
1
+ import clsx from "clsx";
2
+ import {type Child, type DOMAttributes, type RefObject, useLayoutEffect, useRef, useState} from "hono/jsx";
3
+
4
+ /**
5
+ * 탐색 좌표를 제어하는 부모와 넘침 표시를 소유하는 스크롤 영역의 경계
6
+ */
7
+ export interface WgNavigationScrollProps {
8
+ /**
9
+ * 배치별 좌표 복원과 저장에 필요한 실제 스크롤 요소
10
+ */
11
+ portRef: RefObject<HTMLDivElement | null>;
12
+ /**
13
+ * 문서 목록과 현재 페이지 목차의 독립된 스크롤 수명
14
+ */
15
+ kind: "documents" | "outline";
16
+ /**
17
+ * JavaScript가 연결된 뒤에만 손잡이를 넘침 표시로 대체
18
+ */
19
+ ready: boolean;
20
+ /**
21
+ * 탐색 링크를 포함한 영역 내용
22
+ */
23
+ children: Child;
24
+ /**
25
+ * 이동 직전 좌표 보존과 모바일 모달 닫기
26
+ */
27
+ onClick?: DOMAttributes["onClick"];
28
+ /**
29
+ * 실제 스크롤 좌표가 바뀔 때 부모 저장소에 반영
30
+ */
31
+ onScroll?: () => void;
32
+ }
33
+
34
+ export const WgNavigationScroll = (props: WgNavigationScrollProps) => {
35
+ const [overflow, setOverflow] = useState({above: false, below: false});
36
+ const frameRef = useRef(0);
37
+
38
+ /**
39
+ * 소수 픽셀 반올림을 제외한 실제 남은 내용만 위·아래 흐림으로 알림
40
+ */
41
+ const updateOverflow = () => {
42
+ frameRef.current = 0;
43
+ if (props.portRef.current === null) return;
44
+ const above = props.portRef.current.scrollTop > 1;
45
+ const below = props.portRef.current.scrollHeight - props.portRef.current.clientHeight - props.portRef.current.scrollTop > 1;
46
+ setOverflow((state) => (state.above === above && state.below === below ? state : {above, below}));
47
+ };
48
+
49
+ /**
50
+ * 연속 스크롤과 관찰자 알림은 프레임당 한 번 측정
51
+ */
52
+ const scheduleOverflow = () => {
53
+ if (frameRef.current === 0) frameRef.current = requestAnimationFrame(updateOverflow);
54
+ };
55
+
56
+ /**
57
+ * 네이티브 좌표는 바로 저장하고 시각적 넘침만 프레임에 맞춰 갱신
58
+ */
59
+ const handlePortScroll: DOMAttributes["onScroll"] = (_event) => {
60
+ props.onScroll?.();
61
+ scheduleOverflow();
62
+ };
63
+
64
+ /**
65
+ * 영역과 내용의 크기를 함께 추적 · Hono 최초 mount의 분리된 fragment 측정은 연결 직후 실행
66
+ */
67
+ useLayoutEffect(() => {
68
+ if (!props.ready || props.portRef.current === null) return;
69
+ const observer = new ResizeObserver(scheduleOverflow);
70
+ observer.observe(props.portRef.current);
71
+ if (props.portRef.current.firstElementChild !== null) observer.observe(props.portRef.current.firstElementChild);
72
+ let active = true;
73
+ addEventListener("pageshow", scheduleOverflow);
74
+ if (props.portRef.current.isConnected) {
75
+ updateOverflow();
76
+ } else {
77
+ // Hono는 최초 layout effect를 fragment에서 실행하므로 같은 script의 paint 전 microtask에서 측정한다
78
+ queueMicrotask(() => {
79
+ if (active) updateOverflow();
80
+ });
81
+ }
82
+ return () => {
83
+ active = false;
84
+ observer.disconnect();
85
+ removeEventListener("pageshow", scheduleOverflow);
86
+ cancelAnimationFrame(frameRef.current);
87
+ frameRef.current = 0;
88
+ };
89
+ }, [props.portRef, props.ready]);
90
+
91
+ /**
92
+ * 접힘 선택의 렌더가 바뀐 직후 측정 · 좌표 복원은 부모의 연결 후 처리보다 앞서 저장하지 않음
93
+ */
94
+ useLayoutEffect(() => {
95
+ if (props.ready && props.portRef.current?.isConnected) updateOverflow();
96
+ }, [props.children, props.ready]);
97
+
98
+ return (
99
+ // biome-ignore lint/a11y/noStaticElementInteractions lint/a11y/useKeyWithClickEvents: 부모의 링크 이벤트 위임이며 자식 a·button의 네이티브 키보드 동작을 그대로 소비한다
100
+ <div
101
+ ref={props.ready ? props.portRef : undefined}
102
+ className={clsx(
103
+ "wg_navigation__scroll",
104
+ props.kind === "documents" && "wg_navigation__documents",
105
+ props.kind === "outline" && "wg_navigation__headings",
106
+ props.ready && "wg_navigation__scroll--ready",
107
+ props.ready && overflow.above && "wg_navigation__scroll--above",
108
+ props.ready && overflow.below && "wg_navigation__scroll--below",
109
+ )}
110
+ data-navigation-scroll={props.kind}
111
+ onClick={props.onClick}
112
+ onScroll={handlePortScroll}
113
+ >
114
+ {props.children}
115
+ </div>
116
+ );
117
+ };
@@ -1,12 +1,12 @@
1
1
  /*
2
- * 문서 탐색 아래 목차 · 회색 제목·묶음과 본문 글색의 이동 대상 구분
2
+ * 와이드 화면의 오른쪽 목차 · 회색 제목·묶음과 본문 글색의 이동 대상 구분
3
3
  */
4
- .wg_shellToc__root {
4
+ .wg_navigationToc__root {
5
5
  font-size: var(--app-font-size-dense);
6
6
  line-height: var(--app-line-height-tight);
7
7
  }
8
8
 
9
- .wg_shellToc__label {
9
+ .wg_navigationToc__label {
10
10
  margin-bottom: var(--app-space-inline);
11
11
  color: var(--app-color-text-muted);
12
12
  font-size: var(--app-font-size-label);
@@ -14,20 +14,31 @@
14
14
  letter-spacing: var(--app-letter-spacing-label);
15
15
  }
16
16
 
17
- .wg_shellToc__group {
18
- margin: var(--app-space-stack) 0 4px;
17
+ .wg_navigationToc__group {
18
+ margin: 0 0 4px;
19
+ padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
19
20
  color: var(--app-color-text-muted);
20
21
  font-size: var(--app-font-size-group);
21
22
  line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
22
23
  }
23
24
 
24
- .wg_shellToc__list {
25
+ .wg_navigationToc__groupSection {
26
+ /* 가름 제목과 그 하위 목록을 하나의 접힘 대상으로 연결 */
27
+ position: relative;
28
+ display: flow-root;
29
+ }
30
+
31
+ .wg_navigationToc__groupSection--named {
32
+ margin-top: var(--app-space-stack);
33
+ }
34
+
35
+ .wg_navigationToc__list {
25
36
  margin: 0 0 0 var(--app-space-tree-inset);
26
37
  padding: 0;
27
38
  list-style: none;
28
39
  }
29
40
 
30
- .wg_shellToc__link {
41
+ .wg_navigationToc__link {
31
42
  /* 가로 가지는 링크 첫 줄 기준 · 여러 줄 제목에서도 연결 위치 유지 */
32
43
  position: relative;
33
44
  display: block;
@@ -68,7 +79,7 @@
68
79
  }
69
80
  }
70
81
 
71
- .wg_shellToc__link--active {
82
+ .wg_navigationToc__link--active {
72
83
  color: var(--app-color-text-strong);
73
84
  font-weight: var(--app-font-weight-active);
74
85
 
@@ -77,13 +88,17 @@
77
88
  }
78
89
  }
79
90
 
80
- .wg_shellToc__item {
91
+ .wg_navigationToc__item {
81
92
  /* 하위 목록의 margin을 포함해 다음 항목까지 줄기 연결 */
82
93
  display: flow-root;
83
94
 
84
95
  /* 세로 줄기는 항목 전체 기준 · 중간 항목의 소제목 옆에서도 연결 */
85
96
  position: relative;
86
97
 
98
+ &:has(> .wg_navigationBranchToggle__root) > .wg_navigationToc__link {
99
+ padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
100
+ }
101
+
87
102
  &::before {
88
103
  position: absolute;
89
104
  top: 0;
@@ -119,48 +134,48 @@
119
134
  }
120
135
 
121
136
  /* 뒤 항목까지의 세로 경로 · 같은 목록의 형제 안에서만 연결 */
122
- &:where(:has(~ .wg_shellToc__item:hover))::before {
137
+ &:where(:has(~ .wg_navigationToc__item:hover))::before {
123
138
  border-left-color: var(--app-color-text-strong);
124
139
  }
125
140
 
126
- &:where(:has(~ .wg_shellToc__item :focus-visible))::before {
141
+ &:where(:has(~ .wg_navigationToc__item :focus-visible))::before {
127
142
  border-left-color: var(--app-color-text-strong);
128
143
  }
129
144
 
130
145
  /* 하위 제목을 탐색할 때 상위 절의 가지도 연결 */
131
- &:where(:hover) > .wg_shellToc__link::before {
146
+ &:where(:hover) > .wg_navigationToc__link::before {
132
147
  border-top-color: var(--app-color-text-strong);
133
148
  }
134
149
 
135
- &:where(:has(:focus-visible)) > .wg_shellToc__link::before {
150
+ &:where(:has(:focus-visible)) > .wg_navigationToc__link::before {
136
151
  border-top-color: var(--app-color-text-strong);
137
152
  }
138
153
  }
139
154
 
140
- .wg_shellToc__item--trail {
155
+ .wg_navigationToc__item--trail {
141
156
  &::before {
142
157
  border-left-color: var(--app-color-text-strong);
143
158
  }
144
159
  }
145
160
 
146
- .wg_shellToc__item--current {
161
+ .wg_navigationToc__item--current {
147
162
  &::after {
148
163
  border-left-color: var(--app-color-text-strong);
149
164
  }
150
165
 
151
166
  /* 현재 소제목의 상위 절은 글 강조 없이 경로의 가로 가지 연결 */
152
- & > .wg_shellToc__link::before {
167
+ & > .wg_navigationToc__link::before {
153
168
  border-top-color: var(--app-color-text-strong);
154
169
  }
155
170
  }
156
171
 
157
- .wg_shellToc__sub {
172
+ .wg_navigationToc__sub {
158
173
  margin: var(--app-space-tree-row) 0 4px var(--app-space-tree-indent);
159
174
  padding: 0;
160
175
  list-style: none;
161
176
  }
162
177
 
163
- .wg_shellToc__subItem {
178
+ .wg_navigationToc__subItem {
164
179
  /* 하위 줄기는 소제목 항목 기준 · 마지막 소제목 첫 줄에서 종료 */
165
180
  position: relative;
166
181
 
@@ -199,28 +214,28 @@
199
214
  }
200
215
 
201
216
  /* 뒤 항목까지의 세로 경로 · 같은 목록의 형제 안에서만 연결 */
202
- &:where(:has(~ .wg_shellToc__subItem:hover))::before {
217
+ &:where(:has(~ .wg_navigationToc__subItem:hover))::before {
203
218
  border-left-color: var(--app-color-text-strong);
204
219
  }
205
220
 
206
- &:where(:has(~ .wg_shellToc__subItem :focus-visible))::before {
221
+ &:where(:has(~ .wg_navigationToc__subItem :focus-visible))::before {
207
222
  border-left-color: var(--app-color-text-strong);
208
223
  }
209
224
  }
210
225
 
211
- .wg_shellToc__subItem--trail {
226
+ .wg_navigationToc__subItem--trail {
212
227
  &::before {
213
228
  border-left-color: var(--app-color-text-strong);
214
229
  }
215
230
  }
216
231
 
217
- .wg_shellToc__subItem--current {
232
+ .wg_navigationToc__subItem--current {
218
233
  &::after {
219
234
  border-left-color: var(--app-color-text-strong);
220
235
  }
221
236
  }
222
237
 
223
- .wg_shellToc__subLink {
238
+ .wg_navigationToc__subLink {
224
239
  /* 하위 가지도 링크 첫 줄 기준 · 줄바꿈된 제목 옆으로 선이 늘어나지 않음 */
225
240
  position: relative;
226
241
  display: block;
@@ -261,7 +276,7 @@
261
276
  }
262
277
  }
263
278
 
264
- .wg_shellToc__subLink--active {
279
+ .wg_navigationToc__subLink--active {
265
280
  color: var(--app-color-text-strong);
266
281
  font-weight: var(--app-font-weight-active);
267
282