@regardio/react 1.2.1 → 1.3.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.
- package/README.md +17 -16
- package/package.json +17 -38
- package/src/background-slideshow/background-slideshow.test.tsx +146 -0
- package/src/carousel/carousel.test.tsx +86 -0
- package/src/countdown/countdown.test.tsx +46 -0
- package/src/grid/grid.test.tsx +94 -0
- package/src/markdown-container/markdown-container.test.tsx +124 -0
- package/src/password-input/password-input.test.tsx +53 -0
- package/src/protected-email/protected-email.test.tsx +82 -0
- package/dist/generic-error/index.d.mts +0 -47
- package/dist/generic-error/index.mjs +0 -56
- package/dist/hooks/use-current-route-data.d.mts +0 -8
- package/dist/hooks/use-current-route-data.mjs +0 -19
- package/dist/hooks/use-matches-data.d.mts +0 -10
- package/dist/hooks/use-matches-data.mjs +0 -20
- package/dist/hooks/use-user.d.mts +0 -53
- package/dist/hooks/use-user.mjs +0 -32
- package/dist/link/index.d.mts +0 -71
- package/dist/link/index.mjs +0 -127
- package/src/generic-error/generic-error.stories.tsx +0 -45
- package/src/generic-error/generic-error.tsx +0 -105
- package/src/generic-error/index.ts +0 -2
- package/src/hooks/use-current-route-data.ts +0 -20
- package/src/hooks/use-matches-data.ts +0 -21
- package/src/hooks/use-user.tsx +0 -73
- package/src/link/index.ts +0 -2
- package/src/link/link.stories.tsx +0 -109
- package/src/link/link.test.tsx +0 -169
- package/src/link/link.tsx +0 -218
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { cleanup, render, screen } from '@testing-library/react';
|
|
2
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
+
import { MarkdownContainer, transformLink } from './markdown-container';
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
cleanup();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('transformLink', () => {
|
|
10
|
+
it('strips the origin for regard.io URLs and keeps the pathname', () => {
|
|
11
|
+
expect(transformLink('https://www.regard.io/about')).toBe('/about');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('preserves search and hash for regard.io URLs', () => {
|
|
15
|
+
expect(transformLink('https://regard.io/page?q=1#section')).toBe('/page?q=1#section');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns the original URL for external links', () => {
|
|
19
|
+
expect(transformLink('https://example.com/page')).toBe('https://example.com/page');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('returns the original string for relative paths', () => {
|
|
23
|
+
expect(transformLink('/relative/path')).toBe('/relative/path');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('returns pathname from object with pathname', () => {
|
|
27
|
+
expect(transformLink({ pathname: '/products', search: '?ref=nav' })).toBe('/products?ref=nav');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('returns pathname with hash from object', () => {
|
|
31
|
+
expect(transformLink({ hash: '#top', pathname: '/page' })).toBe('/page#top');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns empty string for undefined', () => {
|
|
35
|
+
expect(transformLink(undefined)).toBe('');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('returns empty string for object without pathname', () => {
|
|
39
|
+
expect(transformLink({})).toBe('');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('MarkdownContainer', () => {
|
|
44
|
+
it('renders markdown content', () => {
|
|
45
|
+
render(<MarkdownContainer locale="en">**Bold text**</MarkdownContainer>);
|
|
46
|
+
expect(screen.getByText('Bold text')).toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('applies the markdown class', () => {
|
|
50
|
+
const { container } = render(<MarkdownContainer locale="en">Hello</MarkdownContainer>);
|
|
51
|
+
expect(container.querySelector('.markdown')).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('applies a custom className', () => {
|
|
55
|
+
const { container } = render(
|
|
56
|
+
<MarkdownContainer
|
|
57
|
+
className="custom"
|
|
58
|
+
locale="en"
|
|
59
|
+
>
|
|
60
|
+
Hello
|
|
61
|
+
</MarkdownContainer>,
|
|
62
|
+
);
|
|
63
|
+
expect(container.querySelector('.custom')).toBeInTheDocument();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('truncates by sentences', () => {
|
|
67
|
+
const text = 'First sentence. Second sentence. Third sentence.';
|
|
68
|
+
render(
|
|
69
|
+
<MarkdownContainer
|
|
70
|
+
locale="en"
|
|
71
|
+
sentences={1}
|
|
72
|
+
>
|
|
73
|
+
{text}
|
|
74
|
+
</MarkdownContainer>,
|
|
75
|
+
);
|
|
76
|
+
expect(screen.queryByText(/Third sentence/)).not.toBeInTheDocument();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('truncates by paragraphs', () => {
|
|
80
|
+
const text = 'Paragraph one.\n\nParagraph two.\n\nParagraph three.';
|
|
81
|
+
render(
|
|
82
|
+
<MarkdownContainer
|
|
83
|
+
locale="en"
|
|
84
|
+
paragraphs={1}
|
|
85
|
+
>
|
|
86
|
+
{text}
|
|
87
|
+
</MarkdownContainer>,
|
|
88
|
+
);
|
|
89
|
+
expect(screen.queryByText(/Paragraph two/)).not.toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('truncates by characters', () => {
|
|
93
|
+
const text = 'Short first. Much longer second sentence here.';
|
|
94
|
+
render(
|
|
95
|
+
<MarkdownContainer
|
|
96
|
+
characters={15}
|
|
97
|
+
locale="en"
|
|
98
|
+
>
|
|
99
|
+
{text}
|
|
100
|
+
</MarkdownContainer>,
|
|
101
|
+
);
|
|
102
|
+
expect(screen.queryByText(/longer second/)).not.toBeInTheDocument();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('renders <br> via the br override', () => {
|
|
106
|
+
const { container } = render(
|
|
107
|
+
<MarkdownContainer locale="en">{'Before<br/>After'}</MarkdownContainer>,
|
|
108
|
+
);
|
|
109
|
+
expect(container.querySelector('br')).toBeInTheDocument();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('renders <hr> via the hr override', () => {
|
|
113
|
+
const { container } = render(
|
|
114
|
+
<MarkdownContainer locale="en">{'Above<hr/>Below'}</MarkdownContainer>,
|
|
115
|
+
);
|
|
116
|
+
expect(container.querySelector('hr')).toBeInTheDocument();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('returns full text when no truncation props are given', () => {
|
|
120
|
+
const text = 'All text here.';
|
|
121
|
+
render(<MarkdownContainer locale="en">{text}</MarkdownContainer>);
|
|
122
|
+
expect(screen.getByText('All text here.')).toBeInTheDocument();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
+
import { PasswordInput } from './password-input';
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
cleanup();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('PasswordInput', () => {
|
|
10
|
+
it('starts with type=password', () => {
|
|
11
|
+
render(<PasswordInput />);
|
|
12
|
+
const input = document.querySelector('input');
|
|
13
|
+
expect(input).toHaveAttribute('type', 'password');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('shows the toggle button by default', () => {
|
|
17
|
+
render(<PasswordInput />);
|
|
18
|
+
expect(screen.getByRole('button', { name: /show password/i })).toBeInTheDocument();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('toggles to type=text when the toggle button is clicked', () => {
|
|
22
|
+
render(<PasswordInput />);
|
|
23
|
+
act(() => {
|
|
24
|
+
fireEvent.click(screen.getByRole('button', { name: /show password/i }));
|
|
25
|
+
});
|
|
26
|
+
const input = document.querySelector('input');
|
|
27
|
+
expect(input).toHaveAttribute('type', 'text');
|
|
28
|
+
expect(screen.getByRole('button', { name: /hide password/i })).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('toggles back to type=password on second click', () => {
|
|
32
|
+
render(<PasswordInput />);
|
|
33
|
+
act(() => {
|
|
34
|
+
fireEvent.click(screen.getByRole('button', { name: /show password/i }));
|
|
35
|
+
});
|
|
36
|
+
act(() => {
|
|
37
|
+
fireEvent.click(screen.getByRole('button', { name: /hide password/i }));
|
|
38
|
+
});
|
|
39
|
+
const input = document.querySelector('input');
|
|
40
|
+
expect(input).toHaveAttribute('type', 'password');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('hides the toggle button when showToggle is false', () => {
|
|
44
|
+
render(<PasswordInput showToggle={false} />);
|
|
45
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('applies a custom className', () => {
|
|
49
|
+
render(<PasswordInput className="custom-class" />);
|
|
50
|
+
const wrapper = document.querySelector('.custom-class');
|
|
51
|
+
expect(wrapper).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { act, cleanup, render } from '@testing-library/react';
|
|
2
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
+
import { ProtectedEmail } from './protected-email';
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
cleanup();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('ProtectedEmail', () => {
|
|
10
|
+
it('renders the fallback text', () => {
|
|
11
|
+
const { getByText } = render(
|
|
12
|
+
<ProtectedEmail
|
|
13
|
+
domain="example.com"
|
|
14
|
+
username="hello"
|
|
15
|
+
/>,
|
|
16
|
+
);
|
|
17
|
+
expect(getByText('hello(at)example.com')).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders custom text when provided', () => {
|
|
21
|
+
const { getByText } = render(
|
|
22
|
+
<ProtectedEmail
|
|
23
|
+
domain="example.com"
|
|
24
|
+
text="Contact us"
|
|
25
|
+
username="hello"
|
|
26
|
+
/>,
|
|
27
|
+
);
|
|
28
|
+
expect(getByText('Contact us')).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('has href after mounting', async () => {
|
|
32
|
+
const { getByRole } = render(
|
|
33
|
+
<ProtectedEmail
|
|
34
|
+
domain="example.com"
|
|
35
|
+
username="hello"
|
|
36
|
+
/>,
|
|
37
|
+
);
|
|
38
|
+
await act(async () => {});
|
|
39
|
+
expect(getByRole('link')).toHaveAttribute('href', '#email-protected');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('navigates to mailto on click when mounted', async () => {
|
|
43
|
+
Object.defineProperty(window, 'location', {
|
|
44
|
+
configurable: true,
|
|
45
|
+
value: { href: '' },
|
|
46
|
+
writable: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const { getByRole } = render(
|
|
50
|
+
<ProtectedEmail
|
|
51
|
+
domain="example.com"
|
|
52
|
+
username="hello"
|
|
53
|
+
/>,
|
|
54
|
+
);
|
|
55
|
+
await act(async () => {});
|
|
56
|
+
|
|
57
|
+
getByRole('link').click();
|
|
58
|
+
|
|
59
|
+
expect(window.location.href).toBe('mailto:hello@example.com');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('applies custom className', () => {
|
|
63
|
+
const { getByRole } = render(
|
|
64
|
+
<ProtectedEmail
|
|
65
|
+
className="custom-email"
|
|
66
|
+
domain="example.com"
|
|
67
|
+
username="hello"
|
|
68
|
+
/>,
|
|
69
|
+
);
|
|
70
|
+
expect(getByRole('link')).toHaveClass('custom-email');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('sets a descriptive aria-label', () => {
|
|
74
|
+
const { getByRole } = render(
|
|
75
|
+
<ProtectedEmail
|
|
76
|
+
domain="example.com"
|
|
77
|
+
username="hello"
|
|
78
|
+
/>,
|
|
79
|
+
);
|
|
80
|
+
expect(getByRole('link')).toHaveAttribute('aria-label', 'Email address: hello at example.com');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
//#region src/generic-error/generic-error.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Descriptor returned from getErrorDescriptor to help apps localize messages.
|
|
4
|
-
*/
|
|
5
|
-
type ErrorDescriptor = {
|
|
6
|
-
type: "http";
|
|
7
|
-
status: number;
|
|
8
|
-
statusText: string;
|
|
9
|
-
defaultId: string;
|
|
10
|
-
defaultMessage: string;
|
|
11
|
-
} | {
|
|
12
|
-
type: "error";
|
|
13
|
-
defaultId: string;
|
|
14
|
-
defaultMessage: string;
|
|
15
|
-
message?: string;
|
|
16
|
-
stack?: string;
|
|
17
|
-
} | {
|
|
18
|
-
type: "unknown";
|
|
19
|
-
defaultId: string;
|
|
20
|
-
defaultMessage: string;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Compute a normalized error descriptor from a React Router error.
|
|
24
|
-
* Apps can use this to map to i18n keys.
|
|
25
|
-
*/
|
|
26
|
-
declare function getErrorDescriptor(error: unknown): ErrorDescriptor;
|
|
27
|
-
/**
|
|
28
|
-
* GenericError
|
|
29
|
-
*
|
|
30
|
-
* A reusable error boundary component for React Router apps.
|
|
31
|
-
* - Displays status-based messages for route responses
|
|
32
|
-
* - Shows stack traces in development for non-response errors
|
|
33
|
-
* - SSR-safe: accepts optional error prop for server-side rendering
|
|
34
|
-
*
|
|
35
|
-
* For localization, apps may either:
|
|
36
|
-
* - Wrap this component and use `getErrorDescriptor(error)` to map to i18n keys
|
|
37
|
-
* - Or provide a custom `renderMessage` to override the displayed details
|
|
38
|
-
*/
|
|
39
|
-
declare function GenericError({
|
|
40
|
-
error,
|
|
41
|
-
renderMessage
|
|
42
|
-
}: {
|
|
43
|
-
error: unknown;
|
|
44
|
-
renderMessage?: (descriptor: ErrorDescriptor) => React.JSX.Element;
|
|
45
|
-
}): React.JSX.Element;
|
|
46
|
-
//#endregion
|
|
47
|
-
export { type ErrorDescriptor, GenericError, getErrorDescriptor };
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { isRouteErrorResponse } from "react-router";
|
|
3
|
-
//#region src/generic-error/generic-error.tsx
|
|
4
|
-
/**
|
|
5
|
-
* Compute a normalized error descriptor from a React Router error.
|
|
6
|
-
* Apps can use this to map to i18n keys.
|
|
7
|
-
*/
|
|
8
|
-
function getErrorDescriptor(error) {
|
|
9
|
-
if (isRouteErrorResponse(error)) {
|
|
10
|
-
const status = error.status;
|
|
11
|
-
const statusText = error.statusText || "Error";
|
|
12
|
-
return {
|
|
13
|
-
defaultId: status === 404 ? "errors.404" : "errors.http",
|
|
14
|
-
defaultMessage: status === 404 ? "Not found" : `Error ${status}`,
|
|
15
|
-
status,
|
|
16
|
-
statusText,
|
|
17
|
-
type: "http"
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
if (error instanceof Error) return {
|
|
21
|
-
defaultId: "errors.runtime",
|
|
22
|
-
defaultMessage: "An unexpected error occurred.",
|
|
23
|
-
message: error.message,
|
|
24
|
-
type: "error",
|
|
25
|
-
...error.stack ? { stack: error.stack } : {}
|
|
26
|
-
};
|
|
27
|
-
return {
|
|
28
|
-
defaultId: "errors.unknown",
|
|
29
|
-
defaultMessage: "An unexpected error occurred.",
|
|
30
|
-
type: "unknown"
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* GenericError
|
|
35
|
-
*
|
|
36
|
-
* A reusable error boundary component for React Router apps.
|
|
37
|
-
* - Displays status-based messages for route responses
|
|
38
|
-
* - Shows stack traces in development for non-response errors
|
|
39
|
-
* - SSR-safe: accepts optional error prop for server-side rendering
|
|
40
|
-
*
|
|
41
|
-
* For localization, apps may either:
|
|
42
|
-
* - Wrap this component and use `getErrorDescriptor(error)` to map to i18n keys
|
|
43
|
-
* - Or provide a custom `renderMessage` to override the displayed details
|
|
44
|
-
*/
|
|
45
|
-
function GenericError({ error, renderMessage }) {
|
|
46
|
-
const descriptor = getErrorDescriptor(error);
|
|
47
|
-
return /* @__PURE__ */ jsxs("main", {
|
|
48
|
-
className: "pt-2xl p-sm container mx-auto",
|
|
49
|
-
children: [/* @__PURE__ */ jsx("h1", { children: descriptor.type === "http" ? `Error ${descriptor.status}` : "Error" }), renderMessage ? renderMessage(descriptor) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", { children: descriptor.type === "http" ? descriptor.defaultMessage : descriptor.type === "error" ? descriptor.message || descriptor.defaultMessage : descriptor.defaultMessage }), import.meta.env.DEV && descriptor.type === "error" && descriptor.stack && /* @__PURE__ */ jsx("pre", {
|
|
50
|
-
className: "w-full p-sm overflow-x-auto",
|
|
51
|
-
children: /* @__PURE__ */ jsx("code", { children: descriptor.stack })
|
|
52
|
-
})] })]
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
export { GenericError, getErrorDescriptor };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region src/hooks/use-current-route-data.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* This base hook is used to access data related to the current route
|
|
4
|
-
* @returns {JSON|undefined} The router data or undefined if not found
|
|
5
|
-
*/
|
|
6
|
-
declare function useCurrentRouteData<HeaderData>(): HeaderData | undefined;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { useCurrentRouteData };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
|
-
import { useLocation, useMatches } from "react-router";
|
|
4
|
-
//#region src/hooks/use-current-route-data.ts
|
|
5
|
-
/**
|
|
6
|
-
* This base hook is used to access data related to the current route
|
|
7
|
-
* @returns {JSON|undefined} The router data or undefined if not found
|
|
8
|
-
*/
|
|
9
|
-
function useCurrentRouteData() {
|
|
10
|
-
const location = useLocation();
|
|
11
|
-
const matchingRoutes = useMatches();
|
|
12
|
-
return useMemo(() => {
|
|
13
|
-
return matchingRoutes.find((route) => {
|
|
14
|
-
return route.pathname === location.pathname;
|
|
15
|
-
});
|
|
16
|
-
}, [matchingRoutes, location])?.loaderData || void 0;
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { useCurrentRouteData };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
//#region src/hooks/use-matches-data.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* This base hook is used in other hooks to quickly search for specific data
|
|
4
|
-
* across all loader data using useMatches.
|
|
5
|
-
* @param {string} id The route id
|
|
6
|
-
* @returns {JSON|undefined} The router data or undefined if not found
|
|
7
|
-
*/
|
|
8
|
-
declare function useMatchesData<T>(id: string): T | undefined;
|
|
9
|
-
//#endregion
|
|
10
|
-
export { useMatchesData };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
|
-
import { useMatches } from "react-router";
|
|
4
|
-
//#region src/hooks/use-matches-data.ts
|
|
5
|
-
/**
|
|
6
|
-
* This base hook is used in other hooks to quickly search for specific data
|
|
7
|
-
* across all loader data using useMatches.
|
|
8
|
-
* @param {string} id The route id
|
|
9
|
-
* @returns {JSON|undefined} The router data or undefined if not found
|
|
10
|
-
*/
|
|
11
|
-
function useMatchesData(id) {
|
|
12
|
-
const matchingRoutes = useMatches();
|
|
13
|
-
return useMemo(() => {
|
|
14
|
-
return matchingRoutes.find((route) => {
|
|
15
|
-
return route.id === id;
|
|
16
|
-
});
|
|
17
|
-
}, [matchingRoutes, id])?.data || void 0;
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
export { useMatchesData };
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
import { User } from "@supabase/supabase-js";
|
|
3
|
-
|
|
4
|
-
//#region src/hooks/use-user.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Context for storing and accessing the current authenticated user
|
|
7
|
-
*/
|
|
8
|
-
interface UserContextType {
|
|
9
|
-
/**
|
|
10
|
-
* Whether the user data is currently loading
|
|
11
|
-
*/
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
/**
|
|
14
|
-
* The current authenticated user, or null if not authenticated
|
|
15
|
-
*/
|
|
16
|
-
user: User | null;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Context for storing and accessing the current authenticated user
|
|
20
|
-
*/
|
|
21
|
-
declare const UserContext: React.Context<UserContextType>;
|
|
22
|
-
/**
|
|
23
|
-
* Props for the UserContextProvider component
|
|
24
|
-
*/
|
|
25
|
-
interface UserContextProviderProps {
|
|
26
|
-
/**
|
|
27
|
-
* Child components that will have access to the user context
|
|
28
|
-
*/
|
|
29
|
-
children: ReactNode;
|
|
30
|
-
/**
|
|
31
|
-
* Whether the user data is currently loading
|
|
32
|
-
*/
|
|
33
|
-
isLoading?: boolean;
|
|
34
|
-
/**
|
|
35
|
-
* The current authenticated user, or null if not authenticated
|
|
36
|
-
*/
|
|
37
|
-
user: User | null;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Provider component for the UserContext
|
|
41
|
-
*/
|
|
42
|
-
declare function UserContextProvider({
|
|
43
|
-
user,
|
|
44
|
-
isLoading,
|
|
45
|
-
children
|
|
46
|
-
}: UserContextProviderProps): React.JSX.Element;
|
|
47
|
-
/**
|
|
48
|
-
* Hook to access the current authenticated user from the UserContext
|
|
49
|
-
* @returns The current user context containing the user object and loading state
|
|
50
|
-
*/
|
|
51
|
-
declare function useUser(): UserContextType;
|
|
52
|
-
//#endregion
|
|
53
|
-
export { UserContext, UserContextProvider, UserContextProviderProps, UserContextType, useUser };
|
package/dist/hooks/use-user.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from "react";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
/**
|
|
4
|
-
* Context for storing and accessing the current authenticated user
|
|
5
|
-
*/
|
|
6
|
-
const UserContext = createContext({
|
|
7
|
-
isLoading: false,
|
|
8
|
-
user: null
|
|
9
|
-
});
|
|
10
|
-
/**
|
|
11
|
-
* Provider component for the UserContext
|
|
12
|
-
*/
|
|
13
|
-
function UserContextProvider({ user, isLoading = false, children }) {
|
|
14
|
-
return /* @__PURE__ */ jsx(UserContext.Provider, {
|
|
15
|
-
value: {
|
|
16
|
-
isLoading,
|
|
17
|
-
user
|
|
18
|
-
},
|
|
19
|
-
children
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Hook to access the current authenticated user from the UserContext
|
|
24
|
-
* @returns The current user context containing the user object and loading state
|
|
25
|
-
*/
|
|
26
|
-
function useUser() {
|
|
27
|
-
const context = useContext(UserContext);
|
|
28
|
-
if (context === void 0) throw new Error("useUser must be used within a UserContextProvider");
|
|
29
|
-
return context;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { UserContext, UserContextProvider, useUser };
|
package/dist/link/index.d.mts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { NavLinkProps } from "react-router";
|
|
2
|
-
|
|
3
|
-
//#region src/link/link.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Context for providing a path resolver function.
|
|
6
|
-
* This allows projects to inject their own localization logic.
|
|
7
|
-
*/
|
|
8
|
-
type PathResolver = (routeKey: string) => string;
|
|
9
|
-
declare const PathResolverProvider: React.Provider<PathResolver | null>;
|
|
10
|
-
declare function usePathResolver(): PathResolver | null;
|
|
11
|
-
interface LinkBaseProps extends Omit<NavLinkProps, "to"> {
|
|
12
|
-
routeKey?: string;
|
|
13
|
-
to?: string | Partial<{
|
|
14
|
-
pathname?: string;
|
|
15
|
-
search?: string;
|
|
16
|
-
hash?: string;
|
|
17
|
-
}> | undefined;
|
|
18
|
-
viewTransition?: boolean;
|
|
19
|
-
}
|
|
20
|
-
declare const LinkBase: ({
|
|
21
|
-
className,
|
|
22
|
-
to,
|
|
23
|
-
routeKey,
|
|
24
|
-
children,
|
|
25
|
-
onClick,
|
|
26
|
-
viewTransition,
|
|
27
|
-
...props
|
|
28
|
-
}: LinkBaseProps) => React.JSX.Element;
|
|
29
|
-
declare const arrowVariants: {
|
|
30
|
-
readonly darr: "darr";
|
|
31
|
-
readonly larr: "larr";
|
|
32
|
-
readonly rarr: "rarr";
|
|
33
|
-
readonly uarr: "uarr";
|
|
34
|
-
};
|
|
35
|
-
declare const linkVariants: {
|
|
36
|
-
readonly button: readonly ["block", "button", "mt-s", "relative", "rarr", "text-right", "text-sm", "tracking-wider", "uppercase"];
|
|
37
|
-
readonly code: readonly ["font-monospace"];
|
|
38
|
-
readonly link: readonly ["rarr", "!bg-transparent", "uppercase", "!tracking-wider"];
|
|
39
|
-
readonly navtitle: readonly ["block", "uppercase", "tracking-wider"];
|
|
40
|
-
readonly primary: readonly [];
|
|
41
|
-
readonly subtitle: readonly ["text-lg"];
|
|
42
|
-
};
|
|
43
|
-
type LinkArrow = keyof typeof arrowVariants;
|
|
44
|
-
type LinkVariant = keyof typeof linkVariants;
|
|
45
|
-
interface LinkProps extends Omit<NavLinkProps, "to"> {
|
|
46
|
-
arrow?: LinkArrow;
|
|
47
|
-
routeKey?: string;
|
|
48
|
-
to?: string | Partial<{
|
|
49
|
-
pathname?: string;
|
|
50
|
-
search?: string;
|
|
51
|
-
hash?: string;
|
|
52
|
-
}>;
|
|
53
|
-
variant?: LinkVariant;
|
|
54
|
-
viewTransition?: boolean;
|
|
55
|
-
}
|
|
56
|
-
declare const Link: ({
|
|
57
|
-
arrow,
|
|
58
|
-
children,
|
|
59
|
-
className,
|
|
60
|
-
routeKey,
|
|
61
|
-
to,
|
|
62
|
-
variant,
|
|
63
|
-
viewTransition,
|
|
64
|
-
...props
|
|
65
|
-
}: LinkProps) => React.JSX.Element;
|
|
66
|
-
interface MarkdownLinkProps extends Omit<LinkProps, "to"> {
|
|
67
|
-
href?: string;
|
|
68
|
-
}
|
|
69
|
-
declare const MarkdownLink: React.FC<MarkdownLinkProps>;
|
|
70
|
-
//#endregion
|
|
71
|
-
export { Link, LinkBase, type LinkBaseProps, type LinkProps, MarkdownLink, type MarkdownLinkProps, type PathResolver, PathResolverProvider, usePathResolver };
|