@regardio/react 0.4.7 → 0.5.5
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 +6 -8
- 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-nonce.d.ts +1 -6
- package/dist/hooks/use-nonce.js +1 -6
- 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 +170 -187
- package/src/background-slideshow/background-slideshow.stories.tsx +137 -0
- 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 +135 -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-nonce.ts +0 -10
- 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} +52 -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} +56 -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/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/BackgroundSlideshow.stories.tsx +0 -68
- 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/{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/{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,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
|
|
5
|
+
export interface ListRootContextValue {
|
|
6
|
+
/**
|
|
7
|
+
* Default element type for list items.
|
|
8
|
+
* @default 'li'
|
|
9
|
+
*/
|
|
10
|
+
defaultItemElement: 'li' | 'dd' | 'dt' | 'div' | 'span';
|
|
11
|
+
/**
|
|
12
|
+
* Default className to apply to all list items.
|
|
13
|
+
*/
|
|
14
|
+
defaultItemClassName?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ListRootContext = createContext<ListRootContextValue | undefined>(undefined);
|
|
18
|
+
|
|
19
|
+
export function useListRootContext(): ListRootContextValue | undefined {
|
|
20
|
+
return useContext(ListRootContext);
|
|
21
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ComponentPropsWithoutRef,
|
|
5
|
+
type ElementType,
|
|
6
|
+
type ForwardedRef,
|
|
7
|
+
forwardRef,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
useMemo,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { ListRootContext, type ListRootContextValue } from './list-root-context';
|
|
12
|
+
|
|
13
|
+
type ListRootElement = 'ul' | 'ol' | 'dl' | 'div' | 'menu' | 'nav';
|
|
14
|
+
|
|
15
|
+
export type ListRootProps<T extends ListRootElement = 'ul'> = Omit<
|
|
16
|
+
ComponentPropsWithoutRef<T>,
|
|
17
|
+
'children'
|
|
18
|
+
> & {
|
|
19
|
+
/**
|
|
20
|
+
* The element type to render.
|
|
21
|
+
* @default 'ul'
|
|
22
|
+
*/
|
|
23
|
+
render?: T;
|
|
24
|
+
/**
|
|
25
|
+
* The content of the list.
|
|
26
|
+
*/
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Default element type for list items.
|
|
30
|
+
* When render is 'dl', defaults to 'dd'. Otherwise defaults to 'li'.
|
|
31
|
+
*/
|
|
32
|
+
defaultItemElement?: ListRootContextValue['defaultItemElement'];
|
|
33
|
+
/**
|
|
34
|
+
* Default className to apply to all list items.
|
|
35
|
+
*/
|
|
36
|
+
defaultItemClassName?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function ListRootImpl<T extends ListRootElement = 'ul'>(
|
|
40
|
+
props: ListRootProps<T>,
|
|
41
|
+
ref: ForwardedRef<HTMLElement>,
|
|
42
|
+
) {
|
|
43
|
+
const {
|
|
44
|
+
render = 'ul' as T,
|
|
45
|
+
children,
|
|
46
|
+
defaultItemElement,
|
|
47
|
+
defaultItemClassName,
|
|
48
|
+
...elementProps
|
|
49
|
+
} = props;
|
|
50
|
+
|
|
51
|
+
const resolvedDefaultItemElement = defaultItemElement ?? (render === 'dl' ? 'dd' : 'li');
|
|
52
|
+
|
|
53
|
+
const contextValue = useMemo<ListRootContextValue>(
|
|
54
|
+
() => ({
|
|
55
|
+
defaultItemClassName,
|
|
56
|
+
defaultItemElement: resolvedDefaultItemElement,
|
|
57
|
+
}),
|
|
58
|
+
[resolvedDefaultItemElement, defaultItemClassName],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const Component = render as ElementType;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<ListRootContext.Provider value={contextValue}>
|
|
65
|
+
<Component
|
|
66
|
+
ref={ref}
|
|
67
|
+
{...elementProps}
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
70
|
+
</Component>
|
|
71
|
+
</ListRootContext.Provider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const ListRoot = forwardRef(ListRootImpl) as <T extends ListRootElement = 'ul'>(
|
|
76
|
+
props: ListRootProps<T> & { ref?: ForwardedRef<HTMLElement> },
|
|
77
|
+
) => ReturnType<typeof ListRootImpl>;
|
|
78
|
+
|
|
79
|
+
export namespace ListRoot {
|
|
80
|
+
export type Props<T extends ListRootElement = 'ul'> = ListRootProps<T>;
|
|
81
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS custom properties for List component styling.
|
|
3
|
+
* These can be overridden at any level to customize the appearance.
|
|
4
|
+
*
|
|
5
|
+
* Usage with CSS Modules or plain CSS:
|
|
6
|
+
* .my-list {
|
|
7
|
+
* --list-gap: 1rem;
|
|
8
|
+
* --list-padding: 0;
|
|
9
|
+
* }
|
|
10
|
+
*
|
|
11
|
+
* Usage with Tailwind (via arbitrary properties):
|
|
12
|
+
* <List.Root className="[--list-gap:1rem]">
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
/* List Root */
|
|
17
|
+
--list-gap: 0;
|
|
18
|
+
--list-padding: 0;
|
|
19
|
+
--list-margin: 0;
|
|
20
|
+
--list-style: none;
|
|
21
|
+
|
|
22
|
+
/* List Item */
|
|
23
|
+
--list-item-padding: 0;
|
|
24
|
+
--list-item-margin: 0;
|
|
25
|
+
|
|
26
|
+
/* Definition List specific */
|
|
27
|
+
--list-dl-grid-columns: auto 1fr;
|
|
28
|
+
--list-dl-gap-x: 0.5rem;
|
|
29
|
+
--list-dl-gap-y: 0.25rem;
|
|
30
|
+
--list-dt-font-weight: 600;
|
|
31
|
+
--list-dd-margin: 0;
|
|
32
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { List } from './index';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof List.Root> = {
|
|
5
|
+
component: List.Root,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/List',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof List.Root>;
|
|
15
|
+
|
|
16
|
+
export const UnorderedList: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<List.Root>
|
|
19
|
+
<List.Item>First item</List.Item>
|
|
20
|
+
<List.Item>Second item</List.Item>
|
|
21
|
+
<List.Item>Third item</List.Item>
|
|
22
|
+
</List.Root>
|
|
23
|
+
),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const OrderedList: Story = {
|
|
27
|
+
render: () => (
|
|
28
|
+
<List.Root render="ol">
|
|
29
|
+
<List.Item>Step one</List.Item>
|
|
30
|
+
<List.Item>Step two</List.Item>
|
|
31
|
+
<List.Item>Step three</List.Item>
|
|
32
|
+
</List.Root>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const DefinitionList: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<List.Root
|
|
39
|
+
className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-2"
|
|
40
|
+
render="dl"
|
|
41
|
+
>
|
|
42
|
+
<List.Item
|
|
43
|
+
className="font-semibold"
|
|
44
|
+
render="dt"
|
|
45
|
+
>
|
|
46
|
+
Email
|
|
47
|
+
</List.Item>
|
|
48
|
+
<List.Item>contact@example.com</List.Item>
|
|
49
|
+
<List.Item
|
|
50
|
+
className="font-semibold"
|
|
51
|
+
render="dt"
|
|
52
|
+
>
|
|
53
|
+
Phone
|
|
54
|
+
</List.Item>
|
|
55
|
+
<List.Item>+1 234 567 890</List.Item>
|
|
56
|
+
<List.Item
|
|
57
|
+
className="font-semibold"
|
|
58
|
+
render="dt"
|
|
59
|
+
>
|
|
60
|
+
Address
|
|
61
|
+
</List.Item>
|
|
62
|
+
<List.Item>123 Main Street, City, Country</List.Item>
|
|
63
|
+
</List.Root>
|
|
64
|
+
),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const WithDefaultItemClassName: Story = {
|
|
68
|
+
render: () => (
|
|
69
|
+
<List.Root defaultItemClassName="py-2 border-b border-gray-200 last:border-0">
|
|
70
|
+
<List.Item>Styled item one</List.Item>
|
|
71
|
+
<List.Item>Styled item two</List.Item>
|
|
72
|
+
<List.Item>Styled item three</List.Item>
|
|
73
|
+
</List.Root>
|
|
74
|
+
),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const InlineList: Story = {
|
|
78
|
+
render: () => (
|
|
79
|
+
<List.Root className="flex flex-wrap gap-2 list-none p-0">
|
|
80
|
+
<List.Item className="px-2 py-1 bg-gray-100 rounded">Tag 1</List.Item>
|
|
81
|
+
<List.Item className="px-2 py-1 bg-gray-100 rounded">Tag 2</List.Item>
|
|
82
|
+
<List.Item className="px-2 py-1 bg-gray-100 rounded">Tag 3</List.Item>
|
|
83
|
+
</List.Root>
|
|
84
|
+
),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const NavigationMenu: Story = {
|
|
88
|
+
render: () => (
|
|
89
|
+
<List.Root
|
|
90
|
+
className="flex gap-4"
|
|
91
|
+
defaultItemElement="div"
|
|
92
|
+
render="nav"
|
|
93
|
+
>
|
|
94
|
+
<List.Item className="hover:text-blue-600 cursor-pointer">Home</List.Item>
|
|
95
|
+
<List.Item className="hover:text-blue-600 cursor-pointer">About</List.Item>
|
|
96
|
+
<List.Item className="hover:text-blue-600 cursor-pointer">Contact</List.Item>
|
|
97
|
+
</List.Root>
|
|
98
|
+
),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const CustomElements: Story = {
|
|
102
|
+
render: () => (
|
|
103
|
+
<List.Root
|
|
104
|
+
className="flex gap-2"
|
|
105
|
+
defaultItemElement="span"
|
|
106
|
+
render="div"
|
|
107
|
+
>
|
|
108
|
+
<List.Item className="px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm">
|
|
109
|
+
React
|
|
110
|
+
</List.Item>
|
|
111
|
+
<List.Item className="px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm">
|
|
112
|
+
TypeScript
|
|
113
|
+
</List.Item>
|
|
114
|
+
<List.Item className="px-3 py-1 bg-purple-100 text-purple-800 rounded-full text-sm">
|
|
115
|
+
Tailwind
|
|
116
|
+
</List.Item>
|
|
117
|
+
</List.Root>
|
|
118
|
+
),
|
|
119
|
+
};
|
|
@@ -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,
|
|
@@ -74,3 +74,58 @@ export const WithCharacterLimit: Story = {
|
|
|
74
74
|
locale: 'en',
|
|
75
75
|
},
|
|
76
76
|
};
|
|
77
|
+
|
|
78
|
+
export const WithMDXComponents: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
children: `# Custom Components
|
|
81
|
+
|
|
82
|
+
This text uses custom MDX components.`,
|
|
83
|
+
locale: 'en',
|
|
84
|
+
mdxComponents: {},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const WithMarkdownOverrides: Story = {
|
|
89
|
+
args: {
|
|
90
|
+
children: `# Overridden Heading
|
|
91
|
+
|
|
92
|
+
This paragraph has custom styling applied.`,
|
|
93
|
+
locale: 'en',
|
|
94
|
+
markdownOverrides: {
|
|
95
|
+
h1: {
|
|
96
|
+
props: {
|
|
97
|
+
className: 'text-4xl font-bold text-blue-600',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const WithInternalLink: Story = {
|
|
105
|
+
args: {
|
|
106
|
+
children: 'Check out [our page](https://regardio.com/about) for more info.',
|
|
107
|
+
locale: 'en',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const WithExternalLink: Story = {
|
|
112
|
+
args: {
|
|
113
|
+
children: 'Visit [external site](https://example.com) for details.',
|
|
114
|
+
locale: 'en',
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const EmptyContent: Story = {
|
|
119
|
+
args: {
|
|
120
|
+
children: '',
|
|
121
|
+
locale: 'en',
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const WithClassName: Story = {
|
|
126
|
+
args: {
|
|
127
|
+
children: '**Bold text** in a styled container.',
|
|
128
|
+
className: 'bg-gray-100 p-4 rounded',
|
|
129
|
+
locale: 'en',
|
|
130
|
+
},
|
|
131
|
+
};
|
|
@@ -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
|
+
};
|