@uipath/apollo-vertex 1.3.0 → 2.0.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.
- package/README.md +4 -9
- package/dist/entries/index.d.ts +0 -1
- package/dist/entries/index.js +1 -2
- package/dist/entries/proteus.d.ts +1 -0
- package/dist/entries/proteus.js +2 -0
- package/dist/lib/i18n.d.ts +8 -0
- package/dist/locales/en.json +4 -0
- package/dist/registry/shell/shell-company.js +2 -1
- package/dist/registry/shell/shell-locale-provider.d.ts +2 -1
- package/dist/registry/shell/shell-locale-provider.js +12 -8
- package/dist/registry/shell/shell-minimal-nav-item.d.ts +4 -3
- package/dist/registry/shell/shell-minimal-nav-item.js +3 -7
- package/dist/registry/shell/shell-nav-active.d.ts +12 -0
- package/dist/registry/shell/shell-nav-active.js +24 -0
- package/dist/registry/shell/shell-nav-label.d.ts +7 -0
- package/dist/registry/shell/shell-nav-label.js +54 -0
- package/dist/registry/shell/shell-sidebar.js +126 -114
- package/dist/registry/shell/shell-text.d.ts +2 -2
- package/dist/registry/shell/shell-text.js +3 -2
- package/dist/registry/shell/shell-translation-key.d.ts +5 -0
- package/dist/registry/shell/shell.d.ts +6 -3
- package/dist/registry/shell/shell.js +18 -13
- package/dist/registry/solution-tests/use-solution-test-collection.d.ts +6 -1
- package/dist/registry/solution-tests/use-solution-test-collection.js +6 -3
- package/dist/registry/solution-tests/use-solution-tests.js +2 -2
- package/dist/registry/sonner/sonner.js +4 -7
- package/dist/registry/use-data-table/useEntityDataTable.d.ts +6 -1
- package/package.json +12 -8
- package/skills/setup/SKILL.md +7 -5
package/README.md
CHANGED
|
@@ -26,15 +26,10 @@ import { Button, DataTable } from "@uipath/apollo-vertex";
|
|
|
26
26
|
Everything, including the app shell, charts, feature flags, Solution Tests and AI chat, is exported
|
|
27
27
|
from the package root. Translation JSON files are available at `@uipath/apollo-vertex/locales/*`.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- `@tanstack/react-db`
|
|
34
|
-
- `@uipath/proteus-client`
|
|
35
|
-
|
|
36
|
-
They are declared only in `peerDependenciesMeta` (as optional) so that pnpm does not try to install them
|
|
37
|
-
in this workspace. The two `@uipath` packages are not on the public npm registry.
|
|
29
|
+
The Proteus feature flag adapter, `createProteusProvider`, is exported from
|
|
30
|
+
`@uipath/apollo-vertex/proteus` instead of the root. It needs `@uipath/proteus-client`, which is not on
|
|
31
|
+
the public npm registry, so it is declared only in `peerDependenciesMeta` (as optional). Install it
|
|
32
|
+
yourself if you import that subpath.
|
|
38
33
|
|
|
39
34
|
## Layout
|
|
40
35
|
|
package/dist/entries/index.d.ts
CHANGED
|
@@ -106,7 +106,6 @@ export { FeatureFlagGuard } from "../registry/feature-flag-guard/feature-flag-gu
|
|
|
106
106
|
export { ProtectedFeatureRoute } from "../registry/protected-feature-route/protected-feature-route";
|
|
107
107
|
export { useFeatureFlag } from "../registry/use-feature-flag/use-feature-flag";
|
|
108
108
|
export type { FeatureFlagProviderConfig, FeatureFlagUserContext, } from "../registry/feature-flag-provider/types";
|
|
109
|
-
export { createProteusProvider, type FlagMapping, type ProteusFeatureFlagValues, } from "../registry/feature-flag-provider/proteus-adapter";
|
|
110
109
|
export { SolutionTestsView } from "../registry/solution-tests/solution-tests-view";
|
|
111
110
|
export type { SolutionTestsViewProps } from "../registry/solution-tests/solution-tests-view";
|
|
112
111
|
export { SaveAsTestButton } from "../registry/solution-tests/save-as-test-button";
|
package/dist/entries/index.js
CHANGED
|
@@ -27,7 +27,6 @@ import { FeatureFlagContext, FeatureFlagProvider, useFeatureFlagProvider } from
|
|
|
27
27
|
import { FeatureFlagGuard } from "../registry/feature-flag-guard/feature-flag-guard.js";
|
|
28
28
|
import { ProtectedFeatureRoute } from "../registry/protected-feature-route/protected-feature-route.js";
|
|
29
29
|
import { useFeatureFlag } from "../registry/use-feature-flag/use-feature-flag.js";
|
|
30
|
-
import { createProteusProvider } from "../registry/feature-flag-provider/proteus-adapter.js";
|
|
31
30
|
import { SolutionTestsView } from "../registry/solution-tests/solution-tests-view.js";
|
|
32
31
|
import { SaveAsTestButton } from "../registry/solution-tests/save-as-test-button.js";
|
|
33
32
|
import { SolutionTestActionError } from "../registry/solution-tests/errors.js";
|
|
@@ -145,4 +144,4 @@ export * from "../registry/ai-chat/tools/data-fabric-line/index.js";
|
|
|
145
144
|
export * from "../registry/ai-chat/tools/data-fabric-multi-line/index.js";
|
|
146
145
|
export * from "../registry/ai-chat/tools/data-fabric-table/index.js";
|
|
147
146
|
export * from "../registry/ai-chat/tools/data-fabric/index.js";
|
|
148
|
-
export { AiChat, AiChatEmptyState, AiChatLoading, AiChatMarkdown, AiChatThinking, ApolloShell, AuthContext, AutopilotGradientIcon, BaselineCompare, CASE_EVALUATION_EVALUATOR_ID, CASE_EVALUATION_OUTPUT_RENDERER, CaseEvaluationDetailsSchema, CaseEvaluationOutputResult, CaseEvaluationOutputSchema, CheckboxField, EvaluationPairStatus, ExpandedAgents, ExpandedAgentsView, ExpandedRunTests, ExpandedRunTestsView, FeatureFlagContext, FeatureFlagGuard, FeatureFlagProvider, FieldError as FormFieldError, GENERIC_RENDERER, GroupMembershipGuard, IXP_EXTRACTION_EVALUATOR_ID, IXP_OUTPUT_RENDERER, IxpDetailsSchema, IxpDocStatus, IxpOutputResult, IxpOutputSchema, IxpVerdict, JSON_SIMILARITY_EVALUATOR_ID, JobRole, LLM_JUDGE_EVALUATOR_ID, LocaleProvider, MembershipDenied, NoDataMessage, ProcessOutputView, ProtectedFeatureRoute, RadioGroupField, Role, RunDetails, RunDetailsView, RunResultStatus, RunStatus, STALE_TIME_MS, STORAGE_KEYS, SUPPORTED_LOCALES, SaveAsTestButton, SelectField, ShellAuthProvider, ShellLayout, ShellLogin, ShellSidebar, ShellUserProvider, SolutionTestActionError, SolutionTestStatus, SolutionTests, SolutionTestsProvider, SolutionTestsView, SubmitButton, SummaryVerdict, SwitchField, TOKEN_QUERY_KEY, TextField, TextareaField, ThemeProvider, VerifyingMembership, VersionDeltaGlyph, addVertexTranslations, assertDateOrString, assertString, cn, configurei18n, createAgentHubConnection, createConversationalAgentConnection,
|
|
147
|
+
export { AiChat, AiChatEmptyState, AiChatLoading, AiChatMarkdown, AiChatThinking, ApolloShell, AuthContext, AutopilotGradientIcon, BaselineCompare, CASE_EVALUATION_EVALUATOR_ID, CASE_EVALUATION_OUTPUT_RENDERER, CaseEvaluationDetailsSchema, CaseEvaluationOutputResult, CaseEvaluationOutputSchema, CheckboxField, EvaluationPairStatus, ExpandedAgents, ExpandedAgentsView, ExpandedRunTests, ExpandedRunTestsView, FeatureFlagContext, FeatureFlagGuard, FeatureFlagProvider, FieldError as FormFieldError, GENERIC_RENDERER, GroupMembershipGuard, IXP_EXTRACTION_EVALUATOR_ID, IXP_OUTPUT_RENDERER, IxpDetailsSchema, IxpDocStatus, IxpOutputResult, IxpOutputSchema, IxpVerdict, JSON_SIMILARITY_EVALUATOR_ID, JobRole, LLM_JUDGE_EVALUATOR_ID, LocaleProvider, MembershipDenied, NoDataMessage, ProcessOutputView, ProtectedFeatureRoute, RadioGroupField, Role, RunDetails, RunDetailsView, RunResultStatus, RunStatus, STALE_TIME_MS, STORAGE_KEYS, SUPPORTED_LOCALES, SaveAsTestButton, SelectField, ShellAuthProvider, ShellLayout, ShellLogin, ShellSidebar, ShellUserProvider, SolutionTestActionError, SolutionTestStatus, SolutionTests, SolutionTestsProvider, SolutionTestsView, SubmitButton, SummaryVerdict, SwitchField, TOKEN_QUERY_KEY, TextField, TextareaField, ThemeProvider, VerifyingMembership, VersionDeltaGlyph, addVertexTranslations, assertDateOrString, assertString, cn, configurei18n, createAgentHubConnection, createConversationalAgentConnection, ensureValidToken, genericRenderer, getStoredIdToken, getTokenQueryKey, login, logout, makeProcessOutputRenderer, makeRenderer, resolveEvaluatorRenderer, resolveProcessOutputRenderer, resolveReturnPath, toCodedAppFilePath, useAccessToken, useAdoptJob, useAppForm, useAuth, useBaselineJobs, useCreateTest, useDataTable, useDeleteTest, useEntityColumns, useEntityDataTable, useFeatureFlag, useFeatureFlagProvider, useFieldContext, useForceStopBatch, useForceStopRun, useFormContext, useGroupId, useGroupMembers, useIsGroupMember, useIsMobile, useJobExpectedOutput, useRemoveJobBaseline, useResultAttachment, useRunResults, useRunTests, useSolutionTestBatchRuns, useSolutionTestRuns, useSolutionTests, useSolutionTestsConfig, useSolutionTestsContext, useTheme, useToggleTestActive, useTranslatedErrors, useUpdateBaseline, useUser, versionDelta, withForm };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createProteusProvider, type FlagMapping, type ProteusFeatureFlagValues, } from "../registry/feature-flag-provider/proteus-adapter";
|
package/dist/lib/i18n.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ declare const localeLoaders: {
|
|
|
6
6
|
access_denied: string;
|
|
7
7
|
access_denied_description: string;
|
|
8
8
|
actions: string;
|
|
9
|
+
active: string;
|
|
9
10
|
actual_input: string;
|
|
10
11
|
actual_output: string;
|
|
11
12
|
add_attachment: string;
|
|
@@ -27,6 +28,7 @@ declare const localeLoaders: {
|
|
|
27
28
|
analytics: string;
|
|
28
29
|
apollo_vertex: string;
|
|
29
30
|
apollo_vertex_description: string;
|
|
31
|
+
archive: string;
|
|
30
32
|
are_you_sure: string;
|
|
31
33
|
asc: string;
|
|
32
34
|
ask_ai: string;
|
|
@@ -189,6 +191,8 @@ declare const localeLoaders: {
|
|
|
189
191
|
more_pages: string;
|
|
190
192
|
multi_line_too_few_metrics: string;
|
|
191
193
|
my_template: string;
|
|
194
|
+
nav_collapse: string;
|
|
195
|
+
nav_expand: string;
|
|
192
196
|
need_help: string;
|
|
193
197
|
new_conversation: string;
|
|
194
198
|
new_conversation_confirm_description: string;
|
|
@@ -373,6 +377,7 @@ declare const localeLoaders: {
|
|
|
373
377
|
access_denied: string;
|
|
374
378
|
access_denied_description: string;
|
|
375
379
|
actions: string;
|
|
380
|
+
active: string;
|
|
376
381
|
actual_input: string;
|
|
377
382
|
actual_output: string;
|
|
378
383
|
add_attachment: string;
|
|
@@ -394,6 +399,7 @@ declare const localeLoaders: {
|
|
|
394
399
|
analytics: string;
|
|
395
400
|
apollo_vertex: string;
|
|
396
401
|
apollo_vertex_description: string;
|
|
402
|
+
archive: string;
|
|
397
403
|
are_you_sure: string;
|
|
398
404
|
asc: string;
|
|
399
405
|
ask_ai: string;
|
|
@@ -556,6 +562,8 @@ declare const localeLoaders: {
|
|
|
556
562
|
more_pages: string;
|
|
557
563
|
multi_line_too_few_metrics: string;
|
|
558
564
|
my_template: string;
|
|
565
|
+
nav_collapse: string;
|
|
566
|
+
nav_expand: string;
|
|
559
567
|
need_help: string;
|
|
560
568
|
new_conversation: string;
|
|
561
569
|
new_conversation_confirm_description: string;
|
package/dist/locales/en.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"access_denied": "Access Denied",
|
|
4
4
|
"access_denied_description": "You don't have access to this application. Ask your administrator to add you to the users group.",
|
|
5
5
|
"actions": "Actions",
|
|
6
|
+
"active": "Active",
|
|
6
7
|
"actual_input": "Actual input",
|
|
7
8
|
"actual_output": "Actual output",
|
|
8
9
|
"add_attachment": "Add attachment",
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
"analytics": "Analytics",
|
|
25
26
|
"apollo_vertex": "Apollo Vertex",
|
|
26
27
|
"apollo_vertex_description": "- UiPath Apollo Vertex",
|
|
28
|
+
"archive": "Archive",
|
|
27
29
|
"are_you_sure": "Are you sure?",
|
|
28
30
|
"asc": "Asc",
|
|
29
31
|
"ask_ai": "Ask AI",
|
|
@@ -186,6 +188,8 @@
|
|
|
186
188
|
"more_pages": "More pages",
|
|
187
189
|
"multi_line_too_few_metrics": "Multi-line needs two distinct metrics, but the request resolved to fewer than two.",
|
|
188
190
|
"my_template": "My Template",
|
|
191
|
+
"nav_collapse": "Collapse {{label}}",
|
|
192
|
+
"nav_expand": "Expand {{label}}",
|
|
189
193
|
"need_help": "Need help? Contact your administrator",
|
|
190
194
|
"new_conversation": "New conversation",
|
|
191
195
|
"new_conversation_confirm_description": "This will clear all messages and cannot be undone.",
|
|
@@ -3,11 +3,11 @@ import { Link } from "@tanstack/react-router";
|
|
|
3
3
|
import { AnimatePresence, motion } from "framer-motion";
|
|
4
4
|
import { PanelLeft } from "lucide-react";
|
|
5
5
|
import { useState } from "react";
|
|
6
|
-
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
7
6
|
import { Button } from "../button/button.js";
|
|
8
7
|
import { useSidebar } from "../sidebar/sidebar.js";
|
|
9
8
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../tooltip/tooltip.js";
|
|
10
9
|
import { cn } from "../../lib/utils.js";
|
|
10
|
+
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
11
11
|
import { fastFadeTransition, iconHoverScale, scaleVariants, textFadeVariants } from "./shell-animations.js";
|
|
12
12
|
import { CompanyLogoIcon } from "./shell-company-logo.js";
|
|
13
13
|
function CollapsedLogo({ companyLogo, sidebarHovered, onExpand }) {
|
|
@@ -162,6 +162,7 @@ const Company = ({ companyName, productName, companyLogo, sidebarHovered = false
|
|
|
162
162
|
children: /*#__PURE__*/ jsx(Button, {
|
|
163
163
|
variant: "ghost",
|
|
164
164
|
size: "icon-sm",
|
|
165
|
+
"aria-label": t("close_sidebar"),
|
|
165
166
|
onClick: toggleSidebar,
|
|
166
167
|
className: "ml-auto shrink-0 text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-foreground cursor-pointer",
|
|
167
168
|
children: /*#__PURE__*/ jsx(PanelLeft, {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type PropsWithChildren, type ReactNode } from "react";
|
|
2
2
|
interface LocaleProviderProps {
|
|
3
3
|
loadingElement?: ReactNode;
|
|
4
|
+
configureI18n?: () => Promise<void>;
|
|
4
5
|
}
|
|
5
6
|
export declare const LocaleProviderComponent: ({ children }: PropsWithChildren) => ReactNode;
|
|
6
|
-
export declare const LocaleProvider: ({ children, loadingElement, }: PropsWithChildren<LocaleProviderProps>) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const LocaleProvider: ({ children, loadingElement, configureI18n, }: PropsWithChildren<LocaleProviderProps>) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
|
|
7
8
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useEffectEvent, useState } from "react";
|
|
4
|
-
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
5
4
|
import { Spinner } from "../spinner/spinner.js";
|
|
6
5
|
import { configurei18n } from "../../lib/i18n.js";
|
|
6
|
+
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
7
7
|
import { LANGUAGE_CHANGED_EVENT } from "./shell-constants.js";
|
|
8
8
|
const LocaleProviderComponent = ({ children })=>{
|
|
9
9
|
const { i18n } = useVertexTranslation();
|
|
@@ -21,15 +21,19 @@ const LocaleProviderComponent = ({ children })=>{
|
|
|
21
21
|
}, []);
|
|
22
22
|
return children;
|
|
23
23
|
};
|
|
24
|
-
const LocaleProvider = ({ children, loadingElement })=>{
|
|
24
|
+
const LocaleProvider = ({ children, loadingElement, configureI18n = configurei18n })=>{
|
|
25
25
|
const [isConfigured, setIsConfigured] = useState(false);
|
|
26
|
-
const configure = async ()=>{
|
|
27
|
-
await configurei18n();
|
|
28
|
-
setIsConfigured(true);
|
|
29
|
-
};
|
|
30
26
|
useEffect(()=>{
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
let cancelled = false;
|
|
28
|
+
configureI18n().then(()=>{
|
|
29
|
+
if (!cancelled) setIsConfigured(true);
|
|
30
|
+
});
|
|
31
|
+
return ()=>{
|
|
32
|
+
cancelled = true;
|
|
33
|
+
};
|
|
34
|
+
}, [
|
|
35
|
+
configureI18n
|
|
36
|
+
]);
|
|
33
37
|
if (!isConfigured) return loadingElement ?? /*#__PURE__*/ jsx("div", {
|
|
34
38
|
className: "flex h-full w-full items-center justify-center",
|
|
35
39
|
children: /*#__PURE__*/ jsx(Spinner, {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ShellNavLabel } from "./shell-translation-key";
|
|
2
2
|
interface MinimalNavItemProps {
|
|
3
3
|
to: string;
|
|
4
|
-
|
|
4
|
+
active: boolean;
|
|
5
|
+
label: ShellNavLabel;
|
|
5
6
|
}
|
|
6
|
-
export declare const MinimalNavItem: ({ to, label }: MinimalNavItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const MinimalNavItem: ({ to, active, label }: MinimalNavItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
8
|
export {};
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Link
|
|
2
|
+
import { Link } from "@tanstack/react-router";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
import { Text } from "./shell-text.js";
|
|
5
|
-
const MinimalNavItem = ({ to, label })
|
|
6
|
-
const { pathname } = useLocation();
|
|
7
|
-
const isActive = pathname === to;
|
|
8
|
-
return /*#__PURE__*/ jsx(Link, {
|
|
5
|
+
const MinimalNavItem = ({ to, active, label })=>/*#__PURE__*/ jsx(Link, {
|
|
9
6
|
to: to,
|
|
10
|
-
className: cn("px-4 py-1.5 rounded-full text-sm font-medium transition-colors duration-200 shrink-0 whitespace-nowrap",
|
|
7
|
+
className: cn("px-4 py-1.5 rounded-full text-sm font-medium transition-colors duration-200 shrink-0 whitespace-nowrap", active ? "bg-[oklch(0.92_0.035_218)] dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-semibold" : "text-muted-foreground hover:text-foreground hover:bg-black/[0.04] dark:hover:bg-white/[0.06]"),
|
|
11
8
|
children: /*#__PURE__*/ jsx(Text, {
|
|
12
9
|
value: label
|
|
13
10
|
})
|
|
14
11
|
});
|
|
15
|
-
};
|
|
16
12
|
export { MinimalNavItem };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function navPathIsActive(pathname: string, path: string): boolean;
|
|
2
|
+
export declare function navItemIsCurrent(pathname: string, path: string, childPaths?: readonly string[]): boolean;
|
|
3
|
+
export declare function mostSpecificActivePath(pathname: string, paths: readonly string[]): string | null;
|
|
4
|
+
export declare function navItemState(pathname: string, item: {
|
|
5
|
+
path: string;
|
|
6
|
+
to?: string;
|
|
7
|
+
childPaths?: readonly string[];
|
|
8
|
+
}): {
|
|
9
|
+
href: string;
|
|
10
|
+
prefixActive: boolean;
|
|
11
|
+
current: boolean;
|
|
12
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function navPathIsActive(pathname, path) {
|
|
2
|
+
if ("/" === path) return "/" === pathname;
|
|
3
|
+
return pathname === path || pathname.startsWith(`${path}/`);
|
|
4
|
+
}
|
|
5
|
+
function navItemIsCurrent(pathname, path, childPaths = []) {
|
|
6
|
+
return navPathIsActive(pathname, path) && !childPaths.some((childPath)=>navPathIsActive(pathname, childPath));
|
|
7
|
+
}
|
|
8
|
+
function mostSpecificActivePath(pathname, paths) {
|
|
9
|
+
let match = null;
|
|
10
|
+
for (const path of paths)if (navPathIsActive(pathname, path)) {
|
|
11
|
+
if (null === match || path.length > match.length) match = path;
|
|
12
|
+
}
|
|
13
|
+
return match;
|
|
14
|
+
}
|
|
15
|
+
function navItemState(pathname, item) {
|
|
16
|
+
const childPaths = item.childPaths ?? [];
|
|
17
|
+
const childActive = childPaths.some((childPath)=>navPathIsActive(pathname, childPath));
|
|
18
|
+
return {
|
|
19
|
+
href: item.to ?? item.path,
|
|
20
|
+
prefixActive: navPathIsActive(pathname, item.path) || childActive,
|
|
21
|
+
current: navItemIsCurrent(pathname, item.path, childPaths)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export { mostSpecificActivePath, navItemIsCurrent, navItemState, navPathIsActive };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface NavCatalog {
|
|
2
|
+
namespaces: readonly string[];
|
|
3
|
+
exists: (key: string, namespace: string) => boolean;
|
|
4
|
+
translate: (key: string, namespace: string) => string;
|
|
5
|
+
}
|
|
6
|
+
export declare function navCatalogFromHook(i18n: object): NavCatalog;
|
|
7
|
+
export declare function readNavLabel(catalog: NavCatalog, key: string): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { VERTEX_NAMESPACE } from "../../lib/vertex-translation.js";
|
|
2
|
+
function configuredNamespaces(defaultNS) {
|
|
3
|
+
if ("string" == typeof defaultNS) return defaultNS.length > 0 ? [
|
|
4
|
+
defaultNS
|
|
5
|
+
] : [
|
|
6
|
+
"translation"
|
|
7
|
+
];
|
|
8
|
+
if (!Array.isArray(defaultNS)) return [
|
|
9
|
+
"translation"
|
|
10
|
+
];
|
|
11
|
+
const namespaces = [];
|
|
12
|
+
for (const namespace of defaultNS)if ("string" == typeof namespace && namespace.length > 0) namespaces.push(namespace);
|
|
13
|
+
return namespaces.length > 0 ? namespaces : [
|
|
14
|
+
"translation"
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
function lookupNamespaces(defaultNS) {
|
|
18
|
+
const configured = configuredNamespaces(defaultNS);
|
|
19
|
+
if (configured.includes(VERTEX_NAMESPACE)) return configured;
|
|
20
|
+
return [
|
|
21
|
+
...configured,
|
|
22
|
+
VERTEX_NAMESPACE
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
function isNamespacedI18n(value) {
|
|
26
|
+
return "options" in value && "exists" in value && "function" == typeof value.exists && "t" in value && "function" == typeof value.t;
|
|
27
|
+
}
|
|
28
|
+
function navCatalogFromHook(i18n) {
|
|
29
|
+
if (!isNamespacedI18n(i18n)) return {
|
|
30
|
+
namespaces: [
|
|
31
|
+
"translation",
|
|
32
|
+
VERTEX_NAMESPACE
|
|
33
|
+
],
|
|
34
|
+
exists: ()=>false,
|
|
35
|
+
translate: (key)=>key
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
namespaces: lookupNamespaces(i18n.options.defaultNS),
|
|
39
|
+
exists: (key, namespace)=>i18n.exists(key, {
|
|
40
|
+
ns: namespace
|
|
41
|
+
}),
|
|
42
|
+
translate: (key, namespace)=>{
|
|
43
|
+
const value = i18n.t(key, {
|
|
44
|
+
ns: namespace
|
|
45
|
+
});
|
|
46
|
+
return "string" == typeof value ? value : key;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function readNavLabel(catalog, key) {
|
|
51
|
+
for (const namespace of catalog.namespaces)if (catalog.exists(key, namespace)) return catalog.translate(key, namespace);
|
|
52
|
+
return key;
|
|
53
|
+
}
|
|
54
|
+
export { navCatalogFromHook, readNavLabel };
|
|
@@ -4,45 +4,54 @@ import { Link, useLocation } from "@tanstack/react-router";
|
|
|
4
4
|
import { AnimatePresence, motion } from "framer-motion";
|
|
5
5
|
import { ChevronDown } from "lucide-react";
|
|
6
6
|
import { useEffect, useState } from "react";
|
|
7
|
-
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
8
7
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../collapsible/collapsible.js";
|
|
9
8
|
import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, useSidebar } from "../sidebar/sidebar.js";
|
|
10
9
|
import { cn } from "../../lib/utils.js";
|
|
10
|
+
import { useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
11
11
|
import { fastFadeTransition, iconHoverScale, textFadeVariants } from "./shell-animations.js";
|
|
12
12
|
import { Company } from "./shell-company.js";
|
|
13
13
|
import { MinimalCompany } from "./shell-minimal-company.js";
|
|
14
14
|
import { MinimalNavItem } from "./shell-minimal-nav-item.js";
|
|
15
|
+
import { mostSpecificActivePath, navItemState } from "./shell-nav-active.js";
|
|
16
|
+
import { navCatalogFromHook, readNavLabel } from "./shell-nav-label.js";
|
|
15
17
|
import { Text } from "./shell-text.js";
|
|
16
18
|
import { UserProfile } from "./shell-user-profile.js";
|
|
17
19
|
const activeNavClass = "text-sidebar-foreground/85 hover:text-sidebar-foreground data-[active=true]:text-primary-700 dark:data-[active=true]:text-primary-400 data-[active=true]:font-semibold data-[active=true]:bg-primary-100/40 dark:data-[active=true]:bg-primary-900/30";
|
|
18
20
|
const navButtonClass = `font-medium ${activeNavClass}`;
|
|
19
21
|
const subButtonClass = activeNavClass;
|
|
22
|
+
const prefixActiveClass = "font-semibold text-primary-700 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-400 active:text-primary-700 dark:active:text-primary-400";
|
|
23
|
+
const currentPillClass = "bg-primary-100/40 dark:bg-primary-900/30";
|
|
20
24
|
const ShellSidebar = ({ companyName, productName, variant, companyLogo, navItems })=>{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
const { pathname } = useLocation();
|
|
26
|
+
if ("minimal" === variant) {
|
|
27
|
+
const activePath = mostSpecificActivePath(pathname, navItems.map((item)=>item.path));
|
|
28
|
+
return /*#__PURE__*/ jsxs("header", {
|
|
29
|
+
className: "relative flex items-center justify-between px-4 sm:px-6 lg:px-8 py-6 transition-[padding] duration-300 ease-in-out",
|
|
30
|
+
children: [
|
|
31
|
+
/*#__PURE__*/ jsx(MinimalCompany, {
|
|
32
|
+
companyName: companyName,
|
|
33
|
+
productName: productName,
|
|
34
|
+
companyLogo: companyLogo
|
|
35
|
+
}),
|
|
36
|
+
navItems.length > 0 && /*#__PURE__*/ jsx("nav", {
|
|
37
|
+
className: "absolute left-1/2 -translate-x-1/2 flex items-center bg-muted dark:bg-[oklch(0.24_0.033_254)] rounded-full p-1.5 overflow-x-auto scrollbar-thin",
|
|
38
|
+
children: navItems.map((item)=>/*#__PURE__*/ jsx(MinimalNavItem, {
|
|
39
|
+
to: item.to ?? item.path,
|
|
40
|
+
active: item.path === activePath,
|
|
41
|
+
label: item.label
|
|
42
|
+
}, item.path))
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ jsx("div", {
|
|
45
|
+
className: "flex items-center gap-2",
|
|
46
|
+
children: /*#__PURE__*/ jsx(UserProfile, {
|
|
47
|
+
isCollapsed: true,
|
|
48
|
+
collapsedMenuSide: "bottom",
|
|
49
|
+
collapsedMenuAlign: "end"
|
|
50
|
+
})
|
|
42
51
|
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
46
55
|
return /*#__PURE__*/ jsx(SidebarNav, {
|
|
47
56
|
companyName: companyName,
|
|
48
57
|
productName: productName,
|
|
@@ -51,8 +60,9 @@ const ShellSidebar = ({ companyName, productName, variant, companyLogo, navItems
|
|
|
51
60
|
});
|
|
52
61
|
};
|
|
53
62
|
function SidebarNav({ companyName, productName, companyLogo, navItems }) {
|
|
54
|
-
const { t } = useVertexTranslation();
|
|
55
|
-
const
|
|
63
|
+
const { t, i18n } = useVertexTranslation();
|
|
64
|
+
const catalog = navCatalogFromHook(i18n);
|
|
65
|
+
const { state } = useSidebar();
|
|
56
66
|
const { pathname } = useLocation();
|
|
57
67
|
const isCollapsed = "collapsed" === state;
|
|
58
68
|
const [sidebarHovered, setSidebarHovered] = useState(false);
|
|
@@ -75,24 +85,16 @@ function SidebarNav({ companyName, productName, companyLogo, navItems }) {
|
|
|
75
85
|
pathname,
|
|
76
86
|
navItems
|
|
77
87
|
]);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
toggleSidebar();
|
|
81
|
-
setExpandedItems((prev)=>new Set(prev).add(path));
|
|
82
|
-
} else setExpandedItems((prev)=>{
|
|
88
|
+
const toggleGroup = (path)=>{
|
|
89
|
+
setExpandedItems((prev)=>{
|
|
83
90
|
const next = new Set(prev);
|
|
84
91
|
if (next.has(path)) next.delete(path);
|
|
85
92
|
else next.add(path);
|
|
86
93
|
return next;
|
|
87
94
|
});
|
|
88
95
|
};
|
|
89
|
-
const isActive = (path)=>{
|
|
90
|
-
if ("/" === path) return "/" === pathname;
|
|
91
|
-
return pathname === path || pathname.startsWith(`${path}/`);
|
|
92
|
-
};
|
|
93
|
-
const isParentActive = (item)=>item.subItems?.some((sub)=>isActive(sub.path)) ?? false;
|
|
94
96
|
const getTooltipText = (label)=>{
|
|
95
|
-
if ("string" == typeof label) return
|
|
97
|
+
if ("string" == typeof label) return readNavLabel(catalog, label);
|
|
96
98
|
return t(label.i18nKey, label.values);
|
|
97
99
|
};
|
|
98
100
|
return /*#__PURE__*/ jsxs(Sidebar, {
|
|
@@ -119,97 +121,107 @@ function SidebarNav({ companyName, productName, companyLogo, navItems }) {
|
|
|
119
121
|
children: /*#__PURE__*/ jsx(SidebarMenu, {
|
|
120
122
|
children: navItems.map((item)=>{
|
|
121
123
|
const Icon = item.icon;
|
|
122
|
-
const active = isActive(item.path);
|
|
123
|
-
const parentActive = isParentActive(item);
|
|
124
124
|
const isExpanded = expandedItems.has(item.path);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
125
|
+
const childPaths = item.subItems?.map((sub)=>sub.path) ?? [];
|
|
126
|
+
const row = navItemState(pathname, {
|
|
127
|
+
path: item.path,
|
|
128
|
+
to: item.to,
|
|
129
|
+
childPaths
|
|
130
|
+
});
|
|
131
|
+
if (item.subItems && item.subItems.length > 0) return /*#__PURE__*/ jsx(Collapsible, {
|
|
132
|
+
open: isExpanded && !isCollapsed,
|
|
133
|
+
onOpenChange: ()=>toggleGroup(item.path),
|
|
134
|
+
className: "group/collapsible",
|
|
135
|
+
children: /*#__PURE__*/ jsxs(SidebarMenuItem, {
|
|
136
|
+
children: [
|
|
137
|
+
/*#__PURE__*/ jsxs("div", {
|
|
138
|
+
className: cn("flex w-full min-w-0 items-center rounded-md", !isCollapsed && row.current && currentPillClass, !isCollapsed && !row.current && "hover:bg-sidebar-accent/50"),
|
|
139
|
+
children: [
|
|
140
|
+
/*#__PURE__*/ jsx(SidebarMenuButton, {
|
|
141
|
+
asChild: true,
|
|
136
142
|
tooltip: getTooltipText(item.label),
|
|
137
|
-
isActive:
|
|
138
|
-
className: navButtonClass,
|
|
139
|
-
children:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
/*#__PURE__*/ jsx(AnimatePresence, {
|
|
150
|
-
initial: false,
|
|
151
|
-
children: !isCollapsed && /*#__PURE__*/ jsx(motion.span, {
|
|
152
|
-
variants: textFadeVariants,
|
|
153
|
-
initial: "initial",
|
|
154
|
-
animate: "animate",
|
|
155
|
-
exit: "exit",
|
|
156
|
-
transition: fastFadeTransition,
|
|
157
|
-
className: "whitespace-nowrap truncate",
|
|
158
|
-
children: /*#__PURE__*/ jsx(Text, {
|
|
159
|
-
value: item.label
|
|
143
|
+
isActive: isCollapsed && row.current,
|
|
144
|
+
className: cn(navButtonClass, row.prefixActive && prefixActiveClass, !isCollapsed && "w-auto min-w-0 flex-1 bg-transparent hover:bg-transparent"),
|
|
145
|
+
children: /*#__PURE__*/ jsxs(Link, {
|
|
146
|
+
to: row.href,
|
|
147
|
+
children: [
|
|
148
|
+
/*#__PURE__*/ jsx(motion.span, {
|
|
149
|
+
className: "inline-flex items-center justify-center shrink-0",
|
|
150
|
+
...isCollapsed ? {
|
|
151
|
+
whileHover: iconHoverScale
|
|
152
|
+
} : {},
|
|
153
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
154
|
+
className: "size-4 shrink-0"
|
|
160
155
|
})
|
|
161
|
-
},
|
|
156
|
+
}),
|
|
157
|
+
/*#__PURE__*/ jsx(AnimatePresence, {
|
|
158
|
+
initial: false,
|
|
159
|
+
children: !isCollapsed && /*#__PURE__*/ jsx(motion.span, {
|
|
160
|
+
variants: textFadeVariants,
|
|
161
|
+
initial: "initial",
|
|
162
|
+
animate: "animate",
|
|
163
|
+
exit: "exit",
|
|
164
|
+
transition: fastFadeTransition,
|
|
165
|
+
className: "whitespace-nowrap truncate",
|
|
166
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
167
|
+
value: item.label
|
|
168
|
+
})
|
|
169
|
+
}, "text")
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
})
|
|
173
|
+
}),
|
|
174
|
+
!isCollapsed && /*#__PURE__*/ jsx(CollapsibleTrigger, {
|
|
175
|
+
asChild: true,
|
|
176
|
+
children: /*#__PURE__*/ jsx("button", {
|
|
177
|
+
type: "button",
|
|
178
|
+
"aria-expanded": isExpanded,
|
|
179
|
+
"aria-label": t(isExpanded ? "nav_collapse" : "nav_expand", {
|
|
180
|
+
label: getTooltipText(item.label)
|
|
162
181
|
}),
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
variants: textFadeVariants,
|
|
167
|
-
initial: "initial",
|
|
168
|
-
animate: "animate",
|
|
169
|
-
exit: "exit",
|
|
170
|
-
transition: fastFadeTransition,
|
|
171
|
-
className: "ml-auto",
|
|
172
|
-
children: /*#__PURE__*/ jsx(ChevronDown, {
|
|
173
|
-
className: cn("size-4 transition-transform duration-200", isExpanded && "rotate-180")
|
|
174
|
-
})
|
|
175
|
-
}, "chevron")
|
|
182
|
+
className: "flex size-8 shrink-0 items-center justify-center text-sidebar-foreground/70 hover:text-sidebar-foreground",
|
|
183
|
+
children: /*#__PURE__*/ jsx(ChevronDown, {
|
|
184
|
+
className: cn("size-4 transition-transform duration-200", isExpanded && "rotate-180")
|
|
176
185
|
})
|
|
177
|
-
|
|
186
|
+
})
|
|
178
187
|
})
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
]
|
|
189
|
+
}),
|
|
190
|
+
/*#__PURE__*/ jsx(CollapsibleContent, {
|
|
191
|
+
children: /*#__PURE__*/ jsx(SidebarMenuSub, {
|
|
192
|
+
className: "ml-4 mr-0 mt-1 gap-0.5 pl-3 pr-0",
|
|
193
|
+
children: item.subItems.map((subItem)=>{
|
|
194
|
+
const sub = navItemState(pathname, {
|
|
195
|
+
path: subItem.path,
|
|
196
|
+
to: subItem.to
|
|
197
|
+
});
|
|
198
|
+
return /*#__PURE__*/ jsx(SidebarMenuSubItem, {
|
|
199
|
+
children: /*#__PURE__*/ jsx(SidebarMenuSubButton, {
|
|
200
|
+
asChild: true,
|
|
201
|
+
isActive: sub.current,
|
|
202
|
+
className: cn("cursor-pointer whitespace-nowrap", subButtonClass),
|
|
203
|
+
children: /*#__PURE__*/ jsx(Link, {
|
|
204
|
+
to: sub.href,
|
|
205
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
206
|
+
value: subItem.label
|
|
195
207
|
})
|
|
196
208
|
})
|
|
197
|
-
}
|
|
198
|
-
})
|
|
209
|
+
})
|
|
210
|
+
}, subItem.path);
|
|
199
211
|
})
|
|
200
212
|
})
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
}
|
|
213
|
+
})
|
|
214
|
+
]
|
|
215
|
+
})
|
|
216
|
+
}, item.path);
|
|
205
217
|
return /*#__PURE__*/ jsx(SidebarMenuItem, {
|
|
206
218
|
children: /*#__PURE__*/ jsx(SidebarMenuButton, {
|
|
207
219
|
tooltip: getTooltipText(item.label),
|
|
208
|
-
isActive:
|
|
220
|
+
isActive: row.current,
|
|
209
221
|
asChild: true,
|
|
210
222
|
className: navButtonClass,
|
|
211
223
|
children: /*#__PURE__*/ jsxs(Link, {
|
|
212
|
-
to:
|
|
224
|
+
to: row.href,
|
|
213
225
|
children: [
|
|
214
226
|
/*#__PURE__*/ jsx(motion.span, {
|
|
215
227
|
className: "inline-flex items-center justify-center shrink-0",
|
|
@@ -252,7 +264,7 @@ function SidebarNav({ companyName, productName, companyLogo, navItems }) {
|
|
|
252
264
|
/*#__PURE__*/ jsx("div", {
|
|
253
265
|
className: "absolute inset-0 pointer-events-none",
|
|
254
266
|
style: {
|
|
255
|
-
boxShadow: "inset -1px 0 0 0 color-mix(in srgb, var(--
|
|
267
|
+
boxShadow: "inset -1px 0 0 0 color-mix(in srgb, var(--border) 50%, transparent)"
|
|
256
268
|
}
|
|
257
269
|
})
|
|
258
270
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ShellNavLabel } from "./shell-translation-key";
|
|
2
2
|
export declare const Text: ({ value }: {
|
|
3
|
-
value:
|
|
3
|
+
value: ShellNavLabel;
|
|
4
4
|
}) => string | import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Trans } from "react-i18next";
|
|
3
3
|
import { VERTEX_NAMESPACE, useVertexTranslation } from "../../lib/vertex-translation.js";
|
|
4
|
+
import { navCatalogFromHook, readNavLabel } from "./shell-nav-label.js";
|
|
4
5
|
const Text = ({ value })=>{
|
|
5
|
-
const {
|
|
6
|
-
if ("string" == typeof value) return
|
|
6
|
+
const { i18n } = useVertexTranslation();
|
|
7
|
+
if ("string" == typeof value) return readNavLabel(navCatalogFromHook(i18n), value);
|
|
7
8
|
return /*#__PURE__*/ jsx(Trans, {
|
|
8
9
|
ns: VERTEX_NAMESPACE,
|
|
9
10
|
i18nKey: value.i18nKey,
|
|
@@ -5,3 +5,8 @@ export type TranslationKey = {
|
|
|
5
5
|
values: Record<string, string | number | string[]>;
|
|
6
6
|
components: Record<string, ReactElement>;
|
|
7
7
|
} | ParseKeys;
|
|
8
|
+
type TranslationObject = Extract<TranslationKey, {
|
|
9
|
+
i18nKey: ParseKeys;
|
|
10
|
+
}>;
|
|
11
|
+
export type ShellNavLabel = string | TranslationObject;
|
|
12
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LucideIcon } from "lucide-react";
|
|
2
2
|
import type { FC, PropsWithChildren } from "react";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ShellNavLabel } from "./shell-translation-key";
|
|
4
4
|
export interface CompanyLogo {
|
|
5
5
|
url: string;
|
|
6
6
|
darkUrl?: string;
|
|
@@ -9,11 +9,13 @@ export interface CompanyLogo {
|
|
|
9
9
|
}
|
|
10
10
|
export interface ShellSubNavItem {
|
|
11
11
|
path: string;
|
|
12
|
-
|
|
12
|
+
to?: string;
|
|
13
|
+
label: ShellNavLabel;
|
|
13
14
|
}
|
|
14
15
|
export interface ShellNavItem {
|
|
15
16
|
path: string;
|
|
16
|
-
|
|
17
|
+
to?: string;
|
|
18
|
+
label: ShellNavLabel;
|
|
17
19
|
icon: LucideIcon;
|
|
18
20
|
subItems?: ShellSubNavItem[];
|
|
19
21
|
}
|
|
@@ -24,5 +26,6 @@ export interface ApolloShellProps extends PropsWithChildren {
|
|
|
24
26
|
companyLogo?: CompanyLogo;
|
|
25
27
|
navItems: ShellNavItem[];
|
|
26
28
|
loginDescription?: string;
|
|
29
|
+
configureI18n?: () => Promise<void>;
|
|
27
30
|
}
|
|
28
31
|
export declare const ApolloShell: FC<ApolloShellProps>;
|
|
@@ -7,9 +7,23 @@ import { ShellLayout } from "./shell-layout.js";
|
|
|
7
7
|
import { LocaleProvider } from "./shell-locale-provider.js";
|
|
8
8
|
import { ShellLogin } from "./shell-login.js";
|
|
9
9
|
import { ShellUserProvider } from "./shell-user-provider.js";
|
|
10
|
+
function ShellLoadingSkeleton() {
|
|
11
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
12
|
+
className: "flex h-screen gap-4 p-4 bg-background dark:bg-sidebar",
|
|
13
|
+
children: [
|
|
14
|
+
/*#__PURE__*/ jsx(Skeleton, {
|
|
15
|
+
className: "h-full w-[280px]"
|
|
16
|
+
}),
|
|
17
|
+
/*#__PURE__*/ jsx(Skeleton, {
|
|
18
|
+
className: "h-full flex-1 rounded-lg"
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
10
23
|
const ApolloShellContent = ({ children, companyName, productName, companyLogo, variant, navItems, loginDescription })=>{
|
|
11
24
|
const authContext = useContext(AuthContext);
|
|
12
|
-
const { accessToken } = useAuth();
|
|
25
|
+
const { accessToken, isLoading } = useAuth();
|
|
26
|
+
if (authContext && isLoading) return /*#__PURE__*/ jsx(ShellLoadingSkeleton, {});
|
|
13
27
|
if (authContext && !accessToken) return /*#__PURE__*/ jsx(ShellLogin, {
|
|
14
28
|
title: productName,
|
|
15
29
|
description: loginDescription
|
|
@@ -25,18 +39,9 @@ const ApolloShellContent = ({ children, companyName, productName, companyLogo, v
|
|
|
25
39
|
})
|
|
26
40
|
});
|
|
27
41
|
};
|
|
28
|
-
const ApolloShell = ({ children, companyName, productName, companyLogo, variant, navItems, loginDescription })=>/*#__PURE__*/ jsx(LocaleProvider, {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
children: [
|
|
32
|
-
/*#__PURE__*/ jsx(Skeleton, {
|
|
33
|
-
className: "h-full w-[280px]"
|
|
34
|
-
}),
|
|
35
|
-
/*#__PURE__*/ jsx(Skeleton, {
|
|
36
|
-
className: "h-full flex-1 rounded-lg"
|
|
37
|
-
})
|
|
38
|
-
]
|
|
39
|
-
}),
|
|
42
|
+
const ApolloShell = ({ children, companyName, productName, companyLogo, variant, navItems, loginDescription, configureI18n })=>/*#__PURE__*/ jsx(LocaleProvider, {
|
|
43
|
+
configureI18n: configureI18n,
|
|
44
|
+
loadingElement: /*#__PURE__*/ jsx(ShellLoadingSkeleton, {}),
|
|
40
45
|
children: /*#__PURE__*/ jsx(ApolloShellContent, {
|
|
41
46
|
companyName: companyName,
|
|
42
47
|
productName: productName,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* outside a SolutionProvider or when the named collection is not registered.
|
|
5
5
|
*/
|
|
6
6
|
import type { Collection } from "@tanstack/react-db";
|
|
7
|
+
import { useSolution } from "@uipath/vs-core";
|
|
7
8
|
import { ENTITY } from "./constants";
|
|
8
9
|
import type { SolutionTest, SolutionTestBatchRun, SolutionTestJob, SolutionTestRun, SolutionTestRunResult } from "./types";
|
|
9
10
|
/** Row type stored in each Solution Tests collection, keyed by its entity name. */
|
|
@@ -14,5 +15,9 @@ type SolutionTestRow = {
|
|
|
14
15
|
[ENTITY.jobs]: SolutionTestJob;
|
|
15
16
|
[ENTITY.runResults]: SolutionTestRunResult;
|
|
16
17
|
};
|
|
17
|
-
|
|
18
|
+
type SolutionTestCollection<T extends object> = Collection<T, string, {
|
|
19
|
+
refetch: () => Promise<void>;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function getSolutionTestCollection<K extends keyof SolutionTestRow>(solution: ReturnType<typeof useSolution>, entity: K): SolutionTestCollection<SolutionTestRow[K]> | undefined;
|
|
22
|
+
export declare function useSolutionTestCollection<K extends keyof SolutionTestRow>(entity: K): SolutionTestCollection<SolutionTestRow[K]>;
|
|
18
23
|
export {};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useSolution } from "@uipath/vs-core";
|
|
3
|
+
function getSolutionTestCollection(solution, entity) {
|
|
4
|
+
const collections = solution.api.collections.solutionTests;
|
|
5
|
+
return collections[entity];
|
|
6
|
+
}
|
|
3
7
|
function useSolutionTestCollection(entity) {
|
|
4
8
|
const solution = useSolution();
|
|
5
9
|
if (!solution) throw new Error("useSolutionTestCollection must be used within a SolutionProvider.");
|
|
6
|
-
const
|
|
7
|
-
const collection = selected;
|
|
10
|
+
const collection = getSolutionTestCollection(solution, entity);
|
|
8
11
|
if (!collection) throw new Error(`Solution Tests collection "${entity}" is unavailable.`);
|
|
9
12
|
return collection;
|
|
10
13
|
}
|
|
11
|
-
export { useSolutionTestCollection };
|
|
14
|
+
export { getSolutionTestCollection, useSolutionTestCollection };
|
|
@@ -4,7 +4,7 @@ import { useMutation } from "@tanstack/react-query";
|
|
|
4
4
|
import { useSolution } from "@uipath/vs-core";
|
|
5
5
|
import { ENTITY } from "./constants.js";
|
|
6
6
|
import { useSolutionTestsActions, useSolutionTestsConfig } from "./context.js";
|
|
7
|
-
import { useSolutionTestCollection } from "./use-solution-test-collection.js";
|
|
7
|
+
import { getSolutionTestCollection, useSolutionTestCollection } from "./use-solution-test-collection.js";
|
|
8
8
|
function useSolutionTests() {
|
|
9
9
|
const collection = useSolutionTestCollection(ENTITY.tests);
|
|
10
10
|
const { data, isLoading } = useLiveQuery((q)=>q.from({
|
|
@@ -47,7 +47,7 @@ function useToggleTestActive() {
|
|
|
47
47
|
const { track } = useSolutionTestsConfig();
|
|
48
48
|
return useMutation({
|
|
49
49
|
mutationFn: async ({ testId, isActive })=>{
|
|
50
|
-
const collection = solution
|
|
50
|
+
const collection = solution && getSolutionTestCollection(solution, ENTITY.tests);
|
|
51
51
|
if (!collection) throw new Error("Solution Tests collection is unavailable.");
|
|
52
52
|
const transaction = collection.update(testId, (draft)=>{
|
|
53
53
|
draft.IsActive = isActive;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon } from "lucide-react";
|
|
4
4
|
import { Toaster } from "sonner";
|
|
5
|
-
import { useTheme } from "../shell/shell-theme-provider.js";
|
|
6
5
|
const iconAlign = "[&>[data-icon]]:!items-start [&>[data-icon]>svg]:!mt-0.5";
|
|
7
6
|
const statusTextClasses = "[&>[data-icon]>svg]:!text-[oklch(0.166_0.0283_203.34)] dark:[&>[data-icon]>svg]:!text-foreground [&_[data-title]]:!text-[oklch(0.166_0.0283_203.34)] dark:[&_[data-title]]:!text-foreground [&_[data-description]]:!text-[oklch(0.166_0.0283_203.34)] dark:[&_[data-description]]:!text-foreground [&_[data-close-button]]:!text-[oklch(0.166_0.0283_203.34)] dark:[&_[data-close-button]]:!text-foreground";
|
|
8
7
|
const apolloToastClassNames = {
|
|
@@ -10,12 +9,11 @@ const apolloToastClassNames = {
|
|
|
10
9
|
success: `!border-success !bg-[color-mix(in_srgb,var(--success)_25%,var(--card)_75%)] dark:!bg-[color-mix(in_srgb,var(--success)_25%,var(--popover)_75%)] ${statusTextClasses} ${iconAlign}`,
|
|
11
10
|
warning: `!border-warning !bg-[color-mix(in_srgb,var(--warning)_60%,var(--card)_40%)] dark:!bg-[color-mix(in_srgb,var(--warning)_60%,var(--popover)_40%)] ${statusTextClasses} ${iconAlign}`,
|
|
12
11
|
error: `!border-destructive !bg-[color-mix(in_srgb,var(--destructive)_50%,var(--card)_50%)] dark:!bg-[color-mix(in_srgb,var(--destructive)_50%,var(--popover)_50%)] ${statusTextClasses} ${iconAlign}`,
|
|
13
|
-
|
|
12
|
+
description: "!text-popover-foreground",
|
|
13
|
+
cancelButton: "dark:!bg-white/30",
|
|
14
|
+
closeButton: "!left-auto !right-2 !top-2 !transform-none !border-none !bg-transparent !rounded-sm !text-popover-foreground"
|
|
14
15
|
};
|
|
15
|
-
const sonner_Toaster = ({ theme: _theme, ...props })
|
|
16
|
-
const { resolvedTheme } = useTheme();
|
|
17
|
-
return /*#__PURE__*/ jsx(Toaster, {
|
|
18
|
-
theme: resolvedTheme,
|
|
16
|
+
const sonner_Toaster = ({ theme: _theme, ...props })=>/*#__PURE__*/ jsx(Toaster, {
|
|
19
17
|
className: "toaster group",
|
|
20
18
|
position: "top-center",
|
|
21
19
|
duration: 5000,
|
|
@@ -48,5 +46,4 @@ const sonner_Toaster = ({ theme: _theme, ...props })=>{
|
|
|
48
46
|
},
|
|
49
47
|
...props
|
|
50
48
|
});
|
|
51
|
-
};
|
|
52
49
|
export { sonner_Toaster as Toaster, apolloToastClassNames };
|
|
@@ -10,7 +10,12 @@ export interface UseEntityDataTableOptions<TRecord extends EntityRecord = Entity
|
|
|
10
10
|
columnOverrides?: Record<string, (baseDef: ColumnDefWithAccessorKey<TRecord>) => ColumnDefWithAccessorKey<TRecord>>;
|
|
11
11
|
}
|
|
12
12
|
export declare function useEntityDataTable<TRecord extends EntityRecord = EntityRecord>({ entity, storageKey: storageKeyProp, initialVisibleColumnCount, systemFields, columnOrder: columnOrderProp, extraColumns, columnOverrides, }: UseEntityDataTableOptions<TRecord>): {
|
|
13
|
-
data:
|
|
13
|
+
data: {
|
|
14
|
+
readonly $synced: boolean;
|
|
15
|
+
readonly $origin: import("@tanstack/react-db").VirtualOrigin;
|
|
16
|
+
readonly $key: string;
|
|
17
|
+
readonly $collectionId: string;
|
|
18
|
+
}[];
|
|
14
19
|
isLoading: boolean;
|
|
15
20
|
columns: import("../data-table").ColumnDef<TRecord>[];
|
|
16
21
|
sorting: import("@tanstack/react-table").SortingState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/apollo-vertex",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "UiPath Apollo Vertex design system components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"types": "./dist/entries/index.d.ts",
|
|
18
18
|
"default": "./dist/entries/index.js"
|
|
19
19
|
},
|
|
20
|
+
"./proteus": {
|
|
21
|
+
"types": "./dist/entries/proteus.d.ts",
|
|
22
|
+
"default": "./dist/entries/proteus.js"
|
|
23
|
+
},
|
|
20
24
|
"./theme.css": "./dist/theme.css",
|
|
21
25
|
"./tailwind.css": "./dist/tailwind.css",
|
|
22
26
|
"./locales/*": "./dist/locales/*"
|
|
@@ -80,10 +84,12 @@
|
|
|
80
84
|
"peerDependencies": {
|
|
81
85
|
"@tanstack/ai": "^0.14.0",
|
|
82
86
|
"@tanstack/ai-client": "^0.8.0",
|
|
87
|
+
"@tanstack/react-db": "^0.1.83",
|
|
83
88
|
"@tanstack/react-query": "^5.90.21",
|
|
84
89
|
"@tanstack/react-router": "^1.132.31",
|
|
85
90
|
"@ts-rest/core": "^3.53.0-rc.1",
|
|
86
91
|
"@uipath/uipath-typescript": "^1.7.1",
|
|
92
|
+
"@uipath/vs-core": "^4.4.0",
|
|
87
93
|
"eventsource-parser": "^3.0.6",
|
|
88
94
|
"highlight.js": "^11.11.1",
|
|
89
95
|
"i18next": "^25.8.1 || ^26.0.0",
|
|
@@ -100,14 +106,8 @@
|
|
|
100
106
|
"tailwindcss": "^4.0.0"
|
|
101
107
|
},
|
|
102
108
|
"peerDependenciesMeta": {
|
|
103
|
-
"@tanstack/react-db": {
|
|
104
|
-
"optional": true
|
|
105
|
-
},
|
|
106
109
|
"@uipath/proteus-client": {
|
|
107
110
|
"optional": true
|
|
108
|
-
},
|
|
109
|
-
"@uipath/vs-core": {
|
|
110
|
-
"optional": true
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
|
@@ -116,8 +116,11 @@
|
|
|
116
116
|
"@rslib/core": "^0.19.6",
|
|
117
117
|
"@tanstack/ai": "0.14.0",
|
|
118
118
|
"@tanstack/ai-client": "0.8.0",
|
|
119
|
+
"@tanstack/db": "0.6.5",
|
|
119
120
|
"@tanstack/intent": "0.4.0",
|
|
120
|
-
"@tanstack/
|
|
121
|
+
"@tanstack/query-db-collection": "1.0.36",
|
|
122
|
+
"@tanstack/react-db": "0.1.83",
|
|
123
|
+
"@tanstack/react-query": "^5.104.1",
|
|
121
124
|
"@tanstack/react-router": "^1.170.40",
|
|
122
125
|
"@testing-library/dom": "^10.4.1",
|
|
123
126
|
"@testing-library/react": "^16.3.0",
|
|
@@ -126,6 +129,7 @@
|
|
|
126
129
|
"@types/react": "^19.2.6",
|
|
127
130
|
"@types/react-dom": "^19.2.2",
|
|
128
131
|
"@uipath/uipath-typescript": "^1.8.0",
|
|
132
|
+
"@uipath/vs-core": "^4.5.0",
|
|
129
133
|
"@vitest/coverage-v8": "^4.1.5",
|
|
130
134
|
"dependency-cruiser": "^17.3.6",
|
|
131
135
|
"eslint-plugin-react": "^7.37.5",
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -30,14 +30,16 @@ Install `@uipath/apollo-vertex` if the project doesn't have it yet.
|
|
|
30
30
|
|
|
31
31
|
Then read `peerDependencies` in
|
|
32
32
|
`node_modules/@uipath/apollo-vertex/package.json` and make sure the app has
|
|
33
|
-
every package listed there, in a version that matches the range.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
app's bundler fails to resolve the entry without them.
|
|
33
|
+
every package listed there, in a version that matches the range. Install
|
|
34
|
+
`@uipath/proteus-client` only if the app uses Proteus feature flags (it imports
|
|
35
|
+
`@uipath/apollo-vertex/proteus`).
|
|
37
36
|
|
|
38
37
|
- If the app already has a peer in a version outside the range, tell the user
|
|
39
38
|
about the conflict instead of upgrading it on your own.
|
|
40
|
-
-
|
|
39
|
+
- Pick the `@tanstack/react-db` release whose `@tanstack/db` dependency matches
|
|
40
|
+
the one `@tanstack/query-db-collection` uses in the app. Each release pins an
|
|
41
|
+
exact `@tanstack/db`, and two copies do not work together.
|
|
42
|
+
- `@uipath/proteus-client` is not on the public npm registry. If installing it
|
|
41
43
|
fails with a 404 or an authentication error, stop and ask the user for access
|
|
42
44
|
to UiPath's package registry. Do not install look-alike packages from npm.
|
|
43
45
|
- If the app doesn't use Tailwind yet, set it up for the app's bundler with
|