@thorprovider/blocks 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +156 -40
  3. package/package.json +1 -1
  4. package/src/blocks/application/login-forms/login-page.test.tsx +190 -0
  5. package/src/blocks/application/login-forms/login-page.tsx +240 -0
  6. package/src/blocks/application/password-recovery/forgot-password-page-1.tsx +6 -8
  7. package/src/blocks/application/signup-forms/signup-page-1.tsx +127 -129
  8. package/src/blocks/application/verification/verify-1.tsx +2 -2
  9. package/src/blocks/application/viewport-ownership.test.tsx +41 -0
  10. package/src/blocks/e-commerce/category-filters/category-listing-filter-fields.tsx +218 -0
  11. package/src/blocks/e-commerce/category-filters/{category-filter-2.test.tsx → category-listing.test.tsx} +287 -199
  12. package/src/blocks/e-commerce/category-filters/category-listing.tsx +934 -0
  13. package/src/blocks/e-commerce/checkout-forms/checkout-contact-step.tsx +149 -0
  14. package/src/blocks/e-commerce/checkout-forms/{checkout-form-1-country-field.tsx → checkout-country-field.tsx} +10 -8
  15. package/src/blocks/e-commerce/checkout-forms/checkout-order-summary.tsx +230 -0
  16. package/src/blocks/e-commerce/checkout-forms/checkout-payment-step.tsx +100 -0
  17. package/src/blocks/e-commerce/checkout-forms/checkout-progress.tsx +62 -0
  18. package/src/blocks/e-commerce/checkout-forms/checkout-review-step.tsx +59 -0
  19. package/src/blocks/e-commerce/checkout-forms/{checkout-form-1-shipping-step.tsx → checkout-shipping-step.tsx} +65 -41
  20. package/src/blocks/e-commerce/checkout-forms/checkout.test.tsx +478 -0
  21. package/src/blocks/e-commerce/checkout-forms/checkout.tsx +550 -0
  22. package/src/blocks/{marketing/navbars/navbar-4-account-menu.test.tsx → e-commerce/navigation/storefront-navbar-account-menu.test.tsx} +8 -8
  23. package/src/blocks/{marketing/navbars/navbar-4-account-menu.tsx → e-commerce/navigation/storefront-navbar-account-menu.tsx} +3 -3
  24. package/src/blocks/{marketing/navbars/navbar-4-cart-sheet.test.tsx → e-commerce/navigation/storefront-navbar-cart-sheet.test.tsx} +22 -22
  25. package/src/blocks/{marketing/navbars/navbar-4-cart-sheet.tsx → e-commerce/navigation/storefront-navbar-cart-sheet.tsx} +3 -3
  26. package/src/blocks/{marketing/navbars/navbar-4-mobile-nav.tsx → e-commerce/navigation/storefront-navbar-mobile-nav.tsx} +4 -12
  27. package/src/blocks/{marketing/navbars/navbar-4-search-bar.tsx → e-commerce/navigation/storefront-navbar-search-bar.tsx} +3 -3
  28. package/src/blocks/{marketing/navbars/navbar-4.test.tsx → e-commerce/navigation/storefront-navbar.test.tsx} +40 -40
  29. package/src/blocks/{marketing/navbars/navbar-4.tsx → e-commerce/navigation/storefront-navbar.tsx} +17 -17
  30. package/src/blocks/e-commerce/product-list/product-card.tsx +63 -40
  31. package/src/blocks/e-commerce/shopping-carts/shopping-cart.test.tsx +2 -2
  32. package/src/blocks/marketing/footers/footer-section-accessibility.test.tsx +118 -0
  33. package/src/blocks/marketing/footers/footer-section-actions.test.tsx +131 -0
  34. package/src/blocks/marketing/footers/footer-section-data.test.tsx +127 -0
  35. package/src/blocks/marketing/footers/footer-section-native-links.test.tsx +100 -0
  36. package/src/blocks/marketing/footers/footer-section-public-api.test.tsx +11 -0
  37. package/src/blocks/marketing/footers/footer-section.test.tsx +46 -0
  38. package/src/blocks/marketing/footers/footer-section.tsx +532 -0
  39. package/src/blocks/marketing/navbars/navbar-public-api.test.tsx +57 -0
  40. package/src/blocks/marketing/navbars/navbar.mega.test.tsx +149 -0
  41. package/src/blocks/marketing/navbars/navbar.test.tsx +155 -0
  42. package/src/blocks/marketing/navbars/navbar.tsx +735 -0
  43. package/src/blocks/marketing/testimonials/testimonial-section.test.tsx +171 -0
  44. package/src/blocks/marketing/testimonials/testimonial-section.tsx +237 -0
  45. package/src/index.ts +80 -81
  46. package/src/lib/contracts-curated.test.ts +5 -5
  47. package/src/lib/contracts.test.ts +55 -0
  48. package/src/lib/contracts.ts +64 -2
  49. package/tsup.config.ts +1 -1
  50. package/src/blocks/application/login-forms/login-page-1.tsx +0 -246
  51. package/src/blocks/application/login-forms/login-page-2.tsx +0 -207
  52. package/src/blocks/e-commerce/category-filters/category-filter-1.tsx +0 -260
  53. package/src/blocks/e-commerce/category-filters/category-filter-2-filter-panel.tsx +0 -222
  54. package/src/blocks/e-commerce/category-filters/category-filter-2.tsx +0 -921
  55. package/src/blocks/e-commerce/category-filters/category-filter-4-chip-rail.tsx +0 -57
  56. package/src/blocks/e-commerce/category-filters/category-filter-4-drawer.tsx +0 -124
  57. package/src/blocks/e-commerce/category-filters/category-filter-4-fields.tsx +0 -170
  58. package/src/blocks/e-commerce/category-filters/category-filter-4-sidebar.tsx +0 -52
  59. package/src/blocks/e-commerce/category-filters/category-filter-4-sort-sheet.tsx +0 -57
  60. package/src/blocks/e-commerce/category-filters/category-filter-4-state.ts +0 -68
  61. package/src/blocks/e-commerce/category-filters/category-filter-4.tsx +0 -298
  62. package/src/blocks/e-commerce/checkout-forms/card-formatting.test.ts +0 -47
  63. package/src/blocks/e-commerce/checkout-forms/card-formatting.ts +0 -9
  64. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-contact-step.tsx +0 -96
  65. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-order-summary.tsx +0 -252
  66. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-payment-step.tsx +0 -188
  67. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-progress.tsx +0 -36
  68. package/src/blocks/e-commerce/checkout-forms/checkout-form-1.test.tsx +0 -216
  69. package/src/blocks/e-commerce/checkout-forms/checkout-form-1.tsx +0 -338
  70. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-order-summary.tsx +0 -130
  71. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-payment-card.tsx +0 -175
  72. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-shipping-card.tsx +0 -190
  73. package/src/blocks/e-commerce/checkout-forms/checkout-form-2.tsx +0 -312
  74. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-information-step.tsx +0 -91
  75. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-order-summary.tsx +0 -110
  76. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-payment-step.tsx +0 -137
  77. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-progress.tsx +0 -68
  78. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-review-step.tsx +0 -79
  79. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-shipping-step.tsx +0 -172
  80. package/src/blocks/e-commerce/checkout-forms/checkout-form-3.tsx +0 -392
  81. package/src/blocks/marketing/footers/footer-section-1.test.tsx +0 -117
  82. package/src/blocks/marketing/footers/footer-section-1.tsx +0 -178
  83. package/src/blocks/marketing/footers/footer-section-3.tsx +0 -192
  84. package/src/blocks/marketing/footers/footer-section-4.tsx +0 -355
  85. package/src/blocks/marketing/navbars/navbar-1.tsx +0 -267
  86. package/src/blocks/marketing/navbars/navbar-2.tsx +0 -351
  87. package/src/blocks/marketing/navbars/navbar-3.tsx +0 -303
  88. package/src/blocks/marketing/navbars/navbar-4-like-button.tsx +0 -177
  89. package/src/blocks/marketing/navbars/navbar-4-product-grid.tsx +0 -219
  90. package/src/blocks/marketing/testimonials/testimonial-1.tsx +0 -141
  91. package/src/blocks/marketing/testimonials/testimonial-2.tsx +0 -108
@@ -1,141 +0,0 @@
1
- 'use client'
2
-
3
- import * as React from 'react'
4
- import { Star } from 'lucide-react'
5
- import { cn } from '../../../lib/utils'
6
- import { Card, CardContent, CardHeader, CardFooter, CardTitle } from '../../../ui/card'
7
- import {
8
- Carousel,
9
- CarouselContent,
10
- CarouselItem,
11
- CarouselNext,
12
- CarouselPrevious,
13
- type CarouselApi,
14
- } from '../../../ui/carousel'
15
- import { Avatar, AvatarFallback, AvatarImage } from '../../../ui/avatar'
16
- import { Button } from '../../../ui/button'
17
-
18
- export interface Testimonial1Item {
19
- id: string
20
- name: string
21
- role: string
22
- avatar: string
23
- content: string
24
- rating: number
25
- }
26
-
27
- export interface Testimonial1Props {
28
- items: Testimonial1Item[]
29
- title?: string
30
- prevLabel?: string
31
- nextLabel?: string
32
- slideAriaLabel?: string
33
- }
34
-
35
- function RatingStars({ rating }: { rating: number }) {
36
- return (
37
- <div className='flex items-center gap-1'>
38
- {[...Array(5)].map((_, index) => (
39
- <Star
40
- key={index}
41
- className={cn('size-4', index < Math.floor(rating) ? 'fill-foreground' : 'fill-none')}
42
- />
43
- ))}
44
- <span className='text-muted-foreground ms-2 text-sm'>({rating})</span>
45
- </div>
46
- )
47
- }
48
-
49
- export function Testimonial1({
50
- items,
51
- title = 'Lo que dicen nuestros clientes',
52
- prevLabel = 'Anterior',
53
- nextLabel = 'Siguiente',
54
- slideAriaLabel = 'Ir a la diapositiva {n}',
55
- }: Testimonial1Props) {
56
- const [api, setApi] = React.useState<CarouselApi | null>(null)
57
- const [current, setCurrent] = React.useState(0)
58
-
59
- React.useEffect(() => {
60
- if (!api) return
61
-
62
- const onSelect = () => {
63
- setCurrent(api.selectedScrollSnap())
64
- }
65
-
66
- api.on('select', onSelect)
67
- return () => {
68
- api.off('select', onSelect)
69
- }
70
- }, [api])
71
-
72
- return (
73
- <section className='py-12 lg:py-20'>
74
- <div className='mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8'>
75
- <header className='mb-16 text-center'>
76
- <h2 className='text-3xl font-bold text-balance md:text-4xl'>{title}</h2>
77
- </header>
78
-
79
- <Carousel className='w-full' setApi={setApi} opts={{ align: 'start', loop: true }}>
80
- <CarouselContent className='-ml-1'>
81
- {items.map(testimonial => (
82
- <CarouselItem
83
- key={testimonial.id}
84
- className='basis-full px-4 last:pe-0 sm:basis-1/2 lg:basis-1/3'
85
- >
86
- <Card className='h-full overflow-hidden border border-border py-6'>
87
- <CardHeader className='gap-0 px-6'>
88
- <div className='flex items-center gap-4'>
89
- <Avatar className='bg-muted size-12'>
90
- <AvatarImage src={testimonial.avatar || undefined} alt={testimonial.name} className='size-12' />
91
- <AvatarFallback className='bg-card'>{testimonial.name[0]}</AvatarFallback>
92
- </Avatar>
93
- <div>
94
- <CardTitle className='text-foreground font-semibold'>{testimonial.name}</CardTitle>
95
- <p className='text-muted-foreground text-sm'>{testimonial.role}</p>
96
- </div>
97
- </div>
98
- </CardHeader>
99
- <CardContent className='px-6'>
100
- <p className='text-muted-foreground text-base'>{testimonial.content}</p>
101
- </CardContent>
102
- <CardFooter className='bg-transparent border-t-0 px-6 pb-6'>
103
- <RatingStars rating={testimonial.rating} />
104
- </CardFooter>
105
- </Card>
106
- </CarouselItem>
107
- ))}
108
- </CarouselContent>
109
- <CarouselPrevious
110
- variant='outline'
111
- className='hidden cursor-pointer lg:flex'
112
- aria-label={prevLabel}
113
- />
114
- <CarouselNext
115
- variant='outline'
116
- className='hidden cursor-pointer lg:flex'
117
- aria-label={nextLabel}
118
- />
119
- <div className='mt-8 flex items-center justify-center gap-2'>
120
- {items.map((_, index) => (
121
- <Button
122
- variant='ghost'
123
- key={index}
124
- onClick={() => api?.scrollTo(index)}
125
- className={cn(
126
- 'h-9 px-4 py-2',
127
- 'size-2 cursor-pointer rounded-full !p-0 transition-all',
128
- current === index ? 'bg-foreground w-6' : 'bg-muted',
129
- )}
130
- aria-label={slideAriaLabel.replace('{n}', String(index + 1))}
131
- aria-current={current === index ? 'true' : 'false'}
132
- />
133
- ))}
134
- </div>
135
- </Carousel>
136
- </div>
137
- </section>
138
- )
139
- }
140
-
141
- export default Testimonial1
@@ -1,108 +0,0 @@
1
- import { Quote } from 'lucide-react'
2
- import { Card, CardContent, CardHeader } from '../../../ui/card'
3
- import { Avatar, AvatarFallback, AvatarImage } from '../../../ui/avatar'
4
-
5
- export interface Testimonial2Item {
6
- id: string
7
- name: string
8
- role: string
9
- avatar: string
10
- content: string
11
- }
12
-
13
- export interface Testimonial2Props {
14
- items: Testimonial2Item[]
15
- title?: string
16
- description?: string
17
- }
18
-
19
- const bentoGridClasses = [
20
- 'grid grid-rows-[auto_1fr] gap-8 ring-1 ring-foreground/10 sm:p-6 md:col-span-2 lg:col-span-2 lg:row-span-2 shadow-sm',
21
- 'ring-1 ring-foreground/10 md:col-span-2 lg:col-span-2 py-6 shadow-sm',
22
- 'pt-0 ring-1 ring-foreground/10 lg:col-span-1 shadow-sm',
23
- 'pt-0 ring-1 ring-foreground/10 lg:col-span-1 shadow-sm',
24
- ]
25
-
26
- const contentClasses = [
27
- '',
28
- 'h-full px-6',
29
- 'h-full pt-6 px-6',
30
- 'h-full pt-6 px-6',
31
- ]
32
-
33
- const textClasses = [
34
- 'text-xl text-balance',
35
- 'text-base text-balance',
36
- 'text-base text-balance',
37
- 'text-base text-balance',
38
- ]
39
-
40
- function initials(name: string) {
41
- return name
42
- .split(' ')
43
- .map(n => n[0])
44
- .join('')
45
- }
46
-
47
- export function Testimonial2({
48
- items,
49
- title = 'Con la confianza de quienes construyen',
50
- description,
51
- }: Testimonial2Props) {
52
- /** El diseño bento consume exactamente 4 tarjetas: la primera ocupa la celda
53
- * grande (lg:row-span-2) y las tres restantes completan la cuadrícula. */
54
- const bentoItems = items.slice(0, 4)
55
-
56
- return (
57
- <section className='py-12 md:py-16'>
58
- <div className='mx-auto w-full max-w-7xl flex flex-col gap-8 px-4 sm:px-6 lg:px-8 md:gap-16'>
59
- <div className='relative z-10 mx-auto max-w-4xl flex flex-col gap-6 text-center md:gap-12'>
60
- <h2 className='text-4xl font-medium max-lg:text-balance lg:text-5xl'>{title}</h2>
61
- {description && (
62
- <p className='text-muted-foreground mx-auto max-w-2xl max-lg:text-balance'>
63
- {description}
64
- </p>
65
- )}
66
- </div>
67
-
68
- <div className='grid gap-4 md:grid-cols-2 lg:grid-cols-4 lg:grid-rows-2'>
69
- {bentoItems.map((testimonial, index) => (
70
- <Card key={testimonial.id} className={bentoGridClasses[index]}>
71
- {index === 0 && (
72
- <CardHeader className='pb-6'>
73
- <div className='flex items-center justify-start'>
74
- <Quote className='text-muted-foreground/30 size-16 rotate-180' />
75
- </div>
76
- </CardHeader>
77
- )}
78
- <CardContent className={contentClasses[index]}>
79
- <blockquote className='grid h-full grid-rows-[1fr_auto] gap-6'>
80
- <p className={textClasses[index]}>{testimonial.content}</p>
81
-
82
- <div className='grid grid-cols-[auto_1fr] items-center gap-3'>
83
- <Avatar className='bg-muted size-12'>
84
- <AvatarImage
85
- src={testimonial.avatar || undefined}
86
- alt={testimonial.name}
87
- height='400'
88
- width='400'
89
- loading='lazy'
90
- />
91
- <AvatarFallback>{initials(testimonial.name)}</AvatarFallback>
92
- </Avatar>
93
- <div>
94
- <cite className='text-sm font-medium not-italic'>{testimonial.name}</cite>
95
- <span className='text-muted-foreground block text-sm'>{testimonial.role}</span>
96
- </div>
97
- </div>
98
- </blockquote>
99
- </CardContent>
100
- </Card>
101
- ))}
102
- </div>
103
- </div>
104
- </section>
105
- )
106
- }
107
-
108
- export default Testimonial2