@g4rcez/components 3.0.0 → 3.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.
Files changed (176) hide show
  1. package/dist/ai/SKILL.md +266 -0
  2. package/dist/ai/docs/Alert.md +167 -0
  3. package/dist/ai/docs/AnimatedList.md +205 -0
  4. package/dist/ai/docs/Autocomplete.md +225 -0
  5. package/dist/ai/docs/Button.md +182 -0
  6. package/dist/ai/docs/Calendar.md +219 -0
  7. package/dist/ai/docs/Card.md +174 -0
  8. package/dist/ai/docs/Checkbox.md +199 -0
  9. package/dist/ai/docs/CommandPalette.md +293 -0
  10. package/dist/ai/docs/DatePicker.md +171 -0
  11. package/dist/ai/docs/Dropdown.md +223 -0
  12. package/dist/ai/docs/Empty.md +163 -0
  13. package/dist/ai/docs/Expand.md +143 -0
  14. package/dist/ai/docs/FileUpload.md +225 -0
  15. package/dist/ai/docs/Form.md +107 -0
  16. package/dist/ai/docs/FormReset.md +117 -0
  17. package/dist/ai/docs/Heading.md +88 -0
  18. package/dist/ai/docs/Input.md +237 -0
  19. package/dist/ai/docs/InputField.md +170 -0
  20. package/dist/ai/docs/List.md +205 -0
  21. package/dist/ai/docs/Menu.md +166 -0
  22. package/dist/ai/docs/Modal.md +280 -0
  23. package/dist/ai/docs/MultiSelect.md +196 -0
  24. package/dist/ai/docs/Notifications.md +231 -0
  25. package/dist/ai/docs/PageCalendar.md +271 -0
  26. package/dist/ai/docs/Polymorph.md +159 -0
  27. package/dist/ai/docs/Progress.md +145 -0
  28. package/dist/ai/docs/Radiobox.md +128 -0
  29. package/dist/ai/docs/RenderOnView.md +138 -0
  30. package/dist/ai/docs/Resizable.md +159 -0
  31. package/dist/ai/docs/Select.md +284 -0
  32. package/dist/ai/docs/Shortcut.md +105 -0
  33. package/dist/ai/docs/Skeleton.md +166 -0
  34. package/dist/ai/docs/Slider.md +144 -0
  35. package/dist/ai/docs/Slot.md +173 -0
  36. package/dist/ai/docs/Spinner.md +118 -0
  37. package/dist/ai/docs/Stats.md +137 -0
  38. package/dist/ai/docs/Step.md +159 -0
  39. package/dist/ai/docs/Switch.md +167 -0
  40. package/dist/ai/docs/Table.md +298 -0
  41. package/dist/ai/docs/Tabs.md +191 -0
  42. package/dist/ai/docs/Tag.md +224 -0
  43. package/dist/ai/docs/TaskList.md +144 -0
  44. package/dist/ai/docs/Textarea.md +167 -0
  45. package/dist/ai/docs/Timeline.md +210 -0
  46. package/dist/ai/docs/Toolbar.md +132 -0
  47. package/dist/ai/docs/Tooltip.md +231 -0
  48. package/dist/ai/docs/TransferList.md +142 -0
  49. package/dist/ai/docs/Typography.md +187 -0
  50. package/dist/ai/docs/Wizard.md +213 -0
  51. package/dist/ai/docs/index.md +183 -0
  52. package/dist/components/core/tag.d.ts +1 -1
  53. package/dist/components/core/tag.d.ts.map +1 -1
  54. package/dist/components/display/list.d.ts.map +1 -1
  55. package/dist/components/floating/dropdown.d.ts +1 -0
  56. package/dist/components/floating/dropdown.d.ts.map +1 -1
  57. package/dist/components/floating/menu.d.ts.map +1 -1
  58. package/dist/config/default-translations.d.ts +4 -4
  59. package/dist/hooks/use-translations.d.ts +4 -4
  60. package/dist/hooks/use-translations.d.ts.map +1 -1
  61. package/dist/index.css +1 -1
  62. package/dist/index.js +28 -20
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +2463 -2458
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/index.umd.js +12 -12
  67. package/dist/index.umd.js.map +1 -1
  68. package/package.json +4 -4
  69. package/dist/components/core/button.jsx +0 -79
  70. package/dist/components/core/heading.jsx +0 -4
  71. package/dist/components/core/polymorph.jsx +0 -5
  72. package/dist/components/core/render-on-view.jsx +0 -31
  73. package/dist/components/core/resizable.jsx +0 -51
  74. package/dist/components/core/slot.jsx +0 -156
  75. package/dist/components/core/tag.jsx +0 -51
  76. package/dist/components/core/typography.jsx +0 -22
  77. package/dist/components/display/alert.jsx +0 -58
  78. package/dist/components/display/calendar.jsx +0 -299
  79. package/dist/components/display/card.jsx +0 -43
  80. package/dist/components/display/empty.jsx +0 -11
  81. package/dist/components/display/list.jsx +0 -81
  82. package/dist/components/display/notifications.jsx +0 -126
  83. package/dist/components/display/progress.jsx +0 -11
  84. package/dist/components/display/shortcut.jsx +0 -23
  85. package/dist/components/display/skeleton.jsx +0 -12
  86. package/dist/components/display/spinner.jsx +0 -7
  87. package/dist/components/display/stats.jsx +0 -20
  88. package/dist/components/display/step.jsx +0 -131
  89. package/dist/components/display/tabs.jsx +0 -98
  90. package/dist/components/display/timeline.jsx +0 -25
  91. package/dist/components/floating/command-palette.jsx +0 -194
  92. package/dist/components/floating/dropdown.jsx +0 -53
  93. package/dist/components/floating/expand.jsx +0 -44
  94. package/dist/components/floating/menu.jsx +0 -147
  95. package/dist/components/floating/modal.jsx +0 -299
  96. package/dist/components/floating/toolbar.jsx +0 -5
  97. package/dist/components/floating/tooltip.jsx +0 -58
  98. package/dist/components/floating/wizard.jsx +0 -161
  99. package/dist/components/form/autocomplete.jsx +0 -279
  100. package/dist/components/form/checkbox.jsx +0 -12
  101. package/dist/components/form/date-picker.jsx +0 -115
  102. package/dist/components/form/file-upload.jsx +0 -133
  103. package/dist/components/form/form.jsx +0 -10
  104. package/dist/components/form/formReset.jsx +0 -17
  105. package/dist/components/form/free-text.jsx +0 -41
  106. package/dist/components/form/input-field.jsx +0 -56
  107. package/dist/components/form/input.jsx +0 -36
  108. package/dist/components/form/multi-select.jsx +0 -328
  109. package/dist/components/form/radiobox.jsx +0 -6
  110. package/dist/components/form/select.jsx +0 -42
  111. package/dist/components/form/slider.jsx +0 -45
  112. package/dist/components/form/switch.jsx +0 -46
  113. package/dist/components/form/task-list.jsx +0 -26
  114. package/dist/components/form/textarea.jsx +0 -12
  115. package/dist/components/form/transfer-list.jsx +0 -39
  116. package/dist/components/index.js +0 -45
  117. package/dist/components/page-calendar/calendar-header.jsx +0 -81
  118. package/dist/components/page-calendar/day-view.jsx +0 -87
  119. package/dist/components/page-calendar/event-pill.jsx +0 -25
  120. package/dist/components/page-calendar/index.js +0 -2
  121. package/dist/components/page-calendar/month-view.jsx +0 -47
  122. package/dist/components/page-calendar/page-calendar.jsx +0 -41
  123. package/dist/components/page-calendar/page-calendar.types.js +0 -1
  124. package/dist/components/page-calendar/page-calendar.utils.js +0 -71
  125. package/dist/components/page-calendar/week-view.jsx +0 -64
  126. package/dist/components/table/filter.jsx +0 -141
  127. package/dist/components/table/group.jsx +0 -68
  128. package/dist/components/table/index.jsx +0 -60
  129. package/dist/components/table/inner-table.jsx +0 -104
  130. package/dist/components/table/metadata.jsx +0 -36
  131. package/dist/components/table/pagination.jsx +0 -73
  132. package/dist/components/table/row.jsx +0 -58
  133. package/dist/components/table/sort.jsx +0 -105
  134. package/dist/components/table/table-lib.js +0 -83
  135. package/dist/components/table/table.context.jsx +0 -4
  136. package/dist/components/table/thead.jsx +0 -103
  137. package/dist/config/context.js +0 -12
  138. package/dist/config/default-translations.jsx +0 -83
  139. package/dist/config/default-tweaks.js +0 -4
  140. package/dist/constants.js +0 -2
  141. package/dist/hooks/use-click-outside.js +0 -17
  142. package/dist/hooks/use-color-parser.js +0 -9
  143. package/dist/hooks/use-components-provider.jsx +0 -19
  144. package/dist/hooks/use-debounce.js +0 -12
  145. package/dist/hooks/use-floating-ref.js +0 -6
  146. package/dist/hooks/use-form.js +0 -550
  147. package/dist/hooks/use-hover.js +0 -18
  148. package/dist/hooks/use-input-id.js +0 -5
  149. package/dist/hooks/use-is-coarse-device.js +0 -12
  150. package/dist/hooks/use-locale.js +0 -10
  151. package/dist/hooks/use-media-query.js +0 -25
  152. package/dist/hooks/use-on-event.js +0 -7
  153. package/dist/hooks/use-parent.js +0 -21
  154. package/dist/hooks/use-preferences.js +0 -23
  155. package/dist/hooks/use-previous.js +0 -9
  156. package/dist/hooks/use-reactive.js +0 -9
  157. package/dist/hooks/use-remove-scroll.js +0 -61
  158. package/dist/hooks/use-resize-observer.js +0 -17
  159. package/dist/hooks/use-stable-ref.js +0 -9
  160. package/dist/hooks/use-swipe.js +0 -17
  161. package/dist/hooks/use-translations.js +0 -9
  162. package/dist/hooks/use-tweaks.js +0 -9
  163. package/dist/hooks/use-window-size.js +0 -14
  164. package/dist/lib/combi-keys.js +0 -60
  165. package/dist/lib/dict.js +0 -39
  166. package/dist/lib/dom.js +0 -62
  167. package/dist/lib/fns.js +0 -46
  168. package/dist/lib/fzf.js +0 -117
  169. package/dist/lib/keyboard-area.js +0 -14
  170. package/dist/styles/common.js +0 -29
  171. package/dist/styles/dark.js +0 -214
  172. package/dist/styles/design-tokens.js +0 -69
  173. package/dist/styles/light.js +0 -214
  174. package/dist/styles/theme.js +0 -4
  175. package/dist/styles/theme.types.js +0 -1
  176. package/dist/types.js +0 -1
@@ -0,0 +1,225 @@
1
+ ---
2
+ title: FileUpload
3
+ description: Drag-and-drop file upload area with file preview, modal viewer, and per-file deletion.
4
+ package: "@g4rcez/components"
5
+ export: "{ FileUpload }"
6
+ import: "import { FileUpload } from '@g4rcez/components/file-upload'"
7
+ category: form
8
+ ---
9
+
10
+ # FileUpload
11
+
12
+ Drag-and-drop file upload area with file preview, modal viewer, and per-file deletion.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { FileUpload } from "@g4rcez/components/file-upload";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `files` | `File[]` | - | Controlled files array |
25
+ | `onDrop` | `(files: File[]) => void` | - | Called when files are dropped or selected |
26
+ | `onDeleteFile` | `(file: File) => void` | - | Called when the delete button on a file item is clicked |
27
+ | `idle` | `React.ReactElement` | Default idle UI | Content to show when no files are present and the area is not active |
28
+ | `File` | `React.FC<{ file: File }>` | - | Custom component rendered below each file's name/size row |
29
+ | `accept` | `string \| Record<string, string[]>` | - | Accepted file types (forwarded to `react-dropzone`) |
30
+ | `multiple` | `boolean` | `false` | Allow selecting more than one file |
31
+ | `maxFiles` | `number` | - | Maximum number of files |
32
+ | `maxSize` | `number` | - | Maximum file size in bytes |
33
+ | `disabled` | `boolean` | `false` | Disable the drop zone |
34
+ | `name` | `string` | - | Name for the underlying `<input>` |
35
+ | `...DropzoneProps` | | | All `react-dropzone` props are supported |
36
+
37
+ ## Design Tokens
38
+
39
+ Tokens this component reads. Customize by overriding these CSS variables in your theme.
40
+
41
+ | Token | CSS Variable | Purpose |
42
+ |-------|-------------|---------|
43
+ | `border-card-border` | `--card-border` | Border between file list items and default drop zone border |
44
+ | `bg-card-background` | `--card-background` | Drop zone background when files are present |
45
+ | `text-foreground` | `--foreground` | General text color |
46
+ | `text-primary` | `--primary` | Folder icon color and "browse" link color in default idle state |
47
+ | `text-danger` | `--danger` | Delete button hover color |
48
+
49
+ ## Drag and Drop States
50
+
51
+ | State | Description |
52
+ |-------|-------------|
53
+ | Idle (empty) | Displays the `idle` prop or the default folder icon with an upload prompt |
54
+ | Drag active | Replaces the idle UI with an open folder icon while dragging |
55
+ | Files present | Renders the file list; drop zone border becomes solid and background fills |
56
+
57
+ ## File Type Rendering
58
+
59
+ The component automatically selects an icon based on file extension:
60
+
61
+ | Extension(s) | Icon |
62
+ |---|---|
63
+ | csv, xls, xlsx | `SheetIcon` |
64
+ | pdf, txt | `FileTextIcon` |
65
+ | json | `FileJsonIcon` |
66
+ | mp3 | `AudioLinesIcon` |
67
+ | mp4, mov | `FileVideo2` |
68
+ | Images | Inline `<img>` thumbnail |
69
+ | Other | Generic `FileIcon` |
70
+
71
+ Clicking a file thumbnail opens a `Modal` viewer with full-size preview for images, `<video>` player for videos, and `<audio>` player for audio files.
72
+
73
+ ## Examples
74
+
75
+ ### Controlled image upload
76
+
77
+ ```tsx
78
+ import { FileUpload } from "@g4rcez/components/file-upload";
79
+
80
+ function ImageUpload() {
81
+ const [images, setImages] = useState<File[]>([]);
82
+
83
+ return (
84
+ <FileUpload
85
+ files={images}
86
+ onDrop={(added) => setImages((prev) => [...prev, ...added])}
87
+ onDeleteFile={(file) => setImages((prev) => prev.filter((f) => f !== file))}
88
+ accept="image/*"
89
+ multiple
90
+ maxFiles={10}
91
+ maxSize={5 * 1024 * 1024}
92
+ />
93
+ );
94
+ }
95
+ ```
96
+
97
+ ### Single file upload
98
+
99
+ ```tsx
100
+ function AvatarUpload() {
101
+ const [file, setFile] = useState<File | null>(null);
102
+
103
+ return (
104
+ <FileUpload
105
+ files={file ? [file] : []}
106
+ onDrop={(files) => setFile(files[0])}
107
+ onDeleteFile={() => setFile(null)}
108
+ accept="image/jpeg,image/png"
109
+ multiple={false}
110
+ maxSize={2 * 1024 * 1024}
111
+ />
112
+ );
113
+ }
114
+ ```
115
+
116
+ ### Custom idle state
117
+
118
+ ```tsx
119
+ import { UploadCloudIcon } from "lucide-react";
120
+
121
+ const CustomIdle = () => (
122
+ <div className="flex flex-col items-center gap-2 py-10">
123
+ <UploadCloudIcon size={48} className="text-primary" />
124
+ <p className="text-foreground font-medium">Drop files here</p>
125
+ <p className="text-muted-foreground text-sm">PDF, DOCX, up to 10 MB each</p>
126
+ </div>
127
+ );
128
+
129
+ <FileUpload
130
+ files={[]}
131
+ onDrop={setFiles}
132
+ idle={<CustomIdle />}
133
+ accept="application/pdf,.docx"
134
+ multiple
135
+ />
136
+ ```
137
+
138
+ ### Custom per-file renderer
139
+
140
+ ```tsx
141
+ const ProgressRow = ({ file }: { file: File }) => {
142
+ const progress = useUploadProgress(file);
143
+ return (
144
+ <div className="flex flex-col gap-1 pb-2">
145
+ <div className="flex justify-between text-xs text-muted-foreground">
146
+ <span>{progress < 100 ? "Uploading..." : "Done"}</span>
147
+ <span>{progress}%</span>
148
+ </div>
149
+ <div className="h-1.5 rounded-full bg-muted overflow-hidden">
150
+ <div
151
+ className="h-full rounded-full bg-primary transition-all"
152
+ style={{ width: `${progress}%` }}
153
+ />
154
+ </div>
155
+ </div>
156
+ );
157
+ };
158
+
159
+ <FileUpload files={files} onDrop={setFiles} File={ProgressRow} multiple />
160
+ ```
161
+
162
+ ### Inside a form
163
+
164
+ ```tsx
165
+ import { Form } from "@g4rcez/components/form";
166
+ import { Button } from "@g4rcez/components/button";
167
+
168
+ function SubmissionForm() {
169
+ const [attachments, setAttachments] = useState<File[]>([]);
170
+
171
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
172
+ const data = new FormData(e.currentTarget);
173
+ attachments.forEach((f) => data.append("attachments", f));
174
+ submitToServer(data);
175
+ };
176
+
177
+ return (
178
+ <Form onSubmit={handleSubmit} className="flex flex-col gap-base">
179
+ <FileUpload
180
+ name="attachments"
181
+ files={attachments}
182
+ onDrop={(added) => setAttachments((prev) => [...prev, ...added])}
183
+ onDeleteFile={(f) => setAttachments((prev) => prev.filter((x) => x !== f))}
184
+ accept="image/*,.pdf"
185
+ multiple
186
+ maxSize={10 * 1024 * 1024}
187
+ />
188
+ <Button theme="primary" type="submit">Submit</Button>
189
+ </Form>
190
+ );
191
+ }
192
+ ```
193
+
194
+ ## Do
195
+
196
+ - Always set `accept` to restrict uploads to the file types your server expects.
197
+ - Set `maxSize` to provide immediate client-side feedback for oversized files.
198
+ - Use `multiple` when batch uploads are expected.
199
+ - Use the `File` prop to add progress bars, metadata, or custom actions below each file row.
200
+ - Use design-token classes for wrapper elements (`bg-card-background`, `text-foreground`).
201
+
202
+ ## Don't
203
+
204
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`, `border-gray-300`) — use theme props or design tokens instead.
205
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`, `bg-[--my-var]`) — override CSS variables in your `@theme` block instead.
206
+ - Don't rely solely on client-side `maxSize`/`accept` — validate files server-side as well.
207
+ - Don't skip `onDeleteFile` when `files` is controlled — without it, users cannot remove files they added.
208
+
209
+ ## Accessibility
210
+
211
+ - The drop zone uses `react-dropzone`'s `getRootProps` and `getInputProps`, which include keyboard support (Enter/Space to open the file browser).
212
+ - The hidden `<input type="file">` is accessible by assistive technologies.
213
+ - Delete buttons include a `type="button"` to prevent accidental form submission.
214
+ - The modal viewer opened for file preview is managed by the `Modal` component, which handles focus trapping and Escape to close.
215
+
216
+ ## Data Attributes
217
+
218
+ - `data-active="true"` — on the drop zone wrapper when at least one file is present; used to switch between dashed (empty) and solid (filled) border styles.
219
+
220
+ ## Notes
221
+
222
+ - When `files` is not provided, the component manages its own internal file state. Pass `files` for fully controlled behavior.
223
+ - Object URLs created for previews are revoked on cleanup via `useEffect` to prevent memory leaks.
224
+ - The `File` prop (custom renderer) is rendered inside the file list item, below the file name and size row, alongside the built-in delete button.
225
+ - The component depends on `react-dropzone` and `pretty-bytes` as peer dependencies.
@@ -0,0 +1,107 @@
1
+ ---
2
+ title: Form
3
+ description: Thin wrapper around the HTML form element that calls preventDefault automatically before invoking onSubmit.
4
+ package: "@g4rcez/components"
5
+ export: "{ Form }"
6
+ import: "import { Form } from '@g4rcez/components/form'"
7
+ category: form
8
+ ---
9
+
10
+ # Form
11
+
12
+ Thin wrapper around the HTML `<form>` element that calls `preventDefault` automatically before invoking `onSubmit`.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Form } from "@g4rcez/components/form";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ `Form` accepts all standard HTML `<form>` attributes.
23
+
24
+ | Prop | Type | Default | Description |
25
+ |------|------|---------|-------------|
26
+ | `onSubmit` | `(event: React.FormEvent<HTMLFormElement>) => void` | - | Submit handler. `preventDefault()` is called before this. |
27
+ | `children` | `React.ReactNode` | - | Form fields and other content. |
28
+ | `className` | `string` | - | CSS classes for the `<form>` element. |
29
+ | `...props` | `React.ComponentProps<"form">` | - | All standard form attributes (`action`, `method`, `noValidate`, etc.). |
30
+
31
+ ## Design Tokens
32
+
33
+ `Form` has no direct token usage. Tokens are applied by the child components (`Input`, `Button`, etc.) placed inside it.
34
+
35
+ ## Examples
36
+
37
+ ### Login form
38
+
39
+ ```tsx
40
+ import { Form } from "@g4rcez/components/form";
41
+ import { Input } from "@g4rcez/components/input";
42
+ import { Button } from "@g4rcez/components/button";
43
+
44
+ function LoginForm() {
45
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
46
+ const data = new FormData(e.currentTarget);
47
+ console.log(Object.fromEntries(data));
48
+ };
49
+
50
+ return (
51
+ <Form onSubmit={handleSubmit} className="flex flex-col gap-base max-w-sm">
52
+ <Input name="email" type="email" title="Email" required />
53
+ <Input name="password" type="password" title="Password" required />
54
+ <Button theme="primary" type="submit">Log in</Button>
55
+ </Form>
56
+ );
57
+ }
58
+ ```
59
+
60
+ ### Reading FormData on submit
61
+
62
+ ```tsx
63
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
64
+ const formData = new FormData(e.currentTarget);
65
+ const payload = Object.fromEntries(formData);
66
+ await fetch("/api/contact", { method: "POST", body: JSON.stringify(payload) });
67
+ };
68
+
69
+ <Form onSubmit={handleSubmit} className="flex flex-col gap-base">
70
+ <Input name="name" title="Name" required />
71
+ <Input name="message" title="Message" />
72
+ <Button theme="primary" type="submit">Send</Button>
73
+ </Form>
74
+ ```
75
+
76
+ ### Multi-column layout
77
+
78
+ ```tsx
79
+ <Form className="grid grid-cols-2 gap-base max-w-2xl">
80
+ <Input name="firstName" title="First name" required />
81
+ <Input name="lastName" title="Last name" required />
82
+ <Input name="email" type="email" title="Email" container="col-span-2" required />
83
+ <Button type="submit" theme="primary" container="col-start-2">Save</Button>
84
+ </Form>
85
+ ```
86
+
87
+ ## Do
88
+
89
+ - Use `Form` instead of a raw `<form>` to avoid calling `e.preventDefault()` in every submit handler.
90
+ - Always include a `<Button type="submit">` or `<button type="submit">` so keyboard users can submit with Enter.
91
+ - Use design-token layout utilities (`gap-base`, `gap-sm`) for consistent spacing between fields.
92
+
93
+ ## Don't
94
+
95
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`, `border-gray-300`) to `Form` — use theme props or design tokens instead.
96
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block instead.
97
+ - Don't use `Form` when you need a traditional server-rendered full-page reload; use a plain `<form>` with `action` and `method` instead.
98
+
99
+ ## Accessibility
100
+
101
+ - Renders a semantic `<form>` element, correctly identified by assistive technologies.
102
+ - Ensure every field inside the form has an associated label (the `Input`, `Select`, and other components in this library do this automatically via `InputField`).
103
+
104
+ ## Notes
105
+
106
+ - `Form` is intentionally minimal — it has no state, no validation logic, and no styling. All field-level behavior is delegated to child components.
107
+ - The `e.persist()` call inside the wrapper ensures the synthetic event remains accessible in async submit handlers.
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: formReset
3
+ description: Utility function that resets all inputs and selects in a form to their default values and clears their initialization state.
4
+ package: "@g4rcez/components"
5
+ export: "{ formReset }"
6
+ import: "import { formReset } from '@g4rcez/components'"
7
+ category: form
8
+ ---
9
+
10
+ # formReset
11
+
12
+ Utility function that resets all inputs and selects in a form to their default values and clears their initialization state.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { formReset } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Signature
21
+
22
+ ```ts
23
+ function formReset(form?: HTMLFormElement | null): void
24
+ ```
25
+
26
+ ## Parameters
27
+
28
+ | Parameter | Type | Description |
29
+ |-----------|------|-------------|
30
+ | `form` | `HTMLFormElement \| null \| undefined` | The form element to reset. Safely no-ops if `null` or `undefined`. |
31
+
32
+ ## How It Works
33
+
34
+ 1. Iterates over all elements in the form (`form.elements`).
35
+ 2. For `<input>` elements: sets `input.value` to `input.defaultValue`.
36
+ 3. For `<select>` elements: sets `select.value` to `""`.
37
+ 4. On every processed field: sets `data-initialized="false"`, which tells components like `Input` and `Autocomplete` to treat the field as untouched (suppressing validation messages).
38
+
39
+ ## Examples
40
+
41
+ ### Reset after successful submission
42
+
43
+ ```tsx
44
+ import { useRef } from "react";
45
+ import { Form } from "@g4rcez/components/form";
46
+ import { Input } from "@g4rcez/components/input";
47
+ import { Button } from "@g4rcez/components/button";
48
+ import { formReset } from "@g4rcez/components";
49
+
50
+ function ContactForm() {
51
+ const formRef = useRef<HTMLFormElement>(null);
52
+
53
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
54
+ const data = new FormData(e.currentTarget);
55
+ await submitToServer(Object.fromEntries(data));
56
+ formReset(formRef.current);
57
+ };
58
+
59
+ return (
60
+ <Form ref={formRef} onSubmit={handleSubmit} className="flex flex-col gap-base">
61
+ <Input name="name" title="Name" required />
62
+ <Input name="email" type="email" title="Email" required />
63
+ <Button theme="primary" type="submit">Send</Button>
64
+ </Form>
65
+ );
66
+ }
67
+ ```
68
+
69
+ ### Cancel button that resets the form
70
+
71
+ ```tsx
72
+ function EditForm({ defaultValues }: { defaultValues: Record<string, string> }) {
73
+ const formRef = useRef<HTMLFormElement>(null);
74
+
75
+ return (
76
+ <Form ref={formRef} onSubmit={handleSave} className="flex flex-col gap-base">
77
+ <Input name="title" title="Title" defaultValue={defaultValues.title} />
78
+ <Input name="description" title="Description" defaultValue={defaultValues.description} />
79
+ <div className="flex gap-sm">
80
+ <Button theme="primary" type="submit">Save</Button>
81
+ <Button
82
+ theme="ghost"
83
+ type="button"
84
+ onClick={() => formReset(formRef.current)}
85
+ >
86
+ Cancel
87
+ </Button>
88
+ </div>
89
+ </Form>
90
+ );
91
+ }
92
+ ```
93
+
94
+ ## Do
95
+
96
+ - Use `formReset` (instead of `form.reset()`) when the form contains library components — it also resets the `data-initialized` flag that controls validation UI.
97
+ - Pass a valid `HTMLFormElement` ref.
98
+
99
+ ## Don't
100
+
101
+ - Don't expect `formReset` to fire `onChange` events — it modifies `value` directly in the DOM without dispatching React synthetic events.
102
+ - Don't use `formReset` to reset a single field; use standard DOM methods or React state for that.
103
+ - Don't use `formReset` as a substitute for React-controlled state management in complex forms.
104
+
105
+ ## Accessibility
106
+
107
+ No direct accessibility implications. After a reset, validation error messages will disappear because `data-initialized="false"` prevents them from being shown again until the user interacts with each field.
108
+
109
+ ## Data Attributes
110
+
111
+ - Sets `data-initialized="false"` on every `INPUT` and `SELECT` element in the form. This attribute is read by `InputField` to decide whether to display validation feedback.
112
+
113
+ ## Notes
114
+
115
+ - Safe to call with `null` or `undefined` — the function returns early without throwing.
116
+ - Only processes elements with `tagName === "INPUT"` or `tagName === "SELECT"`. `<textarea>` elements are not currently reset by this utility.
117
+ - This is a plain function, not a React component or hook. It works on DOM references directly.
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: Heading
3
+ description: A minimal heading wrapper that renders as h2 by default, delegating to Polymorph for element flexibility.
4
+ package: "@g4rcez/components"
5
+ export: "{ Heading }"
6
+ import: "import { Heading } from '@g4rcez/components'"
7
+ category: core
8
+ ---
9
+
10
+ # Heading
11
+
12
+ A minimal heading wrapper that renders as `h2` by default. It delegates to `Polymorph` internally, so all children are forwarded without additional styling or tokens.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Heading } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `children` | `React.ReactNode` | - | The content of the heading |
25
+
26
+ ## Design Tokens
27
+
28
+ None — `Heading` itself applies no styles. Style via `className` passed to the component or global heading rules in your theme.
29
+
30
+ ## Examples
31
+
32
+ ### Default Usage
33
+
34
+ ```tsx
35
+ <Heading>Section Title</Heading>
36
+ ```
37
+
38
+ ### Custom Heading Level
39
+
40
+ The current implementation always renders as `h2`. Use the `Polymorph` component directly if you need a different heading level.
41
+
42
+ ```tsx
43
+ import { Polymorph } from "@g4rcez/components";
44
+
45
+ <Polymorph as="h1" className="text-3xl font-bold tracking-tight text-foreground">
46
+ Page Title
47
+ </Polymorph>
48
+
49
+ <Polymorph as="h3" className="text-lg font-semibold text-foreground">
50
+ Subsection Title
51
+ </Polymorph>
52
+ ```
53
+
54
+ ### Applying Typography Styles
55
+
56
+ ```tsx
57
+ <Heading className="text-2xl font-bold text-foreground">
58
+ Dashboard Overview
59
+ </Heading>
60
+ ```
61
+
62
+ ## Do
63
+
64
+ - Use `Heading` for `h2`-level section titles throughout your app to ensure a consistent element
65
+ - Use design-token classes for color (`text-foreground`, `text-muted-foreground`) — never raw color utilities
66
+ - Pair with `PageHeader` or `PageTitle` from the Typography components for full page structure
67
+
68
+ ## Don't
69
+
70
+ - Don't pass raw Tailwind color classes (`text-gray-900`, `text-black`) — use `text-foreground` instead
71
+ - Don't use arbitrary Tailwind values (`text-[#333]`) — override CSS variables in your `@theme` block
72
+ - Don't skip heading hierarchy — if you need `h1` or `h3`, use `Polymorph as="h1"` rather than misusing `Heading`
73
+ - Don't use `Heading` for non-heading content purely for visual sizing
74
+
75
+ ## Accessibility
76
+
77
+ - Renders as `<h2>` by default, providing semantic structure for screen readers and document outline tools
78
+ - Pass `className` for visual styling without altering the semantic element
79
+ - Ensure each page has a single `h1` (use `Polymorph as="h1"`) before using `Heading` (`h2`) for section titles
80
+
81
+ ## Data Attributes
82
+
83
+ - `data-component="polymorph"`: Inherited from the underlying `Polymorph` component
84
+
85
+ ## Notes
86
+
87
+ - `Heading` is a thin wrapper — it accepts `children` only; all other styling is done via `className`
88
+ - If you need an `as` prop for dynamic heading levels, use `Polymorph` directly