plass-ui 1.0.0 → 1.0.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/README.md +165 -0
- package/dist/components/accordion/PlAccordion.js +1 -131
- package/dist/components/accordion/index.js +1 -1
- package/dist/components/alert/PlAlert.js +1 -109
- package/dist/components/alert/index.js +1 -1
- package/dist/components/animate-appear/PlAnimateAppear.js +1 -71
- package/dist/components/animate-appear/index.js +1 -1
- package/dist/components/animate-blink/PlAnimateBlink.js +1 -47
- package/dist/components/animate-blink/index.js +1 -1
- package/dist/components/animate-fade/PlAnimateFade.js +1 -48
- package/dist/components/animate-fade/index.js +1 -1
- package/dist/components/animate-grow/PlAnimateGrow.js +1 -49
- package/dist/components/animate-grow/index.js +1 -1
- package/dist/components/animate-headline/PlAnimateHeadline.js +1 -120
- package/dist/components/animate-headline/index.js +1 -1
- package/dist/components/animate-lighting/PlAnimateLighting.js +1 -65
- package/dist/components/animate-lighting/index.js +1 -1
- package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -94
- package/dist/components/animate-marquee/index.js +1 -1
- package/dist/components/animate-rotate/PlAnimateRotate.js +1 -50
- package/dist/components/animate-rotate/index.js +1 -1
- package/dist/components/animate-slide/PlAnimateSlide.js +1 -49
- package/dist/components/animate-slide/index.js +1 -1
- package/dist/components/animate-typing/PlAnimateTyping.js +1 -177
- package/dist/components/animate-typing/index.js +1 -1
- package/dist/components/animate-zoom/PlAnimateZoom.js +1 -45
- package/dist/components/animate-zoom/index.js +1 -1
- package/dist/components/aspect-ratio/PlAspectRatio.js +1 -58
- package/dist/components/aspect-ratio/index.js +1 -1
- package/dist/components/avatar/PlAvatar.js +1 -121
- package/dist/components/avatar/index.js +1 -1
- package/dist/components/badge/PlBadge.js +1 -168
- package/dist/components/badge/index.js +1 -1
- package/dist/components/blockquote/PlBlockquote.js +1 -112
- package/dist/components/blockquote/index.js +1 -1
- package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -141
- package/dist/components/bottom-navigation/index.js +1 -1
- package/dist/components/box/PlBox.js +1 -46
- package/dist/components/box/index.js +1 -1
- package/dist/components/breadcrumb/PlBreadcrumb.js +1 -201
- package/dist/components/breadcrumb/index.js +1 -1
- package/dist/components/button/PlButton.js +1 -196
- package/dist/components/button/index.js +1 -1
- package/dist/components/button-group/PlButtonGroup.js +1 -64
- package/dist/components/button-group/index.js +1 -1
- package/dist/components/card/PlCard.js +1 -102
- package/dist/components/card/index.js +1 -1
- package/dist/components/carousel/PlCarousel.js +1 -177
- package/dist/components/carousel/index.js +1 -1
- package/dist/components/chat-bubble/PlChatBubble.js +1 -206
- package/dist/components/chat-bubble/index.js +1 -1
- package/dist/components/checkbox/PlCheckbox.js +1 -100
- package/dist/components/checkbox/index.js +1 -1
- package/dist/components/chip/PlChip.js +1 -144
- package/dist/components/chip/index.js +1 -1
- package/dist/components/collapsible/PlCollapsible.js +1 -65
- package/dist/components/collapsible/index.js +1 -1
- package/dist/components/combobox/PlCombobox.js +1 -199
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/container/PlContainer.js +1 -47
- package/dist/components/container/index.js +1 -1
- package/dist/components/date-picker/PlDatePicker.js +1 -87
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/PlDateRangePicker.js +1 -152
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/PlDateTimePicker.js +1 -106
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/divider/PlDivider.js +1 -107
- package/dist/components/divider/index.js +1 -1
- package/dist/components/drawer/PlDrawer.js +1 -190
- package/dist/components/drawer/index.js +1 -1
- package/dist/components/file-picker/PlFilePicker.js +1 -274
- package/dist/components/file-picker/index.js +1 -1
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -291
- package/dist/components/floating-bottom-navigation/index.js +1 -1
- package/dist/components/grid/PlGrid.js +1 -51
- package/dist/components/grid/PlGridItem.js +1 -34
- package/dist/components/grid/index.js +1 -2
- package/dist/components/highlight/PlHighlight.js +1 -185
- package/dist/components/highlight/index.js +1 -1
- package/dist/components/hot-keys/PlHotKeys.js +1 -294
- package/dist/components/hot-keys/index.js +1 -1
- package/dist/components/icon/PlIcon.js +1 -58
- package/dist/components/icon/index.js +1 -1
- package/dist/components/icon-button/PlIconButton.js +1 -37
- package/dist/components/icon-button/index.js +1 -1
- package/dist/components/list/PlList.js +1 -160
- package/dist/components/list/index.js +1 -1
- package/dist/components/menu/PlMenu.js +1 -209
- package/dist/components/menu/index.js +1 -1
- package/dist/components/modal/PlModal.js +1 -150
- package/dist/components/modal/index.js +1 -1
- package/dist/components/number-field/PlNumberField.js +1 -111
- package/dist/components/number-field/index.js +1 -1
- package/dist/components/otp-field/PlOtpField.js +1 -109
- package/dist/components/otp-field/index.js +1 -1
- package/dist/components/overlay/PlOverlay.js +1 -77
- package/dist/components/overlay/index.js +1 -1
- package/dist/components/pagination/PlPagination.js +1 -159
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/panes/PlPanes.js +1 -324
- package/dist/components/panes/index.js +1 -1
- package/dist/components/pill/PlPill.js +1 -154
- package/dist/components/pill/index.js +1 -1
- package/dist/components/popover/PlPopover.js +1 -113
- package/dist/components/popover/index.js +1 -1
- package/dist/components/progress-box/PlProgressBox.js +1 -34
- package/dist/components/progress-box/index.js +1 -1
- package/dist/components/progress-circular/PlProgressCircular.js +1 -47
- package/dist/components/progress-circular/index.js +1 -1
- package/dist/components/progress-linear/PlProgressLinear.js +1 -40
- package/dist/components/progress-linear/index.js +1 -1
- package/dist/components/radio-group/PlRadioGroup.js +1 -99
- package/dist/components/radio-group/index.js +1 -1
- package/dist/components/rating/PlRating.js +1 -101
- package/dist/components/rating/index.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.js +1 -411
- package/dist/components/scroll-zone/index.js +1 -1
- package/dist/components/segmented-button/PlSegmentedButton.js +1 -206
- package/dist/components/segmented-button/index.js +1 -1
- package/dist/components/select/PlSelect.js +1 -115
- package/dist/components/select/index.js +1 -1
- package/dist/components/skeleton/PlSkeleton.js +1 -142
- package/dist/components/skeleton/index.js +1 -1
- package/dist/components/slider/PlSlider.js +1 -132
- package/dist/components/slider/index.js +1 -1
- package/dist/components/spoiler/PlSpoiler.js +1 -74
- package/dist/components/spoiler/index.js +1 -1
- package/dist/components/switch/PlSwitch.js +1 -131
- package/dist/components/switch/index.js +1 -1
- package/dist/components/table/PlTable.js +1 -210
- package/dist/components/table/index.js +1 -1
- package/dist/components/tabs/PlTabs.js +1 -182
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/text-field/PlTextField.js +1 -126
- package/dist/components/text-field/index.js +1 -1
- package/dist/components/text-link/PlTextLink.js +1 -136
- package/dist/components/text-link/index.js +1 -1
- package/dist/components/time-picker/PlTimePicker.js +1 -97
- package/dist/components/time-picker/index.js +1 -1
- package/dist/components/timeline/PlTimeline.js +1 -207
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/toast/PlToast.js +1 -174
- package/dist/components/toast/index.js +1 -1
- package/dist/components/toolbar/PlToolbar.js +1 -65
- package/dist/components/toolbar/index.js +1 -1
- package/dist/components/tooltip/PlTooltip.js +1 -117
- package/dist/components/tooltip/index.js +1 -1
- package/dist/components/typography/PlTypography.js +1 -143
- package/dist/components/typography/index.js +1 -1
- package/dist/index.js +1 -75
- package/dist/internal/animate.js +1 -318
- package/dist/internal/button-group.js +2 -19
- package/dist/internal/calendar.js +1 -501
- package/dist/internal/date.js +1 -353
- package/dist/internal/format.js +1 -41
- package/dist/internal/grid.js +1 -143
- package/dist/internal/icons.js +1 -138
- package/dist/internal/menu.js +1 -18
- package/dist/internal/picker.js +1 -139
- package/dist/internal/progress.js +1 -167
- package/dist/internal/sizer.js +1 -35
- package/dist/internal/styles.js +1 -636
- package/dist/types.js +0 -8
- package/package.json +5 -3
|
@@ -1,34 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Progress } from '@base-ui/react/progress';
|
|
4
|
-
import { fillTransitionClasses, plateGapClasses, plateRadiusClasses, plateSizeClasses, progressAriaText, progressFraction, progressSlots, progressText, trackClasses } from '../../internal/progress.js';
|
|
5
|
-
import { cx, metaTextClasses, stackGapClasses } from '../../internal/styles.js';
|
|
6
|
-
/**
|
|
7
|
-
* A row of small glass plates that light up.
|
|
8
|
-
*
|
|
9
|
-
* The third shape, and the one that is about the material rather than about the
|
|
10
|
-
* quantity. A bar and a ring both say "this much of it is done"; a row of
|
|
11
|
-
* plates says "this is working" in the library's own vocabulary — the same
|
|
12
|
-
* groove, the same corner, the same gradient — which is what makes it the right
|
|
13
|
-
* one for a loading state inside a Plass surface, where a foreign grey spinner
|
|
14
|
-
* would look borrowed.
|
|
15
|
-
*
|
|
16
|
-
* It answers a value when it has one: the plates fill in order, the leading one
|
|
17
|
-
* partially, so four plates read as a four-segment bar rather than as four
|
|
18
|
-
* quarters. Without a value they cycle, each held back by its own index — and
|
|
19
|
-
* what cycles is the fill's **opacity**, because a gradient has no interpolation
|
|
20
|
-
* between itself and nothing.
|
|
21
|
-
*/
|
|
22
|
-
export const PlProgressBox = /* @__PURE__ */ React.forwardRef(function PlProgressBox({ size = 'md', color = 'primary', count = 4, value = null, min = 0, max = 100, label, showValue = false, format, className, style, ...props }, ref) {
|
|
23
|
-
const fraction = progressFraction(value, min, max);
|
|
24
|
-
const indeterminate = fraction === null;
|
|
25
|
-
const hasFormat = format !== undefined;
|
|
26
|
-
// A row of no plates is not a loading indicator, and a fractional count is a
|
|
27
|
-
// caller who divided something. Both land on one plate rather than on none.
|
|
28
|
-
const plates = Math.max(1, Math.floor(count));
|
|
29
|
-
return (_jsxs(Progress.Root, { ref: ref, value: value ?? null, min: min, max: max, format: format, getAriaValueText: progressAriaText(fraction, hasFormat), className: cx('inline-flex flex-col', stackGapClasses[size], className), style: { ...progressSlots(color), ...style }, ...props, children: [label || showValue ? (_jsxs("div", { className: cx('flex items-baseline gap-2', label ? 'justify-between' : 'justify-end', metaTextClasses[size]), children: [label ? (_jsx(Progress.Label, { className: "min-w-0 truncate text-(--plass-fg)", children: label })) : null, showValue ? (_jsx(Progress.Value, { className: "shrink-0 tabular-nums text-(--plass-muted-fg)", children: (formatted) => progressText(fraction, formatted, hasFormat) })) : null] })) : null, _jsx(Progress.Track, { className: cx('flex', plateGapClasses[size]), children: Array.from({ length: plates }, (_, index) => (_jsx("span", { className: cx('relative overflow-hidden', trackClasses, plateSizeClasses[size], plateRadiusClasses[size]), children: _jsx("span", { "aria-hidden": "true", className: cx('absolute inset-y-0 start-0 [background-image:var(--p-fill)]', indeterminate ? 'plass-plate-wave w-full' : fillTransitionClasses), style: indeterminate
|
|
30
|
-
? { '--p-i': index }
|
|
31
|
-
: {
|
|
32
|
-
width: `${Math.min(100, Math.max(0, (fraction * plates - index) * 100))}%`
|
|
33
|
-
} }) }, index))) })] }));
|
|
34
|
-
});
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Progress as s}from"@base-ui/react/progress";import{fillTransitionClasses as r,plateGapClasses as t,plateRadiusClasses as n,plateSizeClasses as i,progressAriaText as o,progressFraction as m,progressSlots as c,progressText as u,trackClasses as f}from"../../internal/progress.js";import{cx as d,metaTextClasses as p,stackGapClasses as x}from"../../internal/styles.js";export const PlProgressBox=/* @__PURE__ */l.forwardRef(function PlProgressBox({size:l="md",color:h="primary",count:g=4,value:y=null,min:b=0,max:v=100,label:w,showValue:N=!1,format:j,className:M,style:P,...k},V){const A=m(y,b,v),B=null===A,R=void 0!==j,T=Math.max(1,Math.floor(g));return a(s.Root,{ref:V,value:y??null,min:b,max:v,format:j,getAriaValueText:o(A,R),className:d("inline-flex flex-col",x[l],M),style:{...c(h),...P},...k,children:[w||N?a("div",{className:d("flex items-baseline gap-2",w?"justify-between":"justify-end",p[l]),children:[w?e(s.Label,{className:"min-w-0 truncate text-(--plass-fg)",children:w}):null,N?e(s.Value,{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:e=>u(A,e,R)}):null]}):null,e(s.Track,{className:d("flex",t[l]),children:Array.from({length:T},(a,s)=>e("span",{className:d("relative overflow-hidden",f,i[l],n[l]),children:e("span",{"aria-hidden":"true",className:d("absolute inset-y-0 start-0 [background-image:var(--p-fill)]",B?"plass-plate-wave w-full":r),style:B?{"--p-i":s}:{width:`${Math.min(100,Math.max(0,100*(A*T-s)))}%`}})},s))})]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlProgressBox}from"./PlProgressBox.js";
|
|
@@ -1,47 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Progress } from '@base-ui/react/progress';
|
|
4
|
-
import { progressAriaText, progressFraction, progressSlots, progressText, ringDiameters, ringStrokes } from '../../internal/progress.js';
|
|
5
|
-
import { cx, gapClasses, metaTextClasses } from '../../internal/styles.js';
|
|
6
|
-
/**
|
|
7
|
-
* A ring that fills, and the one to reach for where there is no room for a bar
|
|
8
|
-
* — inside a button, at the end of a table row, next to a field.
|
|
9
|
-
*
|
|
10
|
-
* The arc is the family's gradient rather than a flat colour, which takes a
|
|
11
|
-
* `<linearGradient>` of its own: an SVG stroke cannot be given a CSS gradient,
|
|
12
|
-
* so the two ends of the fill are lifted out of the slots and rebuilt at 135°.
|
|
13
|
-
* It is worth the extra element — a flat ring beside a swept bar is two
|
|
14
|
-
* materials for one idea.
|
|
15
|
-
*
|
|
16
|
-
* The value and the label sit *beside* the ring rather than inside it. A number
|
|
17
|
-
* in the middle of a dial is the picture everyone has of this component, and it
|
|
18
|
-
* only works at two of the five sizes: at `xs` the ring is fourteen pixels
|
|
19
|
-
* across and there is nowhere for "40%" to go. Beside it, every size reads.
|
|
20
|
-
*/
|
|
21
|
-
export const PlProgressCircular = /* @__PURE__ */ React.forwardRef(function PlProgressCircular({ size = 'md', color = 'primary', value = null, min = 0, max = 100, label, showValue = false, format, className, style, ...props }, ref) {
|
|
22
|
-
const fraction = progressFraction(value, min, max);
|
|
23
|
-
const indeterminate = fraction === null;
|
|
24
|
-
const hasFormat = format !== undefined;
|
|
25
|
-
const gradientId = `${React.useId()}-fill`;
|
|
26
|
-
const diameter = ringDiameters[size];
|
|
27
|
-
const stroke = ringStrokes[size];
|
|
28
|
-
const centre = diameter / 2;
|
|
29
|
-
// The stroke straddles the path, so the radius has to come in by half of it
|
|
30
|
-
// or the ring is clipped by its own viewBox.
|
|
31
|
-
const radius = centre - stroke / 2;
|
|
32
|
-
const circumference = 2 * Math.PI * radius;
|
|
33
|
-
// Indeterminate draws a fixed quarter-arc and turns; determinate holds still
|
|
34
|
-
// and lets the gap close. Both are one dash pattern on one circle.
|
|
35
|
-
const dashArray = indeterminate ? `${circumference * 0.28} ${circumference}` : `${circumference}`;
|
|
36
|
-
const dashOffset = indeterminate ? 0 : circumference * (1 - fraction);
|
|
37
|
-
return (_jsxs(Progress.Root, { ref: ref, value: value ?? null, min: min, max: max, format: format, getAriaValueText: progressAriaText(fraction, hasFormat), className: cx('inline-flex items-center', gapClasses[size], metaTextClasses[size], className), style: { ...progressSlots(color), ...style }, ...props, children: [_jsxs("svg", {
|
|
38
|
-
// The rotation is on the whole `<svg>` and not on a group inside it:
|
|
39
|
-
// `transform-origin: center` resolves against an element's border box,
|
|
40
|
-
// which an SVG child does not have one of unless `transform-box` is set
|
|
41
|
-
// as well. One element, one rule, no surprises across browsers.
|
|
42
|
-
className: cx('shrink-0', indeterminate && 'plass-ring-spin'), width: diameter, height: diameter, viewBox: `0 0 ${diameter} ${diameter}`, fill: "none", "aria-hidden": "true", children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: "var(--p-solid)" }), _jsx("stop", { offset: "100%", stopColor: "var(--p-solid-to)" })] }) }), _jsx("circle", { cx: centre, cy: centre, r: radius, stroke: "var(--plass-track)", strokeWidth: stroke }), _jsx("circle", { cx: centre, cy: centre, r: radius, stroke: `url(#${gradientId})`, strokeWidth: stroke, strokeLinecap: "round", strokeDasharray: dashArray, strokeDashoffset: dashOffset,
|
|
43
|
-
// An SVG geometry attribute rather than a CSS transform: this is where
|
|
44
|
-
// the arc starts, not something the ring does when its state changes.
|
|
45
|
-
// Without it a determinate ring would fill from three o'clock.
|
|
46
|
-
transform: `rotate(-90 ${centre} ${centre})`, className: "[transition:stroke-dashoffset_var(--plass-duration-slow)_var(--plass-ease)]" })] }), label ? (_jsx(Progress.Label, { className: "min-w-0 truncate text-(--plass-fg)", children: label })) : null, showValue ? (_jsx(Progress.Value, { className: "shrink-0 tabular-nums text-(--plass-muted-fg)", children: (formatted) => progressText(fraction, formatted, hasFormat) })) : null] }));
|
|
47
|
-
});
|
|
1
|
+
"use client";import{jsx as r,jsxs as s}from"react/jsx-runtime";import*as e from"react";import{Progress as a}from"@base-ui/react/progress";import{progressAriaText as t,progressFraction as l,progressSlots as o,progressText as i,ringDiameters as n,ringStrokes as c}from"../../internal/progress.js";import{cx as m,gapClasses as f,metaTextClasses as u}from"../../internal/styles.js";export const PlProgressCircular=/* @__PURE__ */e.forwardRef(function PlProgressCircular({size:d="md",color:p="primary",value:h=null,min:x=0,max:k=100,label:g,showValue:v=!1,format:y,className:$,style:w,...N},j){const P=l(h,x,k),b=null===P,C=void 0!==y,V=`${e.useId()}-fill`,D=n[d],I=c[d],L=D/2,R=L-I/2,W=2*Math.PI*R,_=b?`${.28*W} ${W}`:`${W}`,z=b?0:W*(1-P);return s(a.Root,{ref:j,value:h??null,min:x,max:k,format:y,getAriaValueText:t(P,C),className:m("inline-flex items-center",f[d],u[d],$),style:{...o(p),...w},...N,children:[s("svg",{className:m("shrink-0",b&&"plass-ring-spin"),width:D,height:D,viewBox:`0 0 ${D} ${D}`,fill:"none","aria-hidden":"true",children:[r("defs",{children:s("linearGradient",{id:V,x1:"0",y1:"0",x2:"1",y2:"1",children:[r("stop",{offset:"0%",stopColor:"var(--p-solid)"}),r("stop",{offset:"100%",stopColor:"var(--p-solid-to)"})]})}),r("circle",{cx:L,cy:L,r:R,stroke:"var(--plass-track)",strokeWidth:I}),r("circle",{cx:L,cy:L,r:R,stroke:`url(#${V})`,strokeWidth:I,strokeLinecap:"round",strokeDasharray:_,strokeDashoffset:z,transform:`rotate(-90 ${L} ${L})`,className:"[transition:stroke-dashoffset_var(--plass-duration-slow)_var(--plass-ease)]"})]}),g?r(a.Label,{className:"min-w-0 truncate text-(--plass-fg)",children:g}):null,v?r(a.Value,{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:r=>i(P,r,C)}):null]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlProgressCircular}from"./PlProgressCircular.js";
|
|
@@ -1,40 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Progress } from '@base-ui/react/progress';
|
|
4
|
-
import { barThicknessClasses, fillTransitionClasses, progressAriaText, progressFraction, progressSlots, progressText, trackClasses } from '../../internal/progress.js';
|
|
5
|
-
import { cx, metaTextClasses, stackGapClasses } from '../../internal/styles.js';
|
|
6
|
-
/**
|
|
7
|
-
* A bar that fills.
|
|
8
|
-
*
|
|
9
|
-
* The workhorse of the three: it is the only one that can show *how much* is
|
|
10
|
-
* left at a glance, because length is the one quantity a reader can compare
|
|
11
|
-
* without counting.
|
|
12
|
-
*
|
|
13
|
-
* The groove is `--plass-track`, the same neutral ink a PlSlider's rail and a
|
|
14
|
-
* PlSwitch's off state are cut in, and the segment over it is the family's
|
|
15
|
-
* gradient — so the filled part of the run is made of exactly the same material
|
|
16
|
-
* as the button that submits the form it is in. Which is also why the movement
|
|
17
|
-
* is on `width`: a gradient cannot be transitioned, and a length can.
|
|
18
|
-
*
|
|
19
|
-
* Both the groove and the segment are fully rounded, and that is the one place
|
|
20
|
-
* the library's rule about pills does not apply. The rule protects the flat run
|
|
21
|
-
* along a control's edge that a line of text sits on; at six pixels tall there
|
|
22
|
-
* is no flat run left to protect, and a square-ended bar reads as a rendering
|
|
23
|
-
* fault rather than as a cut edge.
|
|
24
|
-
*
|
|
25
|
-
* Base UI owns the semantics — `role="progressbar"`, the value and range
|
|
26
|
-
* attributes, `aria-valuetext`, and dropping the value entirely when the bar is
|
|
27
|
-
* indeterminate — and it computes the fill width too, so the determinate case
|
|
28
|
-
* here is a class list and nothing else.
|
|
29
|
-
*/
|
|
30
|
-
export const PlProgressLinear = /* @__PURE__ */ React.forwardRef(function PlProgressLinear({ size = 'md', color = 'primary', value = null, min = 0, max = 100, label, showValue = false, format, className, style, ...props }, ref) {
|
|
31
|
-
const fraction = progressFraction(value, min, max);
|
|
32
|
-
const indeterminate = fraction === null;
|
|
33
|
-
const hasFormat = format !== undefined;
|
|
34
|
-
return (_jsxs(Progress.Root, { ref: ref, value: value ?? null, min: min, max: max, format: format, getAriaValueText: progressAriaText(fraction, hasFormat), className: cx('flex w-full flex-col', stackGapClasses[size], className), style: { ...progressSlots(color), ...style }, ...props, children: [label || showValue ? (_jsxs("div", { className: cx('flex items-baseline gap-2', label ? 'justify-between' : 'justify-end', metaTextClasses[size]), children: [label ? (_jsx(Progress.Label, { className: "min-w-0 truncate text-(--plass-fg)", children: label })) : null, showValue ? (_jsx(Progress.Value, { className: "shrink-0 tabular-nums text-(--plass-muted-fg)", children: (formatted) => progressText(fraction, formatted, hasFormat) })) : null] })) : null, _jsx(Progress.Track, { className: cx('relative w-full overflow-hidden rounded-full', trackClasses, barThicknessClasses[size]), children: _jsx(Progress.Indicator, { className: cx('rounded-full [background-image:var(--p-fill)]',
|
|
35
|
-
// `plass-progress-sweep` supplies the position, the width and the
|
|
36
|
-
// animation; with a value Base UI supplies the width instead and
|
|
37
|
-
// this transition is what makes it travel rather than jump. Both
|
|
38
|
-
// change an inline size, never a transform.
|
|
39
|
-
indeterminate ? 'plass-progress-sweep' : `absolute top-0 ${fillTransitionClasses}`) }) })] }));
|
|
40
|
-
});
|
|
1
|
+
"use client";import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as s from"react";import{Progress as r}from"@base-ui/react/progress";import{barThicknessClasses as a,fillTransitionClasses as t,progressAriaText as n,progressFraction as o,progressSlots as i,progressText as m,trackClasses as u}from"../../internal/progress.js";import{cx as c,metaTextClasses as f,stackGapClasses as d}from"../../internal/styles.js";export const PlProgressLinear=/* @__PURE__ */s.forwardRef(function PlProgressLinear({size:s="md",color:p="primary",value:x=null,min:g=0,max:b=100,label:h,showValue:w=!1,format:j,className:v,style:N,...y},P){const k=o(x,g,b),L=null===k,V=void 0!==j;return l(r.Root,{ref:P,value:x??null,min:g,max:b,format:j,getAriaValueText:n(k,V),className:c("flex w-full flex-col",d[s],v),style:{...i(p),...N},...y,children:[h||w?l("div",{className:c("flex items-baseline gap-2",h?"justify-between":"justify-end",f[s]),children:[h?e(r.Label,{className:"min-w-0 truncate text-(--plass-fg)",children:h}):null,w?e(r.Value,{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:e=>m(k,e,V)}):null]}):null,e(r.Track,{className:c("relative w-full overflow-hidden rounded-full",u,a[s]),children:e(r.Indicator,{className:c("rounded-full [background-image:var(--p-fill)]",L?"plass-progress-sweep":`absolute top-0 ${t}`)})})]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlProgressLinear}from"./PlProgressLinear.js";
|
|
@@ -1,99 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Radio as BaseUIRadio } from '@base-ui/react/radio';
|
|
4
|
-
import { RadioGroup as BaseUIRadioGroup } from '@base-ui/react/radio-group';
|
|
5
|
-
import { Field } from '@base-ui/react/field';
|
|
6
|
-
import { controlSlots, focusRingClasses, glassClasses, hasContent, metaTextClasses, tickDotClasses, tickRowTextClasses, tickSizeClasses, transitionClasses } from '../../internal/styles.js';
|
|
7
|
-
const RadioGroupContext = /* @__PURE__ */ React.createContext({
|
|
8
|
-
size: 'md',
|
|
9
|
-
color: 'primary',
|
|
10
|
-
readOnly: false
|
|
11
|
-
});
|
|
12
|
-
/**
|
|
13
|
-
* The dot. Round, and one of the two things in the library allowed to be —
|
|
14
|
-
* roundness is exactly what tells a reader "one of these" rather than "any of
|
|
15
|
-
* these", and it is the one convention old enough that breaking it would cost
|
|
16
|
-
* more than it bought.
|
|
17
|
-
*/
|
|
18
|
-
const dotBaseClasses = /* @__PURE__ */ [
|
|
19
|
-
'relative inline-flex shrink-0 items-center justify-center rounded-full border',
|
|
20
|
-
'[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]',
|
|
21
|
-
transitionClasses,
|
|
22
|
-
focusRingClasses
|
|
23
|
-
].join(' ');
|
|
24
|
-
/**
|
|
25
|
-
* No gloss line and no tinted lift, for the reason a PlCheckbox's tick has
|
|
26
|
-
* neither: a 1px white edge is light on a cut edge at 40px and a grey smudge at
|
|
27
|
-
* 18px, and a `0 6px 16px` shadow under an 18px circle is bigger than the
|
|
28
|
-
* circle. The glass stays; only the two decorations go.
|
|
29
|
-
*
|
|
30
|
-
* The edge is `--plass-border` rather than the sheet's own `--plass-glass-line`,
|
|
31
|
-
* and that is not a slip. The glass hairline is white light on a translucent
|
|
32
|
-
* pane, which is invisible the moment the tick is set on a light card rather
|
|
33
|
-
* than on the page wash — and a tick nobody can see is a control nobody can
|
|
34
|
-
* find. A neutral hairline reads on both.
|
|
35
|
-
*/
|
|
36
|
-
const restDotClasses = /* @__PURE__ */ [
|
|
37
|
-
glassClasses,
|
|
38
|
-
'cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]',
|
|
39
|
-
'hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]',
|
|
40
|
-
'data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)',
|
|
41
|
-
'data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105'
|
|
42
|
-
].join(' ');
|
|
43
|
-
const readOnlyDotClasses = /* @__PURE__ */ [
|
|
44
|
-
glassClasses,
|
|
45
|
-
'cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]',
|
|
46
|
-
'saturate-[0.55]',
|
|
47
|
-
'data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)',
|
|
48
|
-
'data-[checked]:[border-color:transparent]'
|
|
49
|
-
].join(' ');
|
|
50
|
-
const disabledDotClasses = /* @__PURE__ */ [
|
|
51
|
-
glassClasses,
|
|
52
|
-
'cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]',
|
|
53
|
-
'opacity-50 saturate-[0.35]',
|
|
54
|
-
'data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)',
|
|
55
|
-
'data-[checked]:[border-color:transparent]'
|
|
56
|
-
].join(' ');
|
|
57
|
-
/** The inner dot: `currentColor`, so it inherits the on-fill ink. */
|
|
58
|
-
const indicatorClasses = 'rounded-full bg-current';
|
|
59
|
-
/**
|
|
60
|
-
* One option in a `PlRadioGroup`.
|
|
61
|
-
*
|
|
62
|
-
* It has no `size` and no `color` of its own — both come from the group, which
|
|
63
|
-
* is the only place they can be set once and mean the same thing for every
|
|
64
|
-
* option in the set.
|
|
65
|
-
*/
|
|
66
|
-
export const PlRadio = /* @__PURE__ */ React.forwardRef(function PlRadio({ label, description, disabled = false, className, style, ...props }, ref) {
|
|
67
|
-
const group = React.useContext(RadioGroupContext);
|
|
68
|
-
const readOnly = props.readOnly ?? group.readOnly;
|
|
69
|
-
return (_jsx(Field.Root, { disabled: disabled, className: ['flex flex-col', className ?? ''].filter(Boolean).join(' '), style: style, children: _jsxs("div", { className: `flex items-start gap-2 ${tickRowTextClasses[group.size]}`, children: [_jsx("span", { className: "flex h-[1lh] shrink-0 items-center", children: _jsx(BaseUIRadio.Root, { ref: ref, className: [
|
|
70
|
-
dotBaseClasses,
|
|
71
|
-
tickSizeClasses[group.size],
|
|
72
|
-
disabled ? disabledDotClasses : readOnly ? readOnlyDotClasses : restDotClasses
|
|
73
|
-
].join(' '), disabled: disabled, ...props, children: _jsx(BaseUIRadio.Indicator, { className: `${indicatorClasses} ${tickDotClasses[group.size]}` }) }) }), label || description ? (_jsxs("span", { className: "flex min-w-0 flex-col gap-0.5", children: [label ? (_jsx(Field.Label, { className: disabled ? 'text-(--plass-muted-fg)' : 'cursor-pointer text-(--plass-fg)', children: label })) : null, description ? (_jsx(Field.Description, { className: `${metaTextClasses[group.size]} text-(--plass-muted-fg)`, children: description })) : null] })) : null] }) }));
|
|
74
|
-
});
|
|
75
|
-
/**
|
|
76
|
-
* A set of options where exactly one is chosen.
|
|
77
|
-
*
|
|
78
|
-
* Base UI owns the roving tab index and the arrow-key navigation, which is the
|
|
79
|
-
* whole reason a radio group is a component at all rather than a `<div>` full of
|
|
80
|
-
* inputs: the set takes one tab stop, and the arrows move within it.
|
|
81
|
-
*/
|
|
82
|
-
export const PlRadioGroup = /* @__PURE__ */ React.forwardRef(function PlRadioGroup({ size = 'md', color = 'primary', orientation = 'vertical', label, description, error, invalid, disabled = false, readOnly = false, className, style, children, ...props }, ref) {
|
|
83
|
-
const hasError = hasContent(error);
|
|
84
|
-
const isInvalid = invalid ?? hasError;
|
|
85
|
-
// Invalid re-points the whole slot family at `danger`, so every dot, the
|
|
86
|
-
// ring and the message all turn over together.
|
|
87
|
-
const family = isInvalid ? 'danger' : color;
|
|
88
|
-
const context = React.useMemo(() => ({ size, color: family, readOnly }), [size, family, readOnly]);
|
|
89
|
-
return (_jsx(RadioGroupContext.Provider, { value: context, children: _jsxs(Field.Root, { disabled: disabled, invalid: isInvalid, className: ['flex flex-col gap-1.5', className ?? ''].filter(Boolean).join(' '),
|
|
90
|
-
// `solid`, because a checked dot *is* the coloured thing.
|
|
91
|
-
style: { ...controlSlots(family, 0, 'solid'), ...style }, children: [label ? (_jsx(Field.Label, { className: [
|
|
92
|
-
metaTextClasses[size],
|
|
93
|
-
'font-semibold',
|
|
94
|
-
disabled ? 'text-(--plass-muted-fg)' : 'text-(--plass-fg)'
|
|
95
|
-
].join(' '), children: label })) : null, description ? (_jsx(Field.Description, { className: `${metaTextClasses[size]} text-(--plass-muted-fg)`, children: description })) : null, _jsx(BaseUIRadioGroup, { ref: ref, disabled: disabled, readOnly: readOnly, className: [
|
|
96
|
-
'flex',
|
|
97
|
-
orientation === 'horizontal' ? 'flex-row flex-wrap gap-x-5 gap-y-2' : 'flex-col gap-2'
|
|
98
|
-
].join(' '), ...props, children: children }), hasError ? (_jsx(Field.Error, { match: true, className: `${metaTextClasses[size]} text-(--p-accent)`, children: error })) : null] }) }));
|
|
99
|
-
});
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as l}from"@base-ui/react/radio";import{RadioGroup as o}from"@base-ui/react/radio-group";import{Field as s}from"@base-ui/react/field";import{controlSlots as t,focusRingClasses as i,glassClasses as d,hasContent as n,metaTextClasses as c,tickDotClasses as p,tickRowTextClasses as m,tickSizeClasses as f,transitionClasses as u}from"../../internal/styles.js";const h=/* @__PURE__ */r.createContext({size:"md",color:"primary",readOnly:!1}),b=/* @__PURE__ */["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",u,i].join(" "),g=/* @__PURE__ */[d,"cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]","hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105"].join(" "),x=/* @__PURE__ */[d,"cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]","saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),v=/* @__PURE__ */[d,"cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]","opacity-50 saturate-[0.35]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" ");export const PlRadio=/* @__PURE__ */r.forwardRef(function PlRadio({label:o,description:t,disabled:i=!1,className:d,style:n,...u},k){const y=r.useContext(h),N=u.readOnly??y.readOnly;return e(s.Root,{disabled:i,className:["flex flex-col",d??""].filter(Boolean).join(" "),style:n,children:a("div",{className:`flex items-start gap-2 ${m[y.size]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:k,className:[b,f[y.size],i?v:N?x:g].join(" "),disabled:i,...u,children:e(l.Indicator,{className:`rounded-full bg-current ${p[y.size]}`})})}),o||t?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[o?e(s.Label,{className:i?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",children:o}):null,t?e(s.Description,{className:`${c[y.size]} text-(--plass-muted-fg)`,children:t}):null]}):null]})})});export const PlRadioGroup=/* @__PURE__ */r.forwardRef(function PlRadioGroup({size:l="md",color:i="primary",orientation:d="vertical",label:p,description:m,error:f,invalid:u,disabled:b=!1,readOnly:g=!1,className:x,style:v,children:k,...y},N){const j=n(f),R=u??j,z=R?"danger":i,w=r.useMemo(()=>({size:l,color:z,readOnly:g}),[l,z,g]);return e(h.Provider,{value:w,children:a(s.Root,{disabled:b,invalid:R,className:["flex flex-col gap-1.5",x??""].filter(Boolean).join(" "),style:{...t(z,0,"solid"),...v},children:[p?e(s.Label,{className:[c[l],"font-semibold",b?"text-(--plass-muted-fg)":"text-(--plass-fg)"].join(" "),children:p}):null,m?e(s.Description,{className:`${c[l]} text-(--plass-muted-fg)`,children:m}):null,e(o,{ref:N,disabled:b,readOnly:g,className:["flex","horizontal"===d?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2"].join(" "),...y,children:k}),j?e(s.Error,{match:!0,className:`${c[l]} text-(--p-accent)`,children:f}):null]})})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlRadio,PlRadioGroup}from"./PlRadioGroup.js";
|
|
@@ -1,101 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { StarIcon, StarOutlineIcon } from '../../internal/icons.js';
|
|
4
|
-
import { controlSlots, cx, focusWithinRingClasses, gapClasses, iconSizeClasses, radiusClasses, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
|
|
5
|
-
/**
|
|
6
|
-
* The box one copy of the glyph is drawn in. Both copies get exactly this, or
|
|
7
|
-
* the clipped one would not line up with the outline underneath it.
|
|
8
|
-
*/
|
|
9
|
-
const starClasses = 'flex items-center justify-center';
|
|
10
|
-
/** The default accessible name of a score. */
|
|
11
|
-
function defaultValueLabel(value, count) {
|
|
12
|
-
return value <= 0 ? 'No rating' : `${value} out of ${count}`;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* A score out of five, as a row of stars.
|
|
16
|
-
*
|
|
17
|
-
* Underneath an interactive rating is a radio group of real `<input>`s, one per
|
|
18
|
-
* choosable score, each visually hidden under the fraction of a star it stands
|
|
19
|
-
* for. That is the whole accessibility argument: a rating *is* "exactly one of
|
|
20
|
-
* these", so it gets one tab stop for the row, arrow keys within it,
|
|
21
|
-
* `aria-checked` on the one that is taken, and a value in a form submission —
|
|
22
|
-
* none of which a row of `<button>`s or a `<div>` with a click handler would
|
|
23
|
-
* have.
|
|
24
|
-
*
|
|
25
|
-
* The fraction is drawn by laying the filled star over the empty one and
|
|
26
|
-
* clipping it to a percentage of the width. Nothing is transformed and no glyph
|
|
27
|
-
* is scaled, so a half star is the left half of exactly the star beside it —
|
|
28
|
-
* which is also the no-transform rule holding on a component whose whole job is
|
|
29
|
-
* a partial shape. The clip runs from the inline start, so it fills from the
|
|
30
|
-
* right under RTL without anything being told to.
|
|
31
|
-
*
|
|
32
|
-
* `readOnly` is a different component in the same clothes: no inputs, no radio
|
|
33
|
-
* group, and one `role="img"` carrying the score as a sentence. A star display
|
|
34
|
-
* that kept twenty focusable radios would be twenty tab stops on a page that
|
|
35
|
-
* was only reporting a number.
|
|
36
|
-
*/
|
|
37
|
-
export const PlRating = /* @__PURE__ */ React.forwardRef(function PlRating({ value: valueProp, defaultValue = 0, onValueChange, count = 5, precision = 1, icon, emptyIcon, clearable = true, readOnly = false, disabled = false, name: nameProp, required = false, size = 'md', color = 'warning', label = 'Rating', valueLabel = defaultValueLabel, className, style, onPointerLeave, ...props }, ref) {
|
|
38
|
-
const generatedName = React.useId();
|
|
39
|
-
const name = nameProp ?? generatedName;
|
|
40
|
-
const [uncontrolled, setUncontrolled] = React.useState(defaultValue);
|
|
41
|
-
const controlled = valueProp !== undefined;
|
|
42
|
-
const value = controlled ? valueProp : uncontrolled;
|
|
43
|
-
// What the pointer is currently promising, which is not the value until it is
|
|
44
|
-
// clicked. `null` is "the pointer is not on the row", not "zero stars".
|
|
45
|
-
const [hovered, setHovered] = React.useState(null);
|
|
46
|
-
const stars = Math.max(1, Math.floor(count));
|
|
47
|
-
const step = precision > 0 && precision <= 1 ? precision : 1;
|
|
48
|
-
const stepsPerStar = Math.round(1 / step);
|
|
49
|
-
const shown = Math.max(0, Math.min(stars, hovered ?? value));
|
|
50
|
-
const change = (next) => {
|
|
51
|
-
if (!controlled) {
|
|
52
|
-
setUncontrolled(next);
|
|
53
|
-
}
|
|
54
|
-
onValueChange?.(next);
|
|
55
|
-
};
|
|
56
|
-
const marks = Array.from({ length: stars }, (_, index) => {
|
|
57
|
-
// How much of *this* star is filled, from 0 to 1.
|
|
58
|
-
const fill = Math.max(0, Math.min(1, shown - index));
|
|
59
|
-
return (_jsxs("span", { className: cx('relative inline-flex shrink-0', iconSizeClasses[size], radiusClasses.xs, readOnly || disabled ? '' : focusWithinRingClasses), children: [_jsx("span", { className: cx(starClasses, iconSizeClasses[size], 'text-(--p-empty)'), children: emptyIcon ?? _jsx(StarOutlineIcon, {}) }), _jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute inset-y-0 start-0 overflow-hidden", style: { width: `${fill * 100}%` }, children: _jsx("span", { className: cx(starClasses, iconSizeClasses[size], 'text-(--p-accent)', transitionClasses), children: icon ?? _jsx(StarIcon, {}) }) }), readOnly
|
|
60
|
-
? null
|
|
61
|
-
: Array.from({ length: stepsPerStar }, (_, part) => {
|
|
62
|
-
const score = Number((index + (part + 1) * step).toFixed(4));
|
|
63
|
-
return (_jsx("label", { className: cx('absolute inset-y-0', disabled ? 'cursor-not-allowed' : 'cursor-pointer'), style: {
|
|
64
|
-
insetInlineStart: `${(part * 100) / stepsPerStar}%`,
|
|
65
|
-
width: `${100 / stepsPerStar}%`
|
|
66
|
-
}, onPointerEnter: () => {
|
|
67
|
-
if (!disabled) {
|
|
68
|
-
setHovered(score);
|
|
69
|
-
}
|
|
70
|
-
}, children: _jsx("input", { type: "radio", className: srOnlyClasses, name: name, value: score, checked: value === score, disabled: disabled, required: required, "aria-label": valueLabel(score, stars), onChange: () => change(score),
|
|
71
|
-
// Clearing cannot ride on `change`: clicking a radio that is
|
|
72
|
-
// already checked fires a click and no change at all, and
|
|
73
|
-
// that click is exactly the gesture being listened for.
|
|
74
|
-
onClick: () => {
|
|
75
|
-
if (clearable && value === score) {
|
|
76
|
-
change(0);
|
|
77
|
-
}
|
|
78
|
-
} }) }, score));
|
|
79
|
-
})] }, index));
|
|
80
|
-
});
|
|
81
|
-
const classNames = cx('inline-flex items-center align-middle', gapClasses[size],
|
|
82
|
-
// The house treatment, not a grey token: the light goes out of the row and
|
|
83
|
-
// the page shows through it, which is what unavailable looks like
|
|
84
|
-
// everywhere else in the library.
|
|
85
|
-
disabled ? 'cursor-not-allowed opacity-50 saturate-[0.35]' : '', className);
|
|
86
|
-
const styles = {
|
|
87
|
-
...controlSlots(color, 0, 'solid'),
|
|
88
|
-
// An empty star is not a disabled one and not a hairline: it is the ghost of
|
|
89
|
-
// the star beside it, so it takes the muted ink at enough strength to read
|
|
90
|
-
// as a shape and not enough to compete with the ones that are filled.
|
|
91
|
-
'--p-empty': 'color-mix(in oklab, var(--plass-muted-fg) 40%, transparent)',
|
|
92
|
-
...style
|
|
93
|
-
};
|
|
94
|
-
if (readOnly) {
|
|
95
|
-
return (_jsx("div", { ref: ref, role: "img", "aria-label": valueLabel(Math.max(0, Math.min(stars, value)), stars), className: classNames, style: styles, onPointerLeave: onPointerLeave, ...props, children: marks }));
|
|
96
|
-
}
|
|
97
|
-
return (_jsx("div", { ref: ref, role: "radiogroup", "aria-label": label, "aria-disabled": disabled || undefined, "aria-required": required || undefined, className: classNames, style: styles, onPointerLeave: (event) => {
|
|
98
|
-
setHovered(null);
|
|
99
|
-
onPointerLeave?.(event);
|
|
100
|
-
}, ...props, children: marks }));
|
|
101
|
-
});
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{StarIcon as n,StarOutlineIcon as r}from"../../internal/icons.js";import{controlSlots as l,cx as i,focusWithinRingClasses as s,gapClasses as o,iconSizeClasses as c,radiusClasses as d,srOnlyClasses as u,transitionClasses as m}from"../../internal/styles.js";const h="flex items-center justify-center";function defaultValueLabel(e,a){return e<=0?"No rating":`${e} out of ${a}`}export const PlRating=/* @__PURE__ */t.forwardRef(function PlRating({value:p,defaultValue:f=0,onValueChange:y,count:b=5,precision:x=1,icon:v,emptyIcon:g,clearable:N=!0,readOnly:M=!1,disabled:w=!1,name:j,required:L=!1,size:P="md",color:k="warning",label:R="Rating",valueLabel:V=defaultValueLabel,className:q,style:C,onPointerLeave:I,...S},A){const $=t.useId(),z=j??$,[E,F]=t.useState(f),O=void 0!==p,B=O?p:E,[D,G]=t.useState(null),H=Math.max(1,Math.floor(b)),J=x>0&&x<=1?x:1,K=Math.round(1/J),Q=Math.max(0,Math.min(H,D??B)),change=e=>{O||F(e),y?.(e)},T=Array.from({length:H},(t,l)=>{const o=Math.max(0,Math.min(1,Q-l));return a("span",{className:i("relative inline-flex shrink-0",c[P],d.xs,M||w?"":s),children:[e("span",{className:i(h,c[P],"text-(--p-empty)"),children:g??e(r,{})}),e("span",{"aria-hidden":"true",className:"pointer-events-none absolute inset-y-0 start-0 overflow-hidden",style:{width:100*o+"%"},children:e("span",{className:i(h,c[P],"text-(--p-accent)",m),children:v??e(n,{})})}),M?null:Array.from({length:K},(a,t)=>{const n=Number((l+(t+1)*J).toFixed(4));return e("label",{className:i("absolute inset-y-0",w?"cursor-not-allowed":"cursor-pointer"),style:{insetInlineStart:100*t/K+"%",width:100/K+"%"},onPointerEnter:()=>{w||G(n)},children:e("input",{type:"radio",className:u,name:z,value:n,checked:B===n,disabled:w,required:L,"aria-label":V(n,H),onChange:()=>change(n),onClick:()=>{N&&B===n&&change(0)}})},n)})]},l)}),U=i("inline-flex items-center align-middle",o[P],w?"cursor-not-allowed opacity-50 saturate-[0.35]":"",q),W={...l(k,0,"solid"),"--p-empty":"color-mix(in oklab, var(--plass-muted-fg) 40%, transparent)",...C};return e("div",M?{ref:A,role:"img","aria-label":V(Math.max(0,Math.min(H,B)),H),className:U,style:W,onPointerLeave:I,...S,children:T}:{ref:A,role:"radiogroup","aria-label":R,"aria-disabled":w||void 0,"aria-required":L||void 0,className:U,style:W,onPointerLeave:e=>{G(null),I?.(e)},...S,children:T})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlRating}from"./PlRating.js";
|