@viraui/react 1.0.12 → 1.0.13
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/dist/catalog.json +6 -0
- package/dist/components/badge/badge.css +1 -0
- package/dist/components/badge/badge.d.ts +39 -0
- package/dist/components/badge/badge.guide.json +55 -0
- package/dist/components/badge/badge.js +50 -0
- package/dist/components/badge/badge.module.js +11 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/button/button-link.js +1 -1
- package/dist/components/button/button.js +1 -1
- package/dist/components/chip/chip.js +1 -1
- package/dist/components/clamp-text/clamp-text.js +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/masonry/masonry.js +1 -1
- package/dist/index.js +2 -1
- package/package.json +3 -3
package/dist/catalog.json
CHANGED
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
"summary": "Overlapping avatar stack with shared sizing, directional layout, and an optional overflow pill.",
|
|
27
27
|
"guidePath": "./components/avatar-group/avatar-group.guide.json"
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
"id": "badge",
|
|
31
|
+
"name": "Badge",
|
|
32
|
+
"summary": "Decorative status-dot overlay that wraps a child, with optional radial mask cutout on the child around the corner dot.",
|
|
33
|
+
"guidePath": "./components/badge/badge.guide.json"
|
|
34
|
+
},
|
|
29
35
|
{
|
|
30
36
|
"id": "bleed",
|
|
31
37
|
"name": "Bleed",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-badge-size{syntax:"<length>";inherits:true;initial-value:12px}@property --vui-badge-color{syntax:"<color>";inherits:true;initial-value:#292929}@property --_badge-hole-progress{syntax:"<number>";inherits:true;initial-value:0}.viraui__badge-module__Badge_lJqlY{--vui-badge-color:var(--global-primary);--vui-badge-size:0.074rem;--vui-badge-position-x:100%;--vui-badge-position-y:0%;--_badge-gap:calc(var(--vui-badge-size) * 0.25);--_badge-mask-size:calc(var(--vui-badge-size) / 2 + var(--_badge-gap));--_badge-hole-progress:0;position:relative;display:inline-flex;&[data-position=top-end]{--vui-badge-position-x:100%;--vui-badge-position-y:0%}&[data-position=top-start]{--vui-badge-position-x:0%;--vui-badge-position-y:0%}&[data-position=bottom-end]{--vui-badge-position-x:100%;--vui-badge-position-y:100%}&[data-position=bottom-start]{--vui-badge-position-x:0%;--vui-badge-position-y:100%}&>*{outline-offset:-4px}&[data-show=true]{&:after{content:"";width:var(--vui-badge-size);aspect-ratio:1;display:block;border-radius:100000px;background:var(--vui-badge-color);position:absolute;left:calc(var(--vui-badge-position-x) - min(var(--vui-badge-position-x), var(--vui-badge-size)));top:calc(var(--vui-badge-position-y) - min(var(--vui-badge-position-y), var(--vui-badge-size)));pointer-events:none;transform-origin:center}&:not([data-exit]):after{transform:scale(0);animation:viraui__badge-module__badge-dot-in_SKMx8 var(--duration-fast) var(--easing-entrance) 60ms forwards}&[data-exit]:after{transform:scale(1);animation:viraui__badge-module__badge-dot-out_vWhcP var(--duration-fast) var(--easing-entrance) forwards}&>*{mask-image:radial-gradient(circle at calc(var(--vui-badge-position-x) - min(var(--vui-badge-position-x), var(--vui-badge-size)) + (var(--vui-badge-size) / 2)) calc(var(--vui-badge-position-y) - min(var(--vui-badge-position-y), var(--vui-badge-size)) + (var(--vui-badge-size) / 2)),#0000 0 calc(var(--_badge-mask-size) * var(--_badge-hole-progress)),red calc(var(--_badge-mask-size) * var(--_badge-hole-progress) + 1px))}&:not([data-exit])>*{animation:viraui__badge-module__badge-hole-in_71iZP var(--duration-fast) var(--easing-entrance) forwards}&[data-exit]>*{--_badge-hole-progress:1;animation:viraui__badge-module__badge-hole-out_JCHCf var(--duration-fast) var(--easing-entrance) 60ms forwards}@media (prefers-reduced-motion:reduce){&:after{transform:none}&:after,&>*{animation:none}&>*{--_badge-hole-progress:1}&[data-exit]>*{--_badge-hole-progress:0}}}}@keyframes viraui__badge-module__badge-hole-in_71iZP{0%{--_badge-hole-progress:0}to{--_badge-hole-progress:1}}@keyframes viraui__badge-module__badge-hole-out_JCHCf{0%{--_badge-hole-progress:1}to{--_badge-hole-progress:0}}@keyframes viraui__badge-module__badge-dot-in_SKMx8{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes viraui__badge-module__badge-dot-out_vWhcP{0%{transform:scale(1)}to{transform:scale(0)}}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ThemeTypes } from '@viraui/foundation/vira/types';
|
|
2
|
+
import type * as React from 'react';
|
|
3
|
+
export type BadgePosition = 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start';
|
|
4
|
+
/**
|
|
5
|
+
* Public Badge props.
|
|
6
|
+
*
|
|
7
|
+
* Includes standard `div` attributes such as `children`, `id`, `className`, and event handlers,
|
|
8
|
+
* plus Vira-owned decorative status-dot controls.
|
|
9
|
+
*
|
|
10
|
+
* @default Native div pass-through props keep React defaults.
|
|
11
|
+
*/
|
|
12
|
+
export type BadgeProps = React.ComponentPropsWithRef<'div'> & {
|
|
13
|
+
/**
|
|
14
|
+
* Diameter of the status dot via `--vui-badge-size`.
|
|
15
|
+
*
|
|
16
|
+
* @default '12px'
|
|
17
|
+
*/
|
|
18
|
+
size?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Highlight token driving the status-dot color via `--vui-badge-color`.
|
|
21
|
+
*
|
|
22
|
+
* @default `var(--global-primary)` when omitted
|
|
23
|
+
*/
|
|
24
|
+
color?: ThemeTypes['highlight'];
|
|
25
|
+
/**
|
|
26
|
+
* When true, shows the decorative status dot and applies the radial mask cutout.
|
|
27
|
+
* Enter: hole expands, then the dot scales in. Exit: reverse (dot then hole).
|
|
28
|
+
*
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
show?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Places the status dot on a corner of the wrapped content.
|
|
34
|
+
*
|
|
35
|
+
* @default 'top-end'
|
|
36
|
+
*/
|
|
37
|
+
position?: BadgePosition;
|
|
38
|
+
};
|
|
39
|
+
export declare const Badge: React.FC<BadgeProps>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Badge",
|
|
3
|
+
"structure": "<Badge>{child}</Badge>",
|
|
4
|
+
"summary": "Decorative status-dot overlay that wraps a child, with optional radial mask cutout on the child around the corner dot.",
|
|
5
|
+
"whenToUse": [
|
|
6
|
+
"Show online/offline or presence on an Avatar or icon without changing the child component API",
|
|
7
|
+
"Mark a control as needing attention with a small corner indicator",
|
|
8
|
+
"Keep Chip for labeled text badges; use Badge only for the status-dot overlay"
|
|
9
|
+
],
|
|
10
|
+
"whenNotToUse": [
|
|
11
|
+
"Conveying critical status that assistive tech must announce — put real meaning in the child name or nearby text",
|
|
12
|
+
"Labeled text badges or tags — use Chip",
|
|
13
|
+
"Count or text inside a pill — out of scope for v1"
|
|
14
|
+
],
|
|
15
|
+
"accessibility": [
|
|
16
|
+
"The status dot is a decorative ::after pseudo — not exposed to assistive tech",
|
|
17
|
+
"Do not rely on the dot alone for status; keep real meaning in the child's accessible name or nearby text",
|
|
18
|
+
"Children retain native semantics; Badge itself is a presentational div wrap",
|
|
19
|
+
"Enter/exit motion (hole↔dot, reverse on hide) is suppressed under prefers-reduced-motion"
|
|
20
|
+
],
|
|
21
|
+
"antiPatterns": [
|
|
22
|
+
"Using the visible dot as the only source of status for assistive tech",
|
|
23
|
+
"Wrapping multiple element children when only one should receive the radial mask cutout",
|
|
24
|
+
"Expecting the dot to participate in hit-testing"
|
|
25
|
+
],
|
|
26
|
+
"related": ["Avatar", "AvatarGroup", "Chip", "Annotate"],
|
|
27
|
+
"properties": {
|
|
28
|
+
"react": {
|
|
29
|
+
"size": {
|
|
30
|
+
"description": "Diameter of the status dot via --vui-badge-size. Defaults to 12px.",
|
|
31
|
+
"refCss": "size"
|
|
32
|
+
},
|
|
33
|
+
"color": {
|
|
34
|
+
"description": "Highlight token driving the status-dot color via --vui-badge-color. When omitted, falls back to var(--global-primary).",
|
|
35
|
+
"refCss": "color"
|
|
36
|
+
},
|
|
37
|
+
"show": {
|
|
38
|
+
"description": "When true, shows the decorative status dot and applies the radial mask cutout to the direct child. Enter: hole expands from center, then the dot scales in. Exit: reverse (dot then hole). Defaults to false."
|
|
39
|
+
},
|
|
40
|
+
"position": {
|
|
41
|
+
"description": "Corner placement for the status dot (top-end, top-start, bottom-end, bottom-start). Defaults to top-end."
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"css": {
|
|
45
|
+
"size": {
|
|
46
|
+
"description": "Status-dot diameter. Defaults to 12px.",
|
|
47
|
+
"refReact": "size"
|
|
48
|
+
},
|
|
49
|
+
"color": {
|
|
50
|
+
"description": "Status-dot accent color. Defaults to var(--global-primary).",
|
|
51
|
+
"refReact": "color"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import './badge.css';
|
|
2
|
+
import { clsx } from "../../core/clsx.js";
|
|
3
|
+
import badge_module_default from "./badge.module.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
//#region src/components/badge/badge.tsx
|
|
7
|
+
var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
8
|
+
var Badge = ({ size = "10px", children, className, color, position = "top-end", ref, show = false, style, ...otherProps }) => {
|
|
9
|
+
const [present, setPresent] = useState(show);
|
|
10
|
+
const [exiting, setExiting] = useState(false);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (show) {
|
|
13
|
+
setPresent(true);
|
|
14
|
+
setExiting(false);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!present) return;
|
|
18
|
+
if (prefersReducedMotion()) {
|
|
19
|
+
setPresent(false);
|
|
20
|
+
setExiting(false);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setExiting(true);
|
|
24
|
+
}, [show, present]);
|
|
25
|
+
const handleAnimationEnd = (event) => {
|
|
26
|
+
if (!exiting) return;
|
|
27
|
+
if (!(event.target instanceof HTMLElement) || event.target.parentElement !== event.currentTarget) return;
|
|
28
|
+
if (!event.animationName.includes("badge-hole-out")) return;
|
|
29
|
+
setPresent(false);
|
|
30
|
+
setExiting(false);
|
|
31
|
+
};
|
|
32
|
+
const dynamicStyle = {
|
|
33
|
+
"--vui-badge-size": size,
|
|
34
|
+
...color && { "--vui-badge-color": `var(--highlight-${color})` },
|
|
35
|
+
...style
|
|
36
|
+
};
|
|
37
|
+
return /* @__PURE__ */ jsx("div", {
|
|
38
|
+
...otherProps,
|
|
39
|
+
ref,
|
|
40
|
+
className: clsx(badge_module_default.Badge, className),
|
|
41
|
+
"data-exit": exiting ? "true" : void 0,
|
|
42
|
+
"data-position": position,
|
|
43
|
+
"data-show": present ? "true" : void 0,
|
|
44
|
+
style: dynamicStyle,
|
|
45
|
+
onAnimationEnd: handleAnimationEnd,
|
|
46
|
+
children
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { Badge };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/components/badge/badge.module.css
|
|
2
|
+
var Badge = "viraui__badge-module__Badge_lJqlY";
|
|
3
|
+
var badge_module_default = {
|
|
4
|
+
Badge,
|
|
5
|
+
"badge-dot-in": "viraui__badge-module__badge-dot-in_SKMx8",
|
|
6
|
+
"badge-dot-out": "viraui__badge-module__badge-dot-out_vWhcP",
|
|
7
|
+
"badge-hole-in": "viraui__badge-module__badge-hole-in_71iZP",
|
|
8
|
+
"badge-hole-out": "viraui__badge-module__badge-hole-out_JCHCf"
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Badge, badge_module_default as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
4
3
|
import "react";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
5
|
//#region src/components/button/button-link.tsx
|
|
6
6
|
var ButtonLink = ({ children, className, disabled = false, addon, addonPosition = "start", loading = false, pill = false, size = "medium", variant = "primary", render, ref, onClick, ...otherProps }) => {
|
|
7
7
|
const isDisabled = disabled || loading;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import './button.css';
|
|
2
2
|
import { ButtonChromeChildren, getButtonChromeRootAttrs } from "./button-chrome.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import * as React from "react";
|
|
4
5
|
import { Button } from "@base-ui/react/button";
|
|
5
6
|
import { useRender } from "@base-ui/react/use-render";
|
|
6
|
-
import * as React from "react";
|
|
7
7
|
//#region src/components/button/button.tsx
|
|
8
8
|
function usesButtonPrimitiveRender(render) {
|
|
9
9
|
return render === void 0 || React.isValidElement(render) && render.type === "button";
|
|
@@ -3,8 +3,8 @@ import { clsx } from "../../core/clsx.js";
|
|
|
3
3
|
import { Stack } from "../stack/stack.js";
|
|
4
4
|
import chip_module_default from "./chip.module.js";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
7
6
|
import "react";
|
|
7
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
8
8
|
//#region src/components/chip/chip.tsx
|
|
9
9
|
var Chip = ({ addon, addonPosition = "start", children, className, ref, render, variant = "primary", ...otherProps }) => {
|
|
10
10
|
const content = /* @__PURE__ */ jsxs(Stack, {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import './clamp-text.css';
|
|
3
3
|
import { clsx } from "../../core/clsx.js";
|
|
4
4
|
import clamp_text_module_default from "./clamp-text.module.js";
|
|
5
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
6
5
|
import { useMemo } from "react";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
7
|
//#region src/components/clamp-text/clamp-text.tsx
|
|
8
8
|
var ClampText = ({ className, inline = false, ref, render, rows = 1, style, ...otherProps }) => {
|
|
9
9
|
const dynamicStyle = useMemo(() => ({ "--vui-clamp-text-rows": rows }), [rows]);
|
|
@@ -6,8 +6,8 @@ import { Stack } from "../stack/stack.js";
|
|
|
6
6
|
import masonry_module_default from "./masonry.module.js";
|
|
7
7
|
import { MasonryItem } from "./masonry-item.js";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
import { useRender } from "@base-ui/react/use-render";
|
|
10
9
|
import { Children, useEffect, useRef, useState } from "react";
|
|
10
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
11
11
|
//#region src/components/masonry/masonry.tsx
|
|
12
12
|
var DEFAULT_BREAKPOINT_COLS = {
|
|
13
13
|
default: 1,
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Accordion } from "./components/accordion/accordion.js";
|
|
|
2
2
|
import { Annotate } from "./components/annotate/annotate.js";
|
|
3
3
|
import { Avatar } from "./components/avatar/avatar.js";
|
|
4
4
|
import { AvatarGroup } from "./components/avatar-group/avatar-group.js";
|
|
5
|
+
import { Badge } from "./components/badge/badge.js";
|
|
5
6
|
import { Bleed } from "./components/bleed/bleed.js";
|
|
6
7
|
import { Spinner } from "./components/spinner/spinner.js";
|
|
7
8
|
import { Button } from "./components/button/button.js";
|
|
@@ -51,4 +52,4 @@ import { ToggleGroup } from "./components/toggle-group/toggle-group.js";
|
|
|
51
52
|
import { Typewriter } from "./components/typewriter/typewriter.js";
|
|
52
53
|
import { TooltipContent } from "./components/tooltip/tooltip-content.js";
|
|
53
54
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "./components/tooltip/tooltip.js";
|
|
54
|
-
export { Accordion, Annotate, Avatar, AvatarGroup, Bleed, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, IconButton, IconButtonLink, LinearProgress, Masonry, Meter, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps };
|
|
55
|
+
export { Accordion, Annotate, Avatar, AvatarGroup, Badge, Bleed, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, IconButton, IconButtonLink, LinearProgress, Masonry, Meter, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viraui/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"unplugin-dts": "1.0.3",
|
|
36
36
|
"vite": "8.1.4",
|
|
37
37
|
"vite-plugin-static-copy": "4.1.1",
|
|
38
|
-
"@viraui/foundation": "1.0.12",
|
|
39
38
|
"@viraui/icons": "0.1.7",
|
|
40
39
|
"@viraui/postcss-config": "0.0.18",
|
|
41
|
-
"@viraui/tsconfig": "0.0.17"
|
|
40
|
+
"@viraui/tsconfig": "0.0.17",
|
|
41
|
+
"@viraui/foundation": "1.0.13"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@base-ui/react": ">=1.6.0",
|