shared-features 0.0.5 → 0.0.7
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 +249 -96
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
# shared-features
|
|
2
2
|
|
|
3
|
-
Centralized common features for Zaions projects. Manage ads,
|
|
3
|
+
Centralized common features for Zaions projects. Manage ads, notifications, contacts, and more from a single admin panel at [aoneahsan.com](https://aoneahsan.com).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Two Core Systems
|
|
8
|
+
|
|
9
|
+
This package provides **two separate systems** for cross-project communication:
|
|
10
|
+
|
|
11
|
+
| System | Purpose | Firestore Collections | Admin Location |
|
|
12
|
+
|--------|---------|----------------------|----------------|
|
|
13
|
+
| **Advertising Campaigns** | Promote Zaions products across apps | `zaions_campaigns`, `zaions_products`, `zaions_impressions` | `/admin/campaigns` |
|
|
14
|
+
| **Broadcasts/Notifications** | In-app notifications, announcements, alerts | `zaions_broadcasts`, `zaions_broadcast_events`, `zaions_notification_templates` | `/admin/notifications` |
|
|
15
|
+
|
|
16
|
+
### When to Use Which?
|
|
17
|
+
|
|
18
|
+
| Use Case | System |
|
|
19
|
+
|----------|--------|
|
|
20
|
+
| Promote ZTools in other apps | **Advertising Campaigns** |
|
|
21
|
+
| Announce new feature to all users | **Broadcasts** |
|
|
22
|
+
| Cross-sell products | **Advertising Campaigns** |
|
|
23
|
+
| Maintenance notice | **Broadcasts** |
|
|
24
|
+
| Product ads in footer/sidebar | **Advertising Campaigns** |
|
|
25
|
+
| Alert banners at top of page | **Broadcasts** |
|
|
26
|
+
| One-time welcome modal for products | **Advertising Campaigns** |
|
|
27
|
+
| One-time announcement modal | **Broadcasts** |
|
|
28
|
+
|
|
29
|
+
---
|
|
4
30
|
|
|
5
31
|
## Features
|
|
6
32
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
33
|
+
### Advertising Campaigns System
|
|
34
|
+
- **5 Ad Components** - AdPanel, AdSlider, AdModal, AdUpdateModal, AdBanner
|
|
35
|
+
- **10 Display Variants** - 5 small (compact), 5 large (feature areas)
|
|
36
|
+
- **Frequency capping** - Control how often users see ads
|
|
37
|
+
- **Analytics** - Track impressions, clicks, CTR per project
|
|
38
|
+
- **Project targeting** - Target specific projects or all
|
|
39
|
+
|
|
40
|
+
### Broadcasts/Notifications System
|
|
41
|
+
- **4 Notification Types** - Banner, Modal, Toast, Bell (notification center)
|
|
42
|
+
- **Priority levels** - Low, Medium, High, Urgent
|
|
43
|
+
- **Scheduling** - Immediate or scheduled delivery
|
|
44
|
+
- **Templates** - Reusable notification templates
|
|
45
|
+
- **Analytics** - Track views, clicks, dismissals
|
|
46
|
+
|
|
47
|
+
---
|
|
17
48
|
|
|
18
49
|
## Installation
|
|
19
50
|
|
|
@@ -23,8 +54,6 @@ yarn add shared-features
|
|
|
23
54
|
|
|
24
55
|
## Peer Dependencies
|
|
25
56
|
|
|
26
|
-
This package requires the following peer dependencies:
|
|
27
|
-
|
|
28
57
|
```bash
|
|
29
58
|
yarn add react react-dom firebase @radix-ui/themes zustand lucide-react
|
|
30
59
|
# Optional for mobile:
|
|
@@ -71,19 +100,39 @@ if (import.meta.env.VITE_SHARED_FEATURES_API_KEY) {
|
|
|
71
100
|
}
|
|
72
101
|
```
|
|
73
102
|
|
|
74
|
-
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
# ADVERTISING CAMPAIGNS SYSTEM
|
|
106
|
+
|
|
107
|
+
Cross-promote Zaions products (ZTools, FilesHub, etc.) across all projects.
|
|
75
108
|
|
|
76
|
-
|
|
109
|
+
## Firestore Collections
|
|
110
|
+
|
|
111
|
+
| Collection | Purpose | Access |
|
|
112
|
+
|------------|---------|--------|
|
|
113
|
+
| `zaions_products` | Product catalog (name, URL, icon, features) | Public read, Admin write |
|
|
114
|
+
| `zaions_campaigns` | Campaign settings (targeting, placements, variants) | Public read, Admin write |
|
|
115
|
+
| `zaions_impressions` | Analytics (impressions, clicks per campaign) | Public create, Admin read |
|
|
116
|
+
|
|
117
|
+
## Displaying Ads
|
|
118
|
+
|
|
119
|
+
### Simple Usage
|
|
77
120
|
|
|
78
121
|
```tsx
|
|
79
|
-
import { AdPanel,
|
|
122
|
+
import { AdPanel, AdSlider } from 'shared-features';
|
|
80
123
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
124
|
+
// Sidebar panel
|
|
125
|
+
<AdPanel placement="sidebar_panel" />
|
|
126
|
+
|
|
127
|
+
// Footer slider
|
|
128
|
+
<AdSlider placement="footer_slider" />
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Custom Implementation
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { useCampaigns } from 'shared-features';
|
|
85
135
|
|
|
86
|
-
// Custom implementation with hook
|
|
87
136
|
function Footer() {
|
|
88
137
|
const { campaigns, loading, recordImpression, recordClick } = useCampaigns({
|
|
89
138
|
placement: 'footer_slider',
|
|
@@ -112,7 +161,7 @@ function Footer() {
|
|
|
112
161
|
}
|
|
113
162
|
```
|
|
114
163
|
|
|
115
|
-
|
|
164
|
+
## Ad Placements
|
|
116
165
|
|
|
117
166
|
| Placement | Description | Recommended Variant |
|
|
118
167
|
|-----------|-------------|-------------------|
|
|
@@ -125,7 +174,7 @@ function Footer() {
|
|
|
125
174
|
| `sidebar_panel` | Web app sidebar | Small variants |
|
|
126
175
|
| `home_banner` | Home page hero | Large variants |
|
|
127
176
|
|
|
128
|
-
|
|
177
|
+
## Ad Variants
|
|
129
178
|
|
|
130
179
|
**Small Variants (compact spaces):**
|
|
131
180
|
- `small_panel_1` - Minimal
|
|
@@ -141,138 +190,242 @@ function Footer() {
|
|
|
141
190
|
- `large_slider_4` - Comparison
|
|
142
191
|
- `large_slider_5` - Video Placeholder
|
|
143
192
|
|
|
144
|
-
##
|
|
145
|
-
|
|
146
|
-
### `initSharedFeatures(config)`
|
|
147
|
-
|
|
148
|
-
Initialize the package with your configuration.
|
|
193
|
+
## Ad Components
|
|
149
194
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
projectName: string;
|
|
155
|
-
platform: 'web' | 'android' | 'ios' | 'extension';
|
|
156
|
-
debug?: boolean;
|
|
157
|
-
}
|
|
195
|
+
### `AdPanel`
|
|
196
|
+
Simple single-ad panel for sidebars and footers.
|
|
197
|
+
```tsx
|
|
198
|
+
<AdPanel placement="sidebar_panel" variant="small_panel_2" />
|
|
158
199
|
```
|
|
159
200
|
|
|
160
|
-
### `
|
|
201
|
+
### `AdSlider`
|
|
202
|
+
Small promotional slider with auto-rotation.
|
|
203
|
+
```tsx
|
|
204
|
+
<AdSlider placement="footer_slider" />
|
|
205
|
+
```
|
|
161
206
|
|
|
162
|
-
|
|
207
|
+
### `AdBanner`
|
|
208
|
+
Permanent promotional banner with progress indicators.
|
|
209
|
+
```tsx
|
|
210
|
+
<AdBanner placement="home_banner" rotationInterval={10000} maxCampaigns={5} />
|
|
211
|
+
```
|
|
163
212
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
autoFetch?: boolean;
|
|
169
|
-
}
|
|
213
|
+
### `AdModal`
|
|
214
|
+
One-time promotional modal shown on first visit.
|
|
215
|
+
```tsx
|
|
216
|
+
import { AdModal, useOneTimeAdModal } from 'shared-features';
|
|
170
217
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
loading: boolean;
|
|
175
|
-
error: string | null;
|
|
176
|
-
refetch: () => Promise<void>;
|
|
177
|
-
recordImpression: (campaign: CampaignWithProduct) => Promise<void>;
|
|
178
|
-
recordClick: (campaign: CampaignWithProduct) => Promise<void>;
|
|
179
|
-
recordClose: (campaign: CampaignWithProduct) => Promise<void>;
|
|
218
|
+
function App() {
|
|
219
|
+
const { shouldShow, markAsShown } = useOneTimeAdModal();
|
|
220
|
+
return shouldShow ? <AdModal onClose={markAsShown} /> : null;
|
|
180
221
|
}
|
|
181
222
|
```
|
|
182
223
|
|
|
183
|
-
###
|
|
184
|
-
|
|
185
|
-
#### `AdPanel`
|
|
186
|
-
|
|
187
|
-
Simple single-ad panel for sidebars and footers.
|
|
188
|
-
|
|
224
|
+
### `AdUpdateModal`
|
|
225
|
+
Carousel modal shown when app version changes.
|
|
189
226
|
```tsx
|
|
190
|
-
|
|
191
|
-
```
|
|
227
|
+
import { AdUpdateModal, useUpdateAdModal } from 'shared-features';
|
|
192
228
|
|
|
193
|
-
|
|
229
|
+
function App() {
|
|
230
|
+
const { shouldShow, markAsShown } = useUpdateAdModal();
|
|
231
|
+
return shouldShow ? <AdUpdateModal onClose={markAsShown} /> : null;
|
|
232
|
+
}
|
|
233
|
+
```
|
|
194
234
|
|
|
195
|
-
|
|
235
|
+
---
|
|
196
236
|
|
|
197
|
-
|
|
198
|
-
<AdSlider placement="footer_slider" className="my-slider" />
|
|
199
|
-
```
|
|
237
|
+
# BROADCASTS/NOTIFICATIONS SYSTEM
|
|
200
238
|
|
|
201
|
-
|
|
239
|
+
Send in-app notifications, announcements, and alerts across all projects.
|
|
202
240
|
|
|
203
|
-
|
|
241
|
+
## Firestore Collections
|
|
204
242
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
/>
|
|
211
|
-
```
|
|
243
|
+
| Collection | Purpose | Access |
|
|
244
|
+
|------------|---------|--------|
|
|
245
|
+
| `zaions_broadcasts` | Notification content, targeting, scheduling | Public read, Admin write |
|
|
246
|
+
| `zaions_broadcast_events` | Analytics (views, clicks, dismissals) | Public create, Admin read |
|
|
247
|
+
| `zaions_notification_templates` | Reusable notification templates | Admin only |
|
|
212
248
|
|
|
213
|
-
|
|
249
|
+
## Displaying Broadcasts
|
|
214
250
|
|
|
215
|
-
|
|
251
|
+
### Banner Notifications (Top of Page)
|
|
216
252
|
|
|
217
253
|
```tsx
|
|
218
|
-
import {
|
|
254
|
+
import { BroadcastBanner, useBannerBroadcasts } from 'shared-features';
|
|
219
255
|
|
|
220
256
|
function App() {
|
|
221
|
-
const {
|
|
257
|
+
const { broadcasts, dismissBroadcast, trackClick } = useBannerBroadcasts();
|
|
222
258
|
|
|
223
259
|
return (
|
|
224
260
|
<>
|
|
225
|
-
|
|
261
|
+
<BroadcastBanner
|
|
262
|
+
broadcasts={broadcasts}
|
|
263
|
+
onDismiss={dismissBroadcast}
|
|
264
|
+
onClick={trackClick}
|
|
265
|
+
/>
|
|
226
266
|
{/* Your app content */}
|
|
227
267
|
</>
|
|
228
268
|
);
|
|
229
269
|
}
|
|
230
270
|
```
|
|
231
271
|
|
|
232
|
-
|
|
272
|
+
### Modal Notifications
|
|
233
273
|
|
|
234
|
-
|
|
274
|
+
```tsx
|
|
275
|
+
import { useBroadcasts } from 'shared-features';
|
|
276
|
+
|
|
277
|
+
function App() {
|
|
278
|
+
const { broadcasts, dismissBroadcast } = useBroadcasts({ variant: 'modal' });
|
|
279
|
+
const modalBroadcast = broadcasts[0];
|
|
280
|
+
|
|
281
|
+
if (!modalBroadcast) return <YourApp />;
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<Modal open onClose={() => dismissBroadcast(modalBroadcast.id)}>
|
|
285
|
+
<h2>{modalBroadcast.title}</h2>
|
|
286
|
+
<p>{modalBroadcast.message}</p>
|
|
287
|
+
</Modal>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Toast Notifications
|
|
235
293
|
|
|
236
294
|
```tsx
|
|
237
|
-
import {
|
|
295
|
+
import { useBroadcasts } from 'shared-features';
|
|
238
296
|
|
|
239
297
|
function App() {
|
|
240
|
-
const {
|
|
298
|
+
const { broadcasts, dismissBroadcast } = useBroadcasts({ variant: 'toast' });
|
|
241
299
|
|
|
242
300
|
return (
|
|
243
301
|
<>
|
|
244
|
-
|
|
245
|
-
{
|
|
302
|
+
<YourApp />
|
|
303
|
+
{broadcasts.map(toast => (
|
|
304
|
+
<Toast key={toast.id} onClose={() => dismissBroadcast(toast.id)}>
|
|
305
|
+
{toast.message}
|
|
306
|
+
</Toast>
|
|
307
|
+
))}
|
|
246
308
|
</>
|
|
247
309
|
);
|
|
248
310
|
}
|
|
249
311
|
```
|
|
250
312
|
|
|
251
|
-
|
|
313
|
+
## Broadcast Variants
|
|
314
|
+
|
|
315
|
+
| Variant | Use Case |
|
|
316
|
+
|---------|----------|
|
|
317
|
+
| `banner` | Persistent notification at top of page |
|
|
318
|
+
| `modal` | Important announcement requiring attention |
|
|
319
|
+
| `toast` | Brief notification that auto-dismisses |
|
|
320
|
+
| `bell` | Notification center item |
|
|
321
|
+
|
|
322
|
+
## Broadcast Priority
|
|
323
|
+
|
|
324
|
+
| Priority | Use Case |
|
|
325
|
+
|----------|----------|
|
|
326
|
+
| `low` | General announcements |
|
|
327
|
+
| `medium` | Feature updates, tips |
|
|
328
|
+
| `high` | Important notices |
|
|
329
|
+
| `urgent` | Critical alerts, maintenance |
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
# API REFERENCE
|
|
334
|
+
|
|
335
|
+
## Initialization
|
|
336
|
+
|
|
337
|
+
### `initSharedFeatures(config)`
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
interface SharedFeaturesConfig {
|
|
341
|
+
firebaseConfig: FirebaseConfig;
|
|
342
|
+
projectId: string; // e.g., 'ztools'
|
|
343
|
+
projectName: string; // e.g., 'ZTools'
|
|
344
|
+
platform: 'web' | 'android' | 'ios' | 'extension';
|
|
345
|
+
debug?: boolean;
|
|
346
|
+
}
|
|
347
|
+
```
|
|
252
348
|
|
|
253
|
-
|
|
349
|
+
## Advertising Hooks
|
|
254
350
|
|
|
255
|
-
|
|
351
|
+
### `useCampaigns(options)`
|
|
256
352
|
|
|
257
353
|
```typescript
|
|
258
|
-
|
|
354
|
+
interface UseCampaignsOptions {
|
|
355
|
+
placement: AdPlacement;
|
|
356
|
+
maxCampaigns?: number;
|
|
357
|
+
autoFetch?: boolean;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
interface UseCampaignsResult {
|
|
361
|
+
campaigns: CampaignWithProduct[];
|
|
362
|
+
campaign: CampaignWithProduct | null;
|
|
363
|
+
loading: boolean;
|
|
364
|
+
error: string | null;
|
|
365
|
+
refetch: () => Promise<void>;
|
|
366
|
+
recordImpression: (campaign) => Promise<void>;
|
|
367
|
+
recordClick: (campaign) => Promise<void>;
|
|
368
|
+
recordClose: (campaign) => Promise<void>;
|
|
369
|
+
}
|
|
259
370
|
```
|
|
260
371
|
|
|
261
|
-
|
|
372
|
+
### `useOneTimeAdModal()`
|
|
373
|
+
Manages first-visit modal visibility.
|
|
374
|
+
|
|
375
|
+
### `useUpdateAdModal(currentVersion?)`
|
|
376
|
+
Manages version-change modal visibility.
|
|
262
377
|
|
|
263
|
-
|
|
378
|
+
## Broadcast Hooks
|
|
379
|
+
|
|
380
|
+
### `useBroadcasts(options)`
|
|
264
381
|
|
|
265
382
|
```typescript
|
|
266
|
-
|
|
383
|
+
interface UseBroadcastsOptions {
|
|
384
|
+
variant?: 'banner' | 'modal' | 'toast' | 'bell';
|
|
385
|
+
maxBroadcasts?: number;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface UseBroadcastsResult {
|
|
389
|
+
broadcasts: BroadcastNotification[];
|
|
390
|
+
isLoading: boolean;
|
|
391
|
+
error: Error | null;
|
|
392
|
+
dismissBroadcast: (id: string) => void;
|
|
393
|
+
trackClick: (broadcast) => Promise<void>;
|
|
394
|
+
refresh: () => Promise<void>;
|
|
395
|
+
}
|
|
267
396
|
```
|
|
268
397
|
|
|
398
|
+
### `useBannerBroadcasts()`
|
|
399
|
+
Convenience hook for banner broadcasts.
|
|
400
|
+
|
|
401
|
+
### `useModalBroadcasts()`
|
|
402
|
+
Convenience hook for modal broadcasts.
|
|
403
|
+
|
|
404
|
+
### `useToastBroadcasts()`
|
|
405
|
+
Convenience hook for toast broadcasts.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
# ADMIN PANEL
|
|
410
|
+
|
|
411
|
+
Both systems are managed through the admin panel at aoneahsan.com:
|
|
412
|
+
|
|
413
|
+
| System | Admin URL | What You Manage |
|
|
414
|
+
|--------|-----------|-----------------|
|
|
415
|
+
| Advertising | `/admin/campaigns` | Products, Campaigns, Ad targeting |
|
|
416
|
+
| Notifications | `/admin/notifications` | Broadcasts, Templates, Scheduling |
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
269
420
|
## Frequency Capping
|
|
270
421
|
|
|
271
|
-
|
|
422
|
+
Both systems support frequency capping:
|
|
423
|
+
- **Ads**: Controlled per campaign (default: 20 days between impressions)
|
|
424
|
+
- **Broadcasts**: Dismissals are tracked, won't show again until dismissed list clears
|
|
272
425
|
|
|
273
|
-
|
|
426
|
+
Tracking uses Capacitor Preferences (mobile) or localStorage (web).
|
|
274
427
|
|
|
275
|
-
|
|
428
|
+
---
|
|
276
429
|
|
|
277
430
|
## License
|
|
278
431
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shared-features",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Shared features for Zaions projects - centralized ads, notifications, broadcasts, contacts, and more",
|
|
5
5
|
"author": "Ahsan Mahmood <aoneahsan@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@radix-ui/react-icons": ">=1.3.2",
|
|
73
73
|
"@radix-ui/themes": ">=3.2.1",
|
|
74
74
|
"firebase": ">=12.8.0",
|
|
75
|
-
"lucide-react": ">=0.
|
|
75
|
+
"lucide-react": ">=0.562.0",
|
|
76
76
|
"react": ">=19.2.3",
|
|
77
77
|
"react-dom": ">=19.2.3",
|
|
78
78
|
"zustand": ">=5.0.10"
|