@nomos-ui/layout 0.0.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 +277 -0
- package/dist/components/dashboard/main-layout.d.ts +56 -0
- package/dist/components/dashboard/main-layout.d.ts.map +1 -0
- package/dist/components/dashboard/main-layout.js +57 -0
- package/dist/components/dashboard/main-layout.js.map +1 -0
- package/dist/components/dashboard/sidebar/item.d.ts +11 -0
- package/dist/components/dashboard/sidebar/item.d.ts.map +1 -0
- package/dist/components/dashboard/sidebar/item.js +13 -0
- package/dist/components/dashboard/sidebar/item.js.map +1 -0
- package/dist/components/dashboard/sidebar/sidebar.d.ts +98 -0
- package/dist/components/dashboard/sidebar/sidebar.d.ts.map +1 -0
- package/dist/components/dashboard/sidebar/sidebar.js +119 -0
- package/dist/components/dashboard/sidebar/sidebar.js.map +1 -0
- package/dist/components/navbar.d.ts +23 -0
- package/dist/components/navbar.d.ts.map +1 -0
- package/dist/components/navbar.js +24 -0
- package/dist/components/navbar.js.map +1 -0
- package/dist/components/shadcn-ui/sidebar.d.ts +2 -0
- package/dist/components/shadcn-ui/sidebar.d.ts.map +1 -0
- package/dist/components/shadcn-ui/sidebar.js +3 -0
- package/dist/components/shadcn-ui/sidebar.js.map +1 -0
- package/dist/exports/dashboard/index.d.ts +4 -0
- package/dist/exports/dashboard/index.d.ts.map +1 -0
- package/dist/exports/dashboard/index.js +11 -0
- package/dist/exports/dashboard/index.js.map +1 -0
- package/dist/exports/index.d.ts +3 -0
- package/dist/exports/index.d.ts.map +1 -0
- package/dist/exports/index.js +9 -0
- package/dist/exports/index.js.map +1 -0
- package/dist/shadcn-ui/components/sidebar.d.ts +2 -0
- package/dist/shadcn-ui/components/sidebar.d.ts.map +1 -0
- package/dist/shadcn-ui/components/sidebar.js +3 -0
- package/dist/shadcn-ui/components/sidebar.js.map +1 -0
- package/package.json +121 -0
package/README.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Nomos UI Layout
|
|
2
|
+
|
|
3
|
+
> **νόμος** (nomos) - Greek: law, order, principle
|
|
4
|
+
|
|
5
|
+
Beautiful, validated form components that integrate seamlessly with React Hook Form. Built on the principle that forms should enforce order and validation effortlessly.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @nomos-ui/layout react-hook-form
|
|
11
|
+
# or
|
|
12
|
+
yarn add @nomos-ui/layout react-hook-form
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @nomos-ui/layout react-hook-form
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```jsx
|
|
20
|
+
import { useForm } from "react-hook-form";
|
|
21
|
+
import { Input, Button, Form } from "@nomos-ui/react";
|
|
22
|
+
|
|
23
|
+
function LoginForm() {
|
|
24
|
+
const form = useForm();
|
|
25
|
+
|
|
26
|
+
const onSubmit = (data) => {
|
|
27
|
+
console.log(data);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Form form={form} onSubmit={onSubmit}>
|
|
32
|
+
<Input
|
|
33
|
+
name="email"
|
|
34
|
+
label="Email"
|
|
35
|
+
type="email"
|
|
36
|
+
rules={{ required: "Email is required" }}
|
|
37
|
+
/>
|
|
38
|
+
<Input
|
|
39
|
+
name="password"
|
|
40
|
+
label="Password"
|
|
41
|
+
type="password"
|
|
42
|
+
rules={{ required: "Password is required", minLength: 8 }}
|
|
43
|
+
/>
|
|
44
|
+
<Button type="submit">Sign In</Button>
|
|
45
|
+
</Form>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Why Nomos UI?
|
|
51
|
+
|
|
52
|
+
- **Zero Boilerplate** - Components auto-register with React Hook Form
|
|
53
|
+
- **Built-in Validation** - Error states handled automatically
|
|
54
|
+
- **Accessible** - WCAG 2.1 AA compliant
|
|
55
|
+
- **Customizable** - Style with Tailwind or your own CSS
|
|
56
|
+
- **Type Safe** - Full TypeScript support
|
|
57
|
+
- **Lightweight** - Tree-shakeable, minimal bundle size
|
|
58
|
+
|
|
59
|
+
## Components
|
|
60
|
+
|
|
61
|
+
### Form Components
|
|
62
|
+
|
|
63
|
+
- `<Input />` - Text, email, password, number inputs
|
|
64
|
+
- `<Textarea />` - Multi-line text input
|
|
65
|
+
- `<Select />` - Dropdown selection
|
|
66
|
+
- `<Checkbox />` - Single checkbox
|
|
67
|
+
- `<CheckboxGroup />` - Multiple checkboxes
|
|
68
|
+
- `<Radio />` - Radio button
|
|
69
|
+
- `<RadioGroup />` - Radio button group
|
|
70
|
+
- `<Switch />` - Toggle switch
|
|
71
|
+
- `<DatePicker />` - Date selection
|
|
72
|
+
- `<FileUpload />` - File input with drag & drop
|
|
73
|
+
|
|
74
|
+
### Layout & UI
|
|
75
|
+
|
|
76
|
+
- `<Form />` - Form wrapper with context
|
|
77
|
+
- `<Button />` - Submit and action buttons
|
|
78
|
+
- `<FieldGroup />` - Group related fields
|
|
79
|
+
- `<FormSection />` - Organize form into sections
|
|
80
|
+
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
### Basic Input with Validation
|
|
84
|
+
|
|
85
|
+
```jsx
|
|
86
|
+
<Input
|
|
87
|
+
name="username"
|
|
88
|
+
label="Username"
|
|
89
|
+
placeholder="Enter username"
|
|
90
|
+
rules={{
|
|
91
|
+
required: "Username is required",
|
|
92
|
+
minLength: { value: 3, message: "Minimum 3 characters" },
|
|
93
|
+
pattern: { value: /^[a-zA-Z0-9_]+$/, message: "Alphanumeric only" },
|
|
94
|
+
}}
|
|
95
|
+
helperText="Choose a unique username"
|
|
96
|
+
/>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Select with Options
|
|
100
|
+
|
|
101
|
+
```jsx
|
|
102
|
+
<Select
|
|
103
|
+
name="country"
|
|
104
|
+
label="Country"
|
|
105
|
+
rules={{ required: "Please select a country" }}
|
|
106
|
+
options={[
|
|
107
|
+
{ value: "us", label: "United States" },
|
|
108
|
+
{ value: "uk", label: "United Kingdom" },
|
|
109
|
+
{ value: "ca", label: "Canada" },
|
|
110
|
+
]}
|
|
111
|
+
/>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Checkbox Group
|
|
115
|
+
|
|
116
|
+
```jsx
|
|
117
|
+
<CheckboxGroup
|
|
118
|
+
name="interests"
|
|
119
|
+
label="Interests"
|
|
120
|
+
options={[
|
|
121
|
+
{ value: "sports", label: "Sports" },
|
|
122
|
+
{ value: "music", label: "Music" },
|
|
123
|
+
{ value: "reading", label: "Reading" },
|
|
124
|
+
]}
|
|
125
|
+
rules={{ required: "Select at least one interest" }}
|
|
126
|
+
/>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Custom Styling
|
|
130
|
+
|
|
131
|
+
```jsx
|
|
132
|
+
<Input
|
|
133
|
+
name="email"
|
|
134
|
+
label="Email"
|
|
135
|
+
className="custom-input"
|
|
136
|
+
labelClassName="custom-label"
|
|
137
|
+
errorClassName="custom-error"
|
|
138
|
+
/>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Controlled Components
|
|
142
|
+
|
|
143
|
+
```jsx
|
|
144
|
+
const { watch, setValue } = useForm();
|
|
145
|
+
const emailValue = watch("email");
|
|
146
|
+
|
|
147
|
+
<Input
|
|
148
|
+
name="email"
|
|
149
|
+
label="Email"
|
|
150
|
+
onChange={(e) => {
|
|
151
|
+
// Custom logic
|
|
152
|
+
setValue("email", e.target.value.toLowerCase());
|
|
153
|
+
}}
|
|
154
|
+
/>;
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## API Reference
|
|
158
|
+
|
|
159
|
+
### Common Props
|
|
160
|
+
|
|
161
|
+
All form components share these props:
|
|
162
|
+
|
|
163
|
+
| Prop | Type | Description |
|
|
164
|
+
| ------------ | --------- | -------------------------------- |
|
|
165
|
+
| `name` | `string` | Field name (required) |
|
|
166
|
+
| `label` | `string` | Field label |
|
|
167
|
+
| `rules` | `object` | React Hook Form validation rules |
|
|
168
|
+
| `helperText` | `string` | Help text shown below field |
|
|
169
|
+
| `disabled` | `boolean` | Disable the field |
|
|
170
|
+
| `className` | `string` | Custom CSS class |
|
|
171
|
+
| `...rest` | `any` | Native HTML attributes |
|
|
172
|
+
|
|
173
|
+
### Input Props
|
|
174
|
+
|
|
175
|
+
| Prop | Type | Default | Description |
|
|
176
|
+
| -------------- | -------- | -------- | ---------------------------------------- |
|
|
177
|
+
| `type` | `string` | `'text'` | Input type (text, email, password, etc.) |
|
|
178
|
+
| `placeholder` | `string` | - | Placeholder text |
|
|
179
|
+
| `autoComplete` | `string` | - | Browser autocomplete hint |
|
|
180
|
+
|
|
181
|
+
### Button Props
|
|
182
|
+
|
|
183
|
+
| Prop | Type | Default | Description |
|
|
184
|
+
| ----------- | --------------------------------------------------- | ----------- | -------------------- |
|
|
185
|
+
| `variant` | `'primary' \| 'secondary' \| 'outline' \| 'danger'` | `'primary'` | Button style variant |
|
|
186
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|
187
|
+
| `loading` | `boolean` | `false` | Show loading spinner |
|
|
188
|
+
| `fullWidth` | `boolean` | `false` | Take full width |
|
|
189
|
+
|
|
190
|
+
## Customization
|
|
191
|
+
|
|
192
|
+
### Theming
|
|
193
|
+
|
|
194
|
+
Override default styles with CSS variables:
|
|
195
|
+
|
|
196
|
+
```css
|
|
197
|
+
:root {
|
|
198
|
+
--nomos-primary: #3b82f6;
|
|
199
|
+
--nomos-error: #ef4444;
|
|
200
|
+
--nomos-border: #d1d5db;
|
|
201
|
+
--nomos-radius: 0.5rem;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Tailwind Integration
|
|
206
|
+
|
|
207
|
+
Components use Tailwind classes by default. Extend with your own:
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
<Input
|
|
211
|
+
name="email"
|
|
212
|
+
className="shadow-xl border-purple-500 focus:ring-purple-500"
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## TypeScript
|
|
217
|
+
|
|
218
|
+
Full type safety with TypeScript:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { useForm } from "react-hook-form";
|
|
222
|
+
import { Input, Button } from "@nomos-ui/react";
|
|
223
|
+
|
|
224
|
+
interface FormData {
|
|
225
|
+
email: string;
|
|
226
|
+
password: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function LoginForm() {
|
|
230
|
+
const form = useForm<FormData>();
|
|
231
|
+
|
|
232
|
+
const onSubmit = (data: FormData) => {
|
|
233
|
+
console.log(data);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<Form form={form} onSubmit={onSubmit}>
|
|
238
|
+
<Input<FormData> name="email" label="Email" />
|
|
239
|
+
<Input<FormData> name="password" label="Password" type="password" />
|
|
240
|
+
<Button type="submit">Sign In</Button>
|
|
241
|
+
</Form>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Roadmap
|
|
247
|
+
|
|
248
|
+
- [ ] `@nomos-ui/vue` - Vue 3 components
|
|
249
|
+
- [ ] `@nomos-ui/svelte` - Svelte components
|
|
250
|
+
- [ ] Advanced components (Autocomplete, MultiSelect, RichText)
|
|
251
|
+
- [ ] Form builder/generator
|
|
252
|
+
- [ ] Headless components
|
|
253
|
+
- [ ] Theme presets
|
|
254
|
+
|
|
255
|
+
## Philosophy
|
|
256
|
+
|
|
257
|
+
**νόμος** (nomos) means "law" or "order" in Greek. In the New Testament, it often refers to divine law and principles. Just as law brings order to society, Nomos UI brings order to your forms - enforcing validation rules, maintaining structure, and ensuring data integrity.
|
|
258
|
+
|
|
259
|
+
> "For the law was given through Moses; grace and truth came through Jesus Christ." - John 1:17
|
|
260
|
+
|
|
261
|
+
We believe forms should be both functional and graceful, enforcing rules while remaining pleasant to use.
|
|
262
|
+
|
|
263
|
+
## Contributing
|
|
264
|
+
|
|
265
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
MIT ©
|
|
270
|
+
|
|
271
|
+
## Credits
|
|
272
|
+
|
|
273
|
+
Built on top of [React Hook Form](https://react-hook-form.com/) - the most performant, flexible form library for React.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
**Made with ♥︎ for developers who value order in chaos**
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { JSX } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* DashboardMainLayout - A responsive layout component for dashboard interfaces
|
|
4
|
+
*
|
|
5
|
+
* This component provides a flexible layout structure with optional sidebar and navbar.
|
|
6
|
+
* It automatically adjusts spacing and dimensions based on the presence of these elements.
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @param {Object} props - Component props
|
|
10
|
+
* @param {React.ReactNode} [props.children] - Main content to be rendered in the layout
|
|
11
|
+
* @param {React.ReactNode} [props.sidebar] - Optional sidebar component
|
|
12
|
+
* @param {React.ReactNode} [props.navbar] - Optional navbar component
|
|
13
|
+
*
|
|
14
|
+
* @returns {JSX.Element} A structured dashboard layout with responsive behavior
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Basic usage with all elements
|
|
18
|
+
* <DashboardMainLayout
|
|
19
|
+
* sidebar={<Sidebar />}
|
|
20
|
+
* navbar={<Navbar />}
|
|
21
|
+
* >
|
|
22
|
+
* <div>Main dashboard content</div>
|
|
23
|
+
* </DashboardMainLayout>
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Without sidebar
|
|
27
|
+
* <DashboardMainLayout navbar={<Navbar />}>
|
|
28
|
+
* <div>Content with navbar only</div>
|
|
29
|
+
* </DashboardMainLayout>
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Without navbar
|
|
33
|
+
* <DashboardMainLayout sidebar={<Sidebar />}>
|
|
34
|
+
* <div>Content with sidebar only</div>
|
|
35
|
+
* </DashboardMainLayout>
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Minimal usage (no sidebar or navbar)
|
|
39
|
+
* <DashboardMainLayout>
|
|
40
|
+
* <div>Standalone content</div>
|
|
41
|
+
* </DashboardMainLayout>
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* Layout Behavior:
|
|
45
|
+
* - When sidebar is present: main content has left margin of 16rem (ml-64) on large screens
|
|
46
|
+
* - When navbar is present: main content has top padding of 72px (pt-[72px]) and minimum height adjusts
|
|
47
|
+
* - Responsive padding: small screens (p-2), medium screens and up (sm:p-4)
|
|
48
|
+
* - Background: zinc-100 (light gray)
|
|
49
|
+
* - Grid layout: single column for content organization
|
|
50
|
+
*/
|
|
51
|
+
export default function DashboardMainLayout({ children, sidebar, navbar, }: {
|
|
52
|
+
children?: React.ReactNode;
|
|
53
|
+
sidebar?: React.ReactNode;
|
|
54
|
+
navbar?: React.ReactNode;
|
|
55
|
+
}): JSX.Element;
|
|
56
|
+
//# sourceMappingURL=main-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-layout.d.ts","sourceRoot":"","sources":["../../../src/components/dashboard/main-layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,QAAQ,EACR,OAAO,EACP,MAAM,GACP,EAAE;IACD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,GAAG,GAAG,CAAC,OAAO,CAmBd"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = DashboardMainLayout;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
/**
|
|
6
|
+
* DashboardMainLayout - A responsive layout component for dashboard interfaces
|
|
7
|
+
*
|
|
8
|
+
* This component provides a flexible layout structure with optional sidebar and navbar.
|
|
9
|
+
* It automatically adjusts spacing and dimensions based on the presence of these elements.
|
|
10
|
+
*
|
|
11
|
+
* @component
|
|
12
|
+
* @param {Object} props - Component props
|
|
13
|
+
* @param {React.ReactNode} [props.children] - Main content to be rendered in the layout
|
|
14
|
+
* @param {React.ReactNode} [props.sidebar] - Optional sidebar component
|
|
15
|
+
* @param {React.ReactNode} [props.navbar] - Optional navbar component
|
|
16
|
+
*
|
|
17
|
+
* @returns {JSX.Element} A structured dashboard layout with responsive behavior
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Basic usage with all elements
|
|
21
|
+
* <DashboardMainLayout
|
|
22
|
+
* sidebar={<Sidebar />}
|
|
23
|
+
* navbar={<Navbar />}
|
|
24
|
+
* >
|
|
25
|
+
* <div>Main dashboard content</div>
|
|
26
|
+
* </DashboardMainLayout>
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Without sidebar
|
|
30
|
+
* <DashboardMainLayout navbar={<Navbar />}>
|
|
31
|
+
* <div>Content with navbar only</div>
|
|
32
|
+
* </DashboardMainLayout>
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Without navbar
|
|
36
|
+
* <DashboardMainLayout sidebar={<Sidebar />}>
|
|
37
|
+
* <div>Content with sidebar only</div>
|
|
38
|
+
* </DashboardMainLayout>
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // Minimal usage (no sidebar or navbar)
|
|
42
|
+
* <DashboardMainLayout>
|
|
43
|
+
* <div>Standalone content</div>
|
|
44
|
+
* </DashboardMainLayout>
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* Layout Behavior:
|
|
48
|
+
* - When sidebar is present: main content has left margin of 16rem (ml-64) on large screens
|
|
49
|
+
* - When navbar is present: main content has top padding of 72px (pt-[72px]) and minimum height adjusts
|
|
50
|
+
* - Responsive padding: small screens (p-2), medium screens and up (sm:p-4)
|
|
51
|
+
* - Background: zinc-100 (light gray)
|
|
52
|
+
* - Grid layout: single column for content organization
|
|
53
|
+
*/
|
|
54
|
+
function DashboardMainLayout({ children, sidebar, navbar, }) {
|
|
55
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [sidebar, (0, jsx_runtime_1.jsxs)("div", { "data-has-sidebar": !!sidebar, className: "data-[has-sidebar=true]:lg:ml-64 min-h-screen peer-data-[hide-details=true]:ml-24", children: [navbar, (0, jsx_runtime_1.jsx)("main", { "data-has-navbar": !!navbar, className: "sm:p-4 p-2 pt-[72px] lg:mt-0 overflow-hidden bg-zinc-100 data-[has-navbar=true]:min-h-[calc(100vh-56px)] grid grid-cols-1", children: children })] })] }));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=main-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-layout.js","sourceRoot":"","sources":["../../../src/components/dashboard/main-layout.tsx"],"names":[],"mappings":";;AAmDA,sCA2BC;;AA5ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,SAAwB,mBAAmB,CAAC,EAC1C,QAAQ,EACR,OAAO,EACP,MAAM,GAKP;IACC,OAAO,CACL,6DACG,OAAO,EACR,qDACoB,CAAC,CAAC,OAAO,EAC3B,SAAS,EAAC,mFAAmF,aAE5F,MAAM,EAEP,oDACmB,CAAC,CAAC,MAAM,EACzB,SAAS,EAAC,2HAA2H,YAEpI,QAAQ,GACJ,IACH,IACL,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LucideProps } from "lucide-react";
|
|
2
|
+
import { ForwardRefExoticComponent, HTMLAttributes, RefAttributes } from "react";
|
|
3
|
+
export type SidebarItemProps = {
|
|
4
|
+
Icon: ForwardRefExoticComponent<Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>>;
|
|
5
|
+
text: string;
|
|
6
|
+
href: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
active?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export default function SidebarItem({ Icon, text, href, className, active, ...props }: SidebarItemProps & HTMLAttributes<HTMLLIElement>): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/sidebar/item.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,aAAa,EACd,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,yBAAyB,CAC7B,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,aAAa,CAAC,aAAa,CAAC,CACxD,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,IAAI,EACJ,IAAI,EACJ,IAAU,EACV,SAAS,EACT,MAAM,EACN,GAAG,KAAK,EACT,EAAE,gBAAgB,GAAG,cAAc,CAAC,aAAa,CAAC,2CA0BlD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = SidebarItem;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const link_1 = __importDefault(require("next/link"));
|
|
9
|
+
const tailwind_merge_1 = require("tailwind-merge");
|
|
10
|
+
function SidebarItem({ Icon, text, href = "/", className, active, ...props }) {
|
|
11
|
+
return ((0, jsx_runtime_1.jsxs)("li", { "data-selected": active, ...props, className: (0, tailwind_merge_1.twMerge)("pr-0 ml-0 relative group/sidebar-item z-50 group", className), children: [(0, jsx_runtime_1.jsx)("div", { className: "h-full absolute w-[3px] bg-primary-300 rounded-l-md hidden group-data-[selected=true]:block" }), (0, jsx_runtime_1.jsxs)(link_1.default, { href: href, "aria-label": text, className: "flex items-center py-[4px] px-3 text-primary-500 rounded-md hover:bg-primary-50 group transition-all w-full group-data-[selected=true]:bg-primary-50 group-data-[selected=true]:text-primary-500 mb-1", children: [(0, jsx_runtime_1.jsx)(Icon, { strokeWidth: 2.5, width: 20, absoluteStrokeWidth: true }), (0, jsx_runtime_1.jsx)("span", { className: "ms-2 text-zinc-800 group-data-[selected=true]:text-primary-600 group-data-[hide-details=true]:hidden", children: text }), (0, jsx_runtime_1.jsx)("span", { className: "ms-3 group-data-[hide-details=false]:hidden group-hover/sidebar-item:block hidden fixed left-[52px] z-50 bg-white text-zinc-800 text-sm p-1 px-2 rounded-md w-fit text-nowrap card", children: text })] })] }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.js","sourceRoot":"","sources":["../../../../src/components/dashboard/sidebar/item.tsx"],"names":[],"mappings":";;;;;AAoBA,8BAiCC;;AAnDD,qDAA6B;AAM7B,mDAAyC;AAYzC,SAAwB,WAAW,CAAC,EAClC,IAAI,EACJ,IAAI,EACJ,IAAI,GAAG,GAAG,EACV,SAAS,EACT,MAAM,EACN,GAAG,KAAK,EACyC;IACjD,OAAO,CACL,iDACiB,MAAM,KACjB,KAAK,EACT,SAAS,EAAE,IAAA,wBAAO,EAChB,kDAAkD,EAClD,SAAS,CACV,aAED,gCAAK,SAAS,EAAC,6FAA6F,GAAO,EACnH,wBAAC,cAAI,IACH,IAAI,EAAE,IAAI,gBACE,IAAI,EAChB,SAAS,EAAC,wMAAwM,aAElN,uBAAC,IAAI,IAAC,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,mBAAmB,SAAG,EACzD,iCAAM,SAAS,EAAC,sGAAsG,YACnH,IAAI,GACA,EACP,iCAAM,SAAS,EAAC,qLAAqL,YAClM,IAAI,GACA,IACF,IACJ,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Dispatch, SetStateAction } from "react";
|
|
3
|
+
import { SidebarItemProps } from "./item";
|
|
4
|
+
export type GroupSidebarItemConfig = {
|
|
5
|
+
title: string;
|
|
6
|
+
items: Omit<SidebarItemProps, "active">[];
|
|
7
|
+
};
|
|
8
|
+
export type SidebarItemConfig = GroupSidebarItemConfig | Omit<SidebarItemProps, "active">;
|
|
9
|
+
/**
|
|
10
|
+
* DashboardSidebar - A responsive dashboard sidebar with search functionality and collapsible sections
|
|
11
|
+
*
|
|
12
|
+
* This component provides a comprehensive sidebar navigation system with support for grouped menu items,
|
|
13
|
+
* search/filtering capabilities, and responsive behavior. It can be controlled externally or manage its
|
|
14
|
+
* own open state internally.
|
|
15
|
+
*
|
|
16
|
+
* @component
|
|
17
|
+
* @param {Object} props - Component props
|
|
18
|
+
* @param {Dispatch<SetStateAction<boolean>>} [props.setIsOpen] - External state setter for controlling sidebar open state
|
|
19
|
+
* @param {boolean} [props.isOpen] - External controlled open state
|
|
20
|
+
* @param {string} [props.className] - Additional CSS classes to apply to the sidebar
|
|
21
|
+
* @param {React.ReactNode} [props.logo] - Logo component to display at the top of the sidebar
|
|
22
|
+
* @param {SidebarItemConfig[]} [props.items] - Array of sidebar items or grouped item configurations
|
|
23
|
+
* @param {string} [props.activeItemText] - Text of the currently active menu item for highlighting
|
|
24
|
+
*
|
|
25
|
+
* @returns {JSX.Element} A fully-featured dashboard sidebar with navigation and search
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Basic usage with controlled state
|
|
29
|
+
* const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
30
|
+
*
|
|
31
|
+
* <DashboardSidebar
|
|
32
|
+
* isOpen={isSidebarOpen}
|
|
33
|
+
* setIsOpen={setIsSidebarOpen}
|
|
34
|
+
* logo={<img src="/logo.png" alt="Logo" />}
|
|
35
|
+
* activeItemText="Dashboard"
|
|
36
|
+
* items={[
|
|
37
|
+
* { text: "Dashboard", href: "/dashboard", icon: <DashboardIcon /> },
|
|
38
|
+
* { text: "Profile", href: "/profile", icon: <ProfileIcon /> },
|
|
39
|
+
* {
|
|
40
|
+
* title: "Settings",
|
|
41
|
+
* items: [
|
|
42
|
+
* { text: "General", href: "/settings/general", icon: <GeneralIcon /> },
|
|
43
|
+
* { text: "Security", href: "/settings/security", icon: <SecurityIcon /> }
|
|
44
|
+
* ]
|
|
45
|
+
* }
|
|
46
|
+
* ]}
|
|
47
|
+
* />
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Uncontrolled usage (sidebar manages its own state)
|
|
51
|
+
* <DashboardSidebar
|
|
52
|
+
* logo={<div>My App</div>}
|
|
53
|
+
* activeItemText="Users"
|
|
54
|
+
* items={[
|
|
55
|
+
* { text: "Dashboard", href: "/dashboard" },
|
|
56
|
+
* { text: "Users", href: "/users" },
|
|
57
|
+
* { text: "Reports", href: "/reports" }
|
|
58
|
+
* ]}
|
|
59
|
+
* />
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // With custom styling
|
|
63
|
+
* <DashboardSidebar
|
|
64
|
+
* className="bg-gray-900 border-r-0"
|
|
65
|
+
* logo={<CustomLogo />}
|
|
66
|
+
* items={navigationItems}
|
|
67
|
+
* activeItemText={currentPath}
|
|
68
|
+
* />
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* Features:
|
|
72
|
+
* - **Controlled/Uncontrolled modes**: Can be controlled externally or manage its own state
|
|
73
|
+
* - **Search functionality**: Filter menu items in real-time
|
|
74
|
+
* - **Grouped navigation**: Support for categorized menu sections with titles
|
|
75
|
+
* - **Responsive design**: Collapsible on mobile, fixed positioning
|
|
76
|
+
* - **Active state highlighting**: Visual indication of current page
|
|
77
|
+
* - **Hide details mode**: Option to collapse sidebar to icons only
|
|
78
|
+
*
|
|
79
|
+
* State Management:
|
|
80
|
+
* - `isOpen`: Controls sidebar visibility (for mobile/responsive)
|
|
81
|
+
* - `hideSidebarDetails`: Controls expanded/collapsed state of sidebar
|
|
82
|
+
* - `itemsSearchTerm`: Search input value for filtering menu items
|
|
83
|
+
*
|
|
84
|
+
* Styling:
|
|
85
|
+
* - Uses Tailwind CSS for styling
|
|
86
|
+
* - Supports custom classes via `className` prop
|
|
87
|
+
* - Includes transitions for smooth animations
|
|
88
|
+
* - Data attributes for conditional styling (`data-hide-details`, `data-hidden`)
|
|
89
|
+
*/
|
|
90
|
+
export default function DashboardSidebar({ isOpen: externalIsOpen, setIsOpen: setIsExternalOpen, className, logo, items, activeItemText, ...props }: {
|
|
91
|
+
setIsOpen?: Dispatch<SetStateAction<boolean>>;
|
|
92
|
+
isOpen?: boolean;
|
|
93
|
+
className?: string;
|
|
94
|
+
logo?: React.ReactNode;
|
|
95
|
+
items?: SidebarItemConfig[];
|
|
96
|
+
activeItemText?: string;
|
|
97
|
+
}): React.JSX.Element;
|
|
98
|
+
//# sourceMappingURL=sidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/sidebar/sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAY,MAAM,OAAO,CAAC;AAC3D,OAAoB,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAIvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,EAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,iBAAiB,EAC5B,SAAS,EACT,IAAI,EACJ,KAAK,EACL,cAAc,EACd,GAAG,KAAK,EACT,EAAE;IACD,SAAS,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuFpB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = DashboardSidebar;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const item_1 = __importDefault(require("./item"));
|
|
10
|
+
const tailwind_merge_1 = require("tailwind-merge");
|
|
11
|
+
const form_1 = require("@nomos-ui/form");
|
|
12
|
+
/**
|
|
13
|
+
* DashboardSidebar - A responsive dashboard sidebar with search functionality and collapsible sections
|
|
14
|
+
*
|
|
15
|
+
* This component provides a comprehensive sidebar navigation system with support for grouped menu items,
|
|
16
|
+
* search/filtering capabilities, and responsive behavior. It can be controlled externally or manage its
|
|
17
|
+
* own open state internally.
|
|
18
|
+
*
|
|
19
|
+
* @component
|
|
20
|
+
* @param {Object} props - Component props
|
|
21
|
+
* @param {Dispatch<SetStateAction<boolean>>} [props.setIsOpen] - External state setter for controlling sidebar open state
|
|
22
|
+
* @param {boolean} [props.isOpen] - External controlled open state
|
|
23
|
+
* @param {string} [props.className] - Additional CSS classes to apply to the sidebar
|
|
24
|
+
* @param {React.ReactNode} [props.logo] - Logo component to display at the top of the sidebar
|
|
25
|
+
* @param {SidebarItemConfig[]} [props.items] - Array of sidebar items or grouped item configurations
|
|
26
|
+
* @param {string} [props.activeItemText] - Text of the currently active menu item for highlighting
|
|
27
|
+
*
|
|
28
|
+
* @returns {JSX.Element} A fully-featured dashboard sidebar with navigation and search
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Basic usage with controlled state
|
|
32
|
+
* const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
33
|
+
*
|
|
34
|
+
* <DashboardSidebar
|
|
35
|
+
* isOpen={isSidebarOpen}
|
|
36
|
+
* setIsOpen={setIsSidebarOpen}
|
|
37
|
+
* logo={<img src="/logo.png" alt="Logo" />}
|
|
38
|
+
* activeItemText="Dashboard"
|
|
39
|
+
* items={[
|
|
40
|
+
* { text: "Dashboard", href: "/dashboard", icon: <DashboardIcon /> },
|
|
41
|
+
* { text: "Profile", href: "/profile", icon: <ProfileIcon /> },
|
|
42
|
+
* {
|
|
43
|
+
* title: "Settings",
|
|
44
|
+
* items: [
|
|
45
|
+
* { text: "General", href: "/settings/general", icon: <GeneralIcon /> },
|
|
46
|
+
* { text: "Security", href: "/settings/security", icon: <SecurityIcon /> }
|
|
47
|
+
* ]
|
|
48
|
+
* }
|
|
49
|
+
* ]}
|
|
50
|
+
* />
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Uncontrolled usage (sidebar manages its own state)
|
|
54
|
+
* <DashboardSidebar
|
|
55
|
+
* logo={<div>My App</div>}
|
|
56
|
+
* activeItemText="Users"
|
|
57
|
+
* items={[
|
|
58
|
+
* { text: "Dashboard", href: "/dashboard" },
|
|
59
|
+
* { text: "Users", href: "/users" },
|
|
60
|
+
* { text: "Reports", href: "/reports" }
|
|
61
|
+
* ]}
|
|
62
|
+
* />
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // With custom styling
|
|
66
|
+
* <DashboardSidebar
|
|
67
|
+
* className="bg-gray-900 border-r-0"
|
|
68
|
+
* logo={<CustomLogo />}
|
|
69
|
+
* items={navigationItems}
|
|
70
|
+
* activeItemText={currentPath}
|
|
71
|
+
* />
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* Features:
|
|
75
|
+
* - **Controlled/Uncontrolled modes**: Can be controlled externally or manage its own state
|
|
76
|
+
* - **Search functionality**: Filter menu items in real-time
|
|
77
|
+
* - **Grouped navigation**: Support for categorized menu sections with titles
|
|
78
|
+
* - **Responsive design**: Collapsible on mobile, fixed positioning
|
|
79
|
+
* - **Active state highlighting**: Visual indication of current page
|
|
80
|
+
* - **Hide details mode**: Option to collapse sidebar to icons only
|
|
81
|
+
*
|
|
82
|
+
* State Management:
|
|
83
|
+
* - `isOpen`: Controls sidebar visibility (for mobile/responsive)
|
|
84
|
+
* - `hideSidebarDetails`: Controls expanded/collapsed state of sidebar
|
|
85
|
+
* - `itemsSearchTerm`: Search input value for filtering menu items
|
|
86
|
+
*
|
|
87
|
+
* Styling:
|
|
88
|
+
* - Uses Tailwind CSS for styling
|
|
89
|
+
* - Supports custom classes via `className` prop
|
|
90
|
+
* - Includes transitions for smooth animations
|
|
91
|
+
* - Data attributes for conditional styling (`data-hide-details`, `data-hidden`)
|
|
92
|
+
*/
|
|
93
|
+
function DashboardSidebar({ isOpen: externalIsOpen, setIsOpen: setIsExternalOpen, className, logo, items, activeItemText, ...props }) {
|
|
94
|
+
const [hideSidebarDetails, setHideSidebarDetails] = (0, react_1.useState)(() => false);
|
|
95
|
+
const [internalIsOpen, setIsInternalOpen] = (0, react_1.useState)(false);
|
|
96
|
+
const isOpen = externalIsOpen ?? internalIsOpen;
|
|
97
|
+
const [itemsSearchTerm, setItemsSearchTerm] = (0, react_1.useState)("");
|
|
98
|
+
function setIsOpen(val) {
|
|
99
|
+
const fn = setIsExternalOpen ?? setIsInternalOpen;
|
|
100
|
+
fn(val);
|
|
101
|
+
}
|
|
102
|
+
return ((0, jsx_runtime_1.jsx)("aside", { "data-hide-details": hideSidebarDetails, ...props, className: (0, tailwind_merge_1.twMerge)("group data-[hide-details=true]:w-auto border-r border-zinc-200/70 fixed top-0 left-0 z-40 w-64 lg:w-64 h-screen bg-white -translate-x-full data-[hidden=true]:translate-x-0 lg:translate-x-0 transition-all peer ", className), children: (0, jsx_runtime_1.jsxs)("div", { className: "h-full p-2 pb-4 overflow-hidden overflow-x-hidden", children: [logo, (0, jsx_runtime_1.jsx)("div", { className: "flex justify-between items-start mb-3 group-data-[hide-details=true]:ml-0 flex-row lg:pt-0 pt-12", children: (0, jsx_runtime_1.jsx)("div", { className: "max-w-80 flex-1", children: (0, jsx_runtime_1.jsx)(form_1.Input, { className: " w-full small-sm:mb-4 mb-4 flex ", inputClassName: "h-7 w-full ", inputContainerClassName: "items-center flex-row-reverse pr-2", placeholder: "Pesquisar menus", type: "search", value: itemsSearchTerm, onChange: setItemsSearchTerm }) }) }), (0, jsx_runtime_1.jsxs)("ul", { className: "font-medium -mt-4 overflow-y-auto overflow-x-hidden max-h-[calc(100vh-280px)] h-full", children: [items?.map((item, i) => {
|
|
103
|
+
const showMenu = itemsSearchTerm
|
|
104
|
+
? JSON.stringify(item)
|
|
105
|
+
.toLowerCase()
|
|
106
|
+
.includes(itemsSearchTerm?.toLowerCase() || "")
|
|
107
|
+
: true;
|
|
108
|
+
if (showMenu)
|
|
109
|
+
if (item.title)
|
|
110
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-0 mt-2", children: [(0, jsx_runtime_1.jsx)("h2", { className: "font-semibold ml-2 pt-2 mb-2 group-data-[hide-details=true]:hidden text-zinc-700", children: item.title }), i !== 0 && ((0, jsx_runtime_1.jsx)("div", { className: "hidden group-data-[hide-details=true]:block w-full py-1", children: (0, jsx_runtime_1.jsx)("div", { className: "h-[2px] w-[70%] mx-auto bg-zinc-200 " }) })), item.items.map((item) => ((0, jsx_runtime_1.jsx)(item_1.default, { onClick: () => setIsOpen(false), active: activeItemText === item.text, ...item }, item.href)))] }, item.title));
|
|
111
|
+
else
|
|
112
|
+
return;
|
|
113
|
+
(0, jsx_runtime_1.jsx)(item_1.default, { onClick: () => setIsOpen(false), active: activeItemText === item.text, ...item }, item.href);
|
|
114
|
+
}), itemsSearchTerm &&
|
|
115
|
+
!JSON.stringify(items)
|
|
116
|
+
.toLowerCase()
|
|
117
|
+
.includes(itemsSearchTerm?.toLowerCase() || "") && ((0, jsx_runtime_1.jsxs)("li", { className: "text-zinc-400 text-sm text-center mt-8", children: ["Nenhum Resultado para \"", itemsSearchTerm, "\""] }))] })] }) }));
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../../../src/components/dashboard/sidebar/sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type NavbarProps = {
|
|
3
|
+
left?: React.ReactNode;
|
|
4
|
+
center?: React.ReactNode;
|
|
5
|
+
right?: React.ReactNode;
|
|
6
|
+
} & React.ComponentProps<"div">;
|
|
7
|
+
/**
|
|
8
|
+
* A sticky navigation bar with left, center, and right sections.
|
|
9
|
+
*
|
|
10
|
+
* @param left - Content for left section (logo, menu button)
|
|
11
|
+
* @param center - Content for center section (title, search)
|
|
12
|
+
* @param right - Content for right section (user menu, actions)
|
|
13
|
+
* @param className - Additional CSS classes
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <Navbar
|
|
17
|
+
* left={<Logo />}
|
|
18
|
+
* center={<h1>Dashboard</h1>}
|
|
19
|
+
* right={<UserMenu />}
|
|
20
|
+
* />
|
|
21
|
+
*/
|
|
22
|
+
export default function Navbar({ left, center, right, className, ...props }: NavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=navbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navbar.d.ts","sourceRoot":"","sources":["../../src/components/navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAEhC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,WAAW,2CAmBb"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = Navbar;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const tailwind_merge_1 = require("tailwind-merge");
|
|
6
|
+
/**
|
|
7
|
+
* A sticky navigation bar with left, center, and right sections.
|
|
8
|
+
*
|
|
9
|
+
* @param left - Content for left section (logo, menu button)
|
|
10
|
+
* @param center - Content for center section (title, search)
|
|
11
|
+
* @param right - Content for right section (user menu, actions)
|
|
12
|
+
* @param className - Additional CSS classes
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* <Navbar
|
|
16
|
+
* left={<Logo />}
|
|
17
|
+
* center={<h1>Dashboard</h1>}
|
|
18
|
+
* right={<UserMenu />}
|
|
19
|
+
* />
|
|
20
|
+
*/
|
|
21
|
+
function Navbar({ left, center, right, className, ...props }) {
|
|
22
|
+
return ((0, jsx_runtime_1.jsx)("nav", { "aria-label": "Main navigation", className: (0, tailwind_merge_1.twMerge)("sticky top-0 z-50 w-full border-b border-zinc-200 p-0 px-2 bg-white", className), ...props, children: (0, jsx_runtime_1.jsx)("div", { className: "py-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between h-[36px]", children: [left && (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-full", children: left }), center && (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-full", children: center }), right && (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-full", children: right })] }) }) }));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=navbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navbar.js","sourceRoot":"","sources":["../../src/components/navbar.tsx"],"names":[],"mappings":";;AAwBA,yBAyBC;;AAhDD,mDAAyC;AAQzC;;;;;;;;;;;;;;GAcG;AACH,SAAwB,MAAM,CAAC,EAC7B,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACI;IACZ,OAAO,CACL,8CACa,iBAAiB,EAC5B,SAAS,EAAE,IAAA,wBAAO,EAChB,qEAAqE,EACrE,SAAS,CACV,KACG,KAAK,YAET,gCAAK,SAAS,EAAC,MAAM,YACnB,iCAAK,SAAS,EAAC,4CAA4C,aACxD,IAAI,IAAI,gCAAK,SAAS,EAAC,eAAe,YAAE,IAAI,GAAO,EACnD,MAAM,IAAI,gCAAK,SAAS,EAAC,eAAe,YAAE,MAAM,GAAO,EACvD,KAAK,IAAI,gCAAK,SAAS,EAAC,eAAe,YAAE,KAAK,GAAO,IAClD,GACF,GACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/shadcn-ui/sidebar.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../../src/components/shadcn-ui/sidebar.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/exports/dashboard/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,4CAA4C,CAAC;AAC1E,OAAO,mBAAmB,MAAM,wCAAwC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DashboardMainLayout = exports.DashboardSidebar = void 0;
|
|
7
|
+
const sidebar_1 = __importDefault(require("../../components/dashboard/sidebar/sidebar"));
|
|
8
|
+
exports.DashboardSidebar = sidebar_1.default;
|
|
9
|
+
const main_layout_1 = __importDefault(require("../../components/dashboard/main-layout"));
|
|
10
|
+
exports.DashboardMainLayout = main_layout_1.default;
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/exports/dashboard/index.ts"],"names":[],"mappings":";;;;;;AAAA,yFAA0E;AAGjE,2BAHF,iBAAgB,CAGE;AAFzB,yFAAyE;AAE9C,8BAFpB,qBAAmB,CAEoB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Navbar = void 0;
|
|
7
|
+
const navbar_1 = __importDefault(require("../components/navbar"));
|
|
8
|
+
exports.Navbar = navbar_1.default;
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":";;;;;;AAAA,kEAA0C;AAEjC,iBAFF,gBAAM,CAEE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/shadcn-ui/components/sidebar.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../../src/shadcn-ui/components/sidebar.tsx"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nomos-ui/layout",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "The Shadcn library for building robust React layouts",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/exports/index.js",
|
|
7
|
+
"types": "dist/exports/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/exports/index.d.ts",
|
|
11
|
+
"import": "./dist/exports/index.js",
|
|
12
|
+
"require": "./dist/exports/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./dashboard": {
|
|
15
|
+
"types": "./dist/dashboard/index.d.ts",
|
|
16
|
+
"import": "./dist/dashboard/index.js",
|
|
17
|
+
"require": "./dist/dashboard/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./types": {
|
|
20
|
+
"types": "./dist/types/index.d.ts",
|
|
21
|
+
"import": "./dist/types/index.js",
|
|
22
|
+
"require": "./dist/types/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"typesVersions": {
|
|
26
|
+
"*": {
|
|
27
|
+
"components": ["./dist/components/index.d.ts"],
|
|
28
|
+
"dashboard": ["./dist/dashboard/index.d.ts"],
|
|
29
|
+
"types": ["./dist/types/index.d.ts"]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "trash dist && tsc",
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"clean": "rm -rf dist",
|
|
36
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
37
|
+
"type-check": "tsc --noEmit",
|
|
38
|
+
"test": "vitest",
|
|
39
|
+
"test:watch": "vitest --watch",
|
|
40
|
+
"test:ui": "vitest --ui",
|
|
41
|
+
"test:coverage": "vitest --coverage",
|
|
42
|
+
"prepublishOnly": "pnpm run build"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"react",
|
|
46
|
+
"react-hook-form",
|
|
47
|
+
"form",
|
|
48
|
+
"forms",
|
|
49
|
+
"validation",
|
|
50
|
+
"components",
|
|
51
|
+
"ui",
|
|
52
|
+
"input",
|
|
53
|
+
"select",
|
|
54
|
+
"checkbox",
|
|
55
|
+
"accessible",
|
|
56
|
+
"a11y",
|
|
57
|
+
"tailwind",
|
|
58
|
+
"typescript",
|
|
59
|
+
"nomos"
|
|
60
|
+
],
|
|
61
|
+
"author": "Uanela Como",
|
|
62
|
+
"license": "MIT",
|
|
63
|
+
"repository": {
|
|
64
|
+
"type": "git",
|
|
65
|
+
"url": "git+https://github.com/uanela/nomos-ui.git",
|
|
66
|
+
"directory": "packages/layout"
|
|
67
|
+
},
|
|
68
|
+
"bugs": {
|
|
69
|
+
"url": "https://github.com/uanela/nomos-ui/issues"
|
|
70
|
+
},
|
|
71
|
+
"homepage": "https://github.com/uanela/nomos-ui/tree/main/packages/react#readme",
|
|
72
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
73
|
+
"sideEffects": false,
|
|
74
|
+
"packageManager": "pnpm@10.13.1",
|
|
75
|
+
"dependencies": {},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/node": "^24.9.1",
|
|
78
|
+
"@types/react": "^19.2.2",
|
|
79
|
+
"@types/react-dom": "^19.2.0",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
81
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
82
|
+
"eslint": "^8.56.0",
|
|
83
|
+
"eslint-plugin-react": "^7.33.2",
|
|
84
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
85
|
+
"tailwindcss": "^4.1.16",
|
|
86
|
+
"trash-cli": "^7.0.0",
|
|
87
|
+
"tsx": "^4.20.3",
|
|
88
|
+
"typescript": "^5.9.3",
|
|
89
|
+
"vitest": "^4.0.3"
|
|
90
|
+
},
|
|
91
|
+
"peerDependencies": {
|
|
92
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
93
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
94
|
+
"react-hook-form": "^7.0.0",
|
|
95
|
+
"@nomos-ui/form": "^0.0.17",
|
|
96
|
+
"@radix-ui/react-slot": "^1.2.3",
|
|
97
|
+
"@tailwindcss/postcss": "^4.1.16",
|
|
98
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
99
|
+
"class-variance-authority": "^0.7.1",
|
|
100
|
+
"clsx": "^2.1.1",
|
|
101
|
+
"lucide-react": "^0.548.0",
|
|
102
|
+
"tailwind-merge": "^3.5.0"
|
|
103
|
+
},
|
|
104
|
+
"peerDependenciesMeta": {
|
|
105
|
+
"react": {
|
|
106
|
+
"optional": false
|
|
107
|
+
},
|
|
108
|
+
"react-dom": {
|
|
109
|
+
"optional": false
|
|
110
|
+
},
|
|
111
|
+
"react-hook-form": {
|
|
112
|
+
"optional": false
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"engines": {
|
|
116
|
+
"node": ">=18.0.0"
|
|
117
|
+
},
|
|
118
|
+
"publishConfig": {
|
|
119
|
+
"access": "public"
|
|
120
|
+
}
|
|
121
|
+
}
|