@grasco/profile-picture 0.1.7 → 0.1.8

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.
@@ -0,0 +1,407 @@
1
+ import React from 'react';
2
+ import * as lit from 'lit';
3
+ import { LitElement } from 'lit';
4
+
5
+ /**
6
+ * Profile Picture Component - Type Definitions
7
+ * Apple-inspired design system with modern 2025 aesthetics
8
+ */
9
+ type Size = "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
10
+ type Variant = "circle" | "rounded" | "squircle" | "square";
11
+ type Position = "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right";
12
+ type LoadingStrategy = "lazy" | "eager";
13
+ type PlaceholderType = "shimmer" | "pulse" | "blur" | "skeleton" | "none";
14
+ type PresenceStatus = "online" | "away" | "busy" | "offline" | "dnd";
15
+ interface PresenceConfig {
16
+ /** Current status */
17
+ status: PresenceStatus;
18
+ /** Show animated ring */
19
+ animate?: boolean;
20
+ /** Ring thickness (1-3) */
21
+ thickness?: 1 | 2 | 3;
22
+ }
23
+ interface BadgeConfig {
24
+ /** Badge content (text, number, or empty for dot) */
25
+ content?: string | number;
26
+ /** Position of the badge */
27
+ position?: Position;
28
+ /** Text/icon color */
29
+ color?: string;
30
+ /** Background color */
31
+ bgColor?: string;
32
+ /** Border radius (CSS value, e.g., "8px", "50%", "9999px") */
33
+ borderRadius?: string;
34
+ /** Enable pulse animation */
35
+ pulse?: boolean;
36
+ /** Enable glow effect */
37
+ glow?: boolean;
38
+ /** Max value to display (shows 99+ if exceeded) */
39
+ max?: number;
40
+ /** Icon to display before content (emoji, Unicode symbol, or text) */
41
+ icon?: string;
42
+ }
43
+ interface GlowConfig {
44
+ /** Glow color (defaults to border or bg color) */
45
+ color?: string;
46
+ /** Intensity (0-1) */
47
+ intensity?: number;
48
+ /** Animate the glow */
49
+ animate?: boolean;
50
+ }
51
+ interface RingConfig {
52
+ /** Show ring */
53
+ show: boolean;
54
+ /** Ring color or gradient */
55
+ color?: string;
56
+ /** Gradient colors for multi-color ring */
57
+ gradient?: string[];
58
+ /** Ring width */
59
+ width?: number;
60
+ /** Gap between ring and avatar */
61
+ gap?: number;
62
+ /** Animate (rotate for gradient) */
63
+ animate?: boolean;
64
+ /** Progress percentage (0-100) for partial fill ring */
65
+ progress?: number;
66
+ /** Color for unfilled portion when progress is set (defaults to gray) */
67
+ emptyColor?: string;
68
+ }
69
+ interface InteractionConfig {
70
+ /** Enable hover effects */
71
+ hoverable?: boolean;
72
+ /** Enable press/click effects */
73
+ pressable?: boolean;
74
+ /** Show focus ring on focus */
75
+ focusable?: boolean;
76
+ /** Cursor style */
77
+ cursor?: "pointer" | "default" | "zoom-in";
78
+ }
79
+ type ShadowPreset = "none" | "sm" | "md" | "lg" | "glow";
80
+ /**
81
+ * Base props interface shared across all framework wrappers.
82
+ * This ensures type consistency between React, Vue, Svelte, and Angular.
83
+ */
84
+ interface ProfilePictureProps$1 {
85
+ /** Image source URL */
86
+ src?: string;
87
+ /** Alt text for accessibility and fallback initials */
88
+ alt?: string;
89
+ /** External customer ID for CDN image loading */
90
+ extCustomerId?: string;
91
+ /** Predefined size or custom pixel value */
92
+ size?: Size | number;
93
+ /** Shape variant */
94
+ variant?: Variant;
95
+ /** Shadow preset */
96
+ shadow?: ShadowPreset;
97
+ /** Enable border */
98
+ border?: boolean;
99
+ /** Border width in pixels */
100
+ borderWidth?: 1 | 2 | 3 | 4 | 5 | 6 | 8;
101
+ /** Border color (CSS color value) */
102
+ borderColor?: string;
103
+ /** Rotation angle in degrees */
104
+ rotation?: number;
105
+ /** Background color (CSS color value) */
106
+ bgColor?: string;
107
+ /** Background gradient (CSS gradient value) */
108
+ bgGradient?: string;
109
+ /** Glow effect configuration */
110
+ glow?: GlowConfig;
111
+ /** Ring effect configuration (Instagram-style) */
112
+ ring?: RingConfig;
113
+ /** Presence indicator configuration */
114
+ presence?: PresenceConfig;
115
+ /** Badge configuration */
116
+ badge?: BadgeConfig;
117
+ /** Loading strategy */
118
+ loading?: LoadingStrategy;
119
+ /** Placeholder type while loading */
120
+ placeholder?: PlaceholderType;
121
+ /** Placeholder background color */
122
+ placeholderColor?: string;
123
+ /** Custom fallback text (overrides initials from alt) */
124
+ fallback?: string;
125
+ /** Interactive behavior configuration */
126
+ interactive?: InteractionConfig;
127
+ }
128
+ /** Direction for stacking avatars */
129
+ type StackDirection = "ltr" | "rtl";
130
+ /** Tooltip position relative to avatar */
131
+ type TooltipPosition = "top" | "bottom" | "left" | "right";
132
+ /** Tooltip configuration */
133
+ interface TooltipConfig {
134
+ /** Enable/disable tooltip (default: true) */
135
+ enabled?: boolean;
136
+ /** Position of tooltip relative to avatar */
137
+ position?: TooltipPosition;
138
+ /** Delay before showing tooltip in ms (default: 300) */
139
+ delay?: number;
140
+ }
141
+ /** User data extracted from profile-picture elements */
142
+ interface GroupUserData {
143
+ /** User ID from data-user-id attribute */
144
+ id?: string;
145
+ /** User name from alt attribute */
146
+ name: string;
147
+ /** Image source URL */
148
+ src?: string;
149
+ /** External customer ID for CDN image loading */
150
+ extCustomerId?: string;
151
+ /** Presence status from data-status attribute */
152
+ status?: PresenceStatus;
153
+ /** Reference to the profile-picture element */
154
+ element: HTMLElement;
155
+ /** Index in the group */
156
+ index: number;
157
+ /** Visual variant (circle, rounded, squircle, square) */
158
+ variant?: Variant;
159
+ /** Shadow preset */
160
+ shadow?: ShadowPreset;
161
+ /** Show border */
162
+ border?: boolean;
163
+ /** Border width (1-8) */
164
+ borderWidth?: 1 | 2 | 3 | 4 | 5 | 6 | 8;
165
+ /** Border color */
166
+ borderColor?: string;
167
+ /** Background color */
168
+ bgColor?: string;
169
+ /** Background gradient */
170
+ bgGradient?: string;
171
+ }
172
+ /** Dropdown configuration for overflow users */
173
+ interface DropdownConfig {
174
+ /** Max height of dropdown in px (default: 280) */
175
+ maxHeight?: number;
176
+ /** Show presence indicator dots (default: true) */
177
+ showPresence?: boolean;
178
+ /** Dropdown position (default: 'bottom') */
179
+ position?: "bottom" | "top";
180
+ }
181
+
182
+ declare class ProfilePictureGroup$1 extends LitElement {
183
+ protected createRenderRoot(): this;
184
+ max: 4;
185
+ direction: StackDirection;
186
+ overlap: 0.3;
187
+ size: Size | string;
188
+ spacing?: number;
189
+ tooltip?: TooltipConfig;
190
+ dropdown?: DropdownConfig;
191
+ showAddButton: boolean;
192
+ addButtonLabel: string;
193
+ animated: true;
194
+ rotationAmount: number;
195
+ private users;
196
+ private dropdownOpen;
197
+ private tooltipData;
198
+ private tooltipTimeout;
199
+ private slotObserver;
200
+ private portalContainer;
201
+ private counterRef;
202
+ private get pixelSize();
203
+ private get tooltipEnabled();
204
+ private get tooltipPosition();
205
+ private get tooltipDelay();
206
+ private get dropdownMaxHeight();
207
+ private get showPresence();
208
+ private get dropdownPosition();
209
+ connectedCallback(): void;
210
+ disconnectedCallback(): void;
211
+ private setupSlotObserver;
212
+ private updateUsers;
213
+ private createPortal;
214
+ private destroyPortal;
215
+ private updatePortalContent;
216
+ private handleAvatarClick;
217
+ private handleAvatarHover;
218
+ private handleAvatarLeave;
219
+ private clearTooltipTimeout;
220
+ private handleCounterClick;
221
+ private readonly handleBackdropClick;
222
+ private handleDropdownItemClick;
223
+ private handleAddClick;
224
+ private handleKeyDown;
225
+ private renderAvatar;
226
+ private renderProfilePicture;
227
+ private renderCounter;
228
+ private renderAddButton;
229
+ private renderTooltip;
230
+ private renderDropdownItem;
231
+ private formatStatus;
232
+ protected updated(changedProperties: Map<PropertyKey, unknown>): void;
233
+ render(): lit.TemplateResult<1>;
234
+ }
235
+
236
+ declare global {
237
+ interface HTMLElementTagNameMap {
238
+ "profile-picture-group": ProfilePictureGroup$1;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * React wrapper for ProfilePictureGroup Web Component
244
+ *
245
+ * Provides a type-safe React interface for the ProfilePictureGroup web component.
246
+ *
247
+ * @example
248
+ * ```tsx
249
+ * import { ProfilePictureGroup, ProfilePicture } from '@grasco/profile-picture';
250
+ *
251
+ * function App() {
252
+ * return (
253
+ * <ProfilePictureGroup
254
+ * max={4}
255
+ * direction="ltr"
256
+ * overlap={0.3}
257
+ * size="md"
258
+ * showAddButton
259
+ * onAvatarClick={(user) => console.log('Clicked:', user)}
260
+ * onAddClick={() => console.log('Add clicked')}
261
+ * >
262
+ * <ProfilePicture src="avatar1.jpg" alt="John Doe" data-user-id="1" />
263
+ * <ProfilePicture src="avatar2.jpg" alt="Jane Smith" data-user-id="2" />
264
+ * <ProfilePicture src="avatar3.jpg" alt="Bob Wilson" data-user-id="3" />
265
+ * </ProfilePictureGroup>
266
+ * );
267
+ * }
268
+ * ```
269
+ */
270
+
271
+ interface ProfilePictureGroupProps {
272
+ /** Maximum visible avatars before showing counter (default: 4) */
273
+ max?: number;
274
+ /** Stack direction - ltr shows first on left (default: 'ltr') */
275
+ direction?: StackDirection;
276
+ /** Overlap amount as percentage 0-1 (default: 0.3) */
277
+ overlap?: number;
278
+ /** Avatar size - inherited by children (default: 'md') */
279
+ size?: Size | number;
280
+ /** Spacing between avatars in px (overrides overlap calculation) */
281
+ spacing?: number;
282
+ /** Tooltip configuration */
283
+ tooltip?: TooltipConfig;
284
+ /** Dropdown configuration for overflow users */
285
+ dropdown?: DropdownConfig;
286
+ /** Show add button (default: false) */
287
+ showAddButton?: boolean;
288
+ /** Add button label for accessibility */
289
+ addButtonLabel?: string;
290
+ /** Enable hover lift animation (default: true) */
291
+ animated?: boolean;
292
+ /** Alternating rotation amount in degrees (0 = no rotation) */
293
+ rotationAmount?: number;
294
+ /** Called when an avatar is clicked */
295
+ onAvatarClick?: (user: GroupUserData) => void;
296
+ /** Called when hovering over an avatar */
297
+ onAvatarHover?: (user: GroupUserData) => void;
298
+ /** Called when the counter is clicked */
299
+ onCounterClick?: (hiddenUsers: GroupUserData[], open: boolean) => void;
300
+ /** Called when a dropdown item is clicked */
301
+ onDropdownItemClick?: (user: GroupUserData) => void;
302
+ /** Called when the add button is clicked */
303
+ onAddClick?: () => void;
304
+ className?: string;
305
+ style?: React.CSSProperties;
306
+ children?: React.ReactNode;
307
+ }
308
+ /**
309
+ * ProfilePictureGroup React Component
310
+ *
311
+ * Type-safe wrapper around the profile-picture-group web component
312
+ */
313
+ declare const ProfilePictureGroup: React.ForwardRefExoticComponent<ProfilePictureGroupProps & React.RefAttributes<HTMLElement>>;
314
+
315
+ /**
316
+ * React wrapper for ProfilePicture Web Component
317
+ *
318
+ * Provides a type-safe React interface for the ProfilePicture web component.
319
+ *
320
+ * @example
321
+ * ```tsx
322
+ * import { ProfilePicture } from '@grasco/profile-picture';
323
+ *
324
+ * function App() {
325
+ * return (
326
+ * <ProfilePicture
327
+ * src="https://example.com/avatar.png"
328
+ * alt="John Doe"
329
+ * size="lg"
330
+ * variant="circle"
331
+ * border
332
+ * borderColor="white"
333
+ * bgColor="bg-gradient-to-br from-purple-500 to-pink-500"
334
+ * badge={{ content: '3', position: 'bottom-right', pulse: true }}
335
+ * onLoad={() => console.log('loaded')}
336
+ * onError={() => console.error('failed')}
337
+ * />
338
+ * );
339
+ * }
340
+ * ```
341
+ */
342
+
343
+ /**
344
+ * Set global CDN base URL for all ProfilePicture instances
345
+ * @example setCdnBaseUrl('https://api.example.com')
346
+ */
347
+ declare function setCdnBaseUrl(url: string): void;
348
+ /**
349
+ * Get current CDN base URL
350
+ */
351
+ declare function getCdnBaseUrl(): string;
352
+ /**
353
+ * React-specific props extending the core ProfilePictureProps
354
+ */
355
+ interface ProfilePictureProps extends ProfilePictureProps$1 {
356
+ /** Called when image loads successfully */
357
+ onLoad?: () => void;
358
+ /** Called when image fails to load */
359
+ onError?: () => void;
360
+ /** Called when CDN image fails to load */
361
+ onCdnError?: (detail: {
362
+ error: string;
363
+ }) => void;
364
+ /** Additional CSS class names */
365
+ className?: string;
366
+ /** Inline styles */
367
+ style?: React.CSSProperties;
368
+ }
369
+ /**
370
+ * ProfilePicture React Component
371
+ *
372
+ * Type-safe wrapper around the profile-picture web component.
373
+ * Uses ref as a prop (React 19+ pattern).
374
+ */
375
+ declare function ProfilePicture({ src, alt, extCustomerId, size, variant, shadow, border, borderWidth, borderColor, rotation, bgColor, bgGradient, glow, ring, presence, badge, loading, placeholder, placeholderColor, fallback, interactive, onLoad, onError, onCdnError, className, style, ref, }: ProfilePictureProps & {
376
+ ref?: React.Ref<HTMLElement>;
377
+ }): React.ReactElement<{
378
+ ref: React.RefObject<HTMLElement>;
379
+ src: string | undefined;
380
+ alt: string | undefined;
381
+ "ext-customer-id": string | undefined;
382
+ size: number | Size | undefined;
383
+ variant: Variant | undefined;
384
+ shadow: ShadowPreset | undefined;
385
+ border: true | undefined;
386
+ "border-width": 1 | 2 | 3 | 4 | 5 | 6 | 8 | undefined;
387
+ "border-color": string | undefined;
388
+ rotation: number | undefined;
389
+ "bg-color": string | undefined;
390
+ "bg-gradient": string | undefined;
391
+ glow: string | undefined;
392
+ ring: string | undefined;
393
+ presence: string | undefined;
394
+ badge: string | undefined;
395
+ loading: LoadingStrategy | undefined;
396
+ placeholder: PlaceholderType | undefined;
397
+ "placeholder-color": string | undefined;
398
+ fallback: string | undefined;
399
+ interactive: string | undefined;
400
+ class: string | undefined;
401
+ style: React.CSSProperties | undefined;
402
+ }, string | React.JSXElementConstructor<any>>;
403
+ declare namespace ProfilePicture {
404
+ var displayName: string;
405
+ }
406
+
407
+ export { type BadgeConfig, type DropdownConfig, type GlowConfig, type GroupUserData, type InteractionConfig, type LoadingStrategy, type PlaceholderType, type PresenceConfig, ProfilePicture, ProfilePictureGroup, type ProfilePictureGroupProps, type ProfilePictureProps, type RingConfig, type ShadowPreset, type Size, type StackDirection, type TooltipConfig, type Variant, getCdnBaseUrl, setCdnBaseUrl };