@regardio/react 0.5.5 → 0.6.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 (182) hide show
  1. package/dist/background-slideshow/index.d.mts +36 -0
  2. package/dist/background-slideshow/index.mjs +110 -0
  3. package/dist/blurry-gradient/index.d.mts +17 -0
  4. package/dist/blurry-gradient/index.mjs +93 -0
  5. package/dist/button/index.d.mts +2 -0
  6. package/dist/button/index.mjs +3 -0
  7. package/dist/button-BiSQpBbc.mjs +129 -0
  8. package/dist/carousel/index.d.mts +40 -0
  9. package/dist/carousel/index.mjs +141 -0
  10. package/dist/checkbox/index.d.mts +37 -0
  11. package/dist/checkbox/index.mjs +70 -0
  12. package/dist/checkbox-group/index.d.mts +17 -0
  13. package/dist/checkbox-group/index.mjs +29 -0
  14. package/dist/chunk-BTpB_u-K.mjs +18 -0
  15. package/dist/countdown/index.d.mts +6 -0
  16. package/dist/countdown/index.mjs +58 -0
  17. package/dist/field/index.d.mts +66 -0
  18. package/dist/field/index.mjs +115 -0
  19. package/dist/fieldset/index.d.mts +33 -0
  20. package/dist/fieldset/index.mjs +61 -0
  21. package/dist/form/index.d.mts +22 -0
  22. package/dist/form/index.mjs +31 -0
  23. package/dist/generic-error/{index.d.ts → index.d.mts} +22 -18
  24. package/dist/generic-error/index.mjs +57 -0
  25. package/dist/grid/index.d.mts +1197 -0
  26. package/dist/grid/index.mjs +221 -0
  27. package/dist/heading/index.d.mts +31 -0
  28. package/dist/heading/index.mjs +29 -0
  29. package/dist/highlight/index.d.mts +18 -0
  30. package/dist/highlight/index.mjs +35 -0
  31. package/dist/hooks/{use-current-route-data.d.ts → use-current-route-data.d.mts} +3 -2
  32. package/dist/hooks/use-current-route-data.mjs +20 -0
  33. package/dist/hooks/{use-focus-search.d.ts → use-focus-search.d.mts} +4 -3
  34. package/dist/hooks/use-focus-search.mjs +21 -0
  35. package/dist/hooks/{use-matches-data.d.ts → use-matches-data.d.mts} +3 -2
  36. package/dist/hooks/use-matches-data.mjs +21 -0
  37. package/dist/hooks/{use-media-query.d.ts → use-media-query.d.mts} +3 -2
  38. package/dist/hooks/use-media-query.mjs +26 -0
  39. package/dist/hooks/use-mobile.d.mts +4 -0
  40. package/dist/hooks/use-mobile.mjs +20 -0
  41. package/dist/hooks/use-nonce.d.mts +8 -0
  42. package/dist/hooks/use-nonce.mjs +13 -0
  43. package/dist/hooks/{use-orientation.d.ts → use-orientation.d.mts} +3 -2
  44. package/dist/hooks/use-orientation.mjs +30 -0
  45. package/dist/hooks/use-user.d.mts +55 -0
  46. package/dist/hooks/use-user.mjs +39 -0
  47. package/dist/icon-button/index.d.mts +29 -0
  48. package/dist/icon-button/index.mjs +36 -0
  49. package/dist/if/index.d.mts +15 -0
  50. package/dist/if/index.mjs +21 -0
  51. package/dist/iframe/index.d.mts +11 -0
  52. package/dist/iframe/index.mjs +15 -0
  53. package/dist/index-Bm-tWhsb.d.mts +30 -0
  54. package/dist/index-YT2CkvL6.d.mts +36 -0
  55. package/dist/input/index.d.mts +2 -0
  56. package/dist/input/index.mjs +3 -0
  57. package/dist/input-CtR6aRVi.mjs +73 -0
  58. package/dist/link/index.d.mts +73 -0
  59. package/dist/link/index.mjs +129 -0
  60. package/dist/list/index.d.mts +71 -0
  61. package/dist/list/index.mjs +54 -0
  62. package/dist/markdown-container/index.d.mts +23 -0
  63. package/dist/markdown-container/index.mjs +71 -0
  64. package/dist/password-input/index.d.mts +24 -0
  65. package/dist/password-input/index.mjs +92 -0
  66. package/dist/picture/{index.d.ts → index.d.mts} +21 -20
  67. package/dist/picture/index.mjs +3 -0
  68. package/dist/picture-DkX3W5zl.mjs +69 -0
  69. package/dist/protected-email/{index.d.ts → index.d.mts} +14 -8
  70. package/dist/protected-email/index.mjs +37 -0
  71. package/dist/radio/index.d.mts +37 -0
  72. package/dist/radio/index.mjs +72 -0
  73. package/dist/radio-group/index.d.mts +17 -0
  74. package/dist/radio-group/index.mjs +29 -0
  75. package/dist/slider/index.d.mts +85 -0
  76. package/dist/slider/index.mjs +133 -0
  77. package/dist/switch/index.d.mts +38 -0
  78. package/dist/switch/index.mjs +87 -0
  79. package/dist/text/index.d.mts +26 -0
  80. package/dist/text/index.mjs +32 -0
  81. package/dist/text-CPlUND-Z.mjs +58 -0
  82. package/dist/toggle/index.d.mts +59 -0
  83. package/dist/toggle/index.mjs +82 -0
  84. package/dist/utils/author/index.d.mts +4 -0
  85. package/dist/utils/author/index.mjs +26 -0
  86. package/dist/utils/text/{index.d.ts → index.d.mts} +4 -3
  87. package/dist/utils/text/index.mjs +3 -0
  88. package/package.json +17 -129
  89. package/src/button/button.stories.tsx +161 -0
  90. package/src/button/button.test.tsx +73 -0
  91. package/src/button/button.tsx +112 -0
  92. package/src/button/index.ts +2 -0
  93. package/src/carousel/carousel-next.tsx +2 -2
  94. package/src/carousel/carousel-previous.tsx +2 -2
  95. package/src/checkbox/checkbox.stories.tsx +118 -0
  96. package/src/checkbox/checkbox.tsx +91 -0
  97. package/src/checkbox/index.ts +2 -0
  98. package/src/checkbox-group/checkbox-group.tsx +40 -0
  99. package/src/checkbox-group/index.ts +2 -0
  100. package/src/field/field.stories.tsx +105 -0
  101. package/src/field/field.test.tsx +61 -0
  102. package/src/field/field.tsx +165 -0
  103. package/src/field/index.ts +12 -0
  104. package/src/fieldset/fieldset.stories.tsx +204 -0
  105. package/src/fieldset/fieldset.test.tsx +63 -0
  106. package/src/fieldset/fieldset.tsx +75 -0
  107. package/src/fieldset/index.ts +7 -0
  108. package/src/form/form.stories.tsx +230 -0
  109. package/src/form/form.test.tsx +68 -0
  110. package/src/form/form.tsx +38 -0
  111. package/src/form/index.ts +2 -0
  112. package/src/icon-button/icon-button.stories.tsx +128 -7
  113. package/src/icon-button/icon-button.test.tsx +152 -0
  114. package/src/icon-button/icon-button.tsx +43 -9
  115. package/src/input/index.ts +2 -0
  116. package/src/input/input.stories.tsx +151 -0
  117. package/src/input/input.test.tsx +65 -0
  118. package/src/input/input.tsx +113 -0
  119. package/src/link/link.test.tsx +169 -0
  120. package/src/password-input/index.ts +1 -1
  121. package/src/password-input/password-input.tsx +104 -27
  122. package/src/radio/index.ts +2 -0
  123. package/src/radio/radio.tsx +92 -0
  124. package/src/radio-group/index.ts +2 -0
  125. package/src/radio-group/radio-group.tsx +36 -0
  126. package/src/slider/index.ts +18 -0
  127. package/src/slider/slider.tsx +179 -0
  128. package/src/switch/index.ts +2 -0
  129. package/src/switch/switch.stories.tsx +118 -0
  130. package/src/switch/switch.tsx +101 -0
  131. package/src/toggle/index.ts +2 -0
  132. package/src/toggle/toggle.stories.tsx +232 -0
  133. package/src/toggle/toggle.test.tsx +149 -0
  134. package/src/toggle/toggle.tsx +88 -0
  135. package/src/utils/text/text.test.tsx +110 -0
  136. package/dist/background-slideshow/index.d.ts +0 -24
  137. package/dist/background-slideshow/index.js +0 -165
  138. package/dist/blurry-gradient/index.d.ts +0 -16
  139. package/dist/blurry-gradient/index.js +0 -128
  140. package/dist/carousel/index.d.ts +0 -36
  141. package/dist/carousel/index.js +0 -171
  142. package/dist/countdown/index.d.ts +0 -5
  143. package/dist/countdown/index.js +0 -73
  144. package/dist/generic-error/index.js +0 -47
  145. package/dist/grid/index.d.ts +0 -1196
  146. package/dist/grid/index.js +0 -239
  147. package/dist/heading/index.d.ts +0 -24
  148. package/dist/heading/index.js +0 -99
  149. package/dist/highlight/index.d.ts +0 -13
  150. package/dist/highlight/index.js +0 -59
  151. package/dist/hooks/use-current-route-data.js +0 -16
  152. package/dist/hooks/use-focus-search.js +0 -19
  153. package/dist/hooks/use-matches-data.js +0 -15
  154. package/dist/hooks/use-media-query.js +0 -20
  155. package/dist/hooks/use-mobile.d.ts +0 -3
  156. package/dist/hooks/use-mobile.js +0 -19
  157. package/dist/hooks/use-nonce.d.ts +0 -7
  158. package/dist/hooks/use-nonce.js +0 -8
  159. package/dist/hooks/use-orientation.js +0 -29
  160. package/dist/hooks/use-user.d.ts +0 -50
  161. package/dist/hooks/use-user.js +0 -25
  162. package/dist/icon-button/index.d.ts +0 -9
  163. package/dist/icon-button/index.js +0 -17
  164. package/dist/if/index.d.ts +0 -10
  165. package/dist/if/index.js +0 -24
  166. package/dist/iframe/index.d.ts +0 -10
  167. package/dist/iframe/index.js +0 -17
  168. package/dist/link/index.d.ts +0 -55
  169. package/dist/link/index.js +0 -195
  170. package/dist/list/index.d.ts +0 -69
  171. package/dist/list/index.js +0 -65
  172. package/dist/markdown-container/index.d.ts +0 -22
  173. package/dist/markdown-container/index.js +0 -128
  174. package/dist/password-input/index.d.ts +0 -11
  175. package/dist/password-input/index.js +0 -46
  176. package/dist/picture/index.js +0 -68
  177. package/dist/protected-email/index.js +0 -30
  178. package/dist/text/index.d.ts +0 -20
  179. package/dist/text/index.js +0 -38
  180. package/dist/utils/author/index.d.ts +0 -3
  181. package/dist/utils/author/index.js +0 -33
  182. package/dist/utils/text/index.js +0 -73
@@ -0,0 +1,149 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { Toggle } from './toggle';
4
+
5
+ const TestIcon = () => (
6
+ <svg
7
+ data-testid="test-icon"
8
+ height="16"
9
+ viewBox="0 0 16 16"
10
+ width="16"
11
+ >
12
+ <circle
13
+ cx="8"
14
+ cy="8"
15
+ r="6"
16
+ />
17
+ </svg>
18
+ );
19
+
20
+ describe('Toggle', () => {
21
+ it('renders with children', () => {
22
+ render(
23
+ <Toggle>
24
+ <TestIcon />
25
+ </Toggle>,
26
+ );
27
+ expect(screen.getByTestId('test-icon')).toBeInTheDocument();
28
+ });
29
+
30
+ it('applies variant styles', () => {
31
+ render(
32
+ <Toggle
33
+ data-testid="variant-toggle"
34
+ variant="ghost"
35
+ >
36
+ <TestIcon />
37
+ </Toggle>,
38
+ );
39
+ const toggle = screen.getByTestId('variant-toggle');
40
+ expect(toggle).toHaveClass('bg-transparent', 'text-gray-700');
41
+ });
42
+
43
+ it('applies size styles', () => {
44
+ render(
45
+ <Toggle
46
+ data-testid="size-toggle"
47
+ size="lg"
48
+ >
49
+ <TestIcon />
50
+ </Toggle>,
51
+ );
52
+ const toggle = screen.getByTestId('size-toggle');
53
+ expect(toggle).toHaveClass('h-12', 'w-12', 'p-3');
54
+ });
55
+
56
+ it('handles pressed state', () => {
57
+ render(
58
+ <Toggle
59
+ data-testid="pressed-toggle"
60
+ defaultPressed
61
+ >
62
+ <TestIcon />
63
+ </Toggle>,
64
+ );
65
+ const toggle = screen.getByTestId('pressed-toggle');
66
+ expect(toggle).toHaveAttribute('data-pressed');
67
+ });
68
+
69
+ it('handles controlled pressed state', () => {
70
+ render(
71
+ <Toggle
72
+ data-testid="controlled-toggle"
73
+ pressed
74
+ >
75
+ <TestIcon />
76
+ </Toggle>,
77
+ );
78
+ const toggle = screen.getByTestId('controlled-toggle');
79
+ expect(toggle).toHaveAttribute('data-pressed');
80
+ });
81
+
82
+ it('handles disabled state', () => {
83
+ render(
84
+ <Toggle
85
+ data-testid="disabled-toggle"
86
+ disabled
87
+ >
88
+ <TestIcon />
89
+ </Toggle>,
90
+ );
91
+ const toggle = screen.getByTestId('disabled-toggle');
92
+ expect(toggle).toBeDisabled();
93
+ expect(toggle).toHaveClass('disabled:opacity-50');
94
+ });
95
+
96
+ it('applies custom className', () => {
97
+ render(
98
+ <Toggle
99
+ aria-label="Custom toggle"
100
+ className="custom-toggle"
101
+ >
102
+ <TestIcon />
103
+ </Toggle>,
104
+ );
105
+ const toggle = screen.getByRole('button', { name: 'Custom toggle' });
106
+ expect(toggle).toHaveClass('custom-toggle');
107
+ });
108
+
109
+ it('sets title attribute', () => {
110
+ render(
111
+ <Toggle
112
+ aria-label="Toggle"
113
+ title="Toggle setting"
114
+ >
115
+ <TestIcon />
116
+ </Toggle>,
117
+ );
118
+ const toggle = screen.getByRole('button', { name: 'Toggle' });
119
+ expect(toggle).toHaveAttribute('title', 'Toggle setting');
120
+ });
121
+
122
+ it('passes through other props', () => {
123
+ render(
124
+ <Toggle
125
+ aria-label="Custom toggle"
126
+ data-testid="custom-toggle"
127
+ >
128
+ <TestIcon />
129
+ </Toggle>,
130
+ );
131
+ const toggle = screen.getByTestId('custom-toggle');
132
+ expect(toggle).toHaveAttribute('aria-label', 'Custom toggle');
133
+ });
134
+
135
+ it('calls onPressedChange when clicked', () => {
136
+ const onPressedChange = vi.fn();
137
+ render(
138
+ <Toggle
139
+ aria-label="Test toggle"
140
+ onPressedChange={onPressedChange}
141
+ >
142
+ <TestIcon />
143
+ </Toggle>,
144
+ );
145
+ const toggle = screen.getByRole('button', { name: 'Test toggle' });
146
+ toggle.click();
147
+ expect(onPressedChange).toHaveBeenCalledWith(true, expect.any(Object));
148
+ });
149
+ });
@@ -0,0 +1,88 @@
1
+ import { Toggle as BaseUIToggle } from '@base-ui/react/toggle';
2
+ import { tv } from '@regardio/tailwind/utils';
3
+ import type { ComponentProps, ReactNode } from 'react';
4
+
5
+ const toggle = tv({
6
+ base: [
7
+ 'inline-flex',
8
+ 'items-center',
9
+ 'justify-center',
10
+ 'rounded-md',
11
+ 'text-sm',
12
+ 'font-medium',
13
+ 'transition-colors',
14
+ 'duration-200',
15
+ 'focus:outline-none',
16
+ 'focus:ring-2',
17
+ 'focus:ring-blue-500',
18
+ 'focus:ring-offset-2',
19
+ 'disabled:pointer-events-none',
20
+ 'disabled:opacity-50',
21
+ ],
22
+ defaultVariants: {
23
+ size: 'md',
24
+ variant: 'outline',
25
+ },
26
+ variants: {
27
+ size: {
28
+ lg: ['h-12', 'w-12', 'p-3'],
29
+ md: ['h-10', 'w-10', 'p-2'],
30
+ sm: ['h-8', 'w-8', 'p-1'],
31
+ },
32
+ variant: {
33
+ default: [],
34
+ ghost: [
35
+ 'bg-transparent',
36
+ 'text-gray-700',
37
+ 'hover:bg-gray-100',
38
+ 'hover:text-gray-900',
39
+ 'data-[pressed]:bg-gray-200',
40
+ 'data-[pressed]:text-gray-900',
41
+ ],
42
+ outline: [
43
+ 'border',
44
+ 'border-gray-300',
45
+ 'bg-white',
46
+ 'text-gray-700',
47
+ 'hover:bg-gray-50',
48
+ 'hover:text-gray-900',
49
+ 'data-[pressed]:bg-gray-100',
50
+ 'data-[pressed]:text-gray-900',
51
+ ],
52
+ },
53
+ },
54
+ });
55
+
56
+ export type ToggleVariant = keyof typeof toggle.variants.variant;
57
+ export type ToggleSize = keyof typeof toggle.variants.size;
58
+
59
+ export interface ToggleProps extends Omit<ComponentProps<typeof BaseUIToggle>, 'className'> {
60
+ className?: string;
61
+ variant?: ToggleVariant;
62
+ size?: ToggleSize;
63
+ children?: ReactNode;
64
+ title?: string;
65
+ }
66
+
67
+ export const Toggle = ({
68
+ className,
69
+ variant = 'outline',
70
+ size = 'md',
71
+ title,
72
+ children,
73
+ ...props
74
+ }: ToggleProps) => {
75
+ return (
76
+ <BaseUIToggle
77
+ className={toggle({
78
+ className,
79
+ size,
80
+ variant,
81
+ })}
82
+ title={title}
83
+ {...props}
84
+ >
85
+ {children}
86
+ </BaseUIToggle>
87
+ );
88
+ };
@@ -0,0 +1,110 @@
1
+ import { isValidElement, type ReactNode } from 'react';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ import { lowerCaseSzett, replaceSpecialChars, shy, wrapSentences } from './text';
5
+
6
+ describe('lowerCaseSzett', () => {
7
+ it('wraps ß in lowercase span for strings', () => {
8
+ const result = lowerCaseSzett('Straße') as ReactNode[];
9
+ expect(Array.isArray(result)).toBe(true);
10
+ expect(result).toHaveLength(3);
11
+ expect(result[0]).toBe('Stra');
12
+ expect(isValidElement(result[1])).toBe(true);
13
+ expect((result[1] as { props: { className: string } }).props.className).toBe('lowercase');
14
+ expect((result[1] as { props: { children: string } }).props.children).toBe('ß');
15
+ expect(result[2]).toBe('e');
16
+ });
17
+
18
+ it('handles strings without ß', () => {
19
+ const result = lowerCaseSzett('Hello') as ReactNode[];
20
+ expect(Array.isArray(result)).toBe(true);
21
+ expect(result).toEqual(['Hello']);
22
+ });
23
+
24
+ it('handles React elements with children containing ß', () => {
25
+ const element = <div>Straße</div>;
26
+ const result = lowerCaseSzett(element);
27
+ expect(isValidElement(result)).toBe(true);
28
+ const children = (result as { props: { children: ReactNode[] } }).props.children;
29
+ expect(Array.isArray(children)).toBe(true);
30
+ });
31
+
32
+ it('handles nested React elements', () => {
33
+ const element = (
34
+ <div>
35
+ <span>Große Straße</span>
36
+ </div>
37
+ );
38
+ const result = lowerCaseSzett(element);
39
+ expect(isValidElement(result)).toBe(true);
40
+ });
41
+
42
+ it('handles arrays of children', () => {
43
+ const result = lowerCaseSzett(['Straße', ' und ', 'Größe']);
44
+ expect(Array.isArray(result)).toBe(true);
45
+ });
46
+
47
+ it('returns non-string/element values as-is', () => {
48
+ expect(lowerCaseSzett(null)).toBeNull();
49
+ expect(lowerCaseSzett(undefined)).toBeUndefined();
50
+ expect(lowerCaseSzett(123 as unknown as string)).toBe(123);
51
+ });
52
+ });
53
+
54
+ describe('shy', () => {
55
+ it('returns null for null input', () => {
56
+ expect(shy(null)).toBeNull();
57
+ });
58
+
59
+ it('replaces soft hyphens in strings', () => {
60
+ const input = 'Weihnachts\u00ADspende';
61
+ const result = shy(input);
62
+ expect(typeof result).toBe('string');
63
+ expect(result).toContain('\u00AD');
64
+ });
65
+
66
+ it('handles React elements with soft hyphens', () => {
67
+ const element = <div>Weihnachts­spende</div>;
68
+ const result = shy(element);
69
+ expect(isValidElement(result)).toBe(true);
70
+ const children = (result as { props: { children: string } }).props.children;
71
+ expect(children).toBe('Weihnachtsspende');
72
+ });
73
+
74
+ it('handles nested React elements with soft hyphens', () => {
75
+ const element = (
76
+ <div>
77
+ <span>Weihnachts­spende</span>
78
+ </div>
79
+ );
80
+ const result = shy(element);
81
+ expect(isValidElement(result)).toBe(true);
82
+ });
83
+
84
+ it('handles arrays in React nodes', () => {
85
+ const element = <div>{['Weihnachts­spende', ' ', 'Test­wort']}</div>;
86
+ const result = shy(element);
87
+ expect(isValidElement(result)).toBe(true);
88
+ });
89
+ });
90
+
91
+ describe('replaceSpecialChars', () => {
92
+ it('applies typographic quotes and shy', () => {
93
+ const result = replaceSpecialChars('"Hello"', 'de');
94
+ expect(typeof result).toBe('string');
95
+ expect(result).toBe('\u201EHello\u201D');
96
+ });
97
+ });
98
+
99
+ describe('wrapSentences', () => {
100
+ it('wraps each sentence in a span', () => {
101
+ const result = wrapSentences('First sentence. Second sentence.');
102
+ expect(Array.isArray(result)).toBe(true);
103
+ expect((result as ReactNode[]).length).toBeGreaterThanOrEqual(2);
104
+ });
105
+
106
+ it('handles single sentence', () => {
107
+ const result = wrapSentences('Just one sentence.');
108
+ expect(Array.isArray(result)).toBe(true);
109
+ });
110
+ });
@@ -1,24 +0,0 @@
1
- import { ReactElement } from 'react';
2
-
3
- type ImageData = {
4
- at: Record<string, string>;
5
- fn: string;
6
- hu: number;
7
- id: string;
8
- po: boolean;
9
- };
10
- interface BackgroundSlideshowProps {
11
- baseUrl: string;
12
- className?: string;
13
- imgClassName?: string;
14
- locale: string;
15
- pictureClassName?: string;
16
- images: ImageData[];
17
- filter?: (image: ImageData) => boolean;
18
- slideshow?: boolean;
19
- slideshowInterval?: number;
20
- transitionDuration?: number;
21
- }
22
- declare function BackgroundSlideshow({ baseUrl, className, imgClassName, locale, pictureClassName, images, slideshow, slideshowInterval, transitionDuration, filter, }: BackgroundSlideshowProps): ReactElement;
23
-
24
- export { BackgroundSlideshow, type BackgroundSlideshowProps, type ImageData };
@@ -1,165 +0,0 @@
1
- import { useMemo, useState, useRef, useEffect } from 'react';
2
- import { cn } from '@regardio/tailwind/utils';
3
- import { jsx, jsxs } from 'react/jsx-runtime';
4
-
5
- // src/background-slideshow/background-slideshow.tsx
6
- var Picture = ({
7
- alt,
8
- baseUrl,
9
- className,
10
- formats,
11
- imgClassName,
12
- placeholder = "{format}",
13
- sizes = "(max-width: 480px) 480px, (max-width: 768px) 600px, (max-width: 1200px) 1024px, 1920px"
14
- }) => {
15
- const imageFormats = formats || [
16
- { size: "480x360", width: 480 },
17
- { size: "600x600", width: 600 },
18
- { size: "1024x768", width: 1024 },
19
- { size: "1920x1440", width: 1920 }
20
- ];
21
- if (imageFormats.length === 0) {
22
- return null;
23
- }
24
- const isSimpleImage = imageFormats.length === 1 && imageFormats[0]?.size === "" || !baseUrl.includes(placeholder);
25
- if (isSimpleImage) {
26
- return /* @__PURE__ */ jsx(
27
- "img",
28
- {
29
- alt,
30
- className: cn(className, imgClassName),
31
- src: baseUrl
32
- }
33
- );
34
- }
35
- const srcSet = imageFormats.map(({ size, width }) => {
36
- const url = baseUrl.replace(placeholder, size);
37
- return `${url} ${width}w`;
38
- }).join(", ");
39
- const defaultFormat = imageFormats[0];
40
- const defaultSrc = defaultFormat ? baseUrl.replace(placeholder, defaultFormat.size) : baseUrl;
41
- return /* @__PURE__ */ jsxs("picture", { className, children: [
42
- /* @__PURE__ */ jsx(
43
- "source",
44
- {
45
- sizes,
46
- srcSet
47
- }
48
- ),
49
- /* @__PURE__ */ jsx(
50
- "img",
51
- {
52
- alt,
53
- className: cn(imgClassName),
54
- src: defaultSrc
55
- }
56
- )
57
- ] });
58
- };
59
- function BackgroundSlideshow({
60
- baseUrl,
61
- className = "",
62
- imgClassName = "",
63
- locale,
64
- pictureClassName = "",
65
- images = [],
66
- slideshow = true,
67
- slideshowInterval = 6e3,
68
- transitionDuration = 6e3,
69
- filter
70
- }) {
71
- const validatedImages = useMemo(() => {
72
- return images.map((img) => {
73
- if (typeof img !== "object" || img === null) return null;
74
- return {
75
- at: img.at || {},
76
- fn: img.fn || "",
77
- hu: img.hu || 0,
78
- id: img.id || "",
79
- po: img.po || false
80
- };
81
- }).filter((img) => img !== null);
82
- }, [images]);
83
- const availableImages = useMemo(() => {
84
- const filtered = filter ? validatedImages.filter(filter) : validatedImages;
85
- return filtered.length > 0 ? filtered : validatedImages;
86
- }, [validatedImages, filter]);
87
- const firstImage = availableImages[0] || null;
88
- const [slideshowStarted, setSlideshowStarted] = useState(false);
89
- const [overlayImage, setOverlayImage] = useState(null);
90
- const [overlayVisible, setOverlayVisible] = useState(false);
91
- const [currentIndex, setCurrentIndex] = useState(0);
92
- const timerRef = useRef(void 0);
93
- const isTransitioning = useRef(false);
94
- useEffect(() => {
95
- if (!slideshow || availableImages.length <= 1) return;
96
- const timeout = window.setTimeout(() => {
97
- setSlideshowStarted(true);
98
- }, slideshowInterval);
99
- return () => window.clearTimeout(timeout);
100
- }, [slideshow, availableImages.length, slideshowInterval]);
101
- useEffect(() => {
102
- if (!slideshowStarted || availableImages.length <= 1) return;
103
- if (timerRef.current) window.clearTimeout(timerRef.current);
104
- const cycleImages = () => {
105
- if (isTransitioning.current) return;
106
- isTransitioning.current = true;
107
- const nextIdx = (currentIndex + 1) % availableImages.length;
108
- const nextImage = availableImages[nextIdx];
109
- if (!nextImage) {
110
- isTransitioning.current = false;
111
- return;
112
- }
113
- setOverlayImage(nextImage);
114
- window.setTimeout(() => {
115
- setOverlayVisible(true);
116
- window.setTimeout(() => {
117
- setCurrentIndex(nextIdx);
118
- setOverlayVisible(false);
119
- isTransitioning.current = false;
120
- timerRef.current = window.setTimeout(cycleImages, slideshowInterval);
121
- }, transitionDuration);
122
- }, 100);
123
- };
124
- cycleImages();
125
- return () => {
126
- if (timerRef.current) window.clearTimeout(timerRef.current);
127
- };
128
- }, [slideshowStarted, availableImages, currentIndex, slideshowInterval, transitionDuration]);
129
- if (validatedImages.length === 0 || !firstImage) {
130
- return /* @__PURE__ */ jsx("div", { className });
131
- }
132
- const baseImage = availableImages[currentIndex] || firstImage;
133
- return /* @__PURE__ */ jsxs("div", { className, children: [
134
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 w-full h-full", children: /* @__PURE__ */ jsx(
135
- Picture,
136
- {
137
- alt: baseImage.at[locale] || "",
138
- baseUrl: baseUrl.replace("{id}", baseImage.id).replace("{fn}", baseImage.fn),
139
- className: pictureClassName,
140
- formats: [{ size: "", width: 1080 }],
141
- imgClassName,
142
- placeholder: ""
143
- }
144
- ) }),
145
- overlayImage && /* @__PURE__ */ jsx(
146
- "div",
147
- {
148
- className: `absolute inset-0 w-full h-full transition-opacity ${overlayVisible ? "opacity-100" : "opacity-0"} ${transitionDuration <= 3e3 ? "duration-3000" : transitionDuration <= 4e3 ? "duration-4000" : transitionDuration <= 5e3 ? "duration-5000" : "duration-6000"}`,
149
- children: /* @__PURE__ */ jsx(
150
- Picture,
151
- {
152
- alt: overlayImage.at[locale] || "",
153
- baseUrl: baseUrl.replace("{id}", overlayImage.id).replace("{fn}", overlayImage.fn),
154
- className: pictureClassName,
155
- formats: [{ size: "", width: 1080 }],
156
- imgClassName,
157
- placeholder: ""
158
- }
159
- )
160
- }
161
- )
162
- ] });
163
- }
164
-
165
- export { BackgroundSlideshow };
@@ -1,16 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { SVGProps } from 'react';
3
-
4
- interface BlurryGradientProps extends SVGProps<SVGSVGElement> {
5
- primaryColor: string;
6
- secondaryColor: string;
7
- neutralColor: string;
8
- /**
9
- * Accessible description for the gradient (for screen readers)
10
- * @default 'Decorative blurry gradient'
11
- */
12
- description?: string;
13
- }
14
- declare const BlurryGradient: (props: BlurryGradientProps) => react_jsx_runtime.JSX.Element;
15
-
16
- export { BlurryGradient, type BlurryGradientProps };
@@ -1,128 +0,0 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
-
3
- // src/blurry-gradient/blurry-gradient.tsx
4
- var BlurryGradient = (props) => {
5
- const {
6
- description = "Decorative blurry gradient",
7
- neutralColor,
8
- primaryColor,
9
- secondaryColor,
10
- ...svgProps
11
- } = props;
12
- const titleId = "blurryGradientTitle";
13
- return /* @__PURE__ */ jsxs(
14
- "svg",
15
- {
16
- "aria-labelledby": titleId,
17
- preserveAspectRatio: "none",
18
- role: "img",
19
- viewBox: "0 0 1000 1000",
20
- ...svgProps,
21
- children: [
22
- /* @__PURE__ */ jsx("title", { id: titleId, children: description }),
23
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
24
- "filter",
25
- {
26
- colorInterpolationFilters: "sRGB",
27
- filterUnits: "userSpaceOnUse",
28
- height: "120%",
29
- width: "120%",
30
- x: "-10%",
31
- y: "-10%",
32
- children: [
33
- /* @__PURE__ */ jsx(
34
- "feFlood",
35
- {
36
- floodOpacity: "0",
37
- result: "BackgroundImageFix"
38
- }
39
- ),
40
- /* @__PURE__ */ jsx(
41
- "feBlend",
42
- {
43
- in: "SourceGraphic",
44
- in2: "BackgroundImageFix",
45
- mode: "normal",
46
- result: "shape"
47
- }
48
- ),
49
- /* @__PURE__ */ jsx(
50
- "feGaussianBlur",
51
- {
52
- result: "effect1_foregroundBlur",
53
- stdDeviation: "161"
54
- }
55
- )
56
- ]
57
- }
58
- ) }),
59
- /* @__PURE__ */ jsx(
60
- "rect",
61
- {
62
- fill: primaryColor,
63
- height: "1000",
64
- width: "1000"
65
- }
66
- ),
67
- /* @__PURE__ */ jsxs("g", { filter: "url(#blurryGradient)", children: [
68
- /* @__PURE__ */ jsx(
69
- "circle",
70
- {
71
- cx: "730",
72
- cy: "559",
73
- fill: secondaryColor,
74
- r: "357"
75
- }
76
- ),
77
- /* @__PURE__ */ jsx(
78
- "circle",
79
- {
80
- cx: "316",
81
- cy: "248",
82
- fill: primaryColor,
83
- r: "357"
84
- }
85
- ),
86
- /* @__PURE__ */ jsx(
87
- "circle",
88
- {
89
- cx: "509",
90
- cy: "410",
91
- fill: neutralColor,
92
- r: "357"
93
- }
94
- ),
95
- /* @__PURE__ */ jsx(
96
- "circle",
97
- {
98
- cx: "633",
99
- cy: "232",
100
- fill: secondaryColor,
101
- r: "357"
102
- }
103
- ),
104
- /* @__PURE__ */ jsx(
105
- "circle",
106
- {
107
- cx: "156",
108
- cy: "82",
109
- fill: primaryColor,
110
- r: "357"
111
- }
112
- ),
113
- /* @__PURE__ */ jsx(
114
- "circle",
115
- {
116
- cx: "150",
117
- cy: "389",
118
- fill: neutralColor,
119
- r: "357"
120
- }
121
- )
122
- ] })
123
- ]
124
- }
125
- );
126
- };
127
-
128
- export { BlurryGradient };