@naeil/ui 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 (77) hide show
  1. package/CHANGELOG.md +38 -3
  2. package/DESIGN.md +10 -2
  3. package/README.md +13 -11
  4. package/THIRD_PARTY_NOTICES.md +4 -2
  5. package/dist/{chunk-XLISHUJZ.js → chunk-ESTQITQO.js} +68 -8
  6. package/dist/{chunk-DBE7R4MR.js → chunk-L25A4OKY.js} +1 -1
  7. package/dist/{chunk-KPE4KKYM.js → chunk-Y5LW3ADW.js} +24 -15
  8. package/dist/components/index.d.ts +3 -3
  9. package/dist/components/index.js +4 -4
  10. package/dist/components/naeil-footer.d.ts +2 -2
  11. package/dist/components/naeil-footer.js +1 -1
  12. package/dist/components/naeil-header.d.ts +23 -8
  13. package/dist/components/naeil-header.js +7 -5
  14. package/dist/components/ui/index.d.ts +2 -2
  15. package/dist/components/ui/index.js +6 -6
  16. package/dist/lib/ui-release.d.ts +1 -1
  17. package/dist/lib/ui-release.js +1 -1
  18. package/dist/lib/utils.js +1 -7
  19. package/dist/naeil-locale/checker.js +1 -1
  20. package/dist/naeil-locale/chrome.d.ts +25 -8
  21. package/dist/naeil-locale/chrome.js +91 -22
  22. package/dist/naeil-locale/{chunk-4U64K4J3.js → chunk-24IL53QO.js} +1 -1
  23. package/dist/naeil-locale/{chunk-U65OQHZY.js → chunk-WT6QXR7O.js} +14 -8
  24. package/dist/naeil-locale/client.js +45 -15
  25. package/dist/naeil-locale/index.js +1 -1
  26. package/dist/naeil-locale/messages.js +2 -2
  27. package/dist/naeil-locale/server.js +6 -6
  28. package/dist/{navigation-D8N1tMTu.d.ts → navigation-CXZapKac.d.ts} +3 -1
  29. package/dist/{site-footer-s113FZgC.d.ts → site-footer-C4jgkGDU.d.ts} +1 -1
  30. package/dist/source/components/naeil-header-core.d.ts +23 -8
  31. package/dist/source/components/naeil-header-core.js +66 -6
  32. package/dist/source/components/naeil-header.d.ts +6 -4
  33. package/dist/source/components/naeil-header.js +4 -2
  34. package/dist/source/components/typography.d.ts +1 -1
  35. package/dist/source/components/typography.js +1 -1
  36. package/dist/source/components/ui/button.js +7 -7
  37. package/dist/source/components/ui/card.js +1 -1
  38. package/dist/source/components/ui/dialog.js +2 -2
  39. package/dist/source/components/ui/navigation.d.ts +3 -1
  40. package/dist/source/components/ui/navigation.js +17 -8
  41. package/dist/source/components/ui/sonner.js +2 -2
  42. package/dist/source/lib/ui-release.d.ts +1 -1
  43. package/dist/source/lib/ui-release.js +1 -1
  44. package/docs/components/README.md +3 -1
  45. package/docs/components/application-layout.md +23 -27
  46. package/docs/components/avatar.md +1 -1
  47. package/docs/components/badge.md +3 -1
  48. package/docs/components/button.md +7 -1
  49. package/docs/components/card.md +5 -1
  50. package/docs/components/checkbox.md +1 -1
  51. package/docs/components/common.md +16 -1
  52. package/docs/components/dialog.md +6 -2
  53. package/docs/components/dropdown-menu.md +1 -1
  54. package/docs/components/input.md +1 -1
  55. package/docs/components/naeil-footer.md +1 -1
  56. package/docs/components/naeil-header.md +41 -12
  57. package/docs/components/naeil-locale.md +36 -0
  58. package/docs/components/navigation.md +10 -4
  59. package/docs/components/select.md +1 -1
  60. package/docs/components/sheet.md +1 -1
  61. package/docs/components/sonner.md +7 -1
  62. package/docs/components/switch.md +1 -1
  63. package/docs/components/tabs.md +1 -1
  64. package/docs/components/textarea.md +1 -1
  65. package/docs/design/public-ui-support.md +3 -1
  66. package/docs/design/v2-migration.md +11 -6
  67. package/docs/package-release.md +36 -12
  68. package/package.json +7 -10
  69. package/src/styles/components.css +29 -0
  70. package/src/styles/globals.css +6 -2
  71. package/src/styles/theme.css +5 -0
  72. package/licenses/Nunito-Sans-OFL.txt +0 -93
  73. package/licenses/React-MIT.txt +0 -21
  74. package/licenses/Storybook-MIT.txt +0 -21
  75. package/licenses/popper-MIT.txt +0 -25
  76. package/licenses/store2-MIT.txt +0 -22
  77. package/licenses/toggle-selection-MIT.txt +0 -21
package/CHANGELOG.md CHANGED
@@ -1,6 +1,37 @@
1
1
  # Changelog
2
2
 
3
- ## 0.12.0 — shared UI refinements and Sheet (unpublished candidate)
3
+ ## 0.13.1 — publication and auto-update policy (unpublished candidate)
4
+
5
+ Not published. Docs-only patch to exercise the protected npm publishing workflow and the services' auto-update flow. Since frozen 0.13.0 source `08ee159`, the only package-shipped change on main is `docs/package-release.md` from #50: same-major consumer updates, a new major for public API/header-contract breaks (including 1.0.0 for a header break while on 0.x), and protected exact-archive publication guidance.
6
+
7
+ - Component code, public APIs, header markup/geometry, styles, dependencies and chrome contract 1 are unchanged.
8
+ - Package metadata, generated `/release`, React/Next fixture versions and maintained guidance move to 0.13.1. The owner approved publication directly to `latest` for Dependabot visibility; `next` stays 0.13.0 unless separately moved. Publication, environment approval, source tag/Release and manual service deployments remain separate actions.
9
+
10
+ ## 0.13.0 — design-system audit fixes and owned-service headers (published 2026-11-12)
11
+
12
+ Published to `next` on 2026-11-12; registry bytes matched the frozen archive on 2026-11-13 JST. The preparation notes below retain their original scope. Includes PR #47 (design-system audit fixes, based on the 2026-11-12 audit b17a015) and PR #48 (owned-service header profiles). Public imports, exports, types and consumer `className` overrides are preserved; changed defaults are listed under compatibility.
13
+
14
+ - Header: add opt-in `service`, `NaeilService`, `NaeilServiceHeaderProps` and readonly `naeilServices` through standalone/provider chrome entries. The DS owns lowercase service branding, product-only tabs and canonical toolbar; toolbar-only mobile sheets omit empty navigation and restore visible toolbar focus on desktop crossing. Generic Navigation exposes opt-in `omitEmptyNavigation` (default false preserves B1). Keep `NaeilHeaderProps` as the extensible legacy interface; service-first/legacy-last component overloads preserve inferred legacy props. Invalid runtime service ids fall back to the legacy profile with a development-only warning; the warning guard tolerates absent `process`. Add four service stories and matching browser contracts.
15
+ - Locale runtime: protocol-hook request-header deletions and replacements are preserved instead of restoring incoming headers (security hardening). Literal backslashes in query/fragment no longer invalidate a registered route (path backslashes still 404). A late commit after a transition timeout clears the error, `retry()` replays the latest failed request and clears an already-satisfied one. Encoded spellings of every reserved protocol segment, including service `protocolPrefixes`, are rejected. `/favicon.svg` passes as a public file; the matcher/public-file contract is documented.
16
+ - `@naeil/ui/utils` is safe to call from React Server Components. `buttonVariants`/`badgeVariants` stay on the client `/ui` barrel; call them on the server through `@naeil/ui/components/ui/button` and `/badge`. Packed Next consumers are now built with both webpack and Turbopack, including a Server Component page.
17
+ - `Button` with `aria-pressed="true"` shows a token-based pressed indicator in every variant.
18
+ - `DialogContent` caps its height to the viewport and scrolls; Toaster dismiss and action controls get 44px hit areas; Toaster follows a forced next-themes theme.
19
+ - `dark:` utilities follow the same OS-dark / `.dark` / root `.light` conditions as the theme tokens.
20
+ - Typography roles carry the DESIGN.md line heights through generated `--text-*--line-height` tokens. The contrast gate checks rendered opacity/state combinations (98 pairs), and the token test compares generated CSS with the committed file without rewriting it.
21
+ - Docs: README and guides no longer pin stale release states; Storybook guide links follow the built version tag; the `/naeil-locale` runtime is linked from entry docs and agent guidance; production login topology was removed from the shipped application-layout guide.
22
+ - Removed: the unused `tw-animate-css` runtime dependency and its `globals.css` import (kept as a devDependency only so frozen 0.7.x rollout fixtures still render); unreachable site components (hero scene, cursor, accent picker, site controls) with their three.js devDependencies; dead `src/lib/axe.ts`, `src/types/i18n.d.ts`, unused one-off scripts and `.prettierrc`. The npm package ships only the license notices the package needs (178 → 172 files).
23
+ - CI: `forbidOnly` on CI, no reuse of a stale local Storybook server, and 40-minute browser/package job limits.
24
+ - Release preparation: package metadata, generated `/release` and clean React/Next fixture versions move to 0.13.0. Publish only the reviewed frozen archive to `next`; preserve `latest=0.12.0` unless separately approved. Chrome contract 1 is unchanged: service profiles are opt-in and legacy header output is preserved. Publication, tag/Release, hosted Docs and consumer adoption remain separate maintainer actions.
25
+
26
+ Compatibility:
27
+ - Omitting `service` preserves legacy header output and overrides. `statusSlot`, `brandSuffix`, `brandSlot`, `toolbarSlot`, `subNav` and `brandLinkComponent` are deprecated for owned services, retained for compatibility. The opt-in service branch rejects brand/catalog/style escape hatches and ignores cast/JavaScript attempts with development-only warnings once per prop; root chrome markers are protected.
28
+ - Visual defaults changed: pressed Buttons; generated line heights for every type size used by the roles (`text-xs` 13/20, `text-sm` 14/22, `text-base` 16/25, `text-xl` 20/29, `text-3xl` 32/42), which also applies to consumer text without an explicit `leading-*` (explicit `leading-*` still wins); Card/Dialog/Page titles follow those roles; `DialogContent` caps its height and scrolls, so its close button scrolls with the content and non-portaled popups inside a dialog are clipped (portaled Radix popups are not); `dark:` utilities under OS dark without a theme class. Opt-outs are in the component guides.
29
+ - Apps that used tw-animate-css utilities (`animate-in`, `fade-in`, ...) only through `@naeil/ui/globals.css` must add `tw-animate-css` themselves. No owned service does (checked AB Storm, Estimate, Home, Persona, Jev).
30
+ - Package-internal Storybook tooling notices are no longer in the npm archive; they stay in the repository and the Docs preview.
31
+
32
+ ## 0.12.0 — shared UI refinements and Sheet (published 2026-11-10)
33
+
34
+ Published to npm with dist-tag `next` on 2026-11-10 and promoted to `latest` on 2026-11-11. Frozen source/tag `v0.12.0`: `e03af076b725d742c4b319aca5ebb2379e2f0258`; archive SHA-256 `7f5f01407c576e3c5fa956cf76ebfb3a8ef59b58619de99da68351974aca721b` (178 files). See the [receipt](https://github.com/naeil-dev/naeil-ui/blob/main/docs/releases/0.12.0/README.md). The publication plan below is the preparation-time record.
4
35
 
5
36
  - Add public `Sheet` primitives through `@naeil/ui/ui` and `@naeil/ui/components/ui/sheet`, using the existing Radix dialog behavior.
6
37
  - Add optional `closeLabel` to `DialogContent` and `DialogFooter`; existing English defaults remain unchanged.
@@ -8,14 +39,18 @@
8
39
  - Add `ui.width-workflow` (896px) and `data-ui-layout="workflow"` for workflow content within the existing application frame. Retain the locale service registration proposal as documentation only.
9
40
  - Additive minor API candidate from PR #42 (`0d1cb08`) and PR #43 (`047de96`). Publish the frozen archive to `next`, preserve `latest` (0.7.2) unless separately approved, and tag the frozen source as `v0.12.0`. Promotion of 0.11.0 remains a separate owner action; publication, consumer adoption and hosted Docs are separate.
10
41
 
11
- ## 0.11.0 — AB Storm locale registration (unpublished candidate)
42
+ ## 0.11.0 — AB Storm locale registration (published 2026-11-08)
43
+
44
+ Published to npm with dist-tag `next` on 2026-11-08 and promoted to `latest` on 2026-11-11 before 0.12.0. See the [receipt](https://github.com/naeil-dev/naeil-ui/blob/main/docs/releases/0.11.0/README.md).
12
45
 
13
46
  - Add the exact owned `abstorm` origin and five protected UI routes to the opt-in locale runtime, with English, Korean and Japanese paths. Keep auth/API/health endpoints outside localized UI routing.
14
47
  - Render localized fail-closed documents with the app’s `abstorm` identity; no favicon is declared by the current app.
15
48
  - Fix generated locale declarations: JSON imports previously left variable initializers in `.d.ts` output and failed installed-consumer TypeScript checks with library checking enabled. Normalize only those declarations to ambient JSON types; runtime imports and message loading remain unchanged. Clean packed-consumer tests now import the locale API and run `tsc` without `skipLibCheck`.
16
49
  - Additive public API release; existing services, default chrome/footer catalogs, messages and chrome contract 1 remain unchanged. Publish the reviewed exact archive to `next`; package publication and consumer adoption remain separate.
17
50
 
18
- ## 0.10.0 — shared language runtime (unpublished candidate)
51
+ ## 0.10.0 — shared language runtime (published 2026-11-04)
52
+
53
+ Published to npm with dist-tag `next` on 2026-11-04 (`latest` then remained 0.7.2). Source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`; archive SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4` (175 files).
19
54
 
20
55
  - Add opt-in `naeil-locale` root, client, server, messages, checker and chrome entries for the owned Next applications. English uses unprefixed paths; Korean/Japanese use `/ko` and `/ja`. Strict route/protocol parsing, legacy receiving aliases, selected JSON loading, ICU validation and committed-intent preference writes share one implementation.
21
56
  - Keep the transition controller above locale layouts, restore stable focus, and share document-departure protection. Consumers retain business/session state, data authorization and logical-navigation guards.
package/DESIGN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # naeil UI v2 — Design brief
2
2
 
3
- Status: Visual direction accepted on 2026-09-29: neutral palette, Pretendard, larger text, purpose-specific widths, comfortable spacing by default, compact spacing for dense views, and short restrained transitions respecting reduced motion. Implemented in the shared package and actual-component Storybook examples. Independent review findings have been addressed; validation evidence and remaining limits are in [the verification report](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/design/v2-verification.md). See [the v2 specification](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/superpowers/specs/2026-09-29-shared-ui-v2-design.md) for scope. Publishing and deployment are separate.
3
+ Status: Visual direction accepted on 2026-09-29: neutral palette, Pretendard, larger text, purpose-specific widths, comfortable spacing by default, compact spacing for dense views, and short restrained transitions respecting reduced motion. Implemented in the shared package and actual-component Storybook examples. Independent review findings have been addressed; validation evidence and remaining limits are in [the verification report](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/v2-verification.md). See [the v2 specification](https://github.com/naeil-dev/naeil-ui/blob/main/docs/superpowers/specs/2026-09-29-shared-ui-v2-design.md) for scope. Publishing and deployment are separate.
4
4
 
5
5
  ## Purpose and scope
6
6
 
@@ -110,18 +110,26 @@ First implement the foundation and existing eight families: Button, Input, Card,
110
110
 
111
111
  Demonstrate the system in three neutral compositions: a settings form, a selectable list with metadata, and a detail panel with actions. These are library examples, not a redesign of a particular website. Additional public components require a demonstrated composition need.
112
112
 
113
+ ### Owned-service header rule (2026-11-12)
114
+
115
+ Owned services set `NaeilHeader service="abstorm" | "home" | "estimate" | "jev"`. The left brand is logo → `.naeil` → lowercase service id, with no status dot or extra indicator; naeil.dev has no service suffix. The service supplies only its own `appNavigation` tabs. The DS owns their shape, placement, sizes, spacing and default/hover/selected/expanded/mobile states; service style or slot overrides are not allowed. Projects/Blog belong only to naeil.dev. A single-screen service leaves the center empty; its mobile menu still exposes theme/locale/account. The right toolbar is unchanged. Omitting `service` preserves the compatibility API and rendered output.
116
+
117
+ The service branch rejects `brandSuffix`, `statusSlot`, `brandSlot`, `toolbarSlot`, `subNav`, `brandLinkComponent`, `projects`, `projectsExternal`, `showProjects`, `showBlog`, `translations`, `className`, `containerClassName`, `style`, `brandLinkProps`, `mobileFooter` and `omitEmptyNavigation`; runtime attempts are ignored. Root `data-slot`, `data-global-header` and `data-naeil-*` markers are protected. Root `id`/`aria-*`/`dir`, consumer `Link` and `authSlot` markup remain consumer-owned and must not be used for styling shared chrome.
118
+
113
119
  ### Application frame and content widths
114
120
 
115
121
  On 2026-10-16 the owner approved a shared maximum application frame of **1600px**, with responsive inline gutters **clamp(16px, 2.4vw, 40px)**, after inspecting Naeil Home at mobile and desktop widths. This supersedes the prior 1280px branded-header cap and fixed 24px frame gutters. The frame includes its padding, centers on wider screens and shrinks to available space. Numeric values live in `ui.width-frame` and `ui.frame-gutter`; `.ui-app-frame`, `Navigation`, `SiteFooter`, `NaeilHeader`, and the legacy adapters use those same defaults.
116
122
 
117
123
  The page root reserves scrollbar space. Shared full-page frames use `html { scrollbar-gutter: stable; }`, with one scrollbar-side gutter in classic mode and no reserved space in overlay mode. Header, main and footer use the resulting available page width. Changing page length or opening and closing a scroll-locking surface MUST NOT move those frames or their content horizontally. A consumer using a different document scroll policy MUST declare the documented root opt-out and own that policy consistently across routes.
118
124
 
119
- The 0.9.0 candidate implements this default once in `components.css`, through either `globals.css` or `theme.css + components.css`. Theme-only/JS-only imports do not set it. `<html data-naeil-scrollbar-gutter="auto">` opts out of both the root reservation and its Radix duplicate-compensation correction before first paint. The default profile is LTR with zero body edge spacing; custom scrollers, body margins or dependency helper classes require consumer integration/opt-out. Unsupported browsers retain existing scroll-lock compensation. See the [adopted frame contract](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md) and [consumer override guidance](docs/components/application-layout.md).
125
+ Since 0.9.0, the package implements this default once in `components.css`, through either `globals.css` or `theme.css + components.css`. Theme-only/JS-only imports do not set it. `<html data-naeil-scrollbar-gutter="auto">` opts out of both the root reservation and its Radix duplicate-compensation correction before first paint. The default profile is LTR with zero body edge spacing; custom scrollers, body margins or dependency helper classes require consumer integration/opt-out. Unsupported browsers retain existing scroll-lock compensation. See the [adopted frame contract](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md) and [consumer override guidance](docs/components/application-layout.md).
120
126
 
121
127
  The optional `@naeil/ui/naeil-header` composition centralizes the actual naeil.dev brand/catalog/control/toolbar/responsive implementation approved on 2026-10-15. Official decorative image URLs remain references; no new artwork rights or redistribution is implied. See [NaeilHeader](docs/components/naeil-header.md).
122
128
 
123
129
  Application navigation and footer must use the shared compositions: complete `NaeilHeader` with `NaeilFooter` for owned naeil services, supplying product menu data through `appNavigation`; generic `Navigation`/`SiteFooter` for a different product without canonical naeil chrome. Existing `Nav`/`Footer` preserve Next compatibility while using that core. Services own menu data, route guards, locale/theme providers and authentication through adapters and slots. Extend the shared API when a reusable behavior is missing instead of copying menu, responsive or footer implementations. See [the application starter and consumer-agent rules](docs/components/application-layout.md).
124
130
 
131
+ Owned Next services under the shared locale provider import chrome from `@naeil/ui/naeil-locale/chrome`; `/naeil-header` and `/naeil-footer` remain standalone React adapters (see [the locale runtime](docs/components/naeil-locale.md)).
132
+
125
133
  The application frame owns navigation placement and outer gutters; each content region owns its purpose-specific width. A narrow settings form inside that frame must not move the shared navigation. For routes using the same frame, keep navigation anchors stable at the same viewport, language and theme, including loading and changing summary counts. A shared Header import alone does not establish this consistency.
126
134
 
127
135
  Content caps are reading **640px**, settings **640px**, short form **480px**, and lists **1600px** (updated from 1200px on 2026-10-16). On 2026-11-09 the owner approved a **workflow** cap of **896px** (`ui.width-workflow`, `data-ui-layout="workflow"`) for multi-step or card-choice input screens whose step cards or option grids are cramped at 640px; it matches the 848–896px main content measured on naeil.dev. Individual fields and helper text inside a workflow still follow the 640/480px caps. Put lists, tables and dashboards inside `.ui-app-frame` so they use the space remaining after its gutters. Narrow reading/forms stay inside that stable outer frame. `data-ui-layout="fluid"` uses the available region. At a 1920px viewport the default frame has 1520px of usable width.
package/README.md CHANGED
@@ -2,26 +2,28 @@
2
2
 
3
3
  React components, semantic design tokens, and shared styles for naeil products. The approved system uses a neutral light/dark palette, Pretendard, 16px controls, comfortable or compact density, purpose-specific content widths, and restrained motion. Radix supplies interaction behavior.
4
4
 
5
- **0.10.0 published and registry-verified — 2026-11-04.** This release adds the shared language runtime and preserves the page-root scrollbar reservation and scroll-lock correction. The registry archive matches frozen SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4` (175 files, source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`); verified tags were `latest=0.7.2`, `next=0.10.0`. See the [publication and service acceptance receipts](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md). Hosted Docs remain separately recorded. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) supports historical **0.7.x only** and cannot deploy or recover the current 0.10.0 release.
5
+ **0.13.1 is an unpublished release candidate.** This docs-only patch includes #50's consumer auto-update version policy and protected publication guidance; it changes no component code or public API. This checkout and its React/Next fixtures pin 0.13.1. Registry tags checked 2026-11-13 JST are `latest=0.12.0`, `next=0.13.0`; 0.13.0 is published. The owner approved publishing the frozen 0.13.1 archive directly to `latest` to exercise the workflow and service auto-update flow, leaving `next=0.13.0`. See the [release procedure](docs/package-release.md).
6
+
7
+ **Historical 0.12.0 publication — 2026-11-10; both tags were 0.12.0 on 2026-11-11.** It adds public Sheet primitives, optional Dialog close labels and the 896px workflow width on top of 0.10.0's opt-in [`/naeil-locale` runtime](docs/components/naeil-locale.md) for owned Next services. The registry archive matches frozen SHA-256 `7f5f01407c576e3c5fa956cf76ebfb3a8ef59b58619de99da68351974aca721b` (178 files, source/tag `e03af076b725d742c4b319aca5ebb2379e2f0258`); see the [0.12.0 receipt](https://github.com/naeil-dev/naeil-ui/blob/main/docs/releases/0.12.0/README.md) and [GitHub Release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.12.0). Hosted Docs remain separately recorded. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) supports historical **0.7.x only** and cannot deploy or recover current releases.
6
8
 
7
9
  This repository also contains the **naeil.dev brand/example website** and an **optional agent reference workflow**. Choose the path you need:
8
10
 
9
11
  | Path | Start here | Tools / keys |
10
12
  | --- | --- | --- |
11
13
  | Use the UI in an app | [Consumer guide](docs/design/v2-migration.md) | React 19, Tailwind 4; **no Next.js or API keys** for shared React entries |
12
- | Develop the shared UI | Commands below and [contributing](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/CONTRIBUTING.md) | Node.js 22+, pnpm; no Supabase or 21st key |
13
- | Use frontend references with an agent | [Optional workflow setup](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/design/frontend-tooling.md) | Supported agent; Python for bundled helpers; your own 21st key only for optional MCP |
14
- | Develop the brand/example website | [Site setup](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/site-development.md) | Next.js and a separate Supabase project for site authentication |
14
+ | Develop the shared UI | Commands below and [contributing](https://github.com/naeil-dev/naeil-ui/blob/main/CONTRIBUTING.md) | Node.js 22+, pnpm; no Supabase or 21st key |
15
+ | Use frontend references with an agent | [Optional workflow setup](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/frontend-tooling.md) | Supported agent; Python for bundled helpers; your own 21st key only for optional MCP |
16
+ | Develop the brand/example website | [Site setup](https://github.com/naeil-dev/naeil-ui/blob/main/docs/site-development.md) | Next.js and a separate Supabase project for site authentication |
15
17
 
16
18
  ## Use the UI
17
19
 
18
- Use React 19 / ReactDOM 19 and Tailwind 4. UI v2 names the design generation independently of npm versioning. The installation example targets the verified exact 0.10.0 release:
20
+ Use React 19 / ReactDOM 19 and Tailwind 4. UI v2 names the design generation independently of npm versioning. The installation example pins the 0.13.1 candidate and requires its publication first; until then, use the reviewed archive for candidate validation or the published 0.13.0 version for registry installs:
19
21
 
20
22
  ```sh
21
- pnpm add --save-exact @naeil/ui@0.10.0
23
+ pnpm add --save-exact @naeil/ui@0.13.1
22
24
  ```
23
25
 
24
- The [npm 0.10.0 archive](https://registry.npmjs.org/@naeil/ui/-/ui-0.10.0.tgz) is byte-identical to its frozen release archive. Bundled guides record the preparation snapshot; maintained guides record later publication outcomes. For local development, `pnpm build:pkg` and `npm pack --ignore-scripts --pack-destination /tmp` produce `/tmp/naeil-ui-VERSION.tgz`, where `VERSION` is the checked-out `package.json` version (currently the unpublished 0.12.0 candidate). Use the exact reviewed archive for release verification; later source or guide changes require a new freeze. The [0.6.0 release record](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.6.0) retains its archive, publication and deployment evidence.
26
+ The [npm 0.13.0 archive](https://registry.npmjs.org/@naeil/ui/-/ui-0.13.0.tgz) is byte-identical to its frozen release archive (verified 2026-11-13 JST). Bundled guides record the preparation snapshot; maintained guides record later publication outcomes. For local development, `pnpm build:pkg` and `npm pack --ignore-scripts --pack-destination /tmp` produce `/tmp/naeil-ui-VERSION.tgz`, where `VERSION` is the checked-out `package.json` version (currently the unpublished 0.13.1 candidate). Use the exact reviewed archive for release verification; later source or guide changes require a new freeze. The [0.6.0 release record](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.6.0) retains its archive, publication and deployment evidence.
25
27
 
26
28
  The preceding [0.5.0 release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.5.0) was published on 2026-10-15 and introduced the whole shared header. Version 0.6.0 adds the shared 1600px frame; existing applications must upgrade and adopt its layout composition.
27
29
 
@@ -79,7 +81,7 @@ Shared CSS follows the OS theme unless the document root has `class="light"` or
79
81
 
80
82
  The [component guides](docs/components/README.md) cover exact APIs, state composition and accessibility responsibilities, with matching Storybook Docs and runnable examples. Canonical footer and account examples live in the existing NaeilHeader/SiteFooter stories. The [consumer guide](docs/design/v2-migration.md) covers peer dependencies, fonts, themes, density, Select versus DropdownMenu, overrides, and layout ownership. Fonts are delivered by the consumer; shared CSS does not fetch them automatically. `/ui`, `/utils`, `/naeil-header`, `/naeil-footer` and `/release` work without Next.js; the last two are included in 0.7.1. The legacy root remains a framework compatibility entry with static Next/next-intl imports; install those optional peers when using it, Nav, Footer or i18n/routing. ThemeProvider/controls and Toaster retain the React library next-themes. Shared deep imports use the exact [allowlist and migration](docs/design/v2-migration.md#03-package-boundary); website-only paths belong in your application.
81
83
 
82
- For the actual naeil.dev branded header, import `NaeilHeader` and `NaeilHeaderAccountControl` from `@naeil/ui/naeil-header`; generic `Navigation` from `/ui` remains available for different product menus. The whole header owns its catalog, header translations, controls and responsive styles. Supply routing/dirty guards, an existing next-themes provider and real authentication state/actions through its props. Its five decorative project images reference official `naeil.dev` URLs and require network access; their bytes are excluded and unresolved redistribution provenance remains in [third-party notices](THIRD_PARTY_NOTICES.md). See [NaeilHeader](docs/components/naeil-header.md) for fixed positioning, the shared frame, supported locales and adapter contract, and [NaeilFooter](docs/components/naeil-footer.md) for canonical destinations and save interception.
84
+ For the actual naeil.dev branded header, import `NaeilHeader` and `NaeilHeaderAccountControl` from `@naeil/ui/naeil-header`; generic `Navigation` from `/ui` remains available for different product menus. The whole header owns its catalog, header translations, controls and responsive styles. Supply routing/dirty guards, an existing next-themes provider and real authentication state/actions through its props. Its single decorative project image (`whale.png`) references an official `naeil.dev` URL and require network access; their bytes are excluded and unresolved redistribution provenance remains in [third-party notices](THIRD_PARTY_NOTICES.md). See [NaeilHeader](docs/components/naeil-header.md) for fixed positioning, the shared frame, supported locales and adapter contract, and [NaeilFooter](docs/components/naeil-footer.md) for canonical destinations and save interception.
83
85
 
84
86
  ## Develop the shared UI
85
87
 
@@ -96,7 +98,7 @@ Storybook uses the actual public components with simulated example data. It need
96
98
  ```sh
97
99
  pnpm build:pkg
98
100
  pnpm pack --pack-destination /tmp
99
- # In your consumer app: pnpm add /tmp/naeil-ui-0.7.1.tgz
101
+ # In your consumer app: pnpm add /tmp/naeil-ui-VERSION.tgz (VERSION from package.json)
100
102
  # This development pack does not replace the frozen release archive.
101
103
  ```
102
104
 
@@ -109,7 +111,7 @@ pnpm pack --pack-destination /tmp
109
111
  | `pnpm build:pkg` / `pnpm check:package` | Build package / inspect package boundary and independently install/build packed React + Next consumers |
110
112
  | `pnpm dev` / `pnpm build` | Brand/example website development / build |
111
113
 
112
- A [reusable React consumer example](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react) composes the packaged header, a settings form and footer. [Release policy](docs/package-release.md) and [changelog](CHANGELOG.md) distinguish implementation, publication and deployment. CI verifies the package and separate website/Storybook. Downloadable preview artifacts include notices and local fonts. The current Storybook source defines 17 Docs pages (15 UI families and Brand / Logo plus NaeilHeader), including Usage, JapaneseApplication, ReferenceFull, ReferenceCompact and AccountStates examples. This does not establish a new hosted deployment. [Hosted Docs](https://naeil-dev.github.io/naeil-ui/) have recorded [0.5.0 verification](https://github.com/naeil-dev/naeil-ui/releases/download/v0.5.0/hosted-docs-verification.json); subsequent deployments require their own source and HTTP checks. The same approved brand is live on [naeil.dev](https://naeil.dev/). See [preview instructions](docs/package-release.md#storybook-preview-artifact) and [support limits](docs/design/public-ui-support.md). Native/manual platform acceptance retains its documented limits; service adoption and rollout have separate [dated records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout).
114
+ A [reusable React consumer example](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react) composes the packaged header, a settings form and footer. [Release policy](docs/package-release.md) and [changelog](CHANGELOG.md) distinguish implementation, publication and deployment. CI verifies the package and separate website/Storybook. Downloadable preview artifacts include notices and local fonts. The current Storybook source defines 18 Docs pages (16 UI families and Brand / Logo plus NaeilHeader), including Usage, JapaneseApplication, ReferenceFull, ReferenceCompact and AccountStates examples. This does not establish a new hosted deployment. [Hosted Docs](https://naeil-dev.github.io/naeil-ui/) have recorded [0.5.0 verification](https://github.com/naeil-dev/naeil-ui/releases/download/v0.5.0/hosted-docs-verification.json); subsequent deployments require their own source and HTTP checks. The same approved brand is live on [naeil.dev](https://naeil.dev/). See [preview instructions](docs/package-release.md#storybook-preview-artifact) and [support limits](docs/design/public-ui-support.md). Native/manual platform acceptance retains its documented limits; service adoption and rollout have separate [dated records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout).
113
115
 
114
116
  Read [DESIGN.md](DESIGN.md) before shared UI changes. Numeric values live in `src/tokens/`; generated CSS is not edited by hand. Shared styles live in `src/styles/`, site-only styles in `src/app/`. Hero art, 3D scenes, cursor effects, and site content belong to the example website.
115
117
 
@@ -117,4 +119,4 @@ Read [DESIGN.md](DESIGN.md) before shared UI changes. Numeric values live in `sr
117
119
 
118
120
  ## Project and license
119
121
 
120
- Maintained in [naeil-dev/naeil-ui](https://github.com/naeil-dev/naeil-ui). See [contributing](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/CONTRIBUTING.md), [security reporting](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/SECURITY.md), [MIT license](LICENSE), and [third-party notices](THIRD_PARTY_NOTICES.md). Third-party code, fonts, and brand assets have their own attribution and scope limits.
122
+ Maintained in [naeil-dev/naeil-ui](https://github.com/naeil-dev/naeil-ui). See [contributing](https://github.com/naeil-dev/naeil-ui/blob/main/CONTRIBUTING.md), [security reporting](https://github.com/naeil-dev/naeil-ui/blob/main/SECURITY.md), [MIT license](LICENSE), and [third-party notices](THIRD_PARTY_NOTICES.md). Third-party code, fonts, and brand assets have their own attribution and scope limits.
@@ -36,7 +36,7 @@ SOFTWARE.
36
36
 
37
37
  Shared package styles declare families; consumers own font delivery. The website imports Pretendard Variable from `pretendard`; Storybook imports Pretendard static CSS and `@fontsource/noto-sans-jp` 400/500/600. Both installed packages carry SIL Open Font License 1.1. Exact installed notices are preserved in [Pretendard](licenses/Pretendard-OFL.txt) and [Noto Sans JP](licenses/Noto-Sans-JP-OFL.txt). Keep the notice/license when redistributing font files; modified fonts must follow reserved-name rules.
38
38
 
39
- Storybook 10.4.6 also bundles Nunito Sans for its manager interface. The original Google Fonts OFL body was read on 2026-10-02 and is preserved in [Nunito Sans](licenses/Nunito-Sans-OFL.txt), including the original project-author notice; documentation preview output carries this notice as well. This manager font is Storybook tooling, not a new shared UI font choice.
39
+ Storybook 10.4.6 also bundles Nunito Sans for its manager interface. The original Google Fonts OFL body was read on 2026-10-02 and is preserved in [Nunito Sans](https://github.com/naeil-dev/naeil-ui/blob/main/licenses/Nunito-Sans-OFL.txt), including the original project-author notice; documentation preview output carries this notice as well. This manager font is Storybook tooling, not a new shared UI font choice.
40
40
 
41
41
  The site's `src/app/layout.tsx` separately requests JetBrains Mono via `next/font/google`; no copied font binary is tracked here. Before redistributing fetched site-build fonts, retain the original license/notice supplied with that font (https://github.com/JetBrains/JetBrainsMono). This audit did not inspect the fetched Google font binary/license and does not certify a deployed site's font-notice bundle. Prototype HTML uses external CDNs separately from packed UI styles.
42
42
 
@@ -44,6 +44,8 @@ The naeil brand wordmark uses outlined Lato Regular 400 from Google Fonts commit
44
44
 
45
45
  ## Dependencies and references
46
46
 
47
+ The package also retains the [react-remove-scroll-bar MIT notice](licenses/react-remove-scroll-bar-MIT.txt) for consumer bundle notice generation. Storybook-only notices remain in the repository and documentation preview output.
48
+
47
49
  Radix, Sonner, Lucide, React, Next.js and other npm dependencies carry licenses in their own distributions. They are not newly attributed as copied sources here; preserve their notices if bundling their code. DESIGN.md's Linear analysis is design reference material, not an official Linear specification or a component license. The optional workflow grants no blanket license to 21st catalog code; inspect each retrieved original before adoption.
48
50
 
49
51
  ## Website-only assets: unresolved provenance
@@ -52,4 +54,4 @@ Radix, Sonner, Lucide, React, Next.js and other npm dependencies carry licenses
52
54
 
53
55
  ### Optional branded header candidate
54
56
 
55
- The0.5.0candidate header refers to the five decorative project images at their official https://naeil.dev/images/ URLs. It does not embed or redistribute those public/images bytes; their unresolved provenance above remains open. Site-adapter extraction does not establish artwork rights or clear unrelated website assets.
57
+ Since 0.7.2, the branded header’s default naeil-ui catalog references one decorative image, https://naeil.dev/images/whale.png. It does not embed or redistribute those public/images bytes; their unresolved provenance above remains open. Site-adapter extraction does not establish artwork rights or clear unrelated website assets.
@@ -4,7 +4,7 @@ import {
4
4
  NaeilStandaloneMessages,
5
5
  uiRelease,
6
6
  useNaeilMessages
7
- } from "./chunk-DBE7R4MR.js";
7
+ } from "./chunk-L25A4OKY.js";
8
8
  import {
9
9
  Badge,
10
10
  Button,
@@ -21,7 +21,7 @@ import {
21
21
  SelectItem,
22
22
  SelectTrigger,
23
23
  SelectValue
24
- } from "./chunk-KPE4KKYM.js";
24
+ } from "./chunk-Y5LW3ADW.js";
25
25
  import {
26
26
  __objRest,
27
27
  __spreadProps,
@@ -122,6 +122,58 @@ function NaeilHeaderAccountControl({ locale, account, Link = NativeLink }) {
122
122
 
123
123
  // src/components/naeil-header-core.tsx
124
124
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
125
+ var naeilServices = Object.freeze(["abstorm", "home", "estimate", "jev"]);
126
+ var serviceCompatibilityProps = [
127
+ "brandSuffix",
128
+ "statusSlot",
129
+ "brandSlot",
130
+ "toolbarSlot",
131
+ "subNav",
132
+ "brandLinkComponent",
133
+ "projects",
134
+ "projectsExternal",
135
+ "showProjects",
136
+ "showBlog",
137
+ "translations",
138
+ "className",
139
+ "containerClassName",
140
+ "style",
141
+ "brandLinkProps",
142
+ "mobileFooter",
143
+ "omitEmptyNavigation"
144
+ ];
145
+ var warnedServiceProps = /* @__PURE__ */ new Set();
146
+ function isDevelopment() {
147
+ try {
148
+ return process.env.NODE_ENV === "development";
149
+ } catch (e) {
150
+ return false;
151
+ }
152
+ }
153
+ function warnServiceProp(name, message) {
154
+ if (!isDevelopment() || warnedServiceProps.has(name)) return;
155
+ warnedServiceProps.add(name);
156
+ console.warn(message);
157
+ }
158
+ function isNaeilService(value) {
159
+ return naeilServices.includes(value);
160
+ }
161
+ function NaeilHeader(input) {
162
+ if (input.service === void 0) return /* @__PURE__ */ jsx2(HeaderComposition, __spreadValues({}, input));
163
+ if (!isNaeilService(input.service)) {
164
+ warnServiceProp("service", "NaeilHeader: invalid service; rendering the legacy profile.");
165
+ const legacy = __spreadProps(__spreadValues({}, input), { service: void 0 });
166
+ delete legacy.service;
167
+ return /* @__PURE__ */ jsx2(HeaderComposition, __spreadValues({}, legacy));
168
+ }
169
+ const props = __spreadValues({}, input);
170
+ for (const name of Object.keys(props)) {
171
+ if (!serviceCompatibilityProps.includes(name) && name !== "data-slot" && name !== "data-global-header" && !name.startsWith("data-naeil-")) continue;
172
+ delete props[name];
173
+ warnServiceProp(name, `NaeilHeader: service profile ignores ${name}; use the shared service composition.`);
174
+ }
175
+ return /* @__PURE__ */ jsx2(HeaderComposition, __spreadProps(__spreadValues({}, props), { service: input.service }));
176
+ }
125
177
  var subscribe = () => () => {
126
178
  };
127
179
  function NaeilHeaderThemeControl({ locale }) {
@@ -158,8 +210,9 @@ function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
158
210
  ] });
159
211
  }
160
212
  var NativeLink2 = (props) => /* @__PURE__ */ jsx2("a", __spreadValues({}, props));
161
- function NaeilHeader(_a) {
213
+ function HeaderComposition(_a) {
162
214
  var _b = _a, {
215
+ service,
163
216
  locale,
164
217
  resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
165
218
  brandHref,
@@ -187,6 +240,7 @@ function NaeilHeader(_a) {
187
240
  className,
188
241
  containerClassName
189
242
  } = _b, props = __objRest(_b, [
243
+ "service",
190
244
  "locale",
191
245
  "resolveHref",
192
246
  "brandHref",
@@ -215,6 +269,11 @@ function NaeilHeader(_a) {
215
269
  "containerClassName"
216
270
  ]);
217
271
  var _b2, _c;
272
+ if (service) {
273
+ brandSuffix = service;
274
+ showProjects = false;
275
+ showBlog = false;
276
+ }
218
277
  const content = useNaeilMessages(locale).header;
219
278
  const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
220
279
  var _a3, _b3, _c2;
@@ -233,7 +292,7 @@ function NaeilHeader(_a) {
233
292
  badge: project.status === "coming" ? /* @__PURE__ */ jsx2(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
234
293
  };
235
294
  });
236
- const brandDestination = brandHref != null ? brandHref : resolveHref("/");
295
+ const brandDestination = brandHref != null ? brandHref : service ? "/" : resolveHref("/");
237
296
  const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
238
297
  const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
239
298
  const toolbar = /* @__PURE__ */ jsx2(
@@ -259,11 +318,11 @@ function NaeilHeader(_a) {
259
318
  __spreadProps(__spreadValues({
260
319
  href: brandDestination,
261
320
  "data-app-brand": true,
262
- "aria-label": brandSlot == null ? ".naeil" : void 0
321
+ "aria-label": service ? `.naeil ${service}` : brandSlot == null ? ".naeil" : void 0
263
322
  }, brandProps), {
264
323
  onClick: (event) => {
265
324
  onBrandClick == null ? void 0 : onBrandClick(event);
266
- onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
325
+ onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: service ? `.naeil ${service}` : ".naeil" });
267
326
  },
268
327
  children: brandSlot != null ? brandSlot : brandSuffix ? /* @__PURE__ */ jsxs2(Fragment, { children: [
269
328
  logo,
@@ -273,7 +332,7 @@ function NaeilHeader(_a) {
273
332
  );
274
333
  return /* @__PURE__ */ jsx2(
275
334
  Navigation,
276
- __spreadProps(__spreadValues({}, props), {
335
+ __spreadProps(__spreadValues(__spreadValues({}, props), service ? { "data-slot": "navigation", omitEmptyNavigation: true } : {}), {
277
336
  "data-global-header": true,
278
337
  "data-naeil-header": true,
279
338
  "data-naeil-chrome": "",
@@ -311,7 +370,7 @@ function NaeilHeaderAccountControl2(props) {
311
370
  // src/components/naeil-header.tsx
312
371
  import { jsx as jsx4 } from "react/jsx-runtime";
313
372
  function NaeilHeader2(props) {
314
- return /* @__PURE__ */ jsx4(NaeilStandaloneMessages, { locale: props.locale, children: /* @__PURE__ */ jsx4(NaeilHeader, __spreadValues({}, props)) });
373
+ return /* @__PURE__ */ jsx4(NaeilStandaloneMessages, { locale: props.locale, children: props.service === void 0 ? /* @__PURE__ */ jsx4(NaeilHeader, __spreadValues({}, props)) : /* @__PURE__ */ jsx4(NaeilHeader, __spreadValues({}, props)) });
315
374
  }
316
375
  function NaeilHeaderThemeControl2(props) {
317
376
  return /* @__PURE__ */ jsx4(NaeilStandaloneMessages, { locale: props.locale, children: /* @__PURE__ */ jsx4(NaeilHeaderThemeControl, __spreadValues({}, props)) });
@@ -322,6 +381,7 @@ function NaeilHeaderLocaleControl2(props) {
322
381
 
323
382
  export {
324
383
  headerLocales,
384
+ naeilServices,
325
385
  NaeilHeaderAccountControl2 as NaeilHeaderAccountControl,
326
386
  NaeilHeader2 as NaeilHeader,
327
387
  NaeilHeaderThemeControl2 as NaeilHeaderThemeControl,
@@ -1425,7 +1425,7 @@ function NaeilStandaloneMessages({ locale, children }) {
1425
1425
  }
1426
1426
 
1427
1427
  // src/lib/ui-release.ts
1428
- var uiRelease = { version: "0.12.0", contractVersion: "1" };
1428
+ var uiRelease = { version: "0.13.1", contractVersion: "1" };
1429
1429
 
1430
1430
  export {
1431
1431
  Logo,
@@ -56,16 +56,16 @@ import { cva as cva2 } from "class-variance-authority";
56
56
  import { Slot as Slot2 } from "radix-ui";
57
57
  import { jsx as jsx2 } from "react/jsx-runtime";
58
58
  var buttonVariants = cva2(
59
- "inline-flex items-center justify-center gap-2 whitespace-nowrap ui-control ui-focus rounded-md text-base font-medium transition-colors duration-(--ui-motion-fast) cursor-pointer disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 ui-focus aria-invalid:border-error",
59
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap ui-control ui-focus rounded-md text-base font-medium transition-colors duration-(--ui-motion-fast) cursor-pointer disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 ui-focus aria-invalid:border-error aria-pressed:inset-ring-2",
60
60
  {
61
61
  variants: {
62
62
  variant: {
63
- default: "bg-primary text-primary-foreground hover:bg-primary-hover",
64
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 ",
65
- outline: "border border-border-strong bg-background hover:bg-surface-subtle",
66
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
67
- ghost: "hover:bg-surface-subtle",
68
- link: "text-primary underline-offset-4 hover:underline"
63
+ default: "bg-primary text-primary-foreground hover:bg-primary-hover aria-pressed:bg-primary-hover aria-pressed:inset-ring-4 aria-pressed:inset-ring-primary-foreground aria-pressed:inset-shadow-[0_0_0_2px_var(--primary-hover)]",
64
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 aria-pressed:inset-ring-4 aria-pressed:inset-ring-destructive-foreground aria-pressed:inset-shadow-[0_0_0_2px_var(--destructive)]",
65
+ outline: "border border-border-strong bg-background hover:bg-surface-subtle aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
66
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
67
+ ghost: "hover:bg-surface-subtle aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
68
+ link: "text-primary underline-offset-4 hover:underline aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground"
69
69
  },
70
70
  size: {
71
71
  default: "px-4 has-[>svg]:px-3",
@@ -472,6 +472,7 @@ function Navigation(_a) {
472
472
  toolbar,
473
473
  mobileToolbar,
474
474
  mobileFooter,
475
+ omitEmptyNavigation = false,
475
476
  mobileOpen: controlledOpen,
476
477
  onMobileOpenChange,
477
478
  containerClassName,
@@ -486,6 +487,7 @@ function Navigation(_a) {
486
487
  "toolbar",
487
488
  "mobileToolbar",
488
489
  "mobileFooter",
490
+ "omitEmptyNavigation",
489
491
  "mobileOpen",
490
492
  "onMobileOpenChange",
491
493
  "containerClassName",
@@ -556,7 +558,8 @@ function Navigation(_a) {
556
558
  setOpenGroup(null);
557
559
  }, [currentHref, setMobileOpen]);
558
560
  React.useEffect(() => {
559
- const element = desktop.current;
561
+ var _a2, _b2;
562
+ const element = omitEmptyNavigation && !items.length ? (_b2 = (_a2 = desktop.current) == null ? void 0 : _a2.parentElement) == null ? void 0 : _b2.querySelector(".ui-navigation-toolbar") : desktop.current;
560
563
  if (!element || typeof ResizeObserver === "undefined") return;
561
564
  const observer = new ResizeObserver(() => {
562
565
  if (element.getBoundingClientRect().width > 0) setMobileOpen(false);
@@ -564,7 +567,8 @@ function Navigation(_a) {
564
567
  });
565
568
  observer.observe(element);
566
569
  return () => observer.disconnect();
567
- }, [setMobileOpen]);
570
+ }, [setMobileOpen, omitEmptyNavigation, items.length]);
571
+ const DesktopElement = omitEmptyNavigation && !items.length ? "div" : "nav";
568
572
  const active = (item) => {
569
573
  var _a2;
570
574
  return (_a2 = item.active) != null ? _a2 : !item.external && item.href === currentHref;
@@ -613,10 +617,12 @@ function Navigation(_a) {
613
617
  children: /* @__PURE__ */ jsx4("div", { className: cn("ui-navigation-frame", containerClassName), children: /* @__PURE__ */ jsxs2("div", { className: "ui-navigation-row", children: [
614
618
  /* @__PURE__ */ jsx4("div", { className: "ui-navigation-brand", children: brand }),
615
619
  /* @__PURE__ */ jsx4(
616
- "nav",
620
+ DesktopElement,
617
621
  {
618
- ref: desktop,
619
- "aria-label": labels.navigation,
622
+ ref: (element) => {
623
+ desktop.current = element;
624
+ },
625
+ "aria-label": omitEmptyNavigation && !items.length ? void 0 : labels.navigation,
620
626
  className: "ui-navigation-desktop",
621
627
  children: items.map(
622
628
  (item) => "items" in item ? /* @__PURE__ */ jsx4(
@@ -668,7 +674,7 @@ function Navigation(_a) {
668
674
  className: "ui-navigation-sheet ui-popup",
669
675
  "aria-describedby": void 0,
670
676
  onCloseAutoFocus: (event) => {
671
- var _a2, _b2;
677
+ var _a2, _b2, _c, _d;
672
678
  if (controlledOpen !== void 0 && (!mounted.current || state.current.open)) {
673
679
  event.preventDefault();
674
680
  return;
@@ -682,7 +688,10 @@ function Navigation(_a) {
682
688
  }
683
689
  if (trigger.current && trigger.current.getBoundingClientRect().width === 0) {
684
690
  event.preventDefault();
685
- (_b2 = (_a2 = desktop.current) == null ? void 0 : _a2.querySelector("button, a")) == null ? void 0 : _b2.focus();
691
+ const target = (_a2 = desktop.current) == null ? void 0 : _a2.querySelector("button, a");
692
+ const toolbar2 = omitEmptyNavigation && !items.length ? (_c = (_b2 = desktop.current) == null ? void 0 : _b2.parentElement) == null ? void 0 : _c.querySelector(".ui-navigation-toolbar") : void 0;
693
+ const toolbarTarget = !target && toolbar2 ? Array.from(toolbar2.querySelectorAll("button, a[href], input, select, textarea, [tabindex]")).find((element) => element.tabIndex >= 0 && !element.matches(":disabled") && element.getBoundingClientRect().width > 0 && element.getBoundingClientRect().height > 0) : void 0;
694
+ (_d = target != null ? target : toolbarTarget) == null ? void 0 : _d.focus();
686
695
  }
687
696
  },
688
697
  children: [
@@ -697,7 +706,7 @@ function Navigation(_a) {
697
706
  }
698
707
  )
699
708
  ] }),
700
- /* @__PURE__ */ jsx4(
709
+ (!omitEmptyNavigation || items.length > 0) && /* @__PURE__ */ jsx4(
701
710
  "nav",
702
711
  {
703
712
  "aria-label": labels.navigation,
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { N as NavigationLink, a as NavigationProps } from '../navigation-D8N1tMTu.js';
3
- import { S as SiteFooterProps } from '../site-footer-s113FZgC.js';
2
+ import { N as NavigationLink, a as NavigationProps } from '../navigation-CXZapKac.js';
3
+ import { S as SiteFooterProps } from '../site-footer-C4jgkGDU.js';
4
4
  import { ThemeProvider as ThemeProvider$1 } from 'next-themes';
5
5
  import * as React$1 from 'react';
6
6
  import { SVGProps } from 'react';
@@ -102,7 +102,7 @@ declare function Logo({ size, mono, variant, tone, theme, label, className, ...p
102
102
  type HeadingProps = React$1.HTMLAttributes<HTMLHeadingElement> & {
103
103
  children: React$1.ReactNode;
104
104
  };
105
- declare const pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
105
+ declare const pageTitleClass = "text-foreground text-3xl font-semibold";
106
106
  declare const sectionTitleClass = "text-foreground text-xl font-semibold";
107
107
  declare function PageTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
108
108
  declare function SectionTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  NaeilHeader,
4
4
  headerLocales
5
- } from "../chunk-XLISHUJZ.js";
5
+ } from "../chunk-ESTQITQO.js";
6
6
  import {
7
7
  Logo,
8
8
  en_default,
9
9
  ja_default,
10
10
  ko_default
11
- } from "../chunk-DBE7R4MR.js";
11
+ } from "../chunk-L25A4OKY.js";
12
12
  import {
13
13
  SiteFooter
14
14
  } from "../chunk-HSTDPY56.js";
@@ -18,7 +18,7 @@ import {
18
18
  DropdownMenuContent,
19
19
  DropdownMenuItem,
20
20
  DropdownMenuTrigger
21
- } from "../chunk-KPE4KKYM.js";
21
+ } from "../chunk-Y5LW3ADW.js";
22
22
  import {
23
23
  __objRest,
24
24
  __spreadProps,
@@ -362,7 +362,7 @@ function ThemeToggleIcon() {
362
362
 
363
363
  // src/components/typography.tsx
364
364
  import { jsx as jsx7 } from "react/jsx-runtime";
365
- var pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
365
+ var pageTitleClass = "text-foreground text-3xl font-semibold";
366
366
  var sectionTitleClass = "text-foreground text-xl font-semibold";
367
367
  function PageTitle(_a) {
368
368
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { S as SiteFooterProps } from '../site-footer-s113FZgC.js';
2
+ import { S as SiteFooterProps } from '../site-footer-C4jgkGDU.js';
3
3
  import { N as NaeilHeaderLocale } from '../naeil-header-data-BvISJ4RV.js';
4
4
  import 'react';
5
- import '../navigation-D8N1tMTu.js';
5
+ import '../navigation-CXZapKac.js';
6
6
 
7
7
  type NaeilFooterLocale = NaeilHeaderLocale;
8
8
  interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
@@ -5,7 +5,7 @@ import {
5
5
  NaeilStandaloneMessages,
6
6
  uiRelease,
7
7
  useNaeilMessages
8
- } from "../chunk-DBE7R4MR.js";
8
+ } from "../chunk-L25A4OKY.js";
9
9
  import {
10
10
  SiteFooter
11
11
  } from "../chunk-HSTDPY56.js";