@nubase/frontend 0.1.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 ADDED
@@ -0,0 +1,127 @@
1
+ # @nubase/frontend
2
+
3
+ React components and utilities for the nubase ecosystem.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nubase/frontend @nubase/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { SchemaForm } from '@nubase/frontend';
15
+ import { nu, type Infer } from '@nubase/core';
16
+ import '@nubase/frontend/styles.css'; // Import base styles
17
+
18
+ // Define your schema - fields are required by default
19
+ const userSchema = nu.object({
20
+ name: nu.string().withMeta({
21
+ label: "Full Name",
22
+ description: "Enter your complete name"
23
+ }),
24
+ email: nu.string().withMeta({
25
+ label: "Email Address",
26
+ description: "We'll send you updates here"
27
+ }),
28
+ phone: nu.string().optional().withMeta({
29
+ label: "Phone Number",
30
+ description: "Optional contact number"
31
+ })
32
+ });
33
+
34
+ type UserData = Infer<typeof userSchema>;
35
+
36
+ function MyComponent() {
37
+ const handleSubmit = (data: UserData) => {
38
+ console.log('Form data:', data);
39
+ // data is properly typed with required/optional fields
40
+ };
41
+
42
+ return (
43
+ <SchemaForm
44
+ schema={userSchema}
45
+ onSubmit={handleSubmit}
46
+ submitText="Create Account"
47
+ />
48
+ );
49
+ }
50
+ ```
51
+
52
+ ### Required vs Optional Fields
53
+
54
+ The `SchemaForm` component automatically:
55
+ - Shows **asterisks (*)** for required fields
56
+ - Validates required fields on submit
57
+ - Allows optional fields to be left empty
58
+
59
+ ```typescript
60
+ const contactSchema = nu.object({
61
+ name: nu.string(), // Required - shows *
62
+ email: nu.string(), // Required - shows *
63
+ phone: nu.string().optional(), // Optional - no *
64
+ notes: nu.string().optional(), // Optional - no *
65
+ });
66
+ ```
67
+
68
+ ## Styling
69
+
70
+ The package includes CSS files that you can import:
71
+
72
+ ```typescript
73
+ // Base component styles
74
+ import '@nubase/frontend/styles.css';
75
+
76
+ // Theme styles (optional)
77
+ import '@nubase/react/theme.css';
78
+ ```
79
+
80
+ ## Components
81
+
82
+ ### Form Components
83
+ - `SchemaForm` - Schema-driven form with automatic field rendering and validation
84
+ - `FormFieldRenderer` - Renders individual form fields based on schema type
85
+
86
+ ### Form Controls
87
+ - `FormControl` - Form field wrapper with label, validation, and error display
88
+ - `TextInput` - Text input with validation states and accessibility
89
+ - `Label` - Form labels with required field indicators
90
+
91
+ ### Button System
92
+ - `Button` - Primary button component with 5 variants and 4 sizes
93
+ - `ButtonBar` - Button container with flexible alignment options
94
+
95
+ ### Floating UI
96
+ - `Dialog` - Confirmation dialogs with promise-based API
97
+ - `Modal` - Multi-size modals with backdrop and stacking support
98
+ - `Toast` - Toast notifications with 6 types including promise toasts
99
+
100
+ ### Navigation
101
+ - `MainNav` - Hierarchical navigation with search and badges
102
+ - `NubaseApp` - Application shell with router integration
103
+
104
+ ### Theming
105
+ - Material Design 3 theming system with 26 semantic color roles
106
+ - Runtime theme switching with CSS variables
107
+ - 4 built-in themes: Light, Dark, Light High Contrast, Dark High Contrast
108
+
109
+ ## Storybook
110
+
111
+ This package includes Storybook stories for component development:
112
+
113
+ ```bash
114
+ npm run storybook
115
+ ```
116
+
117
+ ## Peer Dependencies
118
+
119
+ - React 19+
120
+
121
+ ## Contributing
122
+
123
+ Please see the main repository for contributing guidelines.
124
+
125
+ ## License
126
+
127
+ MIT
package/dist/index.css ADDED
@@ -0,0 +1,50 @@
1
+ /* src/components/dock/ResizeHandle.module.css */
2
+ .interactionArea {
3
+ --handle-size: 20px;
4
+ position: absolute;
5
+ }
6
+ .interactionAreaVertical {
7
+ top: 0;
8
+ bottom: 0;
9
+ left: calc(var(--handle-size) * -0.5);
10
+ right: calc(var(--handle-size) * -0.5);
11
+ }
12
+ .interactionAreaHorizontal {
13
+ left: 0;
14
+ right: 0;
15
+ top: calc(var(--handle-size) * -0.5);
16
+ bottom: calc(var(--handle-size) * -0.5);
17
+ }
18
+ .handle {
19
+ position: absolute;
20
+ z-index: 10;
21
+ transition: all 0.2s ease;
22
+ background-color: transparent;
23
+ }
24
+ .handleVertical {
25
+ cursor: col-resize;
26
+ top: 0;
27
+ bottom: 0;
28
+ left: 50%;
29
+ width: 0;
30
+ transform: translateX(-50%);
31
+ }
32
+ .handleHorizontal {
33
+ cursor: row-resize;
34
+ left: 0;
35
+ right: 0;
36
+ top: 50%;
37
+ height: 0;
38
+ transform: translateY(-50%);
39
+ }
40
+ .handleHover {
41
+ background-color: var(--color-primary);
42
+ opacity: 0.3;
43
+ }
44
+ .handleVertical.handleHover {
45
+ width: var(--handle-size);
46
+ }
47
+ .handleHorizontal.handleHover {
48
+ height: var(--handle-size);
49
+ }
50
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/dock/ResizeHandle.module.css"],"sourcesContent":["/* ResizeHandle.module.css */\n.interactionArea {\n /*\n --handle-size controls both the visible thickness of the handle on hover\n and the invisible grab area around it.\n */\n --handle-size: 20px;\n position: absolute;\n}\n\n.interactionAreaVertical {\n top: 0;\n bottom: 0;\n /* The grab area extends on both sides by the handle size */\n left: calc(var(--handle-size) * -0.5);\n right: calc(var(--handle-size) * -0.5);\n}\n\n.interactionAreaHorizontal {\n left: 0;\n right: 0;\n /* The grab area extends on both sides by the handle size */\n top: calc(var(--handle-size) * -0.5);\n bottom: calc(var(--handle-size) * -0.5);\n}\n\n.handle {\n position: absolute;\n z-index: 10;\n transition: all 0.2s ease;\n background-color: transparent;\n}\n\n.handleVertical {\n cursor: col-resize;\n top: 0;\n bottom: 0;\n left: 50%;\n width: 0;\n transform: translateX(-50%);\n}\n\n.handleHorizontal {\n cursor: row-resize;\n left: 0;\n right: 0;\n top: 50%;\n height: 0;\n transform: translateY(-50%);\n}\n\n.handleHover {\n background-color: var(--color-primary);\n opacity: 0.3;\n}\n\n.handleVertical.handleHover {\n width: var(--handle-size);\n}\n\n.handleHorizontal.handleHover {\n height: var(--handle-size);\n}\n"],"mappings":";AACA,CAAC;AAKC,iBAAe;AACf,YAAU;AACZ;AAEA,CAAC;AACC,OAAK;AACL,UAAQ;AAER,QAAM,KAAK,IAAI,eAAe,EAAE;AAChC,SAAO,KAAK,IAAI,eAAe,EAAE;AACnC;AAEA,CAAC;AACC,QAAM;AACN,SAAO;AAEP,OAAK,KAAK,IAAI,eAAe,EAAE;AAC/B,UAAQ,KAAK,IAAI,eAAe,EAAE;AACpC;AAEA,CAAC;AACC,YAAU;AACV,WAAS;AACT,cAAY,IAAI,KAAK;AACrB,oBAAkB;AACpB;AAEA,CAAC;AACC,UAAQ;AACR,OAAK;AACL,UAAQ;AACR,QAAM;AACN,SAAO;AACP,aAAW,WAAW;AACxB;AAEA,CAAC;AACC,UAAQ;AACR,QAAM;AACN,SAAO;AACP,OAAK;AACL,UAAQ;AACR,aAAW,WAAW;AACxB;AAEA,CAAC;AACC,oBAAkB,IAAI;AACtB,WAAS;AACX;AAEA,CAvBC,cAuBc,CALd;AAMC,SAAO,IAAI;AACb;AAEA,CAlBC,gBAkBgB,CAThB;AAUC,UAAQ,IAAI;AACd;","names":[]}
@@ -0,0 +1,517 @@
1
+ import * as React$1 from 'react';
2
+ import React__default, { FC, ReactNode, RefObject } from 'react';
3
+ import { ObjectSchema, Infer, BaseSchema, SchemaMetadata, ObjectShape, Layout, LayoutField, ObjectOutput, RequestSchema, InferRequestParams, InferRequestBody, InferResponseBody } from '@nubase/core';
4
+ import { ReactFormExtendedApi, AnyFieldApi } from '@tanstack/react-form';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+ import * as class_variance_authority_types from 'class-variance-authority/types';
7
+ import { VariantProps } from 'class-variance-authority';
8
+ import { ColumnDef, SortingState, OnChangeFn } from '@tanstack/react-table';
9
+ import { ClassValue } from 'clsx';
10
+
11
+ interface DockProps {
12
+ center: React__default.ReactNode;
13
+ left?: React__default.ReactNode;
14
+ right?: React__default.ReactNode;
15
+ top?: React__default.ReactNode;
16
+ defaultLeftWidth?: number;
17
+ defaultRightWidth?: number;
18
+ }
19
+ declare const Dock: React__default.FC<DockProps>;
20
+
21
+ type SchemaFormProps<TSchema extends ObjectSchema<any>, TData extends Infer<TSchema> = Infer<TSchema>> = {
22
+ schema: TSchema;
23
+ onSubmit: (data: TData) => void | Promise<void>;
24
+ submitText?: string;
25
+ className?: string;
26
+ /** Specify which layout to use (if schema has layouts defined) */
27
+ layoutName?: string;
28
+ /** Options for computed metadata behavior */
29
+ computedMetadata?: {
30
+ /** Debounce delay in milliseconds for computed metadata updates (default: 300ms) */
31
+ debounceMs?: number;
32
+ };
33
+ };
34
+ type SchemaFormRef<TSchema extends ObjectSchema<any>> = ReactFormExtendedApi<Infer<TSchema>, any, any, any, any, any, any, any, any, any>;
35
+ declare const SchemaForm: <TSchema extends ObjectSchema<any>>(props: SchemaFormProps<TSchema> & {
36
+ ref?: React__default.Ref<SchemaFormRef<TSchema>>;
37
+ }) => React__default.ReactElement;
38
+
39
+ interface FieldApi {
40
+ name: string;
41
+ state: {
42
+ value: any;
43
+ meta: {
44
+ isValidating: boolean;
45
+ isTouched: boolean;
46
+ isValid: boolean;
47
+ errors: (string | undefined)[];
48
+ };
49
+ };
50
+ handleChange: (value: any) => void;
51
+ handleBlur: () => void;
52
+ }
53
+ interface FormFieldRendererProps {
54
+ schema: BaseSchema<any>;
55
+ fieldState: FieldApi;
56
+ metadata: SchemaMetadata<any>;
57
+ }
58
+ declare const FormFieldRenderer: React__default.FC<FormFieldRendererProps>;
59
+
60
+ interface SchemaFormLayoutProps<TShape extends ObjectShape = any> {
61
+ layout: Layout<TShape>;
62
+ renderField: (field: LayoutField<TShape>) => React__default.ReactNode;
63
+ }
64
+ declare const SchemaFormLayout: <TShape extends ObjectShape = any>({ layout, renderField, }: SchemaFormLayoutProps<TShape>) => react_jsx_runtime.JSX.Element;
65
+
66
+ declare const inputVariants: (props?: ({
67
+ hasError?: boolean | null | undefined;
68
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
69
+ interface TextInputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "size">, VariantProps<typeof inputVariants> {
70
+ hasError?: boolean;
71
+ }
72
+ declare const TextInput: React__default.ForwardRefExoticComponent<TextInputProps & React__default.RefAttributes<HTMLInputElement>>;
73
+
74
+ declare const searchInputVariants: (props?: ({
75
+ hasError?: boolean | null | undefined;
76
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
77
+ interface SearchTextInputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "size">, VariantProps<typeof searchInputVariants> {
78
+ hasError?: boolean;
79
+ }
80
+ declare const SearchTextInput: React__default.ForwardRefExoticComponent<SearchTextInputProps & React__default.RefAttributes<HTMLInputElement>>;
81
+
82
+ declare const labelVariants: (props?: ({
83
+ variant?: "default" | "required" | "muted" | null | undefined;
84
+ size?: "sm" | "md" | "lg" | null | undefined;
85
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
86
+ interface LabelProps extends React__default.LabelHTMLAttributes<HTMLLabelElement>, VariantProps<typeof labelVariants> {
87
+ required?: boolean;
88
+ }
89
+ declare const Label: React__default.ForwardRefExoticComponent<LabelProps & React__default.RefAttributes<HTMLLabelElement>>;
90
+
91
+ declare const buttonVariants: (props?: ({
92
+ variant?: "primary" | "secondary" | "danger" | null | undefined;
93
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
94
+ interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
95
+ asChild?: boolean;
96
+ }
97
+ declare const Button: React__default.ForwardRefExoticComponent<ButtonProps & React__default.RefAttributes<HTMLButtonElement>>;
98
+
99
+ interface FormControlProps extends React__default.HTMLAttributes<HTMLDivElement> {
100
+ label?: string;
101
+ hint?: string;
102
+ error?: string;
103
+ required?: boolean;
104
+ spacing?: "sm" | "md" | "lg";
105
+ children: React__default.ReactElement<{
106
+ id?: string;
107
+ hasError?: boolean;
108
+ }>;
109
+ field?: AnyFieldApi | FieldApi;
110
+ }
111
+ declare const FormControl: React__default.ForwardRefExoticComponent<FormControlProps & React__default.RefAttributes<HTMLDivElement>>;
112
+
113
+ declare const selectVariants: (props?: ({
114
+ hasError?: boolean | null | undefined;
115
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
116
+ interface SelectOption<T = unknown> {
117
+ value: T;
118
+ label: string;
119
+ disabled?: boolean;
120
+ }
121
+ interface SelectProps<T = unknown> extends Omit<React__default.HTMLAttributes<HTMLDivElement>, "onChange" | "onSelect">, VariantProps<typeof selectVariants> {
122
+ options: SelectOption<T>[];
123
+ value?: T;
124
+ onChange?: (value: T | null) => void;
125
+ onSelectionChange?: (selectedItem: SelectOption<T> | null) => void;
126
+ placeholder?: string;
127
+ disabled?: boolean;
128
+ hasError?: boolean;
129
+ loading?: boolean;
130
+ loadingMessage?: string;
131
+ emptyMessage?: string;
132
+ clearable?: boolean;
133
+ searchable?: boolean;
134
+ filterOptions?: (options: SelectOption<T>[], inputValue: string) => SelectOption<T>[];
135
+ }
136
+ declare const Select: React__default.ForwardRefExoticComponent<SelectProps<any> & React__default.RefAttributes<HTMLDivElement>>;
137
+
138
+ type ModalAlignment = "center" | "top";
139
+ type ModalProps = {
140
+ open: boolean;
141
+ onClose: () => void;
142
+ children: ReactNode;
143
+ alignment?: ModalAlignment;
144
+ showBackdrop?: boolean;
145
+ showCloseButton?: boolean;
146
+ className?: string;
147
+ size?: "sm" | "md" | "lg" | "xl" | "2xl" | "full";
148
+ zIndex?: number;
149
+ initialFocus?: React.RefObject<HTMLElement | null>;
150
+ };
151
+ declare const Modal: FC<ModalProps>;
152
+
153
+ type DialogProps = {
154
+ open: boolean;
155
+ onClose: () => void;
156
+ onConfirm?: () => void;
157
+ title?: string;
158
+ children: ReactNode;
159
+ size?: "sm" | "md" | "lg" | "xl" | "2xl";
160
+ showCloseButton?: boolean;
161
+ className?: string;
162
+ alignment?: ModalAlignment;
163
+ confirmText?: string;
164
+ cancelText?: string;
165
+ confirmVariant?: "primary" | "danger";
166
+ showBackdrop?: boolean;
167
+ zIndex?: number;
168
+ };
169
+ declare const Dialog: FC<DialogProps>;
170
+
171
+ type DialogConfig = Omit<DialogProps, "open" | "onClose" | "onConfirm" | "children"> & {
172
+ title?: string;
173
+ content: ReactNode;
174
+ onConfirm?: () => void;
175
+ };
176
+ declare const useDialog: () => {
177
+ show: (dialogConfig: DialogConfig) => void;
178
+ hide: () => void;
179
+ isOpen: boolean;
180
+ DialogComponent: react_jsx_runtime.JSX.Element | null;
181
+ };
182
+
183
+ type ModalConfig = Omit<ModalProps, "open" | "onClose" | "children"> & {
184
+ component: ReactNode;
185
+ id: string;
186
+ onDismiss?: () => void;
187
+ };
188
+ declare const ModalProvider: FC<{
189
+ children: ReactNode;
190
+ }>;
191
+ declare const useModal: () => {
192
+ openModal: (component: ReactNode, options?: Omit<ModalConfig, "id" | "component">) => string;
193
+ closeModal: (id?: string) => void;
194
+ closeAllModals: () => void;
195
+ modalCount: number;
196
+ };
197
+
198
+ type ToastType = "default" | "success" | "error" | "warning" | "info";
199
+ type ToastPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
200
+ interface ToastData {
201
+ id: string;
202
+ message: ReactNode;
203
+ type: ToastType;
204
+ duration?: number;
205
+ closable?: boolean;
206
+ promise?: Promise<any>;
207
+ loadingText?: ReactNode;
208
+ }
209
+ interface ToastOptions {
210
+ duration?: number;
211
+ closable?: boolean;
212
+ }
213
+ interface PromiseToastOptions extends ToastOptions {
214
+ loadingText?: ReactNode;
215
+ }
216
+ interface PromiseResult<T = any> {
217
+ success: boolean;
218
+ data?: T;
219
+ error?: any;
220
+ }
221
+ interface PromiseToastConfig {
222
+ message: ReactNode;
223
+ type: ToastType;
224
+ duration?: number;
225
+ }
226
+ type PromiseToastCallback<T = any> = (result: PromiseResult<T>) => PromiseToastConfig;
227
+ interface ToastContextType {
228
+ toasts: ToastData[];
229
+ addToast: (message: ReactNode, type: ToastType, options?: ToastOptions) => string;
230
+ addPromiseToast: <T>(promise: Promise<T>, callback: PromiseToastCallback<T>, options?: PromiseToastOptions) => string;
231
+ removeToast: (id: string) => void;
232
+ updateToast: (id: string, updates: Partial<ToastData>) => void;
233
+ }
234
+
235
+ interface ToastProps {
236
+ toast: ToastData;
237
+ onClose: () => void;
238
+ }
239
+ declare const Toast: FC<ToastProps>;
240
+
241
+ interface ToastContainerProps {
242
+ className?: string;
243
+ }
244
+ declare const ToastContainer: FC<ToastContainerProps>;
245
+
246
+ declare const useToast: () => ToastContextType;
247
+ interface ToastProviderProps {
248
+ children: ReactNode;
249
+ }
250
+ declare const ToastProvider: ({ children }: ToastProviderProps) => react_jsx_runtime.JSX.Element;
251
+
252
+ declare const showToast: (message: ReactNode, type?: ToastType, options?: ToastOptions) => string;
253
+ declare const showPromiseToast: <T>(promise: Promise<T>, callback: PromiseToastCallback<T>, options?: PromiseToastOptions) => string;
254
+
255
+ interface ThemeToggleProps {
256
+ className?: string;
257
+ defaultTheme: "light" | "dark";
258
+ }
259
+ declare const ThemeToggle: ({ className }: ThemeToggleProps) => react_jsx_runtime.JSX.Element;
260
+
261
+ interface TreeNavigatorItem {
262
+ id: string;
263
+ icon: React.ReactNode;
264
+ title: string;
265
+ subtitle?: string;
266
+ onNavigate?: () => void;
267
+ href?: string;
268
+ onFocus?: () => void;
269
+ children?: TreeNavigatorItem[];
270
+ }
271
+ interface FlatItem extends TreeNavigatorItem {
272
+ level: number;
273
+ parentId?: string;
274
+ isExpanded?: boolean;
275
+ hasChildren: boolean;
276
+ }
277
+ interface TreeNavigatorItemComponentProps {
278
+ item: FlatItem;
279
+ index: number;
280
+ isSelected: boolean;
281
+ onToggleExpanded: (itemId: string) => void;
282
+ itemRef: (el: HTMLButtonElement | null) => void;
283
+ }
284
+ declare const TreeNavigatorItemComponent: ({ item, index, isSelected, onToggleExpanded, itemRef, }: TreeNavigatorItemComponentProps) => react_jsx_runtime.JSX.Element;
285
+
286
+ interface MainNavProps extends React.HTMLAttributes<HTMLDivElement> {
287
+ items: TreeNavigatorItem[];
288
+ searchPlaceholder?: string;
289
+ }
290
+ declare const MainNav: React$1.ForwardRefExoticComponent<MainNavProps & React$1.RefAttributes<HTMLDivElement>>;
291
+
292
+ interface NavItem {
293
+ id: string;
294
+ label: string;
295
+ children?: NavItem[];
296
+ href?: string;
297
+ onClick?: () => void;
298
+ disabled?: boolean;
299
+ badge?: string | number;
300
+ }
301
+
302
+ interface NavItemsProps {
303
+ items: NavItem[];
304
+ level?: number;
305
+ expandedItems: string[];
306
+ activeItemId?: string;
307
+ onToggle: (id: string) => void;
308
+ onItemClick?: (item: NavItem) => void;
309
+ }
310
+ declare const NavItems: FC<NavItemsProps>;
311
+
312
+ declare const flattenNavItems: (items: NavItem[], level?: number) => (NavItem & {
313
+ level: number;
314
+ })[];
315
+ declare const filterNavItems: (items: NavItem[], query: string) => NavItem[];
316
+
317
+ interface TreeNavigatorProps {
318
+ items: TreeNavigatorItem[];
319
+ searchInputRef?: RefObject<HTMLInputElement>;
320
+ }
321
+ declare const TreeNavigator: ({ items, searchInputRef, }: TreeNavigatorProps) => react_jsx_runtime.JSX.Element;
322
+ declare const ListNavigator: ({ items, searchInputRef, }: TreeNavigatorProps) => react_jsx_runtime.JSX.Element;
323
+ type ListNavigatorItem = TreeNavigatorItem;
324
+ type ListNavigatorProps = TreeNavigatorProps;
325
+
326
+ type SearchableTreeNavigatorProps = {
327
+ items: TreeNavigatorItem[];
328
+ placeHolder: string;
329
+ height?: "full" | number | string;
330
+ };
331
+ declare const SearchableTreeNavigator: React$1.ForwardRefExoticComponent<SearchableTreeNavigatorProps & React$1.RefAttributes<HTMLInputElement>>;
332
+ declare const SearchableListNavigator: React$1.ForwardRefExoticComponent<SearchableTreeNavigatorProps & React$1.RefAttributes<HTMLInputElement>>;
333
+ type SearchableListNavigatorProps = SearchableTreeNavigatorProps;
334
+
335
+ interface HttpResponse<T = any> {
336
+ status: number;
337
+ data: T;
338
+ }
339
+ interface HttpRequestConfig {
340
+ headers?: Record<string, string>;
341
+ timeout?: number;
342
+ params?: Record<string, any>;
343
+ }
344
+ declare class HttpClient {
345
+ private baseUrl;
346
+ constructor({ baseUrl }: {
347
+ baseUrl?: string;
348
+ });
349
+ private request;
350
+ get<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
351
+ post<T>(url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
352
+ put<T>(url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
353
+ patch<T>(url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
354
+ delete<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
355
+ }
356
+
357
+ type ViewType = "object";
358
+ type ViewBase = {
359
+ title: string;
360
+ id: string;
361
+ };
362
+ type CreateView<TSchema extends ObjectSchema<any> = ObjectSchema<any>, THttpClient = any> = ViewBase & {
363
+ type: "create";
364
+ schema: TSchema;
365
+ onSubmit: ({ data, http, }: {
366
+ data: Infer<TSchema>;
367
+ http: THttpClient;
368
+ }) => Promise<HttpResponse<any>>;
369
+ };
370
+ type ViewView<TSchema extends ObjectSchema<any> = ObjectSchema<any>> = ViewBase & {
371
+ type: "view";
372
+ schema: TSchema;
373
+ };
374
+ type View<TSchema extends ObjectSchema<any> = ObjectSchema<any>, THttpClient = any> = CreateView<TSchema, THttpClient> | ViewView<TSchema>;
375
+
376
+ type NubaseFrontendConfig<TApiEndpoints = any> = {
377
+ appName: string;
378
+ mainMenu: TreeNavigatorItem[];
379
+ /**
380
+ * Maps a view-id to a view configuration.
381
+ */
382
+ views: Record<string, View>;
383
+ /**
384
+ * If set, this will be used as the base URL for all HTTP requests.
385
+ * If not set, only full URLs will be used in HTTP requests.
386
+ */
387
+ apiBaseUrl?: string;
388
+ /**
389
+ * API endpoints definition for type-safe client generation.
390
+ * The framework will automatically create a typed API client from these endpoints.
391
+ * Supports nested structure like: { tickets: { createTicket: schema, ... }, users: { ... } }
392
+ */
393
+ apiEndpoints?: TApiEndpoints;
394
+ themeIds?: string[];
395
+ defaultThemeId?: "light" | "dark";
396
+ };
397
+
398
+ type NubaseAppProps = {
399
+ config: NubaseFrontendConfig;
400
+ };
401
+ declare const NubaseApp: FC<NubaseAppProps>;
402
+
403
+ declare const tableVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
404
+ interface TableProps<TData> extends React__default.TableHTMLAttributes<HTMLTableElement> {
405
+ data: TData[];
406
+ columns: ColumnDef<TData>[];
407
+ loading?: boolean;
408
+ sorting?: SortingState;
409
+ onSortingChange?: OnChangeFn<SortingState>;
410
+ enableSorting?: boolean;
411
+ emptyMessage?: string;
412
+ loadingMessage?: string;
413
+ containerClassName?: string;
414
+ }
415
+ declare const Table: React__default.ForwardRefExoticComponent<TableProps<any> & React__default.RefAttributes<HTMLTableElement>>;
416
+
417
+ declare const paginationVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
418
+ interface PaginationProps extends React__default.HTMLAttributes<HTMLDivElement> {
419
+ currentPage: number;
420
+ totalPages: number;
421
+ pageSize: number;
422
+ totalItems: number;
423
+ onPageChange: (page: number) => void;
424
+ onPageSizeChange?: (pageSize: number) => void;
425
+ pageSizeOptions?: number[];
426
+ showPageSizeSelector?: boolean;
427
+ showInfo?: boolean;
428
+ }
429
+ declare const Pagination: React__default.ForwardRefExoticComponent<PaginationProps & React__default.RefAttributes<HTMLDivElement>>;
430
+
431
+ interface UseComputedMetadataOptions {
432
+ /** Debounce delay in milliseconds (default: 300ms) */
433
+ debounceMs?: number;
434
+ }
435
+ interface UseComputedMetadataResult<TShape extends ObjectShape> {
436
+ /** Merged metadata for all properties (static + computed) */
437
+ metadata: Record<keyof TShape, SchemaMetadata<any>>;
438
+ /** Whether metadata is currently being computed */
439
+ isComputing: boolean;
440
+ /** Error that occurred during computation, if any */
441
+ error: Error | null;
442
+ }
443
+ /**
444
+ * Hook that provides debounced computed metadata for a form schema.
445
+ *
446
+ * This hook:
447
+ * 1. Watches for changes in form data
448
+ * 2. Debounces the computation to avoid excessive recalculation
449
+ * 3. Merges static metadata with computed metadata
450
+ * 4. Returns the final merged metadata for all properties
451
+ *
452
+ * @param schema The ObjectSchema with potential computed metadata
453
+ * @param formData Current form data (partial object)
454
+ * @param options Configuration options
455
+ * @returns Object with merged metadata, loading state, and error state
456
+ */
457
+ declare function useComputedMetadata<TShape extends ObjectShape>(schema: ObjectSchema<TShape>, formData: Partial<ObjectOutput<TShape>>, options?: UseComputedMetadataOptions): UseComputedMetadataResult<TShape>;
458
+
459
+ /**
460
+ * Pure function version of useLayout for testing and non-React contexts.
461
+ * This function has the same logic as useLayout but without React hooks.
462
+ */
463
+ declare function getLayout<TShape extends ObjectShape>(schema: ObjectSchema<TShape>, layoutName?: string): Layout<TShape>;
464
+ /**
465
+ * Hook to get a layout for a schema. If a layoutName is provided and exists in the schema,
466
+ * returns that layout. Otherwise, returns a default layout with all fields in a single group
467
+ * with size 12 (full width).
468
+ */
469
+ declare function useLayout<TShape extends ObjectShape>(schema: ObjectSchema<TShape>, layoutName?: string): Layout<TShape>;
470
+
471
+ /**
472
+ * Utility function for merging Tailwind CSS classes with conditional logic.
473
+ *
474
+ * This function combines clsx for conditional class handling with tailwind-merge
475
+ * to resolve Tailwind class conflicts. It's commonly used throughout the component
476
+ * library to merge default component styles with user-provided className props.
477
+ *
478
+ * @param inputs - Array of class values (strings, objects, arrays, etc.)
479
+ * @returns A string of merged and deduplicated Tailwind classes
480
+ *
481
+ * @example
482
+ * cn("px-4 py-2", "bg-blue-500", { "text-white": isActive })
483
+ * // Returns: "px-4 py-2 bg-blue-500 text-white" (if isActive is true)
484
+ *
485
+ * @example
486
+ * cn("bg-red-500", "bg-blue-500")
487
+ * // Returns: "bg-blue-500" (tailwind-merge resolves the conflict)
488
+ */
489
+ declare function cn(...inputs: ClassValue[]): string;
490
+
491
+ type TypedMethodOptions<T extends RequestSchema> = {
492
+ params?: InferRequestParams<T>;
493
+ data?: InferRequestBody<T>;
494
+ config?: HttpRequestConfig;
495
+ };
496
+ type MethodSignature<T extends RequestSchema> = T["method"] extends "GET" ? (options?: Omit<TypedMethodOptions<T>, "data">) => Promise<HttpResponse<InferResponseBody<T>>> : (options?: TypedMethodOptions<T>) => Promise<HttpResponse<InferResponseBody<T>>>;
497
+ type TypedApiMethods<T> = {
498
+ [K in keyof T]: T[K] extends RequestSchema ? MethodSignature<T[K]> : never;
499
+ };
500
+ declare class TypedApiClient<T> {
501
+ private httpClient;
502
+ private endpoints;
503
+ constructor(httpClient: HttpClient, endpoints: T);
504
+ private createFlatApiClient;
505
+ private executeRequest;
506
+ private isRequestSchema;
507
+ private capitalize;
508
+ }
509
+ declare function createTypedApiClient<T>(httpClient: HttpClient, endpoints: T): TypedApiClient<T> & TypedApiMethods<T>;
510
+
511
+ /**
512
+ * Type helper to extract the typed API client type from an endpoints definition.
513
+ * Supports both flat and nested endpoint structures.
514
+ */
515
+ type TypedApiClientFromEndpoints<T> = ReturnType<typeof createTypedApiClient<T>>;
516
+
517
+ export { Button, type ButtonProps, type CreateView, Dialog, type DialogProps, Dock, type DockProps, type FieldApi, type FlatItem, FormControl, type FormControlProps, FormFieldRenderer, type FormFieldRendererProps, HttpClient, type HttpRequestConfig, type HttpResponse, Label, type LabelProps, ListNavigator, type ListNavigatorItem, type ListNavigatorProps, MainNav, type MainNavProps, Modal, type ModalAlignment, type ModalProps, ModalProvider, type NavItem, NavItems, NubaseApp, type NubaseAppProps, type NubaseFrontendConfig, Pagination, type PaginationProps, type PromiseResult, type PromiseToastCallback, type PromiseToastConfig, type PromiseToastOptions, SchemaForm, SchemaFormLayout, type SchemaFormLayoutProps, type SchemaFormProps, type SchemaFormRef, SearchTextInput, type SearchTextInputProps, SearchableListNavigator, type SearchableListNavigatorProps, SearchableTreeNavigator, type SearchableTreeNavigatorProps, Select, type SelectOption, type SelectProps, Table, type TableProps, TextInput, type TextInputProps, ThemeToggle, type ThemeToggleProps, Toast, ToastContainer, type ToastData, type ToastOptions, type ToastPosition, ToastProvider, type ToastType, TreeNavigator, type TreeNavigatorItem, TreeNavigatorItemComponent, type TreeNavigatorProps, TypedApiClient, type TypedApiClientFromEndpoints, type View, type ViewBase, type ViewType, type ViewView, cn, createTypedApiClient, filterNavItems, flattenNavItems, getLayout, paginationVariants, showPromiseToast, showToast, tableVariants, useComputedMetadata, useDialog, useLayout, useModal, useToast };