@pablo2410/shared-ui 0.3.2

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 ADDED
@@ -0,0 +1,93 @@
1
+ # @oplytics/shared-ui
2
+
3
+ Shared UI component library for all **Oplytics.digital** subdomains. Provides standardised layouts, hierarchy management, RBAC, reporting, hooks, and design tokens as reusable building blocks.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @oplytics/shared-ui
9
+ ```
10
+
11
+ > Requires `.npmrc` with `@oplytics:registry=https://npm.pkg.github.com`
12
+
13
+ ## Modules
14
+
15
+ | Module | Import | Description |
16
+ |--------|--------|-------------|
17
+ | **Layout** | `@oplytics/shared-ui/layout` | Config-driven sidebar, page header, footer, layout factory |
18
+ | **Hierarchy** | `@oplytics/shared-ui/hierarchy` | Org hierarchy types, selection state, enterprise override |
19
+ | **RBAC** | `@oplytics/shared-ui/rbac` | 7-role model, permission checks, error constants |
20
+ | **Reporting** | `@oplytics/shared-ui/reporting` | Incident reporting and feedback toolbar types/config |
21
+ | **Components** | `@oplytics/shared-ui/components` | SharedFooter, NotFound, ErrorBoundary, ViewOnlyBadge types |
22
+ | **Hooks** | `@oplytics/shared-ui/hooks` | useMobile, useComposition, usePersistFn |
23
+ | **Theme** | `@oplytics/shared-ui/theme` | Design tokens, color palette, typography, CSS variables |
24
+
25
+ ## Quick Start
26
+
27
+ ```tsx
28
+ // RBAC — check permissions
29
+ import { hasMinimumRole, ALL_ROLES } from '@oplytics/shared-ui/rbac';
30
+
31
+ if (hasMinimumRole(user.role, 'enterprise_admin')) {
32
+ // show admin features
33
+ }
34
+
35
+ // Hierarchy — enterprise override
36
+ import { applyEnterpriseOverride } from '@oplytics/shared-ui/hierarchy';
37
+
38
+ const resolvedUser = applyEnterpriseOverride(user, req.headers.cookie);
39
+
40
+ // Layout — service config
41
+ import { SERVICE_CONFIGS, defineServiceLayout } from '@oplytics/shared-ui/layout';
42
+
43
+ const myConfig = SERVICE_CONFIGS.sqdcp;
44
+
45
+ // Theme — design tokens
46
+ import { OPLYTICS_COLORS, OPLYTICS_FONTS } from '@oplytics/shared-ui/theme';
47
+
48
+ // Hooks
49
+ import { useMobile, usePersistFn } from '@oplytics/shared-ui/hooks';
50
+ ```
51
+
52
+ ## Theme CSS
53
+
54
+ Import the canonical Oplytics theme variables:
55
+
56
+ ```css
57
+ @import '@oplytics/shared-ui/theme/oplytics-theme.css';
58
+ ```
59
+
60
+ This provides all `--oplytics-*` CSS custom properties for backgrounds, text, accents, borders, spacing, radius, and shadows.
61
+
62
+ ## Development
63
+
64
+ ```bash
65
+ pnpm install
66
+ pnpm build # Build with tsup
67
+ pnpm test # Run vitest
68
+ pnpm typecheck # TypeScript check
69
+ ```
70
+
71
+ ## Architecture
72
+
73
+ The package is tree-shakeable with separate entry points per module. Each subdomain only imports what it needs:
74
+
75
+ ```
76
+ src/
77
+ layout/ # SharedSidebar, createServiceLayout, serviceConfigs
78
+ hierarchy/ # orgHierarchy types, enterpriseOverride
79
+ rbac/ # Roles, permissions, error constants
80
+ reporting/ # ReportingToolbar types and config
81
+ components/ # SharedFooter, NotFound, ErrorBoundary types
82
+ hooks/ # useMobile, useComposition, usePersistFn
83
+ theme/ # Design tokens, CSS variables
84
+ ```
85
+
86
+ ## Versioning
87
+
88
+ - **v0.x** — Types, configs, and pure utilities (no React component rendering)
89
+ - **v1.0** — Full React components with shadcn/ui primitives bundled
90
+
91
+ ## License
92
+
93
+ UNLICENSED — Internal Oplytics.digital use only.
@@ -0,0 +1,11 @@
1
+ // src/utils/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export {
9
+ cn
10
+ };
11
+ //# sourceMappingURL=chunk-JT3XLKKD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
@@ -0,0 +1,152 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { Component, ReactNode, ErrorInfo } from 'react';
4
+
5
+ interface ErrorBoundaryProps {
6
+ /** Fallback UI to show when an error is caught. If not provided, uses the default Oplytics error UI. */
7
+ fallback?: ReactNode;
8
+ /** Error handler callback — use for logging/reporting */
9
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
10
+ /** Children to wrap */
11
+ children: ReactNode;
12
+ /** CSS class for the fallback container */
13
+ className?: string;
14
+ }
15
+ interface ErrorBoundaryState {
16
+ hasError: boolean;
17
+ error: Error | null;
18
+ }
19
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
20
+ constructor(props: ErrorBoundaryProps);
21
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
22
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
23
+ handleRetry: () => void;
24
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
25
+ }
26
+
27
+ interface NotFoundPageProps {
28
+ /** Title text (default: "Page Not Found") */
29
+ title?: string;
30
+ /** Description text */
31
+ description?: string;
32
+ /** Home path to navigate to (default: "/") */
33
+ homePath?: string;
34
+ /** Back button handler (default: window.history.back) */
35
+ onBack?: () => void;
36
+ /** Home button handler — if provided, overrides the <a> link */
37
+ onHome?: () => void;
38
+ /** CSS class for the container */
39
+ className?: string;
40
+ }
41
+ declare function NotFoundPage({ title, description, homePath, onBack, onHome, className, }: NotFoundPageProps): react_jsx_runtime.JSX.Element;
42
+
43
+ interface ManusDialogProps {
44
+ /** Whether the dialog is open */
45
+ open: boolean;
46
+ /** Close handler */
47
+ onClose: () => void;
48
+ /** Dialog title */
49
+ title: string;
50
+ /** Optional subtitle */
51
+ subtitle?: string;
52
+ /** Optional logo/icon to show in the header */
53
+ logo?: string | ReactNode;
54
+ /** Dialog content */
55
+ children: ReactNode;
56
+ /** Footer content (e.g. action buttons) */
57
+ footer?: ReactNode;
58
+ /** Max width class (default: "max-w-md") */
59
+ maxWidth?: string;
60
+ /** CSS class for the dialog panel */
61
+ className?: string;
62
+ /** Whether clicking the overlay closes the dialog (default: true) */
63
+ closeOnOverlay?: boolean;
64
+ }
65
+ declare function ManusDialog({ open, onClose, title, subtitle, logo, children, footer, maxWidth, className, closeOnOverlay, }: ManusDialogProps): react_jsx_runtime.JSX.Element;
66
+
67
+ interface ChatMessage {
68
+ id: string;
69
+ role: "user" | "assistant" | "system";
70
+ content: string;
71
+ timestamp: number;
72
+ /** Whether the message is still streaming */
73
+ isStreaming?: boolean;
74
+ }
75
+ interface AIChatBoxProps {
76
+ /** Chat messages to display */
77
+ messages: ChatMessage[];
78
+ /** Handler when user sends a message */
79
+ onSend: (message: string) => void;
80
+ /** Whether the assistant is currently generating a response */
81
+ isLoading?: boolean;
82
+ /** Placeholder text for the input */
83
+ placeholder?: string;
84
+ /** Title for the chat header */
85
+ title?: string;
86
+ /** Whether to show the chat in a floating panel (default: false — inline) */
87
+ floating?: boolean;
88
+ /** Whether the floating panel is open */
89
+ isOpen?: boolean;
90
+ /** Toggle floating panel open/closed */
91
+ onToggle?: () => void;
92
+ /** Render prop for message content (e.g. to use Streamdown for markdown) */
93
+ renderContent?: (content: string, isStreaming?: boolean) => ReactNode;
94
+ /** Max height for the messages area (default: "400px") */
95
+ maxHeight?: string;
96
+ /** CSS class for the container */
97
+ className?: string;
98
+ /** Whether to show the header (default: true) */
99
+ showHeader?: boolean;
100
+ }
101
+ declare function AIChatBox({ messages, onSend, isLoading, placeholder, title, floating, isOpen, onToggle, renderContent, maxHeight, className, showHeader, }: AIChatBoxProps): react_jsx_runtime.JSX.Element;
102
+
103
+ /**
104
+ * MapView — Google Maps integration with Manus proxy authentication.
105
+ *
106
+ * Provides a MapView component with onMapReady callback for initialising
107
+ * Google Maps services (Places, Geocoder, Directions, Drawing, etc.).
108
+ * All map functionality works directly in the browser via the Manus proxy.
109
+ *
110
+ * Usage:
111
+ * <MapView
112
+ * apiKey={import.meta.env.VITE_FRONTEND_FORGE_API_KEY}
113
+ * forgeBaseUrl={import.meta.env.VITE_FRONTEND_FORGE_API_URL}
114
+ * initialCenter={{ lat: 40.7128, lng: -74.0060 }}
115
+ * initialZoom={15}
116
+ * onMapReady={(map) => { mapRef.current = map; }}
117
+ * />
118
+ */
119
+ declare global {
120
+ interface Window {
121
+ google?: typeof google;
122
+ }
123
+ }
124
+ interface MapViewProps {
125
+ /** Manus Forge API key (VITE_FRONTEND_FORGE_API_KEY) */
126
+ apiKey: string;
127
+ /** Manus Forge base URL (VITE_FRONTEND_FORGE_API_URL) */
128
+ forgeBaseUrl?: string;
129
+ /** Initial map center */
130
+ initialCenter?: google.maps.LatLngLiteral;
131
+ /** Initial zoom level */
132
+ initialZoom?: number;
133
+ /** Callback when the map is ready — use to store ref and initialise services */
134
+ onMapReady?: (map: google.maps.Map) => void;
135
+ /** Map ID for cloud-based map styling */
136
+ mapId?: string;
137
+ /** CSS class for the map container */
138
+ className?: string;
139
+ }
140
+ declare function MapView({ apiKey, forgeBaseUrl, initialCenter, initialZoom, onMapReady, mapId, className, }: MapViewProps): react_jsx_runtime.JSX.Element;
141
+
142
+ interface ViewOnlyBadgeProps {
143
+ /** Custom label (default: "View Only") */
144
+ label?: string;
145
+ /** Size variant */
146
+ size?: "sm" | "md";
147
+ /** CSS class */
148
+ className?: string;
149
+ }
150
+ declare function ViewOnlyBadge({ label, size, className, }: ViewOnlyBadgeProps): react_jsx_runtime.JSX.Element;
151
+
152
+ export { AIChatBox, type AIChatBoxProps, type ChatMessage, ErrorBoundary, type ErrorBoundaryProps, ManusDialog, type ManusDialogProps, MapView, type MapViewProps, NotFoundPage, type NotFoundPageProps, ViewOnlyBadge, type ViewOnlyBadgeProps };