@regardio/react 0.4.7 → 0.5.1

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 (202) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -5
  3. package/dist/{components/background-slideshow.js → background-slideshow/index.js} +2 -11
  4. package/dist/{components/blurry-gradient.js → blurry-gradient/index.js} +15 -9
  5. package/dist/{components/carousel.d.ts → carousel/index.d.ts} +17 -9
  6. package/dist/{components/carousel.js → carousel/index.js} +34 -30
  7. package/dist/{components/countdown.js → countdown/index.js} +2 -11
  8. package/dist/{components/generic-error.js → generic-error/index.js} +1 -1
  9. package/dist/grid/index.d.ts +1196 -0
  10. package/dist/grid/index.js +239 -0
  11. package/dist/heading/index.d.ts +24 -0
  12. package/dist/{components/heading.js → heading/index.js} +15 -34
  13. package/dist/highlight/index.d.ts +13 -0
  14. package/dist/{components/highlight.js → highlight/index.js} +9 -17
  15. package/dist/hooks/{use-current-route-data.js → use-current-route-data/index.js} +1 -1
  16. package/dist/hooks/{use-focus-search.js → use-focus-search/index.js} +1 -1
  17. package/dist/hooks/{use-matches-data.js → use-matches-data/index.js} +1 -1
  18. package/dist/hooks/{use-media-query.js → use-media-query/index.js} +1 -1
  19. package/dist/hooks/{use-mobile.js → use-mobile/index.js} +1 -1
  20. package/dist/hooks/use-nonce/index.d.ts +6 -0
  21. package/dist/hooks/use-nonce/index.js +8 -0
  22. package/dist/hooks/{use-orientation.d.ts → use-orientation/index.d.ts} +1 -1
  23. package/dist/hooks/{use-orientation.js → use-orientation/index.js} +1 -1
  24. package/dist/hooks/{use-user.js → use-user/index.js} +1 -1
  25. package/dist/{components/icon-button.js → icon-button/index.js} +1 -1
  26. package/dist/{components/if.js → if/index.js} +1 -1
  27. package/dist/{components/iframe.js → iframe/index.js} +2 -11
  28. package/dist/{components/link.d.ts → link/index.d.ts} +19 -13
  29. package/dist/{components/link.js → link/index.js} +31 -36
  30. package/dist/list/index.d.ts +69 -0
  31. package/dist/list/index.js +65 -0
  32. package/dist/{components/markdown-container.js → markdown-container/index.js} +3 -67
  33. package/dist/{components/password-input.js → password-input/index.js} +2 -11
  34. package/dist/{components/picture.js → picture/index.js} +2 -11
  35. package/dist/{components/protected-email.d.ts → protected-email/index.d.ts} +1 -1
  36. package/dist/{components/protected-email.js → protected-email/index.js} +1 -1
  37. package/dist/text/index.d.ts +20 -0
  38. package/dist/text/index.js +38 -0
  39. package/dist/utils/author/index.d.ts +3 -0
  40. package/dist/utils/author/index.js +33 -0
  41. package/dist/utils/text/index.d.ts +15 -0
  42. package/dist/utils/text/index.js +73 -0
  43. package/package.json +92 -121
  44. package/src/{stories/BackgroundSlideshow.stories.tsx → background-slideshow/background-slideshow.stories.tsx} +1 -1
  45. package/src/{components → background-slideshow}/background-slideshow.tsx +3 -1
  46. package/src/background-slideshow/index.ts +2 -0
  47. package/src/{stories/BlurryGradient.stories.tsx → blurry-gradient/blurry-gradient.stories.tsx} +1 -1
  48. package/src/{components → blurry-gradient}/blurry-gradient.tsx +14 -8
  49. package/src/blurry-gradient/index.ts +2 -0
  50. package/src/carousel/carousel-content.tsx +16 -0
  51. package/src/carousel/carousel-item.tsx +23 -0
  52. package/src/carousel/carousel-next.tsx +22 -0
  53. package/src/carousel/carousel-previous.tsx +22 -0
  54. package/src/{components/carousel.tsx → carousel/carousel-root.tsx} +8 -78
  55. package/src/carousel/carousel.stories.tsx +89 -0
  56. package/src/carousel/index.parts.ts +5 -0
  57. package/src/carousel/index.ts +4 -0
  58. package/src/{stories/Countdown.stories.tsx → countdown/countdown.stories.tsx} +1 -1
  59. package/src/{components → countdown}/countdown.tsx +3 -7
  60. package/src/countdown/index.ts +1 -0
  61. package/src/{stories/GenericError.stories.tsx → generic-error/generic-error.stories.tsx} +1 -1
  62. package/src/{components → generic-error}/generic-error.tsx +2 -0
  63. package/src/generic-error/index.ts +2 -0
  64. package/src/grid/grid-item.tsx +188 -0
  65. package/src/grid/grid-root.tsx +72 -0
  66. package/src/grid/grid.stories.tsx +236 -0
  67. package/src/grid/index.parts.ts +2 -0
  68. package/src/grid/index.ts +5 -0
  69. package/src/{stories/Heading.stories.tsx → heading/heading.stories.tsx} +1 -1
  70. package/src/{components → heading}/heading.tsx +17 -25
  71. package/src/heading/index.ts +2 -0
  72. package/src/{stories/Highlight.stories.tsx → highlight/highlight.stories.tsx} +1 -1
  73. package/src/{components → highlight}/highlight.tsx +13 -9
  74. package/src/highlight/index.ts +2 -0
  75. package/src/hooks/use-current-route-data/index.ts +1 -0
  76. package/src/hooks/use-focus-search/index.ts +1 -0
  77. package/src/hooks/use-matches-data/index.ts +1 -0
  78. package/src/hooks/use-media-query/index.ts +1 -0
  79. package/src/hooks/use-mobile/index.ts +1 -0
  80. package/src/hooks/use-nonce/index.ts +1 -0
  81. package/src/hooks/use-orientation/index.ts +1 -0
  82. package/src/hooks/use-user/index.ts +2 -0
  83. package/src/{stories/IconButton.stories.tsx → icon-button/icon-button.stories.tsx} +1 -1
  84. package/src/icon-button/index.ts +2 -0
  85. package/src/{stories/If.stories.tsx → if/if.stories.tsx} +1 -1
  86. package/src/if/index.ts +1 -0
  87. package/src/{stories/Iframe.stories.tsx → iframe/iframe.stories.tsx} +1 -1
  88. package/src/{components → iframe}/iframe.tsx +1 -1
  89. package/src/iframe/index.ts +2 -0
  90. package/src/link/index.ts +2 -0
  91. package/src/{stories/Link.stories.tsx → link/link.stories.tsx} +1 -1
  92. package/src/{components → link}/link.tsx +39 -28
  93. package/src/list/index.parts.ts +2 -0
  94. package/src/list/index.ts +4 -0
  95. package/src/list/list-item.tsx +63 -0
  96. package/src/list/list-root-context.ts +21 -0
  97. package/src/list/list-root.tsx +81 -0
  98. package/src/list/list.css +32 -0
  99. package/src/list/list.stories.tsx +119 -0
  100. package/src/list/list.test.tsx +168 -0
  101. package/src/markdown-container/index.ts +2 -0
  102. package/src/{stories/MarkdownContainer.stories.tsx → markdown-container/markdown-container.stories.tsx} +1 -1
  103. package/src/{components → markdown-container}/markdown-container.tsx +3 -1
  104. package/src/password-input/index.ts +2 -0
  105. package/src/{stories/PasswordInput.stories.tsx → password-input/password-input.stories.tsx} +1 -1
  106. package/src/{components → password-input}/password-input.tsx +4 -4
  107. package/src/picture/index.ts +2 -0
  108. package/src/{stories/Picture.stories.tsx → picture/picture.stories.tsx} +1 -1
  109. package/src/{components → picture}/picture.tsx +2 -4
  110. package/src/protected-email/index.ts +2 -0
  111. package/src/{stories/ProtectedEmail.stories.tsx → protected-email/protected-email.stories.tsx} +1 -1
  112. package/src/{components → protected-email}/protected-email.tsx +3 -1
  113. package/src/tailwind.css +10 -0
  114. package/src/text/index.ts +2 -0
  115. package/src/{stories/Text.stories.tsx → text/text.stories.tsx} +1 -1
  116. package/src/text/text.tsx +46 -0
  117. package/src/utils/author/author.tsx +36 -0
  118. package/src/utils/author/index.ts +1 -0
  119. package/src/utils/text/index.ts +1 -0
  120. package/src/utils/text/text.tsx +103 -0
  121. package/dist/components/box.d.ts +0 -20
  122. package/dist/components/box.js +0 -50
  123. package/dist/components/definition-list.d.ts +0 -43
  124. package/dist/components/definition-list.js +0 -89
  125. package/dist/components/heading.d.ts +0 -27
  126. package/dist/components/highlight.d.ts +0 -19
  127. package/dist/components/item.d.ts +0 -70
  128. package/dist/components/item.js +0 -512
  129. package/dist/components/leaflet-map.d.ts +0 -34
  130. package/dist/components/leaflet-map.js +0 -201
  131. package/dist/components/list-item.d.ts +0 -19
  132. package/dist/components/list-item.js +0 -37
  133. package/dist/components/maptiler-map.d.ts +0 -27
  134. package/dist/components/maptiler-map.js +0 -129
  135. package/dist/components/text.d.ts +0 -20
  136. package/dist/components/text.js +0 -45
  137. package/dist/components/unordered-list.d.ts +0 -19
  138. package/dist/components/unordered-list.js +0 -39
  139. package/dist/hooks/use-nonce.d.ts +0 -12
  140. package/dist/hooks/use-nonce.js +0 -13
  141. package/dist/utils/author.d.ts +0 -9
  142. package/dist/utils/author.js +0 -55
  143. package/dist/utils/cn.d.ts +0 -9
  144. package/dist/utils/cn.js +0 -14
  145. package/dist/utils/is-route-active.d.ts +0 -19
  146. package/dist/utils/is-route-active.js +0 -56
  147. package/dist/utils/text.d.ts +0 -24
  148. package/dist/utils/text.js +0 -127
  149. package/src/components/box.tsx +0 -45
  150. package/src/components/definition-list.tsx +0 -90
  151. package/src/components/item.tsx +0 -340
  152. package/src/components/leaflet-map.tsx +0 -294
  153. package/src/components/link.test.tsx +0 -387
  154. package/src/components/list-item.tsx +0 -30
  155. package/src/components/maptiler-map.tsx +0 -181
  156. package/src/components/text.tsx +0 -38
  157. package/src/components/unordered-list.tsx +0 -32
  158. package/src/hooks/use-nonce.test.ts +0 -35
  159. package/src/stories/Box.stories.tsx +0 -83
  160. package/src/stories/Carousel.stories.tsx +0 -95
  161. package/src/stories/DefinitionList.stories.tsx +0 -51
  162. package/src/stories/Item.stories.tsx +0 -79
  163. package/src/stories/ListItem.stories.tsx +0 -38
  164. package/src/stories/UnorderedList.stories.tsx +0 -73
  165. package/src/styles/tailwind.css +0 -7
  166. package/src/test-setup.ts +0 -1
  167. package/src/utils/author.test.ts +0 -54
  168. package/src/utils/author.tsx +0 -73
  169. package/src/utils/cn.test.ts +0 -48
  170. package/src/utils/cn.ts +0 -14
  171. package/src/utils/is-route-active.test.ts +0 -80
  172. package/src/utils/is-route-active.ts +0 -100
  173. package/src/utils/text.test.ts +0 -152
  174. package/src/utils/text.tsx +0 -209
  175. package/src/vite-env.d.ts +0 -1
  176. /package/dist/{components/background-slideshow.d.ts → background-slideshow/index.d.ts} +0 -0
  177. /package/dist/{components/blurry-gradient.d.ts → blurry-gradient/index.d.ts} +0 -0
  178. /package/dist/{components/countdown.d.ts → countdown/index.d.ts} +0 -0
  179. /package/dist/{components/generic-error.d.ts → generic-error/index.d.ts} +0 -0
  180. /package/dist/hooks/{use-current-route-data.d.ts → use-current-route-data/index.d.ts} +0 -0
  181. /package/dist/hooks/{use-focus-search.d.ts → use-focus-search/index.d.ts} +0 -0
  182. /package/dist/hooks/{use-matches-data.d.ts → use-matches-data/index.d.ts} +0 -0
  183. /package/dist/hooks/{use-media-query.d.ts → use-media-query/index.d.ts} +0 -0
  184. /package/dist/hooks/{use-mobile.d.ts → use-mobile/index.d.ts} +0 -0
  185. /package/dist/hooks/{use-user.d.ts → use-user/index.d.ts} +0 -0
  186. /package/dist/{components/icon-button.d.ts → icon-button/index.d.ts} +0 -0
  187. /package/dist/{components/if.d.ts → if/index.d.ts} +0 -0
  188. /package/dist/{components/iframe.d.ts → iframe/index.d.ts} +0 -0
  189. /package/dist/{components/markdown-container.d.ts → markdown-container/index.d.ts} +0 -0
  190. /package/dist/{components/password-input.d.ts → password-input/index.d.ts} +0 -0
  191. /package/dist/{components/picture.d.ts → picture/index.d.ts} +0 -0
  192. /package/src/hooks/{use-current-route-data.ts → use-current-route-data/use-current-route-data.ts} +0 -0
  193. /package/src/hooks/{use-focus-search.ts → use-focus-search/use-focus-search.ts} +0 -0
  194. /package/src/hooks/{use-matches-data.ts → use-matches-data/use-matches-data.ts} +0 -0
  195. /package/src/hooks/{use-media-query.ts → use-media-query/use-media-query.ts} +0 -0
  196. /package/src/hooks/{use-mobile.ts → use-mobile/use-mobile.ts} +0 -0
  197. /package/src/hooks/{use-nonce.ts → use-nonce/use-nonce.ts} +0 -0
  198. /package/src/hooks/{use-orientation.ts → use-orientation/use-orientation.ts} +0 -0
  199. /package/src/hooks/{use-user.tsx → use-user/use-user.tsx} +0 -0
  200. /package/src/{components → icon-button}/icon-button.tsx +0 -0
  201. /package/src/{components → if}/if.tsx +0 -0
  202. /package/src/{styles/storybook.css → storybook.css} +0 -0
@@ -0,0 +1,168 @@
1
+ import { cleanup, render, screen } from '@testing-library/react';
2
+ import { afterEach, describe, expect, it } from 'vitest';
3
+ import { List } from './index';
4
+
5
+ afterEach(() => {
6
+ cleanup();
7
+ });
8
+
9
+ describe('List.Root', () => {
10
+ it('renders as ul by default', () => {
11
+ render(
12
+ <List.Root data-testid="list">
13
+ <List.Item>Item 1</List.Item>
14
+ </List.Root>,
15
+ );
16
+
17
+ const list = screen.getByTestId('list');
18
+ expect(list.tagName).toBe('UL');
19
+ });
20
+
21
+ it('renders as ol when specified', () => {
22
+ render(
23
+ <List.Root
24
+ data-testid="list"
25
+ render="ol"
26
+ >
27
+ <List.Item>Item 1</List.Item>
28
+ </List.Root>,
29
+ );
30
+
31
+ const list = screen.getByTestId('list');
32
+ expect(list.tagName).toBe('OL');
33
+ });
34
+
35
+ it('renders as dl when specified', () => {
36
+ render(
37
+ <List.Root
38
+ data-testid="list"
39
+ render="dl"
40
+ >
41
+ <List.Item render="dt">Term</List.Item>
42
+ <List.Item render="dd">Definition</List.Item>
43
+ </List.Root>,
44
+ );
45
+
46
+ const list = screen.getByTestId('list');
47
+ expect(list.tagName).toBe('DL');
48
+ });
49
+
50
+ it('renders as div when specified', () => {
51
+ render(
52
+ <List.Root
53
+ data-testid="list"
54
+ render="div"
55
+ >
56
+ <List.Item render="div">Item 1</List.Item>
57
+ </List.Root>,
58
+ );
59
+
60
+ const list = screen.getByTestId('list');
61
+ expect(list.tagName).toBe('DIV');
62
+ });
63
+
64
+ it('passes className to root element', () => {
65
+ render(
66
+ <List.Root
67
+ className="custom-class"
68
+ data-testid="list"
69
+ >
70
+ <List.Item>Item 1</List.Item>
71
+ </List.Root>,
72
+ );
73
+
74
+ const list = screen.getByTestId('list');
75
+ expect(list.className).toBe('custom-class');
76
+ });
77
+ });
78
+
79
+ describe('List.Item', () => {
80
+ it('renders as li by default', () => {
81
+ render(
82
+ <List.Root>
83
+ <List.Item data-testid="item">Item 1</List.Item>
84
+ </List.Root>,
85
+ );
86
+
87
+ const item = screen.getByTestId('item');
88
+ expect(item.tagName).toBe('LI');
89
+ });
90
+
91
+ it('renders as dd when parent is dl', () => {
92
+ render(
93
+ <List.Root render="dl">
94
+ <List.Item data-testid="item">Definition</List.Item>
95
+ </List.Root>,
96
+ );
97
+
98
+ const item = screen.getByTestId('item');
99
+ expect(item.tagName).toBe('DD');
100
+ });
101
+
102
+ it('allows explicit render override', () => {
103
+ render(
104
+ <List.Root render="dl">
105
+ <List.Item
106
+ data-testid="item"
107
+ render="dt"
108
+ >
109
+ Term
110
+ </List.Item>
111
+ </List.Root>,
112
+ );
113
+
114
+ const item = screen.getByTestId('item');
115
+ expect(item.tagName).toBe('DT');
116
+ });
117
+
118
+ it('applies defaultItemClassName from context', () => {
119
+ render(
120
+ <List.Root defaultItemClassName="default-item-class">
121
+ <List.Item data-testid="item">Item 1</List.Item>
122
+ </List.Root>,
123
+ );
124
+
125
+ const item = screen.getByTestId('item');
126
+ expect(item.className).toBe('default-item-class');
127
+ });
128
+
129
+ it('merges defaultItemClassName with item className', () => {
130
+ render(
131
+ <List.Root defaultItemClassName="default-class">
132
+ <List.Item
133
+ className="custom-class"
134
+ data-testid="item"
135
+ >
136
+ Item 1
137
+ </List.Item>
138
+ </List.Root>,
139
+ );
140
+
141
+ const item = screen.getByTestId('item');
142
+ expect(item.className).toBe('default-class custom-class');
143
+ });
144
+
145
+ it('passes className when no defaultItemClassName', () => {
146
+ render(
147
+ <List.Root>
148
+ <List.Item
149
+ className="custom-class"
150
+ data-testid="item"
151
+ >
152
+ Item 1
153
+ </List.Item>
154
+ </List.Root>,
155
+ );
156
+
157
+ const item = screen.getByTestId('item');
158
+ expect(item.className).toBe('custom-class');
159
+ });
160
+
161
+ it('works without List.Root context', () => {
162
+ render(<List.Item data-testid="item">Standalone Item</List.Item>);
163
+
164
+ const item = screen.getByTestId('item');
165
+ expect(item.tagName).toBe('LI');
166
+ expect(item.textContent).toBe('Standalone Item');
167
+ });
168
+ });
@@ -0,0 +1,2 @@
1
+ export type { MarkdownContainerProps, MarkdownOverrides, MDXComponent } from './markdown-container';
2
+ export { MarkdownContainer, transformLink } from './markdown-container';
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { MarkdownContainer } from '../components/markdown-container';
2
+ import { MarkdownContainer } from './markdown-container';
3
3
 
4
4
  const meta: Meta<typeof MarkdownContainer> = {
5
5
  component: MarkdownContainer,
@@ -1,7 +1,9 @@
1
+ 'use client';
2
+
1
3
  import { MDXProvider } from '@mdx-js/react';
4
+ import { cn } from '@regardio/tailwind/utils';
2
5
  import Markdown, { type MarkdownToJSX } from 'markdown-to-jsx';
3
6
  import type React from 'react';
4
- import { cn } from '../utils/cn';
5
7
  import { replaceSpecialChars } from '../utils/text';
6
8
 
7
9
  const doubleNewlineRegex = /\n\n+/;
@@ -0,0 +1,2 @@
1
+ export type { InputProps, PasswordInputProps } from './password-input';
2
+ export { PasswordInput } from './password-input';
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { PasswordInput } from '../components/password-input';
2
+ import { PasswordInput } from './password-input';
3
3
 
4
4
  const meta: Meta<typeof PasswordInput> = {
5
5
  component: PasswordInput,
@@ -1,7 +1,9 @@
1
+ 'use client';
2
+
1
3
  import { Button } from '@base-ui/react/button';
2
4
  import { Input } from '@base-ui/react/input';
5
+ import { cn } from '@regardio/tailwind/utils';
3
6
  import { useState } from 'react';
4
- import { cn } from '../utils/cn';
5
7
 
6
8
  export interface InputProps extends React.ComponentPropsWithoutRef<typeof Input> {}
7
9
 
@@ -9,7 +11,7 @@ export interface PasswordInputProps extends InputProps {
9
11
  className?: string;
10
12
  }
11
13
 
12
- const PasswordInput = ({ className, ...props }: PasswordInputProps) => {
14
+ export const PasswordInput = ({ className, ...props }: PasswordInputProps) => {
13
15
  const [showPassword, setShowPassword] = useState(false);
14
16
 
15
17
  const togglePasswordVisibility = () => {
@@ -45,5 +47,3 @@ const PasswordInput = ({ className, ...props }: PasswordInputProps) => {
45
47
  </div>
46
48
  );
47
49
  };
48
-
49
- export { PasswordInput };
@@ -0,0 +1,2 @@
1
+ export type { ImageFormat, PictureProps } from './picture';
2
+ export { Picture, screenSizeVariants } from './picture';
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Picture } from '../components/picture';
2
+ import { Picture } from './picture';
3
3
 
4
4
  const meta: Meta<typeof Picture> = {
5
5
  component: Picture,
@@ -1,5 +1,5 @@
1
+ import { cn } from '@regardio/tailwind/utils';
1
2
  import type React from 'react';
2
- import { cn } from '../utils/cn';
3
3
 
4
4
  // Define screen size variants for responsive images
5
5
  // Define screen size variants for responsive images (used in srcset generation)
@@ -40,7 +40,7 @@ export interface PictureProps {
40
40
  * @param placeholder - Placeholder to replace in baseUrl (default: '{format}')
41
41
  * @param sizes - Custom sizes attribute
42
42
  */
43
- const Picture: React.FC<PictureProps> = ({
43
+ export const Picture: React.FC<PictureProps> = ({
44
44
  alt,
45
45
  baseUrl,
46
46
  className,
@@ -103,5 +103,3 @@ const Picture: React.FC<PictureProps> = ({
103
103
  </picture>
104
104
  );
105
105
  };
106
-
107
- export { Picture };
@@ -0,0 +1,2 @@
1
+ export type { ProtectedEmailProps } from './protected-email';
2
+ export { ProtectedEmail } from './protected-email';
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { ProtectedEmail } from '../components/protected-email';
2
+ import { ProtectedEmail } from './protected-email';
3
3
 
4
4
  const meta: Meta<typeof ProtectedEmail> = {
5
5
  component: ProtectedEmail,
@@ -1,6 +1,8 @@
1
+ 'use client';
2
+
1
3
  import { useEffect, useState } from 'react';
2
4
 
3
- interface ProtectedEmailProps {
5
+ export interface ProtectedEmailProps {
4
6
  username: string;
5
7
  domain: string;
6
8
  text?: string;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tailwind CSS Source Scanning for @regardio/react
3
+ *
4
+ * This file enables Tailwind to detect utility classes used in @regardio/react components.
5
+ * Import this in your app's main CSS file to ensure component styles are included:
6
+ *
7
+ * @import "@regardio/react/tailwind.css";
8
+ */
9
+
10
+ @source "../";
@@ -0,0 +1,2 @@
1
+ export type { TextProps } from './text';
2
+ export { Text } from './text';
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Text } from '../components/text';
2
+ import { Text } from './text';
3
3
 
4
4
  const meta: Meta<typeof Text> = {
5
5
  component: Text,
@@ -0,0 +1,46 @@
1
+ import { tv } from '@regardio/tailwind/utils';
2
+ import type { ComponentProps } from 'react';
3
+
4
+ const themeColorVariants = {
5
+ primary: [],
6
+ } as const;
7
+
8
+ const textVariants = {
9
+ code: ['font-light', 'font-monospace'],
10
+ primary: [],
11
+ subtitle: ['text-lg'],
12
+ } as const;
13
+
14
+ const text = tv({
15
+ base: ['relative', 'block'],
16
+ defaultVariants: {
17
+ themeColor: 'primary',
18
+ variant: 'primary',
19
+ },
20
+ variants: {
21
+ themeColor: themeColorVariants,
22
+ variant: textVariants,
23
+ },
24
+ });
25
+
26
+ export type TextThemeColor = keyof typeof themeColorVariants;
27
+ export type TextVariant = keyof typeof textVariants;
28
+
29
+ export interface TextProps extends ComponentProps<'p'> {
30
+ themeColor?: TextThemeColor;
31
+ variant?: TextVariant;
32
+ }
33
+
34
+ export const Text = ({ children, className, variant, themeColor }: TextProps) => {
35
+ return (
36
+ <div
37
+ className={text({
38
+ className,
39
+ themeColor,
40
+ variant,
41
+ })}
42
+ >
43
+ {children}
44
+ </div>
45
+ );
46
+ };
@@ -0,0 +1,36 @@
1
+ import { parseAuthorString } from '@regardio/js/text';
2
+
3
+ export function generateLinkFromAuthorString(input: string): React.ReactNode {
4
+ const match = parseAuthorString(input);
5
+
6
+ if (match.name) {
7
+ // Generate email link if email is present
8
+ if (match.email) {
9
+ return (
10
+ <a
11
+ className={'u-email p-name'}
12
+ href={`mailto:${match.email}`}
13
+ >
14
+ {match.name}
15
+ </a>
16
+ );
17
+ }
18
+
19
+ // Generate URL link if URL is present (including relative URLs that start with a slash)
20
+ if (match.url && (match.url.startsWith('/') || match.url.startsWith('http'))) {
21
+ return (
22
+ <a
23
+ className={'u-url p-name'}
24
+ href={match.url}
25
+ >
26
+ {match.name}
27
+ </a>
28
+ );
29
+ }
30
+
31
+ // Return plain name with microformat class if only name is present
32
+ return <span className={'p-name'}>{match.name}</span>;
33
+ }
34
+
35
+ return;
36
+ }
@@ -0,0 +1 @@
1
+ export { generateLinkFromAuthorString } from './author';
@@ -0,0 +1 @@
1
+ export { lowerCaseSzett, replaceSpecialChars, shy, wrapSentences } from './text';
@@ -0,0 +1,103 @@
1
+ import { replaceShyInString, splitIntoSentences, typographicQuotes } from '@regardio/js/text';
2
+ import React, { cloneElement, isValidElement, type ReactElement, type ReactNode } from 'react';
3
+
4
+ export const lowerCaseSzett = (text: ReactNode | string, _returnType?: 'string'): ReactNode => {
5
+ // Helper function to process strings
6
+ const processString = (str: string): ReactNode | string => {
7
+ const parts = str.split(/(ß)/g);
8
+ return parts.map((part, index) =>
9
+ part === 'ß' ? (
10
+ <span
11
+ className="lowercase"
12
+ key={index.toString()}
13
+ >
14
+ {part}
15
+ </span>
16
+ ) : (
17
+ part
18
+ ),
19
+ );
20
+ };
21
+
22
+ // Handle strings
23
+ if (typeof text === 'string') {
24
+ return processString(text);
25
+ }
26
+
27
+ // Handle valid React elements with correct type assertion
28
+ if (isValidElement(text)) {
29
+ const element = text as ReactElement<{ children?: ReactNode }>;
30
+ const { children, ...props } = element.props;
31
+
32
+ return cloneElement(element, {
33
+ ...props,
34
+ children: lowerCaseSzett(children),
35
+ });
36
+ }
37
+
38
+ // Handle arrays
39
+ if (Array.isArray(text)) {
40
+ return text.map((child, index) => (
41
+ <React.Fragment key={index.toString()}>{lowerCaseSzett(child as ReactNode)}</React.Fragment>
42
+ ));
43
+ }
44
+
45
+ // Return other types as is
46
+ return text;
47
+ };
48
+
49
+ // Recursive function to traverse ReactNode and replace &shy; in string nodes
50
+ function replaceShyInReactNode(node: ReactNode): ReactNode {
51
+ if (typeof node === 'string') {
52
+ // Replace soft hyphen (&shy;) with an empty string or custom logic
53
+ return node.replace(/\u00AD/g, '');
54
+ }
55
+
56
+ if (isValidElement(node)) {
57
+ const element = node as ReactElement<{ children?: ReactNode }>;
58
+ const { children, ...props } = element.props;
59
+
60
+ return cloneElement(element, {
61
+ ...props,
62
+ children: replaceShyInReactNode(children),
63
+ });
64
+ }
65
+
66
+ if (Array.isArray(node)) {
67
+ return node.map((child, index) => (
68
+ <React.Fragment key={index.toString()}>
69
+ {replaceShyInReactNode(child as ReactNode)}
70
+ </React.Fragment>
71
+ ));
72
+ }
73
+
74
+ return node;
75
+ }
76
+
77
+ export function shy(input: string | ReactNode | null): string | ReactNode | null {
78
+ if (input === null) {
79
+ return null;
80
+ }
81
+
82
+ if (typeof input === 'string') {
83
+ return replaceShyInString(input);
84
+ }
85
+
86
+ return replaceShyInReactNode(input);
87
+ }
88
+
89
+ /**
90
+ * Replace special characters in text: typographic quotes and soft hyphens.
91
+ * This is a React-aware version that handles ReactNode trees.
92
+ */
93
+ export function replaceSpecialChars(text: string, locale: string): string | ReactNode | null {
94
+ return shy(typographicQuotes(text, locale));
95
+ }
96
+
97
+ /**
98
+ * Wrap sentences in span elements
99
+ */
100
+ export function wrapSentences(text: string): ReactNode {
101
+ const sentences = splitIntoSentences(text);
102
+ return sentences.map((sentence, index) => <span key={index.toString()}>{sentence} </span>);
103
+ }
@@ -1,20 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as cva from 'cva';
3
- import { VariantProps } from 'cva';
4
- import { ComponentProps, ElementType } from 'react';
5
-
6
- declare const box: (props?: ({
7
- variant?: "grid" | "main" | "primary" | "aside" | "code" | "container" | "flex" | "section" | undefined;
8
- } & ({
9
- class?: cva.ClassValue;
10
- className?: never;
11
- } | {
12
- class?: never;
13
- className?: cva.ClassValue;
14
- })) | undefined) => string;
15
- interface BoxProps extends ComponentProps<'div'>, VariantProps<typeof box> {
16
- as?: ElementType;
17
- }
18
- declare const Box: ({ as: Component, children, className, variant, ...props }: BoxProps) => react_jsx_runtime.JSX.Element;
19
-
20
- export { Box, type BoxProps };
@@ -1,50 +0,0 @@
1
- import { defineConfig } from 'cva';
2
- import { twMerge } from 'fluid-tailwindcss/tailwind-merge';
3
- import { jsx } from 'react/jsx-runtime';
4
-
5
- // src/utils/cn.ts
6
- var { cva, compose } = defineConfig({
7
- hooks: {
8
- onComplete: (className) => {
9
- return twMerge(className);
10
- }
11
- }
12
- });
13
- var box = cva({
14
- defaultVariants: {
15
- variant: "primary"
16
- },
17
- variants: {
18
- variant: {
19
- aside: [],
20
- code: ["font-monospace", "overflow-scroll"],
21
- container: ["u-container"],
22
- flex: ["flex"],
23
- grid: ["u-grid"],
24
- main: [],
25
- primary: [],
26
- section: ["u-grid", "content-start"]
27
- }
28
- }
29
- });
30
- var Box = ({
31
- as: Component = "div",
32
- children,
33
- className,
34
- variant,
35
- ...props
36
- }) => {
37
- return /* @__PURE__ */ jsx(
38
- Component,
39
- {
40
- className: box({
41
- className,
42
- variant
43
- }),
44
- ...props,
45
- children
46
- }
47
- );
48
- };
49
-
50
- export { Box };
@@ -1,43 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as cva from 'cva';
3
- import { VariantProps } from 'cva';
4
- import { ComponentProps } from 'react';
5
-
6
- declare const dl: (props?: ({
7
- variant?: "primary" | "unstyled" | undefined;
8
- } & ({
9
- class?: cva.ClassValue;
10
- className?: never;
11
- } | {
12
- class?: never;
13
- className?: cva.ClassValue;
14
- })) | undefined) => string;
15
- declare const dt: (props?: ({
16
- variant?: "primary" | undefined;
17
- } & ({
18
- class?: cva.ClassValue;
19
- className?: never;
20
- } | {
21
- class?: never;
22
- className?: cva.ClassValue;
23
- })) | undefined) => string;
24
- declare const dd: (props?: ({
25
- variant?: "primary" | undefined;
26
- } & ({
27
- class?: cva.ClassValue;
28
- className?: never;
29
- } | {
30
- class?: never;
31
- className?: cva.ClassValue;
32
- })) | undefined) => string;
33
- interface DefinitionListProps extends ComponentProps<'dl'>, VariantProps<typeof dl> {
34
- }
35
- interface DtProps extends ComponentProps<'dt'>, VariantProps<typeof dt> {
36
- }
37
- interface DdProps extends ComponentProps<'dd'>, VariantProps<typeof dd> {
38
- }
39
- declare const DefinitionList: (props: DefinitionListProps) => react_jsx_runtime.JSX.Element;
40
- declare const Dt: (props: DtProps) => react_jsx_runtime.JSX.Element;
41
- declare const Dd: (props: DdProps) => react_jsx_runtime.JSX.Element;
42
-
43
- export { Dd, type DdProps, DefinitionList, type DefinitionListProps, Dt, type DtProps };