plass-ui 1.4.0 → 1.5.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 +372 -0
- package/README.md +18 -16
- package/dist/components/accordion/PlAccordion.d.ts +1 -1
- package/dist/components/alert/PlAlert.js +1 -1
- package/dist/components/anchor/PlAnchor.d.ts +14 -1
- package/dist/components/anchor/PlAnchor.js +1 -1
- package/dist/components/animate-appear/PlAnimateAppear.js +1 -1
- package/dist/components/animate-blink/PlAnimateBlink.js +1 -1
- package/dist/components/animate-counter/PlAnimateCounter.js +1 -1
- package/dist/components/animate-fade/PlAnimateFade.js +1 -1
- package/dist/components/animate-float/PlAnimateFloat.js +1 -1
- package/dist/components/animate-grow/PlAnimateGrow.js +1 -1
- package/dist/components/animate-headline/PlAnimateHeadline.js +1 -1
- package/dist/components/animate-lighting/PlAnimateLighting.js +1 -1
- package/dist/components/animate-marquee/PlAnimateMarquee.d.ts +13 -4
- package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -1
- package/dist/components/animate-reveal/PlAnimateReveal.js +1 -1
- package/dist/components/animate-rotate/PlAnimateRotate.js +1 -1
- package/dist/components/animate-scramble/PlAnimateScramble.js +1 -1
- package/dist/components/animate-shake/PlAnimateShake.js +1 -1
- package/dist/components/animate-slide/PlAnimateSlide.js +1 -1
- package/dist/components/animate-split/PlAnimateSplit.d.ts +7 -4
- package/dist/components/animate-split/PlAnimateSplit.js +1 -1
- package/dist/components/animate-typing/PlAnimateTyping.d.ts +3 -2
- package/dist/components/animate-typing/PlAnimateTyping.js +1 -1
- package/dist/components/animate-zoom/PlAnimateZoom.js +1 -1
- package/dist/components/app-logo/PlAppLogo.js +1 -1
- package/dist/components/area-chart/PlAreaChart.d.ts +1 -1
- package/dist/components/area-chart/PlAreaChart.js +1 -1
- package/dist/components/aspect-ratio/PlAspectRatio.d.ts +2 -1
- package/dist/components/aspect-ratio/PlAspectRatio.js +1 -1
- package/dist/components/avatar/PlAvatar.js +1 -1
- package/dist/components/back-top/PlBackTop.d.ts +2 -1
- package/dist/components/back-top/PlBackTop.js +1 -1
- package/dist/components/badge/PlBadge.js +1 -1
- package/dist/components/bar-chart/PlBarChart.d.ts +1 -1
- package/dist/components/bar-chart/PlBarChart.js +1 -1
- package/dist/components/bottom-navigation/PlBottomNavigation.d.ts +3 -0
- package/dist/components/breadcrumb/PlBreadcrumb.js +1 -1
- package/dist/components/button/PlButton.d.ts +8 -0
- package/dist/components/button/PlButton.js +1 -1
- package/dist/components/calendar/PlCalendar.js +1 -1
- package/dist/components/card/PlCard.js +1 -1
- package/dist/components/carousel/PlCarousel.d.ts +1 -1
- package/dist/components/carousel/PlCarousel.js +1 -1
- package/dist/components/chat-bubble/PlChatBubble.d.ts +4 -1
- package/dist/components/chat-bubble/PlChatBubble.js +1 -1
- package/dist/components/checkbox/PlCheckbox.js +1 -1
- package/dist/components/chip/PlChip.d.ts +6 -2
- package/dist/components/chip/PlChip.js +1 -1
- package/dist/components/code-block/PlCodeBlock.d.ts +19 -2
- package/dist/components/code-block/PlCodeBlock.js +1 -1
- package/dist/components/color-picker/PlColorPicker.js +1 -1
- package/dist/components/combobox/PlCombobox.d.ts +6 -5
- package/dist/components/combobox/PlCombobox.js +1 -1
- package/dist/components/command-palette/PlCommandPalette.d.ts +6 -2
- package/dist/components/command-palette/PlCommandPalette.js +1 -1
- package/dist/components/confirm/PlConfirmProvider.js +1 -1
- package/dist/components/container/PlContainer.js +1 -1
- package/dist/components/data-table/PlDataTable.d.ts +20 -6
- package/dist/components/data-table/PlDataTable.js +1 -1
- package/dist/components/date-picker/PlDatePicker.js +1 -1
- package/dist/components/date-range-picker/PlDateRangePicker.js +1 -1
- package/dist/components/date-time-picker/PlDateTimePicker.js +1 -1
- package/dist/components/drawer/PlDrawer.js +1 -1
- package/dist/components/file-picker/PlFilePicker.d.ts +4 -1
- package/dist/components/file-picker/PlFilePicker.js +1 -1
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.d.ts +3 -0
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -1
- package/dist/components/form/PlForm.js +1 -1
- package/dist/components/gallery/PlGallery.d.ts +40 -2
- package/dist/components/gallery/PlGallery.js +1 -1
- package/dist/components/gallery/PlGalleryViewer.js +1 -1
- package/dist/components/gauge-chart/PlGaugeChart.js +1 -1
- package/dist/components/heatmap-chart/PlHeatmapChart.js +1 -1
- package/dist/components/highlight/PlHighlight.js +1 -1
- package/dist/components/hot-keys/PlHotKeys.js +1 -1
- package/dist/components/hover-card/PlHoverCard.d.ts +5 -3
- package/dist/components/hover-card/PlHoverCard.js +1 -1
- package/dist/components/how-to-steps/PlHowToSteps.js +1 -1
- package/dist/components/image/PlImage.d.ts +195 -8
- package/dist/components/image/PlImage.js +1 -1
- package/dist/components/image/PlImagePreview.d.ts +58 -0
- package/dist/components/image/PlImagePreview.js +1 -0
- package/dist/components/image/index.d.ts +1 -1
- package/dist/components/menu/PlMenu.d.ts +14 -5
- package/dist/components/menu/PlMenu.js +1 -1
- package/dist/components/meter/PlMeter.js +1 -1
- package/dist/components/navigation-menu/PlNavigationMenu.d.ts +7 -1
- package/dist/components/navigation-menu/PlNavigationMenu.js +1 -1
- package/dist/components/otp-field/PlOtpField.d.ts +6 -0
- package/dist/components/otp-field/PlOtpField.js +1 -1
- package/dist/components/page-layout/PlPageLayout.js +1 -1
- package/dist/components/pagination/PlPagination.d.ts +12 -9
- package/dist/components/pagination/PlPagination.js +1 -1
- package/dist/components/panes/PlPanes.d.ts +5 -0
- package/dist/components/panes/PlPanes.js +1 -1
- package/dist/components/pie-chart/PlPieChart.js +1 -1
- package/dist/components/pill/PlPill.js +1 -1
- package/dist/components/popover/PlPopover.d.ts +5 -5
- package/dist/components/popover/PlPopover.js +1 -1
- package/dist/components/progress-box/PlProgressBox.js +1 -1
- package/dist/components/progress-circular/PlProgressCircular.js +1 -1
- package/dist/components/progress-linear/PlProgressLinear.js +1 -1
- package/dist/components/radio-group/PlRadioGroup.js +1 -1
- package/dist/components/rating/PlRating.d.ts +1 -1
- package/dist/components/rating/PlRating.js +1 -1
- package/dist/components/scatter-chart/PlScatterChart.js +1 -1
- package/dist/components/scroll-area/PlScrollArea.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.d.ts +19 -6
- package/dist/components/scroll-zone/PlScrollZone.js +1 -1
- package/dist/components/segmented-button/PlSegmentedButton.js +1 -1
- package/dist/components/select/PlSelect.js +1 -1
- package/dist/components/show/PlShow.d.ts +16 -0
- package/dist/components/show/PlShow.js +1 -1
- package/dist/components/sidebar/PlSidebar.js +1 -1
- package/dist/components/sidebar/PlSidebarTrigger.js +1 -1
- package/dist/components/skeleton/PlSkeleton.js +1 -1
- package/dist/components/slider/PlSlider.d.ts +13 -1
- package/dist/components/slider/PlSlider.js +1 -1
- package/dist/components/sparkline/PlSparkline.js +1 -1
- package/dist/components/spoiler/PlSpoiler.d.ts +15 -8
- package/dist/components/spoiler/PlSpoiler.js +1 -1
- package/dist/components/stat/PlStat.d.ts +4 -0
- package/dist/components/stat/PlStat.js +1 -1
- package/dist/components/stepper/PlStepper.d.ts +1 -1
- package/dist/components/stepper/PlStepper.js +1 -1
- package/dist/components/switch/PlSwitch.js +1 -1
- package/dist/components/table/PlTable.d.ts +5 -5
- package/dist/components/tabs/PlTabs.d.ts +26 -1
- package/dist/components/tabs/PlTabs.js +1 -1
- package/dist/components/text-link/PlTextLink.js +1 -1
- package/dist/components/time-picker/PlTimePicker.js +1 -1
- package/dist/components/timeline/PlTimeline.js +1 -1
- package/dist/components/timeline-chart/PlTimelineChart.js +1 -1
- package/dist/components/toast/PlToast.js +1 -1
- package/dist/components/toggle/PlToggle.js +1 -1
- package/dist/components/tooltip/PlTooltip.js +1 -1
- package/dist/components/tour/PlTour.js +1 -1
- package/dist/components/transfer/PlTransfer.d.ts +10 -1
- package/dist/components/transfer/PlTransfer.js +1 -1
- package/dist/components/tree/PlTree.js +1 -1
- package/dist/components/tree-select/PlTreeSelect.js +1 -1
- package/dist/components/typography/PlTypography.js +1 -1
- package/dist/components/window-pane/PlWindowPane.js +1 -1
- package/dist/css/area-chart.css +1 -0
- package/dist/css/back-top.css +2 -0
- package/dist/css/bar-chart.css +1 -0
- package/dist/css/calendar.css +1 -0
- package/dist/css/carousel.css +2 -0
- package/dist/css/color-picker.css +1 -0
- package/dist/css/combobox.css +1 -0
- package/dist/css/command-palette.css +1 -0
- package/dist/css/confirm.css +2 -0
- package/dist/css/data-table.css +5 -0
- package/dist/css/date-picker.css +1 -0
- package/dist/css/date-range-picker.css +1 -0
- package/dist/css/date-time-picker.css +1 -0
- package/dist/css/floating-action-button.css +2 -0
- package/dist/css/gallery.css +5 -0
- package/dist/css/gauge-chart.css +1 -0
- package/dist/css/heatmap-chart.css +1 -0
- package/dist/css/icon-button.css +1 -0
- package/dist/css/image.css +2 -0
- package/dist/css/line-chart.css +1 -0
- package/dist/css/menubar.css +1 -0
- package/dist/css/pagination.css +1 -0
- package/dist/css/pie-chart.css +1 -0
- package/dist/css/popconfirm.css +2 -0
- package/dist/css/scatter-chart.css +1 -0
- package/dist/css/scroll-zone.css +2 -0
- package/dist/css/sidebar.css +3 -0
- package/dist/css/sparkline.css +1 -0
- package/dist/css/spoiler.css +1 -0
- package/dist/css/stat.css +1 -0
- package/dist/css/time-picker.css +1 -0
- package/dist/css/timeline-chart.css +1 -0
- package/dist/css/tour.css +1 -0
- package/dist/css/transfer.css +4 -0
- package/dist/css/tree-select.css +2 -0
- package/dist/hooks/usePlElementSize.d.ts +4 -1
- package/dist/hooks/usePlElementSize.js +1 -1
- package/dist/hooks/usePlHotKeys.d.ts +5 -1
- package/dist/hooks/usePlHotKeys.js +1 -1
- package/dist/hooks/usePlOnScreen.d.ts +4 -0
- package/dist/hooks/usePlOnScreen.js +1 -1
- package/dist/internal/animate.d.ts +30 -2
- package/dist/internal/animate.js +1 -1
- package/dist/internal/calendar.js +1 -1
- package/dist/internal/chart-frame.d.ts +5 -1
- package/dist/internal/chart-frame.js +1 -1
- package/dist/internal/chart-line.js +1 -1
- package/dist/internal/chart.d.ts +81 -3
- package/dist/internal/chart.js +1 -1
- package/dist/internal/color-scheme.js +1 -1
- package/dist/internal/data-table.d.ts +5 -4
- package/dist/internal/data-table.js +1 -1
- package/dist/internal/date.d.ts +10 -0
- package/dist/internal/date.js +1 -1
- package/dist/internal/drag.d.ts +16 -0
- package/dist/internal/drag.js +1 -1
- package/dist/internal/focusable.d.ts +8 -0
- package/dist/internal/focusable.js +1 -0
- package/dist/internal/form.d.ts +61 -0
- package/dist/internal/form.js +1 -0
- package/dist/internal/gallery.d.ts +60 -14
- package/dist/internal/gallery.js +1 -1
- package/dist/internal/glow.d.ts +17 -0
- package/dist/internal/glow.js +1 -0
- package/dist/internal/highlight.js +1 -1
- package/dist/internal/image.d.ts +94 -0
- package/dist/internal/image.js +1 -0
- package/dist/internal/inert.d.ts +19 -0
- package/dist/internal/inert.js +1 -0
- package/dist/internal/keys.d.ts +19 -0
- package/dist/internal/keys.js +1 -1
- package/dist/internal/labels.d.ts +45 -1
- package/dist/internal/labels.js +1 -1
- package/dist/internal/link.d.ts +17 -0
- package/dist/internal/link.js +1 -1
- package/dist/internal/page-layout.d.ts +14 -7
- package/dist/internal/page-layout.js +1 -1
- package/dist/internal/picker.d.ts +43 -6
- package/dist/internal/picker.js +1 -1
- package/dist/internal/progress.d.ts +16 -8
- package/dist/internal/progress.js +1 -1
- package/dist/internal/scramble.d.ts +4 -0
- package/dist/internal/scramble.js +1 -1
- package/dist/internal/scroll-target.d.ts +5 -0
- package/dist/internal/scroll-target.js +1 -0
- package/dist/internal/steps.js +1 -1
- package/dist/internal/styles.d.ts +66 -0
- package/dist/internal/styles.js +1 -1
- package/dist/internal/text.d.ts +39 -0
- package/dist/internal/text.js +1 -0
- package/dist/internal/watermark.d.ts +44 -0
- package/dist/internal/watermark.js +1 -0
- package/dist/internal/wheel.d.ts +52 -0
- package/dist/internal/wheel.js +1 -0
- package/dist/internal/window.js +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/fr.js +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/zh-Hans.js +1 -1
- package/dist/provider/PlColorSchemeScript.js +1 -1
- package/dist/provider/PlassProvider.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +258 -11
- package/dist/tokens.css +258 -11
- package/dist/types.d.ts +16 -29
- package/package.json +15 -15
|
@@ -43,6 +43,10 @@ export interface PlOnScreenOptions {
|
|
|
43
43
|
* A browser with no observer is told **yes** rather than no. There is no way to
|
|
44
44
|
* find out, and a picture that never loads is worse than one that loads early.
|
|
45
45
|
*
|
|
46
|
+
* The refs are read again after every render, so an element or a `root` that is
|
|
47
|
+
* attached after the first one, or swapped for another, is watched from the
|
|
48
|
+
* moment it is there.
|
|
49
|
+
*
|
|
46
50
|
* @example
|
|
47
51
|
* const section = React.useRef<HTMLDivElement>(null);
|
|
48
52
|
* const seen = usePlOnScreen(section, { rootMargin: '200px' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import*as e from"react";export function usePlOnScreen(
|
|
1
|
+
"use client";import*as e from"react";export function usePlOnScreen(t,{threshold:r=0,rootMargin:n,root:o,once:s=!0}={}){const[u,c]=e.useState(!1),[i,l]=e.useState(null),[f,a]=e.useState(null);return e.useEffect(()=>{t.current!==i&&l(t.current),(o?.current??null)!==f&&a(o?.current??null)}),e.useEffect(()=>{if(!i)return;if("undefined"==typeof IntersectionObserver)return void c(!0);const e=new IntersectionObserver(([t])=>{t.isIntersecting?(c(!0),s&&e.disconnect()):s||c(!1)},{threshold:r,rootMargin:n,root:f});return e.observe(i),()=>e.disconnect()},[i,f,r,n,s]),u}
|
|
@@ -150,7 +150,25 @@ export interface AnimationRun {
|
|
|
150
150
|
state: 'running' | 'paused';
|
|
151
151
|
/** Whether the animation has been let go at all. */
|
|
152
152
|
started: boolean;
|
|
153
|
-
/**
|
|
153
|
+
/**
|
|
154
|
+
* How many times it has been started, counting every hover, every `play` and
|
|
155
|
+
* every change of `nonce`.
|
|
156
|
+
*
|
|
157
|
+
* `started` stays `true` from the first start on, so a second hover changes
|
|
158
|
+
* nothing an effect could depend on. A keyframe does not need to know, because
|
|
159
|
+
* it is rewound in the DOM whenever this changes. Counter, Scramble and Typing
|
|
160
|
+
* run their own loops in JavaScript, and they replay by listing this among
|
|
161
|
+
* their effects' dependencies.
|
|
162
|
+
*/
|
|
163
|
+
runs: number;
|
|
164
|
+
/**
|
|
165
|
+
* The hover trigger's handlers when `trigger` is `hover`; empty otherwise.
|
|
166
|
+
*
|
|
167
|
+
* Merged with the caller's props through `mergeProps` rather than spread
|
|
168
|
+
* beside them. Both sides want `onPointerEnter` and `onFocus`, and a spread
|
|
169
|
+
* keeps only one: either a caller's prefetch never runs, or a caller's
|
|
170
|
+
* `onFocus` quietly takes the keyboard's way in away from the effect.
|
|
171
|
+
*/
|
|
154
172
|
handlers: React.HTMLAttributes<HTMLElement>;
|
|
155
173
|
}
|
|
156
174
|
/**
|
|
@@ -171,6 +189,12 @@ export interface AnimationRun {
|
|
|
171
189
|
* with it. Clearing `animation-name`, reading a layout property to force the
|
|
172
190
|
* style to settle, and putting it back is the one move that rewinds the element
|
|
173
191
|
* and leaves everything inside it alone.
|
|
192
|
+
*
|
|
193
|
+
* **`visible` is measured rather than observed.** Two observers report and
|
|
194
|
+
* neither decides: what they say is that the view has moved, and the answer is
|
|
195
|
+
* then read off the element's own resting box. An `IntersectionObserver` sees
|
|
196
|
+
* the element where its first frame is holding it, which for a slide is a
|
|
197
|
+
* screen from where it lives, so the box it reports on is the wrong box.
|
|
174
198
|
*/
|
|
175
199
|
export declare function useAnimationRun({ trigger, play, once, threshold, paused, infinite, nonce }: AnimationRunOptions): AnimationRun;
|
|
176
200
|
export interface StaggerPosition extends Required<PlassAnimateStaggerProps> {
|
|
@@ -224,7 +248,11 @@ export interface AnimateElement {
|
|
|
224
248
|
ref: React.RefCallback<HTMLElement>;
|
|
225
249
|
className: string;
|
|
226
250
|
style: React.CSSProperties;
|
|
227
|
-
/**
|
|
251
|
+
/**
|
|
252
|
+
* The hover handlers and the two data attributes, to be merged with the
|
|
253
|
+
* caller's props through `mergeProps` for the reason `AnimationRun.handlers`
|
|
254
|
+
* gives.
|
|
255
|
+
*/
|
|
228
256
|
props: React.HTMLAttributes<HTMLElement> & Record<string, unknown>;
|
|
229
257
|
/** The children, with the effect written onto them if it was staggered. */
|
|
230
258
|
children: React.ReactNode;
|
package/dist/internal/animate.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"react";import{cx as
|
|
1
|
+
import*as e from"react";import{cx as t}from"./styles.js";export const animationClasses={fade:"plass-anim-fade",grow:"plass-anim-scale",slide:"plass-anim-slide",zoom:"plass-anim-scale",rotate:"plass-anim-rotate",blink:"plass-anim-blink",reveal:"plass-anim-reveal"};export const animBaseClass="plass-anim";export function lengthValue(e){return"number"==typeof e?`${e}px`:e}export function repeatValue(e){return"infinite"===e?"infinite":String(e)}export function isInfinite(e){return"infinite"===e}export function directionValue(e,t){return"out"===e?t?"alternate-reverse":"reverse":t?"alternate":"normal"}export const defaultViewRange="entry 0% cover 45%";export function animationSlots(e){const t={"--p-anim-duration":`${e.duration}ms`,"--p-anim-delay":`${e.delay}ms`,"--p-anim-repeat":repeatValue(e.repeat),"--p-anim-direction":directionValue(e.mode??"in",e.alternate)};return e.easing&&(t["--p-anim-ease"]=e.easing),"view"===e.timeline&&(t["--p-anim-timeline"]="view()",t["--p-anim-range"]=e.range??defaultViewRange),void 0!==e.opacity&&(t["--p-anim-opacity"]=String(e.opacity)),void 0!==e.scale&&(t["--p-anim-scale"]=String(e.scale)),void 0!==e.x&&(t["--p-anim-x"]=e.x),void 0!==e.y&&(t["--p-anim-y"]=e.y),void 0!==e.angle&&(t["--p-anim-angle"]=e.angle),void 0!==e.angleTo&&(t["--p-anim-angle-to"]=e.angleTo),void 0!==e.clip&&(t["--p-anim-clip"]=e.clip),t}export function revealClip(e){switch(e){case"top":return"inset(0 0 100% 0)";case"bottom":return"inset(100% 0 0 0)";case"right":return"inset(0 0 0 100%)";default:return"inset(0 100% 0 0)"}}export function slideOffsets(e,t){const n=lengthValue(t),r="number"==typeof t?-t+"px":`calc(-1 * ${n})`;switch(e){case"top":return{x:"0px",y:r};case"bottom":return{x:"0px",y:n};case"left":return{x:r,y:"0px"};default:return{x:n,y:"0px"}}}function viewportRect(){const e=document.documentElement;return new DOMRect(0,0,e.clientWidth,e.clientHeight)}function holds(e,t){return null!==e&&t instanceof Node&&e.contains(t)}export function useAnimationRun({trigger:t,play:n,once:r,threshold:i,paused:a,infinite:o,nonce:s}){const l=e.useRef(null),[c,u]=e.useState("mount"===t),[m,p]=e.useState(0),f=e.useCallback(()=>{u(!0),p(e=>e+1)},[]);e.useLayoutEffect(()=>{const e=l.current;if(!e||0===m)return;const t=[e];for(const n of e.querySelectorAll(".plass-anim, .plass-marquee-track"))n.closest("[data-plass-animation]")===e&&t.push(n);for(const e of t)e.style.animationName="none";e.offsetWidth;for(const e of t)e.style.animationName=""},[m]);const d=e.useRef("mount"!==t);e.useEffect(()=>{d.current=!c},[c]),e.useEffect(()=>{if("visible"!==t)return;const e=l.current;if(!e||"undefined"==typeof IntersectionObserver)return void u(!0);const n=[],a=e.parentElement;let o=a?null:viewportRect();const check=()=>{if(!o)return;const t=function visibleShare(e,t){const n=e.width*e.height;if(n<=0)return 0;const r=Math.min(e.right,t.right)-Math.max(e.left,t.left),i=Math.min(e.bottom,t.bottom)-Math.max(e.top,t.top);return Math.max(0,r)*Math.max(0,i)/n}(function restingRect(e,t){if(!t)return e.getBoundingClientRect();const n=e.style.animationName;e.style.animationName="none";const r=e.getBoundingClientRect();return e.style.animationName=n,r}(e,d.current),o);if(t>0&&t>=i){if(f(),r)for(const e of n)e.disconnect()}else r||u(!1)},s=function measureSteps(e){const t=Array.from({length:21},(e,t)=>t/20);return e>0&&e<1?[...t,e]:t}(i);if(a){const e=new IntersectionObserver(([e])=>{o=function clipRect(e){const t=e.boundingClientRect;return t.width*t.height>0?e.intersectionRect:e.rootBounds??viewportRect()}(e),check()},{threshold:s});n.push(e),e.observe(a)}const c=new IntersectionObserver(check,{threshold:s});return n.push(c),c.observe(e),()=>{for(const e of n)e.disconnect()}},[t,r,i,f]);const g=e.useRef(s);e.useEffect(()=>{Object.is(s,g.current)||(g.current=s,f())},[s,f]),e.useEffect(()=>{"manual"===t&&(n?f():u(!1))},[t,n,f]);const h="hover"===t?{onPointerEnter:f,onFocus:e=>{holds(l.current,e.relatedTarget)||f()},onPointerLeave:()=>{o&&u(!1)},onBlur:e=>{o&&!holds(l.current,e.relatedTarget)&&u(!1)}}:{};return{ref:e.useCallback(e=>{l.current=e},[]),state:c&&!a?"running":"paused",started:c,runs:m,handlers:h}}export function staggerSlots(e,{index:t,count:n,stagger:r,durationStep:i,reverse:a}){const o=a?n-1-t:t;return{...e,delay:e.delay+o*r,duration:Math.max(0,e.duration+o*i)}}export function animateChildren(n,r,i){const a=e.Children.toArray(n);return a.map((n,o)=>{const s=i(o,a.length);if(!e.isValidElement(n))return e.createElement("span",{key:o,className:r,style:s},n);const l=n.props;return e.cloneElement(n,{className:t(r,l.className),style:{...s,...l.style}})})}export function useAnimateElement(e){const{effect:t,trigger:n,play:r,once:i,threshold:a,paused:o,infinite:s,nonce:l,stagger:c=0,durationStep:u=0,reverse:m=!1,origin:p,children:f,...d}=e,g=useAnimationRun({trigger:"view"===d.timeline?"mount":n,play:r,once:i,threshold:a,paused:o,infinite:s,nonce:l}),h=t?`plass-anim ${animationClasses[t]}`:"",y=0!==c&&null!==t,v=void 0===p?null:{transformOrigin:p};return{ref:g.ref,className:y?"":h,style:{...v,...y?null:animationSlots(d),"--p-anim-state":g.state},props:{...g.handlers,"data-plass-animation":t??void 0,"data-state":g.state},children:y?animateChildren(f,h,(e,t)=>({...v,...animationSlots(staggerSlots(d,{index:e,count:t,stagger:c,durationStep:u,reverse:m}))})):f}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{defaultLabels as r,useLabels as s}from"./labels.js";import{PlButton as n}from"../components/button/PlButton.js";import{ChevronIcon as l}from"./icons.js";import{dateFormatter as a}from"./format.js";import{addDays as i,addMonths as c,addYears as u,calendarWeeks as d,compareDay as m,isDayOutside as h,isMonthBeforeYear as p,isMonthOutside as g,isSameDay as f,isSameMonth as v,isValidDate as b,isYearOutside as x,makeDate as w,meridiemLabels as y,monthLabels as D,startOfDay as N,startOfMonth as S,today as C,weekdayLabels as M,withTime as k,YEAR_PAGE_SIZE as P,yearPageStart as z}from"./date.js";import{controlHeightClasses as Y,controlTextClasses as j,cx as A,gapClasses as F,metaTextClasses as E,srOnlyClasses as R,transitionClasses as H}from"./styles.js";export const defaultPickerLabels=r;export function usePickerLabels(e){const t=s();return o.useMemo(()=>e?{...t,...e}:t,[t,e])}const T={year:0,month:1,day:2},B={xs:"1.5rem",sm:"2rem",md:"2.5rem",lg:"3rem",xl:"3.5rem"},G={xs:"rounded-(--plass-radius-xs)",sm:"rounded-(--plass-radius-xs)",md:"rounded-(--plass-radius-sm)",lg:"rounded-(--plass-radius-md)",xl:"rounded-(--plass-radius-lg)"},K={xs:"rounded-s-(--plass-radius-xs)",sm:"rounded-s-(--plass-radius-xs)",md:"rounded-s-(--plass-radius-sm)",lg:"rounded-s-(--plass-radius-md)",xl:"rounded-s-(--plass-radius-lg)"},L={xs:"rounded-e-(--plass-radius-xs)",sm:"rounded-e-(--plass-radius-xs)",md:"rounded-e-(--plass-radius-sm)",lg:"rounded-e-(--plass-radius-md)",xl:"rounded-e-(--plass-radius-lg)"},I=/* @__PURE__ */["relative flex items-center justify-center tabular-nums select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",H,"focus-visible:z-10 focus-visible:[outline:2px_solid_var(--p-ring)]","focus-visible:[outline-offset:-2px]"].join(" ");function Cell({children:o,label:r,selected:s,inRange:n=!1,rangeEdge:l=null,current:a=!1,muted:i=!1,disabled:c=!1,focused:u=!1,size:d,className:m,onClick:h,onPointerEnter:p,onKeyDown:g}){return t("button",{type:"button",role:"gridcell","aria-label":r,"aria-selected":s,"aria-current":a?"date":void 0,"aria-disabled":c||void 0,tabIndex:u?0:-1,"data-focus-target":u?"true":void 0,className:A(I,"start"===l?K[d]:"end"===l?L[d]:"middle"===l?"rounded-none":G[d],c?"cursor-not-allowed text-(--plass-muted-fg) opacity-50":s?"cursor-pointer font-semibold text-(--p-on-solid) [background-image:var(--p-fill)] hover:brightness-105 active:brightness-95":n?"cursor-pointer bg-(--p-soft) text-(--plass-fg) hover:bg-(--p-soft-hover) active:bg-(--p-soft-press)":a?"cursor-pointer font-semibold text-(--p-accent) hover:bg-(--p-soft) active:bg-(--p-soft-hover)":i?"cursor-pointer text-(--plass-muted-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)":"cursor-pointer text-(--plass-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)",m),onClick:()=>{c||h()},onPointerEnter:p,onKeyDown:g,children:[o,a?e("span",{"aria-hidden":"true",className:"absolute bottom-[0.18em] size-[0.22em] rounded-full bg-current"}):null]})}function Header({size:r,color:s,view:a,precision:i,month:c,locale:u,labels:d,showPreviousButton:m,showNextButton:h,onStep:g,onViewChange:f}){const v=D(u,"long")[c.getMonth()],b=String(c.getFullYear()),x=p(u),w="day"===a?[d.previousMonth,d.nextMonth]:"month"===a?[d.previousYear,d.nextYear]:[d.previousYears,d.nextYears],stepper=(t,o)=>o?e(n,{variant:"ghost",size:r,color:s,density:"compact","aria-label":w[-1===t?0:1],onClick:()=>g(t),startIcon:e("span",{className:A("flex items-center",-1===t?"rotate-90 rtl:-rotate-90":"-rotate-90 rtl:rotate-90"),children:e(l,{})})}):e("span",{"aria-hidden":"true",className:A(Y[r],"w-(--p-cell)")}),disclosure=t=>e("span",{className:A("flex items-center text-(--plass-muted-fg)","[transition:rotate_var(--plass-duration)_var(--plass-ease)]",t&&"rotate-180"),children:e(l,{})}),y=e(n,{variant:"ghost",size:r,color:s,density:"compact","aria-label":d.chooseMonth,"aria-expanded":"month"===a,onClick:()=>f("month"===a?i:"month"),endIcon:disclosure("month"===a),children:v},"month"),N=e(n,{variant:"ghost",size:r,color:s,density:"compact",className:"tabular-nums","aria-label":d.chooseYear,"aria-expanded":"year"===a,onClick:()=>f("year"===a?i:"year"),endIcon:disclosure("year"===a),children:b},"year"),S=z(c.getFullYear());return t("div",{className:"flex items-center justify-between gap-1",children:[stepper(-1,m),e("div",{className:A("flex min-w-0 flex-1 items-center justify-center",F[r]),children:"year"===a?e("span",{className:A("flex items-center font-semibold tabular-nums text-(--plass-fg)",Y[r],j[r]),children:`${S}–${S+P-1}`}):"month"===a?N:t(o.Fragment,x?{children:[y,N]}:{children:[N,y]})}),stepper(1,h)]})}export function Calendar({size:r,color:s,locale:n,weekStartsOn:l,month:a,onMonthChange:i,precision:d="day",selected:m,rangeStart:p=null,rangeEnd:g=null,onSelect:f,onPreviewChange:x,minDate:y,maxDate:D,shouldDisableDate:M,showOutsideDays:k=!0,autoFocus:z=!1,showPreviousButton:Y=!0,showNextButton:j=!0,labels:E,className:R}){const[H,G]=o.useState(d),K=T[H]>T[d]?d:H,L=o.useMemo(()=>m.filter(b),[m]),[I,O]=o.useState(()=>{const e=L.find(e=>v(e,a));return e?N(e):v(C(),a)?C():S(a)}),U=o.useRef(z),q=o.useRef(null);o.useEffect(()=>{O(e=>v(e,a)?e:S(a))},[a]),o.useLayoutEffect(()=>{U.current&&(U.current=!1,q.current?.querySelector('[data-focus-target="true"]')?.focus({preventScroll:!0}))});const $=o.useCallback(e=>h(e,y,D)||(M?.(e)??!1),[y,D,M]),changeView=e=>{U.current=!0,G(e)},moveCursor=e=>{U.current=!0,i(e)};return t("div",{ref:q,className:A("flex flex-col",F[r],R),style:{"--p-cell":B[r]},onPointerLeave:()=>x?.(null),children:[e(Header,{size:r,color:s,view:K,precision:d,month:a,locale:n,labels:E,showPreviousButton:Y,showNextButton:j,onStep:e=>{i("day"===K?c(a,e):u(a,"month"===K?e:e*P))},onViewChange:changeView}),e("div",{className:"h-[calc(var(--p-cell)*7)] w-[calc(var(--p-cell)*7)]",children:"day"===K?e(DayGrid,{size:r,locale:n,weekStartsOn:l,month:a,chosen:L,rangeStart:p,rangeEnd:g,focusedDate:I,showOutsideDays:k,isDisabled:$,onSelect:e=>{O(e),f(e)},onPreviewChange:x,onMoveFocus:e=>{U.current=!0,O(e),v(e,a)||i(S(e))}}):"month"===K?e(MonthGrid,{size:r,locale:n,month:a,chosen:L,minDate:y,maxDate:D,onMoveCursor:moveCursor,onPick:e=>{const t=w(a.getFullYear(),e,1);i(t),"month"===d?f(t):changeView("day")}}):e(YearGrid,{size:r,month:a,chosen:L,minDate:y,maxDate:D,onMoveCursor:moveCursor,onPick:e=>{const t=w(e,"year"===d?0:a.getMonth(),1);i(t),"year"===d?f(t):changeView("month")}})})]})}function DayGrid({size:o,locale:r,weekStartsOn:s,month:n,chosen:l,rangeStart:u,rangeEnd:h,focusedDate:p,showOutsideDays:g,isDisabled:x,onSelect:w,onPreviewChange:y,onMoveFocus:D}){const N=d(n,s),S=M(r,s,"short"),k=M(r,s,"long"),P=a(r,{dateStyle:"full"}),z=function orderedRange(e,t){return b(e)&&b(t)?m(e,t)<=0?[e,t]:[t,e]:null}(u,h),Y=C();return t("div",{role:"grid",className:"flex h-full flex-col",children:[e("div",{role:"row",className:"grid grid-cols-7",children:S.map((t,r)=>e("span",{role:"columnheader","aria-label":k[r],className:A("flex h-(--p-cell) items-center justify-center font-semibold text-(--plass-muted-fg) select-none",E[o]),children:t},r))}),N.map((t,r)=>e("div",{role:"row",className:"grid grid-cols-7",children:t.map(t=>{const r=!v(t,n);if(r&&!g)return e("span",{role:"gridcell","aria-hidden":"true",className:"size-(--p-cell)"},t.getTime());const a=l.some(e=>f(e,t)),u=null!==z&&m(t,z[0])>=0&&m(t,z[1])<=0,d=null!==z&&u&&f(t,z[0]),h=null!==z&&u&&f(t,z[1]);return e(Cell,{size:o,label:P.format(t),selected:a,inRange:u&&!a,rangeEdge:u?d&&h?"both":d?"start":h?"end":"middle":null,current:f(t,Y)&&!a,muted:r,disabled:x(t),focused:f(t,p),className:A("size-(--p-cell)",j[o]),onClick:()=>w(t),onPointerEnter:()=>y?.(t),onKeyDown:e=>((e,t)=>{const o=(t.getDay()-s+7)%7,r={ArrowLeft:()=>i(t,-1),ArrowRight:()=>i(t,1),ArrowUp:()=>i(t,-7),ArrowDown:()=>i(t,7),Home:()=>i(t,-o),End:()=>i(t,6-o),PageUp:()=>c(t,e.shiftKey?-12:-1),PageDown:()=>c(t,e.shiftKey?12:1)}[e.key];r&&(e.preventDefault(),D(r()))})(e,t),children:t.getDate()},t.getTime())})},r))]})}function MonthGrid({size:t,locale:o,month:r,chosen:s,minDate:n,maxDate:l,onMoveCursor:a,onPick:i}){const u=D(o,"short"),d=D(o,"long"),m=r.getFullYear(),h=new Date,onKeyDown=e=>{const t={ArrowLeft:-1,ArrowRight:1,ArrowUp:-3,ArrowDown:3,PageUp:-12,PageDown:12}[e.key];void 0!==t&&(e.preventDefault(),a(c(S(r),t)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2,3].map(o=>e("div",{role:"row",className:"grid grid-cols-3 gap-1",children:[0,1,2].map(a=>{const c=3*o+a;return e(Cell,{size:t,label:`${d[c]} ${m}`,selected:s.some(e=>e.getFullYear()===m&&e.getMonth()===c),current:h.getFullYear()===m&&h.getMonth()===c,disabled:g(w(m,c,1),n,l),focused:c===r.getMonth(),className:A("h-(--p-cell) w-full",j[t]),onClick:()=>i(c),onKeyDown,children:u[c]},c)})},o))})}function YearGrid({size:t,month:o,chosen:r,minDate:s,maxDate:n,onMoveCursor:l,onPick:a}){const i=z(o.getFullYear()),c=(new Date).getFullYear(),onKeyDown=e=>{const t={ArrowLeft:-1,ArrowRight:1,ArrowUp:-4,ArrowDown:4,PageUp:-P,PageDown:P}[e.key];void 0!==t&&(e.preventDefault(),l(u(S(o),t)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2].map(l=>e("div",{role:"row",className:"grid grid-cols-4 gap-1",children:[0,1,2,3].map(u=>{const d=i+4*l+u;return e(Cell,{size:t,label:String(d),selected:r.some(e=>e.getFullYear()===d),current:d===c,disabled:x(w(d,0,1),s,n),focused:d===o.getFullYear(),className:A("h-(--p-cell) w-full",j[t]),onClick:()=>a(d),onKeyDown,children:d},d)})},l))})}function revealInColumn(e){const t=e.parentElement;if(!t)return;const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top-t.clientTop+t.scrollTop,n=s+o.height;s<t.scrollTop?t.scrollTop=s:n>t.scrollTop+t.clientHeight&&(t.scrollTop=n-t.clientHeight)}export function TimeGrid({size:r,density:s,locale:n,value:l,referenceDate:i,onChange:c,hour12:u,showSeconds:d,hourStep:m,minuteStep:h,secondStep:p,shouldDisableTime:g,autoFocus:f=!1,labels:v,className:b}){const x=l??i,w=o.useRef(null),[D,N]=o.useMemo(()=>y(n),[n]);o.useEffect(()=>{const e=w.current;if(e?.querySelectorAll('[data-chosen="true"]').forEach(revealInColumn),f){const t=e?.querySelector('[role="listbox"]');(t?.querySelector('[data-chosen="true"]')??t?.querySelector('[role="option"]'))?.focus({preventScroll:!0})}},[f]);const S=o.useMemo(()=>{const e=Math.ceil((u?12:24)/m),t=Array.from({length:e},(e,t)=>t*m);return u?t.map(e=>0===e?12:e):t},[u,m]),C=o.useMemo(()=>Array.from({length:Math.ceil(60/h)},(e,t)=>t*h),[h]),M=o.useMemo(()=>Array.from({length:Math.ceil(60/p)},(e,t)=>t*p),[p]),pad=e=>String(e).padStart(2,"0"),P=u?x.getHours()%12||12:x.getHours(),column=(t,o,s,n,a)=>e("div",{role:"listbox","aria-label":o,className:A("flex flex-col gap-0.5 overflow-y-auto overscroll-contain","h-[calc(var(--p-cell)*7)] w-[calc(var(--p-cell)*1.75)]","scroll-py-0.5 [scrollbar-width:thin]"),children:s.map(o=>{const s=((e,t)=>k(x,"hour"===e?{hours:u?t%12+(x.getHours()>=12?12:0):t}:"minute"===e?{minutes:t}:"second"===e?{seconds:t}:{hours:x.getHours()%12+12*t}))(t,o),i=null!==l&&n(o),d=g?.(s,t)??!1;return e("button",{type:"button",role:"option","aria-selected":i,"aria-disabled":d||void 0,"data-chosen":i?"true":void 0,className:A(I,G[r],Y[r],j[r],"w-full shrink-0",d?"cursor-not-allowed text-(--plass-muted-fg) opacity-50":i?"cursor-pointer font-semibold text-(--p-on-solid) [background-image:var(--p-fill)] hover:brightness-105 active:brightness-95":"cursor-pointer text-(--plass-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)"),onClick:()=>{d||c(s)},children:a(o)},o)})},t);return t("div",{ref:w,className:A("flex","compact"===s?"gap-0.5":"gap-1",b),style:{"--p-cell":B[r]},children:[column("hour",v.hour,S,e=>e===P,e=>u?String(e):pad(e)),column("minute",v.minute,C,e=>e===x.getMinutes(),pad),d?column("second",v.second,M,e=>e===x.getSeconds(),pad):null,u?column("meridiem",v.meridiem,[0,1],e=>(x.getHours()>=12?1:0)===e,e=>0===e?D:N):null,e("span",{className:R,"aria-live":"polite",children:null===l?"":a(n,{hour:"numeric",minute:"2-digit",...d?{second:"2-digit"}:{}}).format(l)})]})}
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as o from"react";import{defaultLabels as t,useLabels as n}from"./labels.js";import{PlButton as l}from"../components/button/PlButton.js";import{ChevronIcon as s}from"./icons.js";import{dateFormatter as a}from"./format.js";import{addDays as i,addMonths as c,addYears as d,calendarWeeks as u,compareDay as m,isDayOutside as h,isMonthBeforeYear as p,isMonthOutside as g,isSameDay as f,isSameMonth as b,isValidDate as v,isYearOutside as y,makeDate as x,meridiemLabels as w,monthLabels as D,startOfDay as N,startOfMonth as S,today as k,weekdayLabels as C,withTime as M,YEAR_PAGE_SIZE as P,yearPageStart as z}from"./date.js";import{controlHeightClasses as A,controlTextClasses as $,cx as Y,forcedFillClasses as j,gapClasses as B,metaTextClasses as E,srOnlyClasses as F,transitionClasses as I}from"./styles.js";export const defaultPickerLabels=t;export function usePickerLabels(e){const r=n();return o.useMemo(()=>e?{...r,...e}:r,[r,e])}const H={year:0,month:1,day:2},T={xs:"1.5rem",sm:"2rem",md:"2.5rem",lg:"3rem",xl:"3.5rem"},R={xs:"rounded-(--plass-radius-xs)",sm:"rounded-(--plass-radius-xs)",md:"rounded-(--plass-radius-sm)",lg:"rounded-(--plass-radius-md)",xl:"rounded-(--plass-radius-lg)"},K={xs:"rounded-s-(--plass-radius-xs)",sm:"rounded-s-(--plass-radius-xs)",md:"rounded-s-(--plass-radius-sm)",lg:"rounded-s-(--plass-radius-md)",xl:"rounded-s-(--plass-radius-lg)"},O={xs:"rounded-e-(--plass-radius-xs)",sm:"rounded-e-(--plass-radius-xs)",md:"rounded-e-(--plass-radius-sm)",lg:"rounded-e-(--plass-radius-md)",xl:"rounded-e-(--plass-radius-lg)"},G=/* @__PURE__ */["relative flex items-center justify-center tabular-nums select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",I,"focus-visible:z-10 focus-visible:[outline:2px_solid_var(--p-ring)]","focus-visible:[outline-offset:-2px]"].join(" ");function Cell({children:o,label:t,selected:n,inRange:l=!1,rangeEdge:s=null,current:a=!1,muted:i=!1,disabled:c=!1,focused:d=!1,size:u,className:m,onClick:h,onPointerEnter:p,onKeyDown:g}){return r("button",{type:"button",role:"gridcell","aria-label":t,"aria-selected":n,"aria-current":a?"date":void 0,"aria-disabled":c||void 0,tabIndex:d?0:-1,"data-focus-target":d?"true":void 0,className:Y(G,"start"===s?K[u]:"end"===s?O[u]:"middle"===s?"rounded-none":R[u],c?"cursor-not-allowed text-(--plass-muted-fg) opacity-50":n?`cursor-pointer font-semibold text-(--p-on-solid) [background-image:var(--p-fill)] hover:brightness-105 active:brightness-95 ${j}`:l?"cursor-pointer bg-(--p-soft) text-(--plass-fg) hover:bg-(--p-soft-hover) active:bg-(--p-soft-press) forced-colors:border-y forced-colors:[border-color:Highlight]":a?"cursor-pointer font-semibold text-(--p-accent) hover:bg-(--p-soft) active:bg-(--p-soft-hover)":i?"cursor-pointer text-(--plass-muted-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)":"cursor-pointer text-(--plass-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)",m),onClick:()=>{c||h()},onPointerEnter:p,onKeyDown:g,children:[o,a?e("span",{"aria-hidden":"true",className:Y("absolute bottom-[0.18em] size-[0.22em] rounded-full bg-current",n?"forced-colors:[background-color:HighlightText]":"forced-colors:[background-color:CanvasText]")}):null]})}function headingIds(e,r,o){return"year"===r?`${e}-range`:"month"===r?`${e}-year`:p(o)?`${e}-month ${e}-year`:`${e}-year ${e}-month`}function Header({size:t,color:n,view:a,precision:i,month:c,locale:d,labels:u,showPreviousButton:m,showNextButton:h,onStep:g,onViewChange:f,id:b}){const v=D(d,"long")[c.getMonth()],y=String(c.getFullYear()),x=p(d),w="day"===a?[u.previousMonth,u.nextMonth]:"month"===a?[u.previousYear,u.nextYear]:[u.previousYears,u.nextYears],stepper=(r,o)=>o?e(l,{variant:"ghost",size:t,color:n,density:"compact","aria-label":w[-1===r?0:1],onClick:()=>g(r),startIcon:e("span",{className:Y("flex items-center",-1===r?"rotate-90 rtl:-rotate-90":"-rotate-90 rtl:rotate-90"),children:e(s,{})})}):e("span",{"aria-hidden":"true",className:Y(A[t],"w-(--p-cell)")}),disclosure=r=>e("span",{className:Y("flex items-center text-(--plass-muted-fg)","[transition:rotate_var(--plass-duration)_var(--plass-ease)]",r&&"rotate-180"),children:e(s,{})}),N=e(l,{id:`${b}-month`,variant:"ghost",size:t,color:n,density:"compact","aria-describedby":`${b}-month-hint`,"aria-expanded":"month"===a,onClick:()=>f("month"===a?i:"month"),endIcon:disclosure("month"===a),children:v},"month"),S=e(l,{id:`${b}-year`,variant:"ghost",size:t,color:n,density:"compact",className:"tabular-nums","aria-describedby":`${b}-year-hint`,"aria-expanded":"year"===a,onClick:()=>f("year"===a?i:"year"),endIcon:disclosure("year"===a),children:y},"year"),k=z(c.getFullYear());return r("div",{className:"flex items-center justify-between gap-1",children:[stepper(-1,m),e("div",{className:Y("flex min-w-0 flex-1 items-center justify-center",B[t]),children:"year"===a?e("span",{id:`${b}-range`,className:Y("flex items-center font-semibold tabular-nums text-(--plass-fg)",A[t],$[t]),children:`${k}–${k+P-1}`}):"month"===a?S:r(o.Fragment,x?{children:[N,S]}:{children:[S,N]})}),stepper(1,h),e("span",{id:`${b}-month-hint`,hidden:!0,children:u.chooseMonth}),e("span",{id:`${b}-year-hint`,hidden:!0,children:u.chooseYear})]})}export function Calendar({size:t,color:n,locale:l,weekStartsOn:s,month:a,onMonthChange:i,precision:u="day",selected:m,rangeStart:p=null,rangeEnd:g=null,onSelect:f,onPreviewChange:y,minDate:w,maxDate:D,shouldDisableDate:C,showOutsideDays:M=!0,autoFocus:z=!1,showPreviousButton:A=!0,showNextButton:$=!0,labels:j,className:E}){const F=o.useId(),[I,R]=o.useState(u),K=H[I]>H[u]?u:I,O=o.useMemo(()=>m.filter(v),[m]),[G,L]=o.useState(()=>{const e=O.find(e=>b(e,a));return e?N(e):b(k(),a)?k():S(a)}),U=o.useRef(z),q=o.useRef(null);o.useEffect(()=>{L(e=>b(e,a)?e:S(a))},[a]),o.useLayoutEffect(()=>{U.current&&(U.current=!1,q.current?.querySelector('[data-focus-target="true"]')?.focus({preventScroll:!0}))});const _=o.useCallback(e=>h(e,w,D)||(C?.(e)??!1),[w,D,C]),changeView=e=>{U.current=!0,R(e)},moveCursor=e=>{U.current=!0,i(e)};return r("div",{ref:q,className:Y("flex flex-col",B[t],E),style:{"--p-cell":T[t]},onPointerLeave:()=>y?.(null),children:[e(Header,{size:t,color:n,view:K,precision:u,month:a,locale:l,labels:j,showPreviousButton:A,showNextButton:$,onStep:e=>{i("day"===K?c(a,e):d(a,"month"===K?e:e*P))},onViewChange:changeView,id:F}),e("div",{className:"h-[calc(var(--p-cell)*7)] w-[calc(var(--p-cell)*7)]",children:"day"===K?e(DayGrid,{labelledBy:headingIds(F,K,l),size:t,locale:l,weekStartsOn:s,month:a,chosen:O,rangeStart:p,rangeEnd:g,focusedDate:G,showOutsideDays:M,isDisabled:_,onSelect:e=>{L(e),f(e)},onPreviewChange:y,onMoveFocus:e=>{U.current=!0,L(e),b(e,a)||i(S(e))}}):"month"===K?e(MonthGrid,{labelledBy:headingIds(F,K,l),size:t,locale:l,month:a,chosen:O,minDate:w,maxDate:D,onMoveCursor:moveCursor,onPick:e=>{const r=x(a.getFullYear(),e,1);i(r),"month"===u?f(r):changeView("day")}}):e(YearGrid,{labelledBy:headingIds(F,K,l),size:t,month:a,chosen:O,minDate:w,maxDate:D,onMoveCursor:moveCursor,onPick:e=>{const r=x(e,"year"===u?0:a.getMonth(),1);i(r),"year"===u?f(r):changeView("month")}})})]})}function DayGrid({labelledBy:o,size:t,locale:n,weekStartsOn:l,month:s,chosen:d,rangeStart:h,rangeEnd:p,focusedDate:g,showOutsideDays:y,isDisabled:x,onSelect:w,onPreviewChange:D,onMoveFocus:N}){const S=u(s,l),M=C(n,l,"short"),P=C(n,l,"long"),z=a(n,{dateStyle:"full"}),A=function orderedRange(e,r){return v(e)&&v(r)?m(e,r)<=0?[e,r]:[r,e]:null}(h,p),j=k();return r("div",{role:"grid","aria-labelledby":o,className:"flex h-full flex-col",children:[e("div",{role:"row",className:"grid grid-cols-7",children:M.map((r,o)=>e("span",{role:"columnheader","aria-label":P[o],className:Y("flex h-(--p-cell) items-center justify-center font-semibold text-(--plass-muted-fg) select-none",E[t]),children:r},o))}),S.map((r,o)=>e("div",{role:"row",className:"grid grid-cols-7",children:r.map(r=>{const o=!b(r,s);if(o&&!y)return e("span",{role:"gridcell","aria-hidden":"true",className:"size-(--p-cell)"},r.getTime());const n=d.some(e=>f(e,r)),a=null!==A&&m(r,A[0])>=0&&m(r,A[1])<=0,u=null!==A&&a&&f(r,A[0]),h=null!==A&&a&&f(r,A[1]);return e(Cell,{size:t,label:z.format(r),selected:n,inRange:a&&!n,rangeEdge:a?u&&h?"both":u?"start":h?"end":"middle":null,current:f(r,j)&&!n,muted:o,disabled:x(r),focused:f(r,g),className:Y("size-(--p-cell)",$[t]),onClick:()=>w(r),onPointerEnter:()=>D?.(r),onKeyDown:e=>((e,r)=>{const o=(r.getDay()-l+7)%7,t={ArrowLeft:()=>i(r,-1),ArrowRight:()=>i(r,1),ArrowUp:()=>i(r,-7),ArrowDown:()=>i(r,7),Home:()=>i(r,-o),End:()=>i(r,6-o),PageUp:()=>c(r,e.shiftKey?-12:-1),PageDown:()=>c(r,e.shiftKey?12:1)}[e.key];t&&(e.preventDefault(),N(t()))})(e,r),children:r.getDate()},r.getTime())})},o))]})}function MonthGrid({labelledBy:r,size:o,locale:t,month:n,chosen:l,minDate:s,maxDate:a,onMoveCursor:i,onPick:d}){const u=D(t,"short"),m=D(t,"long"),h=n.getFullYear(),p=new Date,onKeyDown=e=>{const r={ArrowLeft:-1,ArrowRight:1,ArrowUp:-3,ArrowDown:3,PageUp:-12,PageDown:12}[e.key];void 0!==r&&(e.preventDefault(),i(c(S(n),r)))};return e("div",{role:"grid","aria-labelledby":r,className:"flex h-full flex-col justify-evenly",children:[0,1,2,3].map(r=>e("div",{role:"row",className:"grid grid-cols-3 gap-1",children:[0,1,2].map(t=>{const i=3*r+t;return e(Cell,{size:o,label:`${m[i]} ${h}`,selected:l.some(e=>e.getFullYear()===h&&e.getMonth()===i),current:p.getFullYear()===h&&p.getMonth()===i,disabled:g(x(h,i,1),s,a),focused:i===n.getMonth(),className:Y("h-(--p-cell) w-full",$[o]),onClick:()=>d(i),onKeyDown,children:u[i]},i)})},r))})}function YearGrid({labelledBy:r,size:o,month:t,chosen:n,minDate:l,maxDate:s,onMoveCursor:a,onPick:i}){const c=z(t.getFullYear()),u=(new Date).getFullYear(),onKeyDown=e=>{const r={ArrowLeft:-1,ArrowRight:1,ArrowUp:-4,ArrowDown:4,PageUp:-P,PageDown:P}[e.key];void 0!==r&&(e.preventDefault(),a(d(S(t),r)))};return e("div",{role:"grid","aria-labelledby":r,className:"flex h-full flex-col justify-evenly",children:[0,1,2].map(r=>e("div",{role:"row",className:"grid grid-cols-4 gap-1",children:[0,1,2,3].map(a=>{const d=c+4*r+a;return e(Cell,{size:o,label:String(d),selected:n.some(e=>e.getFullYear()===d),current:d===u,disabled:y(x(d,0,1),l,s),focused:d===t.getFullYear(),className:Y("h-(--p-cell) w-full",$[o]),onClick:()=>i(d),onKeyDown,children:d},d)})},r))})}function revealInColumn(e){const r=e.parentElement;if(!r)return;const o=e.getBoundingClientRect(),t=r.getBoundingClientRect(),n=o.top-t.top-r.clientTop+r.scrollTop,l=n+o.height;n<r.scrollTop?r.scrollTop=n:l>r.scrollTop+r.clientHeight&&(r.scrollTop=l-r.clientHeight)}export function TimeGrid({size:t,density:n,locale:l,value:s,referenceDate:i,onChange:c,hour12:d,showSeconds:u,hourStep:m,minuteStep:h,secondStep:p,shouldDisableTime:g,autoFocus:f=!1,labels:b,className:v}){const y=s??i,x=o.useRef(null),[D,N]=o.useMemo(()=>w(l),[l]);o.useEffect(()=>{const e=x.current;if(e?.querySelectorAll('[data-chosen="true"]').forEach(revealInColumn),f){const r=e?.querySelector('[role="listbox"]');(r?.querySelector('[data-chosen="true"]')??r?.querySelector('[role="option"]'))?.focus({preventScroll:!0})}},[f]);const S=o.useMemo(()=>{const e=Math.ceil((d?12:24)/m),r=Array.from({length:e},(e,r)=>r*m);return d?r.map(e=>0===e?12:e):r},[d,m]),k=o.useMemo(()=>Array.from({length:Math.ceil(60/h)},(e,r)=>r*h),[h]),C=o.useMemo(()=>Array.from({length:Math.ceil(60/p)},(e,r)=>r*p),[p]),candidate=(e,r)=>M(y,"hour"===e?{hours:d?r%12+(y.getHours()>=12?12:0):r}:"minute"===e?{minutes:r}:"second"===e?{seconds:r}:{hours:y.getHours()%12+12*r}),pad=e=>String(e).padStart(2,"0"),P=d?y.getHours()%12||12:y.getHours(),column=(r,o,n,l,a)=>{const i=n.map(e=>g?.(candidate(r,e),r)??!1),d=null===s?-1:n.findIndex(l),u=d>=0?d:Math.max(0,i.indexOf(!1)),nearest=(e,r)=>{for(let o=e;o>=0&&o<n.length;o+=r)if(!i[o])return o;return-1};return e("div",{role:"listbox","aria-label":o,onKeyDown:e=>{const o=[...e.currentTarget.querySelectorAll('[role="option"]')],t=o.indexOf(e.target);if(t<0)return;const l="ArrowDown"===e.key?nearest(t+1,1):"ArrowUp"===e.key?nearest(t-1,-1):"Home"===e.key?nearest(0,1):"End"===e.key?nearest(n.length-1,-1):null;null!==l&&(e.preventDefault(),l<0||l===t||(c(candidate(r,n[l])),o[l].focus({preventScroll:!0}),revealInColumn(o[l])))},className:Y("flex flex-col gap-0.5 overflow-y-auto overscroll-contain","h-[calc(var(--p-cell)*7)] w-[calc(var(--p-cell)*1.75)]","scroll-py-0.5 [scrollbar-width:thin]"),children:n.map((o,n)=>{const d=candidate(r,o),m=null!==s&&l(o),h=i[n];return e("button",{type:"button",role:"option",tabIndex:n===u?0:-1,"aria-selected":m,"aria-disabled":h||void 0,"data-chosen":m?"true":void 0,className:Y(G,R[t],A[t],$[t],"w-full shrink-0",h?"cursor-not-allowed text-(--plass-muted-fg) opacity-50":m?`cursor-pointer font-semibold text-(--p-on-solid) [background-image:var(--p-fill)] hover:brightness-105 active:brightness-95 ${j}`:"cursor-pointer text-(--plass-fg) hover:bg-(--p-soft) active:bg-(--p-soft-hover)"),onClick:()=>{h||c(d)},children:a(o)},o)})},r)};return r("div",{ref:x,className:Y("flex","compact"===n?"gap-0.5":"gap-1",v),style:{"--p-cell":T[t]},children:[column("hour",b.hour,S,e=>e===P,e=>d?String(e):pad(e)),column("minute",b.minute,k,e=>e===y.getMinutes(),pad),u?column("second",b.second,C,e=>e===y.getSeconds(),pad):null,d?column("meridiem",b.meridiem,[0,1],e=>(y.getHours()>=12?1:0)===e,e=>0===e?D:N):null,e("span",{className:F,"aria-live":"polite",children:null===s?"":a(l,{hour:"numeric",minute:"2-digit",...u?{second:"2-digit"}:{}}).format(s)})]})}
|
|
@@ -273,8 +273,12 @@ interface DataTableProps {
|
|
|
273
273
|
* It is clipped rather than `display: none`, for the reason `srOnlyClasses`
|
|
274
274
|
* gives: the second one takes it off the accessibility tree along with the
|
|
275
275
|
* screen, which would leave the chart exactly as mute as before.
|
|
276
|
+
*
|
|
277
|
+
* Memoised, because it is a row for every category and none of it changes when
|
|
278
|
+
* the pointer or a key moves the active column, which re-renders the chart
|
|
279
|
+
* around it every time.
|
|
276
280
|
*/
|
|
277
|
-
declare
|
|
281
|
+
declare const ChartDataTable: React.MemoExoticComponent<({ id, caption, corner, categories, series, values, format, locale }: DataTableProps) => React.JSX.Element>;
|
|
278
282
|
interface SurfaceProps extends Omit<PlBoxProps, 'children'> {
|
|
279
283
|
legend: React.ReactNode;
|
|
280
284
|
legendSide: NonNullable<PlassChartLegend['side']>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,Fragment as t,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{PlBox as n}from"../components/box/PlBox.js";import{bandScale as s,categoryAt as i,categoryCount as r,categoryExtent as o,chartFontSizes as c,compactNumber as d,extentOf as h,fitsLast as u,formatCategory as m,markerRadii as p,plotHeights as f,seriesColor as x,showsTick as g,textWidth as v,tickStride as b,toValues as y,truncate as k,valueScale as w}from"./chart.js";import{useDefaults as M}from"./defaults.js";import{numberFormatter as C}from"./format.js";import{usePlElementSize as N}from"../hooks/usePlElementSize.js";import{useLabels as S}from"./labels.js";import{cx as z,glassClasses as P,hasContent as A,metaTextClasses as j,srOnlyClasses as B,transitionClasses as T}from"./styles.js";const W=[];function useMeasuredWidth(e){return N(e)?.width??0}export const markTransitionClasses=["[transition:opacity_var(--plass-duration)_var(--plass-ease),","r_var(--plass-duration)_var(--plass-ease),","scale_var(--plass-duration)_var(--plass-ease)]"].join("");function useVisibility(e){const[t,l]=a.useState(()=>{const t=new Set;return e.forEach((e,l)=>{e.hidden&&t.add(l)}),t}),[n,s]=a.useState(null),i=a.useCallback(e=>{l(t=>{const l=new Set(t);return l.has(e)?l.delete(e):l.add(e),l})},[]);return{visible:e.map((e,l)=>!t.has(l)),hovered:n,toggle:i,setHovered:s}}const _={top:"flex-col-reverse",bottom:"flex-col",left:"flex-row-reverse",right:"flex-row"},F={start:"justify-start",center:"justify-center",end:"justify-end"};function ChartLegendBar({series:a,colors:n,options:s,visibility:i,size:r,values:o,swatch:c}){const d=!1!==s.interactive,h="left"===s.side||"right"===s.side;return e("ul",{className:z("flex list-none flex-wrap items-center gap-x-3 gap-y-1 p-0",h?"min-w-0 flex-col items-start":"",F[s.align??"center"],j[r]),children:a.map((a,s)=>{const r=i.visible[s],h=null!==i.hovered&&i.hovered!==s,u=a.name??`${s+1}`,m=r?n[s]:`color-mix(in oklab, ${n[s]} 40%, transparent)`,p=l(t,{children:[e("span",c?{"aria-hidden":"true",className:"flex size-2.5 shrink-0 items-center justify-center",children:c(s,m)}:{"aria-hidden":"true",className:`size-2.5 shrink-0 rounded-[0.1875rem] ${T}`,style:{backgroundColor:m}}),e("span",{className:"min-w-0 truncate",children:u}),o?.[s]?e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:o[s]}):null]});return e("li",{className:"min-w-0",children:d?e("button",{type:"button","aria-pressed":r,onClick:()=>i.toggle(s),onPointerEnter:()=>i.setHovered(s),onPointerLeave:()=>i.setHovered(null),onFocus:()=>i.setHovered(s),onBlur:()=>i.setHovered(null),className:z("flex min-w-0 cursor-pointer items-center gap-1.5 rounded-(--plass-radius-xs)","px-1 py-0.5 text-(--plass-fg)","[transition-property:background-color,color,opacity]","[transition-duration:var(--plass-duration)]","[transition-timing-function:var(--plass-ease)]","hover:bg-(--p-soft)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-1",r?"":"text-(--plass-muted-fg) line-through",h?"opacity-55":""),children:p}):e("span",{className:z("flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-(--plass-fg)",r?"":"text-(--plass-muted-fg) line-through"),children:p})},a.name??s)})})}function ChartScaleLegend({steps:a,from:n,to:s,middle:i,align:r,vertical:o,size:c}){return e("div",{className:z("flex",o?"":F[r]),children:l("div",{className:z("grid grid-cols-[auto_auto_auto] items-center gap-x-2",j[c]),children:[e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:n}),e("span",{"aria-hidden":"true",className:z("flex h-2.5 overflow-hidden rounded-[0.1875rem]",o?"w-20":"w-24"),children:a.map(t=>e("span",{className:"h-full flex-1",style:{backgroundColor:t}},t))}),e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:s}),i?l(t,{children:[e("span",{}),e("span",{className:"text-center tabular-nums text-(--plass-muted-fg)",children:i}),e("span",{})]}):null]})})}function ChartTooltipPanel({heading:t,items:a,x:n,y:s,flip:i,size:r}){return l("div",{"data-plass-tooltip":"",className:z("pointer-events-none absolute z-10 max-w-56 min-w-24","rounded-(--plass-radius-sm) border p-2",P,"bg-(--plass-glass-press) [border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]",j[r]),style:i?{right:`calc(100% - ${n}px + 10px)`,top:s}:{left:n+10,top:s},children:[e("div",{className:"mb-1 font-medium text-(--plass-fg)",children:t}),e("ul",{className:"flex list-none flex-col gap-0.5 p-0",children:a.map(t=>l("li",{className:"flex items-center gap-1.5",children:[e("span",{"aria-hidden":"true",className:"size-2 shrink-0 rounded-[0.125rem]",style:{backgroundColor:t.color}}),t.name?e("span",{className:"min-w-0 flex-1 truncate text-(--plass-muted-fg)",children:t.name}):null,e("span",{className:"ms-auto shrink-0 font-medium tabular-nums text-(--plass-fg)",children:t.label??t.formatted})]},t.seriesIndex))})]})}function ChartStatus({heading:n,items:s}){return e("span",{role:"status","aria-live":"polite",className:B,children:0===s.length?null:l(t,{children:[A(n)?l(t,{children:[n,", "]}):null,s.map((e,t)=>l(a.Fragment,{children:[t>0?", ":null,e.name?`${e.name}: `:null,e.label??e.formatted]},e.seriesIndex))]})})}function ChartDataTable({id:t,caption:a,corner:n,categories:s,series:i,values:r,format:o,locale:c}){return l("table",{id:t,className:B,children:[a?e("caption",{children:a}):null,e("thead",{children:l("tr",{children:[e("th",{scope:"col",children:n??""}),i.map((t,l)=>e("th",{scope:"col",children:t.name??l+1},t.name??l))]})}),e("tbody",{children:s.map((t,a)=>l("tr",{children:[e("th",{scope:"row",children:m(t,c)}),i.map((t,l)=>{const n=r[l]?.[a];return e("td",void 0!==n?.label?{children:n.label}:{children:null==n?.value?"":o(n.value)},t.name??l)})]},a))})]})}function ChartSurface({legend:t,legendSide:a,children:s,table:i,className:r,...o}){return l(n,{...o,className:z("relative flex gap-3",_[a],r??void 0),children:[e("div",{className:"relative min-w-0 flex-1",children:s}),t,i]})}export function CartesianChart({series:t,categories:n,xAxis:u,yAxis:g,horizontal:b=!1,stacked:N=!1,includeZero:P=!0,bandRatio:A=1,inset:B=!1,headroom:T=0,markInset:_=0,xScale:F="band",marks:L,markRadius:$=24,table:I,swatch:R,scale:V,markTooltip:D,height:E,format:H,locale:X,label:Y,legend:Z,tooltip:K,empty:U,size:q,variant:G="ghost",padded:J=!1,className:O,children:Q,...ee}){const te=M(),le=q??te.size??"md",ae=X??te.locale,ne=a.useRef(null),se=useMeasuredWidth(ne),ie=S(),re=a.useId(),oe=useVisibility(t),[ce,de]=a.useState(null),[he,ue]=a.useState(null),[me,pe]=a.useState(null),fe=a.useCallback(e=>H?C(ae,H).format(e):d(e,ae),[H,ae]),xe=a.useMemo(()=>y(t),[t]),ge=a.useMemo(()=>t.map((e,t)=>x(e,t)),[t]),ve=r(t),be=a.useMemo(()=>Array.from({length:ve},(e,t)=>i(t,n,xe)),[ve,n,xe]),ye=xe.filter((e,t)=>oe.visible[t]),ke=h(ye,N),we="number"==typeof E?E:void 0===E?f[le]:null,Me=c[le],Ce=g,Ne=u,Se=V??w(ke,{min:Ce?.min,max:Ce?.max,tickCount:Ce?.tickCount,includeZero:P}),ze="value"===F?o(ye,n):null,Pe="value"===F?w(ze,{min:Ne?.min,max:Ne?.max,tickCount:Ne?.tickCount,includeZero:!1}):null,Ae=Se.ticks.map((e,t)=>Ce?.tickFormat?String(Ce.tickFormat(e,t)):fe(e)),je=Pe?Pe.ticks.map((e,t)=>Ne?.tickFormat?String(Ne.tickFormat(e,t)):d(e,ae)):be.map((e,t)=>Ne?.tickFormat?String(Ne.tickFormat(e,t)):m(e,ae)),Be=Ae.reduce((e,t)=>Math.max(e,v(t,Me)),0),Te=Me+6,We=Ce?.hidden?0:Be+10+(Ce?.label?Te:0),_e=(se-(b?0:We)-16)/Math.max(1,ve),Fe=Pe?je:b||_e-6>=2.4*Me?je.map(e=>k(e,b?150:_e-6,Me)):je,Le=Fe.reduce((e,t)=>Math.max(e,v(t,Me)),0),$e=b?Ne?.hidden?0:Le+10+(Ne?.label?Te:0):We,Ie=b?Ce?.hidden?0:Me+12+(Ce?.label?Te:0):Ne?.hidden?0:Me+12+(Ne?.label?Te:0),Re=(b?Ne:Ce)?.thickness??$e,Ve=(b?Ce:Ne)?.thickness??Ie,De=(b||Pe?12:Math.max(8,Fe.length?Le/2:8))+_,Ee=p[le]+4+T+_,He=we??0,Xe={left:Re+_,top:Ee,width:Math.max(0,se-Re-_-De),height:Math.max(0,He-Ee-Ve-_)},Ye=b?Xe.height:Xe.width,Ze=s(B?Math.max(1,ve-1):ve,Ye,A),Ke=a.useCallback(e=>B?ve<=1?Ye/2:Ye*e/(ve-1):Ze.centre(e),[B,ve,Ye,Ze]),Ue=a.useCallback(e=>b?Xe.left+Se.fraction(e)*Xe.width:Xe.top+(1-Se.fraction(e))*Xe.height,[b,Xe.left,Xe.top,Xe.width,Xe.height,Se]),qe=a.useCallback((e,t)=>b?{x:Ue(t),y:Xe.top+Ke(e)}:{x:Xe.left+Ke(e),y:Ue(t)},[b,Ue,Ke,Xe.left,Xe.top]),Ge=a.useCallback(e=>b?Xe.top+(1-(Pe?.fraction(e)??0))*Xe.height:Xe.left+(Pe?.fraction(e)??0)*Xe.width,[b,Xe.left,Xe.top,Xe.width,Xe.height,Pe]),Je=Ue(Math.min(Math.max(0,Se.min),Se.max)),Oe={plot:Xe,values:xe,visible:oe.visible,colors:ge,scale:Se,band:Ze,horizontal:b,valuePx:Ue,categoryPx:Ke,point:qe,categoryScale:Pe,categoryValuePx:Ge,zeroPx:Je,categories:be,format:fe,size:le},Qe=L?L(Oe):W,et=!1===K?{mode:"none"}:!0===K||void 0===K?{}:K,tt=et.mode??(L?"item":"index"),lt=null===he?null:Qe[he]??null,at=L?lt?lt.index:null:ce,nt=L?Qe.length:ve,clearActive=()=>{de(null),ue(null),pe(null)},goTo=e=>{const t=null===e?null:Math.min(nt-1,Math.max(0,e));L?ue(t):de(t)},step=e=>{pe(null),goTo(((L?he:ce)??(e>0?-1:nt))+e)},st=null===at?[]:t.flatMap((e,t)=>{if(!oe.visible[t]||lt&<.series!==t)return[];const l=xe[t]?.[at];return l&&null!==l.value?[{seriesIndex:t,name:e.name,color:l.color??ge[t],value:l.value,formatted:fe(l.value),label:l.label}]:[]}),it=lt&&D?D(lt):null,rt=it?it.items:"item"===tt&&st.length>1&&null!==me?[st.reduce((e,t)=>Math.abs(Ue(t.value??0)-me)<Math.abs(Ue(e.value??0)-me)?t:e)]:st,ot=lt?xe[lt.series]?.[lt.index]?.x??n?.[lt.index]??lt.index:void 0,ct=lt?lt.x:b?Ue(rt[0]?.value??0):Xe.left+Ke(at??0),dt=lt?lt.y:b?Xe.top+Ke(at??0):Xe.top,ht=lt?(lt.x-Xe.left)/Math.max(1,Xe.width)>.6:(b?Se.fraction(rt[0]?.value??0):Ke(at??0)/Math.max(1,Ye))>.6,ut=!1===Z?{interactive:!1}:!0===Z||void 0===Z?{}:Z,mt=!0===Z||!1!==Z&&t.length>1,pt=ut.side??"bottom",ft={...Oe,hovered:oe.hovered,activeIndex:at,marks:Qe,activeMark:lt},xt=0===ve||null===ke||"value"===F&&null===ze;return l(ChartSurface,{...ee,size:le,variant:G,padded:J,className:O,legendSide:pt,legend:mt?e(ChartLegendBar,{series:t,colors:ge,options:ut,visibility:oe,size:le,swatch:R,values:ut.showValue&&null!==at?t.map((e,t)=>{const l=xe[t]?.[at]?.value;return null==l?void 0:fe(l)}):void 0}):null,table:xt?null:I?.(re)??e(ChartDataTable,{id:re,caption:Y,corner:Ne?.label,categories:be,series:t,values:xe,format:fe,locale:ae}),children:[l("div",{ref:ne,role:"img",tabIndex:xt?void 0:0,"aria-label":Y??ie.chart,"aria-describedby":xt?void 0:re,onPointerMove:e=>{"none"!==tt&&(L?ue(((e,t)=>{const l=ne.current;if(!l||0===Qe.length)return null;const a=l.getBoundingClientRect(),n=e-a.left,s=t-a.top;let i=null,r=1/0,o=1/0;return Qe.forEach((e,t)=>{const l=Math.hypot(e.x-n,e.y-s),a=void 0===e.rx?Math.max(0,l-e.r):Math.hypot(Math.max(0,Math.abs(e.x-n)-e.rx),Math.max(0,Math.abs(e.y-s)-(e.ry??e.rx)));a<=$&&(a<r||a===r&&l<o)&&(r=a,o=l,i=t)}),i})(e.clientX,e.clientY)):de(((e,t)=>{const l=ne.current;if(!l||0===ve)return null;const a=l.getBoundingClientRect(),n=b?t-a.top-Xe.top:e-a.left-Xe.left;if(n<-Ze.step||n>Ye+Ze.step)return null;const s=B?ve<=1?0:Math.round(n/Ye*(ve-1)):Math.floor(n/Ze.step);return Math.min(ve-1,Math.max(0,s))})(e.clientX,e.clientY)),"item"===tt&&pe(((e,t)=>{const l=ne.current;if(!l)return null;const a=l.getBoundingClientRect();return b?e-a.left:t-a.top})(e.clientX,e.clientY)))},onPointerLeave:clearActive,onKeyDown:"none"===tt?void 0:e=>{const t=b?"ArrowDown":"ArrowRight",l=b?"ArrowUp":"ArrowLeft";if(e.key===t)step(1);else if(e.key===l)step(-1);else if("Home"===e.key)goTo(0);else if("End"===e.key)goTo(nt-1);else{if("Escape"!==e.key)return;clearActive()}e.preventDefault()},onBlur:clearActive,className:z("relative w-full","rounded-(--plass-radius-xs)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-2"),style:{height:we??E},children:[xt?e("div",{className:z("flex h-full items-center justify-center text-(--plass-muted-fg)",j[le]),children:U??ie.empty}):se>0?l("svg",{width:se,height:He||"100%",viewBox:`0 0 ${se} ${He}`,"aria-hidden":"true",className:"block overflow-visible",children:[e(ChartAxes,{plot:Xe,scale:Se,band:Ze,horizontal:b,inset:B,categoryPx:Ke,valuePx:Ue,tickTexts:Ae,categoryTexts:Fe,categoryScale:Pe,categoryValuePx:Ge,valueAxis:Ce,categoryAxis:Ne,fontSize:Me,zeroPx:Je}),null===at||L||"index"!==tt||!1===et.crosshair?null:(()=>{const t=Ke(at);return e("line",b?{x1:Xe.left,x2:Xe.left+Xe.width,y1:Xe.top+t,y2:Xe.top+t,stroke:"var(--plass-chart-baseline)",strokeWidth:1}:{x1:Xe.left+t,x2:Xe.left+t,y1:Xe.top,y2:Xe.top+Xe.height,stroke:"var(--plass-chart-baseline)",strokeWidth:1})})(),Q(ft)]}):null,null!==at&&rt.length>0&&"none"!==tt?et.render?e("div",{className:"pointer-events-none absolute z-10",style:ht?{right:`calc(100% - ${ct}px + 10px)`,top:dt}:{left:ct+10,top:dt},children:et.render({index:at,category:ot??be[at],items:rt})}):e(ChartTooltipPanel,{heading:it?it.heading:m(ot??be[at],ae),items:rt,x:ct,y:dt,flip:ht,size:le}):null]}),"none"===tt?null:e(ChartStatus,{heading:null===at?void 0:it?.heading??m(ot??be[at],ae),items:rt})]})}function ChartAxes({plot:a,scale:n,horizontal:s,categoryPx:i,valuePx:r,tickTexts:o,categoryTexts:c,categoryScale:d,categoryValuePx:h,valueAxis:m,categoryAxis:p,fontSize:f,zeroPx:x}){const y=!1!==m?.grid&&!m?.hidden,k=!p?.hidden&&(p?.grid??null!==d),categoryAlong=e=>d?h(d.ticks[e]):(s?a.top:a.left)+i(e),w=b(c.length,s?a.height:a.width,s?1.8*f:Math.max(...c.map(e=>v(e,f)),1)+12),M=b(n.ticks.length,s?a.width:a.height,s?Math.max(...o.map(e=>v(e,f)),1)+16:2*f),C=c.length>1?Math.abs(categoryAlong(1)-categoryAlong(0)):a.width,N=n.ticks.length>1?Math.abs(r(n.ticks[1])-r(n.ticks[0])):a.height,S=u(c.length,w,C,s?1.8*f:v(c[c.length-1]??"",f)),z=u(n.ticks.length,M,N,s?v(o[o.length-1]??"",f):1.6*f);return l("g",{children:[n.ticks.map((t,i)=>{const c=r(t),d=Math.abs(t)<1e-9;return l("g",{children:[y?e("line",s?{x1:c,x2:c,y1:a.top,y2:a.top+a.height,stroke:d?"var(--plass-chart-baseline)":"var(--plass-chart-grid)",strokeWidth:1}:{x1:a.left,x2:a.left+a.width,y1:c,y2:c,stroke:d?"var(--plass-chart-baseline)":"var(--plass-chart-grid)",strokeWidth:1}):null,m?.hidden||!g(i,n.ticks.length,M,z)?null:e("text",s?{x:c,y:a.top+a.height+f+6,textAnchor:0===i?"start":i===n.ticks.length-1?"end":"middle",fontSize:f,fill:"var(--plass-muted-fg)",className:"tabular-nums",children:o[i]}:{x:a.left-8,y:c,textAnchor:"end",dominantBaseline:"central",fontSize:f,fill:"var(--plass-muted-fg)",className:"tabular-nums",children:o[i]})]},t)}),p?.hidden?null:l(t,{children:[e("line",s?{x1:x,x2:x,y1:a.top,y2:a.top+a.height,stroke:"var(--plass-chart-axis)",strokeWidth:1}:{x1:a.left,x2:a.left+a.width,y1:x,y2:x,stroke:"var(--plass-chart-axis)",strokeWidth:1}),c.map((t,n)=>{const i=categoryAlong(n),r=g(n,c.length,w,S);return s?r?e("text",{x:a.left-8,y:i,textAnchor:"end",dominantBaseline:"central",fontSize:f,fill:"var(--plass-muted-fg)",className:d?"tabular-nums":void 0,children:t},n):null:l("g",{children:[k?e("line",{x1:i,x2:i,y1:a.top,y2:a.top+a.height,stroke:"var(--plass-chart-grid)",strokeWidth:1}):null,r?e("text",{x:i,y:a.top+a.height+f+6,textAnchor:d?0===n?"start":n===c.length-1?"end":"middle":"middle",fontSize:f,fill:"var(--plass-muted-fg)",className:d?"tabular-nums":void 0,children:t}):null]},n)})]}),m?.label?e("text",{x:s?a.left+a.width:a.left,y:s?a.top+a.height+2*f+12:a.top-8,textAnchor:s?"end":"start",fontSize:f,fill:"var(--plass-muted-fg)",fontWeight:500,children:m.label}):null,p?.label&&!s?e("text",{x:a.left+a.width,y:a.top+a.height+2*f+12,textAnchor:"end",fontSize:f,fill:"var(--plass-muted-fg)",fontWeight:500,children:p.label}):null]})}export{ChartDataTable,ChartLegendBar,ChartScaleLegend,ChartStatus,ChartSurface,ChartTooltipPanel,useMeasuredWidth,useVisibility};
|
|
1
|
+
"use client";import{jsx as e,Fragment as t,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{PlBox as n}from"../components/box/PlBox.js";import{bandScale as s,categoryAt as i,categoryCount as r,categoriesAreDates as o,categoryExtent as c,chartFontSizes as d,compactNumber as u,extentOf as h,fitCategoryLabels as m,fitsLast as p,formatCategory as f,formatTimeTicks as x,markerRadii as g,plotHeights as v,seriesColor as b,showsTick as y,textWidth as k,tickStride as w,toValues as M,timeScale as C,valueScale as N,writeChartValue as S}from"./chart.js";import{useDefaults as z}from"./defaults.js";import{usePlElementSize as P}from"../hooks/usePlElementSize.js";import{useLabels as A}from"./labels.js";import{cx as j,glassClasses as B,hasContent as W,metaTextClasses as _,srOnlyClasses as T,transitionClasses as L}from"./styles.js";const $=[];function useMeasuredWidth(e){return P(e)?.width??0}export const markTransitionClasses=["[transition:opacity_var(--plass-duration)_var(--plass-ease),","r_var(--plass-duration)_var(--plass-ease),","scale_var(--plass-duration)_var(--plass-ease)]"].join("");function useVisibility(e){const[t,l]=a.useState(()=>{const t=new Set;return e.forEach((e,l)=>{e.hidden&&t.add(l)}),t}),[n,s]=a.useState(null),i=a.useCallback(e=>{l(t=>{const l=new Set(t);return l.has(e)?l.delete(e):l.add(e),l})},[]);return{visible:e.map((e,l)=>!t.has(l)),hovered:n,toggle:i,setHovered:s}}const I={top:"flex-col-reverse",bottom:"flex-col",left:"flex-row-reverse rtl:flex-row",right:"flex-row rtl:flex-row-reverse"},R={start:"justify-start",center:"justify-center",end:"justify-end"};function ChartLegendBar({series:a,colors:n,options:s,visibility:i,size:r,values:o,swatch:c}){const d=!1!==s.interactive,u="left"===s.side||"right"===s.side;return e("ul",{className:j("flex list-none flex-wrap items-center gap-x-3 gap-y-1 p-0",u?"min-w-0 flex-col items-start":"",R[s.align??"center"],_[r]),children:a.map((a,s)=>{const r=i.visible[s],u=null!==i.hovered&&i.hovered!==s,h=a.name??`${s+1}`,m=r?n[s]:`color-mix(in oklab, ${n[s]} 40%, transparent)`,p=l(t,{children:[e("span",c?{"aria-hidden":"true",className:"flex size-2.5 shrink-0 items-center justify-center",children:c(s,m)}:{"aria-hidden":"true",className:`size-2.5 shrink-0 rounded-[0.1875rem] ${L}`,style:{backgroundColor:m}}),e("span",{className:"min-w-0 truncate",children:h}),o?.[s]?e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:o[s]}):null]});return e("li",{className:"min-w-0",children:d?e("button",{type:"button","aria-pressed":r,onClick:()=>i.toggle(s),onPointerEnter:()=>i.setHovered(s),onPointerLeave:()=>i.setHovered(null),onFocus:()=>i.setHovered(s),onBlur:()=>i.setHovered(null),className:j("flex min-w-0 cursor-pointer items-center gap-1.5 rounded-(--plass-radius-xs)","px-1 py-0.5 text-(--plass-fg)","[transition-property:background-color,color,opacity]","[transition-duration:var(--plass-duration)]","[transition-timing-function:var(--plass-ease)]","hover:bg-(--p-soft)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-1",r?"":"text-(--plass-muted-fg) line-through",u?"opacity-55":""),children:p}):e("span",{className:j("flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-(--plass-fg)",r?"":"text-(--plass-muted-fg) line-through"),children:p})},a.name??s)})})}function ChartScaleLegend({steps:a,from:n,to:s,middle:i,align:r,vertical:o,size:c}){return e("div",{className:j("flex",o?"":R[r]),children:l("div",{className:j("grid grid-cols-[auto_auto_auto] items-center gap-x-2",_[c]),children:[e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:n}),e("span",{"aria-hidden":"true",className:j("flex h-2.5 overflow-hidden rounded-[0.1875rem]",o?"w-20":"w-24"),children:a.map(t=>e("span",{className:"h-full flex-1",style:{backgroundColor:t}},t))}),e("span",{className:"shrink-0 tabular-nums text-(--plass-muted-fg)",children:s}),i?l(t,{children:[e("span",{}),e("span",{className:"text-center tabular-nums text-(--plass-muted-fg)",children:i}),e("span",{})]}):null]})})}function ChartTooltipPanel({heading:t,items:a,x:n,y:s,flip:i,size:r}){return l("div",{"data-plass-tooltip":"",className:j("pointer-events-none absolute z-10 max-w-56 min-w-24","rounded-(--plass-radius-sm) border p-2",B,"bg-(--plass-glass-press) [border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]",_[r]),style:i?{right:`calc(100% - ${n}px + 10px)`,top:s}:{left:n+10,top:s},children:[e("div",{className:"mb-1 font-medium text-(--plass-fg)",children:t}),e("ul",{className:"flex list-none flex-col gap-0.5 p-0",children:a.map(t=>l("li",{className:"flex items-center gap-1.5",children:[e("span",{"aria-hidden":"true",className:"size-2 shrink-0 rounded-[0.125rem]",style:{backgroundColor:t.color}}),t.name?e("span",{className:"min-w-0 flex-1 truncate text-(--plass-muted-fg)",children:t.name}):null,e("span",{className:"ms-auto shrink-0 font-medium tabular-nums text-(--plass-fg)",children:t.label??t.formatted})]},t.seriesIndex))})]})}function ChartStatus({heading:n,items:s}){return e("span",{role:"status","aria-live":"polite",className:T,children:0===s.length?null:l(t,{children:[W(n)?l(t,{children:[n,", "]}):null,s.map((e,t)=>l(a.Fragment,{children:[t>0?", ":null,e.name?`${e.name}: `:null,e.label??e.formatted]},e.seriesIndex))]})})}const V=/* @__PURE__ */a.memo(function ChartDataTable({id:t,caption:a,corner:n,categories:s,series:i,values:r,format:o,locale:c}){return l("table",{id:t,className:T,children:[a?e("caption",{children:a}):null,e("thead",{children:l("tr",{children:[e("th",{scope:"col",children:n??""}),i.map((t,l)=>e("th",{scope:"col",children:t.name??l+1},t.name??l))]})}),e("tbody",{children:s.map((t,a)=>l("tr",{children:[e("th",{scope:"row",children:f(t,c)}),i.map((t,l)=>{const n=r[l]?.[a];return e("td",void 0!==n?.label?{children:n.label}:{children:null==n?.value?"":o(n.value)},t.name??l)})]},a))})]})});function ChartSurface({legend:t,legendSide:a,children:s,table:i,className:r,...o}){return l(n,{...o,className:j("relative flex gap-3",I[a],r??void 0),children:[e("div",{className:"relative min-w-0 flex-1",children:s}),t,i]})}export function CartesianChart({series:t,categories:n,xAxis:p,yAxis:y,horizontal:w=!1,stacked:P=!1,includeZero:B=!0,bandRatio:W=1,inset:T=!1,headroom:L=0,markInset:I=0,xScale:R="band",marks:E,markRadius:F=24,table:H,swatch:D,scale:X,markTooltip:Y,height:Z,format:K,locale:U,label:q,legend:G,tooltip:J,empty:O,size:Q,variant:ee="ghost",padded:te=!1,className:le,children:ae,...ne}){const se=z(),ie=Q??se.size??"md",re=U??se.locale,oe=a.useRef(null),ce=useMeasuredWidth(oe),de=A(),ue=a.useId(),he=useVisibility(t),[me,pe]=a.useState(null),[fe,xe]=a.useState(null),[ge,ve]=a.useState(null),be=a.useCallback(e=>S(e,K,re),[K,re]),ye=a.useMemo(()=>M(t),[t]),ke=a.useMemo(()=>t.map((e,t)=>b(e,t)),[t]),we=r(t),Me=a.useMemo(()=>Array.from({length:we},(e,t)=>i(t,n,ye)),[we,n,ye]),Ce=ye.filter((e,t)=>he.visible[t]),Ne=h(Ce,P),Se="number"==typeof Z?Z:void 0===Z?v[ie]:null,ze=d[ie],Pe=y,Ae=p,je=X??N(Ne,{min:Pe?.min,max:Pe?.max,tickCount:Pe?.tickCount,includeZero:B}),Be="value"===R?c(Ce,n):null,We="value"===R&&o(ye,n),_e="value"!==R?null:We?C(Be,{min:Ae?.min,max:Ae?.max,tickCount:Ae?.tickCount}):N(Be,{min:Ae?.min,max:Ae?.max,tickCount:Ae?.tickCount,includeZero:!1}),Te=_e&&"unit"in _e?x(_e.ticks,_e.unit,re):null,Le=je.ticks.map((e,t)=>Pe?.tickFormat?String(Pe.tickFormat(e,t)):be(e)),$e=Ae?.tickFormat,Ie=a.useMemo(()=>Me.map((e,t)=>$e?String($e(e,t)):f(e,re)),[Me,$e,re]),Re=_e?_e.ticks.map((e,t)=>$e?String($e(We?new Date(e):e,t)):Te?.[t]??u(e,re)):Ie,Ve=Le.reduce((e,t)=>Math.max(e,k(t,ze)),0),Ee=ze+6,Fe=Pe?.hidden?0:Ve+10+(Pe?.label?Ee:0),He=(ce-(w?0:Fe)-16)/Math.max(1,we),De=null!==_e,Xe=a.useMemo(()=>m(Re,{horizontal:w,slot:He,fontSize:ze,ticks:De}),[Re,w,He,ze,De]),Ye=a.useMemo(()=>Xe.reduce((e,t)=>Math.max(e,k(t,ze)),0),[Xe,ze]),Ze=w?Ae?.hidden?0:Ye+10+(Ae?.label?Ee:0):Fe,Ke=w?Pe?.hidden?0:ze+12+(Pe?.label?Ee:0):Ae?.hidden?0:ze+12+(Ae?.label?Ee:0),Ue=(w?Ae:Pe)?.thickness??Ze,qe=(w?Pe:Ae)?.thickness??Ke,Ge=(w||_e?12:Math.max(8,Xe.length?Ye/2:8))+I,Je=g[ie]+4+L+I,Oe=Se??0,Qe={left:Ue+I,top:Je,width:Math.max(0,ce-Ue-I-Ge),height:Math.max(0,Oe-Je-qe-I)},et=w?Qe.height:Qe.width,tt=s(T?Math.max(1,we-1):we,et,W),lt=a.useCallback(e=>T?we<=1?et/2:et*e/(we-1):tt.centre(e),[T,we,et,tt]),at=a.useCallback(e=>w?Qe.left+je.fraction(e)*Qe.width:Qe.top+(1-je.fraction(e))*Qe.height,[w,Qe.left,Qe.top,Qe.width,Qe.height,je]),nt=a.useCallback((e,t)=>w?{x:at(t),y:Qe.top+lt(e)}:{x:Qe.left+lt(e),y:at(t)},[w,at,lt,Qe.left,Qe.top]),st=a.useCallback(e=>w?Qe.top+(1-(_e?.fraction(e)??0))*Qe.height:Qe.left+(_e?.fraction(e)??0)*Qe.width,[w,Qe.left,Qe.top,Qe.width,Qe.height,_e]),it=at(Math.min(Math.max(0,je.min),je.max)),rt={plot:Qe,values:ye,visible:he.visible,colors:ke,scale:je,band:tt,horizontal:w,valuePx:at,categoryPx:lt,point:nt,categoryScale:_e,categoryValuePx:st,zeroPx:it,categories:Me,format:be,size:ie},ot=E?E(rt):$,ct=!1===J?{mode:"none"}:!0===J||void 0===J?{}:J,dt=ct.mode??(E?"item":"index"),ut=null===fe?null:ot[fe]??null,ht=E?ut?ut.index:null:me,mt=E?ot.length:we,clearActive=()=>{pe(null),xe(null),ve(null)},goTo=e=>{const t=null===e?null:Math.min(mt-1,Math.max(0,e));E?xe(t):pe(t)},step=e=>{ve(null),goTo(((E?fe:me)??(e>0?-1:mt))+e)},pt=null===ht?[]:t.flatMap((e,t)=>{if(!he.visible[t]||ut&&ut.series!==t)return[];const l=ye[t]?.[ht];return l&&null!==l.value?[{seriesIndex:t,name:e.name,color:l.color??ke[t],value:l.value,formatted:be(l.value),label:l.label}]:[]}),ft=ut&&Y?Y(ut):null,xt=ft?ft.items:"item"===dt&&pt.length>1&&null!==ge?[pt.reduce((e,t)=>Math.abs(at(t.value??0)-ge)<Math.abs(at(e.value??0)-ge)?t:e)]:pt,gt=ut?ye[ut.series]?.[ut.index]?.x??n?.[ut.index]??ut.index:void 0,vt=ut?ut.x:w?at(xt[0]?.value??0):Qe.left+lt(ht??0),bt=ut?ut.y:w?Qe.top+lt(ht??0):Qe.top,yt=ut?(ut.x-Qe.left)/Math.max(1,Qe.width)>.6:(w?je.fraction(xt[0]?.value??0):lt(ht??0)/Math.max(1,et))>.6,kt=!1===G?{interactive:!1}:!0===G||void 0===G?{}:G,wt=!0===G||!1!==G&&t.length>1,Mt=kt.side??"bottom",Ct={...rt,hovered:he.hovered,activeIndex:ht,marks:ot,activeMark:ut},Nt=0===we||null===Ne||"value"===R&&null===Be;return l(ChartSurface,{...ne,size:ie,variant:ee,padded:te,className:le,legendSide:Mt,legend:wt?e(ChartLegendBar,{series:t,colors:ke,options:kt,visibility:he,size:ie,swatch:D,values:kt.showValue&&null!==ht?t.map((e,t)=>{const l=ye[t]?.[ht]?.value;return null==l?void 0:be(l)}):void 0}):null,table:Nt?null:H?.(ue)??e(V,{id:ue,caption:q,corner:Ae?.label,categories:Me,series:t,values:ye,format:be,locale:re}),children:[l("div",{ref:oe,role:"img",tabIndex:Nt?void 0:0,"aria-label":q??de.chart,"aria-describedby":Nt?void 0:ue,onPointerMove:e=>{"none"!==dt&&(E?xe(((e,t)=>{const l=oe.current;if(!l||0===ot.length)return null;const a=l.getBoundingClientRect(),n=e-a.left,s=t-a.top;let i=null,r=1/0,o=1/0;return ot.forEach((e,t)=>{const l=Math.hypot(e.x-n,e.y-s),a=void 0===e.rx?Math.max(0,l-e.r):Math.hypot(Math.max(0,Math.abs(e.x-n)-e.rx),Math.max(0,Math.abs(e.y-s)-(e.ry??e.rx)));a<=F&&(a<r||a===r&&l<o)&&(r=a,o=l,i=t)}),i})(e.clientX,e.clientY)):pe(((e,t)=>{const l=oe.current;if(!l||0===we)return null;const a=l.getBoundingClientRect(),n=w?t-a.top-Qe.top:e-a.left-Qe.left;if(n<-tt.step||n>et+tt.step)return null;const s=T?we<=1?0:Math.round(n/et*(we-1)):Math.floor(n/tt.step);return Math.min(we-1,Math.max(0,s))})(e.clientX,e.clientY)),"item"!==dt||E||ve(((e,t)=>{const l=oe.current;if(!l)return null;const a=l.getBoundingClientRect();return w?e-a.left:t-a.top})(e.clientX,e.clientY)))},onPointerLeave:clearActive,onKeyDown:"none"===dt?void 0:e=>{const t=w?"ArrowDown":"ArrowRight",l=w?"ArrowUp":"ArrowLeft";if(e.key===t)step(1);else if(e.key===l)step(-1);else if("Home"===e.key)goTo(0);else if("End"===e.key)goTo(mt-1);else{if("Escape"!==e.key)return;clearActive()}e.preventDefault()},onBlur:clearActive,className:j("relative w-full","rounded-(--plass-radius-xs)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-2"),style:{height:Se??Z},children:[Nt?e("div",{className:j("flex h-full items-center justify-center text-(--plass-muted-fg)",_[ie]),children:O??de.empty}):ce>0?l("svg",{width:ce,height:Oe||"100%",viewBox:`0 0 ${ce} ${Oe}`,"aria-hidden":"true",className:"block overflow-visible",children:[e(ChartAxes,{plot:Qe,scale:je,band:tt,horizontal:w,inset:T,categoryPx:lt,valuePx:at,tickTexts:Le,categoryTexts:Xe,categoryScale:_e,categoryValuePx:st,valueAxis:Pe,categoryAxis:Ae,fontSize:ze,zeroPx:it}),null===ht||E||"index"!==dt||!1===ct.crosshair?null:(()=>{const t=lt(ht);return e("line",w?{x1:Qe.left,x2:Qe.left+Qe.width,y1:Qe.top+t,y2:Qe.top+t,stroke:"var(--plass-chart-baseline)",strokeWidth:1}:{x1:Qe.left+t,x2:Qe.left+t,y1:Qe.top,y2:Qe.top+Qe.height,stroke:"var(--plass-chart-baseline)",strokeWidth:1})})(),ae(Ct)]}):null,null!==ht&&xt.length>0&&"none"!==dt?ct.render?e("div",{className:"pointer-events-none absolute z-10",style:yt?{right:`calc(100% - ${vt}px + 10px)`,top:bt}:{left:vt+10,top:bt},children:ct.render({index:ht,category:gt??Me[ht],items:xt})}):e(ChartTooltipPanel,{heading:ft?ft.heading:f(gt??Me[ht],re),items:xt,x:vt,y:bt,flip:yt,size:ie}):null]}),"none"===dt?null:e(ChartStatus,{heading:null===ht?void 0:ft?.heading??f(gt??Me[ht],re),items:xt})]})}function ChartAxes({plot:a,scale:n,horizontal:s,categoryPx:i,valuePx:r,tickTexts:o,categoryTexts:c,categoryScale:d,categoryValuePx:u,valueAxis:h,categoryAxis:m,fontSize:f,zeroPx:x}){const g=!1!==h?.grid&&!h?.hidden,v=!m?.hidden&&(m?.grid??null!==d),categoryAlong=e=>d?u(d.ticks[e]):(s?a.top:a.left)+i(e),b=w(c.length,s?a.height:a.width,s?1.8*f:Math.max(...c.map(e=>k(e,f)),1)+12),M=w(n.ticks.length,s?a.width:a.height,s?Math.max(...o.map(e=>k(e,f)),1)+16:2*f),C=c.length>1?Math.abs(categoryAlong(1)-categoryAlong(0)):a.width,N=n.ticks.length>1?Math.abs(r(n.ticks[1])-r(n.ticks[0])):a.height,S=p(c.length,b,C,s?1.8*f:k(c[c.length-1]??"",f)),z=p(n.ticks.length,M,N,s?k(o[o.length-1]??"",f):1.6*f);return l("g",{children:[n.ticks.map((t,i)=>{const c=r(t),d=Math.abs(t)<1e-9;return l("g",{children:[g?e("line",s?{x1:c,x2:c,y1:a.top,y2:a.top+a.height,stroke:d?"var(--plass-chart-baseline)":"var(--plass-chart-grid)",strokeWidth:1}:{x1:a.left,x2:a.left+a.width,y1:c,y2:c,stroke:d?"var(--plass-chart-baseline)":"var(--plass-chart-grid)",strokeWidth:1}):null,h?.hidden||!y(i,n.ticks.length,M,z)?null:e("text",s?{x:c,y:a.top+a.height+f+6,textAnchor:0===i?"start":i===n.ticks.length-1?"end":"middle",fontSize:f,fill:"var(--plass-muted-fg)",className:"tabular-nums",children:o[i]}:{x:a.left-8,y:c,textAnchor:"end",dominantBaseline:"central",fontSize:f,fill:"var(--plass-muted-fg)",className:"tabular-nums",children:o[i]})]},t)}),m?.hidden?null:l(t,{children:[e("line",s?{x1:x,x2:x,y1:a.top,y2:a.top+a.height,stroke:"var(--plass-chart-axis)",strokeWidth:1}:{x1:a.left,x2:a.left+a.width,y1:x,y2:x,stroke:"var(--plass-chart-axis)",strokeWidth:1}),c.map((t,n)=>{const i=categoryAlong(n),r=y(n,c.length,b,S);return r||!s&&v?s?e("text",{x:a.left-8,y:i,textAnchor:"end",dominantBaseline:"central",fontSize:f,fill:"var(--plass-muted-fg)",className:d?"tabular-nums":void 0,children:t},n):l("g",{children:[v?e("line",{x1:i,x2:i,y1:a.top,y2:a.top+a.height,stroke:"var(--plass-chart-grid)",strokeWidth:1}):null,r?e("text",{x:i,y:a.top+a.height+f+6,textAnchor:d?0===n?"start":n===c.length-1?"end":"middle":"middle",fontSize:f,fill:"var(--plass-muted-fg)",className:d?"tabular-nums":void 0,children:t}):null]},n):null})]}),h?.label?e("text",{x:s?a.left+a.width:a.left,y:s?a.top+a.height+2*f+12:a.top-8,textAnchor:s?"end":"start",fontSize:f,fill:"var(--plass-muted-fg)",fontWeight:500,children:h.label}):null,m?.label&&!s?e("text",{x:a.left+a.width,y:a.top+a.height+2*f+12,textAnchor:"end",fontSize:f,fill:"var(--plass-muted-fg)",fontWeight:500,children:m.label}):null]})}export{V as ChartDataTable,ChartLegendBar,ChartScaleLegend,ChartStatus,ChartSurface,ChartTooltipPanel,useMeasuredWidth,useVisibility};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as l,jsxs as e}from"react/jsx-runtime";import{areaPath as
|
|
1
|
+
import{jsx as l,jsxs as e}from"react/jsx-runtime";import{areaPath as r,chartFontSizes as t,dimmedByHover as o,labelledPoints as n,linePath as a,lineWidths as s,markerRadii as i,markGap as c}from"./chart.js";import{markTransitionClasses as u}from"./chart-frame.js";export function LineSeries({context:f,curve:p,filled:d,stacked:m,markers:x,valueLabels:h,connectNulls:k,gradient:v,idPrefix:$}){const{values:y,visible:b,colors:g,hovered:j,activeIndex:C,plot:L,point:N,zeroPx:W,size:z,format:B}=f,E=s[z],G=i[z],P=b.indexOf(!0),S=[],w=[];return y.forEach((l,e)=>{const r=l.map((l,e)=>w[e]??0);S.push(r),m&&b[e]&&l.forEach((l,e)=>{w[e]=(w[e]??0)+(l.value??0)})}),e("g",{children:[e("defs",{children:[v?g.map((r,t)=>e("linearGradient",{id:`${$}-stroke-${t}`,x1:"0",y1:"0",x2:"1",y2:"0",children:[l("stop",{offset:"0%",stopColor:`color-mix(in oklab, ${r} 45%, transparent)`}),l("stop",{offset:"100%",stopColor:r})]},`stroke-${t}`)):null,d&&!m?g.map((r,t)=>e("linearGradient",{id:`${$}-fill-${t}`,x1:"0",y1:"0",x2:"0",y2:"1",children:[l("stop",{offset:"0%",stopColor:`color-mix(in oklab, ${r} 28%, transparent)`}),l("stop",{offset:"100%",stopColor:`color-mix(in oklab, ${r} 2%, transparent)`})]},`fill-${t}`)):null]}),y.map((s,i)=>{if(!b[i])return null;const f=g[i],y=o(j,i,b),w=s.map((l,e)=>{if(null===l.value)return null;const r=m?S[i][e]+l.value:l.value;return N(e,r)}),A=k?w.filter(Boolean):w,I=s.map((l,e)=>null===l.value?null:m?N(e,S[i][e]):{x:N(e,l.value).x,y:W}),O=d&&m,q=n(s,h);return e("g",{opacity:y?.28:1,className:u,children:[d?l("path",{d:r(A,k?I.filter(Boolean):I,p),fill:m?`color-mix(in oklab, ${f} 70%, transparent)`:`url(#${$}-fill-${i})`,stroke:"none"}):null,O&&i!==P?l("path",{d:a(k?I.filter(Boolean):I,p),fill:"none",stroke:"var(--plass-chart-gap)",strokeWidth:c}):null,O?null:l("path",{d:a(A,p),fill:"none",stroke:v?`url(#${$}-stroke-${i})`:f,strokeWidth:E,strokeLinecap:"round",strokeLinejoin:"round"}),w.map((e,r)=>e&&("all"===x||"auto"===x&&s.length<=14||r===C)?l("circle",{cx:e.x,cy:e.y,r:r===C?G+1:G,fill:s[r].color??f,stroke:"var(--plass-chart-gap)",strokeWidth:c,className:u},r):null),"none"===h?null:w.map((e,r)=>{const o=s[r].value;return e&&null!==o&&q(r)?l("text",{x:e.x,y:e.y-G-5,textAnchor:e.x>L.left+L.width-24?"end":e.x<L.left+24?"start":"middle",fontSize:t[z],fontWeight:500,fill:"var(--plass-fg)",className:"tabular-nums",children:s[r].label??B(o)},`label-${r}`):null})]},i)})]})}
|
package/dist/internal/chart.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* makes.
|
|
17
17
|
*/
|
|
18
18
|
import type * as React from 'react';
|
|
19
|
-
import type { PlassChartCategory, PlassChartDatum, PlassChartSeries, PlassDensity, PlassSize } from '../types.js';
|
|
19
|
+
import type { PlassChartCategory, PlassChartDatum, PlassChartSeries, PlassChartValueLabels, PlassDensity, PlassSize } from '../types.js';
|
|
20
20
|
/**
|
|
21
21
|
* How tall a plot is when nobody said, in pixels.
|
|
22
22
|
*
|
|
@@ -92,6 +92,16 @@ export declare function resolveColor(value: string): string;
|
|
|
92
92
|
* "Other" series, or draw a second chart.
|
|
93
93
|
*/
|
|
94
94
|
export declare function seriesColor(series: Pick<PlassChartSeries, 'color'> | undefined, index: number, palette?: readonly string[]): string;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the mark of `index` fades while the legend entry of `hovered` is
|
|
97
|
+
* under the pointer.
|
|
98
|
+
*
|
|
99
|
+
* A hovered entry dims the *others* — but only when the series it names is
|
|
100
|
+
* actually on the plot. Pointing at an entry that is switched off would
|
|
101
|
+
* otherwise fade every visible series to make room for one that is not there,
|
|
102
|
+
* which reads as the whole chart going grey for no reason.
|
|
103
|
+
*/
|
|
104
|
+
export declare function dimmedByHover(hovered: number | null, index: number, visible: readonly boolean[]): boolean;
|
|
95
105
|
/** A datum unpacked into the shape the drawing code reads. */
|
|
96
106
|
export interface ChartValue {
|
|
97
107
|
value: number | null;
|
|
@@ -111,6 +121,32 @@ export interface ChartValue {
|
|
|
111
121
|
export declare function toValue(datum: PlassChartDatum): ChartValue;
|
|
112
122
|
/** Every series unpacked, in the order it was given. */
|
|
113
123
|
export declare function toValues(series: readonly PlassChartSeries[]): ChartValue[][];
|
|
124
|
+
/**
|
|
125
|
+
* Which points of a series get a value label, decided once for the whole
|
|
126
|
+
* series.
|
|
127
|
+
*
|
|
128
|
+
* Once and not per point, which is the only thing worth saying about it: asking
|
|
129
|
+
* "is this the series' high" inside the loop over the points means walking the
|
|
130
|
+
* series again for each of them, and a five-hundred-point line then does a
|
|
131
|
+
* quarter of a million comparisons to place two labels — on every render, which
|
|
132
|
+
* on a chart being hovered is every frame. `last` is the last point that is
|
|
133
|
+
* there rather than the last slot, so a series that ends in a gap still says
|
|
134
|
+
* where it got to.
|
|
135
|
+
*/
|
|
136
|
+
export declare function labelledPoints(one: readonly {
|
|
137
|
+
value: number | null;
|
|
138
|
+
}[], valueLabels: PlassChartValueLabels): (index: number) => boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Every category of a stacked chart renormalised to a hundred.
|
|
141
|
+
*
|
|
142
|
+
* A change to the data rather than to the drawing, which is what lets the axis,
|
|
143
|
+
* the tooltip and the table agree that the number drawn is a share. The number
|
|
144
|
+
* the caller passed survives as each point's `label`, written by `write` the way
|
|
145
|
+
* the chart writes every other value — a chart stacked to `full` that can only
|
|
146
|
+
* tell a reader percentages has thrown away what it was given, and one that
|
|
147
|
+
* writes a revenue as `4830` beside a `$` axis has thrown away how it was given.
|
|
148
|
+
*/
|
|
149
|
+
export declare function stackToFull(series: readonly PlassChartSeries[], write: (value: number) => string): PlassChartSeries[];
|
|
114
150
|
/**
|
|
115
151
|
* A category as a number, for a category axis that is really a value axis.
|
|
116
152
|
*
|
|
@@ -129,6 +165,13 @@ export declare function toNumber(value: PlassChartCategory | undefined): number
|
|
|
129
165
|
* x at every index and there is no column for them to share.
|
|
130
166
|
*/
|
|
131
167
|
export declare function pointX(value: ChartValue, index: number, categories: readonly PlassChartCategory[] | undefined): number | null;
|
|
168
|
+
/**
|
|
169
|
+
* Whether the positions along a chart's x axis are moments.
|
|
170
|
+
*
|
|
171
|
+
* Such an axis runs on milliseconds, and ticking milliseconds by 1-2-5 puts a
|
|
172
|
+
* `1.7T` under every mark. A dated axis ticks where a calendar does instead.
|
|
173
|
+
*/
|
|
174
|
+
export declare function categoriesAreDates(values: readonly ChartValue[][], categories: readonly PlassChartCategory[] | undefined): boolean;
|
|
132
175
|
/**
|
|
133
176
|
* The extent of the category values, for a chart whose x is a number.
|
|
134
177
|
*
|
|
@@ -232,8 +275,20 @@ export declare function timeScale(extent: {
|
|
|
232
275
|
max?: number;
|
|
233
276
|
tickCount?: number;
|
|
234
277
|
}): TimeScale;
|
|
235
|
-
/**
|
|
236
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Whether an axis stepping in hours, minutes or seconds runs over more than one
|
|
280
|
+
* calendar day, and so has to write the date beside each time.
|
|
281
|
+
*
|
|
282
|
+
* `09:00 – 17:00` on an axis two days long could be either day. An axis that
|
|
283
|
+
* ends exactly at midnight has not started the next day, so its last tick does
|
|
284
|
+
* not count on its own.
|
|
285
|
+
*/
|
|
286
|
+
export declare function timeNeedsDate(ticks: readonly number[], unit: TimeUnit): boolean;
|
|
287
|
+
/**
|
|
288
|
+
* One instant on a time axis, written unambiguously — for a tooltip or a table.
|
|
289
|
+
* `withDate` puts the date in front of a time, for an axis `timeNeedsDate`.
|
|
290
|
+
*/
|
|
291
|
+
export declare function formatTimeValue(value: number, unit: TimeUnit, locale?: string, withDate?: boolean): string;
|
|
237
292
|
/**
|
|
238
293
|
* A whole axis of ticks, written the way an axis is read.
|
|
239
294
|
*
|
|
@@ -248,6 +303,10 @@ export declare function formatTimeValue(value: number, unit: TimeUnit, locale?:
|
|
|
248
303
|
* one tick a stride never removes. An axis that crosses a year names it on
|
|
249
304
|
* every tick, so whichever ones survive are each unambiguous. Wider labels mean
|
|
250
305
|
* a heavier stride, and a heavier stride is the better failure.
|
|
306
|
+
*
|
|
307
|
+
* The date on an axis of hours follows the second rule for the same reason: an
|
|
308
|
+
* axis that crosses midnight writes it on every tick, since the midnight tick
|
|
309
|
+
* is as likely to be dropped as the one a year was riding on.
|
|
251
310
|
*/
|
|
252
311
|
export declare function formatTimeTicks(ticks: readonly number[], unit: TimeUnit, locale?: string): string[];
|
|
253
312
|
/**
|
|
@@ -305,6 +364,23 @@ export declare function textWidth(text: string, fontSize: number): number;
|
|
|
305
364
|
* both still have the whole thing.
|
|
306
365
|
*/
|
|
307
366
|
export declare function truncate(text: string, maxWidth: number, fontSize: number): string;
|
|
367
|
+
/**
|
|
368
|
+
* The category labels as the axis writes them.
|
|
369
|
+
*
|
|
370
|
+
* A long name is cut to its slot rather than labels being dropped until the
|
|
371
|
+
* rest fit: five categories called "Onboarding flow" would otherwise leave one
|
|
372
|
+
* label on the axis. Once a slot is narrower than about four characters a cut
|
|
373
|
+
* stops helping, and the axis thins its labels out by stride instead. The
|
|
374
|
+
* ticks of a value-scaled axis are numbers already rounded to be short, so they
|
|
375
|
+
* are never cut: half of `12.4K` is not a smaller number, it is a wrong one.
|
|
376
|
+
* The Dart build answers with `fitCategoryLabels`.
|
|
377
|
+
*/
|
|
378
|
+
export declare function fitCategoryLabels(texts: string[], options: {
|
|
379
|
+
horizontal: boolean;
|
|
380
|
+
slot: number;
|
|
381
|
+
fontSize: number;
|
|
382
|
+
ticks: boolean;
|
|
383
|
+
}): string[];
|
|
308
384
|
/** The plot's box inside the chart, once the axes have taken their bands. */
|
|
309
385
|
export interface PlotBox {
|
|
310
386
|
left: number;
|
|
@@ -471,3 +547,5 @@ export declare function formatCategory(value: PlassChartCategory, locale?: strin
|
|
|
471
547
|
* thousands separators stops being welcome.
|
|
472
548
|
*/
|
|
473
549
|
export declare function compactNumber(value: number, locale?: string): string;
|
|
550
|
+
/** A value as a chart writes it: in the caller's `format`, or compactly without one. */
|
|
551
|
+
export declare function writeChartValue(value: number, format: Intl.NumberFormatOptions | undefined, locale: string | undefined): string;
|
package/dist/internal/chart.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dateFormatter as t,numberFormatter as e}from"./format.js";export const plotHeights={xs:120,sm:160,md:220,lg:280,xl:360};export const sparklineHeights={xs:16,sm:20,md:28,lg:40,xl:56};export const lineWidths={xs:1.5,sm:1.75,md:2,lg:2.25,xl:2.5};export const markerRadii={xs:3,sm:3.5,md:4,lg:4.5,xl:5};export const chartFontSizes={xs:10,sm:11,md:12,lg:13,xl:14};export const barMaxThickness={xs:14,sm:18,md:24,lg:30,xl:36};export const barBandRatio={default:.62,compact:.82};export const markGap=2;export const barRadius=4;export const chartPalette=["var(--plass-chart-1)","var(--plass-chart-2)","var(--plass-chart-3)","var(--plass-chart-4)","var(--plass-chart-5)","var(--plass-chart-6)","var(--plass-chart-7)","var(--plass-chart-8)"];const n=new Set(["primary","secondary","success","warning","danger","info"]);export function resolveColor(t){return n.has(t)?`var(--plass-${t}-accent)`:t}export function seriesColor(t,e,n=chartPalette){return resolveColor(t?.color?t.color:n[e%n.length]??chartPalette[0])}export function toValue(t){return null==t?{value:null}:"number"==typeof t?{value:Number.isFinite(t)?t:null}:(t=>"object"==typeof t&&null!==t)(t)?{value:null!==t.y&&Number.isFinite(t.y)?t.y:null,x:t.x,z:t.z,color:t.color?resolveColor(t.color):void 0,label:t.label}:{value:null}}export function toValues(t){return t.map(t=>t.data.map(toValue))}export function toNumber(t){return t instanceof Date?Number.isFinite(t.getTime())?t.getTime():null:"number"==typeof t&&Number.isFinite(t)?t:null}export function pointX(t,e,n){return toNumber(t.x??n?.[e]??e)}export function categoryExtent(t,e){let n=1/0,r=-1/0,o=!1;return t.forEach(t=>{t.forEach((t,a)=>{if(null===t.value)return;const i=pointX(t,a,e);null!==i&&(o=!0,n=Math.min(n,i),r=Math.max(r,i))})}),o?{min:n,max:r}:null}export function bubbleRadius(t,e,n,r){return e>0&&Number.isFinite(t)&&!(t<=0)?Math.max(r,Math.sqrt(Math.min(t,e)/e)*n):0===t?0:r}export function categoryCount(t){return t.reduce((t,e)=>Math.max(t,e.data.length),0)}export function categoryAt(t,e,n){if(e&&t<e.length)return e[t];for(const e of n){const n=e[t]?.x;if(void 0!==n)return n}return t}export function extentOf(t,e){let n=1/0,r=-1/0,o=!1;if(e){const e=t.reduce((t,e)=>Math.max(t,e.length),0);for(let a=0;a<e;a++){let e=0,i=0;for(const n of t){const t=n[a]?.value;null!=t&&(o=!0,t>=0?e+=t:i+=t)}n=Math.min(n,i),r=Math.max(r,e)}}else for(const e of t)for(const{value:t}of e)null!==t&&(o=!0,n=Math.min(n,t),r=Math.max(r,t));return o?{min:n,max:r}:null}function niceStep(t){const e=10**Math.floor(Math.log10(t)),n=t/e;return n<=1?e:n<=2?2*e:n<=5?5*e:10*e}export function valueScale(t,e={}){const{tickCount:n=5,includeZero:r=!0}=e;let o=e.min??(t?t.min:0),a=e.max??(t?t.max:1);if(r&&void 0===e.min&&(o=Math.min(o,0)),r&&void 0===e.max&&(a=Math.max(a,0)),a===o){const t=Math.abs(a)>0?.5*Math.abs(a):1;o-=t,a+=t}const i=void 0!==e.min&&void 0!==e.max?function dividingStep(t,e){const n=10**Math.floor(Math.log10(t/Math.max(1,e)));let r=niceStep(t/Math.max(1,e)),o=1/0;for(const a of[.1,1,10])for(const i of[1,2,2.5,5]){const u=i*a*n,s=t/u,c=Math.round(s);if(c<1||Math.abs(s-c)>1e-9)continue;const l=Math.abs(c-e);l<o&&(o=l,r=u)}return r}(a-o,n):niceStep((a-o)/Math.max(1,n)),u=void 0!==e.min?o:Math.floor(o/i)*i,s=void 0!==e.max?a:Math.ceil(a/i)*i,c=s-u||1,l=[];for(let t=u;t<=s+1e-9*i;t+=i)l.push(Number(t.toFixed(12)));return{min:u,max:s,ticks:l,fraction:t=>(t-u)/c}}const r=1e3,o=6e4,a=36e5,i=24*a,u=[{unit:"second",count:1,size:r},{unit:"second",count:5,size:5e3},{unit:"second",count:15,size:15e3},{unit:"second",count:30,size:3e4},{unit:"minute",count:1,size:o},{unit:"minute",count:5,size:3e5},{unit:"minute",count:15,size:9e5},{unit:"minute",count:30,size:18e5},{unit:"hour",count:1,size:a},{unit:"hour",count:3,size:3*a},{unit:"hour",count:6,size:6*a},{unit:"hour",count:12,size:12*a},{unit:"day",count:1,size:i},{unit:"day",count:2,size:2*i},{unit:"week",count:1,size:7*i},{unit:"week",count:2,size:14*i},{unit:"month",count:1,size:30*i},{unit:"quarter",count:1,size:91*i},{unit:"month",count:6,size:182*i},{unit:"year",count:1,size:365*i}];function addTime(t,e,n){const a=new Date(t);if("year"===e)a.setFullYear(a.getFullYear()+n);else if("quarter"===e)a.setMonth(a.getMonth()+3*n);else if("month"===e)a.setMonth(a.getMonth()+n);else if("week"===e)a.setDate(a.getDate()+7*n);else if("day"===e)a.setDate(a.getDate()+n);else{if("hour"!==e)return t+n*("minute"===e?o:r);a.setHours(a.getHours()+n)}return a.getTime()}const s={second:"minute",minute:"hour",hour:"day",day:"month",week:"week",month:"year",quarter:"year",year:"year"};export function timeScale(t,e={}){const{tickCount:n=6}=e;let a=e.min??t?.min??Date.parse("2000-01-01T00:00:00"),c=e.max??t?.max??a+i;c<=a&&(a-=i/2,c+=i/2);const l=c-a;let h=u[0],m=1/0;for(const t of u){const e=Math.abs(l/t.size-n);e<m&&(m=e,h=t)}const $=h.unit,f="year"===$?Math.max(1,Math.round(niceStep(l/n/(365*i)))):h.count,x=e.min??function alignTime(t,e,n){let a=function floorTime(t,e){const n=new Date(t);if("year"===e)return new Date(n.getFullYear(),0,1).getTime();if("quarter"===e)return new Date(n.getFullYear(),3*Math.floor(n.getMonth()/3),1).getTime();if("month"===e)return new Date(n.getFullYear(),n.getMonth(),1).getTime();if("week"===e){const t=new Date(n.getFullYear(),n.getMonth(),n.getDate());return t.setDate(t.getDate()-t.getDay()),t.getTime()}return"day"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime():"hour"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours()).getTime():"minute"===e?Math.floor(t/o)*o:Math.floor(t/r)*r}(t,s[e]);if("year"===e&&n>1){const t=new Date(a).getFullYear();a=new Date(t-(t%n+n)%n,0,1).getTime()}for(let r=0;r<500;r++){const r=addTime(a,e,n);if(r>t)return a;a=r}return a}(a,$,f),p=[];let M=x;for(let t=0;t<500&&(p.push(M),!(M>c));t++)M=addTime(M,$,f);const g=e.max??p[p.length-1],d=g-x||1;return{min:x,max:g,ticks:p.filter(t=>t>=x&&t<=g),unit:$,step:f,fraction:t=>(t-x)/d}}function timeParts(t,e){if("second"===t)return{hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"};if("minute"===t||"hour"===t)return{hour:"2-digit",minute:"2-digit",hourCycle:"h23"};if("year"===t)return{year:"numeric"};const n="month"===t||"quarter"===t?{month:"short"}:{month:"short",day:"numeric"};return e?{...n,year:"numeric"}:n}export function formatTimeValue(e,n,r){return t(r,timeParts(n,!0)).format(new Date(e))}export function formatTimeTicks(e,n,r){const o=new Set(e.map(t=>new Date(t).getFullYear())).size>1;return e.map((e,a)=>t(r,timeParts(n,o||0===a)).format(new Date(e)))}export function tickStride(t,e,n){if(t<=1||e<=0)return 1;const r=Math.max(1,Math.floor(e/Math.max(1,n)));return Math.max(1,Math.ceil(t/r))}export function showsTick(t,e,n,r){return t%n===0||r&&t===e-1}export function fitsLast(t,e,n,r){const o=(t-1)%e;return o>0&&o*n>=r+8}export function textWidth(t,e){let n=0;for(const e of t)n+=/[ᄀ-ᇿ⺀-가-豈-︰-﹏]/.test(e)?1:.6;return n*e}export function truncate(t,e,n){if(e<=0||textWidth(t,n)<=e)return t;const r=e-textWidth("…",n);let o="",a=0;for(const e of t){const t=a+textWidth(e,n);if(t>r)break;a=t,o+=e}return o.length>0?`${o.trimEnd()}…`:"…"}export function bandScale(t,e,n){const r=t>0?e/t:e;return{step:r,band:r*n,centre:t=>r*(t+.5)}}export function linePath(t,e){const n=[];let r=[];const flush=()=>{if(0!==r.length){if(1===r.length)n.push(`M${r[0].x} ${r[0].y}h0`);else if("step"===e){n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++){const e=(r[t-1].x+r[t].x)/2;n.push(`H${e}V${r[t].y}H${r[t].x}`)}}else if("smooth"===e)n.push(`M${r[0].x} ${r[0].y}`),n.push(function monotonePath(t){const e=t.length,n=[];for(let r=0;r<e-1;r++){const e=t[r+1].x-t[r].x;n.push(0===e?0:(t[r+1].y-t[r].y)/e)}const r=[n[0]??0];for(let t=1;t<e-1;t++){const e=n[t-1],o=n[t];r.push(e*o<=0?0:2*e*o/(e+o))}r.push(n[e-2]??0);const o=[];for(let n=0;n<e-1;n++){const e=(t[n+1].x-t[n].x)/3;o.push(`C${t[n].x+e} ${t[n].y+r[n]*e} ${t[n+1].x-e} ${t[n+1].y-r[n+1]*e} ${t[n+1].x} ${t[n+1].y}`)}return o.join("")}(r));else{n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++)n.push(`L${r[t].x} ${r[t].y}`)}r=[]}};for(const e of t)null===e?flush():r.push(e);return flush(),n.join("")}export function areaPath(t,e,n){const r=[];let o=0;const flush=a=>{const i=t.slice(o,a).filter(Boolean);if(0===i.length)return;const u="number"==typeof e?i.map(t=>({x:t.x,y:e})).reverse():e.slice(o,a).filter(Boolean).reverse();if(0===u.length)return;const s=linePath(i,n),c=linePath(u,n).replace(/^M/,"L");r.push(`${s}${c}Z`)};for(let e=0;e<t.length;e++)null===t[e]&&(flush(e),o=e+1);return flush(t.length),r.join("")}export function barPath(t,e,n,r,o,a){const i=Math.max(0,Math.min(o,n/2,r/2));if(0===i||n<=0||r<=0)return`M${t} ${e}h${n}v${r}h${-n}Z`;const arc=(t,e)=>`a${i} ${i} 0 0 1 ${t} ${e}`;return"up"===a?`M${t} ${e+r}V${e+i}${arc(i,-i)}H${t+n-i}${arc(i,i)}V${e+r}Z`:"down"===a?`M${t} ${e}H${t+n}V${e+r-i}${arc(-i,i)}H${t+i}${arc(-i,-i)}Z`:"right"===a?`M${t} ${e}H${t+n-i}${arc(i,i)}V${e+r-i}${arc(-i,i)}H${t}Z`:`M${t+n} ${e+r}H${t+i}${arc(-i,-i)}V${e+i}${arc(i,-i)}H${t+n}Z`}export const markShapes=["circle","square","triangle","diamond","cross"];const c={circle:1,square:.8862,triangle:1.5551,diamond:1.2533,cross:1.189};export function markPath(t,e,n,r){const o=Math.max(0,r)*c[t];if(0===o)return"";if("circle"===t)return`M${e-o} ${n}a${o} ${o} 0 1 0 ${2*o} 0a${o} ${o} 0 1 0 ${2*-o} 0Z`;if("square"===t)return`M${e-o} ${n-o}h${2*o}v${2*o}h${2*-o}Z`;if("diamond"===t)return`M${e} ${n-o}L${e+o} ${n}L${e} ${n+o}L${e-o} ${n}Z`;if("triangle"===t)return`M${[0,120,240].map(t=>{const r=(t-90)*Math.PI/180;return`${e+o*Math.cos(r)} ${n+o*Math.sin(r)}`}).join("L")}Z`;const a=o/3;return`M${e-a} ${n-o}h${2*a}v${o-a}h${o-a}v${2*a}h${-(o-a)}v${o-a}h${2*-a}v${-(o-a)}h${-(o-a)}v${2*-a}h${o-a}Z`}export function ringPath(t,e,n,r,o){const point=r=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(o-r)>=360){const t=r+180;return`M${point(r)}A${n} ${n} 0 1 1 ${point(t)}A${n} ${n} 0 1 1 ${point(r)}`}const a=Math.abs(o-r)>180?1:0;return`M${point(r)}A${n} ${n} 0 ${a} 1 ${point(o)}`}export function arcPath(t,e,n,r,o,a){const point=(n,r)=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(a-o)>=360){const t=o+180;return r>0?`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}ZM${point(r,o)}A${r} ${r} 0 1 0 ${point(r,t)}A${r} ${r} 0 1 0 ${point(r,o)}Z`:`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}Z`}const i=Math.abs(a-o)>180?1:0;return r<=0?`M${t} ${e}L${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}Z`:`M${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}L${point(r,a)}A${r} ${r} 0 ${i} 0 ${point(r,o)}Z`}export const rampSteps=5;export function rampStep(t,e,n,r,o=0){if("diverging"===r){const r=Math.max(Math.abs(n-o),Math.abs(o-e));if(!(r>0))return 2;const a=(t-o)/r;return Math.min(4,Math.max(0,2+Math.round(2*a)))}const a=n-e;return a>0?Math.min(4,Math.max(0,Math.floor((t-e)/a*5))):4}export function rampFill(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-${t+1})`}export function rampInk(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-on-${t+1})`}export function squarify(t,e,n){const r=t.reduce((t,e)=>t+Math.max(0,e),0);if(!(r>0)||e<=0||n<=0)return[];const o=e*n/r,a=t.map((t,e)=>({index:e,area:Math.max(0,t)*o})).filter(t=>t.area>0).sort((t,e)=>e.area-t.area),i=[];let u=0,s=0,c=e,l=n,h=[];const worst=t=>{const e=Math.min(c,l),n=t.reduce((t,e)=>t+e.area,0);if(!(n>0&&e>0))return 1/0;const r=t[0].area,o=t[t.length-1].area;return Math.max(e*e*r/(n*n),n*n/(e*e*o))},place=()=>{const t=h.reduce((t,e)=>t+e.area,0),e=Math.min(c,l),n=e>0?t/e:0,r=c>=l;let o=0;for(const t of h){const e=n>0?t.area/n:0;i.push(r?{index:t.index,x:u,y:s+o,width:n,height:e}:{index:t.index,x:u+o,y:s,width:e,height:n}),o+=e}r?(u+=n,c-=n):(s+=n,l-=n),h=[]};for(const t of a)0===h.length||worst([...h,t])<=worst(h)||place(),h.push(t);return h.length>0&&place(),i}const l={month:"short",day:"numeric"},h={notation:"compact",maximumFractionDigits:1},m={maximumFractionDigits:2};export function formatCategory(e,n){return e instanceof Date?t(n,l).format(e):String(e)}export function compactNumber(t,n){return Math.abs(t)>=1e4?e(n,h).format(t):e(n,m).format(t)}
|
|
1
|
+
import{dateFormatter as t,numberFormatter as e}from"./format.js";export const plotHeights={xs:120,sm:160,md:220,lg:280,xl:360};export const sparklineHeights={xs:16,sm:20,md:28,lg:40,xl:56};export const lineWidths={xs:1.5,sm:1.75,md:2,lg:2.25,xl:2.5};export const markerRadii={xs:3,sm:3.5,md:4,lg:4.5,xl:5};export const chartFontSizes={xs:10,sm:11,md:12,lg:13,xl:14};export const barMaxThickness={xs:14,sm:18,md:24,lg:30,xl:36};export const barBandRatio={default:.62,compact:.82};export const markGap=2;export const barRadius=4;export const chartPalette=["var(--plass-chart-1)","var(--plass-chart-2)","var(--plass-chart-3)","var(--plass-chart-4)","var(--plass-chart-5)","var(--plass-chart-6)","var(--plass-chart-7)","var(--plass-chart-8)"];const n=new Set(["primary","secondary","success","warning","danger","info"]);export function resolveColor(t){return n.has(t)?`var(--plass-${t}-accent)`:t}export function seriesColor(t,e,n=chartPalette){return resolveColor(t?.color?t.color:n[e%n.length]??chartPalette[0])}export function dimmedByHover(t,e,n){return null!==t&&t!==e&&!0===n[t]}export function toValue(t){return null==t?{value:null}:"number"==typeof t?{value:Number.isFinite(t)?t:null}:(t=>"object"==typeof t&&null!==t)(t)?{value:null!==t.y&&Number.isFinite(t.y)?t.y:null,x:t.x,z:t.z,color:t.color?resolveColor(t.color):void 0,label:t.label}:{value:null}}export function toValues(t){return t.map(t=>t.data.map(toValue))}export function labelledPoints(t,e){if("none"===e)return()=>!1;if("all"===e)return()=>!0;if("last"===e){let e=-1;for(let n=t.length-1;n>=0;n--)if(null!==t[n].value){e=n;break}return t=>t===e}let n=1/0,r=-1/0;for(const e of t)null!==e.value&&(n=Math.min(n,e.value),r=Math.max(r,e.value));return e=>{const o=t[e].value;return null!==o&&(o===n||o===r)}}export function stackToFull(t,e){const n=toValues(t),r=[];for(const t of n)t.forEach((t,e)=>{r[e]=(r[e]??0)+Math.abs(t.value??0)});return t.map((t,o)=>({...t,data:n[o].map((t,n)=>{if(null===t.value)return null;const o=r[n];return{x:t.x,y:0===o?0:t.value/o*100,color:t.color,label:t.label??e(t.value)}})}))}export function toNumber(t){return t instanceof Date?Number.isFinite(t.getTime())?t.getTime():null:"number"==typeof t&&Number.isFinite(t)?t:null}export function pointX(t,e,n){return toNumber(t.x??n?.[e]??e)}export function categoriesAreDates(t,e){return(e?.some(t=>t instanceof Date)??!1)||t.some(t=>t.some(t=>t.x instanceof Date))}export function categoryExtent(t,e){let n=1/0,r=-1/0,o=!1;return t.forEach(t=>{t.forEach((t,a)=>{if(null===t.value)return;const i=pointX(t,a,e);null!==i&&(o=!0,n=Math.min(n,i),r=Math.max(r,i))})}),o?{min:n,max:r}:null}export function bubbleRadius(t,e,n,r){return e>0&&Number.isFinite(t)&&!(t<=0)?Math.max(r,Math.sqrt(Math.min(t,e)/e)*n):0===t?0:r}export function categoryCount(t){return t.reduce((t,e)=>Math.max(t,e.data.length),0)}export function categoryAt(t,e,n){if(e&&t<e.length)return e[t];for(const e of n){const n=e[t]?.x;if(void 0!==n)return n}return t}export function extentOf(t,e){let n=1/0,r=-1/0,o=!1;if(e){const e=t.reduce((t,e)=>Math.max(t,e.length),0);for(let a=0;a<e;a++){let e=0,i=0;for(const n of t){const t=n[a]?.value;null!=t&&(o=!0,t>=0?e+=t:i+=t)}n=Math.min(n,i),r=Math.max(r,e)}}else for(const e of t)for(const{value:t}of e)null!==t&&(o=!0,n=Math.min(n,t),r=Math.max(r,t));return o?{min:n,max:r}:null}function niceStep(t){const e=10**Math.floor(Math.log10(t)),n=t/e;return n<=1?e:n<=2?2*e:n<=5?5*e:10*e}export function valueScale(t,e={}){const{tickCount:n=5,includeZero:r=!0}=e;let o=e.min??(t?t.min:0),a=e.max??(t?t.max:1);if(r&&void 0===e.min&&(o=Math.min(o,0)),r&&void 0===e.max&&(a=Math.max(a,0)),a===o){const t=Math.abs(a)>0?.5*Math.abs(a):1,n=void 0===e.min,r=void 0===e.max;!n&&r||(o-=t),!r&&n||(a+=t)}const i=void 0!==e.min&&void 0!==e.max?function dividingStep(t,e){const n=10**Math.floor(Math.log10(t/Math.max(1,e)));let r=niceStep(t/Math.max(1,e)),o=1/0;for(const a of[.1,1,10])for(const i of[1,2,2.5,5]){const u=i*a*n,s=t/u,c=Math.round(s);if(c<1||Math.abs(s-c)>1e-9)continue;const l=Math.abs(c-e);l<o&&(o=l,r=u)}return r}(a-o,n):niceStep((a-o)/Math.max(1,n)),u=void 0!==e.min?o:Math.floor(o/i)*i,s=void 0!==e.max?a:Math.ceil(a/i)*i,c=s-u||1,l=[];for(let t=u;t<=s+1e-9*i;t+=i)l.push(Number(t.toFixed(12)));return{min:u,max:s,ticks:l,fraction:t=>(t-u)/c}}const r=1e3,o=6e4,a=36e5,i=24*a,u=[{unit:"second",count:1,size:r},{unit:"second",count:5,size:5e3},{unit:"second",count:15,size:15e3},{unit:"second",count:30,size:3e4},{unit:"minute",count:1,size:o},{unit:"minute",count:5,size:3e5},{unit:"minute",count:15,size:9e5},{unit:"minute",count:30,size:18e5},{unit:"hour",count:1,size:a},{unit:"hour",count:3,size:3*a},{unit:"hour",count:6,size:6*a},{unit:"hour",count:12,size:12*a},{unit:"day",count:1,size:i},{unit:"day",count:2,size:2*i},{unit:"week",count:1,size:7*i},{unit:"week",count:2,size:14*i},{unit:"month",count:1,size:30*i},{unit:"quarter",count:1,size:91*i},{unit:"month",count:6,size:182*i},{unit:"year",count:1,size:365*i}];function floorTime(t,e){const n=new Date(t);if("year"===e)return new Date(n.getFullYear(),0,1).getTime();if("quarter"===e)return new Date(n.getFullYear(),3*Math.floor(n.getMonth()/3),1).getTime();if("month"===e)return new Date(n.getFullYear(),n.getMonth(),1).getTime();if("week"===e){const t=new Date(n.getFullYear(),n.getMonth(),n.getDate());return t.setDate(t.getDate()-t.getDay()),t.getTime()}return"day"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime():"hour"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours()).getTime():"minute"===e?Math.floor(t/o)*o:Math.floor(t/r)*r}function addTime(t,e,n){const a=new Date(t);if("year"===e)a.setFullYear(a.getFullYear()+n);else if("quarter"===e)a.setMonth(a.getMonth()+3*n);else if("month"===e)a.setMonth(a.getMonth()+n);else if("week"===e)a.setDate(a.getDate()+7*n);else if("day"===e)a.setDate(a.getDate()+n);else{if("hour"!==e)return t+n*("minute"===e?o:r);a.setHours(a.getHours()+n)}return a.getTime()}const s={second:"minute",minute:"hour",hour:"day",day:"month",week:"week",month:"year",quarter:"year",year:"year"};export function timeScale(t,e={}){const{tickCount:n=6}=e;let r=e.min??t?.min??Date.parse("2000-01-01T00:00:00"),o=e.max??t?.max??r+i;o<=r&&(r-=i/2,o+=i/2);const a=o-r;let c=u[0],l=1/0;for(const t of u){const e=Math.abs(a/t.size-n);e<l&&(l=e,c=t)}const h=c.unit,m="year"===h?Math.max(1,Math.round(niceStep(a/n/(365*i)))):c.count,f=e.min??function alignTime(t,e,n){let r=floorTime(t,s[e]);if("year"===e&&n>1){const t=new Date(r).getFullYear();r=new Date(t-(t%n+n)%n,0,1).getTime()}for(let o=0;o<500;o++){const o=addTime(r,e,n);if(o>t)return r;r=o}return r}(r,h,m),$=[];let x=f;for(let t=0;t<500&&($.push(x),!(x>o));t++)x=addTime(x,h,m);const p=e.max??$[$.length-1],M=p-f||1;return{min:f,max:p,ticks:$.filter(t=>t>=f&&t<=p),unit:h,step:m,fraction:t=>(t-f)/M}}function timeParts(t,e,n=!1){if("second"===t||"minute"===t||"hour"===t){const r="second"===t?{hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}:{hour:"2-digit",minute:"2-digit",hourCycle:"h23"};if(!n)return r;const o={month:"short",day:"numeric",...r};return e?{...o,year:"numeric"}:o}if("year"===t)return{year:"numeric"};const r="month"===t||"quarter"===t?{month:"short"}:{month:"short",day:"numeric"};return e?{...r,year:"numeric"}:r}export function timeNeedsDate(t,e){return!("second"!==e&&"minute"!==e&&"hour"!==e||t.length<2||floorTime(t[0],"day")===floorTime(t[t.length-1]-1,"day"))}export function formatTimeValue(e,n,r,o=!1){return t(r,timeParts(n,!0,o)).format(new Date(e))}export function formatTimeTicks(e,n,r){const o=new Set(e.map(t=>new Date(t).getFullYear())).size>1,a=timeNeedsDate(e,n);return e.map((e,i)=>t(r,timeParts(n,o||0===i,a)).format(new Date(e)))}export function tickStride(t,e,n){if(t<=1||e<=0)return 1;const r=Math.max(1,Math.floor(e/Math.max(1,n)));return Math.max(1,Math.ceil(t/r))}export function showsTick(t,e,n,r){return t%n===0||r&&t===e-1}export function fitsLast(t,e,n,r){const o=(t-1)%e;return o>0&&o*n>=r+8}export function textWidth(t,e){let n=0;for(const e of t)n+=/[ᄀ-ᇿ⺀-가-豈-︰-﹏]/.test(e)?1:.6;return n*e}export function truncate(t,e,n){if(e<=0||textWidth(t,n)<=e)return t;const r=e-textWidth("…",n);let o="",a=0;for(const e of t){const t=a+textWidth(e,n);if(t>r)break;a=t,o+=e}return o.length>0?`${o.trimEnd()}…`:"…"}export function fitCategoryLabels(t,e){const{horizontal:n,slot:r,fontSize:o,ticks:a}=e;return a||!n&&r-6<2.4*o?t:t.map(t=>truncate(t,n?150:r-6,o))}export function bandScale(t,e,n){const r=t>0?e/t:e;return{step:r,band:r*n,centre:t=>r*(t+.5)}}export function linePath(t,e){const n=[];let r=[];const flush=()=>{if(0!==r.length){if(1===r.length)n.push(`M${r[0].x} ${r[0].y}h0`);else if("step"===e){n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++){const e=(r[t-1].x+r[t].x)/2;n.push(`H${e}V${r[t].y}H${r[t].x}`)}}else if("smooth"===e)n.push(`M${r[0].x} ${r[0].y}`),n.push(function monotonePath(t){const e=t.length,n=[];for(let r=0;r<e-1;r++){const e=t[r+1].x-t[r].x;n.push(0===e?0:(t[r+1].y-t[r].y)/e)}const r=[n[0]??0];for(let t=1;t<e-1;t++){const e=n[t-1],o=n[t];r.push(e*o<=0?0:2*e*o/(e+o))}r.push(n[e-2]??0);const o=[];for(let n=0;n<e-1;n++){const e=(t[n+1].x-t[n].x)/3;o.push(`C${t[n].x+e} ${t[n].y+r[n]*e} ${t[n+1].x-e} ${t[n+1].y-r[n+1]*e} ${t[n+1].x} ${t[n+1].y}`)}return o.join("")}(r));else{n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++)n.push(`L${r[t].x} ${r[t].y}`)}r=[]}};for(const e of t)null===e?flush():r.push(e);return flush(),n.join("")}export function areaPath(t,e,n){const r=[];let o=0;const flush=a=>{const i=t.slice(o,a).filter(Boolean);if(0===i.length)return;const u="number"==typeof e?i.map(t=>({x:t.x,y:e})).reverse():e.slice(o,a).filter(Boolean).reverse();if(0===u.length)return;const s=linePath(i,n),c=linePath(u,n).replace(/^M/,"L");r.push(`${s}${c}Z`)};for(let e=0;e<t.length;e++)null===t[e]&&(flush(e),o=e+1);return flush(t.length),r.join("")}export function barPath(t,e,n,r,o,a){const i=Math.max(0,Math.min(o,n/2,r/2));if(0===i||n<=0||r<=0)return`M${t} ${e}h${n}v${r}h${-n}Z`;const arc=(t,e)=>`a${i} ${i} 0 0 1 ${t} ${e}`;return"up"===a?`M${t} ${e+r}V${e+i}${arc(i,-i)}H${t+n-i}${arc(i,i)}V${e+r}Z`:"down"===a?`M${t} ${e}H${t+n}V${e+r-i}${arc(-i,i)}H${t+i}${arc(-i,-i)}Z`:"right"===a?`M${t} ${e}H${t+n-i}${arc(i,i)}V${e+r-i}${arc(-i,i)}H${t}Z`:`M${t+n} ${e+r}H${t+i}${arc(-i,-i)}V${e+i}${arc(i,-i)}H${t+n}Z`}export const markShapes=["circle","square","triangle","diamond","cross"];const c={circle:1,square:.8862,triangle:1.5551,diamond:1.2533,cross:1.189};export function markPath(t,e,n,r){const o=Math.max(0,r)*c[t];if(0===o)return"";if("circle"===t)return`M${e-o} ${n}a${o} ${o} 0 1 0 ${2*o} 0a${o} ${o} 0 1 0 ${2*-o} 0Z`;if("square"===t)return`M${e-o} ${n-o}h${2*o}v${2*o}h${2*-o}Z`;if("diamond"===t)return`M${e} ${n-o}L${e+o} ${n}L${e} ${n+o}L${e-o} ${n}Z`;if("triangle"===t)return`M${[0,120,240].map(t=>{const r=(t-90)*Math.PI/180;return`${e+o*Math.cos(r)} ${n+o*Math.sin(r)}`}).join("L")}Z`;const a=o/3;return`M${e-a} ${n-o}h${2*a}v${o-a}h${o-a}v${2*a}h${-(o-a)}v${o-a}h${2*-a}v${-(o-a)}h${-(o-a)}v${2*-a}h${o-a}Z`}export function ringPath(t,e,n,r,o){const point=r=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(o-r)>=360){const t=r+180;return`M${point(r)}A${n} ${n} 0 1 1 ${point(t)}A${n} ${n} 0 1 1 ${point(r)}`}const a=Math.abs(o-r)>180?1:0;return`M${point(r)}A${n} ${n} 0 ${a} 1 ${point(o)}`}export function arcPath(t,e,n,r,o,a){const point=(n,r)=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(a-o)>=360){const t=o+180;return r>0?`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}ZM${point(r,o)}A${r} ${r} 0 1 0 ${point(r,t)}A${r} ${r} 0 1 0 ${point(r,o)}Z`:`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}Z`}const i=Math.abs(a-o)>180?1:0;return r<=0?`M${t} ${e}L${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}Z`:`M${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}L${point(r,a)}A${r} ${r} 0 ${i} 0 ${point(r,o)}Z`}export const rampSteps=5;export function rampStep(t,e,n,r,o=0){if("diverging"===r){const r=Math.max(Math.abs(n-o),Math.abs(o-e));if(!(r>0))return 2;const a=(t-o)/r;return Math.min(4,Math.max(0,2+Math.round(2*a)))}const a=n-e;return a>0?Math.min(4,Math.max(0,Math.floor((t-e)/a*5))):4}export function rampFill(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-${t+1})`}export function rampInk(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-on-${t+1})`}export function squarify(t,e,n){const r=t.reduce((t,e)=>t+Math.max(0,e),0);if(!(r>0)||e<=0||n<=0)return[];const o=e*n/r,a=t.map((t,e)=>({index:e,area:Math.max(0,t)*o})).filter(t=>t.area>0).sort((t,e)=>e.area-t.area),i=[];let u=0,s=0,c=e,l=n,h=[];const worst=t=>{const e=Math.min(c,l),n=t.reduce((t,e)=>t+e.area,0);if(!(n>0&&e>0))return 1/0;const r=t[0].area,o=t[t.length-1].area;return Math.max(e*e*r/(n*n),n*n/(e*e*o))},place=()=>{const t=h.reduce((t,e)=>t+e.area,0),e=Math.min(c,l),n=e>0?t/e:0,r=c>=l;let o=0;for(const t of h){const e=n>0?t.area/n:0;i.push(r?{index:t.index,x:u,y:s+o,width:n,height:e}:{index:t.index,x:u+o,y:s,width:e,height:n}),o+=e}r?(u+=n,c-=n):(s+=n,l-=n),h=[]};for(const t of a)0===h.length||worst([...h,t])<=worst(h)||place(),h.push(t);return h.length>0&&place(),i}const l={month:"short",day:"numeric"},h={notation:"compact",maximumFractionDigits:1},m={maximumFractionDigits:2};export function formatCategory(e,n){return e instanceof Date?t(n,l).format(e):String(e)}export function compactNumber(t,n){return Math.abs(t)>=1e4?e(n,h).format(t):e(n,m).format(t)}export function writeChartValue(t,n,r){return n?e(r,n).format(t):compactNumber(t,r)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import*as e from"react";export const DEFAULT_STORAGE_KEY="plass-color-scheme";export const darkQuery="(prefers-color-scheme: dark)";export function applyColorScheme(e){if("undefined"==typeof document)return;const t=document.documentElement;t.classList.remove("light","dark"),"system"!==e?(t.dataset.theme=e,t.classList.add(e)):delete t.dataset.theme}export function readStoredScheme(e){if("undefined"==typeof localStorage)return null;
|
|
1
|
+
"use client";import*as e from"react";export const DEFAULT_STORAGE_KEY="plass-color-scheme";export const darkQuery="(prefers-color-scheme: dark)";export function applyColorScheme(e){if("undefined"==typeof document)return;const t=document.documentElement;t.classList.remove("light","dark"),"system"!==e?(t.dataset.theme=e,t.classList.add(e)):delete t.dataset.theme}export function readStoredScheme(e){try{if("undefined"==typeof localStorage)return null;const t=localStorage.getItem(e);return"light"===t||"dark"===t||"system"===t?t:null}catch{return null}}const t=new Map;function storeFor(e,r){let o=t.get(e);return o||(o={scheme:readStoredScheme(e)??r,listeners:new Set},t.set(e,o)),o}export function useColorSchemeStore(t,r){const o=e.useCallback(e=>{const o=storeFor(t,r);o.listeners.add(e);const onStorage=e=>{if(e.key!==t)return;const s=readStoredScheme(t)??r;s!==o.scheme&&(o.scheme=s,applyColorScheme(s),o.listeners.forEach(e=>e()))};return window.addEventListener("storage",onStorage),()=>{o.listeners.delete(e),window.removeEventListener("storage",onStorage)}},[t,r]),s=e.useCallback(()=>storeFor(t,r).scheme,[t,r]),n=e.useCallback(()=>r,[r]),c=e.useSyncExternalStore(o,s,n),l=e.useCallback(e=>{const o=storeFor(t,r);o.scheme=e,function writeStoredScheme(e,t){try{localStorage.setItem(e,t)}catch{}}(t,e),applyColorScheme(e),o.listeners.forEach(e=>e())},[t,r]);return[c,l]}
|
|
@@ -18,7 +18,8 @@ export interface PlassSort {
|
|
|
18
18
|
direction: PlassSortDirection;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Puts two cell values in order
|
|
21
|
+
* Puts two cell values in order, in the direction given: `1` for ascending and
|
|
22
|
+
* `-1` for descending.
|
|
22
23
|
*
|
|
23
24
|
* Numbers and dates compare as themselves, strings compare the way the reader's
|
|
24
25
|
* language orders them, and everything else falls back to its text. Two rules
|
|
@@ -27,15 +28,15 @@ export interface PlassSort {
|
|
|
27
28
|
* **Nothing sorts last, in both directions.** A column of amounts with three
|
|
28
29
|
* blanks in it is a column whose blanks are not the smallest amounts, and a
|
|
29
30
|
* reader who reversed the sort to find the largest should not be handed the
|
|
30
|
-
* empty ones instead. So the answer for a missing value is decided here,
|
|
31
|
-
*
|
|
31
|
+
* empty ones instead. So the answer for a missing value is decided here, and the
|
|
32
|
+
* direction turns only the rest round.
|
|
32
33
|
*
|
|
33
34
|
* **Strings compare with `localeCompare`.** `'a' < 'B'` is false by code point,
|
|
34
35
|
* which puts every capitalised word above every lower-case one and sorts `Ösi`
|
|
35
36
|
* after `Zoe`. A list of names a reader cannot scan is a list that was sorted
|
|
36
37
|
* for the machine.
|
|
37
38
|
*/
|
|
38
|
-
export declare function compareValues(a: unknown, b: unknown): number;
|
|
39
|
+
export declare function compareValues(a: unknown, b: unknown, direction?: 1 | -1): number;
|
|
39
40
|
/**
|
|
40
41
|
* What pressing a column heading does next.
|
|
41
42
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function compareValues(e,n){const
|
|
1
|
+
export function compareValues(e,n,t=1){const o=null==e||""===e,r=null==n||""===n;return o||r?o&&r?0:o?1:-1:function compareKnown(e,n){return"number"==typeof e&&"number"==typeof n?e-n:"boolean"==typeof e&&"boolean"==typeof n?Number(e)-Number(n):e instanceof Date&&n instanceof Date?e.getTime()-n.getTime():String(e).localeCompare(String(n))}(e,n)*t}export function nextSort(e,n){return null===e||e.key!==n?{key:n,direction:"asc"}:"asc"===e.direction?{key:n,direction:"desc"}:null}export function keysBetween(e,n,t){const o=e.indexOf(n),r=e.indexOf(t);return-1===o||-1===r?[]:o<=r?e.slice(o,r+1):e.slice(r,o+1)}export function pageBounds(e,n,t){const o=Math.max(1,Math.ceil(e/t)),r=(Math.min(Math.max(1,Math.trunc(n)),o)-1)*t;return[r,Math.min(r+t,e)]}
|
package/dist/internal/date.d.ts
CHANGED
|
@@ -112,6 +112,16 @@ export declare function withTime(date: Date, parts: {
|
|
|
112
112
|
minutes?: number;
|
|
113
113
|
seconds?: number;
|
|
114
114
|
}): Date;
|
|
115
|
+
/**
|
|
116
|
+
* Holds a moment inside `[min, max]`, on a whole second when `seconds` is set
|
|
117
|
+
* and a whole minute when it is not — the smallest step the clock can show.
|
|
118
|
+
*
|
|
119
|
+
* The bounds are read at full precision, so a moment is rounded into the span
|
|
120
|
+
* rather than onto a bound it would then sit outside of: up from a minimum and
|
|
121
|
+
* down from a maximum. Two bounds inside one step leave no whole step between
|
|
122
|
+
* them, and the bound itself is returned.
|
|
123
|
+
*/
|
|
124
|
+
export declare function clampMoment(date: Date, min: Date | null | undefined, max: Date | null | undefined, seconds: boolean): Date;
|
|
115
125
|
/** `date`'s calendar day wearing `time`'s clock. */
|
|
116
126
|
export declare function mergeDateAndTime(date: Date, time: Date): Date;
|
|
117
127
|
/**
|