featuredrop 1.1.0 → 1.2.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.
Files changed (60) hide show
  1. package/README.md +376 -4
  2. package/dist/angular.cjs +286 -0
  3. package/dist/angular.cjs.map +1 -0
  4. package/dist/angular.d.cts +229 -0
  5. package/dist/angular.d.ts +229 -0
  6. package/dist/angular.js +283 -0
  7. package/dist/angular.js.map +1 -0
  8. package/dist/featuredrop.cjs +1256 -0
  9. package/dist/featuredrop.cjs.map +1 -0
  10. package/dist/index.cjs +2762 -16
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +979 -9
  13. package/dist/index.d.ts +979 -9
  14. package/dist/index.js +2720 -17
  15. package/dist/index.js.map +1 -1
  16. package/dist/preact.cjs +7289 -0
  17. package/dist/preact.cjs.map +1 -0
  18. package/dist/preact.d.cts +1266 -0
  19. package/dist/preact.d.ts +1266 -0
  20. package/dist/preact.js +7259 -0
  21. package/dist/preact.js.map +1 -0
  22. package/dist/react.cjs +6119 -101
  23. package/dist/react.cjs.map +1 -1
  24. package/dist/react.d.cts +798 -5
  25. package/dist/react.d.ts +798 -5
  26. package/dist/react.js +6103 -103
  27. package/dist/react.js.map +1 -1
  28. package/dist/schema.cjs +215 -0
  29. package/dist/schema.cjs.map +1 -0
  30. package/dist/schema.d.cts +203 -0
  31. package/dist/schema.d.ts +203 -0
  32. package/dist/schema.js +209 -0
  33. package/dist/schema.js.map +1 -0
  34. package/dist/solid.cjs +373 -0
  35. package/dist/solid.cjs.map +1 -0
  36. package/dist/solid.d.cts +242 -0
  37. package/dist/solid.d.ts +242 -0
  38. package/dist/solid.js +366 -0
  39. package/dist/solid.js.map +1 -0
  40. package/dist/svelte.cjs +329 -0
  41. package/dist/svelte.cjs.map +1 -0
  42. package/dist/svelte.js +324 -0
  43. package/dist/svelte.js.map +1 -0
  44. package/dist/testing.cjs +1422 -0
  45. package/dist/testing.cjs.map +1 -0
  46. package/dist/testing.d.cts +339 -0
  47. package/dist/testing.d.ts +339 -0
  48. package/dist/testing.js +1415 -0
  49. package/dist/testing.js.map +1 -0
  50. package/dist/vue.cjs +1084 -0
  51. package/dist/vue.cjs.map +1 -0
  52. package/dist/vue.js +1072 -0
  53. package/dist/vue.js.map +1 -0
  54. package/dist/web-components.cjs +483 -0
  55. package/dist/web-components.cjs.map +1 -0
  56. package/dist/web-components.d.cts +211 -0
  57. package/dist/web-components.d.ts +211 -0
  58. package/dist/web-components.js +477 -0
  59. package/dist/web-components.js.map +1 -0
  60. package/package.json +126 -3
package/README.md CHANGED
@@ -87,6 +87,14 @@ export const FEATURES = createManifest([
87
87
  priority: 'critical',
88
88
  cta: { label: 'Try it', url: '/journal' },
89
89
  },
90
+ {
91
+ id: 'scheduled-reports',
92
+ label: 'Scheduled Reports',
93
+ releasedAt: '2026-02-23T00:00:00Z',
94
+ showNewUntil: '2026-03-23T00:00:00Z',
95
+ dependsOn: { clicked: ['ai-journal'] }, // progressive rollout
96
+ trigger: { type: 'page', match: '/reports/*' }, // contextual trigger
97
+ },
90
98
  ])
91
99
  ```
92
100
 
@@ -112,6 +120,201 @@ hasNewFeature(FEATURES, '/journal', storage) // true/false
112
120
 
113
121
  Works with **any framework**. Zero React dependency for vanilla use.
114
122
 
123
+ ## Adoption Analytics
124
+
125
+ Pipe structured adoption events to PostHog/Amplitude/Mixpanel/Segment or your own endpoint.
126
+
127
+ ```ts
128
+ import { AnalyticsCollector, PostHogAdapter } from 'featuredrop'
129
+
130
+ const collector = new AnalyticsCollector({
131
+ adapter: new PostHogAdapter(posthog),
132
+ batchSize: 20,
133
+ flushInterval: 10_000,
134
+ sampleRate: 1,
135
+ })
136
+ ```
137
+
138
+ ```tsx
139
+ <FeatureDropProvider
140
+ manifest={FEATURES}
141
+ storage={storage}
142
+ collector={collector}
143
+ >
144
+ <App />
145
+ </FeatureDropProvider>
146
+ ```
147
+
148
+ ## A/B Announcement Variants
149
+
150
+ Run deterministic per-user announcement variants with weighted splits.
151
+
152
+ ```ts
153
+ {
154
+ id: 'ai-journal',
155
+ label: 'AI Decision Journal',
156
+ variants: {
157
+ control: { description: 'Track decisions with AI-powered insights.' },
158
+ treatment: { description: 'Never second-guess decisions again.' },
159
+ },
160
+ variantSplit: [50, 50],
161
+ }
162
+ ```
163
+
164
+ ```tsx
165
+ <FeatureDropProvider
166
+ manifest={FEATURES}
167
+ storage={storage}
168
+ variantKey={user.id} // stable key for deterministic assignment
169
+ >
170
+ <App />
171
+ </FeatureDropProvider>
172
+ ```
173
+
174
+ ## Theme Engine
175
+
176
+ Theme all featuredrop components with CSS variables (no CSS-in-JS runtime).
177
+
178
+ ```tsx
179
+ import { ThemeProvider, ChangelogWidget } from 'featuredrop/react'
180
+
181
+ <ThemeProvider theme="dark">
182
+ <ChangelogWidget />
183
+ </ThemeProvider>
184
+ ```
185
+
186
+ ```tsx
187
+ import { createTheme } from 'featuredrop'
188
+ import { ThemeProvider, ChangelogPage } from 'featuredrop/react'
189
+
190
+ const myTheme = createTheme({
191
+ colors: { primary: '#7c3aed' },
192
+ radii: { lg: '16px' },
193
+ })
194
+
195
+ <ThemeProvider theme={myTheme}>
196
+ <ChangelogPage />
197
+ </ThemeProvider>
198
+ ```
199
+
200
+ Presets: `light`, `dark`, `auto`, `minimal`, `vibrant`.
201
+ You can also pass `theme` directly to `ChangelogWidget` and `ChangelogPage` for component-scoped overrides.
202
+
203
+ ## Internationalization
204
+
205
+ Use built-in locale packs or supply partial overrides:
206
+
207
+ ```tsx
208
+ <FeatureDropProvider
209
+ manifest={FEATURES}
210
+ storage={storage}
211
+ locale="fr"
212
+ translations={{
213
+ submit: 'Envoyer maintenant',
214
+ }}
215
+ >
216
+ <App />
217
+ </FeatureDropProvider>
218
+ ```
219
+
220
+ Built-in locales: `en`, `es`, `fr`, `de`, `pt`, `zh-cn`, `ja`, `ko`, `ar`, `hi`.
221
+
222
+ ## Changelog-as-Code
223
+
224
+ Manage announcements as markdown files in your repo and compile to a manifest:
225
+
226
+ ```bash
227
+ npx featuredrop init --format markdown
228
+ npx featuredrop add --label "AI Journal" --category ai --description "Track decisions with AI."
229
+ npx featuredrop build --pattern "features/**/*.md" --out featuredrop.manifest.json
230
+ npx featuredrop validate --pattern "features/**/*.md"
231
+ npx featuredrop stats --pattern "features/**/*.md"
232
+ npx featuredrop doctor --pattern "features/**/*.md"
233
+ npx featuredrop generate-rss --pattern "features/**/*.md" --out featuredrop.rss.xml
234
+ npx featuredrop generate-changelog --pattern "features/**/*.md" --out CHANGELOG.generated.md
235
+ npx featuredrop migrate --from beamer --input beamer-export.json --out featuredrop.manifest.json
236
+ ```
237
+
238
+ Example feature file:
239
+
240
+ ```md
241
+ ---
242
+ id: ai-journal
243
+ label: AI Journal
244
+ type: feature
245
+ category: ai
246
+ releasedAt: 2026-02-15T00:00:00Z
247
+ showNewUntil: 2026-03-15T00:00:00Z
248
+ cta:
249
+ label: Try it now
250
+ url: /journal
251
+ ---
252
+ Track decisions and outcomes with AI-powered insights.
253
+ ```
254
+
255
+ ## Schema Validation
256
+
257
+ Validate manifest JSON in CI or tooling pipelines.
258
+
259
+ ```ts
260
+ import {
261
+ featureEntrySchema,
262
+ featureEntryJsonSchema,
263
+ validateManifest,
264
+ } from 'featuredrop/schema'
265
+
266
+ featureEntrySchema.parse({
267
+ id: 'ai-journal',
268
+ label: 'AI Journal',
269
+ releasedAt: '2026-02-15T00:00:00Z',
270
+ showNewUntil: '2026-03-15T00:00:00Z',
271
+ })
272
+
273
+ const result = validateManifest(data)
274
+ if (!result.valid) {
275
+ throw new Error(result.errors.map((e) => `${e.path}: ${e.message}`).join("; "))
276
+ }
277
+
278
+ console.log(featureEntryJsonSchema.properties.id.type) // "string"
279
+ ```
280
+
281
+ ## Testing Utilities
282
+
283
+ Use `featuredrop/testing` to speed up unit and component tests.
284
+
285
+ ```tsx
286
+ import { render, screen } from '@testing-library/react'
287
+ import { useNewCount } from 'featuredrop/react'
288
+ import { createMockManifest, createMockStorage, createTestProvider } from 'featuredrop/testing'
289
+
290
+ const manifest = createMockManifest([{ label: 'AI Journal', releasedAt: 'today', showNewUntil: '+14d' }])
291
+ const storage = createMockStorage()
292
+ const Wrapper = createTestProvider({ manifest, storage })
293
+
294
+ function Count() {
295
+ return <span>{useNewCount()}</span>
296
+ }
297
+
298
+ render(<Count />, { wrapper: Wrapper })
299
+ expect(screen.getByText('1')).toBeInTheDocument()
300
+ ```
301
+
302
+ ## Playground & Online Demos
303
+
304
+ Use the lightweight component playground for quick UI iteration:
305
+
306
+ ```bash
307
+ pnpm --dir examples/sandbox-react install
308
+ pnpm playground
309
+ pnpm playground:build
310
+ ```
311
+
312
+ One-click editable demos:
313
+
314
+ - React sandbox source: `examples/sandbox-react`
315
+ - StackBlitz: https://stackblitz.com/github/GLINCKER/featuredrop/tree/main/examples/sandbox-react
316
+ - CodeSandbox: https://codesandbox.io/p/sandbox/github/GLINCKER/featuredrop/tree/main/examples/sandbox-react
317
+
115
318
  ## Components
116
319
 
117
320
  Everything you'd expect from Beamer or Headway — but free, self-hosted, and headless-first.
@@ -129,6 +332,9 @@ import { ChangelogWidget } from 'featuredrop/react'
129
332
  // Or modal / popover variant
130
333
  <ChangelogWidget variant="modal" title="Release Notes" />
131
334
 
335
+ // Enable emoji reactions on entries
336
+ <ChangelogWidget showReactions />
337
+
132
338
  // Fully headless
133
339
  <ChangelogWidget>
134
340
  {({ isOpen, toggle, features, count, dismissAll }) => (
@@ -177,6 +383,124 @@ import { Toast } from 'featuredrop/react'
177
383
  <Toast featureIds={["ai-journal"]} autoDismissMs={5000} />
178
384
  ```
179
385
 
386
+ ### Product Tours
387
+
388
+ Guided, multi-step onboarding with keyboard navigation and persistence.
389
+
390
+ ```tsx
391
+ import { Tour, useTour } from 'featuredrop/react'
392
+
393
+ <Tour id="onboarding" steps={steps} />
394
+ const { startTour, nextStep, skipTour } = useTour('onboarding')
395
+ ```
396
+
397
+ ### Onboarding Checklist
398
+
399
+ Task-based onboarding that can trigger tours, links, or callbacks.
400
+
401
+ ```tsx
402
+ import { Checklist, useChecklist } from 'featuredrop/react'
403
+
404
+ <Checklist id="getting-started" tasks={tasks} />
405
+ const { completeTask, progress } = useChecklist('getting-started')
406
+ ```
407
+
408
+ ### Feedback Widget
409
+
410
+ Collect lightweight in-app feedback with optional emoji and screenshots.
411
+
412
+ ```tsx
413
+ import { FeedbackWidget } from 'featuredrop/react'
414
+
415
+ <FeedbackWidget
416
+ featureId="ai-journal"
417
+ onSubmit={async (payload) => {
418
+ await fetch('/api/feedback', { method: 'POST', body: JSON.stringify(payload) })
419
+ }}
420
+ showEmoji
421
+ showScreenshot
422
+ rateLimit="1-per-feature"
423
+ />
424
+ ```
425
+
426
+ ### Survey (NPS / CSAT / CES / Custom)
427
+
428
+ Run micro-surveys with trigger rules and imperative controls.
429
+
430
+ ```tsx
431
+ import { Survey, useSurvey } from 'featuredrop/react'
432
+
433
+ <Survey
434
+ id="nps-main"
435
+ type="nps"
436
+ prompt="How likely are you to recommend us?"
437
+ triggerRules={{ minDaysSinceSignup: 7, signupAt: user.createdAt }}
438
+ onSubmit={saveSurvey}
439
+ />
440
+
441
+ const { show } = useSurvey('nps-main')
442
+ ```
443
+
444
+ ### Feature Request Voting
445
+
446
+ Capture and rank product requests with local persistence and optional webhook sync.
447
+
448
+ ```tsx
449
+ import { FeatureRequestButton, FeatureRequestForm } from 'featuredrop/react'
450
+
451
+ <FeatureRequestButton featureId="dark-mode" requestTitle="Dark mode" />
452
+
453
+ <FeatureRequestForm
454
+ categories={['UI', 'Performance', 'Integration', 'Other']}
455
+ onSubmit={async (request) => {
456
+ await fetch('/api/requests', { method: 'POST', body: JSON.stringify(request) })
457
+ }}
458
+ />
459
+ ```
460
+
461
+ ### Hotspots & Tooltips
462
+
463
+ Persistent contextual hints attached to specific UI targets.
464
+
465
+ ```tsx
466
+ import { Hotspot, TooltipGroup } from 'featuredrop/react'
467
+
468
+ <TooltipGroup maxVisible={1}>
469
+ <Hotspot id="export-help" target="#export-btn" frequency="once">
470
+ Export supports CSV, PDF, and Excel.
471
+ </Hotspot>
472
+ </TooltipGroup>
473
+ ```
474
+
475
+ ### Announcement Modal
476
+
477
+ Priority-based modal announcements with optional slide carousel.
478
+
479
+ ```tsx
480
+ import { AnnouncementModal } from 'featuredrop/react'
481
+
482
+ <AnnouncementModal
483
+ feature={criticalFeature}
484
+ trigger="auto"
485
+ frequency="once"
486
+ />
487
+ ```
488
+
489
+ ### Spotlight Chain
490
+
491
+ Lightweight chained spotlights for "here are 3 new things" flows.
492
+
493
+ ```tsx
494
+ import { SpotlightChain } from 'featuredrop/react'
495
+
496
+ <SpotlightChain
497
+ steps={[
498
+ { target: '#sidebar', content: 'New navigation' },
499
+ { target: '#search', content: 'Global search' },
500
+ ]}
501
+ />
502
+ ```
503
+
180
504
  ### NewBadge
181
505
 
182
506
  Headless badge component with variants. Zero CSS framework dependency.
@@ -211,7 +535,27 @@ npm install featuredrop react # react is an optional peer dep
211
535
  ```tsx
212
536
  import { FeatureDropProvider } from 'featuredrop/react'
213
537
 
214
- <FeatureDropProvider manifest={FEATURES} storage={storage}>
538
+ <FeatureDropProvider manifest={FEATURES} storage={storage} appVersion="2.5.1">
539
+ <App />
540
+ </FeatureDropProvider>
541
+ ```
542
+
543
+ **Throttling + quiet mode:**
544
+
545
+ ```tsx
546
+ <FeatureDropProvider
547
+ manifest={FEATURES}
548
+ storage={storage}
549
+ throttle={{
550
+ maxSimultaneousBadges: 3,
551
+ maxSimultaneousSpotlights: 1,
552
+ maxToastsPerSession: 3,
553
+ minTimeBetweenModals: 30000,
554
+ minTimeBetweenTours: 86400000,
555
+ sessionCooldown: 5000,
556
+ respectDoNotDisturb: true,
557
+ }}
558
+ >
215
559
  <App />
216
560
  </FeatureDropProvider>
217
561
  ```
@@ -248,11 +592,28 @@ import { ChangelogWidget } from 'featuredrop/react'
248
592
  | `useNewFeature(key)` | Single nav item: `{ isNew, feature, dismiss }` |
249
593
  | `useNewCount()` | Just the badge count |
250
594
  | `useTabNotification()` | Updates browser tab title with count |
595
+ | `useTour(id)` | Imperative tour controls and current step snapshot |
596
+ | `useTourSequencer(sequence)` | Ordered multi-tour orchestration by feature readiness |
597
+ | `useChecklist(id)` | Imperative checklist controls + progress |
598
+ | `useSurvey(id)` | Imperative survey controls (`show`, `hide`, `askLater`) + state |
251
599
  | `<NewBadge />` | Headless badge: `pill`, `dot`, or `count` variant |
252
- | `<ChangelogWidget />` | Full changelog feed with trigger button |
600
+ | `<ChangelogWidget />` | Full changelog feed with trigger button + optional reactions |
601
+ | `<ChangelogPage />` | Full-page changelog with filters/search/pagination |
253
602
  | `<Spotlight />` | Pulsing beacon attached to DOM elements |
254
603
  | `<Banner />` | Announcement banner with variants |
255
604
  | `<Toast />` | Stackable toast notifications |
605
+ | `<Tour />` | Multi-step guided product tour |
606
+ | `<Checklist />` | Onboarding task checklist |
607
+ | `<FeedbackWidget />` | In-app feedback form with category/emoji/screenshot support |
608
+ | `<Survey />` | NPS/CSAT/CES/custom survey engine with trigger rules |
609
+ | `<FeatureRequestButton />` | Per-feature voting button with persisted vote guard |
610
+ | `<FeatureRequestForm />` | Request capture form + sortable request list |
611
+ | `<Hotspot />` / `<TooltipGroup />` | Contextual tooltips with visibility caps |
612
+ | `<AnnouncementModal />` | Priority/frequency-gated modal announcements |
613
+ | `<SpotlightChain />` | Lightweight chained spotlight walkthrough |
614
+
615
+ `useFeatureDrop()` also exposes queue/throttle controls: `queuedFeatures`, `totalNewCount`, `quietMode`, `setQuietMode`, `markFeatureSeen`, `markFeatureClicked`, toast-slot helpers, modal/tour pacing checks, and spotlight slot controls.
616
+ It also exposes trigger runtime helpers: `trackUsageEvent`, `trackTriggerEvent`, `trackMilestone`, and `setTriggerPath`.
256
617
 
257
618
  **Analytics integration:**
258
619
 
@@ -260,6 +621,7 @@ import { ChangelogWidget } from 'featuredrop/react'
260
621
  <FeatureDropProvider
261
622
  manifest={FEATURES}
262
623
  storage={storage}
624
+ appVersion="2.5.1" // optional semver for version-pinned features
263
625
  analytics={{
264
626
  onFeatureSeen: (f) => posthog.capture('feature_seen', { id: f.id }),
265
627
  onFeatureDismissed: (f) => posthog.capture('feature_dismissed', { id: f.id }),
@@ -311,7 +673,12 @@ Read the full [Architecture doc](docs/ARCHITECTURE.md) for cross-device sync flo
311
673
  | **Price** | **Free** | $59-399/mo | $49-249/mo | $79-299/mo | $79+ |
312
674
  | Auto-expiring badges | Yes | - | - | - | - |
313
675
  | Changelog widget | Yes | Yes | Yes | Yes | Yes |
676
+ | Product tours | Yes | - | - | - | - |
677
+ | Onboarding checklists | Yes | - | - | - | - |
314
678
  | Spotlight/beacon | Yes | - | - | - | - |
679
+ | Hotspot tooltips | Yes | - | - | - | - |
680
+ | Announcement modal | Yes | - | - | - | - |
681
+ | Spotlight chaining | Yes | - | - | - | - |
315
682
  | Toast notifications | Yes | - | - | - | - |
316
683
  | Announcement banner | Yes | - | - | - | - |
317
684
  | Tab title notification | Yes | - | - | - | - |
@@ -334,8 +701,12 @@ Read the full [Architecture doc](docs/ARCHITECTURE.md) for cross-device sync flo
334
701
  |-----------|--------|--------|
335
702
  | React / Next.js | Stable | `featuredrop/react` |
336
703
  | Vanilla JS | Stable | `featuredrop` |
337
- | Vue 3 | Planned | `featuredrop/vue` |
338
- | Svelte 5 | Planned | `featuredrop/svelte` |
704
+ | SolidJS | Preview | `featuredrop/solid` |
705
+ | Preact (compat) | Preview | `featuredrop/preact` |
706
+ | Web Components | Preview | `featuredrop/web-components` |
707
+ | Angular | Preview | `featuredrop/angular` |
708
+ | Vue 3 | Preview | `featuredrop/vue` |
709
+ | Svelte 5 | Preview (store bindings) | `featuredrop/svelte` |
339
710
 
340
711
  ## Documentation
341
712
 
@@ -343,6 +714,7 @@ Read the full [Architecture doc](docs/ARCHITECTURE.md) for cross-device sync flo
343
714
  - [Architecture](docs/ARCHITECTURE.md) — Three-check algorithm, cross-device sync, custom adapters
344
715
  - [Next.js Example](examples/nextjs/) — Full App Router integration
345
716
  - [Vanilla Example](examples/vanilla/) — Plain HTML, zero build step
717
+ - [React Sandbox](examples/sandbox-react/) — Interactive local/online playground
346
718
 
347
719
  ## Contributing
348
720