@innovui/react-native 0.2.0 → 0.3.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 +1 -0
- package/dist/components/_shared/media-icons.js +125 -0
- package/dist/components/_shared/media-icons.js.map +1 -0
- package/dist/components/_shared/media.js +114 -0
- package/dist/components/_shared/media.js.map +1 -0
- package/dist/components/audio-player/audio-player.d.ts +34 -0
- package/dist/components/audio-player/audio-player.js +89 -0
- package/dist/components/audio-player/audio-player.js.map +1 -0
- package/dist/components/audio-player/index.d.ts +2 -0
- package/dist/components/carousel/carousel.d.ts +34 -0
- package/dist/components/carousel/carousel.js +110 -0
- package/dist/components/carousel/carousel.js.map +1 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/gallery/gallery.d.ts +21 -0
- package/dist/components/gallery/gallery.js +54 -0
- package/dist/components/gallery/gallery.js.map +1 -0
- package/dist/components/gallery/index.d.ts +2 -0
- package/dist/components/lightbox/lightbox.d.ts +30 -0
- package/dist/components/lightbox/lightbox.js +147 -0
- package/dist/components/lightbox/lightbox.js.map +1 -0
- package/dist/components/video-player/index.d.ts +2 -0
- package/dist/components/video-player/video-player.d.ts +37 -0
- package/dist/components/video-player/video-player.js +178 -0
- package/dist/components/video-player/video-player.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +6 -1
- package/dist/tokens/generated.d.ts +8 -0
- package/dist/tokens/generated.js +10 -2
- package/dist/tokens/generated.js.map +1 -1
- package/package.json +1 -1
- package/theme.css +8 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { cn } from "../../utils/cn.js";
|
|
2
|
+
import { useToken } from "../_shared/use-token.js";
|
|
3
|
+
import { ExpandIcon } from "../_shared/media-icons.js";
|
|
4
|
+
import { Lightbox } from "../lightbox/lightbox.js";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Image, Pressable, View, useWindowDimensions } from "react-native";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/gallery/gallery.tsx
|
|
9
|
+
const GAP = 8;
|
|
10
|
+
const TABLET = 768;
|
|
11
|
+
/** Grade de miniaturas que abre a foto ampliada no `Lightbox`. */
|
|
12
|
+
function Gallery({ className, items, columns, openLabel = (item, i) => `Ampliar foto ${i + 1}: ${item.alt}`, lightboxLabel, ...props }) {
|
|
13
|
+
const { width: screen } = useWindowDimensions();
|
|
14
|
+
const [width, setWidth] = useState(0);
|
|
15
|
+
const [opened, setOpened] = useState(null);
|
|
16
|
+
const overlayColor = useToken("--color-media-on-surface");
|
|
17
|
+
const cols = columns ?? (screen >= TABLET ? 3 : 2);
|
|
18
|
+
const size = (width - GAP * (cols - 1)) / cols;
|
|
19
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(View, {
|
|
20
|
+
className: cn("flex-row flex-wrap gap-2", className),
|
|
21
|
+
onLayout: (event) => setWidth(event.nativeEvent.layout.width),
|
|
22
|
+
...props,
|
|
23
|
+
children: items.map((item, i) => /* @__PURE__ */ jsx(Pressable, {
|
|
24
|
+
accessibilityRole: "imagebutton",
|
|
25
|
+
accessibilityLabel: openLabel(item, i),
|
|
26
|
+
onPress: () => setOpened(i),
|
|
27
|
+
className: "overflow-hidden rounded-md bg-bg-skeleton",
|
|
28
|
+
style: {
|
|
29
|
+
width: size,
|
|
30
|
+
aspectRatio: 4 / 3
|
|
31
|
+
},
|
|
32
|
+
children: ({ pressed }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Image, {
|
|
33
|
+
source: { uri: item.thumbSrc ?? item.src },
|
|
34
|
+
className: "size-full",
|
|
35
|
+
resizeMode: "cover"
|
|
36
|
+
}), pressed && /* @__PURE__ */ jsx(View, {
|
|
37
|
+
pointerEvents: "none",
|
|
38
|
+
className: "absolute inset-0 items-center justify-center bg-media-surface/50",
|
|
39
|
+
children: /* @__PURE__ */ jsx(ExpandIcon, { color: overlayColor })
|
|
40
|
+
})] })
|
|
41
|
+
}, item.src))
|
|
42
|
+
}), /* @__PURE__ */ jsx(Lightbox, {
|
|
43
|
+
items,
|
|
44
|
+
label: lightboxLabel,
|
|
45
|
+
open: opened !== null,
|
|
46
|
+
onOpenChange: (open) => !open && setOpened(null),
|
|
47
|
+
index: opened ?? 0,
|
|
48
|
+
onIndexChange: setOpened
|
|
49
|
+
})] });
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Gallery };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=gallery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.js","names":[],"sources":["../../../src/components/gallery/gallery.tsx"],"sourcesContent":["/// <reference types=\"uniwind/types\" />\n\nimport { useState } from 'react'\nimport {\n Image,\n type LayoutChangeEvent,\n Pressable,\n useWindowDimensions,\n View,\n type ViewProps,\n} from 'react-native'\nimport { cn } from '../../utils/cn'\nimport { ExpandIcon } from '../_shared/media-icons'\nimport { useToken } from '../_shared/use-token'\nimport { Lightbox, type LightboxItem } from '../lightbox'\n\nconst GAP = 8\nconst TABLET = 768\n\nexport type GalleryItem = LightboxItem & {\n /** Imagem menor para a grade; sem ela, a grade usa `src`. */\n thumbSrc?: string\n}\n\nexport type GalleryProps = Omit<ViewProps, 'children' | 'style'> & {\n className?: string\n items: GalleryItem[]\n /** Colunas da grade. Padrão: 2 no celular e 3 a partir de 768px de tela. */\n columns?: number\n /** Nome acessível do botão de cada miniatura. Padrão: \"Ampliar foto N: descrição\". */\n openLabel?: (item: GalleryItem, index: number) => string\n /** Nome acessível do visualizador ampliado. */\n lightboxLabel?: string\n}\n\n/** Grade de miniaturas que abre a foto ampliada no `Lightbox`. */\nexport function Gallery({\n className,\n items,\n columns,\n openLabel = (item, i) => `Ampliar foto ${i + 1}: ${item.alt}`,\n lightboxLabel,\n ...props\n}: GalleryProps) {\n const { width: screen } = useWindowDimensions()\n const [width, setWidth] = useState(0)\n const [opened, setOpened] = useState<number | null>(null)\n const overlayColor = useToken('--color-media-on-surface')\n const cols = columns ?? (screen >= TABLET ? 3 : 2)\n const size = (width - GAP * (cols - 1)) / cols\n\n return (\n <>\n <View\n className={cn('flex-row flex-wrap gap-2', className)}\n onLayout={(event: LayoutChangeEvent) => setWidth(event.nativeEvent.layout.width)}\n {...props}\n >\n {items.map((item, i) => (\n <Pressable\n key={item.src}\n accessibilityRole=\"imagebutton\"\n accessibilityLabel={openLabel(item, i)}\n onPress={() => setOpened(i)}\n className=\"overflow-hidden rounded-md bg-bg-skeleton\"\n style={{ width: size, aspectRatio: 4 / 3 }}\n >\n {({ pressed }) => (\n <>\n <Image\n source={{ uri: item.thumbSrc ?? item.src }}\n className=\"size-full\"\n resizeMode=\"cover\"\n />\n {pressed && (\n <View\n pointerEvents=\"none\"\n className=\"absolute inset-0 items-center justify-center bg-media-surface/50\"\n >\n <ExpandIcon color={overlayColor} />\n </View>\n )}\n </>\n )}\n </Pressable>\n ))}\n </View>\n <Lightbox\n items={items}\n label={lightboxLabel}\n open={opened !== null}\n onOpenChange={(open) => !open && setOpened(null)}\n index={opened ?? 0}\n onIndexChange={setOpened}\n />\n </>\n )\n}\n"],"mappings":";;;;;;;;AAgBA,MAAM,MAAM;AACZ,MAAM,SAAS;;AAmBf,SAAgB,QAAQ,EACtB,WACA,OACA,SACA,aAAa,MAAM,MAAM,gBAAgB,IAAI,EAAE,IAAI,KAAK,OACxD,eACA,GAAG,SACY;CACf,MAAM,EAAE,OAAO,WAAW,oBAAoB;CAC9C,MAAM,CAAC,OAAO,YAAY,SAAS,CAAC;CACpC,MAAM,CAAC,QAAQ,aAAa,SAAwB,IAAI;CACxD,MAAM,eAAe,SAAS,0BAA0B;CACxD,MAAM,OAAO,YAAY,UAAU,SAAS,IAAI;CAChD,MAAM,QAAQ,QAAQ,OAAO,OAAO,MAAM;CAE1C,OACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EACE,WAAW,GAAG,4BAA4B,SAAS;EACnD,WAAW,UAA6B,SAAS,MAAM,YAAY,OAAO,KAAK;EAC/E,GAAI;EAEH,UAAA,MAAM,KAAK,MAAM,MAChB,oBAAC,WAAD;GAEE,mBAAkB;GAClB,oBAAoB,UAAU,MAAM,CAAC;GACrC,eAAe,UAAU,CAAC;GAC1B,WAAU;GACV,OAAO;IAAE,OAAO;IAAM,aAAa,IAAI;GAAE;GAEvC,WAAA,EAAE,cACF,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,OAAD;IACE,QAAQ,EAAE,KAAK,KAAK,YAAY,KAAK,IAAI;IACzC,WAAU;IACV,YAAW;GACZ,CAAA,GACA,WACC,oBAAC,MAAD;IACE,eAAc;IACd,WAAU;IAEV,UAAA,oBAAC,YAAD,EAAY,OAAO,aAAe,CAAA;GAC9B,CAAA,CAER,EAAA,CAAA;EAEK,GAxBJ,KAAK,GAwBD,CACZ;CACG,CAAA,GACN,oBAAC,UAAD;EACS;EACP,OAAO;EACP,MAAM,WAAW;EACjB,eAAe,SAAS,CAAC,QAAQ,UAAU,IAAI;EAC/C,OAAO,UAAU;EACjB,eAAe;CAChB,CAAA,CACD,EAAA,CAAA;AAEN"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/components/lightbox/lightbox.d.ts
|
|
2
|
+
export type LightboxItem = {
|
|
3
|
+
/** Endereço da imagem ampliada. */
|
|
4
|
+
src: string;
|
|
5
|
+
/** Descrição da imagem para leitores de tela. */
|
|
6
|
+
alt: string;
|
|
7
|
+
};
|
|
8
|
+
export type LightboxProps = {
|
|
9
|
+
items: LightboxItem[];
|
|
10
|
+
open?: boolean;
|
|
11
|
+
defaultOpen?: boolean;
|
|
12
|
+
onOpenChange?: (open: boolean) => void;
|
|
13
|
+
/** Índice da imagem exibida (modo controlado). */
|
|
14
|
+
index?: number;
|
|
15
|
+
defaultIndex?: number;
|
|
16
|
+
onIndexChange?: (index: number) => void;
|
|
17
|
+
/** Nome acessível do visualizador. */
|
|
18
|
+
label?: string;
|
|
19
|
+
closeLabel?: string;
|
|
20
|
+
previousLabel?: string;
|
|
21
|
+
nextLabel?: string;
|
|
22
|
+
testID?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Imagem ampliada sobre um fundo escurecido, com contador (`1 / 6`), setas e fechar. Deslize para
|
|
26
|
+
* os lados para trocar de foto; as setas dão a volta (da última vai para a primeira).
|
|
27
|
+
*/
|
|
28
|
+
export declare function Lightbox({ items, open, defaultOpen, onOpenChange, index, defaultIndex, onIndexChange, label, closeLabel, previousLabel, nextLabel, testID }: LightboxProps): import("react").JSX.Element;
|
|
29
|
+
//#endregion
|
|
30
|
+
//# sourceMappingURL=lightbox.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { CloseIcon } from "../_shared/status.js";
|
|
2
|
+
import { useToken } from "../_shared/use-token.js";
|
|
3
|
+
import { IconButton } from "../icon-button/icon-button.js";
|
|
4
|
+
import { NextIcon, PreviousIcon } from "../_shared/media-icons.js";
|
|
5
|
+
import { useTransition } from "../_shared/use-transition.js";
|
|
6
|
+
import { Backdrop } from "../_shared/backdrop.js";
|
|
7
|
+
import { useOpenState } from "../_shared/overlay-state.js";
|
|
8
|
+
import { useEffect, useRef, useState } from "react";
|
|
9
|
+
import { Animated, FlatList, Image, Modal, StyleSheet, Text, View, useWindowDimensions } from "react-native";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
//#region src/components/lightbox/lightbox.tsx
|
|
12
|
+
const roundButton = "rounded-full border-border-default bg-surface-elevated active:bg-bg-secondary";
|
|
13
|
+
/**
|
|
14
|
+
* Imagem ampliada sobre um fundo escurecido, com contador (`1 / 6`), setas e fechar. Deslize para
|
|
15
|
+
* os lados para trocar de foto; as setas dão a volta (da última vai para a primeira).
|
|
16
|
+
*/
|
|
17
|
+
function Lightbox({ items, open, defaultOpen, onOpenChange, index, defaultIndex = 0, onIndexChange, label = "Visualizador de imagens", closeLabel = "Fechar", previousLabel = "Foto anterior", nextLabel = "Próxima foto", testID }) {
|
|
18
|
+
const [isOpen, setOpen] = useOpenState({
|
|
19
|
+
open,
|
|
20
|
+
defaultOpen,
|
|
21
|
+
onOpenChange
|
|
22
|
+
});
|
|
23
|
+
const { mounted, progress } = useTransition(isOpen);
|
|
24
|
+
const { width, height } = useWindowDimensions();
|
|
25
|
+
const iconColor = useToken("--color-text-primary");
|
|
26
|
+
const list = useRef(null);
|
|
27
|
+
const [inner, setInner] = useState(defaultIndex);
|
|
28
|
+
const count = items.length;
|
|
29
|
+
const current = Math.min(Math.max(index ?? inner, 0), Math.max(count - 1, 0));
|
|
30
|
+
const shown = useRef(current);
|
|
31
|
+
function show(next) {
|
|
32
|
+
shown.current = next;
|
|
33
|
+
if (index === void 0) setInner(next);
|
|
34
|
+
onIndexChange?.(next);
|
|
35
|
+
}
|
|
36
|
+
function go(next) {
|
|
37
|
+
const wrapped = (next + count) % count;
|
|
38
|
+
list.current?.scrollToIndex({
|
|
39
|
+
index: wrapped,
|
|
40
|
+
animated: true
|
|
41
|
+
});
|
|
42
|
+
show(wrapped);
|
|
43
|
+
}
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!mounted || shown.current === current) return;
|
|
46
|
+
shown.current = current;
|
|
47
|
+
list.current?.scrollToIndex({
|
|
48
|
+
index: current,
|
|
49
|
+
animated: false
|
|
50
|
+
});
|
|
51
|
+
}, [current, mounted]);
|
|
52
|
+
function onMomentumScrollEnd(event) {
|
|
53
|
+
const next = Math.round(event.nativeEvent.contentOffset.x / width);
|
|
54
|
+
if (next !== shown.current && next >= 0 && next < count) show(next);
|
|
55
|
+
}
|
|
56
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
57
|
+
transparent: true,
|
|
58
|
+
statusBarTranslucent: true,
|
|
59
|
+
animationType: "none",
|
|
60
|
+
visible: mounted,
|
|
61
|
+
onRequestClose: () => setOpen(false),
|
|
62
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
63
|
+
className: "flex-1",
|
|
64
|
+
accessibilityViewIsModal: true,
|
|
65
|
+
accessibilityLabel: label,
|
|
66
|
+
testID,
|
|
67
|
+
children: [/* @__PURE__ */ jsx(Animated.View, {
|
|
68
|
+
pointerEvents: "box-none",
|
|
69
|
+
style: [StyleSheet.absoluteFill, { opacity: progress }],
|
|
70
|
+
children: /* @__PURE__ */ jsx(Backdrop, { onPress: () => setOpen(false) })
|
|
71
|
+
}), /* @__PURE__ */ jsxs(Animated.View, {
|
|
72
|
+
pointerEvents: "box-none",
|
|
73
|
+
style: [StyleSheet.absoluteFill, {
|
|
74
|
+
opacity: progress,
|
|
75
|
+
justifyContent: "center"
|
|
76
|
+
}],
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ jsx(FlatList, {
|
|
79
|
+
ref: list,
|
|
80
|
+
data: items,
|
|
81
|
+
horizontal: true,
|
|
82
|
+
pagingEnabled: true,
|
|
83
|
+
showsHorizontalScrollIndicator: false,
|
|
84
|
+
keyExtractor: (item) => item.src,
|
|
85
|
+
initialScrollIndex: current,
|
|
86
|
+
getItemLayout: (_, i) => ({
|
|
87
|
+
length: width,
|
|
88
|
+
offset: width * i,
|
|
89
|
+
index: i
|
|
90
|
+
}),
|
|
91
|
+
onMomentumScrollEnd,
|
|
92
|
+
renderItem: ({ item }) => /* @__PURE__ */ jsx(View, {
|
|
93
|
+
style: {
|
|
94
|
+
width,
|
|
95
|
+
height: height * .7,
|
|
96
|
+
paddingHorizontal: 16
|
|
97
|
+
},
|
|
98
|
+
children: /* @__PURE__ */ jsx(Image, {
|
|
99
|
+
source: { uri: item.src },
|
|
100
|
+
accessibilityLabel: item.alt,
|
|
101
|
+
resizeMode: "contain",
|
|
102
|
+
className: "size-full"
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}),
|
|
106
|
+
count > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(View, {
|
|
107
|
+
pointerEvents: "box-none",
|
|
108
|
+
className: "absolute inset-x-3 flex-row justify-between",
|
|
109
|
+
style: { top: height / 2 - 22 },
|
|
110
|
+
children: [/* @__PURE__ */ jsx(IconButton, {
|
|
111
|
+
accessibilityLabel: previousLabel,
|
|
112
|
+
variant: "tertiary",
|
|
113
|
+
className: roundButton,
|
|
114
|
+
onPress: () => go(shown.current - 1),
|
|
115
|
+
children: /* @__PURE__ */ jsx(PreviousIcon, { color: iconColor })
|
|
116
|
+
}), /* @__PURE__ */ jsx(IconButton, {
|
|
117
|
+
accessibilityLabel: nextLabel,
|
|
118
|
+
variant: "tertiary",
|
|
119
|
+
className: roundButton,
|
|
120
|
+
onPress: () => go(shown.current + 1),
|
|
121
|
+
children: /* @__PURE__ */ jsx(NextIcon, { color: iconColor })
|
|
122
|
+
})]
|
|
123
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
124
|
+
accessibilityLiveRegion: "polite",
|
|
125
|
+
className: "absolute bottom-12 self-center text-sm font-medium leading-5 text-media-on-surface",
|
|
126
|
+
children: [
|
|
127
|
+
current + 1,
|
|
128
|
+
" / ",
|
|
129
|
+
count
|
|
130
|
+
]
|
|
131
|
+
})] }),
|
|
132
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
133
|
+
accessibilityLabel: closeLabel,
|
|
134
|
+
variant: "tertiary",
|
|
135
|
+
className: `absolute right-4 top-12 ${roundButton}`,
|
|
136
|
+
onPress: () => setOpen(false),
|
|
137
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { color: iconColor })
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
})]
|
|
141
|
+
})
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
export { Lightbox };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=lightbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lightbox.js","names":["RNModal"],"sources":["../../../src/components/lightbox/lightbox.tsx"],"sourcesContent":["/// <reference types=\"uniwind/types\" />\n\nimport { useEffect, useRef, useState } from 'react'\nimport {\n Animated,\n FlatList,\n Image,\n type NativeScrollEvent,\n type NativeSyntheticEvent,\n Modal as RNModal,\n StyleSheet,\n Text,\n useWindowDimensions,\n View,\n} from 'react-native'\nimport { Backdrop } from '../_shared/backdrop'\nimport { NextIcon, PreviousIcon } from '../_shared/media-icons'\nimport { useOpenState } from '../_shared/overlay-state'\nimport { CloseIcon } from '../_shared/status'\nimport { useToken } from '../_shared/use-token'\nimport { useTransition } from '../_shared/use-transition'\nimport { IconButton } from '../icon-button'\n\nexport type LightboxItem = {\n /** Endereço da imagem ampliada. */\n src: string\n /** Descrição da imagem para leitores de tela. */\n alt: string\n}\n\nexport type LightboxProps = {\n items: LightboxItem[]\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Índice da imagem exibida (modo controlado). */\n index?: number\n defaultIndex?: number\n onIndexChange?: (index: number) => void\n /** Nome acessível do visualizador. */\n label?: string\n closeLabel?: string\n previousLabel?: string\n nextLabel?: string\n testID?: string\n}\n\nconst roundButton = 'rounded-full border-border-default bg-surface-elevated active:bg-bg-secondary'\n\n/**\n * Imagem ampliada sobre um fundo escurecido, com contador (`1 / 6`), setas e fechar. Deslize para\n * os lados para trocar de foto; as setas dão a volta (da última vai para a primeira).\n */\nexport function Lightbox({\n items,\n open,\n defaultOpen,\n onOpenChange,\n index,\n defaultIndex = 0,\n onIndexChange,\n label = 'Visualizador de imagens',\n closeLabel = 'Fechar',\n previousLabel = 'Foto anterior',\n nextLabel = 'Próxima foto',\n testID,\n}: LightboxProps) {\n const [isOpen, setOpen] = useOpenState({ open, defaultOpen, onOpenChange })\n const { mounted, progress } = useTransition(isOpen)\n const { width, height } = useWindowDimensions()\n const iconColor = useToken('--color-text-primary')\n const list = useRef<FlatList<LightboxItem>>(null)\n const [inner, setInner] = useState(defaultIndex)\n const count = items.length\n const current = Math.min(Math.max(index ?? inner, 0), Math.max(count - 1, 0))\n // índice em que a lista está de fato, para só rolar quando o pai troca `index` por fora\n const shown = useRef(current)\n\n function show(next: number) {\n shown.current = next\n if (index === undefined) setInner(next)\n onIndexChange?.(next)\n }\n\n function go(next: number) {\n const wrapped = (next + count) % count\n list.current?.scrollToIndex({ index: wrapped, animated: true })\n show(wrapped)\n }\n\n useEffect(() => {\n if (!mounted || shown.current === current) return\n shown.current = current\n list.current?.scrollToIndex({ index: current, animated: false })\n }, [current, mounted])\n\n function onMomentumScrollEnd(event: NativeSyntheticEvent<NativeScrollEvent>) {\n const next = Math.round(event.nativeEvent.contentOffset.x / width)\n if (next !== shown.current && next >= 0 && next < count) show(next)\n }\n\n return (\n <RNModal\n transparent\n statusBarTranslucent\n animationType=\"none\"\n visible={mounted}\n onRequestClose={() => setOpen(false)}\n >\n <View className=\"flex-1\" accessibilityViewIsModal accessibilityLabel={label} testID={testID}>\n <Animated.View\n pointerEvents=\"box-none\"\n style={[StyleSheet.absoluteFill, { opacity: progress }]}\n >\n <Backdrop onPress={() => setOpen(false)} />\n </Animated.View>\n <Animated.View\n pointerEvents=\"box-none\"\n style={[StyleSheet.absoluteFill, { opacity: progress, justifyContent: 'center' }]}\n >\n <FlatList\n ref={list}\n data={items}\n horizontal\n pagingEnabled\n showsHorizontalScrollIndicator={false}\n keyExtractor={(item) => item.src}\n initialScrollIndex={current}\n getItemLayout={(_, i) => ({ length: width, offset: width * i, index: i })}\n onMomentumScrollEnd={onMomentumScrollEnd}\n renderItem={({ item }) => (\n <View style={{ width, height: height * 0.7, paddingHorizontal: 16 }}>\n <Image\n source={{ uri: item.src }}\n accessibilityLabel={item.alt}\n resizeMode=\"contain\"\n className=\"size-full\"\n />\n </View>\n )}\n />\n {count > 1 && (\n <>\n <View\n pointerEvents=\"box-none\"\n className=\"absolute inset-x-3 flex-row justify-between\"\n style={{ top: height / 2 - 22 }}\n >\n <IconButton\n accessibilityLabel={previousLabel}\n variant=\"tertiary\"\n className={roundButton}\n onPress={() => go(shown.current - 1)}\n >\n <PreviousIcon color={iconColor} />\n </IconButton>\n <IconButton\n accessibilityLabel={nextLabel}\n variant=\"tertiary\"\n className={roundButton}\n onPress={() => go(shown.current + 1)}\n >\n <NextIcon color={iconColor} />\n </IconButton>\n </View>\n <Text\n accessibilityLiveRegion=\"polite\"\n className=\"absolute bottom-12 self-center text-sm font-medium leading-5 text-media-on-surface\"\n >\n {current + 1} / {count}\n </Text>\n </>\n )}\n <IconButton\n accessibilityLabel={closeLabel}\n variant=\"tertiary\"\n className={`absolute right-4 top-12 ${roundButton}`}\n onPress={() => setOpen(false)}\n >\n <CloseIcon color={iconColor} />\n </IconButton>\n </Animated.View>\n </View>\n </RNModal>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ViewProps } from "react-native";
|
|
3
|
+
//#region src/components/video-player/video-player.d.ts
|
|
4
|
+
export type VideoPlayerProps = Omit<ViewProps, 'style'> & {
|
|
5
|
+
className?: string;
|
|
6
|
+
/** A superfície de vídeo (ex.: o `VideoView` do `expo-video`), que preenche o player. */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** Nome acessível do player. */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Tocando agora: mostra o botão de pausar e esconde o play central. */
|
|
11
|
+
playing?: boolean;
|
|
12
|
+
/** Posição atual, em segundos. */
|
|
13
|
+
position?: number;
|
|
14
|
+
/** Duração total, em segundos. */
|
|
15
|
+
duration?: number;
|
|
16
|
+
/** Sem som: mostra o ícone de volume cortado. */
|
|
17
|
+
muted?: boolean;
|
|
18
|
+
/** Em tela cheia: mostra o ícone de sair. Só vale com `onToggleFullscreen`. */
|
|
19
|
+
fullscreen?: boolean;
|
|
20
|
+
onPlayPause?: () => void;
|
|
21
|
+
/** Chamado com a posição (em segundos) tocada ou arrastada na barra. */
|
|
22
|
+
onSeek?: (seconds: number) => void;
|
|
23
|
+
onToggleMute?: () => void;
|
|
24
|
+
/** Sem ele, o botão de tela cheia não aparece. */
|
|
25
|
+
onToggleFullscreen?: () => void;
|
|
26
|
+
/** Tempo sem interação, em ms, até esconder os controles durante a reprodução. Padrão: 2500. */
|
|
27
|
+
hideControlsAfter?: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Casca de player de vídeo: play central, posição, tempo, mudo e tela cheia sobre o seu vídeo.
|
|
31
|
+
* Não toca nada: quem usa guarda o estado (por exemplo com `expo-video`) e o passa por props,
|
|
32
|
+
* ligando os `on…` ao player de verdade. Tocar no vídeo alterna play/pause e mostra os controles,
|
|
33
|
+
* que somem depois de um tempo sem toques enquanto toca (com leitor de tela ligado, ficam).
|
|
34
|
+
*/
|
|
35
|
+
export declare function VideoPlayer({ className, children, label, playing, position, duration, muted, fullscreen, onPlayPause, onSeek, onToggleMute, onToggleFullscreen, hideControlsAfter, ...props }: VideoPlayerProps): import("react").JSX.Element;
|
|
36
|
+
//#endregion
|
|
37
|
+
//# sourceMappingURL=video-player.d.ts.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { cn } from "../../utils/cn.js";
|
|
2
|
+
import { useToken } from "../_shared/use-token.js";
|
|
3
|
+
import { formatTime, useSeek } from "../_shared/media.js";
|
|
4
|
+
import { MaximizeIcon, MinimizeIcon, PauseIcon, PlayIcon, VolumeIcon, VolumeMutedIcon } from "../_shared/media-icons.js";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { AccessibilityInfo, Pressable, StyleSheet, Text, View } from "react-native";
|
|
7
|
+
import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/components/video-player/video-player.tsx
|
|
10
|
+
const button = "size-9 shrink-0 items-center justify-center rounded-full active:bg-media-on-surface/15";
|
|
11
|
+
/**
|
|
12
|
+
* Casca de player de vídeo: play central, posição, tempo, mudo e tela cheia sobre o seu vídeo.
|
|
13
|
+
* Não toca nada: quem usa guarda o estado (por exemplo com `expo-video`) e o passa por props,
|
|
14
|
+
* ligando os `on…` ao player de verdade. Tocar no vídeo alterna play/pause e mostra os controles,
|
|
15
|
+
* que somem depois de um tempo sem toques enquanto toca (com leitor de tela ligado, ficam).
|
|
16
|
+
*/
|
|
17
|
+
function VideoPlayer({ className, children, label = "Vídeo", playing = false, position = 0, duration = 0, muted = false, fullscreen = false, onPlayPause, onSeek, onToggleMute, onToggleFullscreen, hideControlsAfter = 2500, ...props }) {
|
|
18
|
+
const [active, setActive] = useState(true);
|
|
19
|
+
const [screenReader, setScreenReader] = useState(false);
|
|
20
|
+
const timer = useRef(void 0);
|
|
21
|
+
const onSurface = useToken("--color-media-on-surface");
|
|
22
|
+
const accent = useToken("--color-interactive-primary");
|
|
23
|
+
const scrim = useToken("--color-media-surface") ?? "#000000";
|
|
24
|
+
const seek = useSeek({
|
|
25
|
+
position,
|
|
26
|
+
duration,
|
|
27
|
+
label: "Posição do vídeo",
|
|
28
|
+
onSeek
|
|
29
|
+
});
|
|
30
|
+
const visible = active || !playing || screenReader;
|
|
31
|
+
const progress = duration ? Math.min(position / duration, 1) * 100 : 0;
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
AccessibilityInfo.isScreenReaderEnabled().then(setScreenReader);
|
|
34
|
+
const subscription = AccessibilityInfo.addEventListener("screenReaderChanged", setScreenReader);
|
|
35
|
+
return () => subscription.remove();
|
|
36
|
+
}, []);
|
|
37
|
+
const show = useCallback(() => {
|
|
38
|
+
setActive(true);
|
|
39
|
+
clearTimeout(timer.current);
|
|
40
|
+
timer.current = setTimeout(() => setActive(false), hideControlsAfter);
|
|
41
|
+
}, [hideControlsAfter]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (playing) show();
|
|
44
|
+
else setActive(true);
|
|
45
|
+
return () => clearTimeout(timer.current);
|
|
46
|
+
}, [playing, show]);
|
|
47
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
48
|
+
accessibilityLabel: label,
|
|
49
|
+
className: cn("aspect-video w-full overflow-hidden rounded-lg bg-media-surface shadow-lg", className),
|
|
50
|
+
...props,
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsx(View, {
|
|
53
|
+
pointerEvents: "none",
|
|
54
|
+
className: "absolute inset-0",
|
|
55
|
+
children
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ jsx(Pressable, {
|
|
58
|
+
accessible: false,
|
|
59
|
+
onPress: () => {
|
|
60
|
+
onPlayPause?.();
|
|
61
|
+
show();
|
|
62
|
+
},
|
|
63
|
+
className: "absolute inset-0",
|
|
64
|
+
children: !playing && /* @__PURE__ */ jsx(View, {
|
|
65
|
+
pointerEvents: "none",
|
|
66
|
+
className: "absolute inset-0 bg-media-surface/30"
|
|
67
|
+
})
|
|
68
|
+
}),
|
|
69
|
+
!playing && /* @__PURE__ */ jsx(View, {
|
|
70
|
+
pointerEvents: "box-none",
|
|
71
|
+
className: "absolute inset-0 items-center justify-center",
|
|
72
|
+
children: /* @__PURE__ */ jsx(Pressable, {
|
|
73
|
+
accessible: false,
|
|
74
|
+
importantForAccessibility: "no",
|
|
75
|
+
onPress: onPlayPause,
|
|
76
|
+
className: "size-16 items-center justify-center rounded-full bg-media-on-surface shadow-lg",
|
|
77
|
+
children: /* @__PURE__ */ jsx(PlayIcon, {
|
|
78
|
+
filled: true,
|
|
79
|
+
size: 28,
|
|
80
|
+
color: accent
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
}),
|
|
84
|
+
/* @__PURE__ */ jsxs(View, {
|
|
85
|
+
pointerEvents: visible ? "box-none" : "none",
|
|
86
|
+
importantForAccessibility: visible ? "auto" : "no-hide-descendants",
|
|
87
|
+
accessibilityElementsHidden: !visible,
|
|
88
|
+
className: cn("absolute inset-x-0 bottom-0 px-4 pb-3 pt-[30px]", !visible && "opacity-0"),
|
|
89
|
+
children: [
|
|
90
|
+
/* @__PURE__ */ jsxs(Svg, {
|
|
91
|
+
pointerEvents: "none",
|
|
92
|
+
style: StyleSheet.absoluteFill,
|
|
93
|
+
preserveAspectRatio: "none",
|
|
94
|
+
children: [/* @__PURE__ */ jsx(Defs, { children: /* @__PURE__ */ jsxs(LinearGradient, {
|
|
95
|
+
id: "scrim",
|
|
96
|
+
x1: "0",
|
|
97
|
+
y1: "1",
|
|
98
|
+
x2: "0",
|
|
99
|
+
y2: "0",
|
|
100
|
+
children: [/* @__PURE__ */ jsx(Stop, {
|
|
101
|
+
offset: "0",
|
|
102
|
+
stopColor: scrim,
|
|
103
|
+
stopOpacity: .65
|
|
104
|
+
}), /* @__PURE__ */ jsx(Stop, {
|
|
105
|
+
offset: "1",
|
|
106
|
+
stopColor: scrim,
|
|
107
|
+
stopOpacity: 0
|
|
108
|
+
})]
|
|
109
|
+
}) }), /* @__PURE__ */ jsx(Rect, {
|
|
110
|
+
width: "100%",
|
|
111
|
+
height: "100%",
|
|
112
|
+
fill: "url(#scrim)"
|
|
113
|
+
})]
|
|
114
|
+
}),
|
|
115
|
+
/* @__PURE__ */ jsx(View, {
|
|
116
|
+
...seek.props,
|
|
117
|
+
className: "mb-1 h-4 w-full justify-center",
|
|
118
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
119
|
+
pointerEvents: "none",
|
|
120
|
+
className: "h-1 w-full rounded-full bg-media-on-surface/30",
|
|
121
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
122
|
+
className: "h-full rounded-full bg-media-accent",
|
|
123
|
+
style: { width: `${progress}%` }
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ jsxs(View, {
|
|
128
|
+
className: "h-9 flex-row items-center justify-between",
|
|
129
|
+
children: [/* @__PURE__ */ jsxs(View, {
|
|
130
|
+
className: "flex-row items-center gap-2",
|
|
131
|
+
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
132
|
+
accessibilityRole: "button",
|
|
133
|
+
accessibilityLabel: playing ? "Pausar" : "Reproduzir",
|
|
134
|
+
onPress: () => {
|
|
135
|
+
onPlayPause?.();
|
|
136
|
+
show();
|
|
137
|
+
},
|
|
138
|
+
className: button,
|
|
139
|
+
children: playing ? /* @__PURE__ */ jsx(PauseIcon, { color: onSurface }) : /* @__PURE__ */ jsx(PlayIcon, { color: onSurface })
|
|
140
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
141
|
+
accessible: false,
|
|
142
|
+
className: "text-xs font-medium leading-4 text-media-on-surface",
|
|
143
|
+
style: { fontVariant: ["tabular-nums"] },
|
|
144
|
+
children: [
|
|
145
|
+
formatTime(position),
|
|
146
|
+
" / ",
|
|
147
|
+
formatTime(duration)
|
|
148
|
+
]
|
|
149
|
+
})]
|
|
150
|
+
}), /* @__PURE__ */ jsxs(View, {
|
|
151
|
+
className: "flex-row items-center gap-2",
|
|
152
|
+
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
153
|
+
accessibilityRole: "button",
|
|
154
|
+
accessibilityLabel: muted ? "Ativar o som" : "Silenciar",
|
|
155
|
+
onPress: () => {
|
|
156
|
+
onToggleMute?.();
|
|
157
|
+
show();
|
|
158
|
+
},
|
|
159
|
+
className: button,
|
|
160
|
+
children: muted ? /* @__PURE__ */ jsx(VolumeMutedIcon, { color: onSurface }) : /* @__PURE__ */ jsx(VolumeIcon, { color: onSurface })
|
|
161
|
+
}), onToggleFullscreen && /* @__PURE__ */ jsx(Pressable, {
|
|
162
|
+
accessibilityRole: "button",
|
|
163
|
+
accessibilityLabel: fullscreen ? "Sair da tela cheia" : "Tela cheia",
|
|
164
|
+
onPress: onToggleFullscreen,
|
|
165
|
+
className: button,
|
|
166
|
+
children: fullscreen ? /* @__PURE__ */ jsx(MinimizeIcon, { color: onSurface }) : /* @__PURE__ */ jsx(MaximizeIcon, { color: onSurface })
|
|
167
|
+
})]
|
|
168
|
+
})]
|
|
169
|
+
})
|
|
170
|
+
]
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
export { VideoPlayer };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=video-player.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-player.js","names":[],"sources":["../../../src/components/video-player/video-player.tsx"],"sourcesContent":["/// <reference types=\"uniwind/types\" />\n\nimport { type ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { AccessibilityInfo, Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native'\nimport Svg, { Defs, LinearGradient, Rect, Stop } from 'react-native-svg'\nimport { cn } from '../../utils/cn'\nimport { formatTime, useSeek } from '../_shared/media'\nimport {\n MaximizeIcon,\n MinimizeIcon,\n PauseIcon,\n PlayIcon,\n VolumeIcon,\n VolumeMutedIcon,\n} from '../_shared/media-icons'\nimport { useToken } from '../_shared/use-token'\n\nexport type VideoPlayerProps = Omit<ViewProps, 'style'> & {\n className?: string\n /** A superfície de vídeo (ex.: o `VideoView` do `expo-video`), que preenche o player. */\n children: ReactNode\n /** Nome acessível do player. */\n label?: string\n /** Tocando agora: mostra o botão de pausar e esconde o play central. */\n playing?: boolean\n /** Posição atual, em segundos. */\n position?: number\n /** Duração total, em segundos. */\n duration?: number\n /** Sem som: mostra o ícone de volume cortado. */\n muted?: boolean\n /** Em tela cheia: mostra o ícone de sair. Só vale com `onToggleFullscreen`. */\n fullscreen?: boolean\n onPlayPause?: () => void\n /** Chamado com a posição (em segundos) tocada ou arrastada na barra. */\n onSeek?: (seconds: number) => void\n onToggleMute?: () => void\n /** Sem ele, o botão de tela cheia não aparece. */\n onToggleFullscreen?: () => void\n /** Tempo sem interação, em ms, até esconder os controles durante a reprodução. Padrão: 2500. */\n hideControlsAfter?: number\n}\n\nconst button =\n 'size-9 shrink-0 items-center justify-center rounded-full active:bg-media-on-surface/15'\n\n/**\n * Casca de player de vídeo: play central, posição, tempo, mudo e tela cheia sobre o seu vídeo.\n * Não toca nada: quem usa guarda o estado (por exemplo com `expo-video`) e o passa por props,\n * ligando os `on…` ao player de verdade. Tocar no vídeo alterna play/pause e mostra os controles,\n * que somem depois de um tempo sem toques enquanto toca (com leitor de tela ligado, ficam).\n */\nexport function VideoPlayer({\n className,\n children,\n label = 'Vídeo',\n playing = false,\n position = 0,\n duration = 0,\n muted = false,\n fullscreen = false,\n onPlayPause,\n onSeek,\n onToggleMute,\n onToggleFullscreen,\n hideControlsAfter = 2500,\n ...props\n}: VideoPlayerProps) {\n const [active, setActive] = useState(true)\n const [screenReader, setScreenReader] = useState(false)\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const onSurface = useToken('--color-media-on-surface')\n const accent = useToken('--color-interactive-primary')\n const scrim = useToken('--color-media-surface') ?? '#000000'\n const seek = useSeek({ position, duration, label: 'Posição do vídeo', onSeek })\n const visible = active || !playing || screenReader\n const progress = duration ? Math.min(position / duration, 1) * 100 : 0\n\n useEffect(() => {\n AccessibilityInfo.isScreenReaderEnabled().then(setScreenReader)\n const subscription = AccessibilityInfo.addEventListener('screenReaderChanged', setScreenReader)\n return () => subscription.remove()\n }, [])\n\n const show = useCallback(() => {\n setActive(true)\n clearTimeout(timer.current)\n timer.current = setTimeout(() => setActive(false), hideControlsAfter)\n }, [hideControlsAfter])\n\n useEffect(() => {\n if (playing) show()\n else setActive(true)\n return () => clearTimeout(timer.current)\n }, [playing, show])\n\n return (\n <View\n accessibilityLabel={label}\n className={cn(\n 'aspect-video w-full overflow-hidden rounded-lg bg-media-surface shadow-lg',\n className,\n )}\n {...props}\n >\n <View pointerEvents=\"none\" className=\"absolute inset-0\">\n {children}\n </View>\n <Pressable\n accessible={false}\n onPress={() => {\n onPlayPause?.()\n show()\n }}\n className=\"absolute inset-0\"\n >\n {!playing && <View pointerEvents=\"none\" className=\"absolute inset-0 bg-media-surface/30\" />}\n </Pressable>\n {!playing && (\n <View pointerEvents=\"box-none\" className=\"absolute inset-0 items-center justify-center\">\n <Pressable\n accessible={false}\n importantForAccessibility=\"no\"\n onPress={onPlayPause}\n className=\"size-16 items-center justify-center rounded-full bg-media-on-surface shadow-lg\"\n >\n <PlayIcon filled size={28} color={accent} />\n </Pressable>\n </View>\n )}\n <View\n pointerEvents={visible ? 'box-none' : 'none'}\n importantForAccessibility={visible ? 'auto' : 'no-hide-descendants'}\n accessibilityElementsHidden={!visible}\n className={cn('absolute inset-x-0 bottom-0 px-4 pb-3 pt-[30px]', !visible && 'opacity-0')}\n >\n <Svg pointerEvents=\"none\" style={StyleSheet.absoluteFill} preserveAspectRatio=\"none\">\n <Defs>\n <LinearGradient id=\"scrim\" x1=\"0\" y1=\"1\" x2=\"0\" y2=\"0\">\n <Stop offset=\"0\" stopColor={scrim} stopOpacity={0.65} />\n <Stop offset=\"1\" stopColor={scrim} stopOpacity={0} />\n </LinearGradient>\n </Defs>\n <Rect width=\"100%\" height=\"100%\" fill=\"url(#scrim)\" />\n </Svg>\n <View {...seek.props} className=\"mb-1 h-4 w-full justify-center\">\n {/* Filhos ignoram toques para que `locationX` seja sempre relativo à barra. */}\n <View pointerEvents=\"none\" className=\"h-1 w-full rounded-full bg-media-on-surface/30\">\n <View\n className=\"h-full rounded-full bg-media-accent\"\n style={{ width: `${progress}%` }}\n />\n </View>\n </View>\n <View className=\"h-9 flex-row items-center justify-between\">\n <View className=\"flex-row items-center gap-2\">\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={playing ? 'Pausar' : 'Reproduzir'}\n onPress={() => {\n onPlayPause?.()\n show()\n }}\n className={button}\n >\n {playing ? <PauseIcon color={onSurface} /> : <PlayIcon color={onSurface} />}\n </Pressable>\n <Text\n accessible={false}\n className=\"text-xs font-medium leading-4 text-media-on-surface\"\n style={{ fontVariant: ['tabular-nums'] }}\n >\n {formatTime(position)} / {formatTime(duration)}\n </Text>\n </View>\n <View className=\"flex-row items-center gap-2\">\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={muted ? 'Ativar o som' : 'Silenciar'}\n onPress={() => {\n onToggleMute?.()\n show()\n }}\n className={button}\n >\n {muted ? <VolumeMutedIcon color={onSurface} /> : <VolumeIcon color={onSurface} />}\n </Pressable>\n {onToggleFullscreen && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={fullscreen ? 'Sair da tela cheia' : 'Tela cheia'}\n onPress={onToggleFullscreen}\n className={button}\n >\n {fullscreen ? (\n <MinimizeIcon color={onSurface} />\n ) : (\n <MaximizeIcon color={onSurface} />\n )}\n </Pressable>\n )}\n </View>\n </View>\n </View>\n </View>\n )\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Accordion, AccordionItem, AccordionItemProps, AccordionProps } from "./
|
|
|
2
2
|
import "./components/accordion/index.js";
|
|
3
3
|
import { Alert, AlertProps } from "./components/alert/alert.js";
|
|
4
4
|
import "./components/alert/index.js";
|
|
5
|
+
import { AudioPlayer, AudioPlayerProps } from "./components/audio-player/audio-player.js";
|
|
6
|
+
import "./components/audio-player/index.js";
|
|
5
7
|
import { Avatar, AvatarProps } from "./components/avatar/avatar.js";
|
|
6
8
|
import "./components/avatar/index.js";
|
|
7
9
|
import { Badge, BadgeProps } from "./components/badge/badge.js";
|
|
@@ -14,6 +16,8 @@ import { Button, ButtonProps } from "./components/button/button.js";
|
|
|
14
16
|
import "./components/button/index.js";
|
|
15
17
|
import { Card, CardProps } from "./components/card/card.js";
|
|
16
18
|
import "./components/card/index.js";
|
|
19
|
+
import { Carousel, CarouselItem, CarouselProps } from "./components/carousel/carousel.js";
|
|
20
|
+
import "./components/carousel/index.js";
|
|
17
21
|
import { Checkbox, CheckboxProps } from "./components/checkbox/checkbox.js";
|
|
18
22
|
import "./components/checkbox/index.js";
|
|
19
23
|
import { Combobox, ComboboxOption, ComboboxProps } from "./components/combobox/combobox.js";
|
|
@@ -32,6 +36,9 @@ import { Drawer, DrawerClose, DrawerProps } from "./components/drawer/drawer.js"
|
|
|
32
36
|
import "./components/drawer/index.js";
|
|
33
37
|
import { Field, FieldProps } from "./components/field/field.js";
|
|
34
38
|
import "./components/field/index.js";
|
|
39
|
+
import { Lightbox, LightboxItem, LightboxProps } from "./components/lightbox/lightbox.js";
|
|
40
|
+
import { Gallery, GalleryItem, GalleryProps } from "./components/gallery/gallery.js";
|
|
41
|
+
import "./components/gallery/index.js";
|
|
35
42
|
import { Grid, GridItem, GridItemProps, GridProps } from "./components/grid/grid.js";
|
|
36
43
|
import "./components/grid/index.js";
|
|
37
44
|
import { IconButton, IconButtonProps } from "./components/icon-button/icon-button.js";
|
|
@@ -82,6 +89,8 @@ import { Tooltip, TooltipProps } from "./components/tooltip/tooltip.js";
|
|
|
82
89
|
import "./components/tooltip/index.js";
|
|
83
90
|
import { Upload, UploadFile, UploadFileStatus, UploadProps } from "./components/upload/upload.js";
|
|
84
91
|
import "./components/upload/index.js";
|
|
92
|
+
import { VideoPlayer, VideoPlayerProps } from "./components/video-player/video-player.js";
|
|
93
|
+
import "./components/video-player/index.js";
|
|
85
94
|
import { darkColors, lightColors, overlayOpacity, palette, radius, typography } from "./tokens/generated.js";
|
|
86
95
|
import { cn } from "./utils/cn.js";
|
|
87
|
-
export { Accordion, AccordionItem, type AccordionItemProps, type AccordionProps, Alert, type AlertProps, Avatar, type AvatarProps, Badge, type BadgeProps, Banner, type BannerProps, Breadcrumb, BreadcrumbItem, type BreadcrumbItemProps, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, type CardProps, Checkbox, type CheckboxProps, Combobox, type ComboboxOption, type ComboboxProps, Container, type ContainerProps, DatePicker, type DatePickerProps, type DatePreset, type DateRange, DateRangePicker, type DateRangePickerProps, Divider, type DividerProps, Drawer, DrawerClose, type DrawerProps, Field, type FieldProps, Grid, GridItem, type GridItemProps, type GridProps, IconButton, type IconButtonProps, Input, type InputProps, Link, type LinkProps, List, ListItem, type ListItemProps, type ListProps, Menu, MenuItem, type MenuItemProps, MenuLabel, type MenuLabelProps, type MenuProps, MenuSeparator, type MenuSeparatorProps, Modal, ModalClose, type ModalProps, Pagination, type PaginationProps, Popover, PopoverClose, type PopoverProps, Radio, type RadioProps, SegmentedControl, type SegmentedControlProps, SegmentedItem, type SegmentedItemProps, Select, SelectOption, type SelectOptionProps, type SelectProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Step, type StepProps, Stepper, type StepperProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, Tag, type TagProps, Textarea, type TextareaProps, type ToastOptions, ToastProvider, type ToastProviderProps, Tooltip, type TooltipProps, Upload, type UploadFile, type UploadFileStatus, type UploadProps, cn, darkColors, getDatePresets, lightColors, overlayOpacity, palette, radius, typography, useToast };
|
|
96
|
+
export { Accordion, AccordionItem, type AccordionItemProps, type AccordionProps, Alert, type AlertProps, AudioPlayer, type AudioPlayerProps, Avatar, type AvatarProps, Badge, type BadgeProps, Banner, type BannerProps, Breadcrumb, BreadcrumbItem, type BreadcrumbItemProps, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, type CardProps, Carousel, CarouselItem, type CarouselProps, Checkbox, type CheckboxProps, Combobox, type ComboboxOption, type ComboboxProps, Container, type ContainerProps, DatePicker, type DatePickerProps, type DatePreset, type DateRange, DateRangePicker, type DateRangePickerProps, Divider, type DividerProps, Drawer, DrawerClose, type DrawerProps, Field, type FieldProps, Gallery, type GalleryItem, type GalleryProps, Grid, GridItem, type GridItemProps, type GridProps, IconButton, type IconButtonProps, Input, type InputProps, Lightbox, type LightboxItem, type LightboxProps, Link, type LinkProps, List, ListItem, type ListItemProps, type ListProps, Menu, MenuItem, type MenuItemProps, MenuLabel, type MenuLabelProps, type MenuProps, MenuSeparator, type MenuSeparatorProps, Modal, ModalClose, type ModalProps, Pagination, type PaginationProps, Popover, PopoverClose, type PopoverProps, Radio, type RadioProps, SegmentedControl, type SegmentedControlProps, SegmentedItem, type SegmentedItemProps, Select, SelectOption, type SelectOptionProps, type SelectProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Step, type StepProps, Stepper, type StepperProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, Tag, type TagProps, Textarea, type TextareaProps, type ToastOptions, ToastProvider, type ToastProviderProps, Tooltip, type TooltipProps, Upload, type UploadFile, type UploadFileStatus, type UploadProps, VideoPlayer, type VideoPlayerProps, cn, darkColors, getDatePresets, lightColors, overlayOpacity, palette, radius, typography, useToast };
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,14 @@ import { Accordion, AccordionItem } from "./components/accordion/accordion.js";
|
|
|
3
3
|
import { Spinner } from "./components/spinner/spinner.js";
|
|
4
4
|
import { IconButton } from "./components/icon-button/icon-button.js";
|
|
5
5
|
import { Alert } from "./components/alert/alert.js";
|
|
6
|
+
import { AudioPlayer } from "./components/audio-player/audio-player.js";
|
|
6
7
|
import { Avatar } from "./components/avatar/avatar.js";
|
|
7
8
|
import { Badge } from "./components/badge/badge.js";
|
|
8
9
|
import { Banner } from "./components/banner/banner.js";
|
|
9
10
|
import { Breadcrumb, BreadcrumbItem } from "./components/breadcrumb/breadcrumb.js";
|
|
10
11
|
import { Button } from "./components/button/button.js";
|
|
11
12
|
import { Card } from "./components/card/card.js";
|
|
13
|
+
import { Carousel, CarouselItem } from "./components/carousel/carousel.js";
|
|
12
14
|
import { Checkbox } from "./components/checkbox/checkbox.js";
|
|
13
15
|
import { Combobox } from "./components/combobox/combobox.js";
|
|
14
16
|
import { Container } from "./components/container/container.js";
|
|
@@ -20,6 +22,8 @@ import { DateRangePicker } from "./components/date-picker/date-range-picker.js";
|
|
|
20
22
|
import { Divider } from "./components/divider/divider.js";
|
|
21
23
|
import { Drawer, DrawerClose } from "./components/drawer/drawer.js";
|
|
22
24
|
import { Field } from "./components/field/field.js";
|
|
25
|
+
import { Lightbox } from "./components/lightbox/lightbox.js";
|
|
26
|
+
import { Gallery } from "./components/gallery/gallery.js";
|
|
23
27
|
import { Grid, GridItem } from "./components/grid/grid.js";
|
|
24
28
|
import { Input } from "./components/input/input.js";
|
|
25
29
|
import { Link } from "./components/link/link.js";
|
|
@@ -43,4 +47,5 @@ import { Textarea } from "./components/textarea/textarea.js";
|
|
|
43
47
|
import { ToastProvider, useToast } from "./components/toast/toast.js";
|
|
44
48
|
import { Tooltip } from "./components/tooltip/tooltip.js";
|
|
45
49
|
import { Upload } from "./components/upload/upload.js";
|
|
46
|
-
|
|
50
|
+
import { VideoPlayer } from "./components/video-player/video-player.js";
|
|
51
|
+
export { Accordion, AccordionItem, Alert, AudioPlayer, Avatar, Badge, Banner, Breadcrumb, BreadcrumbItem, Button, Calendar, Card, Carousel, CarouselItem, Checkbox, Combobox, Container, DatePicker, DateRangePicker, Divider, Drawer, DrawerClose, Field, Gallery, Grid, GridItem, IconButton, Input, Lightbox, Link, List, ListItem, Menu, MenuItem, MenuLabel, MenuSeparator, Modal, ModalClose, Pagination, Popover, PopoverClose, Radio, SegmentedControl, SegmentedItem, Select, SelectOption, Skeleton, Slider, Spinner, Stack, Step, Stepper, Switch, Tab, TabList, TabPanel, Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, Tabs, Tag, Textarea, ToastProvider, Tooltip, Upload, VideoPlayer, cn, darkColors, getDatePresets, lightColors, overlayOpacity, palette, radius, typography, useToast };
|
|
@@ -172,6 +172,10 @@ export declare const lightColors: {
|
|
|
172
172
|
readonly selectionToggleTrackOff: "#ccd5e2";
|
|
173
173
|
readonly selectionToggleTrackOffHover: "#96a3b9";
|
|
174
174
|
readonly selectionToggleTrackOnHover: "#7b24d1";
|
|
175
|
+
readonly mediaWaveRest: "#ccd5e2";
|
|
176
|
+
readonly mediaSurface: "#000000";
|
|
177
|
+
readonly mediaOnSurface: "#ffffff";
|
|
178
|
+
readonly mediaAccent: "#bd84ff";
|
|
175
179
|
};
|
|
176
180
|
export declare const darkColors: {
|
|
177
181
|
readonly textPrimary: "#f8fafc";
|
|
@@ -264,6 +268,10 @@ export declare const darkColors: {
|
|
|
264
268
|
readonly selectionToggleTrackOff: "#49556a";
|
|
265
269
|
readonly selectionToggleTrackOffHover: "#96a3b9";
|
|
266
270
|
readonly selectionToggleTrackOnHover: "#d6b4ff";
|
|
271
|
+
readonly mediaWaveRest: "#66748c";
|
|
272
|
+
readonly mediaSurface: "#000000";
|
|
273
|
+
readonly mediaOnSurface: "#ffffff";
|
|
274
|
+
readonly mediaAccent: "#bd84ff";
|
|
267
275
|
};
|
|
268
276
|
export declare const radius: {
|
|
269
277
|
readonly none: 0;
|
package/dist/tokens/generated.js
CHANGED
|
@@ -171,7 +171,11 @@ const lightColors = {
|
|
|
171
171
|
"selectionTextDisabled": "#ccd5e2",
|
|
172
172
|
"selectionToggleTrackOff": "#ccd5e2",
|
|
173
173
|
"selectionToggleTrackOffHover": "#96a3b9",
|
|
174
|
-
"selectionToggleTrackOnHover": "#7b24d1"
|
|
174
|
+
"selectionToggleTrackOnHover": "#7b24d1",
|
|
175
|
+
"mediaWaveRest": "#ccd5e2",
|
|
176
|
+
"mediaSurface": "#000000",
|
|
177
|
+
"mediaOnSurface": "#ffffff",
|
|
178
|
+
"mediaAccent": "#bd84ff"
|
|
175
179
|
};
|
|
176
180
|
const darkColors = {
|
|
177
181
|
"textPrimary": "#f8fafc",
|
|
@@ -263,7 +267,11 @@ const darkColors = {
|
|
|
263
267
|
"selectionTextDisabled": "#49556a",
|
|
264
268
|
"selectionToggleTrackOff": "#49556a",
|
|
265
269
|
"selectionToggleTrackOffHover": "#96a3b9",
|
|
266
|
-
"selectionToggleTrackOnHover": "#d6b4ff"
|
|
270
|
+
"selectionToggleTrackOnHover": "#d6b4ff",
|
|
271
|
+
"mediaWaveRest": "#66748c",
|
|
272
|
+
"mediaSurface": "#000000",
|
|
273
|
+
"mediaOnSurface": "#ffffff",
|
|
274
|
+
"mediaAccent": "#bd84ff"
|
|
267
275
|
};
|
|
268
276
|
const radius = {
|
|
269
277
|
"none": 0,
|