@naeil/ui 0.9.0 → 0.11.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 (61) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -5
  3. package/dist/{chunk-XRO3NJAB.js → chunk-KWEWR46R.js} +40 -154
  4. package/dist/{chunk-JDHGKM25.js → chunk-U3IZCFM4.js} +267 -2
  5. package/dist/components/index.js +12 -3
  6. package/dist/components/naeil-footer.d.ts +3 -3
  7. package/dist/components/naeil-footer.js +14 -11
  8. package/dist/components/naeil-header.d.ts +7 -9
  9. package/dist/components/naeil-header.js +2 -2
  10. package/dist/lib/ui-release.d.ts +1 -1
  11. package/dist/lib/ui-release.js +1 -1
  12. package/dist/naeil-locale/checker.d.ts +16 -0
  13. package/dist/naeil-locale/checker.js +91 -0
  14. package/dist/naeil-locale/chrome.d.ts +150 -0
  15. package/dist/naeil-locale/chrome.js +2385 -0
  16. package/dist/naeil-locale/chunk-4U64K4J3.js +56 -0
  17. package/dist/naeil-locale/chunk-N3ETBM74.js +24 -0
  18. package/dist/naeil-locale/chunk-U65OQHZY.js +167 -0
  19. package/dist/naeil-locale/chunk-YQ5OJWBF.js +53 -0
  20. package/dist/naeil-locale/client.d.ts +70 -0
  21. package/dist/naeil-locale/client.js +388 -0
  22. package/dist/naeil-locale/en-ZC66VDHP.js +86 -0
  23. package/dist/naeil-locale/index.d.ts +40 -0
  24. package/dist/naeil-locale/index.js +111 -0
  25. package/dist/naeil-locale/ja-DKIEQUG7.js +86 -0
  26. package/dist/naeil-locale/ko-CY6663RZ.js +86 -0
  27. package/dist/naeil-locale/messages-BuQvB-u2.d.ts +167 -0
  28. package/dist/naeil-locale/messages.d.ts +1 -0
  29. package/dist/naeil-locale/messages.js +14 -0
  30. package/dist/naeil-locale/server.d.ts +75 -0
  31. package/dist/naeil-locale/server.js +172 -0
  32. package/dist/source/components/naeil-footer-core.d.ts +16 -0
  33. package/dist/source/components/naeil-footer-core.js +93 -0
  34. package/dist/source/components/naeil-footer.d.ts +6 -11
  35. package/dist/source/components/naeil-footer.js +4 -75
  36. package/dist/source/components/naeil-header-account-core.d.ts +26 -0
  37. package/dist/source/components/naeil-header-account-core.js +98 -0
  38. package/dist/source/components/naeil-header-account.d.ts +6 -22
  39. package/dist/source/components/naeil-header-account.js +5 -81
  40. package/dist/source/components/naeil-header-content.d.ts +102 -109
  41. package/dist/source/components/naeil-header-content.js +6 -142
  42. package/dist/source/components/naeil-header-core.d.ts +59 -0
  43. package/dist/source/components/naeil-header-core.js +231 -0
  44. package/dist/source/components/naeil-header-data.d.ts +11 -0
  45. package/dist/source/components/naeil-header-data.js +14 -0
  46. package/dist/source/components/naeil-header.d.ts +10 -51
  47. package/dist/source/components/naeil-header.js +9 -200
  48. package/dist/source/components/naeil-messages-context.d.ts +94 -0
  49. package/dist/source/components/naeil-messages-context.js +16 -0
  50. package/dist/source/components/naeil-standalone-messages.d.ts +11 -0
  51. package/dist/source/components/naeil-standalone-messages.js +13 -0
  52. package/dist/source/i18n/routing.d.ts +22 -20
  53. package/dist/source/lib/ui-release.d.ts +1 -1
  54. package/dist/source/lib/ui-release.js +1 -1
  55. package/dist/source/naeil-locale/messages/en.json +78 -0
  56. package/dist/source/naeil-locale/messages/ja.json +78 -0
  57. package/dist/source/naeil-locale/messages/ko.json +78 -0
  58. package/docs/components/naeil-locale.md +52 -0
  59. package/docs/package-release.md +31 -6
  60. package/package.json +35 -7
  61. /package/dist/{naeil-header-content-BvISJ4RV.d.ts → naeil-header-data-BvISJ4RV.d.ts} +0 -0
@@ -0,0 +1,11 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { NaeilHeaderLocale } from './naeil-header-data.js';
4
+
5
+ /** Only the standalone compatibility entry includes all three small dictionaries. */
6
+ declare function NaeilStandaloneMessages({ locale, children }: {
7
+ locale: NaeilHeaderLocale;
8
+ children: ReactNode;
9
+ }): react_jsx_runtime.JSX.Element;
10
+
11
+ export { NaeilStandaloneMessages };
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import en from "../naeil-locale/messages/en.json";
4
+ import ko from "../naeil-locale/messages/ko.json";
5
+ import ja from "../naeil-locale/messages/ja.json";
6
+ import { NaeilMessagesProvider } from "./naeil-messages-context.js";
7
+ const messages = { en: en.naeil, ko: ko.naeil, ja: ja.naeil };
8
+ function NaeilStandaloneMessages({ locale, children }) {
9
+ return /* @__PURE__ */ jsx(NaeilMessagesProvider, { locale, messages: messages[locale], children });
10
+ }
11
+ export {
12
+ NaeilStandaloneMessages
13
+ };
@@ -1,5 +1,5 @@
1
1
  import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
2
- import * as next_navigation from 'next/navigation';
2
+ import * as next_dist_client_components_redirect_error from 'next/dist/client/components/redirect-error';
3
3
  import * as next_intl_navigation from 'next-intl/navigation';
4
4
  import * as url from 'url';
5
5
  import * as react from 'react';
@@ -31,8 +31,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
31
31
  style?: react.CSSProperties | undefined;
32
32
  title?: string | undefined | undefined;
33
33
  locale?: string | undefined;
34
- onError?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
35
- children?: react.ReactNode;
36
34
  ref?: react.Ref<HTMLAnchorElement> | undefined;
37
35
  prefix?: string | undefined | undefined;
38
36
  key?: react.Key | null | undefined;
@@ -42,12 +40,10 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
42
40
  passHref?: boolean | undefined;
43
41
  prefetch?: boolean | "auto" | null | undefined;
44
42
  legacyBehavior?: boolean | undefined;
45
- onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
46
- onTouchStart?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
47
- onClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
48
43
  onNavigate?: ((event: {
49
44
  preventDefault: () => void;
50
45
  }) => void) | undefined;
46
+ transitionTypes?: string[] | undefined;
51
47
  download?: any;
52
48
  hrefLang?: string | undefined | undefined;
53
49
  media?: string | undefined | undefined;
@@ -104,7 +100,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
104
100
  is?: string | undefined | undefined;
105
101
  exportparts?: string | undefined | undefined;
106
102
  part?: string | undefined | undefined;
107
- tw?: string | undefined;
108
103
  "aria-activedescendant"?: string | undefined | undefined;
109
104
  "aria-atomic"?: (boolean | "true" | "false") | undefined;
110
105
  "aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
@@ -158,6 +153,8 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
158
153
  "aria-valuemin"?: number | undefined | undefined;
159
154
  "aria-valuenow"?: number | undefined | undefined;
160
155
  "aria-valuetext"?: string | undefined | undefined;
156
+ href: string | url.UrlObject;
157
+ children?: react.ReactNode;
161
158
  dangerouslySetInnerHTML?: {
162
159
  __html: string | TrustedHTML;
163
160
  } | undefined | undefined;
@@ -177,20 +174,21 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
177
174
  onFocusCapture?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
178
175
  onBlur?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
179
176
  onBlurCapture?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
180
- onChange?: react.FormEventHandler<HTMLAnchorElement> | undefined;
181
- onChangeCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
177
+ onChange?: react.ChangeEventHandler<HTMLAnchorElement, Element> | undefined;
178
+ onChangeCapture?: react.ChangeEventHandler<HTMLAnchorElement, Element> | undefined;
182
179
  onBeforeInput?: react.InputEventHandler<HTMLAnchorElement> | undefined;
183
- onBeforeInputCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
184
- onInput?: react.FormEventHandler<HTMLAnchorElement> | undefined;
185
- onInputCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
186
- onReset?: react.FormEventHandler<HTMLAnchorElement> | undefined;
187
- onResetCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
188
- onSubmit?: react.FormEventHandler<HTMLAnchorElement> | undefined;
189
- onSubmitCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
190
- onInvalid?: react.FormEventHandler<HTMLAnchorElement> | undefined;
191
- onInvalidCapture?: react.FormEventHandler<HTMLAnchorElement> | undefined;
180
+ onBeforeInputCapture?: react.InputEventHandler<HTMLAnchorElement> | undefined;
181
+ onInput?: react.InputEventHandler<HTMLAnchorElement> | undefined;
182
+ onInputCapture?: react.InputEventHandler<HTMLAnchorElement> | undefined;
183
+ onReset?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
184
+ onResetCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
185
+ onSubmit?: react.SubmitEventHandler<HTMLAnchorElement> | undefined;
186
+ onSubmitCapture?: react.SubmitEventHandler<HTMLAnchorElement> | undefined;
187
+ onInvalid?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
188
+ onInvalidCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
192
189
  onLoad?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
193
190
  onLoadCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
191
+ onError?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
194
192
  onErrorCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
195
193
  onKeyDown?: react.KeyboardEventHandler<HTMLAnchorElement> | undefined;
196
194
  onKeyDownCapture?: react.KeyboardEventHandler<HTMLAnchorElement> | undefined;
@@ -244,6 +242,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
244
242
  onWaitingCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
245
243
  onAuxClick?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
246
244
  onAuxClickCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
245
+ onClick?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
247
246
  onClickCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
248
247
  onContextMenu?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
249
248
  onContextMenuCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
@@ -267,6 +266,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
267
266
  onDropCapture?: react.DragEventHandler<HTMLAnchorElement> | undefined;
268
267
  onMouseDown?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
269
268
  onMouseDownCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
269
+ onMouseEnter?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
270
270
  onMouseLeave?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
271
271
  onMouseMove?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
272
272
  onMouseMoveCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
@@ -284,6 +284,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
284
284
  onTouchEndCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
285
285
  onTouchMove?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
286
286
  onTouchMoveCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
287
+ onTouchStart?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
287
288
  onTouchStartCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
288
289
  onPointerDown?: react.PointerEventHandler<HTMLAnchorElement> | undefined;
289
290
  onPointerDownCapture?: react.PointerEventHandler<HTMLAnchorElement> | undefined;
@@ -325,7 +326,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
325
326
  onTransitionRunCapture?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
326
327
  onTransitionStart?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
327
328
  onTransitionStartCapture?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
328
- href: string | url.UrlObject;
329
329
  }, "ref"> & react.RefAttributes<HTMLAnchorElement>>;
330
330
  declare const redirect: (args: {
331
331
  href: string | {
@@ -334,7 +334,7 @@ declare const redirect: (args: {
334
334
  };
335
335
  locale: string;
336
336
  forcePrefix?: boolean;
337
- }, type?: next_navigation.RedirectType | undefined) => never;
337
+ }, type?: next_dist_client_components_redirect_error.RedirectType | undefined) => never;
338
338
  declare const usePathname: () => string;
339
339
  declare const useRouter: () => {
340
340
  push: (href: string | {
@@ -358,6 +358,8 @@ declare const useRouter: () => {
358
358
  back(): void;
359
359
  forward(): void;
360
360
  refresh(): void;
361
+ experimental_gesturePush?(href: string, options?: next_dist_shared_lib_app_router_context_shared_runtime.NavigateOptions): void;
362
+ bfcacheId: string;
361
363
  };
362
364
  declare const getPathname: (args: {
363
365
  href: string | {
@@ -1,5 +1,5 @@
1
1
  declare const uiRelease: {
2
- readonly version: "0.9.0";
2
+ readonly version: "0.11.0";
3
3
  readonly contractVersion: "1";
4
4
  };
5
5
 
@@ -1,4 +1,4 @@
1
- const uiRelease = { version: "0.9.0", contractVersion: "1" };
1
+ const uiRelease = { version: "0.11.0", contractVersion: "1" };
2
2
  export {
3
3
  uiRelease
4
4
  };
@@ -0,0 +1,78 @@
1
+ {
2
+ "naeil": {
3
+ "header": {
4
+ "nav": {
5
+ "home": "Home",
6
+ "projects": "Projects",
7
+ "blog": "Blog",
8
+ "navigation": "Main navigation",
9
+ "menu": "Menu",
10
+ "closeMenu": "Close menu"
11
+ },
12
+ "theme": {
13
+ "switchToLight": "Switch to light theme",
14
+ "switchToDark": "Switch to dark theme"
15
+ },
16
+ "locale": {
17
+ "switchLabel": "Language"
18
+ },
19
+ "projects": {
20
+ "cc": {
21
+ "name": "Content Collector",
22
+ "description": "Automated content collection from RSS, YouTube, Reddit + AI summarization"
23
+ },
24
+ "pkm": {
25
+ "name": "PKM",
26
+ "description": "Personal knowledge management — document parsing, embeddings, semantic search"
27
+ },
28
+ "naeilUi": {
29
+ "name": "naeil-ui",
30
+ "description": "Minimal design system — OKLCH tokens, Tailwind v4, shadcn"
31
+ },
32
+ "sa": {
33
+ "name": "Sustainability Analyzer",
34
+ "description": "AI-powered ESG report analysis — PDF parsing, qualitative assessment, comparison tables"
35
+ },
36
+ "babyAgent": {
37
+ "name": "Baby Agent",
38
+ "description": "Parenting AI agent — LINE-based Q&A, records, reminders"
39
+ },
40
+ "status": {
41
+ "active": "Active",
42
+ "coming": "Coming Soon"
43
+ }
44
+ }
45
+ },
46
+ "account": {
47
+ "menu": "Account menu",
48
+ "account": "Account",
49
+ "login": "Log in",
50
+ "logout": "Log out",
51
+ "busy": "Logging out…"
52
+ },
53
+ "footer": {
54
+ "navigation": "Navigation",
55
+ "projects": "Projects",
56
+ "blog": "Blog",
57
+ "social": "Social",
58
+ "description": "Tomorrow starts here."
59
+ },
60
+ "locale": {
61
+ "names": {
62
+ "en": "English",
63
+ "ko": "한국어",
64
+ "ja": "日本語"
65
+ },
66
+ "pending": "Changing language…",
67
+ "failed": "The language could not be changed. Your work is still here.",
68
+ "retry": "Try again",
69
+ "errors": {
70
+ "badRequest": "This address is not valid.",
71
+ "notFound": "Page not found.",
72
+ "unauthenticated": "Sign in to continue.",
73
+ "forbidden": "You do not have access to this page.",
74
+ "unavailable": "The service is temporarily unavailable. Please try again."
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "naeil": {
3
+ "header": {
4
+ "nav": {
5
+ "home": "ホーム",
6
+ "projects": "プロジェクト",
7
+ "blog": "ブログ",
8
+ "navigation": "メインナビゲーション",
9
+ "menu": "メニュー",
10
+ "closeMenu": "メニューを閉じる"
11
+ },
12
+ "theme": {
13
+ "switchToLight": "ライトテーマに切り替える",
14
+ "switchToDark": "ダークテーマに切り替える"
15
+ },
16
+ "locale": {
17
+ "switchLabel": "言語"
18
+ },
19
+ "projects": {
20
+ "cc": {
21
+ "name": "Content Collector",
22
+ "description": "RSS、YouTube、Redditの自動収集 + AI要約"
23
+ },
24
+ "pkm": {
25
+ "name": "PKM",
26
+ "description": "個人ナレッジ管理 — ドキュメント解析、埋め込み、セマンティック検索"
27
+ },
28
+ "naeilUi": {
29
+ "name": "naeil-ui",
30
+ "description": "ミニマルデザインシステム — OKLCHトークン、Tailwind v4、shadcn"
31
+ },
32
+ "sa": {
33
+ "name": "Sustainability Analyzer",
34
+ "description": "ESGレポートAI分析 — PDF解析、定性評価、比較表の自動生成"
35
+ },
36
+ "babyAgent": {
37
+ "name": "Baby Agent",
38
+ "description": "育児AIエージェント — LINE Q&A、記録、リマインダー"
39
+ },
40
+ "status": {
41
+ "active": "アクティブ",
42
+ "coming": "準備中"
43
+ }
44
+ }
45
+ },
46
+ "account": {
47
+ "menu": "アカウントメニュー",
48
+ "account": "アカウント",
49
+ "login": "ログイン",
50
+ "logout": "ログアウト",
51
+ "busy": "ログアウト中…"
52
+ },
53
+ "footer": {
54
+ "navigation": "ナビゲーション",
55
+ "projects": "プロジェクト",
56
+ "blog": "ブログ",
57
+ "social": "ソーシャル",
58
+ "description": "Tomorrow starts here."
59
+ },
60
+ "locale": {
61
+ "names": {
62
+ "en": "English",
63
+ "ko": "한국어",
64
+ "ja": "日本語"
65
+ },
66
+ "pending": "言語を変更しています…",
67
+ "failed": "言語を変更できませんでした。作業内容は保持されています。",
68
+ "retry": "再試行",
69
+ "errors": {
70
+ "badRequest": "このアドレスは無効です。",
71
+ "notFound": "ページが見つかりません。",
72
+ "unauthenticated": "続けるにはログインしてください。",
73
+ "forbidden": "このページへのアクセス権限がありません。",
74
+ "unavailable": "サービスを一時的に利用できません。もう一度お試しください。"
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "naeil": {
3
+ "header": {
4
+ "nav": {
5
+ "home": "홈",
6
+ "projects": "프로젝트",
7
+ "blog": "블로그",
8
+ "navigation": "주요 메뉴",
9
+ "menu": "메뉴",
10
+ "closeMenu": "메뉴 닫기"
11
+ },
12
+ "theme": {
13
+ "switchToLight": "밝은 테마로 전환",
14
+ "switchToDark": "어두운 테마로 전환"
15
+ },
16
+ "locale": {
17
+ "switchLabel": "언어"
18
+ },
19
+ "projects": {
20
+ "cc": {
21
+ "name": "Content Collector",
22
+ "description": "RSS, YouTube, Reddit 자동 수집 + AI 요약"
23
+ },
24
+ "pkm": {
25
+ "name": "PKM",
26
+ "description": "개인 지식 관리 — 문서 파싱, 임베딩, 시맨틱 검색"
27
+ },
28
+ "naeilUi": {
29
+ "name": "naeil-ui",
30
+ "description": "미니멀 디자인 시스템 — OKLCH 토큰, Tailwind v4, shadcn"
31
+ },
32
+ "sa": {
33
+ "name": "Sustainability Analyzer",
34
+ "description": "ESG 리포트 AI 분석 — PDF 파싱, 정성평가, 비교표 자동 생성"
35
+ },
36
+ "babyAgent": {
37
+ "name": "Baby Agent",
38
+ "description": "육아 AI 에이전트 — LINE 기반 Q&A, 기록, 리마인더"
39
+ },
40
+ "status": {
41
+ "active": "활성",
42
+ "coming": "준비 중"
43
+ }
44
+ }
45
+ },
46
+ "account": {
47
+ "menu": "계정 메뉴",
48
+ "account": "계정",
49
+ "login": "로그인",
50
+ "logout": "로그아웃",
51
+ "busy": "로그아웃 중…"
52
+ },
53
+ "footer": {
54
+ "navigation": "네비게이션",
55
+ "projects": "프로젝트",
56
+ "blog": "블로그",
57
+ "social": "소셜",
58
+ "description": "Tomorrow starts here."
59
+ },
60
+ "locale": {
61
+ "names": {
62
+ "en": "English",
63
+ "ko": "한국어",
64
+ "ja": "日本語"
65
+ },
66
+ "pending": "언어를 변경하는 중…",
67
+ "failed": "언어를 변경하지 못했습니다. 작업 내용은 유지됩니다.",
68
+ "retry": "다시 시도",
69
+ "errors": {
70
+ "badRequest": "올바르지 않은 주소입니다.",
71
+ "notFound": "페이지를 찾을 수 없습니다.",
72
+ "unauthenticated": "계속하려면 로그인하세요.",
73
+ "forbidden": "이 페이지에 접근할 권한이 없습니다.",
74
+ "unavailable": "일시적으로 서비스를 이용할 수 없습니다. 다시 시도하세요."
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,52 @@
1
+ # Owned-service language runtime
2
+
3
+ The opt-in `@naeil/ui/naeil-locale` entries support the registered naeil Next applications. English uses `/`, Korean `/ko`, and Japanese `/ja`, including deep routes. The URL determines the language. Cookie and browser preferences never redirect or overwrite it. The existing public `i18n/routing`, `Nav` and `Footer` APIs retain their previous behavior.
4
+
5
+ Use exact `next-intl@4.14.8` with the shared server/client entries. Next and React remain external peers. Standalone header/footer imports do not require Next or next-intl.
6
+
7
+ ## Entries and ownership
8
+
9
+ | Import | Responsibility |
10
+ | --- | --- |
11
+ | `@naeil/ui/naeil-locale` | Supported locales, strict service/route registry, `localePath`, `localeHref`, legacy receiving aliases and logical-route comparison |
12
+ | `/naeil-locale/server` | `createNaeilLocaleProxy`, `createNaeilRequestConfig`, request access markers and `localeMetadata` |
13
+ | `/naeil-locale/client` | Root `NaeilLocaleController`, locale `NaeilLocaleProvider`, `useLocaleController`, `useLocaleBeforeUnload` |
14
+ | `/naeil-locale/messages` | Selected common/application JSON loading and namespace merge |
15
+ | `/naeil-locale/checker` | Three-language key, nonempty value, ICU syntax and argument compatibility checks |
16
+ | `/naeil-locale/chrome` | Existing header/account/footer presentation using the provider's selected common dictionary |
17
+
18
+ Place the controller and app-owned session/business store in `app/layout.tsx`, above `[locale]`. Place the shared provider in `app/[locale]/layout.tsx` using the validated locale and server-loaded messages. Keep raw input, dialogs, undo, save/run controllers, stream readers and document-departure guards in the root lifetime. Locale remounts must not save, abort, reset, or seed a retained draft from older server props. Translate message keys at the rendering boundary, not inside persistent business state.
19
+
20
+ The shared config sets `localePrefix: "as-needed"`, `localeDetection: false`, `localeCookie: false`, and `alternateLinks: false`. Consumers set Next's `skipProxyUrlNormalize: true` and `skipTrailingSlashRedirect: true`; normalization follows the existing protocol/auth checks. A trusted ingress consumer may pass `requestOrigin: request => existingValidatedRequestUrl(request).origin` to the proxy. This keeps alias redirects and internal rewrites on the validated authority, including local127.0.0.1 deployments. Never derive it from an unvalidated forwarded host.
21
+
22
+ ```tsx
23
+ // app/layout.tsx — inside the existing html/body
24
+ <NaeilLocaleController service="estimate" preferenceWritesEnabled={false}>
25
+ <BusinessStateProvider>{children}</BusinessStateProvider>
26
+ </NaeilLocaleController>
27
+
28
+ // app/[locale]/layout.tsx — validate locale and setRequestLocale on the server
29
+ <NaeilLocaleProvider locale={locale} messages={await getMessages()}>
30
+ {children}
31
+ </NaeilLocaleProvider>
32
+ ```
33
+
34
+ Use `createNaeilRequestConfig({namespace: "estimate", messages: {en: () => import("../../messages/en.json"), ko: () => import("../../messages/ko.json"), ja: () => import("../../messages/ja.json")}})` in the next-intl request config. Every app JSON has exactly its own namespace. The package owns `naeil`; do not copy it into an app. The shared checker is a required build gate. The loader imports only the selected app dictionary and shared dictionary; an observable English recovery handles unexpected runtime omissions. Such omissions still fail acceptance.
35
+
36
+ Render complete paths with `localePath` for same-service navigation and `localeHref` for owned service links. Pass those paths to base Next Link/router or anchors without another locale option. The controller performs `router.replace(href, {scroll: false})`, serializes requests and waits for the matching provider arrival. It restores a stable `data-naeil-focus-id`, input `name`, or `id`. Only a successful explicit selection may write preference; history, prefetch and direct visits do not. Storage failure cannot block a path change.
37
+
38
+ The canonical chrome can be imported from `/naeil-locale/chrome` under the shared provider. Existing `/naeil-header` and `/naeil-footer` remain standalone compatibility adapters and include the small three-language common dictionary. Consumer Link, auth, save guards, frame overrides, desktop/mobile account locks and project data remain consumer-owned.
39
+
40
+ ## AB Storm registration (0.11.0 candidate)
41
+
42
+ `service="abstorm"` binds to exactly `https://abstorm.naeil.dev`. Its protected UI inventory is `/`, `/new`, `/runs/[id]`, `/runs/[id]/report` and `/experts`; `/new?copy=<id>` uses the same registered page. All support English, Korean and Japanese paths. `/auth/session`, `/auth/logout`, `/api/*` and `/health` remain unlocalized protocol endpoints, with no UI exceptions. Unknown UI paths are rejected instead of inheriting the app’s catch-all history fallback.
43
+
44
+ The inventory was checked against AB Storm source `087e67239db26506a73c51fde7a6d246e4a0d0d9`. Generic error documents use its existing `abstorm` title and no favicon. This registration does not add a default header/footer destination or application translations. Consumer provider, routing, authentication, message loading and upgrade remain app-owned; package registration alone does not establish production adoption.
45
+
46
+ ## Security and rollout
47
+
48
+ The proxy runs exact existing protocol boundaries first, strips external private markers, strictly classifies UI paths, applies the existing app authorizer, and then runs next-intl. Protected entries without an authorizer fail closed. A marker is only a rendering hint: every protected server data read must independently authorize. RSC denial renders a valid localized access boundary and retains the root draft; it must not send login HTML or redirect an in-progress editor to another document. Keep the root beforeunload guard active during RSC failure and access recovery.
49
+
50
+ `localePath` is not an auth-return validator. Keep existing exact return/invite/callback/relay origin and envelope validation. Protocol paths stay outside `[locale]`; localized protocol aliases are rejected. Public metadata advertises only available translations. Protected/auth/error UI is noindex without SEO alternates.
51
+
52
+ Receiver deployment and sending are separate gates. `preferenceWritesEnabled` defaults to false. Before first exposure, validate a separate receiver-compatible fallback or the previous build's safe rejection of new paths. After all required receiver and auth receipts pass, enable the reviewed cross-service links and explicit preference writes. Keep package, source, hosted Docs, app identities, activation times and rollback receipts separate. Home and Baby are outside this migration.
@@ -1,12 +1,16 @@
1
1
  # Package verification and release policy
2
2
 
3
- **Published exact baseline: 0.8.0** (source/tag `3f708e27d05212af7f7a5be769f13f871e8d10c7`, archive SHA-256 `6feb5a8cd50265ace584a0855432683b4127119377e08235282eaebd27081084`, 139 files). Registry download matched that frozen archive on 2026-10-29; tags were `latest=0.7.2`, `next=0.8.0`. Its Home menu/brand/status/controlled-sheet APIs and package-owned chrome typography are published. **0.9.0 is an unpublished candidate** for the adopted page-root frame rule. Contract version remains `1` only if all invariants pass. Historical releases/archives remain immutable; hosted Docs and service activation require separate receipts.
3
+ **Published exact baseline: 0.10.0 — 2026-11-04.** Source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`, frozen archive SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4`, 175 regular files. Registry bytes matched; verified tags were `latest=0.7.2`, `next=0.10.0`. See the [publication and three-service acceptance receipts](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md). Historical releases, archives and receipts remain immutable; hosted Docs require their own receipt. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) is a **0.7.x-only, contract 1** release/recovery tool, outside the current 0.10.0 deployment and recovery procedure. UI v2 names a design generation, not an npm major. Version-scoped installation is in the [README](../README.md#use-the-ui).
4
+
5
+ ## 0.11.0 candidate — AB Storm locale registry
6
+
7
+ This additive API candidate registers AB Storm's five protected UI routes and error-document identity. Use the manual exact-archive procedure below, publish to `next` and preserve `latest`; the intended tag is `v0.11.0` at the frozen source. The historical 0.7.x runner transaction and chrome contract 1 remain unchanged. Package version, generated `/release` metadata and clean consumer fixture versions move together. Freeze only after all bundled documentation edits, and record source, digest, inventory and final checks outside the archive. Publication, registry verification, consumer adoption, GitHub Release and hosted Docs remain separate maintainer steps.
4
8
 
5
9
  ## Architecture
6
10
 
7
11
  One repository contains the shared package and the separate Next.js brand/example website. `@naeil/ui/ui` provides React primitives and generic Navigation/SiteFooter. The opt-in React-only `@naeil/ui/naeil-header` provides the complete actual naeil.dev branded header and `NaeilHeaderAccountControl`; see [its consumer contract](components/naeil-header.md). Owned apps render that control in `authSlot` and supply session state, pending state and guarded callbacks above the header. The legacy root is a framework compatibility entry with static Next/next-intl imports, even when selecting only Logo or a heading; React-only consumers use the documented shared deep modules. Next and next-intl are optional peers, not optional behavior inside the root. Supply them when importing that entry, Nav, Footer, or i18n/routing. Theme controls and Toaster use the framework-independent React library next-themes, retained as a runtime dependency.
8
12
 
9
- Owned services use `@naeil/ui/naeil-footer` for the canonical localized destinations in full/compact variants; generic SiteFooter and legacy Footer retain their APIs. Footer navigation adapters preserve application save/flush decisions and modified-click behavior. `@naeil/ui/release` is server-safe metadata; it contains no application artifact, credential or environment. Applications compile their own allowlisted artifact/source identity. See [the footer contract](components/naeil-footer.md). Current coordinator policy, selected services, activation and recovery evidence are maintained in the [rollout records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout); historical disabled-policy statements describe their dated checkpoints. Publishing a package, creating an update PR or merging it never establishes complete consumer rollout. Home Console is outside the selected shared-UI rollout.
13
+ Owned services use `@naeil/ui/naeil-footer` for the canonical localized destinations in full/compact variants; generic SiteFooter and legacy Footer retain their APIs. Footer navigation adapters preserve application save/flush decisions and modified-click behavior. `@naeil/ui/release` is server-safe metadata; it contains no application artifact, credential or environment. Applications compile their own allowlisted artifact/source identity. See [the footer contract](components/naeil-footer.md). Historical 0.7.x release plans and transaction recovery use the [local rollout runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md); the [rollout records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout) preserve dated evidence and historical policies. Publishing a package, creating an update PR or merging it never establishes complete consumer rollout. Home Console is outside the selected shared-UI rollout.
10
14
 
11
15
  Website tools remain development dependencies so maintainers can develop both products. npm tarball consumers install only component runtime dependencies and their host React/ReactDOM. Build entries, package exports and packed checks constrain the public boundary. There is no bundled website action, Supabase helper, Three/hero/cursor module, blog engine or full application message catalog. The opt-in header includes only its three header dictionaries and canonical project catalog. Its 0.7.2 default catalog contains naeil-ui and references the official `https://naeil.dev/images/whale.png` URL and require network access; no image bytes are bundled, and unresolved artwork redistribution provenance remains in [third-party notices](../THIRD_PARTY_NOTICES.md).
12
16
 
@@ -31,6 +35,17 @@ pnpm exec playwright install chromium firefox webkit
31
35
  pnpm test:browser
32
36
  ```
33
37
 
38
+ The chrome fixture server and standalone navigation sample use `NAEIL_UI_FIXTURE_PORT`, with the unchanged default defined in `scripts/chrome-fixture-config.ts` in the repository. The same module supplies every fixture URL. An explicit port also isolates generated fixtures, test results and HTML reports by port; leave it unset to retain the existing CI paths. Choose a free integer port from 1 to 65535.
39
+
40
+ For two concurrent fixture-only runs in one worktree, use separate terminals:
41
+
42
+ ```sh
43
+ NAEIL_UI_CHROME_ONLY=1 NAEIL_UI_FIXTURE_PORT=16081 pnpm test:browser e2e/page-frame.spec.ts --project=chromium
44
+ NAEIL_UI_CHROME_ONLY=1 NAEIL_UI_FIXTURE_PORT=16082 pnpm test:browser e2e/page-frame.spec.ts --project=chromium
45
+ ```
46
+
47
+ `NAEIL_UI_CHROME_ONLY=1` skips the unrelated Storybook server. Full suites still use `NAEIL_UI_STORYBOOK_PORT` for Storybook. Do not overlap an unset-port run (which cleans the default `test-results` directory) with custom-port runs in the same worktree. The standalone sample uses the same port setting: `NAEIL_UI_FIXTURE_PORT=16083 pnpm exec tsx scripts/serve-navigation-sample.ts`. Stop standalone previews after use; Playwright stops its own fixture server.
48
+
34
49
  `check:package:boundary` inspects an actual `npm pack --ignore-scripts` archive for every declared export, runtime dependencies, source aliases, relative imports, required CSS/tokens/documents/notices and forbidden website payload. `check:consumers` separately installs that tarball with npm into two temporary directories. It builds the reusable React example with Vite/Tailwind, type-checks with library checks enabled, imports shared deep modules, checks SSR and CSS, and asserts Next/Supabase/Three are absent. A separate Next production build exercises root exports and the deep paths observed in the reachable Next consumer, with consumer-owned messages and no auth backend. Neither fixture uses repository dependency symlinks. Network access is needed for uncached npm dependencies; temporary installs are removed on completion or failure.
35
50
 
36
51
  For a frozen release candidate, both archive-producing checks can enforce the reviewed SHA-256 before extraction or consumer installation:
@@ -50,6 +65,14 @@ The explicit font-notice regression gate copies the real React fixture config in
50
65
 
51
66
  ## Publication and deployment
52
67
 
68
+ ### Verified 0.10.0 publication and service acceptance — 2026-11-04
69
+
70
+ The [registry receipt](https://github.com/naeil-dev/naeil-ui/releases/download/v0.10.0/npm-registry-verification.json) verifies the exact frozen archive listed above, including all 175 regular members. [Release v0.10.0](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.10.0) retains its assets at the frozen source. [Implementation progress](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md) and [acceptance](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/acceptance.md) record Site, Jev and Estimate separately. Those service identities and recovery procedures are outside the old 0.7.x runner; its preserved approval and transaction must not be reused for this release.
71
+
72
+ ### Historical 0.8.0 registry checkpoint — 2026-10-29
73
+
74
+ The published 0.8.0 archive matched frozen SHA-256 `6feb5a8cd50265ace584a0855432683b4127119377e08235282eaebd27081084` (139 files, source/tag `3f708e27d05212af7f7a5be769f13f871e8d10c7`). Registry tags at that dated checkpoint were `latest=0.7.2`, `next=0.8.0`. Its Home menu/brand/status/controlled-sheet APIs and package-owned chrome typography remain part of the current public API. This receipt remains historical and does not establish the current registry tags or hosted Docs source.
75
+
53
76
  ### Verified 0.7.1 registry publication and maintained Docs — 2026-10-23
54
77
 
55
78
  The published release preserves these immutable identities:
@@ -66,7 +89,7 @@ The frozen archive was published directly with scripts disabled. npm records pub
66
89
 
67
90
  The archive's bundled guides are an immutable preparation snapshot, including 0.6.0 installation copy. Release notes must point to maintained instructions. Deploy Docs from a separately reviewed commit containing current guidance, the `v0.7.1` link correction and the corrected manual workflow. Record that Docs SHA, workflow run, deployment and actual hosted checks separately; retain `v0.7.1` at the frozen package source.
68
91
 
69
- Postpublication registry checks passed on 2026-10-23. Separate fresh React/Next fixtures installed exact `@naeil/ui@0.7.1` from npmjs with independent empty caches and no repository dependency symlinks; every installed file matched the frozen 139-file inventory in both fixtures. Types, production builds, public root/deep import boundaries, release/footer/account SSR and browser checks passed, including the React fixture's absence of Next/Supabase/Three. The retained `registry-receipt.json` and successful `npm-publication-verification.json` bind these checks to the frozen source/archive; the latter records `checkedAt: 2026-10-23T01:19:50.385Z`. At the 01:19 UTC registry checkpoint, the tag had been pushed and the Release draft prepared. GitHub Release publication, hosted Docs and standing activation require separate receipts; see the release assets and [current rollout runbook](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/standing-rollout.md). Native/manual, real OAuth and global service-discovery evidence retain their separate scopes and limits.
92
+ Postpublication registry checks passed on 2026-10-23. Separate fresh React/Next fixtures installed exact `@naeil/ui@0.7.1` from npmjs with independent empty caches and no repository dependency symlinks; every installed file matched the frozen 139-file inventory in both fixtures. Types, production builds, public root/deep import boundaries, release/footer/account SSR and browser checks passed, including the React fixture's absence of Next/Supabase/Three. The retained `registry-receipt.json` and successful `npm-publication-verification.json` bind these checks to the frozen source/archive; the latter records `checkedAt: 2026-10-23T01:19:50.385Z`. At the 01:19 UTC registry checkpoint, the tag had been pushed and the Release draft prepared. GitHub Release publication, hosted Docs and service rollout require separate receipts; see the release assets and [historical 0.7.x rollout runbook](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md). Native/manual, real OAuth and global service-discovery evidence retain their separate scopes and limits.
70
93
 
71
94
  ### 0.6.0 release scope — 2026-10-16
72
95
 
@@ -104,7 +127,7 @@ The immutable npm archive's bundled guides are the release-preparation snapshot.
104
127
 
105
128
  ### Release procedure
106
129
 
107
- Maintained Storybook resolves relative Markdown guide links against the published `v0.7.2` source `40a3928e24cd2f0141be3e605eed0a75260938fd`. The published 0.8.0 archive and 0.9.0 candidate keep that published guide-link target until a separately reviewed Docs release. That tag is independent of the reviewed Docs deployment SHA. Hosted verification checks that the pinned links resolve; the unpublished `v0.7.0` tag is not a valid target. Historical foundation/source-authority links remain at their original revisions. Freeze subsequent documentation changes separately from immutable release archives.
130
+ Maintained Storybook resolves relative Markdown guide links against the published `v0.7.2` source `40a3928e24cd2f0141be3e605eed0a75260938fd`. Package releases keep that published guide-link target until a separately reviewed Docs release. That tag is independent of the reviewed Docs deployment SHA. Hosted verification checks that the pinned links resolve; the unpublished `v0.7.0` tag is not a valid target. Historical foundation/source-authority links remain at their original revisions. Freeze subsequent documentation changes separately from immutable release archives.
108
131
 
109
132
  The authorized 0.3.0 release completed main merge, npm 0.3.0, a GitHub Release and hosted Docs as recorded above. The release maintainer performs external authentication and publication; documentation preparation does not itself execute those operations. The automatic verification workflow does not publish or deploy. Record native/manual observations with their actual scope and carry unrun checks as limitations; do not substitute automated WebKit/axe checks or publication authorization for human certification.
110
133
 
@@ -121,9 +144,11 @@ npm publication, GitHub Releases, main merge and hosted Docs are distinct operat
121
144
  `vercel.json` disables Git deployments only for `feat/public-ui-readiness`. Other branches retain Vercel's default behavior, so merging or pushing another branch requires a separate deployment decision. The automatic GitHub Actions checks are verification-only; enabling repository workflows is not evidence of a hosted site or approved release.
122
145
 
123
146
 
124
- ### Manual exact-archive preparation for 0.9.0 (following 0.8.0)
147
+ ### Historical manual exact-archive preparation for 0.9.0 (following 0.8.0)
148
+
149
+ The following preparation requirements and deployment hold describe the October 29 checkpoint. The November 4 release and accepted service state are recorded above; this historical section does not describe current service versions or pending approval.
125
150
 
126
- The standing `scripts/rollout/prepare-release.mjs` accepts consecutive stable 0.7.x releases only. Do not change rollout policy, `release.json` or the chrome contract to admit 0.9.0. Use the manual release procedure above: complete G1–G7 from the [adopted root-frame contract](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md), including the retained 0.8.0 P1–P5 regressions, freeze the exact source SHA/archive, then run boundary and clean React/Next checks with `NAEIL_UI_EXPECTED_ARCHIVE_SHA256`. The paired browser gate accepts `NAEIL_UI_CHROME_PACKAGE=/absolute/extracted/package` to exercise that exact archive, alongside SHA-512-pinned 0.7.2 and SHA-256-pinned frozen 0.8.0. Reference-only root/lock CSS adjustments are separate hashed fixture files; immutable archives stay untouched. Both classic and overlay jobs require actual probes. Viewport captures have geometry guards; all acceptance measurement precedes any terminal fullPage capture. It retains numeric differences and screenshots for human review; new renders never replace expectations automatically.
151
+ The retained `scripts/rollout/prepare-release.mjs` accepts consecutive stable 0.7.x releases only. Do not change rollout policy, `release.json` or the chrome contract to admit 0.9.0. Use the manual release procedure above: complete G1–G7 from the [adopted root-frame contract](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md), including the retained 0.8.0 P1–P5 regressions, freeze the exact source SHA/archive, then run boundary and clean React/Next checks with `NAEIL_UI_EXPECTED_ARCHIVE_SHA256`. The paired browser gate accepts `NAEIL_UI_CHROME_PACKAGE=/absolute/extracted/package` to exercise that exact archive, alongside SHA-512-pinned 0.7.2 and SHA-256-pinned frozen 0.8.0. Reference-only root/lock CSS adjustments are separate hashed fixture files; immutable archives stay untouched. Both classic and overlay jobs require actual probes. Viewport captures have geometry guards; all acceptance measurement precedes any terminal fullPage capture. It retains numeric differences and screenshots for human review; new renders never replace expectations automatically.
127
152
 
128
153
  Before npm publication, the separately approved source push must make the linked adopted contract at `434b7d07235316097ca3a55265ee02c1422b0cfd` public. Immediately after that push, verify an anonymous HTTP 200 for the exact guide URL and confirm its status says **rev 1, adopted 2026-10-29**. Local link/boundary checks do not establish public reachability. Source push may trigger Vercel deployment and retains its own approval boundary.
129
154