@kennycorrea/ui 0.9.1 → 0.11.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/CHANGELOG.md +120 -14
- package/README.md +204 -273
- package/dist/atoms/ActionSheet/ActionSheet.d.ts +30 -0
- package/dist/atoms/ActionSheet/ActionSheet.js +42 -0
- package/dist/atoms/ActionSheet/confirm.d.ts +21 -0
- package/dist/atoms/ActionSheet/confirm.js +65 -0
- package/dist/atoms/ActionSheet/index.d.ts +2 -0
- package/dist/atoms/ActionSheet/index.js +2 -0
- package/dist/atoms/Button/Button.js +3 -3
- package/dist/atoms/Button/Button.types.d.ts +7 -1
- package/dist/atoms/Card/Card.d.ts +28 -7
- package/dist/atoms/Card/Card.js +45 -9
- package/dist/atoms/ChipGroup/ChipGroup.d.ts +31 -0
- package/dist/atoms/ChipGroup/ChipGroup.js +69 -0
- package/dist/atoms/ChipGroup/index.d.ts +1 -0
- package/dist/atoms/ChipGroup/index.js +1 -0
- package/dist/atoms/Drawer/Drawer.d.ts +1 -1
- package/dist/atoms/Drawer/Drawer.js +9 -13
- package/dist/atoms/Input/Input.js +7 -1
- package/dist/atoms/List/List.d.ts +73 -0
- package/dist/atoms/List/List.js +88 -0
- package/dist/atoms/List/index.d.ts +1 -0
- package/dist/atoms/List/index.js +1 -0
- package/dist/atoms/List/swipe.d.ts +68 -0
- package/dist/atoms/List/swipe.js +207 -0
- package/dist/atoms/NavBar/BackButton.d.ts +10 -0
- package/dist/atoms/NavBar/BackButton.js +11 -0
- package/dist/atoms/NavBar/NavBar.d.ts +22 -0
- package/dist/atoms/NavBar/NavBar.js +29 -0
- package/dist/atoms/NavBar/index.d.ts +2 -0
- package/dist/atoms/NavBar/index.js +2 -0
- package/dist/atoms/NotificationCard/NotificationCard.d.ts +52 -0
- package/dist/atoms/NotificationCard/NotificationCard.js +78 -0
- package/dist/atoms/NotificationCard/index.d.ts +1 -0
- package/dist/atoms/NotificationCard/index.js +1 -0
- package/dist/atoms/PullToRefresh/PullToRefresh.d.ts +31 -0
- package/dist/atoms/PullToRefresh/PullToRefresh.js +110 -0
- package/dist/atoms/PullToRefresh/index.d.ts +1 -0
- package/dist/atoms/PullToRefresh/index.js +1 -0
- package/dist/atoms/ResponsiveDialog/ResponsiveDialog.d.ts +13 -0
- package/dist/atoms/ResponsiveDialog/ResponsiveDialog.js +27 -0
- package/dist/atoms/ResponsiveDialog/index.d.ts +1 -0
- package/dist/atoms/ResponsiveDialog/index.js +1 -0
- package/dist/atoms/ScrollStrip/ScrollStrip.d.ts +17 -0
- package/dist/atoms/ScrollStrip/ScrollStrip.js +15 -0
- package/dist/atoms/ScrollStrip/index.d.ts +1 -0
- package/dist/atoms/ScrollStrip/index.js +1 -0
- package/dist/atoms/SegmentedControl/SegmentedControl.d.ts +23 -0
- package/dist/atoms/SegmentedControl/SegmentedControl.js +41 -0
- package/dist/atoms/SegmentedControl/index.d.ts +1 -0
- package/dist/atoms/SegmentedControl/index.js +1 -0
- package/dist/atoms/Select/Select.js +1 -1
- package/dist/atoms/Sheet/Sheet.d.ts +63 -0
- package/dist/atoms/Sheet/Sheet.js +261 -0
- package/dist/atoms/Sheet/index.d.ts +1 -0
- package/dist/atoms/Sheet/index.js +1 -0
- package/dist/atoms/StatTile/StatTile.d.ts +36 -0
- package/dist/atoms/StatTile/StatTile.js +17 -0
- package/dist/atoms/StatTile/index.d.ts +1 -0
- package/dist/atoms/StatTile/index.js +1 -0
- package/dist/atoms/TabBar/TabBar.d.ts +42 -0
- package/dist/atoms/TabBar/TabBar.js +36 -0
- package/dist/atoms/TabBar/index.d.ts +1 -0
- package/dist/atoms/TabBar/index.js +1 -0
- package/dist/atoms/Textarea/Textarea.d.ts +4 -0
- package/dist/atoms/Textarea/Textarea.js +1 -1
- package/dist/atoms/Toast/Toast.d.ts +8 -2
- package/dist/atoms/Toast/Toast.js +19 -4
- package/dist/atoms/index.d.ts +12 -0
- package/dist/atoms/index.js +12 -0
- package/dist/primitives/index.d.ts +1 -1
- package/dist/primitives/index.js +1 -1
- package/dist/strings.d.ts +13 -3
- package/dist/strings.js +5 -0
- package/dist/utils/themePortal.d.ts +19 -0
- package/dist/utils/themePortal.js +28 -0
- package/package.json +4 -2
- package/tokens.css +454 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, MouseEventHandler, ReactNode } from 'react';
|
|
2
|
+
import { type CardDensity, type CardVariant, type Responsive } from '../Card/index.js';
|
|
3
|
+
export type StatTone = 'positive' | 'negative' | 'neutral';
|
|
4
|
+
export type StatDirection = 'up' | 'down' | 'flat';
|
|
5
|
+
export interface StatDelta {
|
|
6
|
+
/** The change as the reader should see it, already formatted: "+12%", "−€40". */
|
|
7
|
+
value: ReactNode;
|
|
8
|
+
/** Which way the number moved — picks the arrow. `flat` shows none. */
|
|
9
|
+
direction?: StatDirection;
|
|
10
|
+
/** Whether the move is good news. Independent of direction: fewer no-shows is down and positive. */
|
|
11
|
+
tone?: StatTone;
|
|
12
|
+
/** Spoken context for the change, e.g. "versus last month". Visually hidden. */
|
|
13
|
+
label?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface StatTileProps {
|
|
16
|
+
label: ReactNode;
|
|
17
|
+
/** Already formatted; rendered with tabular numerals so a row of tiles lines up. */
|
|
18
|
+
value: ReactNode;
|
|
19
|
+
delta?: StatDelta;
|
|
20
|
+
/** A small chart, rendered under the value in a fixed-height slot. */
|
|
21
|
+
sparkline?: ReactNode;
|
|
22
|
+
/** Makes the tile a link, with a chevron. */
|
|
23
|
+
href?: string;
|
|
24
|
+
linkProps?: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'className' | 'children'>;
|
|
25
|
+
/** Makes the tile a button (or, with `href`, also fires on the link), with a chevron. */
|
|
26
|
+
onClick?: MouseEventHandler<HTMLElement>;
|
|
27
|
+
variant?: Responsive<CardVariant>;
|
|
28
|
+
density?: Responsive<CardDensity>;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A compact KPI tile: label, value, optional delta and sparkline. Built on `Card`, so `variant`
|
|
33
|
+
* and `density` mean what they mean there. With `href` or `onClick` the whole tile is the target
|
|
34
|
+
* and a chevron says so.
|
|
35
|
+
*/
|
|
36
|
+
export declare function StatTile({ label, value, delta, sparkline, href, linkProps, onClick, variant, density, className, }: StatTileProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowDownIcon, ArrowUpIcon, ChevronRightIcon } from '@radix-ui/react-icons';
|
|
3
|
+
import { cn } from '../../utils/cn.js';
|
|
4
|
+
import { Card } from '../Card/index.js';
|
|
5
|
+
const ARROWS = { up: ArrowUpIcon, down: ArrowDownIcon };
|
|
6
|
+
/**
|
|
7
|
+
* A compact KPI tile: label, value, optional delta and sparkline. Built on `Card`, so `variant`
|
|
8
|
+
* and `density` mean what they mean there. With `href` or `onClick` the whole tile is the target
|
|
9
|
+
* and a chevron says so.
|
|
10
|
+
*/
|
|
11
|
+
export function StatTile({ label, value, delta, sparkline, href, linkProps, onClick, variant, density, className, }) {
|
|
12
|
+
const interactive = href !== undefined || onClick !== undefined;
|
|
13
|
+
const direction = delta?.direction ?? 'flat';
|
|
14
|
+
const Arrow = direction === 'flat' ? null : ARROWS[direction];
|
|
15
|
+
const body = (_jsxs(_Fragment, { children: [_jsx("span", { className: "ui-stat-label", children: label }), _jsxs("span", { className: "ui-stat-row", children: [_jsx("span", { className: "ui-stat-value", children: value }), delta && (_jsxs("span", { className: "ui-stat-delta", "data-tone": delta.tone ?? 'neutral', children: [Arrow && _jsx(Arrow, { "aria-hidden": true }), delta.value, delta.label && _jsxs("span", { className: "sr-only", children: [" ", delta.label] })] }))] }), sparkline && (_jsx("span", { className: "ui-stat-spark", "aria-hidden": true, children: sparkline })), interactive && _jsx(ChevronRightIcon, { className: "ui-stat-chevron", "aria-hidden": true })] }));
|
|
16
|
+
return (_jsx(Card, { variant: variant, density: density, className: cn('ui-stat-card', className), children: href !== undefined ? (_jsx("a", { ...linkProps, href: href, className: "ui-stat", "data-interactive": true, onClick: onClick, children: body })) : onClick ? (_jsx("button", { type: "button", className: "ui-stat", "data-interactive": true, onClick: onClick, children: body })) : (_jsx("div", { className: "ui-stat", children: body })) }));
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './StatTile.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './StatTile.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
export type TabBarBreakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
|
+
/** What a `render` function must spread onto the element it returns (a router link, say). */
|
|
4
|
+
export interface TabBarItemRenderProps {
|
|
5
|
+
className: string;
|
|
6
|
+
'aria-current'?: 'page';
|
|
7
|
+
'aria-label'?: string;
|
|
8
|
+
'data-active': 'true' | 'false';
|
|
9
|
+
onClick: () => void;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export interface TabBarItem {
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
icon: ReactNode;
|
|
16
|
+
/** Shown instead of `icon` while active (a filled glyph, usually). */
|
|
17
|
+
activeIcon?: ReactNode;
|
|
18
|
+
/** A number shows a count (99+ caps); `true` shows a dot. */
|
|
19
|
+
badge?: number | boolean;
|
|
20
|
+
/** Wrap a router link: spread the props onto the element you return. */
|
|
21
|
+
render?: (props: TabBarItemRenderProps) => ReactElement;
|
|
22
|
+
}
|
|
23
|
+
export interface TabBarProps {
|
|
24
|
+
items: TabBarItem[];
|
|
25
|
+
value: string;
|
|
26
|
+
onValueChange?: (value: string) => void;
|
|
27
|
+
/** Breakpoint (Radix Themes' scale) from which the bar is hidden. Default `md`. */
|
|
28
|
+
hideFrom?: TabBarBreakpoint;
|
|
29
|
+
'aria-label'?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A fixed bottom navigation bar for small screens. 3–5 items; the active one is in the brand
|
|
34
|
+
* colour and carries `aria-current="page"`. Height is `--tabbar-height` (49px + `--safe-bottom`);
|
|
35
|
+
* render a {@link TabBarSpacer} (or pad by that variable) so content is not covered.
|
|
36
|
+
* Press feedback is `:active`; nothing depends on hover.
|
|
37
|
+
*/
|
|
38
|
+
export declare function TabBar({ items, value, onValueChange, hideFrom, className, 'aria-label': ariaLabel, }: TabBarProps): import("react").JSX.Element;
|
|
39
|
+
/** Reserves the bar's height in the flow, hidden at the same breakpoint as the bar. */
|
|
40
|
+
export declare function TabBarSpacer({ hideFrom }: {
|
|
41
|
+
hideFrom?: TabBarBreakpoint;
|
|
42
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
function badgeText(badge) {
|
|
3
|
+
if (badge === undefined || badge === false || badge === 0)
|
|
4
|
+
return null;
|
|
5
|
+
if (badge === true)
|
|
6
|
+
return '';
|
|
7
|
+
return badge > 99 ? '99+' : String(badge);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A fixed bottom navigation bar for small screens. 3–5 items; the active one is in the brand
|
|
11
|
+
* colour and carries `aria-current="page"`. Height is `--tabbar-height` (49px + `--safe-bottom`);
|
|
12
|
+
* render a {@link TabBarSpacer} (or pad by that variable) so content is not covered.
|
|
13
|
+
* Press feedback is `:active`; nothing depends on hover.
|
|
14
|
+
*/
|
|
15
|
+
export function TabBar({ items, value, onValueChange, hideFrom = 'md', className, 'aria-label': ariaLabel, }) {
|
|
16
|
+
return (_jsx("nav", { className: ['ui-tabbar', className].filter(Boolean).join(' '), "data-hide-from": hideFrom, "aria-label": ariaLabel, children: items.map((item) => {
|
|
17
|
+
const active = item.value === value;
|
|
18
|
+
const text = badgeText(item.badge);
|
|
19
|
+
const children = (_jsxs(_Fragment, { children: [_jsxs("span", { className: "ui-tabbar__icon", "aria-hidden": "true", children: [active && item.activeIcon ? item.activeIcon : item.icon, text !== null && (_jsx("span", { className: "ui-tabbar__badge", "data-dot": text === '' ? 'true' : undefined, children: text }))] }), _jsx("span", { className: "ui-tabbar__label", children: item.label })] }));
|
|
20
|
+
const props = {
|
|
21
|
+
className: 'ui-tabbar__item',
|
|
22
|
+
'aria-current': active ? 'page' : undefined,
|
|
23
|
+
'aria-label': typeof item.badge === 'number' && item.badge > 0
|
|
24
|
+
? `${item.label}, ${item.badge}`
|
|
25
|
+
: undefined,
|
|
26
|
+
'data-active': active ? 'true' : 'false',
|
|
27
|
+
onClick: () => onValueChange?.(item.value),
|
|
28
|
+
children,
|
|
29
|
+
};
|
|
30
|
+
return (_jsx("span", { className: "ui-tabbar__cell", children: item.render ? item.render(props) : _jsx("button", { type: "button", ...props }) }, item.value));
|
|
31
|
+
}) }));
|
|
32
|
+
}
|
|
33
|
+
/** Reserves the bar's height in the flow, hidden at the same breakpoint as the bar. */
|
|
34
|
+
export function TabBarSpacer({ hideFrom = 'md' }) {
|
|
35
|
+
return _jsx("div", { className: "ui-tabbar-spacer", "data-hide-from": hideFrom, "aria-hidden": "true" });
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TabBar.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TabBar.js';
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { TextArea } from '@radix-ui/themes';
|
|
2
2
|
import { type ComponentPropsWithoutRef } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* `inputMode` and `enterKeyHint` pass through to the `<textarea>`. On coarse pointers the text is
|
|
5
|
+
* never below 16px, or iOS zooms the page on focus.
|
|
6
|
+
*/
|
|
3
7
|
export interface TextareaProps extends Omit<ComponentPropsWithoutRef<typeof TextArea>, 'size' | 'color'> {
|
|
4
8
|
invalid?: boolean;
|
|
5
9
|
}
|
|
@@ -3,5 +3,5 @@ import { TextArea } from '@radix-ui/themes';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { cn } from '../../utils/cn.js';
|
|
5
5
|
export const Textarea = forwardRef(function Textarea({ invalid = false, className, rows = 3, ...props }, ref) {
|
|
6
|
-
return (_jsx(TextArea, { ref: ref, rows: rows, size: "2", color: invalid ? 'red' : undefined, "aria-invalid": invalid || undefined, className: cn('w-full', className), ...props }));
|
|
6
|
+
return (_jsx(TextArea, { ref: ref, rows: rows, size: "2", color: invalid ? 'red' : undefined, "aria-invalid": invalid || undefined, className: cn('ui-textarea w-full', className), ...props }));
|
|
7
7
|
});
|
|
@@ -44,7 +44,13 @@ export declare const toast: typeof show & {
|
|
|
44
44
|
export interface ToasterProps {
|
|
45
45
|
/** Milliseconds a toast stays when it was not given its own `duration`. */
|
|
46
46
|
duration?: number;
|
|
47
|
-
position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
|
47
|
+
position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
|
|
48
|
+
/**
|
|
49
|
+
* Distance from the anchored edge (top for `top-*`, bottom for `bottom-*`). A number is px; a
|
|
50
|
+
* string is any CSS length, so a toast can sit under a nav bar or above a tab bar:
|
|
51
|
+
* `offset="var(--navbar-height)"`, `offset="calc(var(--tabbar-height) + 8px)"`.
|
|
52
|
+
*/
|
|
53
|
+
offset?: number | string;
|
|
48
54
|
/** The landmark name screen readers announce, e.g. "Notificações ({hotkey})". */
|
|
49
55
|
label?: string;
|
|
50
56
|
}
|
|
@@ -55,5 +61,5 @@ export interface ToasterProps {
|
|
|
55
61
|
* stack its live-region announcements, the F8 hotkey to reach it, pause-on-hover and swipe to
|
|
56
62
|
* dismiss.
|
|
57
63
|
*/
|
|
58
|
-
export declare function Toaster({ duration, position, label }: ToasterProps): import("react").JSX.Element;
|
|
64
|
+
export declare function Toaster({ duration, position, offset, label, }: ToasterProps): import("react").JSX.Element;
|
|
59
65
|
export {};
|
|
@@ -68,6 +68,8 @@ const POSITIONS = {
|
|
|
68
68
|
'top-left': 'top-0 left-0',
|
|
69
69
|
'bottom-right': 'bottom-0 right-0 flex-col-reverse',
|
|
70
70
|
'bottom-left': 'bottom-0 left-0 flex-col-reverse',
|
|
71
|
+
'top-center': 'top-0 left-1/2 -translate-x-1/2',
|
|
72
|
+
'bottom-center': 'bottom-0 left-1/2 -translate-x-1/2 flex-col-reverse',
|
|
71
73
|
};
|
|
72
74
|
/**
|
|
73
75
|
* Renders the stack. Mount once, inside `<Theme>` so the toasts take the app's palette.
|
|
@@ -76,10 +78,21 @@ const POSITIONS = {
|
|
|
76
78
|
* stack its live-region announcements, the F8 hotkey to reach it, pause-on-hover and swipe to
|
|
77
79
|
* dismiss.
|
|
78
80
|
*/
|
|
79
|
-
export function Toaster({ duration = 5000, position = 'bottom-right', label }) {
|
|
81
|
+
export function Toaster({ duration = 5000, position = 'bottom-right', offset, label, }) {
|
|
80
82
|
const items = useSyncExternalStore(subscribe, () => records, () => records);
|
|
81
83
|
const strings = useUiStrings();
|
|
82
|
-
|
|
84
|
+
// Centred stacks dismiss vertically, towards the edge they are anchored to: that is the way a
|
|
85
|
+
// thumb flicks a banner away, and sideways would fight the browser's back-swipe.
|
|
86
|
+
const swipeDirection = position.endsWith('center')
|
|
87
|
+
? position.startsWith('top')
|
|
88
|
+
? 'up'
|
|
89
|
+
: 'down'
|
|
90
|
+
: position.endsWith('left')
|
|
91
|
+
? 'left'
|
|
92
|
+
: 'right';
|
|
93
|
+
const vertical = swipeDirection === 'up' || swipeDirection === 'down';
|
|
94
|
+
const edge = position.startsWith('top') ? 'top' : 'bottom';
|
|
95
|
+
const edgeOffset = typeof offset === 'number' ? `${offset}px` : offset;
|
|
83
96
|
return (_jsxs(RadixToast.Provider, { duration: duration, swipeDirection: swipeDirection, label: label, children: [items.map((item) => {
|
|
84
97
|
const { color, icon } = TYPES[item.type];
|
|
85
98
|
return (_jsxs(RadixToast.Root, { open: item.open, duration: item.duration, type: item.type === 'error' ? 'foreground' : 'background', onOpenChange: (open) => {
|
|
@@ -88,10 +101,12 @@ export function Toaster({ duration = 5000, position = 'bottom-right', label }) {
|
|
|
88
101
|
}, onAnimationEnd: () => {
|
|
89
102
|
if (!item.open)
|
|
90
103
|
remove(item.id);
|
|
91
|
-
}, "data-accent-color": color,
|
|
104
|
+
}, "data-accent-color": color, "data-swipe-axis": vertical ? 'y' : undefined, style: vertical
|
|
105
|
+
? { '--ui-toast-swipe-sign': swipeDirection === 'up' ? -1 : 1 }
|
|
106
|
+
: undefined, className: "ui-toast panel pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden py-3 pr-3 pl-4", children: [_jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 w-1 bg-[var(--accent-9)]" }), _jsx(Icon, { name: icon, className: "mt-0.5 text-[var(--accent-11)]" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(RadixToast.Title, { className: "text-sm font-medium text-ink", children: item.title }), item.description ? (_jsx(RadixToast.Description, { className: "mt-0.5 text-sm text-ink-muted", children: item.description })) : null] }), item.action ? (_jsx(RadixToast.Action, { altText: item.action.label, onClick: (event) => {
|
|
92
107
|
item.action?.onClick();
|
|
93
108
|
if (item.action?.keepOpen)
|
|
94
109
|
event.preventDefault();
|
|
95
110
|
}, className: cn('shrink-0 rounded-md px-2 py-1 text-sm font-medium', 'text-[var(--accent-11)] hover:bg-[var(--accent-a3)]'), children: item.action.label })) : null, _jsx(RadixToast.Close, { "aria-label": strings.dismiss, className: "shrink-0 rounded-md p-1 text-ink-muted hover:bg-[var(--gray-a3)]", children: _jsx(Icon, { name: "close", className: "size-4" }) })] }, item.id));
|
|
96
|
-
}), _jsx(RadixToast.Viewport, { ref: warnMissingScales, className: cn('fixed z-50 m-0 flex w-full max-w-sm list-none flex-col gap-2 p-4 outline-none', POSITIONS[position]) })] }));
|
|
111
|
+
}), _jsx(RadixToast.Viewport, { ref: warnMissingScales, style: edgeOffset === undefined ? undefined : { [edge]: edgeOffset }, className: cn('fixed z-50 m-0 flex w-full max-w-sm list-none flex-col gap-2 p-4 outline-none', POSITIONS[position]) })] }));
|
|
97
112
|
}
|
package/dist/atoms/index.d.ts
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
|
+
export * from './ActionSheet/index.js';
|
|
1
2
|
export * from './Alert/index.js';
|
|
2
3
|
export * from './Avatar/index.js';
|
|
3
4
|
export * from './Badge/index.js';
|
|
4
5
|
export * from './Button/index.js';
|
|
5
6
|
export * from './Card/index.js';
|
|
6
7
|
export * from './Checkbox/index.js';
|
|
8
|
+
export * from './ChipGroup/index.js';
|
|
7
9
|
export * from './ContextMenu/index.js';
|
|
8
10
|
export * from './Dialog/index.js';
|
|
9
11
|
export * from './Drawer/index.js';
|
|
10
12
|
export * from './Icon/index.js';
|
|
11
13
|
export * from './Input/index.js';
|
|
12
14
|
export * from './Label/index.js';
|
|
15
|
+
export * from './List/index.js';
|
|
16
|
+
export * from './NavBar/index.js';
|
|
17
|
+
export * from './NotificationCard/index.js';
|
|
13
18
|
export * from './Popover/index.js';
|
|
14
19
|
export * from './Progress/index.js';
|
|
20
|
+
export * from './PullToRefresh/index.js';
|
|
21
|
+
export * from './ResponsiveDialog/index.js';
|
|
15
22
|
export * from './RichText/index.js';
|
|
23
|
+
export * from './ScrollStrip/index.js';
|
|
24
|
+
export * from './SegmentedControl/index.js';
|
|
16
25
|
export * from './Select/index.js';
|
|
17
26
|
export * from './Separator/index.js';
|
|
27
|
+
export * from './Sheet/index.js';
|
|
18
28
|
export * from './Skeleton/index.js';
|
|
19
29
|
export * from './Slider/index.js';
|
|
20
30
|
export * from './Spinner/index.js';
|
|
31
|
+
export * from './StatTile/index.js';
|
|
21
32
|
export * from './Switch/index.js';
|
|
33
|
+
export * from './TabBar/index.js';
|
|
22
34
|
export * from './Textarea/index.js';
|
|
23
35
|
export * from './Toast/index.js';
|
|
24
36
|
export * from './Tooltip/index.js';
|
package/dist/atoms/index.js
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
|
+
export * from './ActionSheet/index.js';
|
|
1
2
|
export * from './Alert/index.js';
|
|
2
3
|
export * from './Avatar/index.js';
|
|
3
4
|
export * from './Badge/index.js';
|
|
4
5
|
export * from './Button/index.js';
|
|
5
6
|
export * from './Card/index.js';
|
|
6
7
|
export * from './Checkbox/index.js';
|
|
8
|
+
export * from './ChipGroup/index.js';
|
|
7
9
|
export * from './ContextMenu/index.js';
|
|
8
10
|
export * from './Dialog/index.js';
|
|
9
11
|
export * from './Drawer/index.js';
|
|
10
12
|
export * from './Icon/index.js';
|
|
11
13
|
export * from './Input/index.js';
|
|
12
14
|
export * from './Label/index.js';
|
|
15
|
+
export * from './List/index.js';
|
|
16
|
+
export * from './NavBar/index.js';
|
|
17
|
+
export * from './NotificationCard/index.js';
|
|
13
18
|
export * from './Popover/index.js';
|
|
14
19
|
export * from './Progress/index.js';
|
|
20
|
+
export * from './PullToRefresh/index.js';
|
|
21
|
+
export * from './ResponsiveDialog/index.js';
|
|
15
22
|
export * from './RichText/index.js';
|
|
23
|
+
export * from './ScrollStrip/index.js';
|
|
24
|
+
export * from './SegmentedControl/index.js';
|
|
16
25
|
export * from './Select/index.js';
|
|
17
26
|
export * from './Separator/index.js';
|
|
27
|
+
export * from './Sheet/index.js';
|
|
18
28
|
export * from './Skeleton/index.js';
|
|
19
29
|
export * from './Slider/index.js';
|
|
20
30
|
export * from './Spinner/index.js';
|
|
31
|
+
export * from './StatTile/index.js';
|
|
21
32
|
export * from './Switch/index.js';
|
|
33
|
+
export * from './TabBar/index.js';
|
|
22
34
|
export * from './Textarea/index.js';
|
|
23
35
|
export * from './Toast/index.js';
|
|
24
36
|
export * from './Tooltip/index.js';
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
* reaches for a `Table` or `Tabs` through this package rather than importing Themes beside it
|
|
7
7
|
* and drifting from the version the atoms were built against.
|
|
8
8
|
*/
|
|
9
|
-
export { AccessibleIcon, AlertDialog, AspectRatio, Blockquote, Box, Callout, CheckboxCards, CheckboxGroup, Code, Container, DataList, DropdownMenu, Em, Flex, Grid, Heading, HoverCard, IconButton, Inset, Kbd, Link, Portal, Quote, Radio, RadioCards, RadioGroup, Reset, ScrollArea, Section, SegmentedControl, Slot, Slottable, Strong, Table, TabNav, Tabs, Text, TextField, Theme as ThemeRoot, ThemePanel, VisuallyHidden, } from '@radix-ui/themes';
|
|
9
|
+
export { AccessibleIcon, AlertDialog, AspectRatio, Blockquote, Box, Callout, CheckboxCards, CheckboxGroup, Code, Container, DataList, DropdownMenu, Em, Flex, Grid, Heading, HoverCard, IconButton, Inset, Kbd, Link, Portal, Quote, Radio, RadioCards, RadioGroup, Reset, ScrollArea, Section, SegmentedControl as RadixSegmentedControl, Slot, Slottable, Strong, Table, TabNav, Tabs, Text, TextField, Theme as ThemeRoot, ThemePanel, VisuallyHidden, } from '@radix-ui/themes';
|
package/dist/primitives/index.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
* reaches for a `Table` or `Tabs` through this package rather than importing Themes beside it
|
|
7
7
|
* and drifting from the version the atoms were built against.
|
|
8
8
|
*/
|
|
9
|
-
export { AccessibleIcon, AlertDialog, AspectRatio, Blockquote, Box, Callout, CheckboxCards, CheckboxGroup, Code, Container, DataList, DropdownMenu, Em, Flex, Grid, Heading, HoverCard, IconButton, Inset, Kbd, Link, Portal, Quote, Radio, RadioCards, RadioGroup, Reset, ScrollArea, Section, SegmentedControl, Slot, Slottable, Strong, Table, TabNav, Tabs, Text, TextField, Theme as ThemeRoot, ThemePanel, VisuallyHidden, } from '@radix-ui/themes';
|
|
9
|
+
export { AccessibleIcon, AlertDialog, AspectRatio, Blockquote, Box, Callout, CheckboxCards, CheckboxGroup, Code, Container, DataList, DropdownMenu, Em, Flex, Grid, Heading, HoverCard, IconButton, Inset, Kbd, Link, Portal, Quote, Radio, RadioCards, RadioGroup, Reset, ScrollArea, Section, SegmentedControl as RadixSegmentedControl, Slot, Slottable, Strong, Table, TabNav, Tabs, Text, TextField, Theme as ThemeRoot, ThemePanel, VisuallyHidden, } from '@radix-ui/themes';
|
package/dist/strings.d.ts
CHANGED
|
@@ -28,12 +28,22 @@ export interface UiStrings {
|
|
|
28
28
|
heading: string;
|
|
29
29
|
bulletList: string;
|
|
30
30
|
orderedList: string;
|
|
31
|
-
/** Drawer: the close button's accessible name. */
|
|
31
|
+
/** Drawer and NotificationCard: the close button's accessible name. */
|
|
32
32
|
close: string;
|
|
33
|
-
/** Drawer
|
|
33
|
+
/** Drawer handle / NotificationCard toggle, while collapsed. */
|
|
34
34
|
expand: string;
|
|
35
|
-
/** Drawer
|
|
35
|
+
/** Drawer handle / NotificationCard toggle, while expanded. */
|
|
36
36
|
collapse: string;
|
|
37
|
+
/** ListRow: the accessible name of the overflow button holding a row's actions. */
|
|
38
|
+
moreActions: string;
|
|
39
|
+
/** ActionSheet's separated button, and confirm()'s dismiss button. */
|
|
40
|
+
cancel: string;
|
|
41
|
+
/** confirm()'s default accept button. */
|
|
42
|
+
confirm: string;
|
|
43
|
+
/** BackButton's accessible name when it has no visible label. */
|
|
44
|
+
back: string;
|
|
45
|
+
/** PullToRefresh: announced while a refresh is in progress. */
|
|
46
|
+
refreshing: string;
|
|
37
47
|
}
|
|
38
48
|
/**
|
|
39
49
|
* Feeds the atoms their strings, once, near the root.
|
package/dist/strings.js
CHANGED
|
@@ -14,6 +14,11 @@ const DEFAULTS = {
|
|
|
14
14
|
close: 'Close',
|
|
15
15
|
expand: 'Expand',
|
|
16
16
|
collapse: 'Collapse',
|
|
17
|
+
moreActions: 'More actions',
|
|
18
|
+
cancel: 'Cancel',
|
|
19
|
+
confirm: 'Confirm',
|
|
20
|
+
back: 'Back',
|
|
21
|
+
refreshing: 'Refreshing',
|
|
17
22
|
};
|
|
18
23
|
const StringsContext = createContext(DEFAULTS);
|
|
19
24
|
/**
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Finds where a floating component may portal without leaving its theme.
|
|
4
|
+
*
|
|
5
|
+
* Radix Themes defines every colour variable on `.radix-themes` and flips light/dark with a
|
|
6
|
+
* class on that element, so a portal under `<body>` renders light whatever the app is in. The
|
|
7
|
+
* target is `container` when given, else the nearest `.radix-themes` above `anchorRef`, else
|
|
8
|
+
* nothing — meaning render in place.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useThemePortalTarget(container?: HTMLElement | null): {
|
|
11
|
+
anchorRef: import("react").RefObject<HTMLSpanElement | null>;
|
|
12
|
+
target: HTMLElement | null;
|
|
13
|
+
resolved: boolean;
|
|
14
|
+
};
|
|
15
|
+
/** Portals into `target` wrapped in a nested `<Theme>` (which inherits appearance and accent), or renders in place. */
|
|
16
|
+
export declare function ThemePortal({ target, children, }: {
|
|
17
|
+
target: HTMLElement | null;
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Theme } from '@radix-ui/themes';
|
|
3
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
/**
|
|
6
|
+
* Finds where a floating component may portal without leaving its theme.
|
|
7
|
+
*
|
|
8
|
+
* Radix Themes defines every colour variable on `.radix-themes` and flips light/dark with a
|
|
9
|
+
* class on that element, so a portal under `<body>` renders light whatever the app is in. The
|
|
10
|
+
* target is `container` when given, else the nearest `.radix-themes` above `anchorRef`, else
|
|
11
|
+
* nothing — meaning render in place.
|
|
12
|
+
*/
|
|
13
|
+
export function useThemePortalTarget(container) {
|
|
14
|
+
const anchorRef = useRef(null);
|
|
15
|
+
const [themeRoot, setThemeRoot] = useState(null);
|
|
16
|
+
const [resolved, setResolved] = useState(false);
|
|
17
|
+
useLayoutEffect(() => {
|
|
18
|
+
setThemeRoot(anchorRef.current?.closest('.radix-themes') ?? null);
|
|
19
|
+
setResolved(true);
|
|
20
|
+
}, []);
|
|
21
|
+
return { anchorRef, target: container ?? themeRoot, resolved: resolved || !!container };
|
|
22
|
+
}
|
|
23
|
+
/** Portals into `target` wrapped in a nested `<Theme>` (which inherits appearance and accent), or renders in place. */
|
|
24
|
+
export function ThemePortal({ target, children, }) {
|
|
25
|
+
if (!target)
|
|
26
|
+
return _jsx(_Fragment, { children: children });
|
|
27
|
+
return createPortal(_jsx(Theme, { hasBackground: false, children: children }), target);
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kennycorrea/ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "A React + TypeScript component library built on Radix Themes: atoms, a Tailwind token bridge and theming.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "UNLICENSED",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
"react-dom": "^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@radix-ui/react-alert-dialog": "^1.1.23",
|
|
39
|
+
"@radix-ui/react-dialog": "^1.3.1",
|
|
38
40
|
"@radix-ui/react-icons": "^1.3.2",
|
|
39
41
|
"@radix-ui/react-slider": "^1.5.0",
|
|
40
42
|
"@radix-ui/react-toast": "^1.2.23",
|