@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 +127 -0
- package/dist/index.css +50 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +517 -0
- package/dist/index.d.ts +517 -0
- package/dist/index.js +7997 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7967 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +1831 -0
- package/package.json +87 -0
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":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -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 };
|