@naeil/ui 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +38 -2
  2. package/DESIGN.md +13 -3
  3. package/README.md +13 -11
  4. package/THIRD_PARTY_NOTICES.md +4 -2
  5. package/dist/{chunk-KWEWR46R.js → chunk-5BXZPDHZ.js} +68 -8
  6. package/dist/{chunk-U3IZCFM4.js → chunk-A2DCQVTP.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 +22 -5
  15. package/dist/components/ui/index.js +181 -34
  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.d.ts +4 -2
  39. package/dist/source/components/ui/dialog.js +10 -6
  40. package/dist/source/components/ui/index.d.ts +1 -0
  41. package/dist/source/components/ui/index.js +22 -0
  42. package/dist/source/components/ui/navigation.d.ts +3 -1
  43. package/dist/source/components/ui/navigation.js +17 -8
  44. package/dist/source/components/ui/sheet.d.ts +20 -0
  45. package/dist/source/components/ui/sheet.js +176 -0
  46. package/dist/source/components/ui/sonner.js +2 -2
  47. package/dist/source/lib/ui-release.d.ts +1 -1
  48. package/dist/source/lib/ui-release.js +1 -1
  49. package/docs/components/README.md +4 -1
  50. package/docs/components/application-layout.md +27 -28
  51. package/docs/components/avatar.md +1 -1
  52. package/docs/components/badge.md +5 -1
  53. package/docs/components/button.md +9 -1
  54. package/docs/components/card.md +5 -1
  55. package/docs/components/checkbox.md +1 -1
  56. package/docs/components/common.md +22 -1
  57. package/docs/components/dialog.md +14 -4
  58. package/docs/components/dropdown-menu.md +1 -1
  59. package/docs/components/input.md +1 -1
  60. package/docs/components/naeil-footer.md +4 -2
  61. package/docs/components/naeil-header.md +41 -12
  62. package/docs/components/naeil-locale.md +36 -0
  63. package/docs/components/navigation.md +10 -4
  64. package/docs/components/select.md +1 -1
  65. package/docs/components/sheet.md +50 -0
  66. package/docs/components/sonner.md +7 -1
  67. package/docs/components/switch.md +1 -1
  68. package/docs/components/tabs.md +1 -1
  69. package/docs/components/textarea.md +1 -1
  70. package/docs/design/public-ui-support.md +3 -1
  71. package/docs/design/v2-migration.md +13 -7
  72. package/docs/package-release.md +24 -8
  73. package/package.json +11 -10
  74. package/src/styles/components.css +40 -2
  75. package/src/styles/globals.css +6 -2
  76. package/src/styles/theme.css +6 -0
  77. package/licenses/Nunito-Sans-OFL.txt +0 -93
  78. package/licenses/React-MIT.txt +0 -21
  79. package/licenses/Storybook-MIT.txt +0 -21
  80. package/licenses/popper-MIT.txt +0 -25
  81. package/licenses/store2-MIT.txt +0 -22
  82. package/licenses/toggle-selection-MIT.txt +0 -21
@@ -1,18 +1,20 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, JSX } from 'react';
3
3
  import { NavigationProps, NavigationItem, NavigationLinkProps, NavigationLink, NavigationLinkComponent } from './ui/navigation.js';
4
4
  import { NaeilHeaderLocale } from './naeil-header-data.js';
5
5
  export { NaeilHeaderAccount, NaeilHeaderAccountControl, NaeilHeaderAccountControlProps } from './naeil-header-account-core.js';
6
6
 
7
7
  interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
8
+ service?: undefined;
8
9
  locale: NaeilHeaderLocale;
9
10
  /** Resolve canonical unlocalized paths. Defaults to the official localized site. */
10
11
  resolveHref?: (path: string) => string;
11
12
  brandHref?: string;
13
+ /** @deprecated Owned services must use service; retained for compatibility. */
12
14
  brandSlot?: ReactNode;
13
- /** Ignored when brandSlot replaces the complete brand content. */
15
+ /** @deprecated Owned services must use service; retained for compatibility. Ignored with brandSlot. */
14
16
  brandSuffix?: string;
15
- /** After the brand link, outside it; rendered once at every width. */
17
+ /** @deprecated Owned services must use service with no indicator; retained for compatibility. */
16
18
  statusSlot?: ReactNode;
17
19
  /** Product menu data, after catalog/blog and before flat subNav links. */
18
20
  appNavigation?: NavigationItem[];
@@ -33,17 +35,32 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
33
35
  };
34
36
  showProjects?: boolean;
35
37
  showBlog?: boolean;
38
+ /** @deprecated Owned services must use service and appNavigation; retained for compatibility. */
36
39
  subNav?: Array<{
37
40
  label: string;
38
41
  href: string;
39
42
  }>;
40
43
  currentProjectKey?: string;
41
44
  currentProjectHref?: string;
42
- /** Compatibility escape hatch replacing the default theme/locale/auth toolbar. */
45
+ /** @deprecated Owned services must use service and authSlot; retained for compatibility. */
43
46
  toolbarSlot?: ReactNode;
44
- /** Compatibility escape hatch for the legacy native external brand link. */
47
+ /** @deprecated Owned services must use service and Link; retained for compatibility. */
45
48
  brandLinkComponent?: NavigationLinkComponent;
46
49
  }
50
+ /** Canonical owned-service identifiers; their spelling is the visible brand suffix. */
51
+ declare const naeilServices: readonly ["abstorm", "home", "estimate", "jev"];
52
+ type NaeilService = typeof naeilServices[number];
53
+ declare const serviceCompatibilityProps: readonly ["brandSuffix", "statusSlot", "brandSlot", "toolbarSlot", "subNav", "brandLinkComponent", "projects", "projectsExternal", "showProjects", "showBlog", "translations", "className", "containerClassName", "style", "brandLinkProps", "mobileFooter", "omitEmptyNavigation"];
54
+ type ServiceCompatibilityProp = typeof serviceCompatibilityProps[number];
55
+ /** Strict owned-service props; the legacy interface remains independently extensible. */
56
+ type NaeilServiceHeaderProps = Omit<NaeilHeaderProps, ServiceCompatibilityProp | "service"> & {
57
+ service: NaeilService;
58
+ } & {
59
+ [Prop in ServiceCompatibilityProp]?: never;
60
+ };
61
+ /** Opt into the owned-service contract without changing the legacy composition. */
62
+ declare function NaeilHeader(props: NaeilServiceHeaderProps): JSX.Element;
63
+ declare function NaeilHeader(props: NaeilHeaderProps): JSX.Element;
47
64
  /** The actual header theme control; reads only the consumer's theme provider. */
48
65
  declare function NaeilHeaderThemeControl({ locale }: {
49
66
  locale: NaeilHeaderLocale;
@@ -53,7 +70,5 @@ declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
53
70
  locale: NaeilHeaderLocale;
54
71
  onLocaleChange: (locale: NaeilHeaderLocale) => void;
55
72
  }): react_jsx_runtime.JSX.Element;
56
- /** One complete, opt-in branded composition shared by naeil.dev and applications. */
57
- declare function NaeilHeader({ locale, resolveHref, brandHref, brandSlot, brandSuffix, statusSlot, appNavigation, brandLinkProps, brandLinkComponent, onLocaleChange, authSlot, toolbarSlot, projects, projectsExternal, translations, showProjects, showBlog, subNav, currentProjectKey, currentProjectHref, labels, Link, currentHref, onNavigate, className, containerClassName, ...props }: NaeilHeaderProps): react_jsx_runtime.JSX.Element;
58
73
 
59
- export { NaeilHeader, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
74
+ export { NaeilHeader, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl, type NaeilService, type NaeilServiceHeaderProps, naeilServices };
@@ -44,6 +44,58 @@ import { uiRelease } from "../lib/ui-release.js";
44
44
  import { headerLocales, headerProjects } from "./naeil-header-data.js";
45
45
  import { useNaeilMessages } from "./naeil-messages-context.js";
46
46
  import { NaeilHeaderAccountControl } from "./naeil-header-account-core.js";
47
+ const naeilServices = Object.freeze(["abstorm", "home", "estimate", "jev"]);
48
+ const serviceCompatibilityProps = [
49
+ "brandSuffix",
50
+ "statusSlot",
51
+ "brandSlot",
52
+ "toolbarSlot",
53
+ "subNav",
54
+ "brandLinkComponent",
55
+ "projects",
56
+ "projectsExternal",
57
+ "showProjects",
58
+ "showBlog",
59
+ "translations",
60
+ "className",
61
+ "containerClassName",
62
+ "style",
63
+ "brandLinkProps",
64
+ "mobileFooter",
65
+ "omitEmptyNavigation"
66
+ ];
67
+ const warnedServiceProps = /* @__PURE__ */ new Set();
68
+ function isDevelopment() {
69
+ try {
70
+ return process.env.NODE_ENV === "development";
71
+ } catch (e) {
72
+ return false;
73
+ }
74
+ }
75
+ function warnServiceProp(name, message) {
76
+ if (!isDevelopment() || warnedServiceProps.has(name)) return;
77
+ warnedServiceProps.add(name);
78
+ console.warn(message);
79
+ }
80
+ function isNaeilService(value) {
81
+ return naeilServices.includes(value);
82
+ }
83
+ function NaeilHeader(input) {
84
+ if (input.service === void 0) return /* @__PURE__ */ jsx(HeaderComposition, __spreadValues({}, input));
85
+ if (!isNaeilService(input.service)) {
86
+ warnServiceProp("service", "NaeilHeader: invalid service; rendering the legacy profile.");
87
+ const legacy = __spreadProps(__spreadValues({}, input), { service: void 0 });
88
+ delete legacy.service;
89
+ return /* @__PURE__ */ jsx(HeaderComposition, __spreadValues({}, legacy));
90
+ }
91
+ const props = __spreadValues({}, input);
92
+ for (const name of Object.keys(props)) {
93
+ if (!serviceCompatibilityProps.includes(name) && name !== "data-slot" && name !== "data-global-header" && !name.startsWith("data-naeil-")) continue;
94
+ delete props[name];
95
+ warnServiceProp(name, `NaeilHeader: service profile ignores ${name}; use the shared service composition.`);
96
+ }
97
+ return /* @__PURE__ */ jsx(HeaderComposition, __spreadProps(__spreadValues({}, props), { service: input.service }));
98
+ }
47
99
  const subscribe = () => () => {
48
100
  };
49
101
  function NaeilHeaderThemeControl({ locale }) {
@@ -80,8 +132,9 @@ function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
80
132
  ] });
81
133
  }
82
134
  const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
83
- function NaeilHeader(_a) {
135
+ function HeaderComposition(_a) {
84
136
  var _b = _a, {
137
+ service,
85
138
  locale,
86
139
  resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
87
140
  brandHref,
@@ -109,6 +162,7 @@ function NaeilHeader(_a) {
109
162
  className,
110
163
  containerClassName
111
164
  } = _b, props = __objRest(_b, [
165
+ "service",
112
166
  "locale",
113
167
  "resolveHref",
114
168
  "brandHref",
@@ -137,6 +191,11 @@ function NaeilHeader(_a) {
137
191
  "containerClassName"
138
192
  ]);
139
193
  var _b2, _c;
194
+ if (service) {
195
+ brandSuffix = service;
196
+ showProjects = false;
197
+ showBlog = false;
198
+ }
140
199
  const content = useNaeilMessages(locale).header;
141
200
  const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
142
201
  var _a3, _b3, _c2;
@@ -155,7 +214,7 @@ function NaeilHeader(_a) {
155
214
  badge: project.status === "coming" ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
156
215
  };
157
216
  });
158
- const brandDestination = brandHref != null ? brandHref : resolveHref("/");
217
+ const brandDestination = brandHref != null ? brandHref : service ? "/" : resolveHref("/");
159
218
  const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
160
219
  const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
161
220
  const toolbar = /* @__PURE__ */ jsx(
@@ -181,11 +240,11 @@ function NaeilHeader(_a) {
181
240
  __spreadProps(__spreadValues({
182
241
  href: brandDestination,
183
242
  "data-app-brand": true,
184
- "aria-label": brandSlot == null ? ".naeil" : void 0
243
+ "aria-label": service ? `.naeil ${service}` : brandSlot == null ? ".naeil" : void 0
185
244
  }, brandProps), {
186
245
  onClick: (event) => {
187
246
  onBrandClick == null ? void 0 : onBrandClick(event);
188
- onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
247
+ onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: service ? `.naeil ${service}` : ".naeil" });
189
248
  },
190
249
  children: brandSlot != null ? brandSlot : brandSuffix ? /* @__PURE__ */ jsxs(Fragment, { children: [
191
250
  logo,
@@ -195,7 +254,7 @@ function NaeilHeader(_a) {
195
254
  );
196
255
  return /* @__PURE__ */ jsx(
197
256
  Navigation,
198
- __spreadProps(__spreadValues({}, props), {
257
+ __spreadProps(__spreadValues(__spreadValues({}, props), service ? { "data-slot": "navigation", omitEmptyNavigation: true } : {}), {
199
258
  "data-global-header": true,
200
259
  "data-naeil-header": true,
201
260
  "data-naeil-chrome": "",
@@ -227,5 +286,6 @@ export {
227
286
  NaeilHeader,
228
287
  NaeilHeaderAccountControl,
229
288
  NaeilHeaderLocaleControl,
230
- NaeilHeaderThemeControl
289
+ NaeilHeaderThemeControl,
290
+ naeilServices
231
291
  };
@@ -1,12 +1,14 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { NaeilHeaderProps } from './naeil-header-core.js';
2
+ import { JSX } from 'react';
3
+ import { NaeilServiceHeaderProps, NaeilHeaderProps } from './naeil-header-core.js';
4
+ export { NaeilService, naeilServices } from './naeil-header-core.js';
3
5
  import { NaeilHeaderLocale } from './naeil-header-data.js';
4
6
  export { NaeilHeaderAccountControl } from './naeil-header-account.js';
5
7
  export { NaeilHeaderAccount, NaeilHeaderAccountControlProps } from './naeil-header-account-core.js';
6
- import 'react';
7
8
  import './ui/navigation.js';
8
9
 
9
- declare function NaeilHeader(props: NaeilHeaderProps): react_jsx_runtime.JSX.Element;
10
+ declare function NaeilHeader(props: NaeilServiceHeaderProps): JSX.Element;
11
+ declare function NaeilHeader(props: NaeilHeaderProps): JSX.Element;
10
12
  declare function NaeilHeaderThemeControl(props: {
11
13
  locale: NaeilHeaderLocale;
12
14
  }): react_jsx_runtime.JSX.Element;
@@ -15,4 +17,4 @@ declare function NaeilHeaderLocaleControl(props: {
15
17
  onLocaleChange: (locale: NaeilHeaderLocale) => void;
16
18
  }): react_jsx_runtime.JSX.Element;
17
19
 
18
- export { NaeilHeader, NaeilHeaderLocale, NaeilHeaderLocaleControl, NaeilHeaderProps, NaeilHeaderThemeControl };
20
+ export { NaeilHeader, NaeilHeaderLocale, NaeilHeaderLocaleControl, NaeilHeaderProps, NaeilHeaderThemeControl, NaeilServiceHeaderProps };
@@ -18,9 +18,10 @@ var __spreadValues = (a, b) => {
18
18
  import { jsx } from "react/jsx-runtime";
19
19
  import { NaeilHeader as Header, NaeilHeaderThemeControl as ThemeControl, NaeilHeaderLocaleControl as LocaleControl } from "./naeil-header-core.js";
20
20
  import { NaeilStandaloneMessages } from "./naeil-standalone-messages.js";
21
+ import { naeilServices } from "./naeil-header-core.js";
21
22
  import { NaeilHeaderAccountControl } from "./naeil-header-account.js";
22
23
  function NaeilHeader(props) {
23
- return /* @__PURE__ */ jsx(NaeilStandaloneMessages, { locale: props.locale, children: /* @__PURE__ */ jsx(Header, __spreadValues({}, props)) });
24
+ return /* @__PURE__ */ jsx(NaeilStandaloneMessages, { locale: props.locale, children: props.service === void 0 ? /* @__PURE__ */ jsx(Header, __spreadValues({}, props)) : /* @__PURE__ */ jsx(Header, __spreadValues({}, props)) });
24
25
  }
25
26
  function NaeilHeaderThemeControl(props) {
26
27
  return /* @__PURE__ */ jsx(NaeilStandaloneMessages, { locale: props.locale, children: /* @__PURE__ */ jsx(ThemeControl, __spreadValues({}, props)) });
@@ -32,5 +33,6 @@ export {
32
33
  NaeilHeader,
33
34
  NaeilHeaderAccountControl,
34
35
  NaeilHeaderLocaleControl,
35
- NaeilHeaderThemeControl
36
+ NaeilHeaderThemeControl,
37
+ naeilServices
36
38
  };
@@ -4,7 +4,7 @@ import * as react from 'react';
4
4
  type HeadingProps = react.HTMLAttributes<HTMLHeadingElement> & {
5
5
  children: react.ReactNode;
6
6
  };
7
- declare const pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
7
+ declare const pageTitleClass = "text-foreground text-3xl font-semibold";
8
8
  declare const sectionTitleClass = "text-foreground text-xl font-semibold";
9
9
  declare function PageTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
10
10
  declare function SectionTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
@@ -31,7 +31,7 @@ var __objRest = (source, exclude) => {
31
31
  };
32
32
  import { jsx } from "react/jsx-runtime";
33
33
  import { cn } from "../lib/utils.js";
34
- const pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
34
+ const pageTitleClass = "text-foreground text-3xl font-semibold";
35
35
  const sectionTitleClass = "text-foreground text-xl font-semibold";
36
36
  function PageTitle(_a) {
37
37
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
@@ -31,16 +31,16 @@ import { cva } from "class-variance-authority";
31
31
  import { Slot } from "radix-ui";
32
32
  import { cn } from "../../lib/utils.js";
33
33
  const buttonVariants = cva(
34
- "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",
34
+ "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",
35
35
  {
36
36
  variants: {
37
37
  variant: {
38
- default: "bg-primary text-primary-foreground hover:bg-primary-hover",
39
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 ",
40
- outline: "border border-border-strong bg-background hover:bg-surface-subtle",
41
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
42
- ghost: "hover:bg-surface-subtle",
43
- link: "text-primary underline-offset-4 hover:underline"
38
+ 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)]",
39
+ 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)]",
40
+ 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",
41
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
42
+ ghost: "hover:bg-surface-subtle aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
43
+ link: "text-primary underline-offset-4 hover:underline aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground"
44
44
  },
45
45
  size: {
46
46
  default: "px-4 has-[>svg]:px-3",
@@ -73,7 +73,7 @@ function CardTitle(_g) {
73
73
  "div",
74
74
  __spreadValues({
75
75
  "data-slot": "card-title",
76
- className: cn("leading-none font-semibold", className)
76
+ className: cn("text-base font-semibold", className)
77
77
  }, props)
78
78
  );
79
79
  }
@@ -7,12 +7,14 @@ declare function DialogTrigger({ ...props }: react.ComponentProps<typeof Dialog$
7
7
  declare function DialogPortal({ ...props }: react.ComponentProps<typeof Dialog$1.Portal>): react_jsx_runtime.JSX.Element;
8
8
  declare function DialogClose({ ...props }: react.ComponentProps<typeof Dialog$1.Close>): react_jsx_runtime.JSX.Element;
9
9
  declare function DialogOverlay({ className, ...props }: react.ComponentProps<typeof Dialog$1.Overlay>): react_jsx_runtime.JSX.Element;
10
- declare function DialogContent({ className, children, showCloseButton, ...props }: react.ComponentProps<typeof Dialog$1.Content> & {
10
+ declare function DialogContent({ className, children, showCloseButton, closeLabel, ...props }: react.ComponentProps<typeof Dialog$1.Content> & {
11
11
  showCloseButton?: boolean;
12
+ closeLabel?: string;
12
13
  }): react_jsx_runtime.JSX.Element;
13
14
  declare function DialogHeader({ className, ...props }: react.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
14
- declare function DialogFooter({ className, showCloseButton, children, ...props }: react.ComponentProps<"div"> & {
15
+ declare function DialogFooter({ className, showCloseButton, closeLabel, children, ...props }: react.ComponentProps<"div"> & {
15
16
  showCloseButton?: boolean;
17
+ closeLabel?: string;
16
18
  }): react_jsx_runtime.JSX.Element;
17
19
  declare function DialogTitle({ className, ...props }: react.ComponentProps<typeof Dialog$1.Title>): react_jsx_runtime.JSX.Element;
18
20
  declare function DialogDescription({ className, ...props }: react.ComponentProps<typeof Dialog$1.Description>): react_jsx_runtime.JSX.Element;
@@ -69,11 +69,13 @@ function DialogContent(_g) {
69
69
  var _h = _g, {
70
70
  className,
71
71
  children,
72
- showCloseButton = true
72
+ showCloseButton = true,
73
+ closeLabel = "Close"
73
74
  } = _h, props = __objRest(_h, [
74
75
  "className",
75
76
  "children",
76
- "showCloseButton"
77
+ "showCloseButton",
78
+ "closeLabel"
77
79
  ]);
78
80
  return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
79
81
  /* @__PURE__ */ jsx(DialogOverlay, {}),
@@ -82,7 +84,7 @@ function DialogContent(_g) {
82
84
  __spreadProps(__spreadValues({
83
85
  "data-slot": "dialog-content",
84
86
  className: cn(
85
- "bg-popover ui-popup fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border-strong p-6 sm:max-w-lg",
87
+ "bg-popover ui-popup fixed top-[50%] left-[50%] z-50 grid w-full max-h-[min(calc(100%-2rem),calc(100dvh-2rem))] overflow-y-auto max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border-strong p-6 sm:max-w-lg",
86
88
  className
87
89
  )
88
90
  }, props), {
@@ -95,7 +97,7 @@ function DialogContent(_g) {
95
97
  className: "ui-focus absolute top-2 right-2 flex size-10 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground transition-colors ui-focus disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
96
98
  children: [
97
99
  /* @__PURE__ */ jsx(XIcon, {}),
98
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
100
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: closeLabel })
99
101
  ]
100
102
  }
101
103
  )
@@ -118,10 +120,12 @@ function DialogFooter(_k) {
118
120
  var _l = _k, {
119
121
  className,
120
122
  showCloseButton = false,
123
+ closeLabel = "Close",
121
124
  children
122
125
  } = _l, props = __objRest(_l, [
123
126
  "className",
124
127
  "showCloseButton",
128
+ "closeLabel",
125
129
  "children"
126
130
  ]);
127
131
  return /* @__PURE__ */ jsxs(
@@ -135,7 +139,7 @@ function DialogFooter(_k) {
135
139
  }, props), {
136
140
  children: [
137
141
  children,
138
- showCloseButton && /* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", children: "Close" }) })
142
+ showCloseButton && /* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", children: closeLabel }) })
139
143
  ]
140
144
  })
141
145
  );
@@ -150,7 +154,7 @@ function DialogTitle(_m) {
150
154
  DialogPrimitive.Title,
151
155
  __spreadValues({
152
156
  "data-slot": "dialog-title",
153
- className: cn("text-xl leading-normal font-semibold", className)
157
+ className: cn("text-xl font-semibold", className)
154
158
  }, props)
155
159
  );
156
160
  }
@@ -3,6 +3,7 @@ export { Badge, badgeVariants } from './badge.js';
3
3
  export { Button, buttonVariants } from './button.js';
4
4
  export { Card, CardAction, CardContent, CardDescription, CardElevated, CardFooter, CardHeader, CardTitle } from './card.js';
5
5
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './dialog.js';
6
+ export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger } from './sheet.js';
6
7
  export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from './dropdown-menu.js';
7
8
  export { Input } from './input.js';
8
9
  export { Toaster } from './sonner.js';
@@ -30,6 +30,18 @@ import {
30
30
  DialogTitle,
31
31
  DialogTrigger
32
32
  } from "./dialog.js";
33
+ import {
34
+ Sheet,
35
+ SheetClose,
36
+ SheetContent,
37
+ SheetDescription,
38
+ SheetFooter,
39
+ SheetHeader,
40
+ SheetOverlay,
41
+ SheetPortal,
42
+ SheetTitle,
43
+ SheetTrigger
44
+ } from "./sheet.js";
33
45
  import {
34
46
  DropdownMenu,
35
47
  DropdownMenuPortal,
@@ -122,6 +134,16 @@ export {
122
134
  SelectSeparator,
123
135
  SelectTrigger,
124
136
  SelectValue,
137
+ Sheet,
138
+ SheetClose,
139
+ SheetContent,
140
+ SheetDescription,
141
+ SheetFooter,
142
+ SheetHeader,
143
+ SheetOverlay,
144
+ SheetPortal,
145
+ SheetTitle,
146
+ SheetTrigger,
125
147
  SiteFooter,
126
148
  Switch,
127
149
  Tabs,
@@ -25,6 +25,8 @@ interface NavigationGroup {
25
25
  }
26
26
  type NavigationItem = NavigationLink | NavigationGroup;
27
27
  interface NavigationProps extends Omit<react.ComponentPropsWithoutRef<"header">, "children" | "onSelect"> {
28
+ /** Omit empty landmarks and dismiss toolbar-only sheets on desktop crossing. */
29
+ omitEmptyNavigation?: boolean;
28
30
  brand: react.ReactNode;
29
31
  items: NavigationItem[];
30
32
  /** Translated landmark/dialog/close labels are supplied by the application. */
@@ -49,6 +51,6 @@ declare const NavigationSheetAction: react.Context<((action: () => void) => {
49
51
  menuClosed: () => void;
50
52
  cancel: () => void;
51
53
  }) | undefined>;
52
- declare function Navigation({ brand, items, labels, Link, currentHref, toolbar, mobileToolbar, mobileFooter, mobileOpen: controlledOpen, onMobileOpenChange, containerClassName, onNavigate, className, ...props }: NavigationProps): react_jsx_runtime.JSX.Element;
54
+ declare function Navigation({ brand, items, labels, Link, currentHref, toolbar, mobileToolbar, mobileFooter, omitEmptyNavigation, mobileOpen: controlledOpen, onMobileOpenChange, containerClassName, onNavigate, className, ...props }: NavigationProps): react_jsx_runtime.JSX.Element;
53
55
 
54
56
  export { Navigation, type NavigationGroup, type NavigationItem, type NavigationLink, type NavigationLinkComponent, type NavigationLinkProps, type NavigationProps, NavigationSheetAction };
@@ -169,6 +169,7 @@ function Navigation(_a) {
169
169
  toolbar,
170
170
  mobileToolbar,
171
171
  mobileFooter,
172
+ omitEmptyNavigation = false,
172
173
  mobileOpen: controlledOpen,
173
174
  onMobileOpenChange,
174
175
  containerClassName,
@@ -183,6 +184,7 @@ function Navigation(_a) {
183
184
  "toolbar",
184
185
  "mobileToolbar",
185
186
  "mobileFooter",
187
+ "omitEmptyNavigation",
186
188
  "mobileOpen",
187
189
  "onMobileOpenChange",
188
190
  "containerClassName",
@@ -253,7 +255,8 @@ function Navigation(_a) {
253
255
  setOpenGroup(null);
254
256
  }, [currentHref, setMobileOpen]);
255
257
  React.useEffect(() => {
256
- const element = desktop.current;
258
+ var _a2, _b2;
259
+ const element = omitEmptyNavigation && !items.length ? (_b2 = (_a2 = desktop.current) == null ? void 0 : _a2.parentElement) == null ? void 0 : _b2.querySelector(".ui-navigation-toolbar") : desktop.current;
257
260
  if (!element || typeof ResizeObserver === "undefined") return;
258
261
  const observer = new ResizeObserver(() => {
259
262
  if (element.getBoundingClientRect().width > 0) setMobileOpen(false);
@@ -261,7 +264,8 @@ function Navigation(_a) {
261
264
  });
262
265
  observer.observe(element);
263
266
  return () => observer.disconnect();
264
- }, [setMobileOpen]);
267
+ }, [setMobileOpen, omitEmptyNavigation, items.length]);
268
+ const DesktopElement = omitEmptyNavigation && !items.length ? "div" : "nav";
265
269
  const active = (item) => {
266
270
  var _a2;
267
271
  return (_a2 = item.active) != null ? _a2 : !item.external && item.href === currentHref;
@@ -310,10 +314,12 @@ function Navigation(_a) {
310
314
  children: /* @__PURE__ */ jsx("div", { className: cn("ui-navigation-frame", containerClassName), children: /* @__PURE__ */ jsxs("div", { className: "ui-navigation-row", children: [
311
315
  /* @__PURE__ */ jsx("div", { className: "ui-navigation-brand", children: brand }),
312
316
  /* @__PURE__ */ jsx(
313
- "nav",
317
+ DesktopElement,
314
318
  {
315
- ref: desktop,
316
- "aria-label": labels.navigation,
319
+ ref: (element) => {
320
+ desktop.current = element;
321
+ },
322
+ "aria-label": omitEmptyNavigation && !items.length ? void 0 : labels.navigation,
317
323
  className: "ui-navigation-desktop",
318
324
  children: items.map(
319
325
  (item) => "items" in item ? /* @__PURE__ */ jsx(
@@ -365,7 +371,7 @@ function Navigation(_a) {
365
371
  className: "ui-navigation-sheet ui-popup",
366
372
  "aria-describedby": void 0,
367
373
  onCloseAutoFocus: (event) => {
368
- var _a2, _b2;
374
+ var _a2, _b2, _c, _d;
369
375
  if (controlledOpen !== void 0 && (!mounted.current || state.current.open)) {
370
376
  event.preventDefault();
371
377
  return;
@@ -379,7 +385,10 @@ function Navigation(_a) {
379
385
  }
380
386
  if (trigger.current && trigger.current.getBoundingClientRect().width === 0) {
381
387
  event.preventDefault();
382
- (_b2 = (_a2 = desktop.current) == null ? void 0 : _a2.querySelector("button, a")) == null ? void 0 : _b2.focus();
388
+ const target = (_a2 = desktop.current) == null ? void 0 : _a2.querySelector("button, a");
389
+ const toolbar2 = omitEmptyNavigation && !items.length ? (_c = (_b2 = desktop.current) == null ? void 0 : _b2.parentElement) == null ? void 0 : _c.querySelector(".ui-navigation-toolbar") : void 0;
390
+ 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;
391
+ (_d = target != null ? target : toolbarTarget) == null ? void 0 : _d.focus();
383
392
  }
384
393
  },
385
394
  children: [
@@ -394,7 +403,7 @@ function Navigation(_a) {
394
403
  }
395
404
  )
396
405
  ] }),
397
- /* @__PURE__ */ jsx(
406
+ (!omitEmptyNavigation || items.length > 0) && /* @__PURE__ */ jsx(
398
407
  "nav",
399
408
  {
400
409
  "aria-label": labels.navigation,
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import { Dialog } from 'radix-ui';
4
+
5
+ declare function Sheet({ ...props }: react.ComponentProps<typeof Dialog.Root>): react_jsx_runtime.JSX.Element;
6
+ declare function SheetTrigger({ ...props }: react.ComponentProps<typeof Dialog.Trigger>): react_jsx_runtime.JSX.Element;
7
+ declare function SheetPortal({ ...props }: react.ComponentProps<typeof Dialog.Portal>): react_jsx_runtime.JSX.Element;
8
+ declare function SheetClose({ ...props }: react.ComponentProps<typeof Dialog.Close>): react_jsx_runtime.JSX.Element;
9
+ declare function SheetOverlay({ className, ...props }: react.ComponentProps<typeof Dialog.Overlay>): react_jsx_runtime.JSX.Element;
10
+ declare function SheetContent({ className, children, side, showCloseButton, closeLabel, ...props }: react.ComponentProps<typeof Dialog.Content> & {
11
+ side?: "right" | "left" | "top" | "bottom";
12
+ showCloseButton?: boolean;
13
+ closeLabel?: string;
14
+ }): react_jsx_runtime.JSX.Element;
15
+ declare function SheetHeader({ className, ...props }: react.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
16
+ declare function SheetFooter({ className, ...props }: react.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
17
+ declare function SheetTitle({ className, ...props }: react.ComponentProps<typeof Dialog.Title>): react_jsx_runtime.JSX.Element;
18
+ declare function SheetDescription({ className, ...props }: react.ComponentProps<typeof Dialog.Description>): react_jsx_runtime.JSX.Element;
19
+
20
+ export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger };