negodesign 0.0.11 → 0.0.13
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/dist/components/NegoDesign.svelte +1 -1
- package/dist/components/NegoDesign.svelte.d.ts +1 -1
- package/dist/components/core/button/ButtonBack.svelte +1 -1
- package/dist/components/core/button/ButtonLogin.svelte +1 -1
- package/dist/components/core/button/ButtonLoginWith.svelte +1 -1
- package/dist/components/core/button/ButtonSend.svelte +1 -1
- package/dist/components/core/card/media/01/CardMedia01.svelte +114 -0
- package/dist/components/core/card/media/01/CardMedia01.svelte.d.ts +4 -0
- package/dist/components/core/card/media/02/CardMedia02.svelte +113 -0
- package/dist/components/core/card/media/02/CardMedia02.svelte.d.ts +4 -0
- package/dist/components/core/card/media/CardMedia.svelte +17 -0
- package/dist/components/core/card/media/CardMedia.svelte.d.ts +8 -0
- package/dist/components/core/card/media/data.d.ts +3 -0
- package/dist/components/core/card/media/data.js +117 -0
- package/dist/components/core/card/profile/01/CardProfile01.svelte +101 -0
- package/dist/components/core/card/profile/01/CardProfile01.svelte.d.ts +4 -0
- package/dist/components/core/card/profile/02/CardProfile02.svelte +97 -0
- package/dist/components/core/card/profile/02/CardProfile02.svelte.d.ts +4 -0
- package/dist/components/core/card/profile/CardProfile.svelte +17 -0
- package/dist/components/core/card/profile/CardProfile.svelte.d.ts +8 -0
- package/dist/components/core/card/profile/data.d.ts +3 -0
- package/dist/components/core/card/profile/data.js +107 -0
- package/dist/components/core/card/promotion/CardPromotion.svelte +44 -0
- package/dist/components/core/card/promotion/CardPromotion.svelte.d.ts +8 -0
- package/dist/components/core/card/promotion/data.d.ts +3 -0
- package/dist/components/core/card/promotion/data.js +31 -0
- package/dist/components/core/card/shared/CardButton.svelte +30 -0
- package/dist/components/core/card/shared/CardButton.svelte.d.ts +12 -0
- package/dist/components/core/card/shared/CardDescription.svelte +23 -0
- package/dist/components/core/card/shared/CardDescription.svelte.d.ts +6 -0
- package/dist/components/core/card/shared/CardFavorite.svelte +28 -0
- package/dist/components/core/card/shared/CardFavorite.svelte.d.ts +7 -0
- package/dist/components/core/card/shared/CardStarRating.svelte +20 -0
- package/dist/components/core/card/shared/CardStarRating.svelte.d.ts +7 -0
- package/dist/components/core/card/shared/CardTags.svelte +56 -0
- package/dist/components/core/card/shared/CardTags.svelte.d.ts +10 -0
- package/dist/components/core/card/shared/CardThumbnailVideo.svelte +170 -0
- package/dist/components/core/card/shared/CardThumbnailVideo.svelte.d.ts +10 -0
- package/dist/components/core/card/shared/TruncatableText.svelte +56 -0
- package/dist/components/core/card/shared/TruncatableText.svelte.d.ts +8 -0
- package/dist/components/core/card/types.d.ts +54 -0
- package/dist/components/core/carousel/promotion/ui/CarouselPromotion.svelte +53 -0
- package/dist/components/core/carousel/promotion/ui/CarouselPromotion.svelte.d.ts +4 -0
- package/dist/components/core/carousel/shared/ui/SimpleBadgeCarousel.svelte +59 -0
- package/dist/components/core/carousel/shared/ui/SimpleBadgeCarousel.svelte.d.ts +4 -0
- package/dist/components/core/carousel/types.d.ts +34 -0
- package/dist/components/core/datatable/ui/DataTableCore.svelte +5 -5
- package/dist/components/core/form/ui/input-code-otp.svelte +3 -3
- package/dist/components/core/form/ui/input-code-otp.svelte.d.ts +2 -2
- package/dist/components/core/form/ui/input-email-or-phone.svelte +1 -1
- package/dist/components/core/form/ui/input-email.svelte +1 -1
- package/dist/components/core/form/ui/input-password-confirm.svelte +1 -1
- package/dist/components/core/form/ui/input-password.svelte +1 -1
- package/dist/components/core/form/ui/input-phone.svelte +1 -1
- package/dist/components/core/form/ui/input-username.svelte +2 -2
- package/dist/components/core/nav/data/nav-menu-sidebar.d.ts +7 -7
- package/dist/components/core/nav/data/nav-menu.d.ts +31 -0
- package/dist/components/core/nav/data/nav-user-sidebar.d.ts +1 -1
- package/dist/components/core/nav/ui/menu-links.svelte +28 -0
- package/dist/components/core/nav/ui/menu-links.svelte.d.ts +10 -0
- package/dist/components/core/nav/ui/mobile/nav-menu-drawer.svelte +85 -0
- package/dist/components/core/nav/ui/mobile/nav-menu-drawer.svelte.d.ts +9 -0
- package/dist/components/core/nav/ui/{nav-menu-bottom-bar.svelte → nav-menu-bottom-sidebar.svelte} +2 -2
- package/dist/components/core/nav/ui/nav-menu-bottom-sidebar.svelte.d.ts +10 -0
- package/dist/components/core/nav/ui/nav-menu-header-sidebar.svelte.d.ts +10 -0
- package/dist/components/core/nav/ui/{nav-menu-bar.svelte → nav-menu-sidebar.svelte} +7 -7
- package/dist/components/core/nav/ui/nav-menu-sidebar.svelte.d.ts +7 -0
- package/dist/components/core/nav/ui/nav-menu-top-bar-sidebar.svelte.d.ts +4 -0
- package/dist/components/core/nav/ui/nav-menu.svelte +98 -0
- package/dist/components/core/nav/ui/nav-menu.svelte.d.ts +4 -0
- package/dist/components/core/nav/ui/nav-user-sidebar.svelte +2 -2
- package/dist/components/core/nav/ui/nav-user-sidebar.svelte.d.ts +2 -2
- package/dist/components/core/panel/CarouselSlot.svelte +38 -0
- package/dist/components/core/panel/CarouselSlot.svelte.d.ts +11 -0
- package/dist/components/core/panel/LeftHero.svelte +3 -3
- package/dist/components/core/panel/LeftHero.svelte.d.ts +2 -2
- package/dist/components/core/search/01/Search01.svelte +15 -0
- package/dist/components/core/search/01/Search01.svelte.d.ts +4 -0
- package/dist/components/core/search/02/Search02.svelte +15 -0
- package/dist/components/core/search/02/Search02.svelte.d.ts +4 -0
- package/dist/components/core/search/SearchInput.svelte +32 -0
- package/dist/components/core/search/SearchInput.svelte.d.ts +4 -0
- package/dist/components/core/search/shared/SearchInputCore.svelte +66 -0
- package/dist/components/core/search/shared/SearchInputCore.svelte.d.ts +4 -0
- package/dist/components/core/search/types.d.ts +15 -0
- package/dist/components/core/sidebar/MenuBarSidebar.svelte +14 -14
- package/dist/components/core/sidebar/MenuBarSidebar.svelte.d.ts +8 -8
- package/dist/components/pages/admin/{ui → 01/ui}/AdminContent.svelte +1 -1
- package/dist/components/pages/admin/{ui → 01/ui}/AdminContent.svelte.d.ts +1 -1
- package/dist/components/pages/admin/{ui → 01/ui}/AdminPanel.svelte +8 -8
- package/dist/components/pages/admin/{ui → 01/ui}/AdminPanel.svelte.d.ts +4 -4
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/DocsSidebar.svelte +69 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/DocsSidebar.svelte.d.ts +10 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/PrivacyPolicyOrTermsOfUse01.svelte +73 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/PrivacyPolicyOrTermsOfUse01.svelte.d.ts +7 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/TableOfContents.svelte +37 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/01/TableOfContents.svelte.d.ts +8 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/DocsPageHero.svelte +59 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/DocsPageHero.svelte.d.ts +10 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/PageHero.svelte +51 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/PageHero.svelte.d.ts +14 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/PrivacyPolicyOrTermsOfUse02.svelte +24 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/02/PrivacyPolicyOrTermsOfUse02.svelte.d.ts +7 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/PrivacyPolicyOrTermsOfUse.svelte +32 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/PrivacyPolicyOrTermsOfUse.svelte.d.ts +4 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/ContentBlockView.svelte +26 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/ContentBlockView.svelte.d.ts +7 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/DocSectionView.svelte +44 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/DocSectionView.svelte.d.ts +7 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/PrivacyPolicyOrTermsOfUseBreadcrumb.svelte +34 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/PrivacyPolicyOrTermsOfUseBreadcrumb.svelte.d.ts +7 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/toc.d.ts +8 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/toc.js +14 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/types.d.ts +62 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/types.js +5 -0
- package/dist/components/pages/{forget-password → security/forget-password}/01/ui/ForgetPasswordCard.svelte +15 -10
- package/dist/components/pages/{forget-password → security/forget-password}/01/ui/ForgetPasswordCard.svelte.d.ts +0 -5
- package/dist/components/pages/{forget-password → security/forget-password}/01/ui/FormForgetPassword.svelte +15 -5
- package/dist/components/pages/{forget-password → security/forget-password}/01/ui/PageForgetPassword01.svelte +6 -6
- package/dist/components/pages/{forget-password → security/forget-password}/PageForgetPassword.svelte +10 -7
- package/dist/components/pages/{forget-password → security/forget-password}/PageForgetPassword.svelte.d.ts +0 -7
- package/dist/components/pages/{forget-password → security/forget-password}/types.d.ts +3 -3
- package/dist/components/pages/{login → security/login}/01/ui/FormLogin.svelte +19 -15
- package/dist/components/pages/{login → security/login}/01/ui/FormLogin.svelte.d.ts +0 -6
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginEmailPassword.svelte +10 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginEmailPassword.svelte.d.ts +0 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginPhonePassword.svelte +10 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginPhonePassword.svelte.d.ts +0 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginUsernamePassword.svelte +10 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormLoginUsernamePassword.svelte.d.ts +0 -1
- package/dist/components/pages/{login → security/login}/01/ui/FormRegister.svelte +5 -5
- package/dist/components/pages/{login → security/login}/01/ui/LoginCard.svelte +28 -20
- package/dist/components/pages/security/login/01/ui/LoginCard.svelte.d.ts +13 -0
- package/dist/components/pages/{login → security/login}/01/ui/PageLogin01.svelte +12 -11
- package/dist/components/pages/security/login/PageLogin.svelte +22 -0
- package/dist/components/pages/security/login/PageLogin.svelte.d.ts +8 -0
- package/dist/components/pages/security/login/types.d.ts +33 -0
- package/dist/components/pages/security/login/types.js +1 -0
- package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/FormOtpVerification.svelte +13 -3
- package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/OtpVerificationCard.svelte +15 -10
- package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/OtpVerificationCard.svelte.d.ts +0 -5
- package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/PageOtpVerification01.svelte +12 -6
- package/dist/components/pages/{otp-verification → security/otp-verification}/PageOtpVerification.svelte +10 -4
- package/dist/components/pages/{otp-verification → security/otp-verification}/PageOtpVerification.svelte.d.ts +0 -4
- package/dist/components/pages/{otp-verification → security/otp-verification}/types.d.ts +3 -3
- package/dist/components/pages/security/otp-verification/types.js +1 -0
- package/dist/components/pages/{reset-password → security/reset-password}/01/ui/FormResetPassword.svelte +15 -5
- package/dist/components/pages/{reset-password → security/reset-password}/01/ui/PageResetPassword01.svelte +12 -6
- package/dist/components/pages/{reset-password → security/reset-password}/01/ui/ResetPasswordCard.svelte +15 -10
- package/dist/components/pages/{reset-password → security/reset-password}/01/ui/ResetPasswordCard.svelte.d.ts +0 -5
- package/dist/components/pages/{reset-password → security/reset-password}/PageResetPassword.svelte +10 -4
- package/dist/components/pages/{reset-password → security/reset-password}/PageResetPassword.svelte.d.ts +0 -4
- package/dist/components/pages/{reset-password → security/reset-password}/types.d.ts +3 -3
- package/dist/components/pages/security/reset-password/types.js +1 -0
- package/dist/components/ui/button/button.svelte +82 -101
- package/dist/components/ui/button/button.svelte.d.ts +36 -63
- package/dist/components/ui/button/index.d.ts +2 -2
- package/dist/components/ui/button/index.js +2 -2
- package/dist/components/ui/carousel/carousel-content.svelte +43 -0
- package/dist/components/ui/carousel/carousel-content.svelte.d.ts +5 -0
- package/dist/components/ui/carousel/carousel-item.svelte +30 -0
- package/dist/components/ui/carousel/carousel-item.svelte.d.ts +5 -0
- package/dist/components/ui/carousel/carousel-next.svelte +40 -0
- package/dist/components/ui/carousel/carousel-next.svelte.d.ts +4 -0
- package/dist/components/ui/carousel/carousel-previous.svelte +40 -0
- package/dist/components/ui/carousel/carousel-previous.svelte.d.ts +4 -0
- package/dist/components/ui/carousel/carousel.svelte +94 -0
- package/dist/components/ui/carousel/carousel.svelte.d.ts +5 -0
- package/dist/components/ui/carousel/context.d.ts +31 -0
- package/dist/components/ui/carousel/context.js +12 -0
- package/dist/components/ui/carousel/index.d.ts +6 -0
- package/dist/components/ui/carousel/index.js +8 -0
- package/dist/components/ui/input-group/input-group-addon.svelte +6 -0
- package/dist/components/ui/input-group/input-group-addon.svelte.d.ts +6 -0
- package/dist/components/ui/light-switch/light-switch.svelte +17 -6
- package/dist/components/ui/light-switch/light-switch.svelte.d.ts +2 -2
- package/dist/components/ui/star-rating/index.d.ts +2 -0
- package/dist/components/ui/star-rating/index.js +2 -0
- package/dist/components/ui/star-rating/star-rating-star.svelte +41 -0
- package/dist/components/ui/star-rating/star-rating-star.svelte.d.ts +4 -0
- package/dist/components/ui/star-rating/star-rating.svelte +20 -0
- package/dist/components/ui/star-rating/star-rating.svelte.d.ts +4 -0
- package/dist/components/ui/star-rating/types.d.ts +5 -0
- package/dist/components/ui/star-rating/types.js +1 -0
- package/dist/globals.css +645 -36
- package/dist/hooks/responsive.svelte.d.ts +3 -0
- package/dist/hooks/responsive.svelte.js +18 -0
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/langs/en.d.ts +23 -8
- package/dist/i18n/langs/en.js +23 -8
- package/dist/i18n/langs/pt.d.ts +23 -8
- package/dist/i18n/langs/pt.js +23 -8
- package/dist/i18n/translations.d.ts +46 -16
- package/dist/index.d.ts +15 -9
- package/dist/index.js +15 -9
- package/dist/styles/globals.css +147 -141
- package/dist/types/index.d.ts +4 -4
- package/package.json +11 -9
- package/dist/components/core/carousel/data/CarouselModel.d.ts +0 -11
- package/dist/components/core/nav/ui/nav-menu-bar.svelte.d.ts +0 -7
- package/dist/components/core/nav/ui/nav-menu-bottom-bar.svelte.d.ts +0 -10
- package/dist/components/core/nav/ui/nav-menu-header.svelte.d.ts +0 -10
- package/dist/components/core/nav/ui/nav-menu-top-bar.svelte.d.ts +0 -4
- package/dist/components/pages/login/01/ui/LoginCard.svelte.d.ts +0 -21
- package/dist/components/pages/login/PageLogin.svelte +0 -21
- package/dist/components/pages/login/PageLogin.svelte.d.ts +0 -17
- package/dist/components/pages/login/types.d.ts +0 -23
- /package/dist/components/{pages/forget-password → core/card}/types.js +0 -0
- /package/dist/components/{pages/login → core/carousel}/types.js +0 -0
- /package/dist/components/core/{carousel/data/CarouselModel.js → nav/data/nav-menu.js} +0 -0
- /package/dist/components/core/nav/ui/{nav-menu-header.svelte → nav-menu-header-sidebar.svelte} +0 -0
- /package/dist/components/core/nav/ui/{nav-menu-top-bar.svelte → nav-menu-top-bar-sidebar.svelte} +0 -0
- /package/dist/components/{pages/otp-verification → core/search}/types.js +0 -0
- /package/dist/components/pages/{forget-password → security/forget-password}/01/ui/FormForgetPassword.svelte.d.ts +0 -0
- /package/dist/components/pages/{forget-password → security/forget-password}/01/ui/PageForgetPassword01.svelte.d.ts +0 -0
- /package/dist/components/pages/{reset-password → security/forget-password}/types.js +0 -0
- /package/dist/components/pages/{login → security/login}/01/ui/FormRegister.svelte.d.ts +0 -0
- /package/dist/components/pages/{login → security/login}/01/ui/PageLogin01.svelte.d.ts +0 -0
- /package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/FormOtpVerification.svelte.d.ts +0 -0
- /package/dist/components/pages/{otp-verification → security/otp-verification}/01/ui/PageOtpVerification01.svelte.d.ts +0 -0
- /package/dist/components/pages/{reset-password → security/reset-password}/01/ui/FormResetPassword.svelte.d.ts +0 -0
- /package/dist/components/pages/{reset-password → security/reset-password}/01/ui/PageResetPassword01.svelte.d.ts +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CardProfileProps } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
variant?: 1 | 2;
|
|
4
|
+
};
|
|
5
|
+
type $$ComponentProps = CardProfileProps & Props;
|
|
6
|
+
declare const CardProfile: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type CardProfile = ReturnType<typeof CardProfile>;
|
|
8
|
+
export default CardProfile;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { GlobalIcon, MapPin, NecklaceIcon } from "@hugeicons/core-free-icons";
|
|
2
|
+
const items = [
|
|
3
|
+
{
|
|
4
|
+
id: 1,
|
|
5
|
+
logo: 'https://api.dicebear.com/9.x/initials/svg?seed=Hotel%20Baía%20Azul&backgroundColor=1a2420&textColor=e3b563',
|
|
6
|
+
title: 'Hotel Baía Azul',
|
|
7
|
+
content: 'Hotel à beira-mar com vista panorâmica sobre a baía, piscina infinita e restaurante gastronómico. Resort tropical rodeado de jardins, com acesso direto à praia e atividades para toda a família Resort tropical rodeado de jardins, com acesso direto à praia e atividades para toda a família',
|
|
8
|
+
startNumber: 5,
|
|
9
|
+
startMax: 5,
|
|
10
|
+
isFavorite: true,
|
|
11
|
+
tags: [
|
|
12
|
+
{
|
|
13
|
+
icon: GlobalIcon,
|
|
14
|
+
text: 'Luanda',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
icon: MapPin,
|
|
18
|
+
text: 'Kilamba',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
icon: NecklaceIcon,
|
|
22
|
+
text: 'Rua 19',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 2,
|
|
28
|
+
logo: 'https://api.dicebear.com/9.x/initials/svg?seed=Miramar%20Suites&backgroundColor=1a2420&textColor=e3b563',
|
|
29
|
+
title: 'Miramar Suites',
|
|
30
|
+
content: 'Suítes modernas no coração da cidade, com spa completo e serviço de quarto 24 horas.',
|
|
31
|
+
startNumber: 4,
|
|
32
|
+
startMax: 5,
|
|
33
|
+
tags: [
|
|
34
|
+
{
|
|
35
|
+
icon: GlobalIcon,
|
|
36
|
+
text: 'Benguela',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
icon: MapPin,
|
|
40
|
+
text: 'Catumbela',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
icon: GlobalIcon,
|
|
44
|
+
text: 'Luanda',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
icon: MapPin,
|
|
48
|
+
text: 'Kilamba',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 3,
|
|
54
|
+
logo: 'https://api.dicebear.com/9.x/initials/svg?seed=Palm%20Resort&backgroundColor=1a2420&textColor=e3b563',
|
|
55
|
+
title: 'Palm Resort & Spa',
|
|
56
|
+
content: 'Resort tropical rodeado de jardins, com acesso direto à praia e atividades para toda a família.',
|
|
57
|
+
startNumber: 5,
|
|
58
|
+
startMax: 5,
|
|
59
|
+
isFavorite: true,
|
|
60
|
+
tags: [
|
|
61
|
+
{
|
|
62
|
+
icon: GlobalIcon,
|
|
63
|
+
text: 'Huíla',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
icon: MapPin,
|
|
67
|
+
text: 'Huíla',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 4,
|
|
73
|
+
logo: 'https://api.dicebear.com/9.x/initials/svg?seed=Hotel%20Central%20Park&backgroundColor=1a2420&textColor=e3b563',
|
|
74
|
+
title: 'Hotel Central Park',
|
|
75
|
+
content: 'Localização privilegiada no centro urbano, ideal para viagens de negócios, com centro de conferências.',
|
|
76
|
+
startNumber: 3,
|
|
77
|
+
startMax: 5,
|
|
78
|
+
tags: [
|
|
79
|
+
{
|
|
80
|
+
icon: NecklaceIcon,
|
|
81
|
+
text: 'Rua 19',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
icon: GlobalIcon,
|
|
85
|
+
text: 'Luanda',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
icon: MapPin,
|
|
89
|
+
text: 'Kilamba',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
icon: NecklaceIcon,
|
|
93
|
+
text: 'Rua 19',
|
|
94
|
+
},
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 5,
|
|
99
|
+
logo: 'https://api.dicebear.com/9.x/initials/svg?seed=Villa%20Serena&backgroundColor=1a2420&textColor=e3b563',
|
|
100
|
+
title: 'Villa Serena Boutique',
|
|
101
|
+
content: 'Boutique hotel intimista com decoração exclusiva, café da manhã artesanal e vista para as montanhas.',
|
|
102
|
+
startNumber: 4,
|
|
103
|
+
startMax: 5,
|
|
104
|
+
isFavorite: true,
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
export default items;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import CardFavorite from "../shared/CardFavorite.svelte";
|
|
3
|
+
/**
|
|
4
|
+
* Card component with a title and content.
|
|
5
|
+
* @component
|
|
6
|
+
*/
|
|
7
|
+
import type { CardPromotionProps } from "../types";
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
logo,
|
|
11
|
+
imageUrl,
|
|
12
|
+
title,
|
|
13
|
+
isFavorite = false,
|
|
14
|
+
}: CardPromotionProps = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<article class="relative rounded-sm">
|
|
18
|
+
{#if logo}
|
|
19
|
+
<div class="absolute top-1 left-1 z-2 flex gap-1 p-2">
|
|
20
|
+
<img src={logo} width={30} height={30} alt={title} class="rounded-lg" />
|
|
21
|
+
</div>
|
|
22
|
+
{/if}
|
|
23
|
+
|
|
24
|
+
<div class="absolute top-1 right-1 z-2 flex gap-1 p-2">
|
|
25
|
+
<CardFavorite {isFavorite} />
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
{#if imageUrl}
|
|
29
|
+
<img
|
|
30
|
+
src={imageUrl}
|
|
31
|
+
alt={imageUrl}
|
|
32
|
+
class="rounded-lg md:h-37.5 md:w-37.5 lg:h-50 lg:w-50 object-cover object-center"
|
|
33
|
+
/>
|
|
34
|
+
{/if}
|
|
35
|
+
<div class="absolute inset-0 bg-black/5 rounded-sm h-full w-full"></div>
|
|
36
|
+
|
|
37
|
+
<div
|
|
38
|
+
class="absolute bottom-1 inset-x-0 flex justify-center m-auto bg-black/10 backdrop-blur-sm max-w-11/12 p-2 rounded-md"
|
|
39
|
+
>
|
|
40
|
+
{#if title}
|
|
41
|
+
<div class="text-center font-semibold text-[12px]">{title}</div>
|
|
42
|
+
{/if}
|
|
43
|
+
</div>
|
|
44
|
+
</article>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card component with a title and content.
|
|
3
|
+
* @component
|
|
4
|
+
*/
|
|
5
|
+
import type { CardPromotionProps } from "../types";
|
|
6
|
+
declare const CardPromotion: import("svelte").Component<CardPromotionProps, {}, "">;
|
|
7
|
+
type CardPromotion = ReturnType<typeof CardPromotion>;
|
|
8
|
+
export default CardPromotion;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const items = [
|
|
2
|
+
{
|
|
3
|
+
id: 1,
|
|
4
|
+
imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
5
|
+
title: 'Hotel Baía Azul',
|
|
6
|
+
isFavorite: true,
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: 2,
|
|
10
|
+
imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
11
|
+
title: 'Miramar Suites',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 3,
|
|
15
|
+
imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
16
|
+
title: 'Palm Resort & Spa',
|
|
17
|
+
isFavorite: true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 4,
|
|
21
|
+
imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
22
|
+
title: 'Hotel Central Park',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 5,
|
|
26
|
+
imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
27
|
+
title: 'Villa Serena Boutique',
|
|
28
|
+
isFavorite: true,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
export default items;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from "../../../ui/button/index.js";
|
|
3
|
+
import { HugeiconsIcon, type IconSvgElement } from "@hugeicons/svelte";
|
|
4
|
+
|
|
5
|
+
type CardButtonProps = {
|
|
6
|
+
id: string | number;
|
|
7
|
+
icon: IconSvgElement;
|
|
8
|
+
isFlex?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
text: string;
|
|
11
|
+
onClick: (id: string | number) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
id,
|
|
16
|
+
icon,
|
|
17
|
+
isFlex,
|
|
18
|
+
className,
|
|
19
|
+
text,
|
|
20
|
+
onClick
|
|
21
|
+
}: CardButtonProps = $props();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Button
|
|
25
|
+
class="{isFlex ? 'flex-1' : ''} {className}"
|
|
26
|
+
onclick={() => onClick(id)}
|
|
27
|
+
>
|
|
28
|
+
<HugeiconsIcon {icon} />
|
|
29
|
+
<span>{text}</span>
|
|
30
|
+
</Button>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type IconSvgElement } from "@hugeicons/svelte";
|
|
2
|
+
type CardButtonProps = {
|
|
3
|
+
id: string | number;
|
|
4
|
+
icon: IconSvgElement;
|
|
5
|
+
isFlex?: boolean;
|
|
6
|
+
className?: string;
|
|
7
|
+
text: string;
|
|
8
|
+
onClick: (id: string | number) => void;
|
|
9
|
+
};
|
|
10
|
+
declare const CardButton: import("svelte").Component<CardButtonProps, {}, "">;
|
|
11
|
+
type CardButton = ReturnType<typeof CardButton>;
|
|
12
|
+
export default CardButton;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Message01Icon } from "@hugeicons/core-free-icons";
|
|
3
|
+
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
4
|
+
import TruncatableText from "./TruncatableText.svelte";
|
|
5
|
+
import { t } from "../../../../i18n";
|
|
6
|
+
|
|
7
|
+
type CardDescriptionProps = {
|
|
8
|
+
content?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
let { content }: CardDescriptionProps = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if content}
|
|
15
|
+
<div class="mb-1 text-[14px] flex items-center gap-1">
|
|
16
|
+
<HugeiconsIcon icon={Message01Icon} class="h-4 w-4" />
|
|
17
|
+
<div>{$t("label.description")}</div>
|
|
18
|
+
</div>
|
|
19
|
+
<TruncatableText
|
|
20
|
+
text={content}
|
|
21
|
+
class="text-justify text-[13px] text-gray-800 dark:text-gray-50 mt-3 my-4"
|
|
22
|
+
/>
|
|
23
|
+
{/if}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from "../../../ui/button/index.js";
|
|
3
|
+
import { HeartAddIcon, HeartRemoveIcon } from "@hugeicons/core-free-icons";
|
|
4
|
+
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
isFavorite: boolean;
|
|
8
|
+
onFavoriteClick?: () => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
let { isFavorite, onFavoriteClick }: Props = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if isFavorite}
|
|
15
|
+
<Button
|
|
16
|
+
class="w-8 h-8 rounded-full bg-[#ce2356]"
|
|
17
|
+
onclick={() => onFavoriteClick!()}
|
|
18
|
+
>
|
|
19
|
+
<HugeiconsIcon icon={HeartRemoveIcon} />
|
|
20
|
+
</Button>
|
|
21
|
+
{:else}
|
|
22
|
+
<Button
|
|
23
|
+
class="w-8 h-8 rounded-full bg-[#808080]"
|
|
24
|
+
onclick={() => onFavoriteClick!()}
|
|
25
|
+
>
|
|
26
|
+
<HugeiconsIcon icon={HeartAddIcon} />
|
|
27
|
+
</Button>
|
|
28
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as StarRating from "../../../ui/star-rating";
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
startNumber: number;
|
|
6
|
+
startMax: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
let { startNumber, startMax }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if startNumber}
|
|
13
|
+
<StarRating.Root max={startMax} value={startNumber} class="size-15 h-auto">
|
|
14
|
+
{#snippet children({ items })}
|
|
15
|
+
{#each items as item (item.index)}
|
|
16
|
+
<StarRating.Star {...item} class="py-0! my-0!" />
|
|
17
|
+
{/each}
|
|
18
|
+
{/snippet}
|
|
19
|
+
</StarRating.Root>
|
|
20
|
+
{/if}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
3
|
+
import type { CardTagsProps } from "../types";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
className?: string;
|
|
7
|
+
tags: CardTagsProps[];
|
|
8
|
+
isTagBorderBottom?: boolean;
|
|
9
|
+
isWrap?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
tags,
|
|
14
|
+
className,
|
|
15
|
+
isTagBorderBottom,
|
|
16
|
+
isWrap = false,
|
|
17
|
+
}: Props = $props();
|
|
18
|
+
|
|
19
|
+
let isJustify = $derived(tags.length == 2 || tags.length == 3);
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#snippet createBadge(tag: CardTagsProps)}
|
|
23
|
+
<div
|
|
24
|
+
class="flex items-center h-5 shrink-0 {isTagBorderBottom
|
|
25
|
+
? 'border border-gray-200 rounded-full px-2 py-1'
|
|
26
|
+
: ''}"
|
|
27
|
+
>
|
|
28
|
+
{#if tag.icon}
|
|
29
|
+
<HugeiconsIcon
|
|
30
|
+
icon={tag.icon}
|
|
31
|
+
class="mr-0.5 h-3.75 w-3.75 shrink-0"
|
|
32
|
+
/>
|
|
33
|
+
{/if}
|
|
34
|
+
<div class="whitespace-nowrap">{tag.text}</div>
|
|
35
|
+
</div>
|
|
36
|
+
{/snippet}
|
|
37
|
+
|
|
38
|
+
{#if tags && tags.length > 0}
|
|
39
|
+
{#if isWrap}
|
|
40
|
+
<div class="flex flex-wrap gap-2 md:gap-5 {className}">
|
|
41
|
+
{#each tags as tag, i (i)}
|
|
42
|
+
{@render createBadge(tag)}
|
|
43
|
+
{/each}
|
|
44
|
+
</div>
|
|
45
|
+
{:else}
|
|
46
|
+
<div class="flex overflow-x-auto no-scrollbar w-full
|
|
47
|
+
{isJustify ? 'justify-between' : 'gap-4 md:gap-5 lg:gap-10'}
|
|
48
|
+
{className}">
|
|
49
|
+
{#each tags as tag, i (i)}
|
|
50
|
+
{@render createBadge(tag)}
|
|
51
|
+
{/each}
|
|
52
|
+
</div>
|
|
53
|
+
{/if}
|
|
54
|
+
{:else}
|
|
55
|
+
<div class="w-full h-5 {className}"></div>
|
|
56
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CardTagsProps } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
className?: string;
|
|
4
|
+
tags: CardTagsProps[];
|
|
5
|
+
isTagBorderBottom?: boolean;
|
|
6
|
+
isWrap?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const CardTags: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type CardTags = ReturnType<typeof CardTags>;
|
|
10
|
+
export default CardTags;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<!-- CardMedia.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Image thumbnail with hover-to-play video, lazy loading,
|
|
5
|
+
* duration badge, video indicator, and optional maximize overlay.
|
|
6
|
+
* @component
|
|
7
|
+
*/
|
|
8
|
+
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
9
|
+
import { Maximize01Icon, Cancel01Icon, VideoReplayIcon } from "@hugeicons/core-free-icons";
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
imageUrl?: string;
|
|
13
|
+
videoUrl?: string;
|
|
14
|
+
class?: string;
|
|
15
|
+
isImageButtonMaximized?: boolean;
|
|
16
|
+
isVideoButtonMaximized?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
imageUrl,
|
|
21
|
+
videoUrl,
|
|
22
|
+
class: className = "w-64 h-64",
|
|
23
|
+
isImageButtonMaximized = false,
|
|
24
|
+
isVideoButtonMaximized = false,
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
|
|
27
|
+
let containerEl: HTMLDivElement | undefined = $state();
|
|
28
|
+
let videoEl: HTMLVideoElement | undefined = $state();
|
|
29
|
+
|
|
30
|
+
let isHovering = $state(false);
|
|
31
|
+
let isVisible = $state(false);
|
|
32
|
+
let isMaximized = $state(false);
|
|
33
|
+
let duration = $state("");
|
|
34
|
+
|
|
35
|
+
let showVideo = $derived(!imageUrl || isHovering);
|
|
36
|
+
let showMaximize = $derived((imageUrl && isImageButtonMaximized) || (videoUrl && isVideoButtonMaximized));
|
|
37
|
+
let showVideoBadge = $derived(!!imageUrl && !!videoUrl && !isHovering);
|
|
38
|
+
|
|
39
|
+
function onLoadedMetadata() {
|
|
40
|
+
if (!videoEl) return;
|
|
41
|
+
const m = Math.floor(videoEl.duration / 60);
|
|
42
|
+
const s = Math.floor(videoEl.duration % 60);
|
|
43
|
+
duration = `${m}:${s.toString().padStart(2, "0")}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function toggleHover(state: boolean) {
|
|
47
|
+
if (!videoUrl) return;
|
|
48
|
+
isHovering = state;
|
|
49
|
+
if (state) videoEl?.play();
|
|
50
|
+
else {
|
|
51
|
+
videoEl?.pause();
|
|
52
|
+
if (imageUrl && videoEl) videoEl.currentTime = 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
$effect(() => {
|
|
57
|
+
if (!containerEl) return;
|
|
58
|
+
const observer = new IntersectionObserver(
|
|
59
|
+
([entry]) => {
|
|
60
|
+
if (entry.isIntersecting) {
|
|
61
|
+
isVisible = true;
|
|
62
|
+
observer.disconnect();
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{ rootMargin: "100px" }
|
|
66
|
+
);
|
|
67
|
+
observer.observe(containerEl);
|
|
68
|
+
return () => observer.disconnect();
|
|
69
|
+
});
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<svelte:window onkeydown={isMaximized ? (e) => e.key === "Escape" && (isMaximized = false) : undefined} />
|
|
73
|
+
|
|
74
|
+
{#snippet maximizeButton()}
|
|
75
|
+
<button
|
|
76
|
+
type="button"
|
|
77
|
+
class="absolute top-2 right-2 z-10 rounded-full bg-black/50 p-1.5 text-white transition-colors hover:bg-black/70"
|
|
78
|
+
onclick={(e) => { e.stopPropagation(); isMaximized = true; videoEl?.pause(); }}
|
|
79
|
+
aria-label="Maximizar"
|
|
80
|
+
>
|
|
81
|
+
<HugeiconsIcon icon={Maximize01Icon} size={16} color="currentColor" strokeWidth={1.5} />
|
|
82
|
+
</button>
|
|
83
|
+
{/snippet}
|
|
84
|
+
|
|
85
|
+
{#if imageUrl || videoUrl}
|
|
86
|
+
<div
|
|
87
|
+
bind:this={containerEl}
|
|
88
|
+
class="relative w-full {className}"
|
|
89
|
+
role="button"
|
|
90
|
+
tabindex="0"
|
|
91
|
+
onmouseenter={() => toggleHover(true)}
|
|
92
|
+
onmouseleave={() => toggleHover(false)}
|
|
93
|
+
onfocus={() => toggleHover(true)}
|
|
94
|
+
onblur={() => toggleHover(false)}
|
|
95
|
+
onkeydown={(e) => (e.key === "Enter" || e.key === " ") && (e.preventDefault(), toggleHover(!isHovering))}
|
|
96
|
+
>
|
|
97
|
+
{#if imageUrl}
|
|
98
|
+
<img
|
|
99
|
+
src={isVisible ? imageUrl : undefined}
|
|
100
|
+
loading="lazy"
|
|
101
|
+
decoding="async"
|
|
102
|
+
alt={imageUrl}
|
|
103
|
+
class="absolute inset-0 w-full {className} rounded-md object-cover transition-opacity duration-500"
|
|
104
|
+
class:opacity-0={videoUrl && showVideo}
|
|
105
|
+
/>
|
|
106
|
+
{/if}
|
|
107
|
+
|
|
108
|
+
{#if videoUrl && isVisible}
|
|
109
|
+
<video
|
|
110
|
+
bind:this={videoEl}
|
|
111
|
+
src={videoUrl}
|
|
112
|
+
preload="metadata"
|
|
113
|
+
onloadedmetadata={onLoadedMetadata}
|
|
114
|
+
class="absolute inset-0 w-full {className} rounded-md object-cover transition-opacity duration-500"
|
|
115
|
+
class:opacity-0={imageUrl && !showVideo}
|
|
116
|
+
muted
|
|
117
|
+
loop
|
|
118
|
+
playsinline
|
|
119
|
+
></video>
|
|
120
|
+
{/if}
|
|
121
|
+
|
|
122
|
+
{#if showVideoBadge}
|
|
123
|
+
<div class="pointer-events-none absolute inset-0 flex items-center justify-center transition-opacity duration-300">
|
|
124
|
+
<div class="flex h-11 w-11 items-center justify-center rounded-full bg-black/50 backdrop-blur-sm">
|
|
125
|
+
<HugeiconsIcon icon={VideoReplayIcon} size={22} color="white" strokeWidth={1.5} />
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
{#if duration}
|
|
129
|
+
<span class="absolute bottom-2 right-2 z-10 rounded bg-black/60 px-1.5 py-0.5 text-xs font-medium text-white">
|
|
130
|
+
{duration}
|
|
131
|
+
</span>
|
|
132
|
+
{/if}
|
|
133
|
+
{/if}
|
|
134
|
+
|
|
135
|
+
{#if showMaximize}
|
|
136
|
+
{@render maximizeButton()}
|
|
137
|
+
{/if}
|
|
138
|
+
</div>
|
|
139
|
+
{/if}
|
|
140
|
+
|
|
141
|
+
{#if isMaximized}
|
|
142
|
+
<div class="fixed inset-0 z-50">
|
|
143
|
+
<button
|
|
144
|
+
type="button"
|
|
145
|
+
class="absolute inset-0 h-full w-full cursor-default bg-black/80"
|
|
146
|
+
onclick={() => (isMaximized = false)}
|
|
147
|
+
aria-label="Fechar modal"
|
|
148
|
+
></button>
|
|
149
|
+
|
|
150
|
+
<div class="pointer-events-none fixed inset-0 z-50 flex items-center justify-center p-4">
|
|
151
|
+
<div class="pointer-events-auto relative max-h-[90vh] max-w-4xl">
|
|
152
|
+
<button
|
|
153
|
+
type="button"
|
|
154
|
+
class="absolute top-3 right-3 rounded-full bg-red-900/50 p-2 text-white hover:bg-black/70"
|
|
155
|
+
onclick={() => (isMaximized = false)}
|
|
156
|
+
aria-label="Fechar"
|
|
157
|
+
>
|
|
158
|
+
<HugeiconsIcon icon={Cancel01Icon} size={20} color="currentColor" strokeWidth={1.5} />
|
|
159
|
+
</button>
|
|
160
|
+
|
|
161
|
+
{#if videoUrl && showVideo}
|
|
162
|
+
<!-- svelte-ignore a11y_media_has_caption -->
|
|
163
|
+
<video src={videoUrl} class="max-h-[90vh] max-w-full rounded-md" controls autoplay playsinline></video>
|
|
164
|
+
{:else if imageUrl}
|
|
165
|
+
<img src={imageUrl} alt={imageUrl} class="max-h-[90vh] max-w-full rounded-md object-contain" />
|
|
166
|
+
{/if}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
imageUrl?: string;
|
|
3
|
+
videoUrl?: string;
|
|
4
|
+
class?: string;
|
|
5
|
+
isImageButtonMaximized?: boolean;
|
|
6
|
+
isVideoButtonMaximized?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const CardThumbnailVideo: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type CardThumbnailVideo = ReturnType<typeof CardThumbnailVideo>;
|
|
10
|
+
export default CardThumbnailVideo;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!-- shared/TruncatableText.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Clamps text to N lines; if it overflows, shows an indicator
|
|
5
|
+
* ("Ler texto completo") positioned absolutely at the end of the
|
|
6
|
+
* text, that opens the full text in a Popover.
|
|
7
|
+
* @component
|
|
8
|
+
*/
|
|
9
|
+
import * as Popover from "../../../ui/popover";
|
|
10
|
+
import { t } from "../../../../i18n";
|
|
11
|
+
|
|
12
|
+
type Props = { text: string; class?: string; lines?: 2 | 3 | 4 };
|
|
13
|
+
let { text, class: className = "", lines = 2 }: Props = $props();
|
|
14
|
+
|
|
15
|
+
// Tailwind precisa de classes literais no código-fonte para as gerar —
|
|
16
|
+
// "line-clamp-{lines}" interpolado nunca é detectado pelo scanner.
|
|
17
|
+
const clampClasses = {
|
|
18
|
+
2: "line-clamp-2",
|
|
19
|
+
3: "line-clamp-3",
|
|
20
|
+
4: "line-clamp-4",
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
let textEl: HTMLParagraphElement | undefined = $state();
|
|
24
|
+
let isTruncated = $state(false);
|
|
25
|
+
|
|
26
|
+
$effect(() => {
|
|
27
|
+
if (!textEl) return;
|
|
28
|
+
const check = () =>
|
|
29
|
+
(isTruncated = textEl!.scrollHeight > textEl!.clientHeight + 1);
|
|
30
|
+
// requestAnimationFrame garante que o layout com o clamp já foi aplicado
|
|
31
|
+
// antes de medirmos — medir no mesmo tick pode dar valores desatualizados.
|
|
32
|
+
requestAnimationFrame(check);
|
|
33
|
+
const ro = new ResizeObserver(check);
|
|
34
|
+
ro.observe(textEl);
|
|
35
|
+
return () => ro.disconnect();
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div class="relative">
|
|
40
|
+
<p bind:this={textEl} class="{clampClasses[lines]} {className}">
|
|
41
|
+
{text}
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
{#if isTruncated}
|
|
45
|
+
<Popover.Root>
|
|
46
|
+
<Popover.Trigger
|
|
47
|
+
class="absolute bottom-0 right-0 bg-background pl-1 text-[11px] font-medium text-primary underline underline-offset-2 cursor-pointer"
|
|
48
|
+
>
|
|
49
|
+
{$t("label.view.full")}
|
|
50
|
+
</Popover.Trigger>
|
|
51
|
+
<Popover.Content>
|
|
52
|
+
<p class="max-w-xs text-justify text-[12px]">{text}</p>
|
|
53
|
+
</Popover.Content>
|
|
54
|
+
</Popover.Root>
|
|
55
|
+
{/if}
|
|
56
|
+
</div>
|