@fmarlats/react-like-button 1.1.4
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/LICENSE +22 -0
- package/README.md +482 -0
- package/dist/chunk-VLFZGMEX.js +725 -0
- package/dist/chunk-VLFZGMEX.js.map +1 -0
- package/dist/index.cjs +926 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +209 -0
- package/dist/index.js.map +1 -0
- package/dist/like-button.css +68 -0
- package/dist/styles.css +181 -0
- package/dist/vanilla.cjs +742 -0
- package/dist/vanilla.cjs.map +1 -0
- package/dist/vanilla.d.cts +562 -0
- package/dist/vanilla.d.ts +562 -0
- package/dist/vanilla.js +16 -0
- package/dist/vanilla.js.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Particle System Type Definitions
|
|
6
|
+
*
|
|
7
|
+
* This file contains all type definitions for the enhanced particle effects system.
|
|
8
|
+
* Supports configurable shapes, animations, presets, and custom particle configurations.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Built-in particle shape presets
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <LikeButton particleConfig={{ shape: 'star' }} />
|
|
16
|
+
* <LikeButton particleConfig={{ shape: 'heart' }} />
|
|
17
|
+
* <LikeButton particleConfig={{ shape: 'sparkle' }} />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
type ParticleShapePreset = "heart" | "star" | "circle" | "square" | "sparkle";
|
|
21
|
+
/**
|
|
22
|
+
* Props passed to particle shape render functions
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* const MyShape = ({ size, color, className }: ParticleShapeProps) => (
|
|
27
|
+
* <svg width={size} height={size} className={className}>
|
|
28
|
+
* <circle cx={size/2} cy={size/2} r={size/2} fill={color} />
|
|
29
|
+
* </svg>
|
|
30
|
+
* );
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
interface ParticleShapeProps {
|
|
34
|
+
/** Size of the shape in pixels */
|
|
35
|
+
size: number;
|
|
36
|
+
/** Color of the shape (hex or CSS color) */
|
|
37
|
+
color: string;
|
|
38
|
+
/** Additional CSS class names */
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Custom particle shape configuration
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const customShape: CustomParticleShape = {
|
|
47
|
+
* render: ({ size, color }) => (
|
|
48
|
+
* <svg width={size} height={size}>
|
|
49
|
+
* <polygon points="..." fill={color} />
|
|
50
|
+
* </svg>
|
|
51
|
+
* )
|
|
52
|
+
* };
|
|
53
|
+
*
|
|
54
|
+
* <LikeButton particleConfig={{ shape: customShape }} />
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
interface CustomParticleShape {
|
|
58
|
+
/** Custom render function for the particle shape */
|
|
59
|
+
render: (props: ParticleShapeProps) => React.ReactNode;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Particle shape - either a preset string or custom shape config
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```tsx
|
|
66
|
+
* // Using preset
|
|
67
|
+
* const shape1: ParticleShape = 'star';
|
|
68
|
+
*
|
|
69
|
+
* // Using custom shape
|
|
70
|
+
* const shape2: ParticleShape = {
|
|
71
|
+
* render: (props) => <MyCustomShape {...props} />
|
|
72
|
+
* };
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
type ParticleShape = ParticleShapePreset | CustomParticleShape;
|
|
76
|
+
/**
|
|
77
|
+
* Built-in particle effect presets
|
|
78
|
+
*
|
|
79
|
+
* - **burst**: Quick explosion of hearts in all directions (12 particles)
|
|
80
|
+
* - **fountain**: Upward spray effect (10 particles)
|
|
81
|
+
* - **confetti**: Colorful celebration with mixed shapes (15 particles)
|
|
82
|
+
* - **gentle**: Subtle floating effect (6 particles)
|
|
83
|
+
* - **fireworks**: Explosive sparkle effect (16 particles)
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```tsx
|
|
87
|
+
* <LikeButton particlePreset="burst" />
|
|
88
|
+
* <LikeButton particlePreset="confetti" />
|
|
89
|
+
* <LikeButton particlePreset="fireworks" />
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
type ParticlePreset = "burst" | "fountain" | "confetti" | "gentle" | "fireworks";
|
|
93
|
+
/**
|
|
94
|
+
* Range configuration for numeric values
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```tsx
|
|
98
|
+
* const distanceRange: Range = { min: 80, max: 120 };
|
|
99
|
+
* const sizeRange: Range = { min: 1.0, max: 2.0 };
|
|
100
|
+
*
|
|
101
|
+
* <LikeButton particleConfig={{
|
|
102
|
+
* distance: distanceRange,
|
|
103
|
+
* size: sizeRange
|
|
104
|
+
* }} />
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
interface Range {
|
|
108
|
+
/** Minimum value */
|
|
109
|
+
min: number;
|
|
110
|
+
/** Maximum value */
|
|
111
|
+
max: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Complete particle configuration interface.
|
|
115
|
+
* All fields are optional - defaults will be applied.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```tsx
|
|
119
|
+
* const config: ParticleConfig = {
|
|
120
|
+
* shape: 'star',
|
|
121
|
+
* colors: ['#FFD700', '#FFA500'],
|
|
122
|
+
* count: 12,
|
|
123
|
+
* speed: 600,
|
|
124
|
+
* distance: { min: 80, max: 120 },
|
|
125
|
+
* spread: 180,
|
|
126
|
+
* spreadOffset: -90,
|
|
127
|
+
* };
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
interface ParticleConfig {
|
|
131
|
+
/**
|
|
132
|
+
* Particle shape - preset name or custom shape config
|
|
133
|
+
* @default 'heart'
|
|
134
|
+
*/
|
|
135
|
+
shape?: ParticleShape;
|
|
136
|
+
/**
|
|
137
|
+
* Array of colors for particles (randomly selected)
|
|
138
|
+
* @default ['#EF4444', '#B9FF14', '#3B82F6']
|
|
139
|
+
*/
|
|
140
|
+
colors?: string[];
|
|
141
|
+
/**
|
|
142
|
+
* Number of particles to spawn per click
|
|
143
|
+
* @default 8
|
|
144
|
+
*/
|
|
145
|
+
count?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Size range for particles (scale multiplier)
|
|
148
|
+
* Can be a single number or a range
|
|
149
|
+
* @default { min: 1.0, max: 1.5 }
|
|
150
|
+
*/
|
|
151
|
+
size?: number | Range;
|
|
152
|
+
/**
|
|
153
|
+
* Animation duration in milliseconds
|
|
154
|
+
* @default 500
|
|
155
|
+
*/
|
|
156
|
+
speed?: number;
|
|
157
|
+
/**
|
|
158
|
+
* Distance particles travel in pixels
|
|
159
|
+
* Can be a single number or a range
|
|
160
|
+
* @default { min: 60, max: 100 }
|
|
161
|
+
*/
|
|
162
|
+
distance?: number | Range;
|
|
163
|
+
/**
|
|
164
|
+
* Spread angle in degrees (0-360)
|
|
165
|
+
* 360 = full circle, 180 = semicircle, etc.
|
|
166
|
+
* @default 360
|
|
167
|
+
*/
|
|
168
|
+
spread?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Starting angle offset in degrees
|
|
171
|
+
* 0 = right, 90 = down, 180 = left, 270 = up
|
|
172
|
+
* @default 0
|
|
173
|
+
*/
|
|
174
|
+
spreadOffset?: number;
|
|
175
|
+
/**
|
|
176
|
+
* CSS easing function for particle animation
|
|
177
|
+
* @default 'cubic-bezier(0.22, 1, 0.36, 1)'
|
|
178
|
+
*/
|
|
179
|
+
easing?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Whether particles fade out during animation
|
|
182
|
+
* @default true
|
|
183
|
+
*/
|
|
184
|
+
fadeOut?: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Preset configuration type.
|
|
188
|
+
* Used internally to define preset configurations.
|
|
189
|
+
*/
|
|
190
|
+
type ParticlePresetConfig = Required<Omit<ParticleConfig, "shape">> & {
|
|
191
|
+
shape: ParticleShapePreset;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/** Data structure for a single particle effect */
|
|
195
|
+
interface ParticleData {
|
|
196
|
+
id: string;
|
|
197
|
+
angle: number;
|
|
198
|
+
distance: number;
|
|
199
|
+
scale: number;
|
|
200
|
+
color: string;
|
|
201
|
+
shape: ParticleShape;
|
|
202
|
+
speed: number;
|
|
203
|
+
easing: string;
|
|
204
|
+
fadeOut: boolean;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* State object passed to dynamic aria-label functions.
|
|
208
|
+
* Enables internationalization (i18n) support for accessibility labels.
|
|
209
|
+
*/
|
|
210
|
+
interface AriaLabelState {
|
|
211
|
+
/** Whether the maximum clicks have been reached */
|
|
212
|
+
isMaxed: boolean;
|
|
213
|
+
/** Number of clicks remaining before max */
|
|
214
|
+
remaining: number;
|
|
215
|
+
/** Current number of clicks by the user */
|
|
216
|
+
clicks: number;
|
|
217
|
+
/** Maximum number of clicks allowed */
|
|
218
|
+
maxClicks: number;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Aria label can be either:
|
|
222
|
+
* - A static string for simple use cases
|
|
223
|
+
* - A function that receives state for dynamic/i18n labels
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```tsx
|
|
227
|
+
* // Static string
|
|
228
|
+
* ariaLabel="Like this post"
|
|
229
|
+
*
|
|
230
|
+
* // Dynamic function for i18n
|
|
231
|
+
* ariaLabel={({ isMaxed, remaining }) =>
|
|
232
|
+
* isMaxed ? t('likes.maxed') : t('likes.remaining', { count: remaining })
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
type AriaLabelProp = string | ((state: AriaLabelState) => string);
|
|
237
|
+
/** Options for the useLikeButton hook */
|
|
238
|
+
interface UseLikeButtonOptions {
|
|
239
|
+
/** Current click count (controlled mode). If not provided, internal state is used. */
|
|
240
|
+
clicks?: number;
|
|
241
|
+
/**
|
|
242
|
+
* Initial click count for uncontrolled mode.
|
|
243
|
+
* Only used on first render; ignored if `clicks` prop is provided.
|
|
244
|
+
* @default 0
|
|
245
|
+
*/
|
|
246
|
+
defaultClicks?: number;
|
|
247
|
+
/** Maximum number of clicks allowed per user */
|
|
248
|
+
maxClicks?: number;
|
|
249
|
+
/**
|
|
250
|
+
* Callback when button is clicked.
|
|
251
|
+
* @param clicks - The current click count, after increment
|
|
252
|
+
* @param event - The mouse event that triggered the click
|
|
253
|
+
*/
|
|
254
|
+
onClick?: (clicks: number, event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
255
|
+
/**
|
|
256
|
+
* Callback when click count changes. Simpler alternative to onClick for controlled mode.
|
|
257
|
+
* Called with just the new count, ideal for state setters like `onChange={setClicks}`.
|
|
258
|
+
* @param clicks - The new click count
|
|
259
|
+
*/
|
|
260
|
+
onChange?: (clicks: number) => void;
|
|
261
|
+
/**
|
|
262
|
+
* Callback when button is right-clicked. Also triggered by Shift+Enter for keyboard accessibility.
|
|
263
|
+
* @param clicks - The current click count, not incremented as right-click does not increment
|
|
264
|
+
* @param event - The mouse or keyboard event that triggered the action
|
|
265
|
+
*/
|
|
266
|
+
onRightClick?: (clicks: number, event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>) => void;
|
|
267
|
+
/** Whether the button is disabled */
|
|
268
|
+
disabled?: boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Show particle effects on click.
|
|
271
|
+
* When false, no particles are spawned or rendered.
|
|
272
|
+
* @default true
|
|
273
|
+
*/
|
|
274
|
+
showParticles?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Custom aria-label override. Accepts either a static string or a function
|
|
277
|
+
* that receives the current state for dynamic/i18n labels.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```tsx
|
|
281
|
+
* // Static string
|
|
282
|
+
* ariaLabel="Like this post"
|
|
283
|
+
*
|
|
284
|
+
* // Dynamic function for i18n support
|
|
285
|
+
* ariaLabel={({ isMaxed, remaining }) =>
|
|
286
|
+
* isMaxed ? t('likes.maxed') : t('likes.remaining', { count: remaining })
|
|
287
|
+
* }
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
ariaLabel?: AriaLabelProp;
|
|
291
|
+
/**
|
|
292
|
+
* Particle effect preset (burst, fountain, confetti, gentle, fireworks)
|
|
293
|
+
* @example
|
|
294
|
+
* ```tsx
|
|
295
|
+
* useLikeButton({ particlePreset: 'burst' })
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
particlePreset?: ParticlePreset;
|
|
299
|
+
/**
|
|
300
|
+
* Custom particle configuration (overrides preset)
|
|
301
|
+
* @example
|
|
302
|
+
* ```tsx
|
|
303
|
+
* useLikeButton({
|
|
304
|
+
* particleConfig: {
|
|
305
|
+
* shape: 'star',
|
|
306
|
+
* colors: ['#FFD700', '#FFA500'],
|
|
307
|
+
* count: 12,
|
|
308
|
+
* }
|
|
309
|
+
* })
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
particleConfig?: Partial<ParticleConfig>;
|
|
313
|
+
}
|
|
314
|
+
/** Default values */
|
|
315
|
+
declare const LIKE_BUTTON_DEFAULTS: {
|
|
316
|
+
readonly maxClicks: 1;
|
|
317
|
+
readonly size: 96;
|
|
318
|
+
readonly fillColor: "#EF4444";
|
|
319
|
+
readonly waveColor: "#B91C1C";
|
|
320
|
+
};
|
|
321
|
+
/** Return type for the useLikeButton hook */
|
|
322
|
+
interface UseLikeButtonReturn {
|
|
323
|
+
/** Current click count */
|
|
324
|
+
clicks: number;
|
|
325
|
+
/** Whether max clicks reached */
|
|
326
|
+
isMaxed: boolean;
|
|
327
|
+
/** Whether button is disabled */
|
|
328
|
+
disabled: boolean;
|
|
329
|
+
/** Fill percentage (0-100) */
|
|
330
|
+
fillPercentage: number;
|
|
331
|
+
/** Active particles to render */
|
|
332
|
+
particles: ParticleData[];
|
|
333
|
+
/** Click handler for the button */
|
|
334
|
+
handleClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
335
|
+
/** Right-click handler for the button */
|
|
336
|
+
handleRightClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
337
|
+
/**
|
|
338
|
+
* Keyboard handler for accessibility.
|
|
339
|
+
* Triggers onRightClick when Shift+Enter is pressed.
|
|
340
|
+
*/
|
|
341
|
+
handleKeyDown: (e: React.KeyboardEvent<HTMLButtonElement>) => void;
|
|
342
|
+
/** Aria label for accessibility */
|
|
343
|
+
ariaLabel: string;
|
|
344
|
+
/** Whether button has been pressed */
|
|
345
|
+
isPressed: boolean;
|
|
346
|
+
/** Whether onRightClick is provided (for aria-keyshortcuts) */
|
|
347
|
+
hasRightClickAction: boolean;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Headless hook for LikeButton logic.
|
|
351
|
+
* Handles state management, particle spawning, and accessibility.
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```tsx
|
|
355
|
+
* const { handleClick, clicks, particles, ariaLabel } = useLikeButton({
|
|
356
|
+
* maxClicks: 10,
|
|
357
|
+
* onClick: (count, event) => {
|
|
358
|
+
* console.log('Clicked!', count)
|
|
359
|
+
* // Access event if needed
|
|
360
|
+
* event.stopPropagation()
|
|
361
|
+
* },
|
|
362
|
+
* });
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
declare function useLikeButton(options?: UseLikeButtonOptions): UseLikeButtonReturn;
|
|
366
|
+
|
|
367
|
+
/** Props passed to custom icon render function */
|
|
368
|
+
interface IconRenderProps {
|
|
369
|
+
/** Suggested icon size in pixels (50% of button size by default) */
|
|
370
|
+
size: number;
|
|
371
|
+
/** Base CSS classes for positioning and transitions */
|
|
372
|
+
className: string;
|
|
373
|
+
/** Whether button is at max clicks */
|
|
374
|
+
isMaxed: boolean;
|
|
375
|
+
/** Current fill percentage (0-100) */
|
|
376
|
+
fillPercentage: number;
|
|
377
|
+
}
|
|
378
|
+
/** Preset shape values */
|
|
379
|
+
type ShapePreset = "circle" | "rounded" | "square";
|
|
380
|
+
/** Custom shape configuration */
|
|
381
|
+
interface CustomShape {
|
|
382
|
+
/** CSS border-radius value (e.g., "1rem", "50%", "1rem 2rem") */
|
|
383
|
+
borderRadius?: string;
|
|
384
|
+
/** CSS clip-path value for custom shapes (e.g., "polygon(...)", "circle(...)") */
|
|
385
|
+
clipPath?: string;
|
|
386
|
+
}
|
|
387
|
+
/** Shape prop type - either a preset or custom configuration */
|
|
388
|
+
type Shape = ShapePreset | CustomShape;
|
|
389
|
+
/** Preset cursor values */
|
|
390
|
+
type CursorPreset = "heart" | "star" | "thumbs-up" | "pointer" | "none";
|
|
391
|
+
/** Custom cursor configuration */
|
|
392
|
+
interface CustomCursor {
|
|
393
|
+
/**
|
|
394
|
+
* Cursor URL - can be a data URL (SVG/image) or external URL.
|
|
395
|
+
* @example "data:image/svg+xml;utf8,<svg>...</svg>"
|
|
396
|
+
* @example "/cursors/my-cursor.png"
|
|
397
|
+
*/
|
|
398
|
+
url: string;
|
|
399
|
+
/** Hotspot X coordinate (default: 16) */
|
|
400
|
+
hotspotX?: number;
|
|
401
|
+
/** Hotspot Y coordinate (default: 16) */
|
|
402
|
+
hotspotY?: number;
|
|
403
|
+
/** Fallback cursor if custom cursor fails to load (default: "pointer") */
|
|
404
|
+
fallback?: "pointer" | "default" | "grab";
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Cursor prop type - either a preset string or custom configuration.
|
|
408
|
+
* - "heart" (default): Heart-shaped cursor
|
|
409
|
+
* - "star": Star-shaped cursor
|
|
410
|
+
* - "thumbs-up": Thumbs up cursor
|
|
411
|
+
* - "pointer": Standard pointer cursor (disables custom cursor)
|
|
412
|
+
* - "none": Hides cursor entirely
|
|
413
|
+
* - CustomCursor: Custom cursor with URL and hotspot configuration
|
|
414
|
+
*/
|
|
415
|
+
type Cursor = CursorPreset | CustomCursor;
|
|
416
|
+
/** Override brutalist styling */
|
|
417
|
+
interface StyleOverrides {
|
|
418
|
+
/** Border width in pixels (default: 4) */
|
|
419
|
+
borderWidth?: number;
|
|
420
|
+
/** Border color (default: "#111827") */
|
|
421
|
+
borderColor?: string;
|
|
422
|
+
/** Shadow offset in pixels (default: 8) */
|
|
423
|
+
shadowOffset?: number;
|
|
424
|
+
/** Shadow color (default: "#111827") */
|
|
425
|
+
shadowColor?: string;
|
|
426
|
+
/** Background color (default: "white") */
|
|
427
|
+
backgroundColor?: string;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Base props shared between Tailwind and Vanilla CSS versions.
|
|
431
|
+
* Both versions accept identical props for API consistency.
|
|
432
|
+
*/
|
|
433
|
+
interface BaseLikeButtonProps extends UseLikeButtonOptions {
|
|
434
|
+
/** Button size in pixels */
|
|
435
|
+
size?: number;
|
|
436
|
+
/** Fill color for the liquid effect */
|
|
437
|
+
fillColor?: string;
|
|
438
|
+
/** Wave color (darker shade for back wave) */
|
|
439
|
+
waveColor?: string;
|
|
440
|
+
/** Additional CSS class name */
|
|
441
|
+
className?: string;
|
|
442
|
+
/**
|
|
443
|
+
* Show animated wave effect on top of the liquid fill.
|
|
444
|
+
* When false, the fill displays as a flat color without wave animation.
|
|
445
|
+
* @default true
|
|
446
|
+
*/
|
|
447
|
+
showWaves?: boolean;
|
|
448
|
+
/**
|
|
449
|
+
* Initial/minimum fill percentage shown even before any clicks.
|
|
450
|
+
* Useful for custom shapes with narrow bottoms (e.g., hearts, diamonds)
|
|
451
|
+
* where low fill percentages may be invisible.
|
|
452
|
+
*
|
|
453
|
+
* Valid range: 0-85 (values above 85 will be clamped to 85)
|
|
454
|
+
* @default 0
|
|
455
|
+
* @example
|
|
456
|
+
* // Show 15% minimum fill for a heart shape
|
|
457
|
+
* <LikeButton minFillPercent={15} shape={{ clipPath: "polygon(...)" }} />
|
|
458
|
+
*/
|
|
459
|
+
minFillPercent?: number;
|
|
460
|
+
/**
|
|
461
|
+
* Custom icon render function.
|
|
462
|
+
* - If undefined: renders default heart icon
|
|
463
|
+
* - If null: renders no icon
|
|
464
|
+
* - If function: calls with IconRenderProps
|
|
465
|
+
*/
|
|
466
|
+
renderIcon?: ((props: IconRenderProps) => React.ReactNode) | null;
|
|
467
|
+
/**
|
|
468
|
+
* Button shape.
|
|
469
|
+
* - Presets: "circle" (default), "rounded", "square"
|
|
470
|
+
* - Custom: { borderRadius?: string, clipPath?: string }
|
|
471
|
+
*/
|
|
472
|
+
shape?: Shape;
|
|
473
|
+
/** Override brutalist styling (border, shadow, background) */
|
|
474
|
+
styles?: StyleOverrides;
|
|
475
|
+
/**
|
|
476
|
+
* Cursor displayed when hovering over the button.
|
|
477
|
+
* - "heart" (default): Heart-shaped cursor
|
|
478
|
+
* - "star": Star-shaped cursor
|
|
479
|
+
* - "thumbs-up": Thumbs up cursor
|
|
480
|
+
* - "pointer": Standard pointer cursor
|
|
481
|
+
* - "none": Hides cursor
|
|
482
|
+
* - CustomCursor: { url, hotspotX?, hotspotY?, fallback? }
|
|
483
|
+
*/
|
|
484
|
+
cursor?: Cursor;
|
|
485
|
+
}
|
|
486
|
+
/** Props for the LikeButton component (Tailwind version) */
|
|
487
|
+
type LikeButtonProps = BaseLikeButtonProps;
|
|
488
|
+
/** Props for the LikeButton component (Vanilla CSS version) */
|
|
489
|
+
type LikeButtonVanillaProps = BaseLikeButtonProps;
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Default heart icon for LikeButton.
|
|
493
|
+
* Can be used as reference for creating custom icons.
|
|
494
|
+
*/
|
|
495
|
+
declare function DefaultHeartIcon({ size, className }: IconRenderProps): react_jsx_runtime.JSX.Element;
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* LikeButton - Animated like button with liquid fill and particle effects.
|
|
499
|
+
* This version uses vanilla CSS (no Tailwind dependency).
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```tsx
|
|
503
|
+
* import { LikeButtonVanilla } from '@fmarlats/react-like-button';
|
|
504
|
+
* import '@fmarlats/react-like-button/styles.css';
|
|
505
|
+
*
|
|
506
|
+
* // Default usage
|
|
507
|
+
* <LikeButtonVanilla onClick={(clicks, event) => console.log('Clicks:', clicks)} />
|
|
508
|
+
*
|
|
509
|
+
* // Custom icon
|
|
510
|
+
* <LikeButtonVanilla renderIcon={({ size }) => <CustomIcon size={size} />} />
|
|
511
|
+
*
|
|
512
|
+
* // Custom shape
|
|
513
|
+
* <LikeButtonVanilla shape="rounded" />
|
|
514
|
+
* <LikeButtonVanilla shape={{ clipPath: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)" }} />
|
|
515
|
+
*
|
|
516
|
+
* // Custom styles
|
|
517
|
+
* <LikeButtonVanilla styles={{ shadowOffset: 4, borderWidth: 2 }} />
|
|
518
|
+
*
|
|
519
|
+
* // Custom cursor
|
|
520
|
+
* <LikeButtonVanilla cursor="star" />
|
|
521
|
+
* <LikeButtonVanilla cursor={{ url: "data:image/svg+xml;...", hotspotX: 16, hotspotY: 16 }} />
|
|
522
|
+
*
|
|
523
|
+
* // Minimum fill for custom shapes
|
|
524
|
+
* <LikeButtonVanilla minFillPercent={15} shape={{ clipPath: "polygon(...)" }} />
|
|
525
|
+
*
|
|
526
|
+
* // Particle presets (same API as Tailwind version)
|
|
527
|
+
* <LikeButtonVanilla particlePreset="burst" />
|
|
528
|
+
* <LikeButtonVanilla particlePreset="confetti" />
|
|
529
|
+
* <LikeButtonVanilla particlePreset="fireworks" />
|
|
530
|
+
*
|
|
531
|
+
* // Custom particle configuration
|
|
532
|
+
* <LikeButtonVanilla particleConfig={{
|
|
533
|
+
* shape: 'star',
|
|
534
|
+
* colors: ['#FFD700', '#FFA500'],
|
|
535
|
+
* count: 15,
|
|
536
|
+
* speed: 800
|
|
537
|
+
* }} />
|
|
538
|
+
*
|
|
539
|
+
* // Combine preset with custom config
|
|
540
|
+
* <LikeButtonVanilla
|
|
541
|
+
* particlePreset="burst"
|
|
542
|
+
* particleConfig={{ count: 20 }}
|
|
543
|
+
* />
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
declare const LikeButtonVanilla: react.ForwardRefExoticComponent<BaseLikeButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Built-in particle effect presets.
|
|
550
|
+
* Each preset provides a distinct visual effect optimized for different use cases.
|
|
551
|
+
*
|
|
552
|
+
* @example
|
|
553
|
+
* ```tsx
|
|
554
|
+
* import { PARTICLE_PRESETS } from '@fmarlats/react-like-button';
|
|
555
|
+
*
|
|
556
|
+
* // Use a preset directly
|
|
557
|
+
* const burstConfig = PARTICLE_PRESETS.burst;
|
|
558
|
+
* ```
|
|
559
|
+
*/
|
|
560
|
+
declare const PARTICLE_PRESETS: Record<ParticlePreset, ParticlePresetConfig>;
|
|
561
|
+
|
|
562
|
+
export { type AriaLabelProp, type AriaLabelState, type BaseLikeButtonProps, type Cursor, type CursorPreset, type CustomCursor, type CustomParticleShape, type CustomShape, DefaultHeartIcon, type IconRenderProps, LIKE_BUTTON_DEFAULTS, type LikeButtonProps, LikeButtonVanilla, type LikeButtonVanillaProps, PARTICLE_PRESETS, type ParticleConfig, type ParticleData, type ParticlePreset, type ParticleShape, type ParticleShapePreset, type ParticleShapeProps, type Range, type Shape, type ShapePreset, type StyleOverrides, type UseLikeButtonOptions, type UseLikeButtonReturn, LikeButtonVanilla as default, useLikeButton };
|
package/dist/vanilla.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefaultHeartIcon,
|
|
3
|
+
LIKE_BUTTON_DEFAULTS,
|
|
4
|
+
LikeButtonVanilla,
|
|
5
|
+
PARTICLE_PRESETS,
|
|
6
|
+
useLikeButton
|
|
7
|
+
} from "./chunk-VLFZGMEX.js";
|
|
8
|
+
export {
|
|
9
|
+
DefaultHeartIcon,
|
|
10
|
+
LIKE_BUTTON_DEFAULTS,
|
|
11
|
+
LikeButtonVanilla,
|
|
12
|
+
PARTICLE_PRESETS,
|
|
13
|
+
LikeButtonVanilla as default,
|
|
14
|
+
useLikeButton
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=vanilla.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fmarlats/react-like-button",
|
|
3
|
+
"version": "1.1.4",
|
|
4
|
+
"description": "Animated React like button component with configurable multi clicks to fill the button, particle animations on click, all customizable. Supports Tailwind CSS and vanilla CSS. TypeScript-ready and accessible.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./vanilla": {
|
|
16
|
+
"types": "./dist/vanilla.d.ts",
|
|
17
|
+
"import": "./dist/vanilla.js",
|
|
18
|
+
"require": "./dist/vanilla.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./styles.css": "./dist/styles.css",
|
|
21
|
+
"./like-button.css": "./dist/like-button.css"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"*.css"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup && node scripts/build-css.js",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"test:coverage": "vitest run --coverage",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"format": "biome format --write .",
|
|
37
|
+
"format:check": "biome format .",
|
|
38
|
+
"lint": "biome lint .",
|
|
39
|
+
"lint:fix": "biome lint --write .",
|
|
40
|
+
"check": "biome check --write .",
|
|
41
|
+
"ci": "biome ci .",
|
|
42
|
+
"prepublishOnly": "pnpm run ci && pnpm run typecheck && pnpm run test && pnpm run build"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "2.3.10",
|
|
46
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
47
|
+
"@testing-library/react": "^16.3.0",
|
|
48
|
+
"@types/react": "^19.2.7",
|
|
49
|
+
"@types/react-dom": "^19.2.3",
|
|
50
|
+
"@vitejs/plugin-react": "^4.4.1",
|
|
51
|
+
"jsdom": "^26.1.0",
|
|
52
|
+
"react": "^19.2.3",
|
|
53
|
+
"react-dom": "^19.2.3",
|
|
54
|
+
"tsup": "^8.5.0",
|
|
55
|
+
"typescript": "^5.8.3",
|
|
56
|
+
"vitest": "^3.2.3"
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"react",
|
|
60
|
+
"react-component",
|
|
61
|
+
"like-button",
|
|
62
|
+
"like",
|
|
63
|
+
"button",
|
|
64
|
+
"animation",
|
|
65
|
+
"animated-button",
|
|
66
|
+
"particles",
|
|
67
|
+
"particle-effects",
|
|
68
|
+
"liquid-fill",
|
|
69
|
+
"liquid-animation",
|
|
70
|
+
"wave-animation",
|
|
71
|
+
"brutalist",
|
|
72
|
+
"brutalist-design",
|
|
73
|
+
"tailwind",
|
|
74
|
+
"tailwindcss",
|
|
75
|
+
"vanilla-css",
|
|
76
|
+
"typescript",
|
|
77
|
+
"interactive",
|
|
78
|
+
"ui-component",
|
|
79
|
+
"react-ui",
|
|
80
|
+
"engagement",
|
|
81
|
+
"social",
|
|
82
|
+
"heart-button",
|
|
83
|
+
"favorite-button",
|
|
84
|
+
"upvote",
|
|
85
|
+
"rating",
|
|
86
|
+
"feedback",
|
|
87
|
+
"click-animation",
|
|
88
|
+
"micro-interaction",
|
|
89
|
+
"headless-ui",
|
|
90
|
+
"customizable",
|
|
91
|
+
"accessible",
|
|
92
|
+
"a11y",
|
|
93
|
+
"multiple-likes"
|
|
94
|
+
],
|
|
95
|
+
"author": "Florian MARLATS",
|
|
96
|
+
"license": "MIT",
|
|
97
|
+
"repository": {
|
|
98
|
+
"type": "git",
|
|
99
|
+
"url": "git+https://github.com/fmarlats/react-like-button.git"
|
|
100
|
+
},
|
|
101
|
+
"homepage": "https://github.com/fmarlats/react-like-button#readme",
|
|
102
|
+
"bugs": {
|
|
103
|
+
"url": "https://github.com/fmarlats/react-like-button/issues"
|
|
104
|
+
},
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
107
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
108
|
+
}
|
|
109
|
+
}
|