@sybilion/uilib 1.1.0 → 1.2.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/README.md +8 -8
- package/assets/{mini-app-global.css → standalone-global.css} +1 -1
- package/dist/esm/components/ui/Image/Image.styl.js +1 -1
- package/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +28 -0
- package/dist/esm/components/ui/NavUserHeader/NavUserHeader.styl.js +7 -0
- package/dist/esm/components/ui/Sidebar/Sidebar.styl.js +2 -2
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.js +48 -0
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl.js +7 -0
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.js +38 -0
- package/dist/esm/index.js +6 -5
- package/dist/esm/sybilion-auth/SybilionAuthProvider.js +208 -0
- package/dist/esm/sybilion-auth/authPaths.js +7 -0
- package/dist/esm/sybilion-auth/exchangeSybilionToken.js +44 -0
- package/dist/esm/types/src/components/ui/Input/Input.d.ts +1 -1
- package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.d.ts +2 -0
- package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.types.d.ts +25 -0
- package/dist/esm/types/src/components/ui/NavUserHeader/index.d.ts +2 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.d.ts +11 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.d.ts +8 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/index.d.ts +3 -0
- package/dist/esm/types/src/docs/pages/NavUserHeaderPage.d.ts +1 -0
- package/dist/esm/types/src/docs/pages/SidebarDatasetsItemsGroupedPage.d.ts +1 -0
- package/dist/esm/types/src/docs/pages/SybilionAuthProviderPage.d.ts +1 -0
- package/dist/esm/types/src/index.d.ts +4 -1
- package/dist/esm/types/src/sybilion-auth/SybilionAuthProvider.d.ts +42 -0
- package/dist/esm/types/src/sybilion-auth/authPaths.d.ts +3 -0
- package/dist/esm/types/src/sybilion-auth/exchangeSybilionToken.d.ts +4 -0
- package/dist/esm/types/src/sybilion-auth/index.d.ts +4 -0
- package/dist/esm/types/src/{mini-app/miniAppDataTypes.d.ts → types/sybilionDatasetSnapshots.d.ts} +5 -8
- package/docs/standalone-apps.md +181 -0
- package/package.json +15 -3
- package/src/components/ui/Image/Image.styl +1 -0
- package/src/components/ui/NavUserHeader/NavUserHeader.styl +125 -0
- package/src/components/ui/NavUserHeader/NavUserHeader.styl.d.ts +28 -0
- package/src/components/ui/NavUserHeader/NavUserHeader.tsx +148 -0
- package/src/components/ui/NavUserHeader/NavUserHeader.types.ts +27 -0
- package/src/components/ui/NavUserHeader/avatar.svg +4 -0
- package/src/components/ui/NavUserHeader/index.ts +5 -0
- package/src/components/ui/Sidebar/Sidebar.styl +0 -25
- package/src/components/ui/Sidebar/Sidebar.styl.d.ts +0 -1
- package/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl +29 -0
- package/src/{mini-app/MiniAppRoot.styl.d.ts → components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl.d.ts} +4 -2
- package/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx +128 -0
- package/src/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.ts +51 -0
- package/src/components/widgets/SidebarDatasetsItemsGrouped/index.ts +10 -0
- package/src/docs/pages/NavUserHeaderPage.tsx +89 -0
- package/src/docs/pages/SidebarDatasetsItemsGroupedPage.tsx +136 -0
- package/src/docs/pages/SybilionAuthProviderPage.tsx +40 -0
- package/src/docs/registry.ts +15 -3
- package/src/index.ts +4 -1
- package/src/sybilion-auth/SybilionAuthProvider.tsx +344 -0
- package/src/sybilion-auth/authPaths.ts +6 -0
- package/src/sybilion-auth/exchangeSybilionToken.ts +51 -0
- package/src/sybilion-auth/index.ts +17 -0
- package/src/{mini-app/miniAppDataTypes.ts → types/sybilionDatasetSnapshots.ts} +5 -8
- package/dist/esm/mini-app/MiniAppRoot.js +0 -82
- package/dist/esm/mini-app/MiniAppRoot.styl.js +0 -7
- package/dist/esm/mini-app/miniAppChatBridge.js +0 -45
- package/dist/esm/mini-app/miniAppDataClient.js +0 -98
- package/dist/esm/mini-app/miniAppProtocol.js +0 -153
- package/dist/esm/mini-app/miniAppThemeConfig.js +0 -40
- package/dist/esm/types/src/docs/pages/MiniAppRootPage.d.ts +0 -1
- package/dist/esm/types/src/mini-app/MiniAppRoot.d.ts +0 -18
- package/dist/esm/types/src/mini-app/index.d.ts +0 -10
- package/dist/esm/types/src/mini-app/miniAppChatBridge.d.ts +0 -6
- package/dist/esm/types/src/mini-app/miniAppDataClient.d.ts +0 -16
- package/dist/esm/types/src/mini-app/miniAppProtocol.d.ts +0 -89
- package/dist/esm/types/src/mini-app/miniAppThemeConfig.d.ts +0 -3
- package/docs/workspace-mini-apps.md +0 -51
- package/src/docs/pages/MiniAppRootPage.tsx +0 -58
- package/src/mini-app/MiniAppRoot.styl +0 -24
- package/src/mini-app/MiniAppRoot.tsx +0 -150
- package/src/mini-app/index.ts +0 -43
- package/src/mini-app/miniAppChatBridge.ts +0 -55
- package/src/mini-app/miniAppDataClient.ts +0 -165
- package/src/mini-app/miniAppProtocol.ts +0 -247
- package/src/mini-app/miniAppThemeConfig.ts +0 -45
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type SidebarDatasetsItemsGroupBy, type SidebarDatasetsItemsGroupedDataset } from './groupSidebarDatasets';
|
|
2
|
+
export type SidebarDatasetsItemsGroupedProps = {
|
|
3
|
+
groupBy: SidebarDatasetsItemsGroupBy;
|
|
4
|
+
datasets: SidebarDatasetsItemsGroupedDataset[];
|
|
5
|
+
selectedDatasetId?: number;
|
|
6
|
+
onDatasetClick?: (datasetId: number) => void;
|
|
7
|
+
/** When omitted, all groups start expanded. */
|
|
8
|
+
defaultExpandedGroupNames?: string[];
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function SidebarDatasetsItemsGrouped({ groupBy, datasets, selectedDatasetId, onDatasetClick, defaultExpandedGroupNames, className, }: SidebarDatasetsItemsGroupedProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SybilionDatasetSnapshot } from '#uilib/types/sybilionDatasetSnapshots';
|
|
2
|
+
export type SidebarDatasetsItemsGroupedDataset = SybilionDatasetSnapshot;
|
|
3
|
+
export type SidebarDatasetsItemsGroupBy = 'target_type' | 'regions' | 'categories';
|
|
4
|
+
export type GroupedSidebarDatasetsEntry = readonly [
|
|
5
|
+
groupName: string,
|
|
6
|
+
datasets: SidebarDatasetsItemsGroupedDataset[]
|
|
7
|
+
];
|
|
8
|
+
export declare function groupSidebarDatasets(datasets: SidebarDatasetsItemsGroupedDataset[], groupBy: SidebarDatasetsItemsGroupBy): GroupedSidebarDatasetsEntry[];
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { SidebarDatasetsItemsGrouped, type SidebarDatasetsItemsGroupedProps, } from './SidebarDatasetsItemsGrouped';
|
|
2
|
+
export type { GroupedSidebarDatasetsEntry, SidebarDatasetsItemsGroupBy, SidebarDatasetsItemsGroupedDataset, } from './groupSidebarDatasets';
|
|
3
|
+
export { groupSidebarDatasets } from './groupSidebarDatasets';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function NavUserHeaderPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function SidebarDatasetsItemsGroupedPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function SybilionAuthProviderPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './sybilion-auth';
|
|
2
|
+
export * from './types/sybilionDatasetSnapshots';
|
|
2
3
|
export * from './contexts/chat-context';
|
|
3
4
|
export * from './types/chat-api.types';
|
|
4
5
|
export * from './components/ui/AnalysesSelector';
|
|
@@ -30,6 +31,7 @@ export * from './components/ui/LabelWithId';
|
|
|
30
31
|
export * from './components/ui/LegacyPlatformLink';
|
|
31
32
|
export * from './components/ui/Logo';
|
|
32
33
|
export * from './components/ui/MobileAdaptiveSelector';
|
|
34
|
+
export * from './components/ui/NavUserHeader';
|
|
33
35
|
export * from './components/ui/NumberControl';
|
|
34
36
|
export * from './components/ui/Page';
|
|
35
37
|
export * from './components/ui/Progress';
|
|
@@ -53,3 +55,4 @@ export * from './components/ui/Toggle';
|
|
|
53
55
|
export * from './components/ui/ToggleGroup';
|
|
54
56
|
export * from './components/ui/Tooltip';
|
|
55
57
|
export * from './components/ui/VimeoEmbed';
|
|
58
|
+
export * from './components/widgets/SidebarDatasetsItemsGrouped';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type RedirectLoginOptions } from '@auth0/auth0-react';
|
|
2
|
+
import type { SybilionSDK } from '@sybilion/sdk';
|
|
3
|
+
import type { JSX, ReactNode } from 'react';
|
|
4
|
+
/** Origin (`scheme://host:port`) for paths like `/api/v1/...`; derived from SDK URL layout. */
|
|
5
|
+
export declare function getSybilionApiOriginFromSdk(sdk: SybilionSDK): string;
|
|
6
|
+
export type SybilionAuthProviderProps = {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
sdk: SybilionSDK;
|
|
9
|
+
auth0Domain: string;
|
|
10
|
+
auth0ClientId: string;
|
|
11
|
+
redirectUri: string;
|
|
12
|
+
/**
|
|
13
|
+
* Defaults match sybilion-client AuthProvider (Management API audience + metadata scope).
|
|
14
|
+
* Override if your Auth0 SPA app uses a Resource Server audience for `/v1/auth/login`.
|
|
15
|
+
*/
|
|
16
|
+
authorizationParams?: {
|
|
17
|
+
audience?: string;
|
|
18
|
+
scope?: string;
|
|
19
|
+
redirect_uri?: string;
|
|
20
|
+
};
|
|
21
|
+
sybilionTokenStorageKey?: string;
|
|
22
|
+
logoutReturnTo?: string;
|
|
23
|
+
};
|
|
24
|
+
export type SybilionAuthContextValue = {
|
|
25
|
+
apiBaseUrl: string;
|
|
26
|
+
isLoading: boolean;
|
|
27
|
+
/** Auth0 authenticated and Sybilion JWT present. */
|
|
28
|
+
isAuthenticated: boolean;
|
|
29
|
+
sybilionAccessToken: string | null;
|
|
30
|
+
error: string | null;
|
|
31
|
+
loginWithRedirect: (options?: RedirectLoginOptions) => Promise<void>;
|
|
32
|
+
logout: () => void;
|
|
33
|
+
getAuth0AccessToken: () => Promise<string | undefined>;
|
|
34
|
+
getSybilionAccessToken: () => Promise<string | null>;
|
|
35
|
+
};
|
|
36
|
+
export declare function useSybilionAuth(): SybilionAuthContextValue;
|
|
37
|
+
/** fetch() relative to Sybilion API base with Bearer Sybilion JWT. */
|
|
38
|
+
export declare function sybilionApiFetch(apiBaseUrl: string, bearerToken: string, path: string, init?: RequestInit): Promise<Response>;
|
|
39
|
+
export declare function createSybilionApiFetch(apiBaseUrl: string, getSybilionAccessToken: () => Promise<string | null>): (path: string, init?: RequestInit) => Promise<Response>;
|
|
40
|
+
/** Authenticated fetch using {@link useSybilionAuth} context. */
|
|
41
|
+
export declare function useSybilionApiFetch(): (path: string, init?: RequestInit) => Promise<Response>;
|
|
42
|
+
export declare function SybilionAuthProvider({ children, sdk, auth0Domain, auth0ClientId, redirectUri, authorizationParams, sybilionTokenStorageKey, logoutReturnTo, }: SybilionAuthProviderProps): JSX.Element;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** POST `{ identity: auth0AccessToken, type: 'auth0' }` → Sybilion API JWT string. */
|
|
2
|
+
export declare function exchangeAuth0AccessTokenForSybilionJwt(
|
|
3
|
+
/** API origin only (no trailing slash), same as SDK `baseUrl`. */
|
|
4
|
+
apiBaseUrl: string, auth0AccessToken: string): Promise<string>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { SybilionAuthProviderProps, SybilionAuthContextValue, } from '#uilib/sybilion-auth/SybilionAuthProvider';
|
|
2
|
+
export { SybilionAuthProvider, getSybilionApiOriginFromSdk, useSybilionAuth, sybilionApiFetch, createSybilionApiFetch, useSybilionApiFetch, } from '#uilib/sybilion-auth/SybilionAuthProvider';
|
|
3
|
+
export { SYBILION_AUTH_LOGIN_PATH, normalizeApiBaseUrl, } from '#uilib/sybilion-auth/authPaths';
|
|
4
|
+
export { exchangeAuth0AccessTokenForSybilionJwt } from '#uilib/sybilion-auth/exchangeSybilionToken';
|
package/dist/esm/types/src/{mini-app/miniAppDataTypes.d.ts → types/sybilionDatasetSnapshots.d.ts}
RENAMED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Subset of Sybilion `Dataset` / API types — use `unknown` where payloads are large or evolving.
|
|
2
|
+
* Loose JSON shapes aligned with Sybilion dataset payloads (standalone apps / widgets).
|
|
4
3
|
*/
|
|
5
|
-
export type
|
|
4
|
+
export type SybilionDatasetSnapshot = {
|
|
6
5
|
id: number;
|
|
7
6
|
user_id?: number;
|
|
8
7
|
name: string;
|
|
@@ -34,14 +33,12 @@ export type MiniAppDataset = {
|
|
|
34
33
|
version?: number;
|
|
35
34
|
};
|
|
36
35
|
/** `forecastData` slice: analysis id (string) → forecast series blob. */
|
|
37
|
-
export type
|
|
38
|
-
export type
|
|
39
|
-
/** Cached Performance-tab API payload, or null if user never opened Performance / cache empty. */
|
|
36
|
+
export type SybilionForecastMap = Record<string, unknown>;
|
|
37
|
+
export type SybilionPerformanceSnapshot = {
|
|
40
38
|
table: unknown;
|
|
41
|
-
/** In-memory spaghetti lines from shell context, or null. */
|
|
42
39
|
spaghetti: unknown;
|
|
43
40
|
};
|
|
44
|
-
export type
|
|
41
|
+
export type SybilionDriversComparisonSnapshot = {
|
|
45
42
|
byRegion: unknown;
|
|
46
43
|
byCountry: unknown;
|
|
47
44
|
byCategory: unknown;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Standalone Sybilion apps (@sybilion/uilib)
|
|
2
|
+
|
|
3
|
+
Greenfield SPA on **your own origin**: `@sybilion/uilib` for layout/UI, **SybilionAuthProvider** + Sybilion API for data—no iframe in the main client.
|
|
4
|
+
|
|
5
|
+
**Agents / humans:** Use `AppShell` + `AppShellMainContent`; stick to uilib spacing primitives (e.g. `Gap`) instead of ad hoc root horizontal gutters.
|
|
6
|
+
|
|
7
|
+
## 1. Dependencies and global CSS
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yarn add react react-dom react-router-dom @auth0/auth0-react @sybilion/uilib @sybilion/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Import tokens/fonts once:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import '@sybilion/uilib/standalone-global.css';
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. Layout (AppShell)
|
|
20
|
+
|
|
21
|
+
### Minimal example
|
|
22
|
+
|
|
23
|
+
`AppHeaderHost` is the empty header bar; put triggers and `NavUserHeader` (a.k.a. the user / account menu) inside `AppHeaderPortal` so they render in that bar.
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import type { ReactNode } from 'react';
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
AppHeaderHost,
|
|
30
|
+
AppHeaderPortal,
|
|
31
|
+
AppShell,
|
|
32
|
+
AppShellMainContent,
|
|
33
|
+
Gap,
|
|
34
|
+
NavUserHeader,
|
|
35
|
+
PageFooter,
|
|
36
|
+
PageScroll,
|
|
37
|
+
} from '@sybilion/uilib';
|
|
38
|
+
|
|
39
|
+
export function AppLayout({ children }: { children: ReactNode }) {
|
|
40
|
+
return (
|
|
41
|
+
<PageScroll>
|
|
42
|
+
<AppShell>
|
|
43
|
+
{/* Optional: sidebar as a sibling before main, e.g. <Sidebar … /> */}
|
|
44
|
+
<AppShellMainContent
|
|
45
|
+
header={<AppHeaderHost />}
|
|
46
|
+
footer={<PageFooter versionLink="/releases" versionLabel="0.0.0" />}
|
|
47
|
+
>
|
|
48
|
+
<AppHeaderPortal>
|
|
49
|
+
<Gap />
|
|
50
|
+
<NavUserHeader
|
|
51
|
+
theme="light"
|
|
52
|
+
onThemeToggle={() => undefined}
|
|
53
|
+
onLogout={() => undefined}
|
|
54
|
+
isAuthenticated={false}
|
|
55
|
+
/>
|
|
56
|
+
</AppHeaderPortal>
|
|
57
|
+
{children}
|
|
58
|
+
</AppShellMainContent>
|
|
59
|
+
</AppShell>
|
|
60
|
+
</PageScroll>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Wire `NavUserHeader` to real auth (`useSybilionAuth`, theme context, etc.). Demo page in repo: `src/docs/pages/NavUserHeaderPage.tsx` (slug `nav-user-header`).
|
|
66
|
+
|
|
67
|
+
### Full pattern
|
|
68
|
+
|
|
69
|
+
Reference: `[src/docs/DocsShell.tsx](https://github.com/Mir-Insight/uilib/blob/main/src/docs/DocsShell.tsx)` — `PageScroll` → `AppShell` → sidebar → `AppShellMainContent` with `AppHeaderHost`, `PageFooter`, and routed body (`Outlet`). Add `Theme` and optional `SidebarProvider` from `@homecode/ui`.
|
|
70
|
+
|
|
71
|
+
### Glossary (high-use pieces)
|
|
72
|
+
|
|
73
|
+
| Component / API | What it is for |
|
|
74
|
+
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `**PageScroll**` | Page-level vertical scroll wrapper; usual outer shell for the app body. |
|
|
76
|
+
| `**AppShell**` | Layout grid container; typically holds a sidebar (optional) + main column. |
|
|
77
|
+
| `**AppShellMainContent**` | Main column with slots: `header`, scrollable body (`children`), `footer`. |
|
|
78
|
+
| `**AppHeaderHost**` | Renders the top header anchor (DOM id `page-header`); stays empty on purpose. |
|
|
79
|
+
| `**AppHeaderPortal**` | Portals children into `AppHeaderHost` — put header actions, `NavUserHeader`, theme toggle here. |
|
|
80
|
+
| `**NavUserHeader**` | Header user menu: avatar, account dropdown, theme row, logout; **not** a bare `DropdownMenu`. |
|
|
81
|
+
| `**Sidebar`\*\* | Collapsible app sidebar / nav rail (pair with `SidebarProvider` from `@homecode/ui` when needed). |
|
|
82
|
+
| `**PageFooter**` | Standard app footer (logo, links, version badge). Requires `versionLink` + `versionLabel`. |
|
|
83
|
+
| `**Gap**` | Horizontal or vertical spacing primitive between flex children (prefer over raw margins). |
|
|
84
|
+
| `**SybilionAuthProvider**` | Auth0 + Sybilion JWT bootstrap for the whole app (see §3). |
|
|
85
|
+
| `**useSybilionAuth**` | Current user, tokens, login/logout inside the provider tree. |
|
|
86
|
+
| `**useSybilionApiFetch**` | Authenticated `fetch` to the Sybilion API using the stored JWT. |
|
|
87
|
+
| `**Breadcrumb**`, `**BreadcrumbList`, …\*\* | Accessible breadcrumb trail for the page header (compose `BreadcrumbItem` / `BreadcrumbLink` / `BreadcrumbPage`). |
|
|
88
|
+
| `**Button`**, `**Card\*\*` | Primary actions and grouped content blocks—default building blocks for screens inside the layout body. |
|
|
89
|
+
|
|
90
|
+
## 3. Auth (`SybilionAuthProvider`)
|
|
91
|
+
|
|
92
|
+
Use inside `BrowserRouter` if redirects hit a callback route.
|
|
93
|
+
|
|
94
|
+
Env vars depend on bundler—for **Vite** only `import.meta.env.VITE_` is exposed client-side:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { useMemo, type ReactNode } from 'react';
|
|
98
|
+
|
|
99
|
+
import { SybilionAuthProvider } from '@sybilion/uilib';
|
|
100
|
+
import { createSybilionSDK } from '@sybilion/sdk';
|
|
101
|
+
|
|
102
|
+
const sybilionJwtKey = 'sybilion.standalone.jwt';
|
|
103
|
+
|
|
104
|
+
export function AppProviders({ children }: { children: ReactNode }) {
|
|
105
|
+
const apiBaseUrl = import.meta.env.VITE_SYBILION_API_BASE_URL as string;
|
|
106
|
+
const auth0Domain = import.meta.env.VITE_AUTH0_DOMAIN as string;
|
|
107
|
+
const auth0ClientId = import.meta.env.VITE_AUTH0_CLIENT_ID as string;
|
|
108
|
+
|
|
109
|
+
const sdk = useMemo(
|
|
110
|
+
() =>
|
|
111
|
+
createSybilionSDK({
|
|
112
|
+
baseUrl: apiBaseUrl,
|
|
113
|
+
apiPrefix: '/api',
|
|
114
|
+
getToken: () =>
|
|
115
|
+
typeof localStorage !== 'undefined'
|
|
116
|
+
? localStorage.getItem(sybilionJwtKey) ?? undefined
|
|
117
|
+
: undefined,
|
|
118
|
+
}),
|
|
119
|
+
[apiBaseUrl],
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<SybilionAuthProvider
|
|
124
|
+
sdk={sdk}
|
|
125
|
+
sybilionTokenStorageKey={sybilionJwtKey}
|
|
126
|
+
auth0Domain={auth0Domain}
|
|
127
|
+
auth0ClientId={auth0ClientId}
|
|
128
|
+
redirectUri={window.location.origin}
|
|
129
|
+
>
|
|
130
|
+
{children}
|
|
131
|
+
</SybilionAuthProvider>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Flow:** Auth0 SPA → `sdk.auth.loginWithAuth0Identity(<Auth0 AT>)` → Sybilion JWT (`data.token` / `token`) persisted → same `sdk` + `getToken` supply Bearer on API calls; `useSybilionApiFetch()` uses `getSybilionApiOriginFromSdk(sdk)` for URLs (paths like `/api/v1/...`).
|
|
137
|
+
|
|
138
|
+
**Defaults** for `authorizationParams` match sybilion-client (Management audience + `openid profile email offline_access …`); override if your Auth0 SPA needs a Resource Server audience (backend confirms).
|
|
139
|
+
|
|
140
|
+
| Layer | Configure |
|
|
141
|
+
| ---------------- | ------------------------------------------------------------------------------------- |
|
|
142
|
+
| **Auth0** | Callback, logout, and web origins → your URLs (+ previews). |
|
|
143
|
+
| **Sybilion API** | CORS → your deploy `Origin`. |
|
|
144
|
+
| **App** | `createSybilionSDK` (`baseUrl`, `apiPrefix`), pass **`sdk`** to `SybilionAuthProvider`; align `sybilionTokenStorageKey` with `getToken`; Auth0 `domain` / `clientId`; redirect usually `window.location.origin`. |
|
|
145
|
+
|
|
146
|
+
**Hooks:** `useSybilionAuth()`, `useSybilionApiFetch()` (or `createSybilionApiFetch` / `sybilionApiFetch` helpers).
|
|
147
|
+
|
|
148
|
+
## 4. Data
|
|
149
|
+
|
|
150
|
+
Fetch the Sybilion API with the JWT above (e.g. via `useSybilionApiFetch`).
|
|
151
|
+
|
|
152
|
+
### `@sybilion/sdk`
|
|
153
|
+
|
|
154
|
+
Install the typed client alongside uilib:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
yarn add @sybilion/sdk
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Configure **`createSybilionSDK`** with the same instance you pass to **`SybilionAuthProvider`** (`sdk` prop). Use **`baseUrl`**: API origin only (no trailing slash), default **`apiPrefix: '/api'`** so requests hit `{baseUrl}/api/v1/...`. **`getToken`** should read the same storage key as **`sybilionTokenStorageKey`** on the provider (default `sybilion.standalone.jwt`).
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { createSybilionSDK } from '@sybilion/sdk';
|
|
164
|
+
|
|
165
|
+
const sdk = createSybilionSDK({
|
|
166
|
+
baseUrl: apiBaseUrl,
|
|
167
|
+
apiPrefix: '/api',
|
|
168
|
+
getToken: () => localStorage.getItem('sybilion.standalone.jwt') ?? undefined,
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- **`sdk.auth`** — `loginWithAuth0Identity`, `getMe`, `updateMe` (Auth0 bootstrap + user profile).
|
|
173
|
+
- **`sdk.raw`** — thin `GET`/`POST`/… wrappers for `/v1/...` paths (e.g. `raw.analyses.driversMapOnce`; returns parsed JSON, no app-specific shaping).
|
|
174
|
+
- **`sdk.resources`** — higher-level helpers (datasets, drivers, subscriptions) that compose `raw` calls with parsing where applicable.
|
|
175
|
+
|
|
176
|
+
See the package README: [`@sybilion/sdk`](https://www.npmjs.com/package/@sybilion/sdk) — in this monorepo, [`../../sdk/README.md`](../../sdk/README.md).
|
|
177
|
+
|
|
178
|
+
## Related
|
|
179
|
+
|
|
180
|
+
- [auth0-configuration-guide.md](https://github.com/Mir-Insight/sybilion-client/blob/main/docs/auth0-configuration-guide.md)
|
|
181
|
+
- [server-auth-verification.md](https://github.com/Mir-Insight/sybilion-client/blob/main/docs/server-auth-verification.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sybilion/uilib",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Sybilion Design System — React UI components (Webpack + Stylus)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"default": "./src/index.ts"
|
|
31
31
|
},
|
|
32
32
|
"./src/*": "./src/*",
|
|
33
|
-
"./
|
|
33
|
+
"./standalone-global.css": "./assets/standalone-global.css"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"assets",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
},
|
|
77
77
|
"homepage": "https://github.com/Mir-Insight/uilib#readme",
|
|
78
78
|
"dependencies": {
|
|
79
|
+
"@homecode/ui": "^4.17.0",
|
|
79
80
|
"@phosphor-icons/react": "^2.1.10",
|
|
80
81
|
"@radix-ui/react-avatar": "^1.1.10",
|
|
81
82
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
@@ -104,12 +105,23 @@
|
|
|
104
105
|
"vaul": "^1.1.2"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
|
-
"@
|
|
108
|
+
"@auth0/auth0-react": "^2.3.1",
|
|
109
|
+
"@sybilion/sdk": ">=0.0.1",
|
|
108
110
|
"react": ">=18.0.0",
|
|
109
111
|
"react-dom": ">=18.0.0",
|
|
110
112
|
"react-router-dom": ">=6.0.0"
|
|
111
113
|
},
|
|
114
|
+
"peerDependenciesMeta": {
|
|
115
|
+
"@auth0/auth0-react": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"@sybilion/sdk": {
|
|
119
|
+
"optional": true
|
|
120
|
+
}
|
|
121
|
+
},
|
|
112
122
|
"devDependencies": {
|
|
123
|
+
"@auth0/auth0-react": "^2.3.1",
|
|
124
|
+
"@sybilion/sdk": "file:../sdk",
|
|
113
125
|
"@babel/core": "^7.20.12",
|
|
114
126
|
"@babel/preset-typescript": "^7.21.0",
|
|
115
127
|
"@homecode/ui": "^4.30.6",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
.loadingButton
|
|
2
|
+
gap 0.5rem
|
|
3
|
+
|
|
4
|
+
.avatarSkeleton
|
|
5
|
+
height 2rem
|
|
6
|
+
width 2rem
|
|
7
|
+
border-radius 9999px
|
|
8
|
+
background-color var(--color-muted)
|
|
9
|
+
animation pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite
|
|
10
|
+
|
|
11
|
+
.textSkeleton
|
|
12
|
+
height 1rem
|
|
13
|
+
width 5rem
|
|
14
|
+
border-radius 0.25rem
|
|
15
|
+
background-color var(--color-muted)
|
|
16
|
+
animation pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite
|
|
17
|
+
|
|
18
|
+
.loginButton
|
|
19
|
+
gap 0.5rem
|
|
20
|
+
|
|
21
|
+
.iconLg
|
|
22
|
+
height 1.25rem
|
|
23
|
+
width 1.25rem
|
|
24
|
+
|
|
25
|
+
.iconSm
|
|
26
|
+
height 0.75rem
|
|
27
|
+
width 0.75rem
|
|
28
|
+
|
|
29
|
+
.menuIcon
|
|
30
|
+
margin-right 0.5rem
|
|
31
|
+
height 1rem
|
|
32
|
+
width 1rem
|
|
33
|
+
|
|
34
|
+
.dropdownContent
|
|
35
|
+
width 14rem
|
|
36
|
+
|
|
37
|
+
.userButton
|
|
38
|
+
gap 0.5rem
|
|
39
|
+
height 52px
|
|
40
|
+
padding var(--p-2)
|
|
41
|
+
|
|
42
|
+
&.compact
|
|
43
|
+
padding 0
|
|
44
|
+
background-color transparent !important
|
|
45
|
+
transition transform 0.2s ease-in-out
|
|
46
|
+
|
|
47
|
+
&:hover
|
|
48
|
+
transform scale(1.1)
|
|
49
|
+
|
|
50
|
+
.avatar
|
|
51
|
+
height 2rem
|
|
52
|
+
width 2rem
|
|
53
|
+
|
|
54
|
+
.avatarImage
|
|
55
|
+
width 100%
|
|
56
|
+
height 100%
|
|
57
|
+
object-fit cover
|
|
58
|
+
border-radius inherit
|
|
59
|
+
|
|
60
|
+
.avatarFallback
|
|
61
|
+
background-color var(--color-primary)
|
|
62
|
+
color var(--color-primary-foreground)
|
|
63
|
+
background url('./avatar.svg') no-repeat center center
|
|
64
|
+
width 100%
|
|
65
|
+
height 100%
|
|
66
|
+
border-radius inherit
|
|
67
|
+
|
|
68
|
+
.userInfo
|
|
69
|
+
display flex
|
|
70
|
+
flex-direction column
|
|
71
|
+
align-items flex-start
|
|
72
|
+
text-align left
|
|
73
|
+
gap 0.25rem
|
|
74
|
+
|
|
75
|
+
.userName
|
|
76
|
+
font-size var(--text-sm)
|
|
77
|
+
font-weight 400
|
|
78
|
+
line-height 1
|
|
79
|
+
text-overflow ellipsis
|
|
80
|
+
overflow hidden
|
|
81
|
+
white-space nowrap
|
|
82
|
+
max-width 7.5rem
|
|
83
|
+
|
|
84
|
+
.userEmail
|
|
85
|
+
font-size var(--text-xs)
|
|
86
|
+
color var(--sb-slate-500)
|
|
87
|
+
line-height 1
|
|
88
|
+
|
|
89
|
+
.userLabel
|
|
90
|
+
padding 0
|
|
91
|
+
font-weight normal
|
|
92
|
+
|
|
93
|
+
.userLabelContent
|
|
94
|
+
display flex
|
|
95
|
+
align-items center
|
|
96
|
+
gap 0.5rem
|
|
97
|
+
padding 0.5rem
|
|
98
|
+
text-align left
|
|
99
|
+
font-size 0.875rem
|
|
100
|
+
|
|
101
|
+
.userDetails
|
|
102
|
+
display grid
|
|
103
|
+
flex 1
|
|
104
|
+
text-align left
|
|
105
|
+
font-size 0.875rem
|
|
106
|
+
line-height 1.25
|
|
107
|
+
|
|
108
|
+
.userDetailName
|
|
109
|
+
text-overflow ellipsis
|
|
110
|
+
overflow hidden
|
|
111
|
+
white-space nowrap
|
|
112
|
+
font-weight 500
|
|
113
|
+
|
|
114
|
+
.userDetailEmail
|
|
115
|
+
color var(--color-muted-foreground)
|
|
116
|
+
text-overflow ellipsis
|
|
117
|
+
overflow hidden
|
|
118
|
+
white-space nowrap
|
|
119
|
+
font-size 0.75rem
|
|
120
|
+
|
|
121
|
+
@keyframes pulse
|
|
122
|
+
0%, 100%
|
|
123
|
+
opacity 1
|
|
124
|
+
50%
|
|
125
|
+
opacity 0.5
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// This file is automatically generated.
|
|
2
|
+
// Please do not change this file!
|
|
3
|
+
interface CssExports {
|
|
4
|
+
'avatar': string;
|
|
5
|
+
'avatarFallback': string;
|
|
6
|
+
'avatarImage': string;
|
|
7
|
+
'avatarSkeleton': string;
|
|
8
|
+
'compact': string;
|
|
9
|
+
'dropdownContent': string;
|
|
10
|
+
'iconLg': string;
|
|
11
|
+
'iconSm': string;
|
|
12
|
+
'loadingButton': string;
|
|
13
|
+
'loginButton': string;
|
|
14
|
+
'menuIcon': string;
|
|
15
|
+
'pulse': string;
|
|
16
|
+
'textSkeleton': string;
|
|
17
|
+
'userButton': string;
|
|
18
|
+
'userDetailEmail': string;
|
|
19
|
+
'userDetailName': string;
|
|
20
|
+
'userDetails': string;
|
|
21
|
+
'userEmail': string;
|
|
22
|
+
'userInfo': string;
|
|
23
|
+
'userLabel': string;
|
|
24
|
+
'userLabelContent': string;
|
|
25
|
+
'userName': string;
|
|
26
|
+
}
|
|
27
|
+
export const cssExports: CssExports;
|
|
28
|
+
export default cssExports;
|