for-humanity 0.12.0 → 0.13.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.
Files changed (226) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +16 -9
  3. package/dist/browser.js +14 -16
  4. package/dist/cli.css +2 -968
  5. package/dist/cli.js +92 -2318
  6. package/dist/config.js +1 -0
  7. package/dist/constant/copy.d.ts +100 -0
  8. package/dist/constant/site.d.ts +20 -0
  9. package/dist/constant/status.d.ts +19 -0
  10. package/dist/copy-C1uzvEnr.js +103 -0
  11. package/dist/group-path-XAThmzvC.js +10 -0
  12. package/dist/load-site-B-u5-jv0.js +2343 -0
  13. package/dist/logger-Dv1i9xSV.js +9 -0
  14. package/dist/mermaid/THIRD-PARTY-NOTICES.txt +3134 -0
  15. package/dist/mermaid/chunk--TN-qHgG.js +2 -0
  16. package/dist/mermaid/chunk-0kM1Lv4D.js +2 -0
  17. package/dist/mermaid/chunk-3FHei3pH.js +2001 -0
  18. package/dist/mermaid/chunk-3_2p2GqN.js +2 -0
  19. package/dist/mermaid/chunk-6HLei9i0.js +84 -0
  20. package/dist/mermaid/chunk-7Sz3kAwl.js +2214 -0
  21. package/dist/mermaid/chunk-7Tarqbpa.js +18047 -0
  22. package/dist/mermaid/chunk-9kkt8lzL.js +10 -0
  23. package/dist/mermaid/chunk-B--pNBQF.js +884 -0
  24. package/dist/mermaid/chunk-B4F-pysn.js +4241 -0
  25. package/dist/mermaid/chunk-B58sEIY_.js +14 -0
  26. package/dist/mermaid/chunk-B9_UWzSH.js +1517 -0
  27. package/dist/mermaid/chunk-BB8uZHwY.js +75 -0
  28. package/dist/mermaid/chunk-BFfk0LEc.js +717 -0
  29. package/dist/mermaid/chunk-BKri0qr7.js +89 -0
  30. package/dist/mermaid/chunk-BL404pH5.js +26 -0
  31. package/dist/mermaid/chunk-BLeiQSWo.js +354 -0
  32. package/dist/mermaid/chunk-BOmH_UFd.js +2 -0
  33. package/dist/mermaid/chunk-BSej9Nhy.js +1361 -0
  34. package/dist/mermaid/chunk-BYzrzvCI.js +12 -0
  35. package/dist/mermaid/chunk-BariMtWr.js +3020 -0
  36. package/dist/mermaid/chunk-BcrBoMwH.js +2352 -0
  37. package/dist/mermaid/chunk-Bok8z-Yo.js +67 -0
  38. package/dist/mermaid/chunk-BpTHLKQM.js +1970 -0
  39. package/dist/mermaid/chunk-BqjuxRsC.js +733 -0
  40. package/dist/mermaid/chunk-BuvPd-s5.js +1073 -0
  41. package/dist/mermaid/chunk-BvVehae3.js +5069 -0
  42. package/dist/mermaid/chunk-C-JABYpd.js +3075 -0
  43. package/dist/mermaid/chunk-C9XlTm4w.js +2 -0
  44. package/dist/mermaid/chunk-CApNbSU9.js +6 -0
  45. package/dist/mermaid/chunk-CCM2AH-C.js +9 -0
  46. package/dist/mermaid/chunk-CD1E0F_N.js +2 -0
  47. package/dist/mermaid/chunk-CDWvKG7D.js +2 -0
  48. package/dist/mermaid/chunk-CEVPpC1F.js +34 -0
  49. package/dist/mermaid/chunk-CLDr12lf.js +47504 -0
  50. package/dist/mermaid/chunk-CLVYqOBI.js +61 -0
  51. package/dist/mermaid/chunk-CLeOkFb5.js +15 -0
  52. package/dist/mermaid/chunk-CLgRAtOz.js +37 -0
  53. package/dist/mermaid/chunk-CMqFNUBl.js +134 -0
  54. package/dist/mermaid/chunk-CTPaBJXB.js +2 -0
  55. package/dist/mermaid/chunk-CVi6IGBL.js +2 -0
  56. package/dist/mermaid/chunk-CWV_EN-4.js +4745 -0
  57. package/dist/mermaid/chunk-CZ0dAs3g.js +2 -0
  58. package/dist/mermaid/chunk-C_YGy4Fn.js +236 -0
  59. package/dist/mermaid/chunk-CcVH22Yt.js +100 -0
  60. package/dist/mermaid/chunk-CgG6CD9_.js +7175 -0
  61. package/dist/mermaid/chunk-CgOP6IDB.js +3397 -0
  62. package/dist/mermaid/chunk-Cgg2UTSf.js +13 -0
  63. package/dist/mermaid/chunk-ChJfJJ1A.js +214 -0
  64. package/dist/mermaid/chunk-Ck5XRA46.js +447 -0
  65. package/dist/mermaid/chunk-Ckuw16cl.js +203 -0
  66. package/dist/mermaid/chunk-CpAbRCbF.js +1880 -0
  67. package/dist/mermaid/chunk-CuYekbSv.js +2 -0
  68. package/dist/mermaid/chunk-CwS4wZ5a.js +2 -0
  69. package/dist/mermaid/chunk-D-bcrBO3.js +82 -0
  70. package/dist/mermaid/chunk-D3IEAkCW.js +76 -0
  71. package/dist/mermaid/chunk-D8XfBJ_K.js +645 -0
  72. package/dist/mermaid/chunk-D9Ddd9y4.js +2228 -0
  73. package/dist/mermaid/chunk-DBh1mIbK.js +12 -0
  74. package/dist/mermaid/chunk-DD6Df6Ic.js +5 -0
  75. package/dist/mermaid/chunk-DGVDaXjx.js +8 -0
  76. package/dist/mermaid/chunk-DK9KqIXj.js +632 -0
  77. package/dist/mermaid/chunk-DORnIAsy.js +4487 -0
  78. package/dist/mermaid/chunk-DU69_VcF.js +363 -0
  79. package/dist/mermaid/chunk-DVNvSFoz.js +2144 -0
  80. package/dist/mermaid/chunk-DZe-4kde.js +20 -0
  81. package/dist/mermaid/chunk-D_a06Rz4.js +287 -0
  82. package/dist/mermaid/chunk-DfyFJJi2.js +972 -0
  83. package/dist/mermaid/chunk-DhKYPp1Z.js +2 -0
  84. package/dist/mermaid/chunk-DjFqgNTG.js +94 -0
  85. package/dist/mermaid/chunk-DmbDDrr-.js +65 -0
  86. package/dist/mermaid/chunk-DpuxlyL_.js +696 -0
  87. package/dist/mermaid/chunk-DqGhppWe.js +2 -0
  88. package/dist/mermaid/chunk-DqPZxHXa.js +5 -0
  89. package/dist/mermaid/chunk-Dt_1Jyif.js +293 -0
  90. package/dist/mermaid/chunk-DyQBE_NW.js +1935 -0
  91. package/dist/mermaid/chunk-JckyC4mW.js +1009 -0
  92. package/dist/mermaid/chunk-K7Myuj2-.js +1334 -0
  93. package/dist/mermaid/chunk-KuPYb48V.js +275 -0
  94. package/dist/mermaid/chunk-MFVRUoO0.js +4020 -0
  95. package/dist/mermaid/chunk-MbInCS_6.js +28 -0
  96. package/dist/mermaid/chunk-MexOLyKV.js +355 -0
  97. package/dist/mermaid/chunk-NnbDtJzg.js +21856 -0
  98. package/dist/mermaid/chunk-SGpOYZbI.js +2139 -0
  99. package/dist/mermaid/chunk-TbxLDlcU.js +198 -0
  100. package/dist/mermaid/chunk-TftHqGLg.js +490 -0
  101. package/dist/mermaid/chunk-UjQ8vA_Z.js +4138 -0
  102. package/dist/mermaid/chunk-YgmVTKqc.js +16 -0
  103. package/dist/mermaid/chunk-_a9EZE1v.js +1798 -0
  104. package/dist/mermaid/chunk-dTb8jqeP.js +2 -0
  105. package/dist/mermaid/chunk-fFdMfF8S.js +2240 -0
  106. package/dist/mermaid/chunk-feYbMzBj.js +1267 -0
  107. package/dist/mermaid/chunk-g3Pn8DkW.js +46 -0
  108. package/dist/mermaid/chunk-hM77LvCb.js +19832 -0
  109. package/dist/mermaid/chunk-hUDb-eAW.js +527 -0
  110. package/dist/mermaid/chunk-tpABtZ-3.js +4252 -0
  111. package/dist/mermaid/chunk-xIbz3oFK.js +59 -0
  112. package/dist/mermaid/chunk-yBz-vst0.js +976 -0
  113. package/dist/mermaid/mermaid-BhtR3wyB.js +1145 -0
  114. package/dist/run-site-command-cqCjpIlc.js +129 -0
  115. package/dist/site-config-bllORGpm.js +90 -0
  116. package/dist/site.js +1 -0
  117. package/dist/start-dev-server-x7Ja5uwv.js +184 -0
  118. package/dist/to-change-queue-DbEnZGNK.js +34 -0
  119. package/dist/to-error-message-pF6_7wGK.js +16 -0
  120. package/dist/type/group-path.d.ts +7 -0
  121. package/dist/type/site-config.d.ts +57 -0
  122. package/package.json +34 -17
  123. package/src/component/widget/cursor-face/_constant/cursor-face.ts +0 -14
  124. package/src/component/widget/cursor-face/wg-cursor-face.css +0 -15
  125. package/src/component/widget/cursor-face/wg-cursor-face.tsx +0 -153
  126. package/src/component/widget/navigation/_constant/locale.ts +0 -9
  127. package/src/component/widget/navigation/_constant/navigation-data-schema.ts +0 -33
  128. package/src/component/widget/navigation/_constant/navigation.ts +0 -9
  129. package/src/component/widget/navigation/_constant/reading-line.ts +0 -4
  130. package/src/component/widget/navigation/_function/restore-navigation-scroll.ts +0 -59
  131. package/src/component/widget/navigation/_function/to-doc-groups/_to-doc-branches.ts +0 -15
  132. package/src/component/widget/navigation/_function/to-doc-groups/_to-doc-group-branches.ts +0 -70
  133. package/src/component/widget/navigation/_function/to-doc-groups/to-doc-groups.ts +0 -15
  134. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts +0 -13
  135. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts +0 -13
  136. package/src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts +0 -18
  137. package/src/component/widget/navigation/_function/to-navigation-json.ts +0 -8
  138. package/src/component/widget/navigation/_function/to-toc-groups.ts +0 -38
  139. package/src/component/widget/navigation/_type/doc-branch.ts +0 -11
  140. package/src/component/widget/navigation/_type/doc-group.ts +0 -24
  141. package/src/component/widget/navigation/_type/navigation-data.ts +0 -75
  142. package/src/component/widget/navigation/_type/navigation-focus-snapshot.ts +0 -17
  143. package/src/component/widget/navigation/_type/toc-group.ts +0 -39
  144. package/src/component/widget/navigation/_wg-navigation-nav-list.css +0 -48
  145. package/src/component/widget/navigation/_wg-navigation-nav-list.tsx +0 -61
  146. package/src/component/widget/navigation/_wg-navigation-nav.css +0 -21
  147. package/src/component/widget/navigation/_wg-navigation-nav.tsx +0 -33
  148. package/src/component/widget/navigation/_wg-navigation-scroll.tsx +0 -117
  149. package/src/component/widget/navigation/_wg-navigation-toc.css +0 -91
  150. package/src/component/widget/navigation/_wg-navigation-toc.tsx +0 -114
  151. package/src/component/widget/navigation/wg-navigation.css +0 -282
  152. package/src/component/widget/navigation/wg-navigation.tsx +0 -420
  153. package/src/component/widget/prose/_constant/heading-highlight.ts +0 -4
  154. package/src/component/widget/prose/_constant/section.ts +0 -7
  155. package/src/component/widget/prose/_constant/status.ts +0 -9
  156. package/src/component/widget/prose/_function/has-block-content.ts +0 -30
  157. package/src/component/widget/prose/_function/rehype-head.ts +0 -31
  158. package/src/component/widget/prose/_function/rehype-sections/_to-section-headings.ts +0 -20
  159. package/src/component/widget/prose/_function/rehype-sections/rehype-sections.ts +0 -21
  160. package/src/component/widget/prose/_function/rehype-tables.ts +0 -22
  161. package/src/component/widget/prose/_function/remark-blocks.ts +0 -112
  162. package/src/component/widget/prose/_function/remark-flow.ts +0 -26
  163. package/src/component/widget/prose/_function/remark-links.ts +0 -33
  164. package/src/component/widget/prose/_function/remark-parts.ts +0 -26
  165. package/src/component/widget/prose/_function/remark-status.ts +0 -59
  166. package/src/component/widget/prose/_function/remark-swatch.ts +0 -16
  167. package/src/component/widget/prose/_function/remark-unknown-directives.ts +0 -25
  168. package/src/component/widget/prose/wg-prose.css +0 -484
  169. package/src/component/widget/prose/wg-prose.tsx +0 -43
  170. package/src/component/widget/shell/wg-shell.css +0 -63
  171. package/src/component/widget/shell/wg-shell.tsx +0 -88
  172. package/src/component/widget/shell-controls/wg-shell-controls.css +0 -4
  173. package/src/component/widget/shell-controls/wg-shell-controls.tsx +0 -170
  174. package/src/constant/asset.ts +0 -63
  175. package/src/constant/copy.ts +0 -133
  176. package/src/constant/doc.ts +0 -13
  177. package/src/constant/font.ts +0 -34
  178. package/src/constant/site.ts +0 -24
  179. package/src/constant/status.ts +0 -15
  180. package/src/entry/browser/browser.tsx +0 -22
  181. package/src/entry/cli/_constant/cli.ts +0 -19
  182. package/src/entry/cli/_constant/crawling.ts +0 -14
  183. package/src/entry/cli/_constant/snippet.ts +0 -21
  184. package/src/entry/cli/_function/create-app.tsx +0 -57
  185. package/src/entry/cli/_function/create-dev-app.ts +0 -87
  186. package/src/entry/cli/_function/create-processor/_rehype-assets.ts +0 -70
  187. package/src/entry/cli/_function/create-processor/_rehype-heading-ids.ts +0 -34
  188. package/src/entry/cli/_function/create-processor/_remark-report.ts +0 -15
  189. package/src/entry/cli/_function/create-processor/_remark-snippets.ts +0 -117
  190. package/src/entry/cli/_function/create-processor/_shiki-transformers.ts +0 -91
  191. package/src/entry/cli/_function/create-processor/create-processor.ts +0 -64
  192. package/src/entry/cli/_function/read-docs.ts +0 -128
  193. package/src/entry/cli/_function/read-home.ts +0 -32
  194. package/src/entry/cli/_function/to-crawling-app.ts +0 -42
  195. package/src/entry/cli/cli.test.ts +0 -804
  196. package/src/entry/cli/cli.ts +0 -206
  197. package/src/env.d.ts +0 -6
  198. package/src/page/doc/pg-doc.tsx +0 -35
  199. package/src/page/home/pg-home.tsx +0 -40
  200. package/src/store/navigation/create-navigation-stores.test.ts +0 -74
  201. package/src/store/navigation/create-navigation-stores.ts +0 -59
  202. package/src/store/navigation/navigation-state.ts +0 -36
  203. package/src/store/navigation/navigation-storage.ts +0 -9
  204. package/src/store/navigation/to-navigation-scroll-state.ts +0 -42
  205. package/src/style/base.css +0 -28
  206. package/src/style/token.css +0 -188
  207. package/src/type/doc-content.ts +0 -15
  208. package/src/type/doc-data.ts +0 -38
  209. package/src/type/doc-file-data.ts +0 -21
  210. package/src/type/doc-heading.ts +0 -17
  211. package/src/type/doc-outline.ts +0 -16
  212. package/src/type/doc-section.ts +0 -9
  213. package/src/type/doc.ts +0 -20
  214. package/src/type/group-path.ts +0 -7
  215. package/src/type/site-assets.ts +0 -25
  216. package/src/type/site-config.ts +0 -73
  217. package/src/type/vfile-data.d.ts +0 -10
  218. package/src/util/async/to-change-queue.test.ts +0 -58
  219. package/src/util/async/to-change-queue.ts +0 -43
  220. package/src/util/dom/find-hash-target.ts +0 -18
  221. package/src/util/dom/reveal-hash-target.ts +0 -15
  222. package/src/util/error/to-error-message.ts +0 -10
  223. package/src/util/file/to-asset-path.ts +0 -26
  224. package/src/util/font/to-font-css.test.ts +0 -41
  225. package/src/util/font/to-font-css.ts +0 -28
  226. package/src/util/mermaid/render-flow.js +0 -321
@@ -1,48 +0,0 @@
1
- /*
2
- * 재귀 문서 목록 · 단계별 들여쓰기
3
- */
4
- .wg_navigationNavList__root {
5
- margin: 0;
6
- padding: 0;
7
- list-style: none;
8
- }
9
-
10
- .wg_navigationNavList__branch {
11
- display: block;
12
- padding: var(--app-space-tree-row) 0;
13
- color: var(--app-color-text-muted);
14
- font-size: var(--app-font-size-group);
15
- line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
16
- overflow-wrap: anywhere;
17
- }
18
-
19
- .wg_navigationNavList__link {
20
- display: block;
21
- padding: var(--app-space-tree-row) 0;
22
- color: var(--app-color-link);
23
- font-size: var(--app-font-size-dense);
24
- line-height: var(--app-line-height-tight);
25
- text-decoration: none;
26
- overflow-wrap: anywhere;
27
-
28
- &:where(:hover) {
29
- text-decoration: underline;
30
- }
31
-
32
- /* hover와 같은 밑줄로 키보드 위치 표시 */
33
- &:where(:focus-visible) {
34
- outline: none;
35
- text-decoration: underline;
36
- }
37
- }
38
-
39
- .wg_navigationNavList__link--active {
40
- color: var(--app-color-link);
41
- font-weight: var(--app-font-weight-active);
42
- }
43
-
44
- .wg_navigationNavList__item {
45
- & > .wg_navigationNavList__root {
46
- margin-left: var(--app-space-tree-indent);
47
- }
48
- }
@@ -1,61 +0,0 @@
1
- import clsx from "clsx";
2
- import {Fragment} from "hono/jsx";
3
- import type {NavigationGroup} from "@/component/widget/navigation/_type/navigation-data";
4
- import "./_wg-navigation-nav-list.css";
5
-
6
- /**
7
- * 한 단계의 문서 목록과 하위 묶음 · 재귀에서도 같은 탐색 표현 유지
8
- */
9
- export interface WgNavigationNavListProps {
10
- /**
11
- * 현재 단계의 문서와 하위 묶음
12
- */
13
- group: NavigationGroup;
14
- }
15
-
16
- export const WgNavigationNavList = (props: WgNavigationNavListProps) => {
17
- const entries = [
18
- ...props.group.docs.map((doc) => ({kind: "document" as const, key: `doc:${doc.id}`, doc})),
19
- ...props.group.groups.map((group) => ({kind: "group" as const, key: `group:${JSON.stringify(group.path)}`, group})),
20
- ];
21
-
22
- return (
23
- <ul className={clsx("wg_navigationNavList__root")} aria-label={props.group.name}>
24
- {/**
25
- * 문서 링크는 원래 파일 URL 사용
26
- */}
27
- {entries.map((entry) => (
28
- <li className={clsx("wg_navigationNavList__item")} key={entry.key}>
29
- {/**
30
- * 문서 링크 · 부모도 독립 페이지, 현재 한 문서에만 페이지 상태 부여
31
- */}
32
- {entry.kind === "document" && (
33
- <Fragment>
34
- <a
35
- className={clsx("wg_navigationNavList__link", {"wg_navigationNavList__link--active": entry.doc.active})}
36
- href={`/${entry.doc.id}/`}
37
- title={entry.doc.label}
38
- aria-current={entry.doc.active ? "page" : undefined}
39
- >
40
- {entry.doc.name}
41
- </a>
42
- {/**
43
- * 하위 문서 · 부모 아래에서도 기존 목록의 들여쓰기와 키보드 이동 유지
44
- */}
45
- {entry.doc.children.length > 0 && <WgNavigationNavList group={{name: entry.doc.name, path: props.group.path, docs: entry.doc.children, groups: []}} />}
46
- </Fragment>
47
- )}
48
- {/**
49
- * 하위 묶음 · 같은 목록을 재귀로 이어 깊이에 따라 들여쓰기
50
- */}
51
- {entry.kind === "group" && (
52
- <Fragment>
53
- <span className={clsx("wg_navigationNavList__branch")}>{entry.group.name}</span>
54
- <WgNavigationNavList group={entry.group} />
55
- </Fragment>
56
- )}
57
- </li>
58
- ))}
59
- </ul>
60
- );
61
- };
@@ -1,21 +0,0 @@
1
- /*
2
- * 읽는 순서의 문서 목록 · 작은 회색 묶음과 링크색 문서
3
- */
4
- .wg_navigationNav__root {
5
- font-size: var(--app-font-size-dense);
6
- line-height: var(--app-line-height-tight);
7
- }
8
-
9
- .wg_navigationNav__docs {
10
- display: flex;
11
- flex-direction: column;
12
- gap: var(--app-space-tree-group);
13
- }
14
-
15
- .wg_navigationNav__group {
16
- margin: 0 0 var(--app-space-tree-label);
17
- color: var(--app-color-text-muted);
18
- font-size: var(--app-font-size-group);
19
- line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
20
- text-box: trim-start cap alphabetic;
21
- }
@@ -1,33 +0,0 @@
1
- import clsx from "clsx";
2
- import type {NavigationGroup} from "@/component/widget/navigation/_type/navigation-data";
3
- import {WgNavigationNavList} from "@/component/widget/navigation/_wg-navigation-nav-list";
4
- import {copy_nav_aria_label} from "@/constant/copy";
5
- import "./_wg-navigation-nav.css";
6
-
7
- /**
8
- * 서버·브라우저가 공유하는 문서 트리
9
- */
10
- export interface WgNavigationNavProps {
11
- /**
12
- * 본문을 제외한 읽는 순서의 문서 묶음
13
- */
14
- groups: NavigationGroup[];
15
- }
16
-
17
- export const WgNavigationNav = (props: WgNavigationNavProps) => {
18
- return (
19
- <nav className={clsx("wg_navigationNav__root")} aria-label={copy_nav_aria_label}>
20
- {/**
21
- * 문서 이동 · 클릭하지 않는 묶음과 독립 문서
22
- */}
23
- <div className={clsx("wg_navigationNav__docs")}>
24
- {props.groups.map((group) => (
25
- <section className={clsx("wg_navigationNav__docGroup")} key={JSON.stringify(group.path)} aria-label={group.name}>
26
- <div className={clsx("wg_navigationNav__group")}>{group.name}</div>
27
- <WgNavigationNavList group={group} />
28
- </section>
29
- ))}
30
- </div>
31
- </nav>
32
- );
33
- };
@@ -1,117 +0,0 @@
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,91 +0,0 @@
1
- /*
2
- * 와이드 화면의 오른쪽 목차 · 라벨·묶음은 문서 탐색의 묶음과 같은 표현
3
- */
4
- .wg_navigationToc__root {
5
- font-size: var(--app-font-size-dense);
6
- line-height: var(--app-line-height-tight);
7
- }
8
-
9
- .wg_navigationToc__label {
10
- margin: 0 0 var(--app-space-tree-label);
11
- color: var(--app-color-text-muted);
12
- font-size: var(--app-font-size-group);
13
- line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
14
- text-box: trim-start cap alphabetic;
15
- }
16
-
17
- .wg_navigationToc__group {
18
- margin: 0 0 var(--app-space-tree-label);
19
- color: var(--app-color-text-muted);
20
- font-size: var(--app-font-size-group);
21
- line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
22
- text-box: trim-start cap alphabetic;
23
- }
24
-
25
- .wg_navigationToc__groupSection--named {
26
- margin-top: var(--app-space-tree-group);
27
- }
28
-
29
- .wg_navigationToc__list {
30
- margin: 0;
31
- padding: 0;
32
- list-style: none;
33
- }
34
-
35
- .wg_navigationToc__link {
36
- display: block;
37
- padding: var(--app-space-tree-row) 0;
38
- color: var(--app-color-text);
39
- font-size: var(--app-font-size-dense);
40
- line-height: var(--app-line-height-tight);
41
- text-decoration: none;
42
-
43
- &:where(:hover) {
44
- color: var(--app-color-text-strong);
45
- text-decoration: underline;
46
- }
47
-
48
- /* 박스 대신 hover와 같은 진한 글·밑줄로 키보드 위치 표시 */
49
- &:where(:focus-visible) {
50
- outline: none;
51
- color: var(--app-color-text-strong);
52
- text-decoration: underline;
53
- }
54
- }
55
-
56
- .wg_navigationToc__link--active {
57
- color: var(--app-color-text-strong);
58
- font-weight: var(--app-font-weight-active);
59
- }
60
-
61
- .wg_navigationToc__sub {
62
- margin: var(--app-space-tree-row) 0 4px var(--app-space-tree-indent);
63
- padding: 0;
64
- list-style: none;
65
- }
66
-
67
- .wg_navigationToc__subLink {
68
- display: block;
69
- padding: var(--app-space-tree-row) 0;
70
- color: var(--app-color-text);
71
- font-size: var(--app-font-size-detail);
72
- line-height: var(--app-line-height-tight);
73
- text-decoration: none;
74
-
75
- &:where(:hover) {
76
- color: var(--app-color-text-strong);
77
- text-decoration: underline;
78
- }
79
-
80
- /* 상위 목차와 같은 키보드 표현 */
81
- &:where(:focus-visible) {
82
- outline: none;
83
- color: var(--app-color-text-strong);
84
- text-decoration: underline;
85
- }
86
- }
87
-
88
- .wg_navigationToc__subLink--active {
89
- color: var(--app-color-text-strong);
90
- font-weight: var(--app-font-weight-active);
91
- }
@@ -1,114 +0,0 @@
1
- import clsx from "clsx";
2
- import {useLayoutEffect, useState} from "hono/jsx";
3
- import {reading_line_slack_px} from "@/component/widget/navigation/_constant/reading-line";
4
- import type {TocGroup} from "@/component/widget/navigation/_type/toc-group";
5
- import {copy_nav_toc_label} from "@/constant/copy";
6
- import {findHashTarget} from "@/util/dom/find-hash-target";
7
- import "./_wg-navigation-toc.css";
8
-
9
- /**
10
- * 현재 문서의 목차 · 읽는 제목 한 항목만 강조
11
- */
12
- export interface WgNavigationTocProps {
13
- /**
14
- * 본문 순서의 가름·절·소제목
15
- */
16
- groups: TocGroup[];
17
- }
18
-
19
- export const WgNavigationToc = (props: WgNavigationTocProps) => {
20
- const [currentSlug, setCurrentSlug] = useState<string>();
21
-
22
- /**
23
- * 구독은 연결마다 한 번 설치 · 초기 갱신은 본문 파싱 이후로 미룸
24
- */
25
- useLayoutEffect(() => {
26
- const sections = props.groups.flatMap((group) => group.sections);
27
- const headings = sections.flatMap((section) => [section.heading, ...section.subs.map((sub) => sub.heading)]);
28
- const frame = {id: 0};
29
-
30
- /**
31
- * 접힌 본문 제목은 제외하고 읽는 선을 통과한 마지막 제목 선택
32
- */
33
- const updateCurrentHeading = () => {
34
- frame.id = 0;
35
- const visible = headings.flatMap((heading) => {
36
- const target = findHashTarget(`#${heading.slug}`);
37
- return target?.checkVisibility()
38
- ? [{slug: heading.slug, top: target.getBoundingClientRect().top - Number.parseFloat(getComputedStyle(target).scrollMarginTop)}]
39
- : [];
40
- });
41
- setCurrentSlug(visible.findLast((heading) => heading.top <= reading_line_slack_px)?.slug ?? visible[0]?.slug);
42
- };
43
-
44
- /**
45
- * 연속 스크롤은 프레임당 한 번만 읽음
46
- */
47
- const handleReadingPositionChange = () => {
48
- if (frame.id === 0) frame.id = requestAnimationFrame(updateCurrentHeading);
49
- };
50
-
51
- addEventListener("scroll", handleReadingPositionChange, {passive: true});
52
- addEventListener("resize", handleReadingPositionChange);
53
- addEventListener("toggle", handleReadingPositionChange, true);
54
- addEventListener("pageshow", handleReadingPositionChange);
55
- document.addEventListener("DOMContentLoaded", handleReadingPositionChange);
56
- if (document.readyState !== "loading") updateCurrentHeading();
57
-
58
- return () => {
59
- cancelAnimationFrame(frame.id);
60
- removeEventListener("scroll", handleReadingPositionChange);
61
- removeEventListener("resize", handleReadingPositionChange);
62
- removeEventListener("toggle", handleReadingPositionChange, true);
63
- removeEventListener("pageshow", handleReadingPositionChange);
64
- document.removeEventListener("DOMContentLoaded", handleReadingPositionChange);
65
- };
66
- }, [props.groups]);
67
-
68
- return (
69
- <nav className={clsx("wg_navigationToc__root")} aria-label={copy_nav_toc_label}>
70
- <div className={clsx("wg_navigationToc__label")}>{copy_nav_toc_label}</div>
71
- {/**
72
- * 가름별 제목 이동 · 하위 제목이 현재 위치여도 부모 글씨는 강조하지 않음
73
- */}
74
- {props.groups.map((group) => (
75
- <div className={clsx("wg_navigationToc__groupSection", {"wg_navigationToc__groupSection--named": group.part !== undefined})} key={group.sections[0].heading.slug}>
76
- {group.part !== undefined && <div className={clsx("wg_navigationToc__group")}>{group.part}</div>}
77
- <ul className={clsx("wg_navigationToc__list")}>
78
- {group.sections.map((section) => (
79
- <li className={clsx("wg_navigationToc__item")} key={section.heading.slug}>
80
- <a
81
- className={clsx("wg_navigationToc__link", {"wg_navigationToc__link--active": section.heading.slug === currentSlug})}
82
- href={`#${section.heading.slug}`}
83
- data-toc-link=""
84
- aria-current={section.heading.slug === currentSlug ? "location" : undefined}
85
- >
86
- {section.heading.text}
87
- </a>
88
- {/**
89
- * 하위 제목 · 활성 링크는 한 제목만
90
- */}
91
- {section.subs.length > 0 && (
92
- <ul className={clsx("wg_navigationToc__sub")}>
93
- {section.subs.map((sub) => (
94
- <li className={clsx("wg_navigationToc__subItem")} key={sub.heading.slug}>
95
- <a
96
- className={clsx("wg_navigationToc__subLink", {"wg_navigationToc__subLink--active": sub.heading.slug === currentSlug})}
97
- href={`#${sub.heading.slug}`}
98
- data-toc-sub-link=""
99
- aria-current={sub.heading.slug === currentSlug ? "location" : undefined}
100
- >
101
- {sub.heading.text}
102
- </a>
103
- </li>
104
- ))}
105
- </ul>
106
- )}
107
- </li>
108
- ))}
109
- </ul>
110
- </div>
111
- ))}
112
- </nav>
113
- );
114
- };