@algenium/blocks 1.12.0 → 1.14.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 +160 -0
- package/dist/index.cjs +1781 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +291 -7
- package/dist/index.d.ts +291 -7
- package/dist/index.js +1629 -32
- package/dist/index.js.map +1 -1
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -20,6 +20,13 @@ This package requires the following peer dependencies:
|
|
|
20
20
|
pnpm add react react-dom next-themes lucide-react motion
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
`hls.js` (`>=1.5`) is an **optional** peer dependency required only by
|
|
24
|
+
`VideoPlayer`; install it in apps that use the player:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm add hls.js
|
|
28
|
+
```
|
|
29
|
+
|
|
23
30
|
## Configuration
|
|
24
31
|
|
|
25
32
|
### Tailwind CSS
|
|
@@ -415,6 +422,159 @@ interface Notification {
|
|
|
415
422
|
|
|
416
423
|
---
|
|
417
424
|
|
|
425
|
+
### EmojiPicker
|
|
426
|
+
|
|
427
|
+
A zero-dependency emoji picker with bilingual (English + Spanish) search,
|
|
428
|
+
category navigation, a persisted "frequently used" section, a global skin-tone
|
|
429
|
+
preference, and desktop-first keyboard navigation. The emoji dataset (~1,900
|
|
430
|
+
emoji, Unicode ≤ 15.1) is generated at build time from Unicode CLDR annotations
|
|
431
|
+
and committed to the repo, so consuming apps ship **no** extra runtime
|
|
432
|
+
dependencies. Because the package is `sideEffects: false` and tree-shaken, apps
|
|
433
|
+
that never import `EmojiPicker` don't bundle the data at all.
|
|
434
|
+
|
|
435
|
+
**Features:**
|
|
436
|
+
|
|
437
|
+
- Bilingual search: "corazón", "corazon" and "heart" all match ❤️
|
|
438
|
+
- 9 categories with an icon tab bar and scroll-to-section
|
|
439
|
+
- "Frequently used" recents, persisted in `localStorage`
|
|
440
|
+
- Global skin-tone selector (applied to capable emoji), persisted
|
|
441
|
+
- Keyboard navigation: arrows move, Enter/Space selects
|
|
442
|
+
- `labels` + `locale` props for i18n; search is always bilingual
|
|
443
|
+
|
|
444
|
+
**Usage:**
|
|
445
|
+
|
|
446
|
+
```tsx
|
|
447
|
+
import { useRef, useState } from "react";
|
|
448
|
+
import { EmojiPickerPopover } from "@algenium/blocks";
|
|
449
|
+
|
|
450
|
+
function Composer() {
|
|
451
|
+
const ref = useRef<HTMLTextAreaElement>(null);
|
|
452
|
+
const [value, setValue] = useState("");
|
|
453
|
+
|
|
454
|
+
function insert(emoji: string) {
|
|
455
|
+
const el = ref.current;
|
|
456
|
+
if (!el) return setValue((v) => v + emoji);
|
|
457
|
+
const start = el.selectionStart ?? value.length;
|
|
458
|
+
const end = el.selectionEnd ?? value.length;
|
|
459
|
+
setValue(value.slice(0, start) + emoji + value.slice(end));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return (
|
|
463
|
+
<div className="flex items-end gap-2">
|
|
464
|
+
<textarea
|
|
465
|
+
ref={ref}
|
|
466
|
+
value={value}
|
|
467
|
+
onChange={(e) => setValue(e.target.value)}
|
|
468
|
+
/>
|
|
469
|
+
<EmojiPickerPopover locale="es" onSelect={insert} />
|
|
470
|
+
</div>
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Use the standalone panel when you want to place it inside your own anchor:
|
|
476
|
+
|
|
477
|
+
```tsx
|
|
478
|
+
import { EmojiPicker } from "@algenium/blocks";
|
|
479
|
+
|
|
480
|
+
<EmojiPicker locale="es" onSelect={(emoji) => insert(emoji)} />;
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**Props (`EmojiPicker`):**
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
interface EmojiPickerProps {
|
|
487
|
+
onSelect: (emoji: string) => void;
|
|
488
|
+
locale?: "en" | "es"; // Section titles + skin-tone names. Default "en"
|
|
489
|
+
labels?: EmojiPickerLabels; // Overrides individual strings / category titles
|
|
490
|
+
className?: string;
|
|
491
|
+
recentLimit?: number; // Default 24
|
|
492
|
+
storageKey?: string | null; // localStorage namespace; null disables persistence
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
`EmojiPickerPopover` accepts every `EmojiPicker` prop plus `triggerLabel`,
|
|
497
|
+
`triggerClassName`, `side`, `align`, `open`/`onOpenChange` (controlled), and
|
|
498
|
+
`keepOpenOnSelect`.
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
### VideoPlayer
|
|
503
|
+
|
|
504
|
+
A standardized HLS video player with a fully custom control bar (no native
|
|
505
|
+
`controls`), for both live streams and on-demand recordings. `hls.js` is an
|
|
506
|
+
**optional peer dependency** loaded on demand via dynamic import — apps that
|
|
507
|
+
already depend on it (`app`, `admin`, `media`) bundle nothing new, and Safari
|
|
508
|
+
falls back to native HLS.
|
|
509
|
+
|
|
510
|
+
**Features:**
|
|
511
|
+
|
|
512
|
+
- Click-to-play poster (attaches HLS only after the user gesture)
|
|
513
|
+
- Play/pause, mute + hover volume slider, keyboard shortcuts
|
|
514
|
+
- Resolution picker (Auto + hls.js levels), playback speed (VOD)
|
|
515
|
+
- Picture-in-Picture and fullscreen (menus stay usable in fullscreen)
|
|
516
|
+
- VOD: seekbar with buffered ranges + current/total time
|
|
517
|
+
- Live: red pulsing badge, **no seekbar**, and a "go live" affordance when the
|
|
518
|
+
playhead drifts behind the edge
|
|
519
|
+
- `stats` prop renders live viewer / VOD reproduction counts
|
|
520
|
+
- Loading / waiting / error states with retry; errors surfaced via `onError`
|
|
521
|
+
(no bundled reporting) and localized via `labels`
|
|
522
|
+
|
|
523
|
+
**Usage:**
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
import { VideoPlayer, usePlaybackStats } from "@algenium/blocks";
|
|
527
|
+
|
|
528
|
+
function Recording({ mediaId, src, poster }: Props) {
|
|
529
|
+
const stats = usePlaybackStats(
|
|
530
|
+
`https://media.example.com/playback/${mediaId}/stats`,
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
return (
|
|
534
|
+
<VideoPlayer
|
|
535
|
+
src={src}
|
|
536
|
+
mode="vod"
|
|
537
|
+
poster={poster}
|
|
538
|
+
stats={stats}
|
|
539
|
+
labels={{ live: "EN VIVO", formatViews: (n) => `${n} reproducciones` }}
|
|
540
|
+
onFirstPlay={() => {
|
|
541
|
+
void fetch(`https://media.example.com/playback/${mediaId}/view`, {
|
|
542
|
+
method: "POST",
|
|
543
|
+
});
|
|
544
|
+
}}
|
|
545
|
+
onError={(e) => reportToSentry(e)}
|
|
546
|
+
/>
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
For live playback pass `mode="live"` and, typically, `autoPlay muted`.
|
|
552
|
+
|
|
553
|
+
**Props:**
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
interface VideoPlayerProps {
|
|
557
|
+
src: string;
|
|
558
|
+
mode: "live" | "vod";
|
|
559
|
+
poster?: string;
|
|
560
|
+
autoPlay?: boolean;
|
|
561
|
+
muted?: boolean;
|
|
562
|
+
stats?: { viewers?: number; views?: number };
|
|
563
|
+
labels?: VideoPlayerLabels;
|
|
564
|
+
showQualitySelector?: boolean; // Default true
|
|
565
|
+
onPlayingChange?: (playing: boolean) => void;
|
|
566
|
+
onFirstPlay?: () => void; // Fires once — wire your view beacon here
|
|
567
|
+
onError?: (error: DescribedPlaybackError) => void;
|
|
568
|
+
className?: string;
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Also exported: `useHlsPlayback` (the attach/detach hook), `usePlaybackStats`
|
|
573
|
+
(polls a stats endpoint), `createLiveHlsConfig` / `createVodHlsConfig`, and
|
|
574
|
+
`describePlaybackError`.
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
418
578
|
## UI Primitives
|
|
419
579
|
|
|
420
580
|
The package also exports underlying UI primitives that can be used independently:
|