@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.
- package/LICENSE +1 -1
- package/README.md +5 -5
- package/dist/{components/background-slideshow.js → background-slideshow/index.js} +2 -11
- package/dist/{components/blurry-gradient.js → blurry-gradient/index.js} +15 -9
- package/dist/{components/carousel.d.ts → carousel/index.d.ts} +17 -9
- package/dist/{components/carousel.js → carousel/index.js} +34 -30
- package/dist/{components/countdown.js → countdown/index.js} +2 -11
- package/dist/{components/generic-error.js → generic-error/index.js} +1 -1
- package/dist/grid/index.d.ts +1196 -0
- package/dist/grid/index.js +239 -0
- package/dist/heading/index.d.ts +24 -0
- package/dist/{components/heading.js → heading/index.js} +15 -34
- package/dist/highlight/index.d.ts +13 -0
- package/dist/{components/highlight.js → highlight/index.js} +9 -17
- package/dist/hooks/{use-current-route-data.js → use-current-route-data/index.js} +1 -1
- package/dist/hooks/{use-focus-search.js → use-focus-search/index.js} +1 -1
- package/dist/hooks/{use-matches-data.js → use-matches-data/index.js} +1 -1
- package/dist/hooks/{use-media-query.js → use-media-query/index.js} +1 -1
- package/dist/hooks/{use-mobile.js → use-mobile/index.js} +1 -1
- package/dist/hooks/use-nonce/index.d.ts +6 -0
- package/dist/hooks/use-nonce/index.js +8 -0
- package/dist/hooks/{use-orientation.d.ts → use-orientation/index.d.ts} +1 -1
- package/dist/hooks/{use-orientation.js → use-orientation/index.js} +1 -1
- package/dist/hooks/{use-user.js → use-user/index.js} +1 -1
- package/dist/{components/icon-button.js → icon-button/index.js} +1 -1
- package/dist/{components/if.js → if/index.js} +1 -1
- package/dist/{components/iframe.js → iframe/index.js} +2 -11
- package/dist/{components/link.d.ts → link/index.d.ts} +19 -13
- package/dist/{components/link.js → link/index.js} +31 -36
- package/dist/list/index.d.ts +69 -0
- package/dist/list/index.js +65 -0
- package/dist/{components/markdown-container.js → markdown-container/index.js} +3 -67
- package/dist/{components/password-input.js → password-input/index.js} +2 -11
- package/dist/{components/picture.js → picture/index.js} +2 -11
- package/dist/{components/protected-email.d.ts → protected-email/index.d.ts} +1 -1
- package/dist/{components/protected-email.js → protected-email/index.js} +1 -1
- package/dist/text/index.d.ts +20 -0
- package/dist/text/index.js +38 -0
- package/dist/utils/author/index.d.ts +3 -0
- package/dist/utils/author/index.js +33 -0
- package/dist/utils/text/index.d.ts +15 -0
- package/dist/utils/text/index.js +73 -0
- package/package.json +92 -121
- package/src/{stories/BackgroundSlideshow.stories.tsx → background-slideshow/background-slideshow.stories.tsx} +1 -1
- package/src/{components → background-slideshow}/background-slideshow.tsx +3 -1
- package/src/background-slideshow/index.ts +2 -0
- package/src/{stories/BlurryGradient.stories.tsx → blurry-gradient/blurry-gradient.stories.tsx} +1 -1
- package/src/{components → blurry-gradient}/blurry-gradient.tsx +14 -8
- package/src/blurry-gradient/index.ts +2 -0
- package/src/carousel/carousel-content.tsx +16 -0
- package/src/carousel/carousel-item.tsx +23 -0
- package/src/carousel/carousel-next.tsx +22 -0
- package/src/carousel/carousel-previous.tsx +22 -0
- package/src/{components/carousel.tsx → carousel/carousel-root.tsx} +8 -78
- package/src/carousel/carousel.stories.tsx +89 -0
- package/src/carousel/index.parts.ts +5 -0
- package/src/carousel/index.ts +4 -0
- package/src/{stories/Countdown.stories.tsx → countdown/countdown.stories.tsx} +1 -1
- package/src/{components → countdown}/countdown.tsx +3 -7
- package/src/countdown/index.ts +1 -0
- package/src/{stories/GenericError.stories.tsx → generic-error/generic-error.stories.tsx} +1 -1
- package/src/{components → generic-error}/generic-error.tsx +2 -0
- package/src/generic-error/index.ts +2 -0
- package/src/grid/grid-item.tsx +188 -0
- package/src/grid/grid-root.tsx +72 -0
- package/src/grid/grid.stories.tsx +236 -0
- package/src/grid/index.parts.ts +2 -0
- package/src/grid/index.ts +5 -0
- package/src/{stories/Heading.stories.tsx → heading/heading.stories.tsx} +1 -1
- package/src/{components → heading}/heading.tsx +17 -25
- package/src/heading/index.ts +2 -0
- package/src/{stories/Highlight.stories.tsx → highlight/highlight.stories.tsx} +1 -1
- package/src/{components → highlight}/highlight.tsx +13 -9
- package/src/highlight/index.ts +2 -0
- package/src/hooks/use-current-route-data/index.ts +1 -0
- package/src/hooks/use-focus-search/index.ts +1 -0
- package/src/hooks/use-matches-data/index.ts +1 -0
- package/src/hooks/use-media-query/index.ts +1 -0
- package/src/hooks/use-mobile/index.ts +1 -0
- package/src/hooks/use-nonce/index.ts +1 -0
- package/src/hooks/use-orientation/index.ts +1 -0
- package/src/hooks/use-user/index.ts +2 -0
- package/src/{stories/IconButton.stories.tsx → icon-button/icon-button.stories.tsx} +1 -1
- package/src/icon-button/index.ts +2 -0
- package/src/{stories/If.stories.tsx → if/if.stories.tsx} +1 -1
- package/src/if/index.ts +1 -0
- package/src/{stories/Iframe.stories.tsx → iframe/iframe.stories.tsx} +1 -1
- package/src/{components → iframe}/iframe.tsx +1 -1
- package/src/iframe/index.ts +2 -0
- package/src/link/index.ts +2 -0
- package/src/{stories/Link.stories.tsx → link/link.stories.tsx} +1 -1
- package/src/{components → link}/link.tsx +39 -28
- package/src/list/index.parts.ts +2 -0
- package/src/list/index.ts +4 -0
- package/src/list/list-item.tsx +63 -0
- package/src/list/list-root-context.ts +21 -0
- package/src/list/list-root.tsx +81 -0
- package/src/list/list.css +32 -0
- package/src/list/list.stories.tsx +119 -0
- package/src/list/list.test.tsx +168 -0
- package/src/markdown-container/index.ts +2 -0
- package/src/{stories/MarkdownContainer.stories.tsx → markdown-container/markdown-container.stories.tsx} +1 -1
- package/src/{components → markdown-container}/markdown-container.tsx +3 -1
- package/src/password-input/index.ts +2 -0
- package/src/{stories/PasswordInput.stories.tsx → password-input/password-input.stories.tsx} +1 -1
- package/src/{components → password-input}/password-input.tsx +4 -4
- package/src/picture/index.ts +2 -0
- package/src/{stories/Picture.stories.tsx → picture/picture.stories.tsx} +1 -1
- package/src/{components → picture}/picture.tsx +2 -4
- package/src/protected-email/index.ts +2 -0
- package/src/{stories/ProtectedEmail.stories.tsx → protected-email/protected-email.stories.tsx} +1 -1
- package/src/{components → protected-email}/protected-email.tsx +3 -1
- package/src/tailwind.css +10 -0
- package/src/text/index.ts +2 -0
- package/src/{stories/Text.stories.tsx → text/text.stories.tsx} +1 -1
- package/src/text/text.tsx +46 -0
- package/src/utils/author/author.tsx +36 -0
- package/src/utils/author/index.ts +1 -0
- package/src/utils/text/index.ts +1 -0
- package/src/utils/text/text.tsx +103 -0
- package/dist/components/box.d.ts +0 -20
- package/dist/components/box.js +0 -50
- package/dist/components/definition-list.d.ts +0 -43
- package/dist/components/definition-list.js +0 -89
- package/dist/components/heading.d.ts +0 -27
- package/dist/components/highlight.d.ts +0 -19
- package/dist/components/item.d.ts +0 -70
- package/dist/components/item.js +0 -512
- package/dist/components/leaflet-map.d.ts +0 -34
- package/dist/components/leaflet-map.js +0 -201
- package/dist/components/list-item.d.ts +0 -19
- package/dist/components/list-item.js +0 -37
- package/dist/components/maptiler-map.d.ts +0 -27
- package/dist/components/maptiler-map.js +0 -129
- package/dist/components/text.d.ts +0 -20
- package/dist/components/text.js +0 -45
- package/dist/components/unordered-list.d.ts +0 -19
- package/dist/components/unordered-list.js +0 -39
- package/dist/hooks/use-nonce.d.ts +0 -12
- package/dist/hooks/use-nonce.js +0 -13
- package/dist/utils/author.d.ts +0 -9
- package/dist/utils/author.js +0 -55
- package/dist/utils/cn.d.ts +0 -9
- package/dist/utils/cn.js +0 -14
- package/dist/utils/is-route-active.d.ts +0 -19
- package/dist/utils/is-route-active.js +0 -56
- package/dist/utils/text.d.ts +0 -24
- package/dist/utils/text.js +0 -127
- package/src/components/box.tsx +0 -45
- package/src/components/definition-list.tsx +0 -90
- package/src/components/item.tsx +0 -340
- package/src/components/leaflet-map.tsx +0 -294
- package/src/components/link.test.tsx +0 -387
- package/src/components/list-item.tsx +0 -30
- package/src/components/maptiler-map.tsx +0 -181
- package/src/components/text.tsx +0 -38
- package/src/components/unordered-list.tsx +0 -32
- package/src/hooks/use-nonce.test.ts +0 -35
- package/src/stories/Box.stories.tsx +0 -83
- package/src/stories/Carousel.stories.tsx +0 -95
- package/src/stories/DefinitionList.stories.tsx +0 -51
- package/src/stories/Item.stories.tsx +0 -79
- package/src/stories/ListItem.stories.tsx +0 -38
- package/src/stories/UnorderedList.stories.tsx +0 -73
- package/src/styles/tailwind.css +0 -7
- package/src/test-setup.ts +0 -1
- package/src/utils/author.test.ts +0 -54
- package/src/utils/author.tsx +0 -73
- package/src/utils/cn.test.ts +0 -48
- package/src/utils/cn.ts +0 -14
- package/src/utils/is-route-active.test.ts +0 -80
- package/src/utils/is-route-active.ts +0 -100
- package/src/utils/text.test.ts +0 -152
- package/src/utils/text.tsx +0 -209
- package/src/vite-env.d.ts +0 -1
- /package/dist/{components/background-slideshow.d.ts → background-slideshow/index.d.ts} +0 -0
- /package/dist/{components/blurry-gradient.d.ts → blurry-gradient/index.d.ts} +0 -0
- /package/dist/{components/countdown.d.ts → countdown/index.d.ts} +0 -0
- /package/dist/{components/generic-error.d.ts → generic-error/index.d.ts} +0 -0
- /package/dist/hooks/{use-current-route-data.d.ts → use-current-route-data/index.d.ts} +0 -0
- /package/dist/hooks/{use-focus-search.d.ts → use-focus-search/index.d.ts} +0 -0
- /package/dist/hooks/{use-matches-data.d.ts → use-matches-data/index.d.ts} +0 -0
- /package/dist/hooks/{use-media-query.d.ts → use-media-query/index.d.ts} +0 -0
- /package/dist/hooks/{use-mobile.d.ts → use-mobile/index.d.ts} +0 -0
- /package/dist/hooks/{use-user.d.ts → use-user/index.d.ts} +0 -0
- /package/dist/{components/icon-button.d.ts → icon-button/index.d.ts} +0 -0
- /package/dist/{components/if.d.ts → if/index.d.ts} +0 -0
- /package/dist/{components/iframe.d.ts → iframe/index.d.ts} +0 -0
- /package/dist/{components/markdown-container.d.ts → markdown-container/index.d.ts} +0 -0
- /package/dist/{components/password-input.d.ts → password-input/index.d.ts} +0 -0
- /package/dist/{components/picture.d.ts → picture/index.d.ts} +0 -0
- /package/src/hooks/{use-current-route-data.ts → use-current-route-data/use-current-route-data.ts} +0 -0
- /package/src/hooks/{use-focus-search.ts → use-focus-search/use-focus-search.ts} +0 -0
- /package/src/hooks/{use-matches-data.ts → use-matches-data/use-matches-data.ts} +0 -0
- /package/src/hooks/{use-media-query.ts → use-media-query/use-media-query.ts} +0 -0
- /package/src/hooks/{use-mobile.ts → use-mobile/use-mobile.ts} +0 -0
- /package/src/hooks/{use-nonce.ts → use-nonce/use-nonce.ts} +0 -0
- /package/src/hooks/{use-orientation.ts → use-orientation/use-orientation.ts} +0 -0
- /package/src/hooks/{use-user.tsx → use-user/use-user.tsx} +0 -0
- /package/src/{components → icon-button}/icon-button.tsx +0 -0
- /package/src/{components → if}/if.tsx +0 -0
- /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
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { MarkdownContainer } from '
|
|
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+/;
|
|
@@ -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 };
|
|
@@ -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 };
|
package/src/tailwind.css
ADDED
|
@@ -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,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 ­ in string nodes
|
|
50
|
+
function replaceShyInReactNode(node: ReactNode): ReactNode {
|
|
51
|
+
if (typeof node === 'string') {
|
|
52
|
+
// Replace soft hyphen (­) 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
|
+
}
|
package/dist/components/box.d.ts
DELETED
|
@@ -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 };
|
package/dist/components/box.js
DELETED
|
@@ -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 };
|