@viraui/react 2026.11.0-next.1 → 2026.11.0-next.2
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/components/gauge/demos/tooltip-portal.d.ts +10 -0
- package/dist/components/gauge/gauge.css +1 -1
- package/dist/components/gauge/tooltip.d.ts +7 -0
- package/dist/components/gauge/tooltip.js +10 -7
- package/dist/specs/components/gauge/props.xml +3 -0
- package/dist/specs/components/gauge/usage.xml +1 -0
- package/dist/specs/index.xml +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
type TooltipPortalDemoProps = {
|
|
3
|
+
value?: number;
|
|
4
|
+
min?: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
label?: string;
|
|
7
|
+
};
|
|
8
|
+
/** Forced-open tooltip portalled into a custom host (iframe / sandbox body). */
|
|
9
|
+
export declare function TooltipPortalDemo({ value, min, max, label }: TooltipPortalDemoProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-gauge-aspect-ratio{syntax:"*";inherits:false;initial-value:1}.viraui__gauge-module__Gauge_XrCKK{overflow:visible;color:var(--global-foreground);&[data-fit=square]{inline-size:100%;block-size:100%}&[data-fit=content]{inline-size:100%;max-block-size:100%;aspect-ratio:var(--vui-gauge-aspect-ratio)}}.viraui__gauge-module__Control_33uqc{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;outline:none;cursor:grab;aspect-ratio:1;border-radius:var(--radius-full);&[data-disabled=true]{cursor:default}&:not([data-disabled=true]):active{cursor:grabbing}&:focus-visible,&:has(:focus-visible:not([data-pointer])){outline:var(--outline);outline-offset:var(--outline-offset)}}.viraui__gauge-module__VisuallyHidden_LUbhj{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;&:focus-visible{outline:none}}.viraui__gauge-module__TooltipPositioner_5wZsF{position:absolute;inset-block-start:0;inset-inline-start:0;z-index:50;pointer-events:none}.viraui__gauge-module__Tooltip_BRUR6{box-sizing:border-box;inline-size:max-content;max-inline-size:20rem;padding-block:var(--space-2xs);padding-inline:var(--space-s);border-radius:var(--radius-
|
|
1
|
+
@layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-gauge-aspect-ratio{syntax:"*";inherits:false;initial-value:1}.viraui__gauge-module__Gauge_XrCKK{overflow:visible;color:var(--global-foreground);&[data-fit=square]{inline-size:100%;block-size:100%}&[data-fit=content]{inline-size:100%;max-block-size:100%;aspect-ratio:var(--vui-gauge-aspect-ratio)}}.viraui__gauge-module__Control_33uqc{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;outline:none;cursor:grab;aspect-ratio:1;border-radius:var(--radius-full);&[data-disabled=true]{cursor:default}&:not([data-disabled=true]):active{cursor:grabbing}&:focus-visible,&:has(:focus-visible:not([data-pointer])){outline:var(--outline);outline-offset:var(--outline-offset)}}.viraui__gauge-module__VisuallyHidden_LUbhj{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;&:focus-visible{outline:none}}.viraui__gauge-module__TooltipPositioner_5wZsF{position:absolute;inset-block-start:0;inset-inline-start:0;z-index:50;pointer-events:none}.viraui__gauge-module__Tooltip_BRUR6{box-sizing:border-box;inline-size:max-content;max-inline-size:20rem;padding-block:var(--space-2xs);padding-inline:var(--space-s);border-radius:var(--radius-s);background:var(--global-foreground);color:var(--global-background);font-size:var(--font-scale-body-s);animation:viraui__gauge-module__gauge-tooltip-in_5JTLs var(--duration-fast) var(--easing-entrance);@media (prefers-reduced-motion:reduce){animation:none}}.viraui__gauge-module__TooltipBody_44-M9{display:flex;flex-direction:column;align-items:center;line-height:1.15}.viraui__gauge-module__TooltipLabel_T-Hp5{opacity:.7}.viraui__gauge-module__TooltipValue_gAqRL{font-size:var(--font-scale-body-m);font-weight:600;font-variation-settings:"wght" 600;font-variant-numeric:tabular-nums}.viraui__gauge-module__TooltipUnit_iIW0i{margin-inline-start:var(--space-2xs);font-size:var(--font-scale-body-s);font-weight:500;font-variation-settings:"wght" 500;opacity:.7}@keyframes viraui__gauge-module__gauge-tooltip-in_5JTLs{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}}
|
|
@@ -61,6 +61,13 @@ export type GaugeTooltipProps = {
|
|
|
61
61
|
* @defaultValue undefined
|
|
62
62
|
*/
|
|
63
63
|
open?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* DOM node the bubble portals into. Defaults to `document.body`. Pass the
|
|
66
|
+
* sandbox / iframe body (or another host) when the dial is not in the same
|
|
67
|
+
* document as the page shell — otherwise the bubble paints off-canvas.
|
|
68
|
+
* @defaultValue `document.body`
|
|
69
|
+
*/
|
|
70
|
+
container?: HTMLElement | null;
|
|
64
71
|
/**
|
|
65
72
|
* Small line above the value. Leave out for the value on its own.
|
|
66
73
|
* @defaultValue undefined
|
|
@@ -110,7 +110,7 @@ var DefaultContent = ({ text, label, unit }) => /* @__PURE__ */ jsxs("div", {
|
|
|
110
110
|
* transform, so it is never clipped by the gauge and keeps its own CSS size
|
|
111
111
|
* however the gauge, or an inset it sits in, is scaled.
|
|
112
112
|
*/
|
|
113
|
-
var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap = 8, avoidCollisions = true, collisionPadding = 8, open, label, unit, decimals = 0, format, separator = "–", className, style, children }) => {
|
|
113
|
+
var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap = 8, avoidCollisions = true, collisionPadding = 8, open, container = null, label, unit, decimals = 0, format, separator = "–", className, style, children }) => {
|
|
114
114
|
const gauge = useGauge();
|
|
115
115
|
const isClient = useIsClient();
|
|
116
116
|
const anchor = React.useRef(null);
|
|
@@ -181,6 +181,8 @@ var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap =
|
|
|
181
181
|
el.style.visibility = "hidden";
|
|
182
182
|
return;
|
|
183
183
|
}
|
|
184
|
+
const doc = el.ownerDocument;
|
|
185
|
+
const win = doc.defaultView ?? window;
|
|
184
186
|
const size = {
|
|
185
187
|
width: el.offsetWidth,
|
|
186
188
|
height: el.offsetHeight
|
|
@@ -189,8 +191,8 @@ var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap =
|
|
|
189
191
|
let atPoint = corner(p, d, size, gap);
|
|
190
192
|
if (avoidCollisions) {
|
|
191
193
|
const view = {
|
|
192
|
-
width:
|
|
193
|
-
height:
|
|
194
|
+
width: doc.documentElement.clientWidth,
|
|
195
|
+
height: doc.documentElement.clientHeight
|
|
194
196
|
};
|
|
195
197
|
const pad = collisionPadding;
|
|
196
198
|
const spill = (spot, axis) => {
|
|
@@ -223,8 +225,8 @@ var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap =
|
|
|
223
225
|
}
|
|
224
226
|
}
|
|
225
227
|
el.style.visibility = "";
|
|
226
|
-
el.style.left = `${atPoint.x +
|
|
227
|
-
el.style.top = `${atPoint.y +
|
|
228
|
+
el.style.left = `${atPoint.x + win.scrollX}px`;
|
|
229
|
+
el.style.top = `${atPoint.y + win.scrollY}px`;
|
|
228
230
|
});
|
|
229
231
|
React.useEffect(() => {
|
|
230
232
|
const svg = anchor.current?.ownerSVGElement;
|
|
@@ -319,7 +321,8 @@ var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap =
|
|
|
319
321
|
label,
|
|
320
322
|
unit
|
|
321
323
|
});
|
|
322
|
-
|
|
324
|
+
const portalRoot = container ?? (typeof document !== "undefined" ? document.body : null);
|
|
325
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("g", { ref: anchor }), shown && isClient && portalRoot && createPortal(/* @__PURE__ */ jsx("div", {
|
|
323
326
|
ref: box,
|
|
324
327
|
className: gauge_module_default.TooltipPositioner,
|
|
325
328
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -330,7 +333,7 @@ var GaugeTooltip = ({ position = "value", side = "auto", at, offset = 24, gap =
|
|
|
330
333
|
className: clsx(gauge_module_default.Tooltip, className),
|
|
331
334
|
children: content
|
|
332
335
|
})
|
|
333
|
-
}),
|
|
336
|
+
}), portalRoot)] });
|
|
334
337
|
};
|
|
335
338
|
//#endregion
|
|
336
339
|
export { GaugeTooltip };
|
|
@@ -417,6 +417,9 @@
|
|
|
417
417
|
<prop name="GaugeTooltip.open" kind="react">
|
|
418
418
|
<description>Force open or shut instead of hover/press/focus.</description>
|
|
419
419
|
</prop>
|
|
420
|
+
<prop name="GaugeTooltip.container" kind="react">
|
|
421
|
+
<description>Portal host for the bubble. Default `document.body`. Pass an iframe/sandbox body when the dial is not in the page document.</description>
|
|
422
|
+
</prop>
|
|
420
423
|
<prop name="GaugeTooltip.label" kind="react">
|
|
421
424
|
<description>Small line above the value.</description>
|
|
422
425
|
</prop>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<do>When you need paint, pass theme CSS vars as strings on `color` (and Needle `tailColor`, TickFill `dimColor`, Dot `haloColor`, Zones `zones[].color`): `--global-*` for chrome/labels (`foreground`, `background`, `primary`, `contrast`, `muted`), `--highlight-*` for status/decorative bands (`red`, `green`, `yellow`, `cyan`, `acid`, `blue`, `purple`, …)</do>
|
|
7
7
|
<do>Zone-driven readings: put token colors on `zones[].color`, then reuse with `zoneColor(zones, value)` (or `zoneCutoffs`) on Arc / Marks so the live fill matches the active band</do>
|
|
8
8
|
<do>Pass `label` on read-only roots (or `aria-label`) and always pass `label` on `GaugeControl`</do>
|
|
9
|
+
<do>When the dial lives in an iframe or docs sandbox, pass `GaugeTooltip` `container` to that document's `body` so the bubble portals with the dial</do>
|
|
9
10
|
<do>Prefer `Meter` for compact horizontal capacity chrome; prefer `Slider` for linear interactive ranges; prefer Gauge when polar composition or dial Control is needed</do>
|
|
10
11
|
<do>Needle visual style prop is `kind` (not upstream `style`) to avoid clashing with React `style`</do>
|
|
11
12
|
<dont>Using Gauge / GaugeControl as a linear bar — use Slider (or Meter / LinearProgress for non-interactive)</dont>
|
package/dist/specs/index.xml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<index package="@viraui/react" version="2026.11.0-next.
|
|
2
|
+
<index package="@viraui/react" version="2026.11.0-next.2" generated="2026-10-28T10:39:16.158Z">
|
|
3
3
|
<categories>
|
|
4
4
|
<category id="layout" />
|
|
5
5
|
<category id="action" />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viraui/react",
|
|
3
|
-
"version": "2026.11.0-next.
|
|
3
|
+
"version": "2026.11.0-next.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@base-ui/react": ">=1.8.0",
|
|
31
|
-
"@viraui/foundation": "2026.11.0-next.
|
|
31
|
+
"@viraui/foundation": "2026.11.0-next.2",
|
|
32
32
|
"@viraui/icons": "2026.1.0",
|
|
33
33
|
"@viraui/postcss-config": "2026.0.0",
|
|
34
34
|
"@viraui/tsconfig": "2026.0.0",
|