@jorgequevedoc/react-gridforms 1.1.0

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.
Files changed (63) hide show
  1. package/README.md +278 -0
  2. package/dist/components/FormField.d.ts +11 -0
  3. package/dist/components/FormField.d.ts.map +1 -0
  4. package/dist/components/FormField.js +111 -0
  5. package/dist/components/FormField.js.map +1 -0
  6. package/dist/components/FormRow.d.ts +9 -0
  7. package/dist/components/FormRow.d.ts.map +1 -0
  8. package/dist/components/FormRow.js +38 -0
  9. package/dist/components/FormRow.js.map +1 -0
  10. package/dist/components/FormSection.d.ts +9 -0
  11. package/dist/components/FormSection.d.ts.map +1 -0
  12. package/dist/components/FormSection.js +36 -0
  13. package/dist/components/FormSection.js.map +1 -0
  14. package/dist/components/GridForm.d.ts +9 -0
  15. package/dist/components/GridForm.d.ts.map +1 -0
  16. package/dist/components/GridForm.js +88 -0
  17. package/dist/components/GridForm.js.map +1 -0
  18. package/dist/components/ThemeToggle.d.ts +7 -0
  19. package/dist/components/ThemeToggle.d.ts.map +1 -0
  20. package/dist/components/ThemeToggle.js +30 -0
  21. package/dist/components/ThemeToggle.js.map +1 -0
  22. package/dist/components/index.d.ts +9 -0
  23. package/dist/components/index.d.ts.map +1 -0
  24. package/dist/components/index.js +9 -0
  25. package/dist/components/index.js.map +1 -0
  26. package/dist/components/inputs/RadioGroup.d.ts +14 -0
  27. package/dist/components/inputs/RadioGroup.d.ts.map +1 -0
  28. package/dist/components/inputs/RadioGroup.js +39 -0
  29. package/dist/components/inputs/RadioGroup.js.map +1 -0
  30. package/dist/components/inputs/SelectInput.d.ts +18 -0
  31. package/dist/components/inputs/SelectInput.d.ts.map +1 -0
  32. package/dist/components/inputs/SelectInput.js +29 -0
  33. package/dist/components/inputs/SelectInput.js.map +1 -0
  34. package/dist/components/inputs/TextInput.d.ts +15 -0
  35. package/dist/components/inputs/TextInput.d.ts.map +1 -0
  36. package/dist/components/inputs/TextInput.js +28 -0
  37. package/dist/components/inputs/TextInput.js.map +1 -0
  38. package/dist/index.d.ts +8 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +6 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/index.ts +27 -0
  43. package/dist/lib.d.ts +4 -0
  44. package/dist/lib.d.ts.map +1 -0
  45. package/dist/lib.js +6 -0
  46. package/dist/lib.js.map +1 -0
  47. package/dist/theme/ThemeContext.d.ts +16 -0
  48. package/dist/theme/ThemeContext.d.ts.map +1 -0
  49. package/dist/theme/ThemeContext.js +32 -0
  50. package/dist/theme/ThemeContext.js.map +1 -0
  51. package/dist/theme/index.d.ts +3 -0
  52. package/dist/theme/index.d.ts.map +1 -0
  53. package/dist/theme/index.js +2 -0
  54. package/dist/theme/index.js.map +1 -0
  55. package/dist/theme/themes.d.ts +4 -0
  56. package/dist/theme/themes.d.ts.map +1 -0
  57. package/dist/theme/themes.js +87 -0
  58. package/dist/theme/themes.js.map +1 -0
  59. package/dist/theme/types.d.ts +46 -0
  60. package/dist/theme/types.d.ts.map +1 -0
  61. package/dist/theme/types.js +2 -0
  62. package/dist/theme/types.js.map +1 -0
  63. package/package.json +78 -0
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # React GridForms
2
+
3
+ A modern React TypeScript implementation of GridForms - a compact and beautiful grid-based form system with built-in theming support.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Modern Design**: Clean, responsive grid-based form layout
8
+ - 🌙 **Theme Support**: Built-in light and dark themes with easy customization
9
+ - 📱 **Responsive**: Works seamlessly across all device sizes
10
+ - 🎯 **TypeScript**: Full TypeScript support with comprehensive type definitions
11
+ - ⚡ **Performance**: Optimized for performance with minimal bundle size
12
+ - 🎨 **Styled Components**: Built with styled-components for flexible styling
13
+
14
+ ## Installation
15
+
16
+ ### Option 1: Publish to npm (Recommended)
17
+
18
+ 1. **Build the library:**
19
+
20
+ ```bash
21
+ yarn build:lib
22
+ ```
23
+
24
+ 2. **Publish to npm:**
25
+
26
+ ```bash
27
+ npm publish
28
+ ```
29
+
30
+ 3. **Install in your project:**
31
+ ```bash
32
+ yarn add react-gridforms
33
+ ```
34
+
35
+ ### Option 2: Use as a Git dependency
36
+
37
+ Add this repository as a dependency in your `package.json`:
38
+
39
+ ```json
40
+ {
41
+ "dependencies": {
42
+ "react-gridforms": "github:yourusername/react-gridforms#main"
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Option 3: Use with yarn link (Development)
48
+
49
+ 1. **Link the library:**
50
+
51
+ ```bash
52
+ cd /path/to/react-gridforms
53
+ yarn link
54
+ ```
55
+
56
+ 2. **Link in your project:**
57
+ ```bash
58
+ cd /path/to/your-project
59
+ yarn link react-gridforms
60
+ ```
61
+
62
+ ### Option 4: Use as a local dependency
63
+
64
+ 1. **Build the library:**
65
+
66
+ ```bash
67
+ cd /path/to/react-gridforms
68
+ yarn build:lib
69
+ ```
70
+
71
+ 2. **Add to your project's package.json:**
72
+
73
+ ```json
74
+ {
75
+ "dependencies": {
76
+ "react-gridforms": "file:/path/to/react-gridforms"
77
+ }
78
+ }
79
+ ```
80
+
81
+ 3. **Install:**
82
+ ```bash
83
+ yarn install
84
+ ```
85
+
86
+ ## Usage
87
+
88
+ ### Basic Setup
89
+
90
+ ```tsx
91
+ import React from 'react';
92
+ import {
93
+ GridForm,
94
+ FormSection,
95
+ FormRow,
96
+ FormField,
97
+ TextInput,
98
+ ThemeProvider,
99
+ lightTheme,
100
+ } from 'react-gridforms';
101
+
102
+ function App() {
103
+ return (
104
+ <ThemeProvider theme={lightTheme}>
105
+ <GridForm onSubmit={(data) => console.log(data)}>
106
+ <FormSection title="Personal Information">
107
+ <FormRow>
108
+ <FormField label="First Name">
109
+ <TextInput name="firstName" placeholder="Enter your first name" />
110
+ </FormField>
111
+ <FormField label="Last Name">
112
+ <TextInput name="lastName" placeholder="Enter your last name" />
113
+ </FormField>
114
+ </FormRow>
115
+ </FormSection>
116
+ </GridForm>
117
+ </ThemeProvider>
118
+ );
119
+ }
120
+ ```
121
+
122
+ ### Available Components
123
+
124
+ #### Core Components
125
+
126
+ - `GridForm` - Main form container
127
+ - `FormSection` - Group form fields into sections
128
+ - `FormRow` - Arrange fields in a row
129
+ - `FormField` - Individual form field wrapper
130
+
131
+ #### Input Components
132
+
133
+ - `TextInput` - Text input field
134
+ - `SelectInput` - Dropdown select field
135
+ - `RadioGroup` - Radio button group
136
+
137
+ #### Theme Components
138
+
139
+ - `ThemeProvider` - Theme context provider
140
+ - `ThemeToggle` - Toggle between light and dark themes
141
+
142
+ ### Theming
143
+
144
+ ```tsx
145
+ import { ThemeProvider, lightTheme, darkTheme, useTheme } from 'react-gridforms';
146
+
147
+ // Use light theme
148
+ <ThemeProvider theme={lightTheme}>
149
+ {/* Your form */}
150
+ </ThemeProvider>
151
+
152
+ // Use dark theme
153
+ <ThemeProvider theme={darkTheme}>
154
+ {/* Your form */}
155
+ </ThemeProvider>
156
+
157
+ // Custom theme
158
+ const customTheme = {
159
+ ...lightTheme,
160
+ colors: {
161
+ ...lightTheme.colors,
162
+ primary: '#ff6b6b',
163
+ secondary: '#4ecdc4',
164
+ }
165
+ };
166
+
167
+ <ThemeProvider theme={customTheme}>
168
+ {/* Your form */}
169
+ </ThemeProvider>
170
+ ```
171
+
172
+ ### Form Submission
173
+
174
+ ```tsx
175
+ <GridForm
176
+ onSubmit={(data) => {
177
+ console.log('Form data:', data);
178
+ // Handle form submission
179
+ }}
180
+ >
181
+ {/* Form fields */}
182
+ </GridForm>
183
+ ```
184
+
185
+ ## API Reference
186
+
187
+ ### GridForm Props
188
+
189
+ - `onSubmit: (data: Record<string, any>) => void` - Form submission handler
190
+ - `children: ReactNode` - Form content
191
+
192
+ ### FormSection Props
193
+
194
+ - `title: string` - Section title
195
+ - `children: ReactNode` - Section content
196
+
197
+ ### FormRow Props
198
+
199
+ - `children: ReactNode` - Row content
200
+
201
+ ### FormField Props
202
+
203
+ - `label: string` - Field label
204
+ - `children: ReactNode` - Input component
205
+
206
+ ### TextInput Props
207
+
208
+ - `name: string` - Field name
209
+ - `placeholder?: string` - Placeholder text
210
+ - `type?: string` - Input type (default: "text")
211
+ - `required?: boolean` - Required field
212
+ - `disabled?: boolean` - Disabled state
213
+
214
+ ### SelectInput Props
215
+
216
+ - `name: string` - Field name
217
+ - `options: SelectOption[]` - Select options
218
+ - `placeholder?: string` - Placeholder text
219
+ - `required?: boolean` - Required field
220
+ - `disabled?: boolean` - Disabled state
221
+
222
+ ### RadioGroup Props
223
+
224
+ - `name: string` - Field name
225
+ - `options: RadioOption[]` - Radio options
226
+ - `required?: boolean` - Required field
227
+ - `disabled?: boolean` - Disabled state
228
+
229
+ ## Development
230
+
231
+ ### Prerequisites
232
+
233
+ - Node.js 18+
234
+ - Yarn
235
+
236
+ ### Setup
237
+
238
+ ```bash
239
+ git clone https://github.com/yourusername/react-gridforms.git
240
+ cd react-gridforms
241
+ yarn install
242
+ ```
243
+
244
+ ### Available Scripts
245
+
246
+ - `yarn dev` - Start development server
247
+ - `yarn build` - Build for production
248
+ - `yarn build:lib` - Build library for distribution
249
+ - `yarn lint` - Run ESLint
250
+ - `yarn preview` - Preview production build
251
+
252
+ ### Project Structure
253
+
254
+ ```
255
+ src/
256
+ ├── components/ # React components
257
+ │ ├── inputs/ # Input components
258
+ │ └── index.ts # Component exports
259
+ ├── theme/ # Theme configuration
260
+ ├── index.ts # Main library exports
261
+ └── lib.ts # Library build entry point
262
+ ```
263
+
264
+ ## Contributing
265
+
266
+ 1. Fork the repository
267
+ 2. Create a feature branch
268
+ 3. Make your changes
269
+ 4. Add tests if applicable
270
+ 5. Submit a pull request
271
+
272
+ ## License
273
+
274
+ MIT License - see LICENSE file for details.
275
+
276
+ ## Support
277
+
278
+ For support, please open an issue on GitHub or contact the maintainers.
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface FormFieldProps {
3
+ children: React.ReactNode;
4
+ span: number;
5
+ label?: string;
6
+ className?: string;
7
+ rowspan?: number;
8
+ }
9
+ export declare const FormField: React.FC<FormFieldProps>;
10
+ export {};
11
+ //# sourceMappingURL=FormField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../src/components/FormField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,cAAc;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkFD,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA4D9C,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import styled from 'styled-components';
4
+ const StyledFormField = styled.div `
5
+ padding: ${(props) => props.theme.spacing.sm};
6
+ position: relative;
7
+ flex: ${({ span = 1, rowspan = 12 }) => `0 0 ${(100 / rowspan) * span}%`};
8
+ max-width: ${({ span = 1, rowspan = 12 }) => `${(100 / rowspan) * span}%`};
9
+ background-color: ${(props) => props.isFocused ? props.theme.colors.focusBackground : 'transparent'};
10
+ transition: background-color 0.2s ease;
11
+ border-right: 1px solid ${(props) => props.theme.colors.border};
12
+
13
+ label {
14
+ display: block;
15
+ font-size: ${(props) => props.theme.typography.fontSizeSmall};
16
+ color: ${(props) => props.theme.colors.textPrimary};
17
+ text-transform: uppercase;
18
+ letter-spacing: 0.5px;
19
+ margin-bottom: ${(props) => props.theme.spacing.xs};
20
+ }
21
+
22
+ /* Field styles */
23
+ input[type='text'],
24
+ input[type='email'],
25
+ input[type='number'],
26
+ input[type='password'],
27
+ input[type='search'],
28
+ input[type='tel'],
29
+ input[type='url'],
30
+ input[type='color'],
31
+ input[type='date'],
32
+ input[type='datetime'],
33
+ input[type='datetime-local'],
34
+ input[type='month'],
35
+ input[type='time'],
36
+ input[type='week'],
37
+ textarea,
38
+ select {
39
+ font-size: ${(props) => props.theme.typography.fontSizeLarge};
40
+ padding: 0;
41
+ margin: 0;
42
+ width: 100%;
43
+ border: 0;
44
+ background: ${(props) => props.theme.colors.inputBackground};
45
+
46
+ &::placeholder {
47
+ font-weight: ${(props) => props.theme.typography.fontWeightLight};
48
+ color: ${(props) => props.theme.colors.inputPlaceholder};
49
+ }
50
+
51
+ &:focus {
52
+ outline: none;
53
+ }
54
+ }
55
+
56
+ /* Radio and checkbox styles */
57
+ input[type='radio'],
58
+ input[type='checkbox'] {
59
+ margin-right: ${(props) => props.theme.spacing.sm};
60
+ }
61
+
62
+ /* Radio and checkbox labels */
63
+ input[type='radio'] + label,
64
+ input[type='checkbox'] + label {
65
+ display: inline;
66
+ text-transform: none;
67
+ letter-spacing: normal;
68
+ margin-bottom: 0;
69
+ margin-left: ${(props) => props.theme.spacing.xs};
70
+ }
71
+
72
+ @media only screen and (max-width: 768px) {
73
+ flex: 1 1 100%;
74
+ max-width: 100%;
75
+ border-bottom: 1px solid ${(props) => props.theme.colors.border};
76
+ }
77
+ `;
78
+ export const FormField = ({ children, span, label, className, rowspan = 12, }) => {
79
+ const [isFocused, setIsFocused] = useState(false);
80
+ const fieldRef = useRef(null);
81
+ useEffect(() => {
82
+ const handleClick = (e) => {
83
+ if (fieldRef.current && !fieldRef.current.contains(e.target)) {
84
+ setIsFocused(false);
85
+ }
86
+ };
87
+ const handleFocus = () => setIsFocused(true);
88
+ const handleBlur = () => setIsFocused(false);
89
+ const field = fieldRef.current;
90
+ if (field) {
91
+ const focusableElements = field.querySelectorAll('input, textarea, select');
92
+ focusableElements.forEach((el) => {
93
+ el.addEventListener('focus', handleFocus);
94
+ el.addEventListener('blur', handleBlur);
95
+ });
96
+ }
97
+ document.addEventListener('click', handleClick);
98
+ return () => {
99
+ document.removeEventListener('click', handleClick);
100
+ if (field) {
101
+ const focusableElements = field.querySelectorAll('input, textarea, select');
102
+ focusableElements.forEach((el) => {
103
+ el.removeEventListener('focus', handleFocus);
104
+ el.removeEventListener('blur', handleBlur);
105
+ });
106
+ }
107
+ };
108
+ }, []);
109
+ return (_jsxs(StyledFormField, { ref: fieldRef, "data-field-span": span, span: span, isFocused: isFocused, className: className, rowspan: rowspan, children: [label && _jsx("label", { children: label }), children] }));
110
+ };
111
+ //# sourceMappingURL=FormField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormField.js","sourceRoot":"","sources":["../../src/components/FormField.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface FormRowProps {
3
+ children: React.ReactNode;
4
+ span: number;
5
+ className?: string;
6
+ }
7
+ export declare const FormRow: React.FC<FormRowProps>;
8
+ export {};
9
+ //# sourceMappingURL=FormRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRow.d.ts","sourceRoot":"","sources":["../../src/components/FormRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,YAAY;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2BD,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAkB1C,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import styled from 'styled-components';
4
+ const StyledFormRow = styled.div `
5
+ border-bottom: 1px solid ${(props) => props.theme.colors.border};
6
+ width: 100%;
7
+ display: flex;
8
+ flex-wrap: wrap
9
+
10
+ > div[data-field-span]:first-child {
11
+ border-left: none;
12
+ }
13
+
14
+ > div[data-field-span]:last-child {
15
+ border-right: none;
16
+ }
17
+
18
+ @media only screen and (max-width: 768px) {
19
+ border-bottom: none;
20
+ flex-direction: column;
21
+
22
+ > div[data-field-span] {
23
+ flex: 1 1 100%;
24
+ max-width: 100%;
25
+ }
26
+ }
27
+ `;
28
+ export const FormRow = ({ children, span, className, }) => {
29
+ // Clone children and inject rowspan prop
30
+ const childrenWithRowspan = React.Children.map(children, (child) => {
31
+ if (React.isValidElement(child)) {
32
+ return React.cloneElement(child, { rowspan: span });
33
+ }
34
+ return child;
35
+ });
36
+ return (_jsx(StyledFormRow, { "data-row-span": span, span: span, className: className, children: childrenWithRowspan }));
37
+ };
38
+ //# sourceMappingURL=FormRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRow.js","sourceRoot":"","sources":["../../src/components/FormRow.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAQvC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAkB;6BACrB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;CAsBhE,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAC9C,QAAQ,EACR,IAAI,EACJ,SAAS,GACV,EAAE,EAAE;IACH,yCAAyC;IACzC,MAAM,mBAAmB,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;QACjE,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAS,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,KAAC,aAAa,qBAAgB,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,YACjE,mBAAmB,GACN,CACjB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface FormSectionProps {
3
+ children: React.ReactNode;
4
+ title: string;
5
+ className?: string;
6
+ }
7
+ export declare const FormSection: React.FC<FormSectionProps>;
8
+ export {};
9
+ //# sourceMappingURL=FormSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormSection.d.ts","sourceRoot":"","sources":["../../src/components/FormSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,gBAAgB;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAWlD,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
3
+ const StyledFieldset = styled.fieldset `
4
+ border: none;
5
+ padding: 0;
6
+ margin: 0;
7
+ margin-top: ${(props) => props.theme.spacing.xl};
8
+
9
+ legend {
10
+ border: none;
11
+ border-bottom: 4px solid ${(props) => props.theme.colors.legend};
12
+ color: ${(props) => props.theme.colors.legend};
13
+ font-size: ${(props) => props.theme.typography.fontSizeLarge};
14
+ font-weight: ${(props) => props.theme.typography.fontWeightBold};
15
+ padding-bottom: 5px;
16
+ position: static;
17
+ width: 100%;
18
+ margin-bottom: ${(props) => props.theme.spacing.xs};
19
+ }
20
+
21
+ /* Nested fieldset styles */
22
+ fieldset legend {
23
+ border-bottom: 2px solid ${(props) => props.theme.colors.legend};
24
+ font-weight: ${(props) => props.theme.typography.fontWeightNormal};
25
+ }
26
+
27
+ fieldset fieldset legend {
28
+ border-bottom: 1px solid ${(props) => props.theme.colors.legend};
29
+ font-weight: ${(props) => props.theme.typography.fontWeightNormal};
30
+ font-size: ${(props) => props.theme.typography.fontSizeBase};
31
+ }
32
+ `;
33
+ export const FormSection = ({ children, title, className, }) => {
34
+ return (_jsxs(StyledFieldset, { className: className, children: [_jsx("legend", { children: title }), children] }));
35
+ };
36
+ //# sourceMappingURL=FormSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormSection.js","sourceRoot":"","sources":["../../src/components/FormSection.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAQvC,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAA;;;;gBAItB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;;;;+BAIlB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;aACtD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;iBAChC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa;mBAC7C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc;;;;qBAI9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;;;;;+BAKvB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;mBAChD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,gBAAgB;;;;+BAItC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;mBAChD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,gBAAgB;iBACpD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY;;CAE9D,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAA+B,CAAC,EACtD,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,MAAC,cAAc,IAAC,SAAS,EAAE,SAAS,aAClC,2BAAS,KAAK,GAAU,EACvB,QAAQ,IACM,CAClB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface GridFormProps {
3
+ children: React.ReactNode;
4
+ onSubmit?: (e: React.FormEvent) => void;
5
+ className?: string;
6
+ }
7
+ export declare const GridForm: React.FC<GridFormProps>;
8
+ export {};
9
+ //# sourceMappingURL=GridForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GridForm.d.ts","sourceRoot":"","sources":["../../src/components/GridForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,aAAa;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqFD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAa5C,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
3
+ const StyledGridForm = styled.form `
4
+ width: 100%;
5
+ max-width: 100%;
6
+
7
+ /* Grid form base styles */
8
+ *,
9
+ *:before,
10
+ *:after {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ /* Remove backgrounds and borders from fields */
15
+ input[type='text'],
16
+ input[type='email'],
17
+ input[type='number'],
18
+ input[type='password'],
19
+ input[type='search'],
20
+ input[type='tel'],
21
+ input[type='url'],
22
+ input[type='color'],
23
+ input[type='date'],
24
+ input[type='datetime'],
25
+ input[type='datetime-local'],
26
+ input[type='month'],
27
+ input[type='time'],
28
+ input[type='week'],
29
+ textarea {
30
+ border: 0;
31
+ background: ${(props) => props.theme.colors.inputBackground};
32
+
33
+ &::placeholder {
34
+ font-weight: ${(props) => props.theme.typography.fontWeightLight};
35
+ color: ${(props) => props.theme.colors.inputPlaceholder};
36
+ }
37
+
38
+ &:focus {
39
+ outline: none;
40
+ }
41
+ }
42
+
43
+ /* Row styles */
44
+ [data-row-span] {
45
+ border-bottom: 1px solid ${(props) => props.theme.colors.border};
46
+ width: 100%;
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+
50
+ @media only screen and (max-width: 768px) {
51
+ border-bottom: none;
52
+ }
53
+ }
54
+
55
+ /* Field container styles */
56
+ [data-field-span] {
57
+ padding: ${(props) => props.theme.spacing.sm};
58
+ position: relative;
59
+
60
+ label {
61
+ display: block;
62
+ font-size: ${(props) => props.theme.typography.fontSizeSmall};
63
+ color: ${(props) => props.theme.colors.textPrimary};
64
+ text-transform: uppercase;
65
+ letter-spacing: 0.5px;
66
+ margin-bottom: ${(props) => props.theme.spacing.xs};
67
+ }
68
+
69
+ &.focus {
70
+ background-color: ${(props) => props.theme.colors.focusBackground};
71
+ }
72
+ }
73
+
74
+ /* Responsive behavior */
75
+ @media only screen and (max-width: 768px) {
76
+ [data-row-span] {
77
+ flex-direction: column;
78
+ }
79
+
80
+ [data-field-span] {
81
+ border-bottom: 1px solid ${(props) => props.theme.colors.border};
82
+ }
83
+ }
84
+ `;
85
+ export const GridForm = ({ children, onSubmit, className, }) => {
86
+ return (_jsx(StyledGridForm, { className: `grid-form ${className || ''}`, onSubmit: onSubmit, children: children }));
87
+ };
88
+ //# sourceMappingURL=GridForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GridForm.js","sourceRoot":"","sources":["../../src/components/GridForm.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAQvC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4BhB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe;;;qBAG1C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,eAAe;eACvD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB;;;;;;;;;;+BAU9B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;;;;;;;;;;;;eAYpD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;;;;;mBAK7B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa;eACnD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW;;;uBAGjC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;;;;0BAI9B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe;;;;;;;;;;;iCAWtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;;;CAGpE,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAA4B,CAAC,EAChD,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,KAAC,cAAc,IACb,SAAS,EAAE,aAAa,SAAS,IAAI,EAAE,EAAE,EACzC,QAAQ,EAAE,QAAQ,YAEjB,QAAQ,GACM,CAClB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface ThemeToggleProps {
3
+ className?: string;
4
+ }
5
+ export declare const ThemeToggle: React.FC<ThemeToggleProps>;
6
+ export {};
7
+ //# sourceMappingURL=ThemeToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../src/components/ThemeToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,gBAAgB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0BD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CASlD,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
3
+ import { useTheme } from '../theme/ThemeContext';
4
+ const ToggleButton = styled.button `
5
+ background: ${(props) => props.theme.colors.surface};
6
+ border: 1px solid ${(props) => props.theme.colors.border};
7
+ color: ${(props) => props.theme.colors.textPrimary};
8
+ padding: ${(props) => props.theme.spacing.sm}
9
+ ${(props) => props.theme.spacing.md};
10
+ border-radius: ${(props) => props.theme.borderRadius.md};
11
+ cursor: pointer;
12
+ font-size: ${(props) => props.theme.typography.fontSizeBase};
13
+ transition: all 0.2s ease;
14
+
15
+ &:hover {
16
+ background: ${(props) => props.theme.colors.hover};
17
+ }
18
+
19
+ &:active {
20
+ background: ${(props) => props.theme.colors.active};
21
+ }
22
+ `;
23
+ const ToggleIcon = styled.span `
24
+ margin-right: ${(props) => props.theme.spacing.xs};
25
+ `;
26
+ export const ThemeToggle = ({ className }) => {
27
+ const { themeMode, toggleTheme } = useTheme();
28
+ return (_jsxs(ToggleButton, { onClick: toggleTheme, className: className, children: [_jsx(ToggleIcon, { children: themeMode === 'light' ? '🌙' : '☀️' }), themeMode === 'light' ? 'Dark Mode' : 'Light Mode'] }));
29
+ };
30
+ //# sourceMappingURL=ThemeToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeToggle.js","sourceRoot":"","sources":["../../src/components/ThemeToggle.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMjD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAA;gBAClB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;sBAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;WAC/C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW;aACvC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;MACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;mBACpB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;;eAE1C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY;;;;kBAI3C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK;;;;kBAInC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;;CAErD,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;kBACZ,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;CAClD,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAA+B,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;IACvE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE9C,OAAO,CACL,MAAC,YAAY,IAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,aACtD,KAAC,UAAU,cAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAc,EAC7D,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,IACtC,CAChB,CAAC;AACJ,CAAC,CAAC"}