@emiketic/lib-mantine 1.0.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.
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # @emiketic/lib-mantine
2
+
3
+ A collection of handy components built on [Mantine v9](https://mantine.dev) components.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @emiketic/lib-mantine
9
+ ```
10
+
11
+ ### Peer dependencies
12
+
13
+ Make sure the following are installed in your project:
14
+
15
+ ```bash
16
+ npm install react react-dom @mantine/core @tabler/icons-react
17
+ ```
18
+
19
+ ### CSS
20
+
21
+ Import Mantine's base CSS in your app entry point (e.g. `_app.tsx` or `layout.tsx`):
22
+
23
+ ```tsx
24
+ import '@mantine/core/styles.css';
25
+ ```
26
+
27
+ For `TextEditor`, also import:
28
+
29
+ ```tsx
30
+ import '@mantine/tiptap/styles.css';
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Components
36
+
37
+ ### `ClientOnly`
38
+
39
+ Prevents SSR hydration mismatches by rendering children only after the component mounts on the client.
40
+
41
+ | Prop | Type | Default | Description |
42
+ |---|---|---|---|
43
+ | `children` | `ReactNode` | — | Content to render |
44
+ | `withLoader` | `boolean` | `false` | Show a `LoadingOverlay` while waiting for mount |
45
+
46
+ ```tsx
47
+ import { ClientOnly } from '@emiketic/lib-mantine';
48
+
49
+ <ClientOnly>
50
+ <MyClientSideWidget />
51
+ </ClientOnly>
52
+ ```
53
+
54
+ ---
55
+
56
+ ### `ConfirmBar`
57
+
58
+ A form action bar with Confirm and Cancel buttons, typically placed at the bottom of a form.
59
+
60
+ | Prop | Type | Default | Description |
61
+ |---|---|---|---|
62
+ | `onConfirm` | `() => void` | — | Called when the confirm button is clicked |
63
+ | `onCancel` | `() => void` | `() => {}` | Called when the cancel button is clicked |
64
+ | `disabled` | `boolean` | `false` | Disables the confirm button |
65
+ | `loading` | `boolean` | `false` | Shows a loading spinner on the confirm button |
66
+ | `color` | `MantineColor` | — | Color of the confirm button |
67
+ | `withCancel` | `boolean` | `true` | Whether to show the cancel button |
68
+ | `labelProps` | `{ confirm?: string; cancel?: string }` | — | Custom button labels |
69
+
70
+ Also accepts all `BoxProps` from Mantine.
71
+
72
+ ```tsx
73
+ import { ConfirmBar } from '@emiketic/lib-mantine';
74
+
75
+ <ConfirmBar
76
+ onConfirm={handleSubmit}
77
+ onCancel={handleReset}
78
+ labelProps={{ confirm: 'Save', cancel: 'Discard' }}
79
+ color="blue"
80
+ />
81
+ ```
82
+
83
+ ---
84
+
85
+ ### `ContentLoader`
86
+
87
+ A skeleton loading placeholder made up of animated skeleton bars. Useful as a page-level or section-level loading state.
88
+
89
+ | Prop | Type | Default | Description |
90
+ |---|---|---|---|
91
+ | `numberOfBars` | `number` | `3` | Total skeleton bars across all groups |
92
+ | `numberOfBarGroups` | `number` | `3` | Number of bar groups (adds spacing between groups) |
93
+ | `barHeight` | `number` | `15` | Height of each skeleton bar in px |
94
+ | `barSpacing` | `number` | `6` | Vertical spacing between bars in px |
95
+ | `barGroupSpacing` | `MantineSpacing` | `'lg'` | Space between bar groups |
96
+ | `visible` | `boolean` | `true` | When `false`, renders nothing |
97
+ | `withCircle` | `boolean` | `false` | Add a circular skeleton (e.g. for avatar) at the top |
98
+
99
+ Also accepts all `StackProps` from Mantine.
100
+
101
+ ```tsx
102
+ import { ContentLoader } from '@emiketic/lib-mantine';
103
+
104
+ <ContentLoader visible={isLoading} withCircle />
105
+ ```
106
+
107
+ ---
108
+
109
+ ### `ImageInput`
110
+
111
+ A file input with an inline image preview. Supports both `File` objects and URL strings as value.
112
+
113
+ | Prop | Type | Default | Description |
114
+ |---|---|---|---|
115
+ | `value` | `File \| string \| null` | — | Current value (controlled) |
116
+ | `withPreview` | `boolean` | `true` | Show image thumbnail next to the input |
117
+ | `previewProps` | `ImageProps` | — | Props forwarded to the preview `<Image>` |
118
+ | `disabledPlaceholderProps` | `AvatarProps` | — | Props for the `<Avatar>` shown when disabled |
119
+ | `maxFileSizeBytes` | `number` | `500_000` | Max file size before showing a warning (bytes) |
120
+
121
+ Also accepts all `FileInputProps` from Mantine (except `value`).
122
+
123
+ ```tsx
124
+ import { ImageInput } from '@emiketic/lib-mantine';
125
+
126
+ const [file, setFile] = useState<File | null>(null);
127
+
128
+ <ImageInput
129
+ label="Logo"
130
+ value={file}
131
+ onChange={setFile}
132
+ maxFileSizeBytes={2_000_000}
133
+ />
134
+ ```
135
+
136
+ ---
137
+
138
+ ### `Logo`
139
+
140
+ An avatar-style component for displaying a business/brand logo. Optionally extracts the dominant color from the image and uses it as a background, creating a visually consistent color pair. Falls back to a building icon when no image is provided.
141
+
142
+ Requires `@emiketic/lib-utils` (installed automatically as a dependency).
143
+
144
+ | Prop | Type | Default | Description |
145
+ |---|---|---|---|
146
+ | `withColorPair` | `boolean` | `true` | Extract dominant color from image for background |
147
+
148
+ Also accepts all `AvatarProps` from Mantine.
149
+
150
+ ```tsx
151
+ import { Logo } from '@emiketic/lib-mantine';
152
+
153
+ <Logo src="https://example.com/logo.png" withColorPair />
154
+ ```
155
+
156
+ ---
157
+
158
+ ### `NativePDFViewer`
159
+
160
+ Renders a PDF file using the browser's native `<object>` tag with per-browser toolbar height correction. Handles Safari, Edge, Firefox, and Chromium-based browsers.
161
+
162
+ | Prop | Type | Default | Description |
163
+ |---|---|---|---|
164
+ | `mediaUrl` | `string` | — | URL of the PDF file |
165
+ | `title` | `string` | — | Accessible title for the object element |
166
+ | `zoomLevel` | `number` | — | Initial zoom percentage |
167
+ | `withToolbar` | `boolean` | `true` | Whether to show the browser's PDF toolbar |
168
+ | `fallback` | `ReactNode \| () => ReactNode` | Default message | Shown when the browser can't render PDFs |
169
+
170
+ ```tsx
171
+ import { NativePDFViewer } from '@emiketic/lib-mantine';
172
+
173
+ <div style={{ height: '600px' }}>
174
+ <NativePDFViewer mediaUrl="/files/report.pdf" withToolbar={false} />
175
+ </div>
176
+ ```
177
+
178
+ ---
179
+
180
+ ### `NoData`
181
+
182
+ A centered empty-state component using Mantine's `Alert`. Useful for lists, tables, or search results with no entries.
183
+
184
+ | Prop | Type | Default | Description |
185
+ |---|---|---|---|
186
+ | `title` | `string` | `'No data'` | Title shown in the alert |
187
+ | `alertProps` | `AlertProps` | — | Props forwarded to the `<Alert>` |
188
+ | `children` | `ReactNode` | — | Optional content below the title (e.g. a CTA) |
189
+
190
+ Also accepts all `CenterProps` from Mantine.
191
+
192
+ ```tsx
193
+ import { NoData } from '@emiketic/lib-mantine';
194
+
195
+ <NoData title="No reviews yet">
196
+ <Button>Be the first to review</Button>
197
+ </NoData>
198
+ ```
199
+
200
+ ---
201
+
202
+ ### `PageContainer`
203
+
204
+ A flexible page layout wrapper with optional title, header, right section, and scrollable content area. Useful for panel/dashboard-style pages.
205
+
206
+ | Prop | Type | Default | Description |
207
+ |---|---|---|---|
208
+ | `title` | `string` | — | Page title rendered as `<h2>` |
209
+ | `titleProps` | `TitleProps` | — | Props forwarded to `<Title>` |
210
+ | `header` | `ReactNode` | — | Custom header — overrides the default title + right section layout |
211
+ | `headerProps` | `GroupProps` | — | Props for the default header `<Group>` |
212
+ | `rightSection` | `ReactNode` | `null` | Rendered in the top-right corner of the header |
213
+ | `fullPage` | `boolean` | `false` | Removes the header and padding — just wraps content in a `<Box>` |
214
+ | `withContentScroll` | `boolean` | `false` | Makes the container a full-height `ScrollArea` |
215
+ | `contentProps` | `StackProps \| BoxProps` | — | Props for the inner content wrapper |
216
+ | `outerContentProps` | `StackProps` | — | Props for the outer content wrapper |
217
+
218
+ Also accepts all `ScrollAreaProps` from Mantine (used when `withContentScroll` is `true`).
219
+
220
+ ```tsx
221
+ import { PageContainer } from '@emiketic/lib-mantine';
222
+
223
+ <PageContainer title="Users" rightSection={<Button>Add user</Button>}>
224
+ <UserTable />
225
+ </PageContainer>
226
+ ```
227
+
228
+ ---
229
+
230
+ ### `PhoneInput`
231
+
232
+ An international phone number input combining a searchable country code selector with a phone number text input. Validates and normalizes to E.164 format using `libphonenumber-js`.
233
+
234
+ | Prop | Type | Default | Description |
235
+ |---|---|---|---|
236
+ | `value` | `string` | — | Phone number in E.164 format (e.g. `+21698765432`) |
237
+ | `defaultValue` | `string` | — | Uncontrolled initial value |
238
+ | `defaultCountryCode` | `CountryCode` | — | Pre-select a country code (e.g. `'TN'`, `'FR'`) |
239
+ | `onChange` | `(value: string) => void` | — | Called with the full E.164 number when valid |
240
+
241
+ Also accepts all `TextInputProps` from Mantine (except `onChange`).
242
+
243
+ ```tsx
244
+ import { PhoneInput } from '@emiketic/lib-mantine';
245
+
246
+ const [phone, setPhone] = useState('');
247
+
248
+ <PhoneInput
249
+ label="Mobile"
250
+ defaultCountryCode="FR"
251
+ value={phone}
252
+ onChange={setPhone}
253
+ />
254
+ ```
255
+
256
+ ---
257
+
258
+ ### `TextEditor`
259
+
260
+ A rich text editor built on [Tiptap](https://tiptap.dev) and [`@mantine/tiptap`](https://mantine.dev/x/tiptap/). Includes a sticky toolbar with formatting controls (bold, italic, headings, lists, links, alignment, etc.).
261
+
262
+ Requires importing `@mantine/tiptap/styles.css` in your app.
263
+
264
+ | Prop | Type | Default | Description |
265
+ |---|---|---|---|
266
+ | `content` | `string` | — | Initial HTML content |
267
+ | `value` | `string` | — | Alias for `content` |
268
+ | `onChangeEditorHTML` | `(html?: string) => void` | `() => {}` | Called with the current HTML on every change |
269
+ | `onChange` | `(html?: string) => void` | `() => {}` | Alias for `onChangeEditorHTML` |
270
+
271
+ Also accepts all `RichTextEditorProps` from `@mantine/tiptap` (except `editor`).
272
+
273
+ ```tsx
274
+ import { TextEditor } from '@emiketic/lib-mantine';
275
+ import '@mantine/tiptap/styles.css';
276
+
277
+ <TextEditor
278
+ content="<p>Initial content</p>"
279
+ onChangeEditorHTML={(html) => setBody(html)}
280
+ />
281
+ ```
282
+
283
+ ---
284
+
285
+ ### `ThemeToggle`
286
+
287
+ A dark/light mode switch using Mantine's color scheme system. Wraps a `Switch` in a tooltip and a `ClientOnly` boundary.
288
+
289
+ | Prop | Type | Default | Description |
290
+ |---|---|---|---|
291
+ | `size` | `MantineSize` | `'md'` | Size of the switch and icon |
292
+
293
+ Also accepts all `SwitchProps` from Mantine.
294
+
295
+ ```tsx
296
+ import { ThemeToggle } from '@emiketic/lib-mantine';
297
+
298
+ <ThemeToggle />
299
+ ```
300
+
301
+ > Requires your app to use Mantine's `MantineProvider` with `colorSchemeManager` configured.
302
+
303
+ ---
304
+
305
+ ## Storybook
306
+
307
+ Run the local Storybook to preview all components interactively:
308
+
309
+ ```bash
310
+ npm run storybook
311
+ ```
312
+
313
+ Opens at [http://localhost:6007](http://localhost:6007).
314
+
315
+ ---
316
+
317
+ ## License
318
+
319
+ MIT © [Emiketic](https://emiketic.com)