@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
import { b as NavigationLinkComponent, a as NavigationProps, c as NavigationItem, d as NavigationLinkProps, N as NavigationLink } from '../navigation-
|
|
2
|
+
import { ReactNode, JSX } from 'react';
|
|
3
|
+
import { b as NavigationLinkComponent, a as NavigationProps, c as NavigationItem, d as NavigationLinkProps, N as NavigationLink } from '../navigation-CXZapKac.js';
|
|
4
4
|
import { N as NaeilHeaderLocale } from '../naeil-header-data-BvISJ4RV.js';
|
|
5
5
|
|
|
6
6
|
type NaeilHeaderAccount = {
|
|
@@ -22,14 +22,16 @@ interface NaeilHeaderAccountControlProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
|
|
25
|
+
service?: undefined;
|
|
25
26
|
locale: NaeilHeaderLocale;
|
|
26
27
|
/** Resolve canonical unlocalized paths. Defaults to the official localized site. */
|
|
27
28
|
resolveHref?: (path: string) => string;
|
|
28
29
|
brandHref?: string;
|
|
30
|
+
/** @deprecated Owned services must use service; retained for compatibility. */
|
|
29
31
|
brandSlot?: ReactNode;
|
|
30
|
-
/**
|
|
32
|
+
/** @deprecated Owned services must use service; retained for compatibility. Ignored with brandSlot. */
|
|
31
33
|
brandSuffix?: string;
|
|
32
|
-
/**
|
|
34
|
+
/** @deprecated Owned services must use service with no indicator; retained for compatibility. */
|
|
33
35
|
statusSlot?: ReactNode;
|
|
34
36
|
/** Product menu data, after catalog/blog and before flat subNav links. */
|
|
35
37
|
appNavigation?: NavigationItem[];
|
|
@@ -50,21 +52,34 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
|
|
|
50
52
|
};
|
|
51
53
|
showProjects?: boolean;
|
|
52
54
|
showBlog?: boolean;
|
|
55
|
+
/** @deprecated Owned services must use service and appNavigation; retained for compatibility. */
|
|
53
56
|
subNav?: Array<{
|
|
54
57
|
label: string;
|
|
55
58
|
href: string;
|
|
56
59
|
}>;
|
|
57
60
|
currentProjectKey?: string;
|
|
58
61
|
currentProjectHref?: string;
|
|
59
|
-
/**
|
|
62
|
+
/** @deprecated Owned services must use service and authSlot; retained for compatibility. */
|
|
60
63
|
toolbarSlot?: ReactNode;
|
|
61
|
-
/**
|
|
64
|
+
/** @deprecated Owned services must use service and Link; retained for compatibility. */
|
|
62
65
|
brandLinkComponent?: NavigationLinkComponent;
|
|
63
66
|
}
|
|
67
|
+
/** Canonical owned-service identifiers; their spelling is the visible brand suffix. */
|
|
68
|
+
declare const naeilServices: readonly ["abstorm", "home", "estimate", "jev"];
|
|
69
|
+
type NaeilService = typeof naeilServices[number];
|
|
70
|
+
declare const serviceCompatibilityProps: readonly ["brandSuffix", "statusSlot", "brandSlot", "toolbarSlot", "subNav", "brandLinkComponent", "projects", "projectsExternal", "showProjects", "showBlog", "translations", "className", "containerClassName", "style", "brandLinkProps", "mobileFooter", "omitEmptyNavigation"];
|
|
71
|
+
type ServiceCompatibilityProp = typeof serviceCompatibilityProps[number];
|
|
72
|
+
/** Strict owned-service props; the legacy interface remains independently extensible. */
|
|
73
|
+
type NaeilServiceHeaderProps = Omit<NaeilHeaderProps, ServiceCompatibilityProp | "service"> & {
|
|
74
|
+
service: NaeilService;
|
|
75
|
+
} & {
|
|
76
|
+
[Prop in ServiceCompatibilityProp]?: never;
|
|
77
|
+
};
|
|
64
78
|
|
|
65
79
|
declare function NaeilHeaderAccountControl(props: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
|
|
66
80
|
|
|
67
|
-
declare function NaeilHeader(props:
|
|
81
|
+
declare function NaeilHeader(props: NaeilServiceHeaderProps): JSX.Element;
|
|
82
|
+
declare function NaeilHeader(props: NaeilHeaderProps): JSX.Element;
|
|
68
83
|
declare function NaeilHeaderThemeControl(props: {
|
|
69
84
|
locale: NaeilHeaderLocale;
|
|
70
85
|
}): react_jsx_runtime.JSX.Element;
|
|
@@ -73,4 +88,4 @@ declare function NaeilHeaderLocaleControl(props: {
|
|
|
73
88
|
onLocaleChange: (locale: NaeilHeaderLocale) => void;
|
|
74
89
|
}): react_jsx_runtime.JSX.Element;
|
|
75
90
|
|
|
76
|
-
export { NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
|
|
91
|
+
export { NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl, type NaeilService, type NaeilServiceHeaderProps, naeilServices };
|
|
@@ -4,14 +4,16 @@ import {
|
|
|
4
4
|
NaeilHeader,
|
|
5
5
|
NaeilHeaderAccountControl,
|
|
6
6
|
NaeilHeaderLocaleControl,
|
|
7
|
-
NaeilHeaderThemeControl
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import "../chunk-
|
|
7
|
+
NaeilHeaderThemeControl,
|
|
8
|
+
naeilServices
|
|
9
|
+
} from "../chunk-ESTQITQO.js";
|
|
10
|
+
import "../chunk-L25A4OKY.js";
|
|
11
|
+
import "../chunk-Y5LW3ADW.js";
|
|
11
12
|
import "../chunk-JBTDRVZ7.js";
|
|
12
13
|
export {
|
|
13
14
|
NaeilHeader,
|
|
14
15
|
NaeilHeaderAccountControl,
|
|
15
16
|
NaeilHeaderLocaleControl,
|
|
16
|
-
NaeilHeaderThemeControl
|
|
17
|
+
NaeilHeaderThemeControl,
|
|
18
|
+
naeilServices
|
|
17
19
|
};
|
|
@@ -4,8 +4,8 @@ import { Avatar as Avatar$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1,
|
|
|
4
4
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
import { ToasterProps } from 'sonner';
|
|
7
|
-
export { e as Navigation, f as NavigationGroup, c as NavigationItem, N as NavigationLink, b as NavigationLinkComponent, d as NavigationLinkProps, a as NavigationProps } from '../../navigation-
|
|
8
|
-
export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-
|
|
7
|
+
export { e as Navigation, f as NavigationGroup, c as NavigationItem, N as NavigationLink, b as NavigationLinkComponent, d as NavigationLinkProps, a as NavigationProps } from '../../navigation-CXZapKac.js';
|
|
8
|
+
export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-C4jgkGDU.js';
|
|
9
9
|
|
|
10
10
|
declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof Avatar$1.Root> & {
|
|
11
11
|
size?: "default" | "sm" | "lg";
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
SelectValue,
|
|
34
34
|
badgeVariants,
|
|
35
35
|
buttonVariants
|
|
36
|
-
} from "../../chunk-
|
|
36
|
+
} from "../../chunk-Y5LW3ADW.js";
|
|
37
37
|
import {
|
|
38
38
|
__objRest,
|
|
39
39
|
__spreadProps,
|
|
@@ -189,7 +189,7 @@ function CardTitle(_a) {
|
|
|
189
189
|
"div",
|
|
190
190
|
__spreadValues({
|
|
191
191
|
"data-slot": "card-title",
|
|
192
|
-
className: cn("
|
|
192
|
+
className: cn("text-base font-semibold", className)
|
|
193
193
|
}, props)
|
|
194
194
|
);
|
|
195
195
|
}
|
|
@@ -293,7 +293,7 @@ function DialogContent(_a) {
|
|
|
293
293
|
__spreadProps(__spreadValues({
|
|
294
294
|
"data-slot": "dialog-content",
|
|
295
295
|
className: cn(
|
|
296
|
-
"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",
|
|
296
|
+
"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",
|
|
297
297
|
className
|
|
298
298
|
)
|
|
299
299
|
}, props), {
|
|
@@ -363,7 +363,7 @@ function DialogTitle(_a) {
|
|
|
363
363
|
DialogPrimitive.Title,
|
|
364
364
|
__spreadValues({
|
|
365
365
|
"data-slot": "dialog-title",
|
|
366
|
-
className: cn("text-xl
|
|
366
|
+
className: cn("text-xl font-semibold", className)
|
|
367
367
|
}, props)
|
|
368
368
|
);
|
|
369
369
|
}
|
|
@@ -547,11 +547,11 @@ import { Toaster as Sonner } from "sonner";
|
|
|
547
547
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
548
548
|
var Toaster = (_a) => {
|
|
549
549
|
var props = __objRest(_a, []);
|
|
550
|
-
const { theme = "system" } = useTheme();
|
|
550
|
+
const { theme = "system", forcedTheme } = useTheme();
|
|
551
551
|
return /* @__PURE__ */ jsx6(
|
|
552
552
|
Sonner,
|
|
553
553
|
__spreadValues({
|
|
554
|
-
theme,
|
|
554
|
+
theme: forcedTheme != null ? forcedTheme : theme,
|
|
555
555
|
className: "toaster group font-sans",
|
|
556
556
|
position: "bottom-right",
|
|
557
557
|
duration: 4e3,
|
package/dist/lib/ui-release.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const uiRelease: Readonly<{version: "0.
|
|
1
|
+
export declare const uiRelease: Readonly<{version: "0.13.1"; contractVersion: "1"}>;
|
package/dist/lib/ui-release.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const uiRelease = Object.freeze({"version":"0.
|
|
1
|
+
export const uiRelease = Object.freeze({"version":"0.13.1","contractVersion":"1"});
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { ReactNode, JSX } from 'react';
|
|
4
4
|
|
|
5
5
|
type NavigationLinkProps = React.ComponentPropsWithoutRef<"a"> & {
|
|
6
6
|
href: string;
|
|
@@ -26,6 +26,8 @@ interface NavigationGroup {
|
|
|
26
26
|
}
|
|
27
27
|
type NavigationItem = NavigationLink | NavigationGroup;
|
|
28
28
|
interface NavigationProps extends Omit<React.ComponentPropsWithoutRef<"header">, "children" | "onSelect"> {
|
|
29
|
+
/** Omit empty landmarks and dismiss toolbar-only sheets on desktop crossing. */
|
|
30
|
+
omitEmptyNavigation?: boolean;
|
|
29
31
|
brand: React.ReactNode;
|
|
30
32
|
items: NavigationItem[];
|
|
31
33
|
/** Translated landmark/dialog/close labels are supplied by the application. */
|
|
@@ -71,14 +73,16 @@ interface NaeilHeaderAccountControlProps {
|
|
|
71
73
|
declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
|
|
72
74
|
|
|
73
75
|
interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
|
|
76
|
+
service?: undefined;
|
|
74
77
|
locale: NaeilHeaderLocale;
|
|
75
78
|
/** Resolve canonical unlocalized paths. Defaults to the official localized site. */
|
|
76
79
|
resolveHref?: (path: string) => string;
|
|
77
80
|
brandHref?: string;
|
|
81
|
+
/** @deprecated Owned services must use service; retained for compatibility. */
|
|
78
82
|
brandSlot?: ReactNode;
|
|
79
|
-
/**
|
|
83
|
+
/** @deprecated Owned services must use service; retained for compatibility. Ignored with brandSlot. */
|
|
80
84
|
brandSuffix?: string;
|
|
81
|
-
/**
|
|
85
|
+
/** @deprecated Owned services must use service with no indicator; retained for compatibility. */
|
|
82
86
|
statusSlot?: ReactNode;
|
|
83
87
|
/** Product menu data, after catalog/blog and before flat subNav links. */
|
|
84
88
|
appNavigation?: NavigationItem[];
|
|
@@ -99,17 +103,32 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
|
|
|
99
103
|
};
|
|
100
104
|
showProjects?: boolean;
|
|
101
105
|
showBlog?: boolean;
|
|
106
|
+
/** @deprecated Owned services must use service and appNavigation; retained for compatibility. */
|
|
102
107
|
subNav?: Array<{
|
|
103
108
|
label: string;
|
|
104
109
|
href: string;
|
|
105
110
|
}>;
|
|
106
111
|
currentProjectKey?: string;
|
|
107
112
|
currentProjectHref?: string;
|
|
108
|
-
/**
|
|
113
|
+
/** @deprecated Owned services must use service and authSlot; retained for compatibility. */
|
|
109
114
|
toolbarSlot?: ReactNode;
|
|
110
|
-
/**
|
|
115
|
+
/** @deprecated Owned services must use service and Link; retained for compatibility. */
|
|
111
116
|
brandLinkComponent?: NavigationLinkComponent;
|
|
112
117
|
}
|
|
118
|
+
/** Canonical owned-service identifiers; their spelling is the visible brand suffix. */
|
|
119
|
+
declare const naeilServices: readonly ["abstorm", "home", "estimate", "jev"];
|
|
120
|
+
type NaeilService = typeof naeilServices[number];
|
|
121
|
+
declare const serviceCompatibilityProps: readonly ["brandSuffix", "statusSlot", "brandSlot", "toolbarSlot", "subNav", "brandLinkComponent", "projects", "projectsExternal", "showProjects", "showBlog", "translations", "className", "containerClassName", "style", "brandLinkProps", "mobileFooter", "omitEmptyNavigation"];
|
|
122
|
+
type ServiceCompatibilityProp = typeof serviceCompatibilityProps[number];
|
|
123
|
+
/** Strict owned-service props; the legacy interface remains independently extensible. */
|
|
124
|
+
type NaeilServiceHeaderProps = Omit<NaeilHeaderProps, ServiceCompatibilityProp | "service"> & {
|
|
125
|
+
service: NaeilService;
|
|
126
|
+
} & {
|
|
127
|
+
[Prop in ServiceCompatibilityProp]?: never;
|
|
128
|
+
};
|
|
129
|
+
/** Opt into the owned-service contract without changing the legacy composition. */
|
|
130
|
+
declare function NaeilHeader(props: NaeilServiceHeaderProps): JSX.Element;
|
|
131
|
+
declare function NaeilHeader(props: NaeilHeaderProps): JSX.Element;
|
|
113
132
|
/** The actual header theme control; reads only the consumer's theme provider. */
|
|
114
133
|
declare function NaeilHeaderThemeControl({ locale }: {
|
|
115
134
|
locale: NaeilHeaderLocale;
|
|
@@ -119,8 +138,6 @@ declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
|
|
|
119
138
|
locale: NaeilHeaderLocale;
|
|
120
139
|
onLocaleChange: (locale: NaeilHeaderLocale) => void;
|
|
121
140
|
}): react_jsx_runtime.JSX.Element;
|
|
122
|
-
/** One complete, opt-in branded composition shared by naeil.dev and applications. */
|
|
123
|
-
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;
|
|
124
141
|
|
|
125
142
|
interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
|
|
126
143
|
brand?: React.ReactNode;
|
|
@@ -147,4 +164,4 @@ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description"
|
|
|
147
164
|
/** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
|
|
148
165
|
declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
|
|
149
166
|
|
|
150
|
-
export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps, NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, type NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
|
|
167
|
+
export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps, NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, type NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl, type NaeilService, type NaeilServiceHeaderProps, naeilServices };
|
|
@@ -1230,16 +1230,16 @@ import { cva as cva2 } from "class-variance-authority";
|
|
|
1230
1230
|
import { Slot as Slot2 } from "radix-ui";
|
|
1231
1231
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1232
1232
|
var buttonVariants = cva2(
|
|
1233
|
-
"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",
|
|
1233
|
+
"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",
|
|
1234
1234
|
{
|
|
1235
1235
|
variants: {
|
|
1236
1236
|
variant: {
|
|
1237
|
-
default: "bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
1238
|
-
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 ",
|
|
1239
|
-
outline: "border border-border-strong bg-background hover:bg-surface-subtle",
|
|
1240
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
1241
|
-
ghost: "hover:bg-surface-subtle",
|
|
1242
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1237
|
+
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)]",
|
|
1238
|
+
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)]",
|
|
1239
|
+
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",
|
|
1240
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
|
|
1241
|
+
ghost: "hover:bg-surface-subtle aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground",
|
|
1242
|
+
link: "text-primary underline-offset-4 hover:underline aria-pressed:bg-surface-selected aria-pressed:text-foreground aria-pressed:inset-ring-foreground"
|
|
1243
1243
|
},
|
|
1244
1244
|
size: {
|
|
1245
1245
|
default: "px-4 has-[>svg]:px-3",
|
|
@@ -1615,6 +1615,7 @@ function Navigation(_a) {
|
|
|
1615
1615
|
toolbar,
|
|
1616
1616
|
mobileToolbar,
|
|
1617
1617
|
mobileFooter,
|
|
1618
|
+
omitEmptyNavigation = false,
|
|
1618
1619
|
mobileOpen: controlledOpen,
|
|
1619
1620
|
onMobileOpenChange,
|
|
1620
1621
|
containerClassName,
|
|
@@ -1629,6 +1630,7 @@ function Navigation(_a) {
|
|
|
1629
1630
|
"toolbar",
|
|
1630
1631
|
"mobileToolbar",
|
|
1631
1632
|
"mobileFooter",
|
|
1633
|
+
"omitEmptyNavigation",
|
|
1632
1634
|
"mobileOpen",
|
|
1633
1635
|
"onMobileOpenChange",
|
|
1634
1636
|
"containerClassName",
|
|
@@ -1699,7 +1701,8 @@ function Navigation(_a) {
|
|
|
1699
1701
|
setOpenGroup(null);
|
|
1700
1702
|
}, [currentHref, setMobileOpen]);
|
|
1701
1703
|
React.useEffect(() => {
|
|
1702
|
-
|
|
1704
|
+
var _a2, _b2;
|
|
1705
|
+
const element = omitEmptyNavigation && !items.length ? (_b2 = (_a2 = desktop.current) == null ? void 0 : _a2.parentElement) == null ? void 0 : _b2.querySelector(".ui-navigation-toolbar") : desktop.current;
|
|
1703
1706
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
1704
1707
|
const observer = new ResizeObserver(() => {
|
|
1705
1708
|
if (element.getBoundingClientRect().width > 0) setMobileOpen(false);
|
|
@@ -1707,7 +1710,8 @@ function Navigation(_a) {
|
|
|
1707
1710
|
});
|
|
1708
1711
|
observer.observe(element);
|
|
1709
1712
|
return () => observer.disconnect();
|
|
1710
|
-
}, [setMobileOpen]);
|
|
1713
|
+
}, [setMobileOpen, omitEmptyNavigation, items.length]);
|
|
1714
|
+
const DesktopElement = omitEmptyNavigation && !items.length ? "div" : "nav";
|
|
1711
1715
|
const active = (item) => {
|
|
1712
1716
|
var _a2;
|
|
1713
1717
|
return (_a2 = item.active) != null ? _a2 : !item.external && item.href === currentHref;
|
|
@@ -1756,10 +1760,12 @@ function Navigation(_a) {
|
|
|
1756
1760
|
children: /* @__PURE__ */ jsx6("div", { className: cn("ui-navigation-frame", containerClassName), children: /* @__PURE__ */ jsxs4("div", { className: "ui-navigation-row", children: [
|
|
1757
1761
|
/* @__PURE__ */ jsx6("div", { className: "ui-navigation-brand", children: brand }),
|
|
1758
1762
|
/* @__PURE__ */ jsx6(
|
|
1759
|
-
|
|
1763
|
+
DesktopElement,
|
|
1760
1764
|
{
|
|
1761
|
-
ref:
|
|
1762
|
-
|
|
1765
|
+
ref: (element) => {
|
|
1766
|
+
desktop.current = element;
|
|
1767
|
+
},
|
|
1768
|
+
"aria-label": omitEmptyNavigation && !items.length ? void 0 : labels.navigation,
|
|
1763
1769
|
className: "ui-navigation-desktop",
|
|
1764
1770
|
children: items.map(
|
|
1765
1771
|
(item) => "items" in item ? /* @__PURE__ */ jsx6(
|
|
@@ -1811,7 +1817,7 @@ function Navigation(_a) {
|
|
|
1811
1817
|
className: "ui-navigation-sheet ui-popup",
|
|
1812
1818
|
"aria-describedby": void 0,
|
|
1813
1819
|
onCloseAutoFocus: (event) => {
|
|
1814
|
-
var _a2, _b2;
|
|
1820
|
+
var _a2, _b2, _c, _d;
|
|
1815
1821
|
if (controlledOpen !== void 0 && (!mounted.current || state.current.open)) {
|
|
1816
1822
|
event.preventDefault();
|
|
1817
1823
|
return;
|
|
@@ -1825,7 +1831,10 @@ function Navigation(_a) {
|
|
|
1825
1831
|
}
|
|
1826
1832
|
if (trigger.current && trigger.current.getBoundingClientRect().width === 0) {
|
|
1827
1833
|
event.preventDefault();
|
|
1828
|
-
|
|
1834
|
+
const target = (_a2 = desktop.current) == null ? void 0 : _a2.querySelector("button, a");
|
|
1835
|
+
const toolbar2 = omitEmptyNavigation && !items.length ? (_c = (_b2 = desktop.current) == null ? void 0 : _b2.parentElement) == null ? void 0 : _c.querySelector(".ui-navigation-toolbar") : void 0;
|
|
1836
|
+
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;
|
|
1837
|
+
(_d = target != null ? target : toolbarTarget) == null ? void 0 : _d.focus();
|
|
1829
1838
|
}
|
|
1830
1839
|
},
|
|
1831
1840
|
children: [
|
|
@@ -1840,7 +1849,7 @@ function Navigation(_a) {
|
|
|
1840
1849
|
}
|
|
1841
1850
|
)
|
|
1842
1851
|
] }),
|
|
1843
|
-
/* @__PURE__ */ jsx6(
|
|
1852
|
+
(!omitEmptyNavigation || items.length > 0) && /* @__PURE__ */ jsx6(
|
|
1844
1853
|
"nav",
|
|
1845
1854
|
{
|
|
1846
1855
|
"aria-label": labels.navigation,
|
|
@@ -1886,7 +1895,7 @@ function Navigation(_a) {
|
|
|
1886
1895
|
}
|
|
1887
1896
|
|
|
1888
1897
|
// src/lib/ui-release.ts
|
|
1889
|
-
var uiRelease = { version: "0.
|
|
1898
|
+
var uiRelease = { version: "0.13.1", contractVersion: "1" };
|
|
1890
1899
|
|
|
1891
1900
|
// src/components/naeil-header-data.ts
|
|
1892
1901
|
var headerLocales = ["en", "ko", "ja"];
|
|
@@ -2078,6 +2087,58 @@ function NaeilHeaderAccountControl({ locale, account, Link = NativeLink3 }) {
|
|
|
2078
2087
|
|
|
2079
2088
|
// src/components/naeil-header-core.tsx
|
|
2080
2089
|
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2090
|
+
var naeilServices = Object.freeze(["abstorm", "home", "estimate", "jev"]);
|
|
2091
|
+
var serviceCompatibilityProps = [
|
|
2092
|
+
"brandSuffix",
|
|
2093
|
+
"statusSlot",
|
|
2094
|
+
"brandSlot",
|
|
2095
|
+
"toolbarSlot",
|
|
2096
|
+
"subNav",
|
|
2097
|
+
"brandLinkComponent",
|
|
2098
|
+
"projects",
|
|
2099
|
+
"projectsExternal",
|
|
2100
|
+
"showProjects",
|
|
2101
|
+
"showBlog",
|
|
2102
|
+
"translations",
|
|
2103
|
+
"className",
|
|
2104
|
+
"containerClassName",
|
|
2105
|
+
"style",
|
|
2106
|
+
"brandLinkProps",
|
|
2107
|
+
"mobileFooter",
|
|
2108
|
+
"omitEmptyNavigation"
|
|
2109
|
+
];
|
|
2110
|
+
var warnedServiceProps = /* @__PURE__ */ new Set();
|
|
2111
|
+
function isDevelopment() {
|
|
2112
|
+
try {
|
|
2113
|
+
return process.env.NODE_ENV === "development";
|
|
2114
|
+
} catch (e) {
|
|
2115
|
+
return false;
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
function warnServiceProp(name, message) {
|
|
2119
|
+
if (!isDevelopment() || warnedServiceProps.has(name)) return;
|
|
2120
|
+
warnedServiceProps.add(name);
|
|
2121
|
+
console.warn(message);
|
|
2122
|
+
}
|
|
2123
|
+
function isNaeilService(value) {
|
|
2124
|
+
return naeilServices.includes(value);
|
|
2125
|
+
}
|
|
2126
|
+
function NaeilHeader(input) {
|
|
2127
|
+
if (input.service === void 0) return /* @__PURE__ */ jsx9(HeaderComposition, __spreadValues({}, input));
|
|
2128
|
+
if (!isNaeilService(input.service)) {
|
|
2129
|
+
warnServiceProp("service", "NaeilHeader: invalid service; rendering the legacy profile.");
|
|
2130
|
+
const legacy = __spreadProps(__spreadValues({}, input), { service: void 0 });
|
|
2131
|
+
delete legacy.service;
|
|
2132
|
+
return /* @__PURE__ */ jsx9(HeaderComposition, __spreadValues({}, legacy));
|
|
2133
|
+
}
|
|
2134
|
+
const props = __spreadValues({}, input);
|
|
2135
|
+
for (const name of Object.keys(props)) {
|
|
2136
|
+
if (!serviceCompatibilityProps.includes(name) && name !== "data-slot" && name !== "data-global-header" && !name.startsWith("data-naeil-")) continue;
|
|
2137
|
+
delete props[name];
|
|
2138
|
+
warnServiceProp(name, `NaeilHeader: service profile ignores ${name}; use the shared service composition.`);
|
|
2139
|
+
}
|
|
2140
|
+
return /* @__PURE__ */ jsx9(HeaderComposition, __spreadProps(__spreadValues({}, props), { service: input.service }));
|
|
2141
|
+
}
|
|
2081
2142
|
var subscribe = () => () => {
|
|
2082
2143
|
};
|
|
2083
2144
|
function NaeilHeaderThemeControl({ locale }) {
|
|
@@ -2114,8 +2175,9 @@ function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
|
|
|
2114
2175
|
] });
|
|
2115
2176
|
}
|
|
2116
2177
|
var NativeLink4 = (props) => /* @__PURE__ */ jsx9("a", __spreadValues({}, props));
|
|
2117
|
-
function
|
|
2178
|
+
function HeaderComposition(_a) {
|
|
2118
2179
|
var _b = _a, {
|
|
2180
|
+
service,
|
|
2119
2181
|
locale,
|
|
2120
2182
|
resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
|
|
2121
2183
|
brandHref,
|
|
@@ -2143,6 +2205,7 @@ function NaeilHeader(_a) {
|
|
|
2143
2205
|
className,
|
|
2144
2206
|
containerClassName
|
|
2145
2207
|
} = _b, props = __objRest(_b, [
|
|
2208
|
+
"service",
|
|
2146
2209
|
"locale",
|
|
2147
2210
|
"resolveHref",
|
|
2148
2211
|
"brandHref",
|
|
@@ -2171,6 +2234,11 @@ function NaeilHeader(_a) {
|
|
|
2171
2234
|
"containerClassName"
|
|
2172
2235
|
]);
|
|
2173
2236
|
var _b2, _c;
|
|
2237
|
+
if (service) {
|
|
2238
|
+
brandSuffix = service;
|
|
2239
|
+
showProjects = false;
|
|
2240
|
+
showBlog = false;
|
|
2241
|
+
}
|
|
2174
2242
|
const content = useNaeilMessages(locale).header;
|
|
2175
2243
|
const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
|
|
2176
2244
|
var _a3, _b3, _c2;
|
|
@@ -2189,7 +2257,7 @@ function NaeilHeader(_a) {
|
|
|
2189
2257
|
badge: project.status === "coming" ? /* @__PURE__ */ jsx9(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
|
|
2190
2258
|
};
|
|
2191
2259
|
});
|
|
2192
|
-
const brandDestination = brandHref != null ? brandHref : resolveHref("/");
|
|
2260
|
+
const brandDestination = brandHref != null ? brandHref : service ? "/" : resolveHref("/");
|
|
2193
2261
|
const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
|
|
2194
2262
|
const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
|
|
2195
2263
|
const toolbar = /* @__PURE__ */ jsx9(
|
|
@@ -2215,11 +2283,11 @@ function NaeilHeader(_a) {
|
|
|
2215
2283
|
__spreadProps(__spreadValues({
|
|
2216
2284
|
href: brandDestination,
|
|
2217
2285
|
"data-app-brand": true,
|
|
2218
|
-
"aria-label": brandSlot == null ? ".naeil" : void 0
|
|
2286
|
+
"aria-label": service ? `.naeil ${service}` : brandSlot == null ? ".naeil" : void 0
|
|
2219
2287
|
}, brandProps), {
|
|
2220
2288
|
onClick: (event) => {
|
|
2221
2289
|
onBrandClick == null ? void 0 : onBrandClick(event);
|
|
2222
|
-
onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
|
|
2290
|
+
onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: service ? `.naeil ${service}` : ".naeil" });
|
|
2223
2291
|
},
|
|
2224
2292
|
children: brandSlot != null ? brandSlot : brandSuffix ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
2225
2293
|
logo,
|
|
@@ -2229,7 +2297,7 @@ function NaeilHeader(_a) {
|
|
|
2229
2297
|
);
|
|
2230
2298
|
return /* @__PURE__ */ jsx9(
|
|
2231
2299
|
Navigation,
|
|
2232
|
-
__spreadProps(__spreadValues({}, props), {
|
|
2300
|
+
__spreadProps(__spreadValues(__spreadValues({}, props), service ? { "data-slot": "navigation", omitEmptyNavigation: true } : {}), {
|
|
2233
2301
|
"data-global-header": true,
|
|
2234
2302
|
"data-naeil-header": true,
|
|
2235
2303
|
"data-naeil-chrome": "",
|
|
@@ -2381,5 +2449,6 @@ export {
|
|
|
2381
2449
|
NaeilHeader,
|
|
2382
2450
|
NaeilHeaderAccountControl,
|
|
2383
2451
|
NaeilHeaderLocaleControl,
|
|
2384
|
-
NaeilHeaderThemeControl
|
|
2452
|
+
NaeilHeaderThemeControl,
|
|
2453
|
+
naeilServices
|
|
2385
2454
|
};
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
// src/naeil-locale/routing.ts
|
|
7
7
|
var naeilLocales = ["en", "ko", "ja"];
|
|
8
8
|
var defaultLocale = "en";
|
|
9
|
+
function escapeRegExp(value) {
|
|
10
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11
|
+
}
|
|
12
|
+
var localePrefix = new RegExp(`^/(?:${naeilLocales.map(escapeRegExp).join("|")})(?:/|$)`);
|
|
9
13
|
var naeilRouting = {
|
|
10
14
|
locales: naeilLocales,
|
|
11
15
|
defaultLocale,
|
|
@@ -28,7 +32,7 @@ var origins = {
|
|
|
28
32
|
estimate: "https://abestimate.naeil.dev"
|
|
29
33
|
};
|
|
30
34
|
var protocolPrefixes = ["/api", "/auth", "/_next", "/_vercel", "/.well-known", "/health", "/invite", "/return", "/webhook", "/images", "/fonts"];
|
|
31
|
-
var protocolFiles = ["/favicon.ico", "/icon.svg", "/apple-icon.png", "/robots.txt", "/sitemap.xml"];
|
|
35
|
+
var protocolFiles = ["/favicon.ico", "/favicon.svg", "/icon.svg", "/apple-icon.png", "/robots.txt", "/sitemap.xml"];
|
|
32
36
|
function defineLocaleService(service) {
|
|
33
37
|
var _a, _b, _c, _d;
|
|
34
38
|
if (origins[service.id] !== service.origin) throw new Error("Service origin must match the exact owned origin");
|
|
@@ -36,7 +40,7 @@ function defineLocaleService(service) {
|
|
|
36
40
|
if (!paths.length || new Set(paths).size !== paths.length) throw new Error("Route inventory is empty or duplicated");
|
|
37
41
|
for (const path of paths) {
|
|
38
42
|
if (!/^\/(?:[A-Za-z0-9._~-]+|\[[A-Za-z][A-Za-z0-9_]*\])(?:\/(?:[A-Za-z0-9._~-]+|\[[A-Za-z][A-Za-z0-9_]*\]))*$/.test(path) && path !== "/") throw new Error(`Invalid registered route: ${path}`);
|
|
39
|
-
if (
|
|
43
|
+
if (localePrefix.test(path) || isProtocolPath(path, service) && !((_a = service.uiProtocolExceptions) == null ? void 0 : _a.includes(path)) || path.split("/").some((segment) => segment === "." || segment === "..")) throw new Error(`Locale/protocol path cannot be a UI route: ${path}`);
|
|
40
44
|
}
|
|
41
45
|
for (const exception of (_b = service.uiProtocolExceptions) != null ? _b : []) if (exception.includes("[") || !paths.includes(exception)) throw new Error("Protocol UI exceptions must be exact registered routes");
|
|
42
46
|
return Object.freeze(__spreadProps(__spreadValues({}, service), { routes: Object.freeze(service.routes.map((route) => typeof route === "string" ? route : Object.freeze(__spreadValues({}, route)))), protocolPrefixes: Object.freeze([...(_c = service.protocolPrefixes) != null ? _c : []]), uiProtocolExceptions: Object.freeze([...(_d = service.uiProtocolExceptions) != null ? _d : []]) }));
|
|
@@ -72,7 +76,7 @@ function invalid(reason, status = 404, locale) {
|
|
|
72
76
|
return __spreadValues({ kind: "invalid", status, reason }, locale ? { locale } : {});
|
|
73
77
|
}
|
|
74
78
|
function splitInput(input, origin) {
|
|
75
|
-
if (!input || /[\u0000-\u0020\u007f
|
|
79
|
+
if (!input || /[\u0000-\u0020\u007f]/.test(input)) return;
|
|
76
80
|
let path = input;
|
|
77
81
|
if (!path.startsWith("/")) {
|
|
78
82
|
if (!path.startsWith(origin + "/") && path !== origin) return;
|
|
@@ -85,12 +89,14 @@ function splitInput(input, origin) {
|
|
|
85
89
|
const queryAt = withoutHash.indexOf("?");
|
|
86
90
|
return { pathname: queryAt < 0 ? withoutHash : withoutHash.slice(0, queryAt), search: queryAt < 0 ? "" : withoutHash.slice(queryAt), hash };
|
|
87
91
|
}
|
|
88
|
-
function safePath(path) {
|
|
92
|
+
function safePath(path, service) {
|
|
93
|
+
var _a;
|
|
89
94
|
if (!path.startsWith("/") || path.includes("//")) return false;
|
|
95
|
+
const reserved = /* @__PURE__ */ new Set([...naeilLocales, ...[...protocolPrefixes, ...(_a = service.protocolPrefixes) != null ? _a : []].flatMap((prefix) => prefix.split("/").filter(Boolean))]);
|
|
90
96
|
return path.split("/").every((segment) => {
|
|
91
97
|
try {
|
|
92
98
|
const decoded = decodeURIComponent(segment);
|
|
93
|
-
return !/[\u0000-\u001f\u007f/\\%?#]/.test(decoded) && decoded !== "." && decoded !== ".." && (
|
|
99
|
+
return !/[\u0000-\u001f\u007f/\\%?#]/.test(decoded) && decoded !== "." && decoded !== ".." && (!reserved.has(decoded) || decoded === segment);
|
|
94
100
|
} catch (e) {
|
|
95
101
|
return false;
|
|
96
102
|
}
|
|
@@ -113,7 +119,7 @@ function resolveLocaleUrl(inputService, input) {
|
|
|
113
119
|
var _a, _b;
|
|
114
120
|
const service = getLocaleService(inputService);
|
|
115
121
|
const parts = splitInput(input, service.origin);
|
|
116
|
-
if (!parts || !safePath(parts.pathname)) return invalid("Malformed or encoded path");
|
|
122
|
+
if (!parts || !safePath(parts.pathname, service)) return invalid("Malformed or encoded path");
|
|
117
123
|
const rawPathname = parts.pathname;
|
|
118
124
|
const pathname = rawPathname !== "/" && rawPathname.endsWith("/") ? rawPathname.slice(0, -1) : rawPathname;
|
|
119
125
|
if (isProtocolPath(pathname, service) && !((_a = service.uiProtocolExceptions) == null ? void 0 : _a.includes(pathname))) return { kind: "protocol", pathname };
|
|
@@ -121,7 +127,7 @@ function resolveLocaleUrl(inputService, input) {
|
|
|
121
127
|
const explicit = isNaeilLocale(segments[1]);
|
|
122
128
|
const pathLocale = explicit ? segments[1] : void 0;
|
|
123
129
|
const logicalPath = explicit ? "/" + segments.slice(2).join("/") : pathname;
|
|
124
|
-
if (
|
|
130
|
+
if (localePrefix.test(logicalPath) || isProtocolPath(logicalPath, service) && !((_b = service.uiProtocolExceptions) == null ? void 0 : _b.includes(logicalPath))) return invalid("Nested locale or localized protocol path", 404, pathLocale);
|
|
125
131
|
const route = matchRoute(service, logicalPath);
|
|
126
132
|
if (!route) return invalid("Unregistered UI route", 404, pathLocale);
|
|
127
133
|
const legacy = service.id !== "main";
|
|
@@ -137,7 +143,7 @@ function localePath(inputService, unlocalizedRoute, locale) {
|
|
|
137
143
|
assertLocale(locale);
|
|
138
144
|
const service = getLocaleService(inputService);
|
|
139
145
|
const parts = splitInput(unlocalizedRoute, service.origin);
|
|
140
|
-
if (!parts ||
|
|
146
|
+
if (!parts || localePrefix.test(parts.pathname)) throw new Error("localePath requires an unlocalized route");
|
|
141
147
|
const result = resolveLocaleUrl(service, parts.pathname);
|
|
142
148
|
if (result.kind !== "ui") throw new Error("Unregistered UI destination");
|
|
143
149
|
return prefixPath(result.logicalPath, locale) + (service.id === "main" ? parts.search : stripLegacyLang(parts.search)) + parts.hash;
|