lib-pixelbuild 0.3.1 → 0.3.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.
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- import { getBoolean } from '../utils/propertyUtils.js';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useRef, useState } from 'react';
3
+ import { getBoolean, getString } from '../utils/propertyUtils.js';
4
4
  function toEmbed(src) {
5
5
  const value = src.trim();
6
6
  if (!value)
@@ -13,13 +13,101 @@ function toEmbed(src) {
13
13
  return { kind: 'iframe', src: `https://player.vimeo.com/video/${vimeo[1]}` };
14
14
  return { kind: 'native', src: value };
15
15
  }
16
+ function formatTime(seconds) {
17
+ if (!Number.isFinite(seconds) || seconds < 0)
18
+ return '0:00';
19
+ const minutes = Math.floor(seconds / 60);
20
+ const secs = Math.floor(seconds % 60);
21
+ return `${minutes}:${secs.toString().padStart(2, '0')}`;
22
+ }
23
+ const playIcon = (_jsx("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M8 5v14l11-7z" }) }));
24
+ const pauseIcon = (_jsx("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M6 5h4v14H6zM14 5h4v14h-4z" }) }));
25
+ const fullscreenIcon = (_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M8 3H5a2 2 0 0 0-2 2v3" }), _jsx("path", { d: "M21 8V5a2 2 0 0 0-2-2h-3" }), _jsx("path", { d: "M3 16v3a2 2 0 0 0 2 2h3" }), _jsx("path", { d: "M16 21h3a2 2 0 0 0 2-2v-3" })] }));
26
+ function NativeVideo({ src, poster, showFullscreen, showSettings, centerPlayButton, showProgressBar }) {
27
+ const containerRef = useRef(null);
28
+ const videoRef = useRef(null);
29
+ const [playing, setPlaying] = useState(false);
30
+ const [currentTime, setCurrentTime] = useState(0);
31
+ const [duration, setDuration] = useState(0);
32
+ const customControls = centerPlayButton || !showProgressBar;
33
+ const togglePlay = useCallback(() => {
34
+ const video = videoRef.current;
35
+ if (!video)
36
+ return;
37
+ if (video.paused)
38
+ void video.play();
39
+ else
40
+ video.pause();
41
+ }, []);
42
+ const seek = useCallback((value) => {
43
+ const video = videoRef.current;
44
+ if (!video)
45
+ return;
46
+ video.currentTime = value;
47
+ setCurrentTime(value);
48
+ }, []);
49
+ const toggleFullscreen = useCallback(() => {
50
+ const container = containerRef.current;
51
+ if (!container)
52
+ return;
53
+ if (document.fullscreenElement)
54
+ void document.exitFullscreen();
55
+ else
56
+ void container.requestFullscreen();
57
+ }, []);
58
+ const videoStyle = { width: '100%', height: 'auto', display: 'block', borderRadius: '4px' };
59
+ if (!customControls) {
60
+ const controlsList = [
61
+ !showFullscreen ? 'nofullscreen' : '',
62
+ !showSettings ? 'nodownload noplaybackrate' : ''
63
+ ].filter(Boolean).join(' ');
64
+ return (_jsx("video", { controls: true, preload: "metadata", playsInline: true, src: src, poster: poster || undefined, controlsList: controlsList || undefined, disablePictureInPicture: !showSettings || undefined, style: videoStyle }));
65
+ }
66
+ return (_jsxs("div", { ref: containerRef, style: { position: 'relative', width: '100%', borderRadius: '4px', overflow: 'hidden', backgroundColor: '#000' }, children: [_jsx("video", { ref: videoRef, src: src, poster: poster || undefined, preload: "metadata", playsInline: true, onClick: togglePlay, onPlay: () => setPlaying(true), onPause: () => setPlaying(false), onTimeUpdate: () => { var _a, _b; return setCurrentTime((_b = (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.currentTime) !== null && _b !== void 0 ? _b : 0); }, onLoadedMetadata: () => { var _a, _b; return setDuration((_b = (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.duration) !== null && _b !== void 0 ? _b : 0); }, style: { width: '100%', height: 'auto', display: 'block', cursor: 'pointer' } }), _jsx("button", { type: "button", "aria-label": playing ? 'Pausar' : 'Reproduzir', onClick: togglePlay, style: {
67
+ position: 'absolute',
68
+ top: '50%',
69
+ left: '50%',
70
+ transform: 'translate(-50%, -50%)',
71
+ width: 64,
72
+ height: 64,
73
+ borderRadius: '50%',
74
+ border: 'none',
75
+ cursor: 'pointer',
76
+ backgroundColor: 'rgba(0,0,0,0.55)',
77
+ color: '#fff',
78
+ display: 'flex',
79
+ alignItems: 'center',
80
+ justifyContent: 'center',
81
+ opacity: playing ? 0 : 1,
82
+ pointerEvents: playing ? 'none' : 'auto',
83
+ transition: 'opacity 0.15s ease'
84
+ }, children: playing ? pauseIcon : playIcon }), (showProgressBar || showFullscreen) && (_jsxs("div", { style: {
85
+ position: 'absolute',
86
+ left: 0,
87
+ right: 0,
88
+ bottom: 0,
89
+ display: 'flex',
90
+ alignItems: 'center',
91
+ gap: 10,
92
+ padding: '10px 12px',
93
+ background: 'linear-gradient(transparent, rgba(0,0,0,0.65))'
94
+ }, children: [showProgressBar && (_jsx("input", { type: "range", min: 0, max: duration || 0, step: 0.1, value: currentTime, onChange: (event) => seek(Number(event.target.value)), style: { flex: 1, accentColor: '#fff' } })), showProgressBar && (_jsxs("span", { style: { color: '#fff', fontSize: 12, fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' }, children: [formatTime(currentTime), " / ", formatTime(duration)] })), showFullscreen && (_jsx("button", { type: "button", "aria-label": "Tela cheia", onClick: toggleFullscreen, style: { background: 'none', border: 'none', color: '#fff', cursor: 'pointer', padding: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: fullscreenIcon }))] }))] }));
95
+ }
16
96
  export function VideoComponent({ component }) {
17
- const { src = '', height = '400px', placeholderBackgroundColor = '#e0e0e0', placeholderTextColor = '#666' } = component.properties;
18
- const fullBleed = getBoolean(component.properties, 'fullBleed', false);
97
+ const properties = component.properties;
98
+ const src = getString(properties, 'src', '');
99
+ const poster = getString(properties, 'poster', '');
100
+ const fullBleed = getBoolean(properties, 'fullBleed', false);
101
+ const showFullscreen = getBoolean(properties, 'showFullscreen', true);
102
+ const showSettings = getBoolean(properties, 'showSettings', true);
103
+ const centerPlayButton = getBoolean(properties, 'centerPlayButton', false);
104
+ const showProgressBar = getBoolean(properties, 'showProgressBar', true);
105
+ const placeholderBackgroundColor = getString(properties, 'placeholderBackgroundColor', '#e0e0e0');
106
+ const placeholderTextColor = getString(properties, 'placeholderTextColor', '#666');
19
107
  const video = useMemo(() => toEmbed(src), [src]);
20
- const content = (video === null || video === void 0 ? void 0 : video.kind) === 'iframe' ? (_jsx("iframe", { title: "V\u00EDdeo", src: video.src, width: "100%", height: height, style: { border: 0, borderRadius: '4px' }, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true, loading: "lazy" })) : (video === null || video === void 0 ? void 0 : video.kind) === 'native' ? (_jsx("video", { controls: true, src: video.src, style: { width: '100%', height, borderRadius: '4px', display: 'block' } })) : (_jsx("div", { style: {
108
+ const content = (video === null || video === void 0 ? void 0 : video.kind) === 'iframe' ? (_jsx("div", { style: { width: '100%', aspectRatio: '16 / 9', borderRadius: '4px', overflow: 'hidden' }, children: _jsx("iframe", { title: "V\u00EDdeo", src: video.src, style: { width: '100%', height: '100%', border: 0, display: 'block' }, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true, loading: "lazy" }) })) : (video === null || video === void 0 ? void 0 : video.kind) === 'native' ? (_jsx(NativeVideo, { src: video.src, poster: poster, showFullscreen: showFullscreen, showSettings: showSettings, centerPlayButton: centerPlayButton, showProgressBar: showProgressBar })) : (_jsx("div", { style: {
21
109
  width: '100%',
22
- height,
110
+ aspectRatio: '16 / 9',
23
111
  backgroundColor: placeholderBackgroundColor,
24
112
  display: 'flex',
25
113
  alignItems: 'center',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lib-pixelbuild",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
4
4
  "engines": {
5
5
  "node": "^24.0.0",
6
6
  "npm": ">=10"