@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.
- package/CHANGELOG.md +38 -3
- package/DESIGN.md +10 -2
- package/README.md +13 -11
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/{chunk-XLISHUJZ.js → chunk-ESTQITQO.js} +68 -8
- package/dist/{chunk-DBE7R4MR.js → chunk-L25A4OKY.js} +1 -1
- package/dist/{chunk-KPE4KKYM.js → chunk-Y5LW3ADW.js} +24 -15
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.js +4 -4
- package/dist/components/naeil-footer.d.ts +2 -2
- package/dist/components/naeil-footer.js +1 -1
- package/dist/components/naeil-header.d.ts +23 -8
- package/dist/components/naeil-header.js +7 -5
- package/dist/components/ui/index.d.ts +2 -2
- package/dist/components/ui/index.js +6 -6
- package/dist/lib/ui-release.d.ts +1 -1
- package/dist/lib/ui-release.js +1 -1
- package/dist/lib/utils.js +1 -7
- package/dist/naeil-locale/checker.js +1 -1
- package/dist/naeil-locale/chrome.d.ts +25 -8
- package/dist/naeil-locale/chrome.js +91 -22
- package/dist/naeil-locale/{chunk-4U64K4J3.js → chunk-24IL53QO.js} +1 -1
- package/dist/naeil-locale/{chunk-U65OQHZY.js → chunk-WT6QXR7O.js} +14 -8
- package/dist/naeil-locale/client.js +45 -15
- package/dist/naeil-locale/index.js +1 -1
- package/dist/naeil-locale/messages.js +2 -2
- package/dist/naeil-locale/server.js +6 -6
- package/dist/{navigation-D8N1tMTu.d.ts → navigation-CXZapKac.d.ts} +3 -1
- package/dist/{site-footer-s113FZgC.d.ts → site-footer-C4jgkGDU.d.ts} +1 -1
- package/dist/source/components/naeil-header-core.d.ts +23 -8
- package/dist/source/components/naeil-header-core.js +66 -6
- package/dist/source/components/naeil-header.d.ts +6 -4
- package/dist/source/components/naeil-header.js +4 -2
- package/dist/source/components/typography.d.ts +1 -1
- package/dist/source/components/typography.js +1 -1
- package/dist/source/components/ui/button.js +7 -7
- package/dist/source/components/ui/card.js +1 -1
- package/dist/source/components/ui/dialog.js +2 -2
- package/dist/source/components/ui/navigation.d.ts +3 -1
- package/dist/source/components/ui/navigation.js +17 -8
- package/dist/source/components/ui/sonner.js +2 -2
- package/dist/source/lib/ui-release.d.ts +1 -1
- package/dist/source/lib/ui-release.js +1 -1
- package/docs/components/README.md +3 -1
- package/docs/components/application-layout.md +23 -27
- package/docs/components/avatar.md +1 -1
- package/docs/components/badge.md +3 -1
- package/docs/components/button.md +7 -1
- package/docs/components/card.md +5 -1
- package/docs/components/checkbox.md +1 -1
- package/docs/components/common.md +16 -1
- package/docs/components/dialog.md +6 -2
- package/docs/components/dropdown-menu.md +1 -1
- package/docs/components/input.md +1 -1
- package/docs/components/naeil-footer.md +1 -1
- package/docs/components/naeil-header.md +41 -12
- package/docs/components/naeil-locale.md +36 -0
- package/docs/components/navigation.md +10 -4
- package/docs/components/select.md +1 -1
- package/docs/components/sheet.md +1 -1
- package/docs/components/sonner.md +7 -1
- package/docs/components/switch.md +1 -1
- package/docs/components/tabs.md +1 -1
- package/docs/components/textarea.md +1 -1
- package/docs/design/public-ui-support.md +3 -1
- package/docs/design/v2-migration.md +11 -6
- package/docs/package-release.md +36 -12
- package/package.json +7 -10
- package/src/styles/components.css +29 -0
- package/src/styles/globals.css +6 -2
- package/src/styles/theme.css +5 -0
- package/licenses/Nunito-Sans-OFL.txt +0 -93
- package/licenses/React-MIT.txt +0 -21
- package/licenses/Storybook-MIT.txt +0 -21
- package/licenses/popper-MIT.txt +0 -25
- package/licenses/store2-MIT.txt +0 -22
- package/licenses/toggle-selection-MIT.txt +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
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 (
|
|
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 (
|
|
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/
|
|
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
|
-
|
|
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.
|
|
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/
|
|
13
|
-
| Use frontend references with an agent | [Optional workflow setup](https://github.com/naeil-dev/naeil-ui/blob/
|
|
14
|
-
| Develop the brand/example website | [Site setup](https://github.com/naeil-dev/naeil-ui/blob/
|
|
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
|
|
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.
|
|
23
|
+
pnpm add --save-exact @naeil/ui@0.13.1
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
The [npm 0.
|
|
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
|
|
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-
|
|
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
|
|
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/
|
|
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.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -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
|
-
|
|
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-
|
|
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-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
620
|
+
DesktopElement,
|
|
617
621
|
{
|
|
618
|
-
ref:
|
|
619
|
-
|
|
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
|
-
|
|
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-
|
|
3
|
-
import { S as SiteFooterProps } from '../site-footer-
|
|
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
|
|
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;
|
package/dist/components/index.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
NaeilHeader,
|
|
4
4
|
headerLocales
|
|
5
|
-
} from "../chunk-
|
|
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-
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
5
|
+
import '../navigation-CXZapKac.js';
|
|
6
6
|
|
|
7
7
|
type NaeilFooterLocale = NaeilHeaderLocale;
|
|
8
8
|
interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
|