@wallarm-org/claude-design 0.0.0-stage → 4.8.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/README.md +114 -2
- package/bin/claude-design.js +347 -0
- package/dist/SETUP.md +130 -0
- package/dist/UPDATE.md +84 -0
- package/dist/assets/Icons/activity.svg +1 -0
- package/dist/assets/Icons/alt.svg +1 -0
- package/dist/assets/Icons/android-neutral.svg +1 -0
- package/dist/assets/Icons/android.svg +1 -0
- package/dist/assets/Icons/api.svg +1 -0
- package/dist/assets/Icons/apple-music-neutral.svg +1 -0
- package/dist/assets/Icons/apple-music.svg +1 -0
- package/dist/assets/Icons/apple-neutral.svg +1 -0
- package/dist/assets/Icons/apple-podcasts-neutral.svg +1 -0
- package/dist/assets/Icons/apple-podcasts.svg +1 -0
- package/dist/assets/Icons/apple.svg +1 -0
- package/dist/assets/Icons/archive.svg +1 -0
- package/dist/assets/Icons/arrow-big-up-dash.svg +1 -0
- package/dist/assets/Icons/arrow-big-up.svg +1 -0
- package/dist/assets/Icons/arrow-down-left.svg +1 -0
- package/dist/assets/Icons/arrow-down-right.svg +1 -0
- package/dist/assets/Icons/arrow-down.svg +1 -0
- package/dist/assets/Icons/arrow-left.svg +1 -0
- package/dist/assets/Icons/arrow-right-alt.svg +1 -0
- package/dist/assets/Icons/arrow-right.svg +1 -0
- package/dist/assets/Icons/arrow-up-down.svg +1 -0
- package/dist/assets/Icons/arrow-up-left.svg +1 -0
- package/dist/assets/Icons/arrow-up-right.svg +1 -0
- package/dist/assets/Icons/arrow-up.svg +1 -0
- package/dist/assets/Icons/artstation-neutral.svg +1 -0
- package/dist/assets/Icons/artstation.svg +1 -0
- package/dist/assets/Icons/asterisk.svg +1 -0
- package/dist/assets/Icons/audio-waveform.svg +1 -0
- package/dist/assets/Icons/aws-neutral.svg +1 -0
- package/dist/assets/Icons/aws.svg +1 -0
- package/dist/assets/Icons/badge-check.svg +1 -0
- package/dist/assets/Icons/baidu-neutral.svg +1 -0
- package/dist/assets/Icons/baidu.svg +1 -0
- package/dist/assets/Icons/bandage.svg +1 -0
- package/dist/assets/Icons/behance-neutral.svg +1 -0
- package/dist/assets/Icons/behance.svg +1 -0
- package/dist/assets/Icons/bell-cog.svg +1 -0
- package/dist/assets/Icons/bell.svg +1 -0
- package/dist/assets/Icons/binary.svg +1 -0
- package/dist/assets/Icons/book-open.svg +1 -0
- package/dist/assets/Icons/book.svg +1 -0
- package/dist/assets/Icons/boosty-neutral.svg +1 -0
- package/dist/assets/Icons/boosty.svg +1 -0
- package/dist/assets/Icons/bot.svg +1 -0
- package/dist/assets/Icons/brain.svg +1 -0
- package/dist/assets/Icons/braze-neutral.svg +1 -0
- package/dist/assets/Icons/braze.svg +1 -0
- package/dist/assets/Icons/brevo-neutral.svg +1 -0
- package/dist/assets/Icons/brevo.svg +1 -0
- package/dist/assets/Icons/bug-off.svg +1 -0
- package/dist/assets/Icons/bug-play.svg +1 -0
- package/dist/assets/Icons/bug.svg +1 -0
- package/dist/assets/Icons/building.svg +1 -0
- package/dist/assets/Icons/building2.svg +1 -0
- package/dist/assets/Icons/calendar-check.svg +1 -0
- package/dist/assets/Icons/calendar-check2.svg +1 -0
- package/dist/assets/Icons/calendar-clock.svg +1 -0
- package/dist/assets/Icons/calendar-cog.svg +1 -0
- package/dist/assets/Icons/calendar-days.svg +1 -0
- package/dist/assets/Icons/calendar-fold.svg +1 -0
- package/dist/assets/Icons/calendar-heart.svg +1 -0
- package/dist/assets/Icons/calendar-minus.svg +1 -0
- package/dist/assets/Icons/calendar-minus2.svg +1 -0
- package/dist/assets/Icons/calendar-off.svg +1 -0
- package/dist/assets/Icons/calendar-plus.svg +1 -0
- package/dist/assets/Icons/calendar-plus2.svg +1 -0
- package/dist/assets/Icons/calendar-range.svg +1 -0
- package/dist/assets/Icons/calendar-search.svg +1 -0
- package/dist/assets/Icons/calendar-x.svg +1 -0
- package/dist/assets/Icons/calendar-x2.svg +1 -0
- package/dist/assets/Icons/calendar.svg +1 -0
- package/dist/assets/Icons/chart-area.svg +1 -0
- package/dist/assets/Icons/chart-bar.svg +1 -0
- package/dist/assets/Icons/chart-column.svg +1 -0
- package/dist/assets/Icons/chart-no-axes-column.svg +1 -0
- package/dist/assets/Icons/check-check.svg +1 -0
- package/dist/assets/Icons/check.svg +1 -0
- package/dist/assets/Icons/checkbox-indeterminate.svg +1 -0
- package/dist/assets/Icons/chevron-down.svg +1 -0
- package/dist/assets/Icons/chevron-first.svg +1 -0
- package/dist/assets/Icons/chevron-last.svg +1 -0
- package/dist/assets/Icons/chevron-left.svg +1 -0
- package/dist/assets/Icons/chevron-right.svg +1 -0
- package/dist/assets/Icons/chevron-up-down.svg +1 -0
- package/dist/assets/Icons/chevron-up.svg +1 -0
- package/dist/assets/Icons/chevrons-down-up.svg +1 -0
- package/dist/assets/Icons/chevrons-down.svg +1 -0
- package/dist/assets/Icons/chevrons-left-right.svg +1 -0
- package/dist/assets/Icons/chevrons-left.svg +1 -0
- package/dist/assets/Icons/chevrons-right-left.svg +1 -0
- package/dist/assets/Icons/chevrons-right.svg +1 -0
- package/dist/assets/Icons/chevrons-up-down.svg +1 -0
- package/dist/assets/Icons/chevrons-up.svg +1 -0
- package/dist/assets/Icons/circle-arrow-down.svg +1 -0
- package/dist/assets/Icons/circle-arrow-left.svg +1 -0
- package/dist/assets/Icons/circle-arrow-out-down-left.svg +1 -0
- package/dist/assets/Icons/circle-arrow-out-down-right.svg +1 -0
- package/dist/assets/Icons/circle-arrow-out-up-left.svg +1 -0
- package/dist/assets/Icons/circle-arrow-out-up-right.svg +1 -0
- package/dist/assets/Icons/circle-arrow-right.svg +1 -0
- package/dist/assets/Icons/circle-arrow-up.svg +1 -0
- package/dist/assets/Icons/circle-check-big.svg +1 -0
- package/dist/assets/Icons/circle-check.svg +1 -0
- package/dist/assets/Icons/circle-chevron-down.svg +1 -0
- package/dist/assets/Icons/circle-chevron-left.svg +1 -0
- package/dist/assets/Icons/circle-chevron-right.svg +1 -0
- package/dist/assets/Icons/circle-chevron-up.svg +1 -0
- package/dist/assets/Icons/circle-dashed.svg +1 -0
- package/dist/assets/Icons/circle-dot-dashed.svg +1 -0
- package/dist/assets/Icons/circle-ellipsis.svg +1 -0
- package/dist/assets/Icons/circle-gauge.svg +1 -0
- package/dist/assets/Icons/circle-help.svg +1 -0
- package/dist/assets/Icons/circle-minus.svg +1 -0
- package/dist/assets/Icons/circle-plus.svg +1 -0
- package/dist/assets/Icons/circle-slash.svg +1 -0
- package/dist/assets/Icons/circle-slash2.svg +1 -0
- package/dist/assets/Icons/circle-stop.svg +1 -0
- package/dist/assets/Icons/circle.svg +1 -0
- package/dist/assets/Icons/clipboard-check.svg +1 -0
- package/dist/assets/Icons/clipboard-x.svg +1 -0
- package/dist/assets/Icons/clipboard.svg +1 -0
- package/dist/assets/Icons/clock-fading.svg +1 -0
- package/dist/assets/Icons/clock.svg +1 -0
- package/dist/assets/Icons/cloud-off.svg +1 -0
- package/dist/assets/Icons/cloud-sync.svg +1 -0
- package/dist/assets/Icons/cloud.svg +1 -0
- package/dist/assets/Icons/code.svg +1 -0
- package/dist/assets/Icons/collapse.svg +1 -0
- package/dist/assets/Icons/columns3-cog.svg +1 -0
- package/dist/assets/Icons/command.svg +1 -0
- package/dist/assets/Icons/compass.svg +1 -0
- package/dist/assets/Icons/copy-slash.svg +1 -0
- package/dist/assets/Icons/copy.svg +1 -0
- package/dist/assets/Icons/corner-down-left.svg +1 -0
- package/dist/assets/Icons/corner-down-right.svg +1 -0
- package/dist/assets/Icons/corner-left-down.svg +1 -0
- package/dist/assets/Icons/corner-left-up.svg +1 -0
- package/dist/assets/Icons/corner-right-down.svg +1 -0
- package/dist/assets/Icons/corner-right-up.svg +1 -0
- package/dist/assets/Icons/corner-up-left.svg +1 -0
- package/dist/assets/Icons/corner-up-right.svg +1 -0
- package/dist/assets/Icons/cpu.svg +1 -0
- package/dist/assets/Icons/credit-card.svg +1 -0
- package/dist/assets/Icons/crosshair.svg +1 -0
- package/dist/assets/Icons/ctrl.svg +1 -0
- package/dist/assets/Icons/database.svg +1 -0
- package/dist/assets/Icons/devianart-neutral.svg +1 -0
- package/dist/assets/Icons/devianart.svg +1 -0
- package/dist/assets/Icons/discord-neutral.svg +1 -0
- package/dist/assets/Icons/discord.svg +1 -0
- package/dist/assets/Icons/dollar-sign.svg +1 -0
- package/dist/assets/Icons/dot.svg +1 -0
- package/dist/assets/Icons/download.svg +1 -0
- package/dist/assets/Icons/dprofile-neutral.svg +1 -0
- package/dist/assets/Icons/dprofile.svg +1 -0
- package/dist/assets/Icons/dribbble-neutral.svg +1 -0
- package/dist/assets/Icons/dribbble.svg +1 -0
- package/dist/assets/Icons/droplet.svg +1 -0
- package/dist/assets/Icons/duplicate.svg +1 -0
- package/dist/assets/Icons/dzen-neutral.svg +1 -0
- package/dist/assets/Icons/dzen.svg +1 -0
- package/dist/assets/Icons/earth-lock.svg +1 -0
- package/dist/assets/Icons/earth.svg +1 -0
- package/dist/assets/Icons/ellipsis.svg +1 -0
- package/dist/assets/Icons/expand.svg +1 -0
- package/dist/assets/Icons/external-link.svg +1 -0
- package/dist/assets/Icons/eye-off.svg +1 -0
- package/dist/assets/Icons/eye.svg +1 -0
- package/dist/assets/Icons/facebook-neutral.svg +1 -0
- package/dist/assets/Icons/facebook.svg +1 -0
- package/dist/assets/Icons/fast-forward.svg +1 -0
- package/dist/assets/Icons/figma-neutral.svg +1 -0
- package/dist/assets/Icons/figma.svg +1 -0
- package/dist/assets/Icons/file-down.svg +1 -0
- package/dist/assets/Icons/file-plus.svg +1 -0
- package/dist/assets/Icons/file-text.svg +1 -0
- package/dist/assets/Icons/file.svg +1 -0
- package/dist/assets/Icons/film.svg +1 -0
- package/dist/assets/Icons/filter-x.svg +1 -0
- package/dist/assets/Icons/filter.svg +1 -0
- package/dist/assets/Icons/fingerprint-pattern.svg +1 -0
- package/dist/assets/Icons/flag.svg +1 -0
- package/dist/assets/Icons/flask-conical.svg +1 -0
- package/dist/assets/Icons/folder.svg +1 -0
- package/dist/assets/Icons/funnel-plus.svg +1 -0
- package/dist/assets/Icons/ghost.svg +1 -0
- package/dist/assets/Icons/git-branch.svg +1 -0
- package/dist/assets/Icons/git-commit-horizontal.svg +1 -0
- package/dist/assets/Icons/git-commit-vertical.svg +1 -0
- package/dist/assets/Icons/git-compare-arrows-alt.svg +1 -0
- package/dist/assets/Icons/git-compare-arrows.svg +1 -0
- package/dist/assets/Icons/git-compare.svg +1 -0
- package/dist/assets/Icons/git-fork.svg +1 -0
- package/dist/assets/Icons/git-graph.svg +1 -0
- package/dist/assets/Icons/git-merge.svg +1 -0
- package/dist/assets/Icons/git-pull-request-arrow.svg +1 -0
- package/dist/assets/Icons/git-pull-request-closed.svg +1 -0
- package/dist/assets/Icons/git-pull-request-create-arrow.svg +1 -0
- package/dist/assets/Icons/git-pull-request-create.svg +1 -0
- package/dist/assets/Icons/git-pull-request-draft.svg +1 -0
- package/dist/assets/Icons/git-pull-request.svg +1 -0
- package/dist/assets/Icons/github-neutral.svg +1 -0
- package/dist/assets/Icons/github.svg +1 -0
- package/dist/assets/Icons/globe-lock.svg +1 -0
- package/dist/assets/Icons/globe.svg +1 -0
- package/dist/assets/Icons/gmail-neutral.svg +1 -0
- package/dist/assets/Icons/gmail.svg +1 -0
- package/dist/assets/Icons/google-meet-neutral.svg +1 -0
- package/dist/assets/Icons/google-meet.svg +1 -0
- package/dist/assets/Icons/google-neutral.svg +1 -0
- package/dist/assets/Icons/google-play-neutral.svg +1 -0
- package/dist/assets/Icons/google-play.svg +1 -0
- package/dist/assets/Icons/google-podcast-neutral.svg +1 -0
- package/dist/assets/Icons/google-podcast.svg +1 -0
- package/dist/assets/Icons/google.svg +1 -0
- package/dist/assets/Icons/grip-horizontal.svg +1 -0
- package/dist/assets/Icons/grip-vertical.svg +1 -0
- package/dist/assets/Icons/hammer.svg +1 -0
- package/dist/assets/Icons/heart-pulse.svg +1 -0
- package/dist/assets/Icons/history.svg +1 -0
- package/dist/assets/Icons/home.svg +1 -0
- package/dist/assets/Icons/imo-neutral.svg +1 -0
- package/dist/assets/Icons/imo.svg +1 -0
- package/dist/assets/Icons/infinity.svg +1 -0
- package/dist/assets/Icons/info.svg +1 -0
- package/dist/assets/Icons/infobip-neutral.svg +1 -0
- package/dist/assets/Icons/infobip.svg +1 -0
- package/dist/assets/Icons/instagram-neutral.svg +1 -0
- package/dist/assets/Icons/instagram.svg +1 -0
- package/dist/assets/Icons/key-round.svg +1 -0
- package/dist/assets/Icons/key-square.svg +1 -0
- package/dist/assets/Icons/keyboard.svg +1 -0
- package/dist/assets/Icons/kickstarter-neutral.svg +1 -0
- package/dist/assets/Icons/kickstarter.svg +1 -0
- package/dist/assets/Icons/laptop.svg +1 -0
- package/dist/assets/Icons/layers.svg +1 -0
- package/dist/assets/Icons/layers2.svg +1 -0
- package/dist/assets/Icons/layers3.svg +1 -0
- package/dist/assets/Icons/layout-dashboard.svg +1 -0
- package/dist/assets/Icons/layout-grid.svg +1 -0
- package/dist/assets/Icons/layout-list.svg +1 -0
- package/dist/assets/Icons/layout-panel-left.svg +1 -0
- package/dist/assets/Icons/layout-panel-top.svg +1 -0
- package/dist/assets/Icons/layout-template.svg +1 -0
- package/dist/assets/Icons/library-big.svg +1 -0
- package/dist/assets/Icons/life-buoy.svg +1 -0
- package/dist/assets/Icons/lightbulb-off.svg +1 -0
- package/dist/assets/Icons/lightbulb.svg +1 -0
- package/dist/assets/Icons/line-neutral.svg +1 -0
- package/dist/assets/Icons/line.svg +1 -0
- package/dist/assets/Icons/link.svg +1 -0
- package/dist/assets/Icons/link2-off.svg +1 -0
- package/dist/assets/Icons/link2.svg +1 -0
- package/dist/assets/Icons/linkedin-neutral.svg +1 -0
- package/dist/assets/Icons/linkedin.svg +1 -0
- package/dist/assets/Icons/list-checks.svg +1 -0
- package/dist/assets/Icons/list-collapse.svg +1 -0
- package/dist/assets/Icons/list-filter.svg +1 -0
- package/dist/assets/Icons/list-minus.svg +1 -0
- package/dist/assets/Icons/list-ordered.svg +1 -0
- package/dist/assets/Icons/list-plus.svg +1 -0
- package/dist/assets/Icons/list-restart.svg +1 -0
- package/dist/assets/Icons/list-start.svg +1 -0
- package/dist/assets/Icons/list-todo.svg +1 -0
- package/dist/assets/Icons/list-tree.svg +1 -0
- package/dist/assets/Icons/list-video.svg +1 -0
- package/dist/assets/Icons/list-x.svg +1 -0
- package/dist/assets/Icons/list.svg +1 -0
- package/dist/assets/Icons/loader-circle.svg +1 -0
- package/dist/assets/Icons/loader.svg +1 -0
- package/dist/assets/Icons/lock-open.svg +1 -0
- package/dist/assets/Icons/lock.svg +1 -0
- package/dist/assets/Icons/log-in.svg +1 -0
- package/dist/assets/Icons/log-out.svg +1 -0
- package/dist/assets/Icons/mail-check.svg +1 -0
- package/dist/assets/Icons/mail-minus.svg +1 -0
- package/dist/assets/Icons/mail-open.svg +1 -0
- package/dist/assets/Icons/mail-plus.svg +1 -0
- package/dist/assets/Icons/mail-question.svg +1 -0
- package/dist/assets/Icons/mail-search.svg +1 -0
- package/dist/assets/Icons/mail-warning.svg +1 -0
- package/dist/assets/Icons/mail-x.svg +1 -0
- package/dist/assets/Icons/mail.svg +1 -0
- package/dist/assets/Icons/mailbox.svg +1 -0
- package/dist/assets/Icons/mailersend-neutral.svg +1 -0
- package/dist/assets/Icons/mailersend.svg +1 -0
- package/dist/assets/Icons/mailgun-neutral.svg +1 -0
- package/dist/assets/Icons/mailgun.svg +1 -0
- package/dist/assets/Icons/mailjet-neutral.svg +1 -0
- package/dist/assets/Icons/mailjet.svg +1 -0
- package/dist/assets/Icons/mails.svg +1 -0
- package/dist/assets/Icons/mailtrap-neutral.svg +1 -0
- package/dist/assets/Icons/mailtrap.svg +1 -0
- package/dist/assets/Icons/mandrill-neutral.svg +1 -0
- package/dist/assets/Icons/mandrill.svg +1 -0
- package/dist/assets/Icons/map-pin.svg +1 -0
- package/dist/assets/Icons/maqsam-neutral.svg +1 -0
- package/dist/assets/Icons/maqsam.svg +1 -0
- package/dist/assets/Icons/mattermost-neutral.svg +1 -0
- package/dist/assets/Icons/mattermost.svg +1 -0
- package/dist/assets/Icons/maximize.svg +1 -0
- package/dist/assets/Icons/maximize2.svg +1 -0
- package/dist/assets/Icons/medium-neutral.svg +1 -0
- package/dist/assets/Icons/medium.svg +1 -0
- package/dist/assets/Icons/megaphone-off.svg +1 -0
- package/dist/assets/Icons/megaphone.svg +1 -0
- package/dist/assets/Icons/menu.svg +1 -0
- package/dist/assets/Icons/merge.svg +1 -0
- package/dist/assets/Icons/message-square-code.svg +1 -0
- package/dist/assets/Icons/message-square-dashed.svg +1 -0
- package/dist/assets/Icons/message-square-diff.svg +1 -0
- package/dist/assets/Icons/message-square-dot.svg +1 -0
- package/dist/assets/Icons/message-square-heart.svg +1 -0
- package/dist/assets/Icons/message-square-off.svg +1 -0
- package/dist/assets/Icons/message-square-plus.svg +1 -0
- package/dist/assets/Icons/message-square-quote.svg +1 -0
- package/dist/assets/Icons/message-square-reply.svg +1 -0
- package/dist/assets/Icons/message-square-share.svg +1 -0
- package/dist/assets/Icons/message-square-text.svg +1 -0
- package/dist/assets/Icons/message-square-warning.svg +1 -0
- package/dist/assets/Icons/message-square-x.svg +1 -0
- package/dist/assets/Icons/message-square.svg +1 -0
- package/dist/assets/Icons/messages-square.svg +1 -0
- package/dist/assets/Icons/messenger-neutral.svg +1 -0
- package/dist/assets/Icons/messenger.svg +1 -0
- package/dist/assets/Icons/microsoft-neutral.svg +1 -0
- package/dist/assets/Icons/microsoft-teams-neutral.svg +1 -0
- package/dist/assets/Icons/microsoft-teams.svg +1 -0
- package/dist/assets/Icons/microsoft.svg +1 -0
- package/dist/assets/Icons/minimize.svg +1 -0
- package/dist/assets/Icons/minimize2.svg +1 -0
- package/dist/assets/Icons/minus.svg +1 -0
- package/dist/assets/Icons/moon.svg +1 -0
- package/dist/assets/Icons/mouse-pointer-ban.svg +1 -0
- package/dist/assets/Icons/mouse-pointer-click.svg +1 -0
- package/dist/assets/Icons/mouse-pointer.svg +1 -0
- package/dist/assets/Icons/mouse-pointer2.svg +1 -0
- package/dist/assets/Icons/mouse.svg +1 -0
- package/dist/assets/Icons/move-diagonal.svg +1 -0
- package/dist/assets/Icons/move-diagonal2.svg +1 -0
- package/dist/assets/Icons/move-down-left.svg +1 -0
- package/dist/assets/Icons/move-down-right.svg +1 -0
- package/dist/assets/Icons/move-down.svg +1 -0
- package/dist/assets/Icons/move-horizontal.svg +1 -0
- package/dist/assets/Icons/move-left.svg +1 -0
- package/dist/assets/Icons/move-right.svg +1 -0
- package/dist/assets/Icons/move-up-left.svg +1 -0
- package/dist/assets/Icons/move-up-right.svg +1 -0
- package/dist/assets/Icons/move-up.svg +1 -0
- package/dist/assets/Icons/move-vertical.svg +1 -0
- package/dist/assets/Icons/move3-d.svg +1 -0
- package/dist/assets/Icons/netcore-neutral.svg +1 -0
- package/dist/assets/Icons/netcore.svg +1 -0
- package/dist/assets/Icons/notebook-pen.svg +1 -0
- package/dist/assets/Icons/notebook-tabs.svg +1 -0
- package/dist/assets/Icons/notebook-text.svg +1 -0
- package/dist/assets/Icons/notebook.svg +1 -0
- package/dist/assets/Icons/notepad-text-dashed.svg +1 -0
- package/dist/assets/Icons/notepad-text.svg +1 -0
- package/dist/assets/Icons/notion-neutral.svg +1 -0
- package/dist/assets/Icons/notion.svg +1 -0
- package/dist/assets/Icons/octagon-alert.svg +1 -0
- package/dist/assets/Icons/octagon-pause.svg +1 -0
- package/dist/assets/Icons/octagon-x.svg +1 -0
- package/dist/assets/Icons/octagon.svg +1 -0
- package/dist/assets/Icons/ok-neutral.svg +1 -0
- package/dist/assets/Icons/ok-only-sign-neutral.svg +1 -0
- package/dist/assets/Icons/ok-only-sign.svg +1 -0
- package/dist/assets/Icons/ok.svg +1 -0
- package/dist/assets/Icons/onlyfans-neutral.svg +1 -0
- package/dist/assets/Icons/onlyfans.svg +1 -0
- package/dist/assets/Icons/option.svg +1 -0
- package/dist/assets/Icons/outlook365-neutral.svg +1 -0
- package/dist/assets/Icons/outlook365.svg +1 -0
- package/dist/assets/Icons/paintbrush.svg +1 -0
- package/dist/assets/Icons/panel-bottom-open.svg +1 -0
- package/dist/assets/Icons/panel-bottom.svg +1 -0
- package/dist/assets/Icons/panel-left-close.svg +1 -0
- package/dist/assets/Icons/panel-left-dashed.svg +1 -0
- package/dist/assets/Icons/panel-left-open.svg +1 -0
- package/dist/assets/Icons/panel-left.svg +1 -0
- package/dist/assets/Icons/panel-right-animated.svg +1 -0
- package/dist/assets/Icons/panel-right-close.svg +1 -0
- package/dist/assets/Icons/panel-right-dashed.svg +1 -0
- package/dist/assets/Icons/panel-right-open.svg +1 -0
- package/dist/assets/Icons/panel-right.svg +1 -0
- package/dist/assets/Icons/panel-top-bottom-dashed.svg +1 -0
- package/dist/assets/Icons/panel-top-close.svg +1 -0
- package/dist/assets/Icons/panel-top-open.svg +1 -0
- package/dist/assets/Icons/panel-top.svg +1 -0
- package/dist/assets/Icons/panels-left-bottom.svg +1 -0
- package/dist/assets/Icons/panels-right-bottom.svg +1 -0
- package/dist/assets/Icons/panels-top-left.svg +1 -0
- package/dist/assets/Icons/paperclip.svg +1 -0
- package/dist/assets/Icons/patreon-neutral.svg +1 -0
- package/dist/assets/Icons/patreon.svg +1 -0
- package/dist/assets/Icons/paypal-neutral.svg +1 -0
- package/dist/assets/Icons/paypal.svg +1 -0
- package/dist/assets/Icons/pen-line.svg +1 -0
- package/dist/assets/Icons/pen-off.svg +1 -0
- package/dist/assets/Icons/pen-tool.svg +1 -0
- package/dist/assets/Icons/pen.svg +1 -0
- package/dist/assets/Icons/pencil-line.svg +1 -0
- package/dist/assets/Icons/pencil-off.svg +1 -0
- package/dist/assets/Icons/pencil-ruler.svg +1 -0
- package/dist/assets/Icons/pencil.svg +1 -0
- package/dist/assets/Icons/pentagon.svg +1 -0
- package/dist/assets/Icons/percentage.svg +1 -0
- package/dist/assets/Icons/phone.svg +1 -0
- package/dist/assets/Icons/pin-off.svg +1 -0
- package/dist/assets/Icons/pin.svg +1 -0
- package/dist/assets/Icons/pinterest-neutral.svg +1 -0
- package/dist/assets/Icons/pinterest.svg +1 -0
- package/dist/assets/Icons/play.svg +1 -0
- package/dist/assets/Icons/plug.svg +1 -0
- package/dist/assets/Icons/plunk-neutral.svg +1 -0
- package/dist/assets/Icons/plunk.svg +1 -0
- package/dist/assets/Icons/plus.svg +1 -0
- package/dist/assets/Icons/postmark-neutral.svg +1 -0
- package/dist/assets/Icons/postmark.svg +1 -0
- package/dist/assets/Icons/product-hunt-neutral.svg +1 -0
- package/dist/assets/Icons/product-hunt.svg +1 -0
- package/dist/assets/Icons/quora-neutral.svg +1 -0
- package/dist/assets/Icons/quora.svg +1 -0
- package/dist/assets/Icons/quote.svg +1 -0
- package/dist/assets/Icons/radar.svg +1 -0
- package/dist/assets/Icons/reddit-neutral.svg +1 -0
- package/dist/assets/Icons/reddit.svg +1 -0
- package/dist/assets/Icons/redo-dot.svg +1 -0
- package/dist/assets/Icons/redo.svg +1 -0
- package/dist/assets/Icons/redo2.svg +1 -0
- package/dist/assets/Icons/refresh-ccw.svg +1 -0
- package/dist/assets/Icons/refresh-cw-off.svg +1 -0
- package/dist/assets/Icons/resend-neutral.svg +1 -0
- package/dist/assets/Icons/resend.svg +1 -0
- package/dist/assets/Icons/rss.svg +1 -0
- package/dist/assets/Icons/rules.svg +1 -0
- package/dist/assets/Icons/scan-line.svg +1 -0
- package/dist/assets/Icons/scroll-text.svg +1 -0
- package/dist/assets/Icons/search-hint.svg +1 -0
- package/dist/assets/Icons/search-x.svg +1 -0
- package/dist/assets/Icons/search.svg +1 -0
- package/dist/assets/Icons/sendgrid-neutral.svg +1 -0
- package/dist/assets/Icons/sendgrid.svg +1 -0
- package/dist/assets/Icons/server.svg +1 -0
- package/dist/assets/Icons/ses-neutral.svg +1 -0
- package/dist/assets/Icons/ses.svg +1 -0
- package/dist/assets/Icons/settings.svg +1 -0
- package/dist/assets/Icons/settings2.svg +1 -0
- package/dist/assets/Icons/shapes.svg +1 -0
- package/dist/assets/Icons/share.svg +1 -0
- package/dist/assets/Icons/sheet.svg +1 -0
- package/dist/assets/Icons/shield-alert.svg +1 -0
- package/dist/assets/Icons/shield-ban.svg +1 -0
- package/dist/assets/Icons/shield-check.svg +1 -0
- package/dist/assets/Icons/shield-ellipsis.svg +1 -0
- package/dist/assets/Icons/shield-half.svg +1 -0
- package/dist/assets/Icons/shield-minus.svg +1 -0
- package/dist/assets/Icons/shield-off.svg +1 -0
- package/dist/assets/Icons/shield-plus.svg +1 -0
- package/dist/assets/Icons/shield-question.svg +1 -0
- package/dist/assets/Icons/shield-user.svg +1 -0
- package/dist/assets/Icons/shield-x.svg +1 -0
- package/dist/assets/Icons/shield.svg +1 -0
- package/dist/assets/Icons/shift.svg +1 -0
- package/dist/assets/Icons/signal-neutral.svg +1 -0
- package/dist/assets/Icons/signal.svg +1 -0
- package/dist/assets/Icons/signpost.svg +1 -0
- package/dist/assets/Icons/sina-weibo-neutral.svg +1 -0
- package/dist/assets/Icons/sina-weibo.svg +1 -0
- package/dist/assets/Icons/skull.svg +1 -0
- package/dist/assets/Icons/skype-neutral.svg +1 -0
- package/dist/assets/Icons/skype.svg +1 -0
- package/dist/assets/Icons/slack-neutral.svg +1 -0
- package/dist/assets/Icons/slack.svg +1 -0
- package/dist/assets/Icons/sliders-horizontal.svg +1 -0
- package/dist/assets/Icons/sliders-vertical.svg +1 -0
- package/dist/assets/Icons/smtp-neutral.svg +1 -0
- package/dist/assets/Icons/smtp.svg +1 -0
- package/dist/assets/Icons/snapchat-neutral.svg +1 -0
- package/dist/assets/Icons/snapchat.svg +1 -0
- package/dist/assets/Icons/soundcloud-neutral.svg +1 -0
- package/dist/assets/Icons/soundcloud.svg +1 -0
- package/dist/assets/Icons/space.svg +1 -0
- package/dist/assets/Icons/sparkpost-neutral.svg +1 -0
- package/dist/assets/Icons/sparkpost.svg +1 -0
- package/dist/assets/Icons/speed.svg +1 -0
- package/dist/assets/Icons/split.svg +1 -0
- package/dist/assets/Icons/spotify-neutral.svg +1 -0
- package/dist/assets/Icons/spotify.svg +1 -0
- package/dist/assets/Icons/square-arrow-out-up-right.svg +1 -0
- package/dist/assets/Icons/square-minus.svg +1 -0
- package/dist/assets/Icons/square-pen.svg +1 -0
- package/dist/assets/Icons/square-plus.svg +1 -0
- package/dist/assets/Icons/square-user-round.svg +1 -0
- package/dist/assets/Icons/stack-overflow-neutral.svg +1 -0
- package/dist/assets/Icons/stack-overflow.svg +1 -0
- package/dist/assets/Icons/star.svg +1 -0
- package/dist/assets/Icons/sun.svg +1 -0
- package/dist/assets/Icons/syringe.svg +1 -0
- package/dist/assets/Icons/tag.svg +1 -0
- package/dist/assets/Icons/target.svg +1 -0
- package/dist/assets/Icons/teams-neutral.svg +1 -0
- package/dist/assets/Icons/teams.svg +1 -0
- package/dist/assets/Icons/telegram-neutral.svg +1 -0
- package/dist/assets/Icons/telegram-only-sign-neutral.svg +1 -0
- package/dist/assets/Icons/telegram-only-sign.svg +1 -0
- package/dist/assets/Icons/telegram.svg +1 -0
- package/dist/assets/Icons/terminal.svg +1 -0
- package/dist/assets/Icons/test-policies.svg +1 -0
- package/dist/assets/Icons/threads-neutral.svg +1 -0
- package/dist/assets/Icons/threads.svg +1 -0
- package/dist/assets/Icons/thumbs-down.svg +1 -0
- package/dist/assets/Icons/thumbs-up.svg +1 -0
- package/dist/assets/Icons/tiktok-neutral.svg +1 -0
- package/dist/assets/Icons/tiktok.svg +1 -0
- package/dist/assets/Icons/tinder-neutral.svg +1 -0
- package/dist/assets/Icons/tinder.svg +1 -0
- package/dist/assets/Icons/trash.svg +1 -0
- package/dist/assets/Icons/trash2.svg +1 -0
- package/dist/assets/Icons/triangle-alert.svg +1 -0
- package/dist/assets/Icons/tumblr-neutral.svg +1 -0
- package/dist/assets/Icons/tumblr.svg +1 -0
- package/dist/assets/Icons/twitch-neutral.svg +1 -0
- package/dist/assets/Icons/twitch.svg +1 -0
- package/dist/assets/Icons/undo-dot.svg +1 -0
- package/dist/assets/Icons/undo.svg +1 -0
- package/dist/assets/Icons/undo2.svg +1 -0
- package/dist/assets/Icons/unplug.svg +1 -0
- package/dist/assets/Icons/user-check.svg +1 -0
- package/dist/assets/Icons/user-minus.svg +1 -0
- package/dist/assets/Icons/user-plus.svg +1 -0
- package/dist/assets/Icons/user-round-x.svg +1 -0
- package/dist/assets/Icons/user-round.svg +1 -0
- package/dist/assets/Icons/user.svg +1 -0
- package/dist/assets/Icons/username.svg +1 -0
- package/dist/assets/Icons/users-round.svg +1 -0
- package/dist/assets/Icons/users.svg +1 -0
- package/dist/assets/Icons/viber-neutral.svg +1 -0
- package/dist/assets/Icons/viber.svg +1 -0
- package/dist/assets/Icons/video.svg +1 -0
- package/dist/assets/Icons/vimeo-neutral.svg +1 -0
- package/dist/assets/Icons/vimeo.svg +1 -0
- package/dist/assets/Icons/vk-music-neutral.svg +1 -0
- package/dist/assets/Icons/vk-music.svg +1 -0
- package/dist/assets/Icons/vk-neutral.svg +1 -0
- package/dist/assets/Icons/vk-only-sign-neutral.svg +1 -0
- package/dist/assets/Icons/vk-only-sign.svg +1 -0
- package/dist/assets/Icons/vk.svg +1 -0
- package/dist/assets/Icons/webhook-neutral.svg +1 -0
- package/dist/assets/Icons/webhook.svg +1 -0
- package/dist/assets/Icons/wechat-neutral.svg +1 -0
- package/dist/assets/Icons/wechat.svg +1 -0
- package/dist/assets/Icons/whatsapp-badge-neutral.svg +1 -0
- package/dist/assets/Icons/whatsapp-badge.svg +1 -0
- package/dist/assets/Icons/whatsapp-neutral.svg +1 -0
- package/dist/assets/Icons/whatsapp.svg +1 -0
- package/dist/assets/Icons/workflow.svg +1 -0
- package/dist/assets/Icons/wrap-text.svg +1 -0
- package/dist/assets/Icons/wrench.svg +1 -0
- package/dist/assets/Icons/x-ex-twitter-neutral.svg +1 -0
- package/dist/assets/Icons/x-ex-twitter.svg +1 -0
- package/dist/assets/Icons/x.svg +1 -0
- package/dist/assets/Icons/xing-neutral.svg +1 -0
- package/dist/assets/Icons/xing.svg +1 -0
- package/dist/assets/Icons/yandex-music-neutral.svg +1 -0
- package/dist/assets/Icons/yandex-music.svg +1 -0
- package/dist/assets/Icons/yelp-neutral.svg +1 -0
- package/dist/assets/Icons/yelp.svg +1 -0
- package/dist/assets/Icons/youtube-music-neutral.svg +1 -0
- package/dist/assets/Icons/youtube-music.svg +1 -0
- package/dist/assets/Icons/youtube-neutral.svg +1 -0
- package/dist/assets/Icons/youtube-shorts-neutral.svg +1 -0
- package/dist/assets/Icons/youtube-shorts.svg +1 -0
- package/dist/assets/Icons/youtube.svg +1 -0
- package/dist/assets/Icons/zap.svg +1 -0
- package/dist/assets/Icons/zoom-in.svg +1 -0
- package/dist/assets/Icons/zoom-neutral.svg +1 -0
- package/dist/assets/Icons/zoom-out.svg +1 -0
- package/dist/assets/Icons/zoom.svg +1 -0
- package/dist/assets/Icons/zulip-neutral.svg +1 -0
- package/dist/assets/Icons/zulip.svg +1 -0
- package/dist/assets/Logos/wallarm.svg +1 -0
- package/dist/assets.json +4666 -0
- package/dist/project/README.md +265 -0
- package/dist/project/components/Accordion/README.md +354 -0
- package/dist/project/components/Accordion/preview.html +2 -0
- package/dist/project/components/Accordion/stories.js +12 -0
- package/dist/project/components/AgentAvatar/README.md +127 -0
- package/dist/project/components/AgentAvatar/preview.html +2 -0
- package/dist/project/components/AgentAvatar/stories.js +12 -0
- package/dist/project/components/AgentAvatar/stories.md +1805 -0
- package/dist/project/components/AgentGlyph/README.md +1182 -0
- package/dist/project/components/AgentGlyph/preview.html +2 -0
- package/dist/project/components/AgentGlyph/stories.js +12 -0
- package/dist/project/components/AgentLookBuilder/README.md +269 -0
- package/dist/project/components/AgentLookBuilder/preview.html +2 -0
- package/dist/project/components/AgentLookBuilder/stories.js +12 -0
- package/dist/project/components/Alert/README.md +492 -0
- package/dist/project/components/Alert/preview.html +2 -0
- package/dist/project/components/Alert/stories.js +12 -0
- package/dist/project/components/AnimatedBackground/README.md +124 -0
- package/dist/project/components/AnimatedBackground/preview.html +2 -0
- package/dist/project/components/AnimatedBackground/stories.js +12 -0
- package/dist/project/components/AppShell/README.md +75 -0
- package/dist/project/components/AppShell/preview.html +2 -0
- package/dist/project/components/AppShell/stories.js +28 -0
- package/dist/project/components/AppShell/stories.md +2878 -0
- package/dist/project/components/ApprovalCard/README.md +353 -0
- package/dist/project/components/ApprovalCard/preview.html +2 -0
- package/dist/project/components/ApprovalCard/stories.js +12 -0
- package/dist/project/components/AreaChart/README.md +673 -0
- package/dist/project/components/AreaChart/preview.html +2 -0
- package/dist/project/components/AreaChart/stories.js +12 -0
- package/dist/project/components/AssistantMessage/README.md +724 -0
- package/dist/project/components/AssistantMessage/preview.html +2 -0
- package/dist/project/components/AssistantMessage/stories.js +55 -0
- package/dist/project/components/Attribute/README.md +1174 -0
- package/dist/project/components/Attribute/preview.html +2 -0
- package/dist/project/components/Attribute/stories.js +12 -0
- package/dist/project/components/Avatar/README.md +416 -0
- package/dist/project/components/Avatar/preview.html +2 -0
- package/dist/project/components/Avatar/stories.js +12 -0
- package/dist/project/components/Badge/README.md +853 -0
- package/dist/project/components/Badge/preview.html +2 -0
- package/dist/project/components/Badge/stories.js +12 -0
- package/dist/project/components/Banner/README.md +341 -0
- package/dist/project/components/Banner/preview.html +2 -0
- package/dist/project/components/Banner/stories.js +12 -0
- package/dist/project/components/BarList/README.md +757 -0
- package/dist/project/components/BarList/preview.html +2 -0
- package/dist/project/components/BarList/stories.js +12 -0
- package/dist/project/components/Breadcrumbs/README.md +274 -0
- package/dist/project/components/Breadcrumbs/preview.html +2 -0
- package/dist/project/components/Breadcrumbs/stories.js +12 -0
- package/dist/project/components/BulkBar/README.md +19 -0
- package/dist/project/components/Button/README.md +467 -0
- package/dist/project/components/Button/preview.html +2 -0
- package/dist/project/components/Button/stories.js +12 -0
- package/dist/project/components/Calendar/README.md +654 -0
- package/dist/project/components/Calendar/preview.html +2 -0
- package/dist/project/components/Calendar/stories.js +12 -0
- package/dist/project/components/Card/README.md +367 -0
- package/dist/project/components/Card/preview.html +2 -0
- package/dist/project/components/Card/stories.js +12 -0
- package/dist/project/components/ChainOfThought/README.md +412 -0
- package/dist/project/components/ChainOfThought/preview.html +2 -0
- package/dist/project/components/ChainOfThought/stories.js +12 -0
- package/dist/project/components/Chart/README.md +224 -0
- package/dist/project/components/Chart/preview.html +2 -0
- package/dist/project/components/Chart/stories.js +12 -0
- package/dist/project/components/Chat/README.md +1244 -0
- package/dist/project/components/Chat/preview.html +2 -0
- package/dist/project/components/Chat/stories.js +12 -0
- package/dist/project/components/ChatInput/README.md +378 -0
- package/dist/project/components/ChatInput/preview.html +2 -0
- package/dist/project/components/ChatInput/stories.js +12 -0
- package/dist/project/components/ChatPermissions/README.md +218 -0
- package/dist/project/components/ChatPermissions/preview.html +2 -0
- package/dist/project/components/ChatPermissions/stories.js +12 -0
- package/dist/project/components/Checkbox/README.md +367 -0
- package/dist/project/components/Checkbox/preview.html +2 -0
- package/dist/project/components/Checkbox/stories.js +12 -0
- package/dist/project/components/Code/README.md +243 -0
- package/dist/project/components/Code/preview.html +2 -0
- package/dist/project/components/Code/stories.js +12 -0
- package/dist/project/components/CodeEditor/README.md +280 -0
- package/dist/project/components/CodeEditor/preview.html +2 -0
- package/dist/project/components/CodeEditor/stories.js +162 -0
- package/dist/project/components/CodeEditor/stories.md +1533 -0
- package/dist/project/components/CodeSnippet/README.md +1352 -0
- package/dist/project/components/CodeSnippet/preview.html +2 -0
- package/dist/project/components/CodeSnippet/stories.js +156 -0
- package/dist/project/components/ColumnChart/README.md +521 -0
- package/dist/project/components/ColumnChart/preview.html +2 -0
- package/dist/project/components/ColumnChart/stories.js +12 -0
- package/dist/project/components/Conversation/README.md +314 -0
- package/dist/project/components/Conversation/preview.html +2 -0
- package/dist/project/components/Conversation/stories.js +12 -0
- package/dist/project/components/Copyable/README.md +406 -0
- package/dist/project/components/Copyable/preview.html +2 -0
- package/dist/project/components/Copyable/stories.js +12 -0
- package/dist/project/components/Country/README.md +226 -0
- package/dist/project/components/Country/preview.html +2 -0
- package/dist/project/components/Country/stories.js +12 -0
- package/dist/project/components/Cover/preview.html +43 -0
- package/dist/project/components/DateInput/README.md +458 -0
- package/dist/project/components/DateInput/preview.html +2 -0
- package/dist/project/components/DateInput/stories.js +12 -0
- package/dist/project/components/DateRangeInput/README.md +412 -0
- package/dist/project/components/DateRangeInput/preview.html +2 -0
- package/dist/project/components/DateRangeInput/stories.js +12 -0
- package/dist/project/components/Dialog/README.md +1140 -0
- package/dist/project/components/Dialog/preview.html +2 -0
- package/dist/project/components/Dialog/stories.js +12 -0
- package/dist/project/components/Drawer/README.md +1163 -0
- package/dist/project/components/Drawer/preview.html +2 -0
- package/dist/project/components/Drawer/stories.js +12 -0
- package/dist/project/components/DropdownMenu/README.md +678 -0
- package/dist/project/components/DropdownMenu/preview.html +2 -0
- package/dist/project/components/DropdownMenu/stories.js +12 -0
- package/dist/project/components/EmptyState/README.md +276 -0
- package/dist/project/components/EmptyState/preview.html +2 -0
- package/dist/project/components/EmptyState/stories.js +12 -0
- package/dist/project/components/FeedbackPulse/README.md +125 -0
- package/dist/project/components/FeedbackPulse/preview.html +2 -0
- package/dist/project/components/FeedbackPulse/stories.js +12 -0
- package/dist/project/components/Field/README.md +676 -0
- package/dist/project/components/Field/preview.html +2 -0
- package/dist/project/components/Field/stories.js +12 -0
- package/dist/project/components/FileUpload/README.md +544 -0
- package/dist/project/components/FileUpload/preview.html +2 -0
- package/dist/project/components/FileUpload/stories.js +12 -0
- package/dist/project/components/FilterCascade/README.md +348 -0
- package/dist/project/components/FilterCascade/preview.html +2 -0
- package/dist/project/components/FilterCascade/stories.js +12 -0
- package/dist/project/components/FilterDropdown/README.md +542 -0
- package/dist/project/components/FilterDropdown/preview.html +2 -0
- package/dist/project/components/FilterDropdown/stories.js +12 -0
- package/dist/project/components/FilterInput/README.md +416 -0
- package/dist/project/components/FilterInput/preview.html +2 -0
- package/dist/project/components/FilterInput/stories.js +12 -0
- package/dist/project/components/FilterInput/stories.md +6682 -0
- package/dist/project/components/Flex/README.md +225 -0
- package/dist/project/components/Flex/preview.html +2 -0
- package/dist/project/components/Flex/stories.js +12 -0
- package/dist/project/components/FormatDateTime/README.md +315 -0
- package/dist/project/components/FormatDateTime/preview.html +2 -0
- package/dist/project/components/FormatDateTime/stories.js +12 -0
- package/dist/project/components/FormatNumber/README.md +317 -0
- package/dist/project/components/FormatNumber/preview.html +2 -0
- package/dist/project/components/FormatNumber/stories.js +12 -0
- package/dist/project/components/Heading/README.md +240 -0
- package/dist/project/components/Heading/preview.html +2 -0
- package/dist/project/components/Heading/stories.js +12 -0
- package/dist/project/components/HorizontalBarStack/README.md +281 -0
- package/dist/project/components/HorizontalBarStack/preview.html +2 -0
- package/dist/project/components/HorizontalBarStack/stories.js +12 -0
- package/dist/project/components/HttpMethod/README.md +137 -0
- package/dist/project/components/HttpMethod/preview.html +2 -0
- package/dist/project/components/HttpMethod/stories.js +12 -0
- package/dist/project/components/ImageCropper/README.md +332 -0
- package/dist/project/components/ImageCropper/preview.html +2 -0
- package/dist/project/components/ImageCropper/stories.js +33 -0
- package/dist/project/components/Indicator/README.md +110 -0
- package/dist/project/components/Indicator/preview.html +2 -0
- package/dist/project/components/Indicator/stories.js +12 -0
- package/dist/project/components/InlineEdit/README.md +977 -0
- package/dist/project/components/InlineEdit/preview.html +2 -0
- package/dist/project/components/InlineEdit/stories.js +12 -0
- package/dist/project/components/Input/README.md +187 -0
- package/dist/project/components/Input/preview.html +2 -0
- package/dist/project/components/Input/stories.js +12 -0
- package/dist/project/components/InputGroup/README.md +423 -0
- package/dist/project/components/InputGroup/preview.html +2 -0
- package/dist/project/components/InputGroup/stories.js +12 -0
- package/dist/project/components/InputOTP/README.md +201 -0
- package/dist/project/components/InputOTP/preview.html +2 -0
- package/dist/project/components/InputOTP/stories.js +12 -0
- package/dist/project/components/Ip/README.md +226 -0
- package/dist/project/components/Ip/preview.html +2 -0
- package/dist/project/components/Ip/stories.js +12 -0
- package/dist/project/components/Kbd/README.md +126 -0
- package/dist/project/components/Kbd/preview.html +2 -0
- package/dist/project/components/Kbd/stories.js +12 -0
- package/dist/project/components/LineChart/README.md +1479 -0
- package/dist/project/components/LineChart/preview.html +2 -0
- package/dist/project/components/LineChart/stories.js +12 -0
- package/dist/project/components/Link/README.md +160 -0
- package/dist/project/components/Link/preview.html +2 -0
- package/dist/project/components/Link/stories.js +12 -0
- package/dist/project/components/List/README.md +181 -0
- package/dist/project/components/List/preview.html +2 -0
- package/dist/project/components/List/stories.js +12 -0
- package/dist/project/components/Loader/README.md +145 -0
- package/dist/project/components/Loader/preview.html +2 -0
- package/dist/project/components/Loader/stories.js +12 -0
- package/dist/project/components/Logo/README.md +183 -0
- package/dist/project/components/Logo/preview.html +2 -0
- package/dist/project/components/Logo/stories.js +12 -0
- package/dist/project/components/MessageActions/README.md +255 -0
- package/dist/project/components/MessageActions/preview.html +2 -0
- package/dist/project/components/MessageActions/stories.js +12 -0
- package/dist/project/components/Metric/README.md +324 -0
- package/dist/project/components/Metric/preview.html +2 -0
- package/dist/project/components/Metric/stories.js +12 -0
- package/dist/project/components/NavRail/README.md +25 -0
- package/dist/project/components/NotificationCenter/README.md +91 -0
- package/dist/project/components/NotificationCenter/preview.html +2 -0
- package/dist/project/components/NotificationCenter/stories.js +12 -0
- package/dist/project/components/NotificationCenter/stories.md +2170 -0
- package/dist/project/components/NumberInput/README.md +177 -0
- package/dist/project/components/NumberInput/preview.html +2 -0
- package/dist/project/components/NumberInput/stories.js +12 -0
- package/dist/project/components/NumericBadge/README.md +252 -0
- package/dist/project/components/NumericBadge/preview.html +2 -0
- package/dist/project/components/NumericBadge/stories.js +12 -0
- package/dist/project/components/OverflowList/README.md +324 -0
- package/dist/project/components/OverflowList/preview.html +2 -0
- package/dist/project/components/OverflowList/stories.js +12 -0
- package/dist/project/components/OverflowTooltip/README.md +421 -0
- package/dist/project/components/OverflowTooltip/preview.html +2 -0
- package/dist/project/components/OverflowTooltip/stories.js +12 -0
- package/dist/project/components/Overlay/README.md +95 -0
- package/dist/project/components/Overlay/preview.html +2 -0
- package/dist/project/components/Overlay/stories.js +12 -0
- package/dist/project/components/Overview/README.md +445 -0
- package/dist/project/components/Overview/preview.html +2 -0
- package/dist/project/components/Overview/stories.js +12 -0
- package/dist/project/components/Page/README.md +215 -0
- package/dist/project/components/Page/preview.html +2 -0
- package/dist/project/components/Page/stories.js +12 -0
- package/dist/project/components/Pagination/README.md +302 -0
- package/dist/project/components/Pagination/preview.html +2 -0
- package/dist/project/components/Pagination/stories.js +12 -0
- package/dist/project/components/ParameterPath/README.md +284 -0
- package/dist/project/components/ParameterPath/preview.html +2 -0
- package/dist/project/components/ParameterPath/stories.js +12 -0
- package/dist/project/components/PasswordComplexity/README.md +171 -0
- package/dist/project/components/PasswordComplexity/preview.html +2 -0
- package/dist/project/components/PasswordComplexity/stories.js +12 -0
- package/dist/project/components/PasswordInput/README.md +254 -0
- package/dist/project/components/PasswordInput/preview.html +2 -0
- package/dist/project/components/PasswordInput/stories.js +12 -0
- package/dist/project/components/PieChart/README.md +895 -0
- package/dist/project/components/PieChart/preview.html +2 -0
- package/dist/project/components/PieChart/stories.js +12 -0
- package/dist/project/components/Popover/README.md +282 -0
- package/dist/project/components/Popover/preview.html +2 -0
- package/dist/project/components/Popover/stories.js +12 -0
- package/dist/project/components/Progress/README.md +174 -0
- package/dist/project/components/Progress/preview.html +2 -0
- package/dist/project/components/Progress/stories.js +12 -0
- package/dist/project/components/Radio/README.md +264 -0
- package/dist/project/components/Radio/preview.html +2 -0
- package/dist/project/components/Radio/stories.js +12 -0
- package/dist/project/components/RemoteShell/README.md +1758 -0
- package/dist/project/components/RemoteShell/preview.html +2 -0
- package/dist/project/components/RemoteShell/stories.js +28 -0
- package/dist/project/components/Resizable/README.md +290 -0
- package/dist/project/components/Resizable/preview.html +2 -0
- package/dist/project/components/Resizable/stories.js +12 -0
- package/dist/project/components/ResponseCode/README.md +205 -0
- package/dist/project/components/ResponseCode/preview.html +2 -0
- package/dist/project/components/ResponseCode/stories.js +12 -0
- package/dist/project/components/ScrollArea/README.md +234 -0
- package/dist/project/components/ScrollArea/preview.html +2 -0
- package/dist/project/components/ScrollArea/stories.js +12 -0
- package/dist/project/components/SearchInput/README.md +158 -0
- package/dist/project/components/SearchInput/preview.html +2 -0
- package/dist/project/components/SearchInput/stories.js +12 -0
- package/dist/project/components/SearchModal/README.md +836 -0
- package/dist/project/components/SearchModal/preview.html +2 -0
- package/dist/project/components/SearchModal/stories.js +12 -0
- package/dist/project/components/SegmentedControl/README.md +382 -0
- package/dist/project/components/SegmentedControl/preview.html +2 -0
- package/dist/project/components/SegmentedControl/stories.js +12 -0
- package/dist/project/components/SegmentedTabs/README.md +390 -0
- package/dist/project/components/SegmentedTabs/preview.html +2 -0
- package/dist/project/components/SegmentedTabs/stories.js +12 -0
- package/dist/project/components/Select/README.md +1311 -0
- package/dist/project/components/Select/preview.html +2 -0
- package/dist/project/components/Select/stories.js +12 -0
- package/dist/project/components/Selection/README.md +648 -0
- package/dist/project/components/Selection/preview.html +2 -0
- package/dist/project/components/Selection/stories.js +12 -0
- package/dist/project/components/Separator/README.md +77 -0
- package/dist/project/components/Separator/preview.html +2 -0
- package/dist/project/components/Separator/stories.js +12 -0
- package/dist/project/components/Skeleton/README.md +358 -0
- package/dist/project/components/Skeleton/preview.html +2 -0
- package/dist/project/components/Skeleton/stories.js +12 -0
- package/dist/project/components/Slider/README.md +433 -0
- package/dist/project/components/Slider/preview.html +2 -0
- package/dist/project/components/Slider/stories.js +12 -0
- package/dist/project/components/SplashScreen/README.md +192 -0
- package/dist/project/components/SplashScreen/preview.html +2 -0
- package/dist/project/components/SplashScreen/stories.js +12 -0
- package/dist/project/components/SplitButton/README.md +402 -0
- package/dist/project/components/SplitButton/preview.html +2 -0
- package/dist/project/components/SplitButton/stories.js +12 -0
- package/dist/project/components/Stack/README.md +269 -0
- package/dist/project/components/Stack/preview.html +2 -0
- package/dist/project/components/Stack/stories.js +12 -0
- package/dist/project/components/Stepper/README.md +682 -0
- package/dist/project/components/Stepper/preview.html +2 -0
- package/dist/project/components/Stepper/stories.js +12 -0
- package/dist/project/components/Switch/README.md +236 -0
- package/dist/project/components/Switch/preview.html +2 -0
- package/dist/project/components/Switch/stories.js +12 -0
- package/dist/project/components/Table/README.md +471 -0
- package/dist/project/components/Table/preview.html +2 -0
- package/dist/project/components/Table/stories.js +12 -0
- package/dist/project/components/Table/stories.md +3697 -0
- package/dist/project/components/Tabs/README.md +443 -0
- package/dist/project/components/Tabs/preview.html +2 -0
- package/dist/project/components/Tabs/stories.js +12 -0
- package/dist/project/components/Tag/README.md +324 -0
- package/dist/project/components/Tag/preview.html +2 -0
- package/dist/project/components/Tag/stories.js +12 -0
- package/dist/project/components/Text/README.md +200 -0
- package/dist/project/components/Text/preview.html +2 -0
- package/dist/project/components/Text/stories.js +12 -0
- package/dist/project/components/Textarea/README.md +273 -0
- package/dist/project/components/Textarea/preview.html +2 -0
- package/dist/project/components/Textarea/stories.js +12 -0
- package/dist/project/components/TimeInput/README.md +359 -0
- package/dist/project/components/TimeInput/preview.html +2 -0
- package/dist/project/components/TimeInput/stories.js +12 -0
- package/dist/project/components/Timeline/README.md +204 -0
- package/dist/project/components/Timeline/preview.html +2 -0
- package/dist/project/components/Timeline/stories.js +12 -0
- package/dist/project/components/Toast/README.md +718 -0
- package/dist/project/components/Toast/preview.html +2 -0
- package/dist/project/components/Toast/stories.js +12 -0
- package/dist/project/components/ToggleButton/README.md +292 -0
- package/dist/project/components/ToggleButton/preview.html +2 -0
- package/dist/project/components/ToggleButton/stories.js +12 -0
- package/dist/project/components/Tooltip/README.md +199 -0
- package/dist/project/components/Tooltip/preview.html +2 -0
- package/dist/project/components/Tooltip/stories.js +12 -0
- package/dist/project/components/TopHeader/README.md +21 -0
- package/dist/project/components/Tour/README.md +532 -0
- package/dist/project/components/Tour/preview.html +2 -0
- package/dist/project/components/Tour/stories.js +12 -0
- package/dist/project/components/Tree/README.md +450 -0
- package/dist/project/components/Tree/preview.html +2 -0
- package/dist/project/components/Tree/stories.js +12 -0
- package/dist/project/components/TreeView/README.md +531 -0
- package/dist/project/components/TreeView/preview.html +2 -0
- package/dist/project/components/TreeView/stories.js +12 -0
- package/dist/project/components/UTILITIES.md +647 -0
- package/dist/project/components/UserMessage/README.md +166 -0
- package/dist/project/components/UserMessage/preview.html +2 -0
- package/dist/project/components/UserMessage/stories.js +12 -0
- package/dist/project/components/UtilityPage/README.md +147 -0
- package/dist/project/components/UtilityPage/preview.html +2 -0
- package/dist/project/components/UtilityPage/stories.js +12 -0
- package/dist/project/components/WallyAssistant/README.md +1380 -0
- package/dist/project/components/WallyAssistant/preview.html +2 -0
- package/dist/project/components/WallyAssistant/stories.js +12 -0
- package/dist/project/components/WallyIcon/README.md +130 -0
- package/dist/project/components/WallyIcon/preview.html +2 -0
- package/dist/project/components/WallyIcon/stories.js +12 -0
- package/dist/project/components/WallySkeleton/README.md +96 -0
- package/dist/project/components/WallySkeleton/preview.html +2 -0
- package/dist/project/components/WallySkeleton/stories.js +12 -0
- package/dist/project/components/bundle.css +18734 -0
- package/dist/project/components/bundle.js +167 -0
- package/dist/project/components/index.d.ts +27226 -0
- package/dist/project/design-system.json +35 -0
- package/dist/project/fonts/Geist-Variable.woff2 +0 -0
- package/dist/project/fonts/GeistMono-Variable.woff2 +0 -0
- package/dist/project/fonts/GeistPixel-Square.woff2 +0 -0
- package/dist/project/sampler.dc.html +238 -0
- package/dist/project/tokens.css +1395 -0
- package/dist/project/tokens.json +5235 -0
- package/dist/wallarm-sampler.dc.html +239 -0
- package/package.json +67 -3
|
@@ -0,0 +1,1479 @@
|
|
|
1
|
+
A time series in the family's card — request volume, error rate, latency, anything where the X axis reads left to right; reach for `BarList` for a top-N comparison and `PieChart` for a share of a total. Every part is an opt-in child, so a bare sparkline and a fully instrumented panel are the same component with different children, and hover, filtering and zoom all travel through one context.
|
|
2
|
+
|
|
3
|
+
## Props as canvas attributes
|
|
4
|
+
|
|
5
|
+
Use kebab-case attribute names. Pass non-string values through renderVals holes, including booleans. The full emitted API is in `components/index.d.ts`.
|
|
6
|
+
|
|
7
|
+
| Attribute | Type | Required | Default | Description |
|
|
8
|
+
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `data` | `T[]` | yes | — | Long-form data array, one entry per X position. |
|
|
10
|
+
| `series` | `complex` | yes | — | Schema describing each line drawn from `data`. |
|
|
11
|
+
| `x-key` | `Extract<keyof T, string>` | yes | — | Key on each datum used as the X-axis value. Required — a silent fallback would hide key-name typos until the chart renders empty. |
|
|
12
|
+
| `active-key` | `string \| null \| undefined` | no | — | Controlled hover key — pass alongside `onActiveKeyChange` for cross-chart sync. **Heads-up:** if the controlled value points at a series key that no longer exists in `series` (filter, schema change, refresh), the chart pushes `null` back through `onActiveKeyChange` so sibling charts stop highlighting a stale key. If you wire `activeKey` to external state, the snap-to-null write will arrive as a normal state change — do not be surprised when your value resets after a series disappears. |
|
|
13
|
+
| `on-active-key-change` | `((key: string \| null) => void) \| undefined` | no | — | |
|
|
14
|
+
| `filtered-keys` | `string[] \| undefined` | no | — | Controlled set of `series.key` values to hide from the plot. |
|
|
15
|
+
| `on-zoom-change` | `complex` | no | — | Fired after the user confirms a brush selection. |
|
|
16
|
+
| `sync-id` | `string \| number \| undefined` | no | — | Charts that share a `syncId` synchronise their tooltip cursor and brush via recharts' built-in middleware — hovering one chart highlights the matching X on every sibling chart with the same id. Pair with `activeKey` + `onActiveKeyChange` if you also want the *series* highlight to sync. |
|
|
17
|
+
| `sync-method` | `complex` | no | — | How sibling `syncId` charts match X positions. Defaults to `'index'` (Recharts' default). Use `'value'` when the synced charts have different dataset lengths but share categorical X values. |
|
|
18
|
+
| `default-checked` | `boolean \| undefined` | no | — | |
|
|
19
|
+
| `default-value` | `string \| number \| readonly string[] \| undefined` | no | — | |
|
|
20
|
+
| `auto-focus` | `boolean \| undefined` | no | — | |
|
|
21
|
+
| `id` | `string \| undefined` | no | — | |
|
|
22
|
+
| `tab-index` | `number \| undefined` | no | — | |
|
|
23
|
+
| `title` | `string \| undefined` | no | — | |
|
|
24
|
+
| `rel` | `string \| undefined` | no | — | |
|
|
25
|
+
| `on-change` | `ChangeEventHandler<T, Element> \| undefined` | no | — | |
|
|
26
|
+
| `data-testid` | `string \| undefined` | no | — | |
|
|
27
|
+
|
|
28
|
+
## Sub-components
|
|
29
|
+
|
|
30
|
+
- `WallarmDS.LineChartBody` — `LineChartBodyProps` in the declaration bundle.
|
|
31
|
+
- `WallarmDS.LineChartEmpty` — `LineChartEmptyProps` in the declaration bundle.
|
|
32
|
+
- `WallarmDS.LineChartGrid` — `LineChartGridProps` in the declaration bundle.
|
|
33
|
+
- `WallarmDS.LineChartHoverPopoverDot` — `LineChartHoverPopoverDotProps` in the declaration bundle.
|
|
34
|
+
- `WallarmDS.LineChartHoverPopover` — `LineChartHoverPopoverProps` in the declaration bundle.
|
|
35
|
+
- `WallarmDS.LineChartHoverPopoverRow` — `LineChartHoverPopoverRowProps` in the declaration bundle.
|
|
36
|
+
- `WallarmDS.LineChartHoverPopoverTimestamp` — `LineChartHoverPopoverTimestampProps` in the declaration bundle.
|
|
37
|
+
- `WallarmDS.LineChartLegendItem` — `LineChartLegendItemProps` in the declaration bundle.
|
|
38
|
+
- `WallarmDS.LineChartLegend` — `LineChartLegendProps` in the declaration bundle.
|
|
39
|
+
- `WallarmDS.LineChartLine` — `LineChartLineProps` in the declaration bundle.
|
|
40
|
+
- `WallarmDS.LineChartTooltip` — `LineChartTooltipProps` in the declaration bundle.
|
|
41
|
+
- `WallarmDS.LineChartXAxis` — `LineChartXAxisProps` in the declaration bundle.
|
|
42
|
+
- `WallarmDS.LineChartYAxis` — `LineChartYAxisProps` in the declaration bundle.
|
|
43
|
+
- `WallarmDS.LineChartZoomBrush` — `LineChartZoomBrushProps` in the declaration bundle.
|
|
44
|
+
- `WallarmDS.LineChartZoomPopoverConfirm` — `LineChartZoomPopoverConfirmProps` in the declaration bundle.
|
|
45
|
+
- `WallarmDS.LineChartZoomPopover` — `LineChartZoomPopoverProps` in the declaration bundle.
|
|
46
|
+
- `WallarmDS.LineChartZoomPopoverRange` — `LineChartZoomPopoverRangeProps` in the declaration bundle.
|
|
47
|
+
|
|
48
|
+
## Stories
|
|
49
|
+
|
|
50
|
+
### Default
|
|
51
|
+
|
|
52
|
+
One series with the full chrome — grid, both axes, and a tooltip that follows the pointer
|
|
53
|
+
along the line.
|
|
54
|
+
|
|
55
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Default
|
|
56
|
+
|
|
57
|
+
### DefaultMulti
|
|
58
|
+
|
|
59
|
+
Three series with a legend composed from `LineChartLegendItem` rows. The dot in each row is
|
|
60
|
+
the same one the tooltip uses, so the colours cannot drift apart.
|
|
61
|
+
|
|
62
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#DefaultMulti
|
|
63
|
+
|
|
64
|
+
### WithMetric
|
|
65
|
+
|
|
66
|
+
The metric variant: the shared `Metric` bricks sit to the left of the legend in a row of
|
|
67
|
+
their own between the header and the plot. Pure composition — the chart is untouched and the
|
|
68
|
+
card simply grows by that row.
|
|
69
|
+
|
|
70
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#WithMetric
|
|
71
|
+
|
|
72
|
+
### Curves
|
|
73
|
+
|
|
74
|
+
Straight joins tell the truth about where the samples are; `monotone` smooths between them
|
|
75
|
+
and reads better for a rate. Mix the two only when the series mean genuinely different
|
|
76
|
+
things.
|
|
77
|
+
|
|
78
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Curves
|
|
79
|
+
|
|
80
|
+
### LineStyling
|
|
81
|
+
|
|
82
|
+
A dashed series against a solid one — the way to separate a threshold or a projection from
|
|
83
|
+
measured data — and a CSS colour string for a series whose colour is decided elsewhere.
|
|
84
|
+
|
|
85
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#LineStyling
|
|
86
|
+
|
|
87
|
+
### EdgeCases
|
|
88
|
+
|
|
89
|
+
The three shapes that break naive charts: a sparkline with no chrome at all, a single data
|
|
90
|
+
point, and a series with null gaps, which has to break the line rather than bridge it.
|
|
91
|
+
|
|
92
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#EdgeCases
|
|
93
|
+
|
|
94
|
+
### CustomTooltip
|
|
95
|
+
|
|
96
|
+
Composing the hover popover yourself, a `LineChartHoverPopoverRow` per series, for when a
|
|
97
|
+
value needs its unit rather than the default name-and-number.
|
|
98
|
+
|
|
99
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#CustomTooltip
|
|
100
|
+
|
|
101
|
+
### LegendPlacements
|
|
102
|
+
|
|
103
|
+
Legend placement is structural rather than a prop: JSX order picks top or bottom, and
|
|
104
|
+
wrapping the body and the legend in an `HStack` picks left or right, where a vertical
|
|
105
|
+
orientation stacks its rows.
|
|
106
|
+
|
|
107
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#LegendPlacements
|
|
108
|
+
|
|
109
|
+
### Filterable
|
|
110
|
+
|
|
111
|
+
Clicking a legend row isolates that series and clicking another adds it back, with the
|
|
112
|
+
header's clear control appearing while anything is hidden.
|
|
113
|
+
|
|
114
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Filterable
|
|
115
|
+
|
|
116
|
+
### CrossChartHoverSync
|
|
117
|
+
|
|
118
|
+
Two cards sharing a pointer, and it takes two mechanisms: `syncId` lines up the cursor and
|
|
119
|
+
tooltip through recharts, while `activeKey` shares the series highlight through our own
|
|
120
|
+
context.
|
|
121
|
+
|
|
122
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#CrossChartHoverSync
|
|
123
|
+
|
|
124
|
+
### Zoom
|
|
125
|
+
|
|
126
|
+
Drag across the plot to choose a range, then confirm in the popover — Enter or the button
|
|
127
|
+
emits `onZoomChange`, while Escape, an outside click or a new drag dismisses it. Slicing the
|
|
128
|
+
data to that range is yours, and so is the way back out.
|
|
129
|
+
|
|
130
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Zoom
|
|
131
|
+
|
|
132
|
+
### Loading
|
|
133
|
+
|
|
134
|
+
There is no `loading` prop: the state is composed from the same primitives as a populated
|
|
135
|
+
chart — `Skeleton` chips inside the legend and a bare `LineChartEmpty` for the dashed plot —
|
|
136
|
+
with `aria-busy` on the `Chart` left to the caller.
|
|
137
|
+
|
|
138
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Loading
|
|
139
|
+
|
|
140
|
+
### Refreshing
|
|
141
|
+
|
|
142
|
+
Each panel loads for two seconds before swapping to data, and the refresh button replays it.
|
|
143
|
+
The skeleton and the real chart share an outer layout, so nothing but the content moves on
|
|
144
|
+
the swap.
|
|
145
|
+
|
|
146
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Refreshing
|
|
147
|
+
|
|
148
|
+
### Empty
|
|
149
|
+
|
|
150
|
+
`LineChartEmpty` keeps the dashed plot frame and puts the message inside it, so a card with
|
|
151
|
+
no data still reads as a chart rather than as something broken.
|
|
152
|
+
|
|
153
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#Empty
|
|
154
|
+
|
|
155
|
+
### LongTimeRange
|
|
156
|
+
|
|
157
|
+
A thousand hourly samples in one card: drag to zoom and the header's control restores the
|
|
158
|
+
full range. The story slices the data itself, exactly as a consumer has to.
|
|
159
|
+
|
|
160
|
+
Source: SimpleCharts/LineChart/LineChart.stories.tsx#LongTimeRange
|
|
161
|
+
|
|
162
|
+
## Story sources
|
|
163
|
+
|
|
164
|
+
### SimpleCharts/LineChart/LineChart.stories.tsx
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
168
|
+
import type { Meta, StoryFn } from 'storybook-react-rsbuild';
|
|
169
|
+
import { FilterX, RefreshCcw, ZoomOut } from '../../../icons';
|
|
170
|
+
import { formatFullNumber } from '../../../utils/abbreviateNumber';
|
|
171
|
+
import { Button } from '../../Button';
|
|
172
|
+
import { Skeleton } from '../../Skeleton';
|
|
173
|
+
import { HStack } from '../../Stack';
|
|
174
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '../../Tooltip';
|
|
175
|
+
import { Chart } from '../Chart/Chart';
|
|
176
|
+
import { ChartActions } from '../Chart/ChartActions';
|
|
177
|
+
import { ChartHeader } from '../Chart/ChartHeader';
|
|
178
|
+
import { ChartTitle } from '../Chart/ChartTitle';
|
|
179
|
+
import { useChartTimeFormatters } from '../hooks/useChartTimeFormatters';
|
|
180
|
+
import { MetricDelta } from '../Metric/MetricDelta';
|
|
181
|
+
import { MetricHeader } from '../Metric/MetricHeader';
|
|
182
|
+
import { MetricValue } from '../Metric/MetricValue';
|
|
183
|
+
import { LineChart } from './LineChart';
|
|
184
|
+
import { LineChartBody } from './LineChartBody';
|
|
185
|
+
import type { LineChartSeries, LineChartZoomRange } from './LineChartContext';
|
|
186
|
+
import { LineChartEmpty } from './LineChartEmpty';
|
|
187
|
+
import { LineChartGrid } from './LineChartGrid';
|
|
188
|
+
import { LineChartHoverPopover } from './LineChartHoverPopover';
|
|
189
|
+
import { LineChartHoverPopoverDot } from './LineChartHoverPopoverDot';
|
|
190
|
+
import { LineChartHoverPopoverRow } from './LineChartHoverPopoverRow';
|
|
191
|
+
import { LineChartHoverPopoverTimestamp } from './LineChartHoverPopoverTimestamp';
|
|
192
|
+
import { LineChartLegend } from './LineChartLegend';
|
|
193
|
+
import { LineChartLegendItem } from './LineChartLegendItem';
|
|
194
|
+
import { LineChartLine } from './LineChartLine';
|
|
195
|
+
import { LineChartTooltip } from './LineChartTooltip';
|
|
196
|
+
import { LineChartXAxis } from './LineChartXAxis';
|
|
197
|
+
import { LineChartYAxis } from './LineChartYAxis';
|
|
198
|
+
import { LineChartZoomBrush } from './LineChartZoomBrush';
|
|
199
|
+
import { formatRange } from './lib/formatRange';
|
|
200
|
+
import {
|
|
201
|
+
customColorSeries,
|
|
202
|
+
dailyData60,
|
|
203
|
+
dashedSeries,
|
|
204
|
+
dataWithErrorGaps,
|
|
205
|
+
hourlyData24,
|
|
206
|
+
hourlyData1000,
|
|
207
|
+
hourlyDataA,
|
|
208
|
+
hourlyDataB,
|
|
209
|
+
multiSeries,
|
|
210
|
+
singlePointData,
|
|
211
|
+
singleSeries,
|
|
212
|
+
unitsByKey,
|
|
213
|
+
} from './lib/sampleData';
|
|
214
|
+
|
|
215
|
+
const formatYTick = (value: unknown) => formatFullNumber(Number(value));
|
|
216
|
+
|
|
217
|
+
const DESCRIPTION = [
|
|
218
|
+
"A time series in the family's card — request volume, error rate, latency, anything where the X axis reads left to right; reach for `BarList` for a top-N comparison and `PieChart` for a share of a total.",
|
|
219
|
+
'Every part is an opt-in child, so a bare sparkline and a fully instrumented panel are the same component with different children, and hover, filtering and zoom all travel through one context.',
|
|
220
|
+
].join(' ');
|
|
221
|
+
|
|
222
|
+
const meta = {
|
|
223
|
+
title: 'Data Display/SimpleCharts/LineChart',
|
|
224
|
+
component: LineChart,
|
|
225
|
+
subcomponents: {
|
|
226
|
+
LineChartBody,
|
|
227
|
+
LineChartGrid,
|
|
228
|
+
LineChartXAxis,
|
|
229
|
+
LineChartYAxis,
|
|
230
|
+
LineChartLine,
|
|
231
|
+
LineChartTooltip,
|
|
232
|
+
LineChartHoverPopover,
|
|
233
|
+
LineChartHoverPopoverTimestamp,
|
|
234
|
+
LineChartHoverPopoverRow,
|
|
235
|
+
LineChartHoverPopoverDot,
|
|
236
|
+
LineChartLegend,
|
|
237
|
+
LineChartLegendItem,
|
|
238
|
+
LineChartZoomBrush,
|
|
239
|
+
LineChartEmpty,
|
|
240
|
+
},
|
|
241
|
+
parameters: {
|
|
242
|
+
layout: 'padded',
|
|
243
|
+
design: {
|
|
244
|
+
type: 'figma',
|
|
245
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=7490-123142&m=dev',
|
|
246
|
+
},
|
|
247
|
+
docs: { description: { component: DESCRIPTION } },
|
|
248
|
+
},
|
|
249
|
+
tags: ['autodocs'],
|
|
250
|
+
} satisfies Meta<typeof LineChart>;
|
|
251
|
+
|
|
252
|
+
export default meta;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* One series with the full chrome — grid, both axes, and a tooltip that follows the pointer
|
|
256
|
+
* along the line.
|
|
257
|
+
*/
|
|
258
|
+
export const Default: StoryFn<typeof meta> = () => {
|
|
259
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
260
|
+
return (
|
|
261
|
+
<div className='w-560'>
|
|
262
|
+
<Chart>
|
|
263
|
+
<ChartHeader>
|
|
264
|
+
<ChartTitle>Requests per hour</ChartTitle>
|
|
265
|
+
</ChartHeader>
|
|
266
|
+
<LineChart data={hourlyData24} series={singleSeries} xKey='timestamp'>
|
|
267
|
+
<LineChartBody>
|
|
268
|
+
<LineChartGrid />
|
|
269
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
270
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
271
|
+
<LineChartLine seriesKey='requests' curve='linear' />
|
|
272
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
273
|
+
</LineChartBody>
|
|
274
|
+
</LineChart>
|
|
275
|
+
</Chart>
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
Default.parameters = {
|
|
281
|
+
design: {
|
|
282
|
+
type: 'figma',
|
|
283
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=7490-123143&m=dev',
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Three series with a legend composed from `LineChartLegendItem` rows. The dot in each row is
|
|
289
|
+
* the same one the tooltip uses, so the colours cannot drift apart.
|
|
290
|
+
*/
|
|
291
|
+
export const DefaultMulti: StoryFn<typeof meta> = () => {
|
|
292
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
293
|
+
return (
|
|
294
|
+
<div className='w-560'>
|
|
295
|
+
<Chart data-testid='chart'>
|
|
296
|
+
<ChartHeader>
|
|
297
|
+
<ChartTitle>Traffic, errors, and latency</ChartTitle>
|
|
298
|
+
</ChartHeader>
|
|
299
|
+
<LineChart
|
|
300
|
+
data-testid='line-chart'
|
|
301
|
+
data={hourlyData24}
|
|
302
|
+
series={multiSeries}
|
|
303
|
+
xKey='timestamp'
|
|
304
|
+
>
|
|
305
|
+
<LineChartLegend>
|
|
306
|
+
{multiSeries.map(s => (
|
|
307
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
308
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
309
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
310
|
+
</LineChartLegendItem>
|
|
311
|
+
))}
|
|
312
|
+
</LineChartLegend>
|
|
313
|
+
<LineChartBody>
|
|
314
|
+
<LineChartGrid />
|
|
315
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
316
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
317
|
+
{multiSeries.map(s => (
|
|
318
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
319
|
+
))}
|
|
320
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
321
|
+
</LineChartBody>
|
|
322
|
+
</LineChart>
|
|
323
|
+
</Chart>
|
|
324
|
+
</div>
|
|
325
|
+
);
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
DefaultMulti.parameters = {
|
|
329
|
+
design: {
|
|
330
|
+
type: 'figma',
|
|
331
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=7509-2355&m=dev',
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const MultiLegend = ({ series = multiSeries }: { series?: LineChartSeries[] }) => (
|
|
336
|
+
<LineChartLegend>
|
|
337
|
+
{series.map(s => (
|
|
338
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
339
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
340
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
341
|
+
</LineChartLegendItem>
|
|
342
|
+
))}
|
|
343
|
+
</LineChartLegend>
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* The metric variant: the shared `Metric` bricks sit to the left of the legend in a row of
|
|
348
|
+
* their own between the header and the plot. Pure composition — the chart is untouched and the
|
|
349
|
+
* card simply grows by that row.
|
|
350
|
+
*/
|
|
351
|
+
export const WithMetric: StoryFn<typeof meta> = () => {
|
|
352
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
353
|
+
return (
|
|
354
|
+
<div className='w-800'>
|
|
355
|
+
<Chart>
|
|
356
|
+
<ChartHeader>
|
|
357
|
+
<ChartTitle>Requests per hour</ChartTitle>
|
|
358
|
+
</ChartHeader>
|
|
359
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
360
|
+
<div className='flex items-center justify-between pr-8'>
|
|
361
|
+
<MetricHeader className='px-16'>
|
|
362
|
+
<MetricValue>{2903}</MetricValue>
|
|
363
|
+
<MetricDelta value={10} trend='up' sentiment='negative' />
|
|
364
|
+
</MetricHeader>
|
|
365
|
+
<MultiLegend />
|
|
366
|
+
</div>
|
|
367
|
+
<LineChartBody>
|
|
368
|
+
<LineChartGrid />
|
|
369
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
370
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
371
|
+
{multiSeries.map(s => (
|
|
372
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
373
|
+
))}
|
|
374
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
375
|
+
</LineChartBody>
|
|
376
|
+
</LineChart>
|
|
377
|
+
</Chart>
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
WithMetric.parameters = {
|
|
383
|
+
design: {
|
|
384
|
+
type: 'figma',
|
|
385
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=11626-37312',
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Straight joins tell the truth about where the samples are; `monotone` smooths between them
|
|
391
|
+
* and reads better for a rate. Mix the two only when the series mean genuinely different
|
|
392
|
+
* things.
|
|
393
|
+
*/
|
|
394
|
+
export const Curves: StoryFn<typeof meta> = () => {
|
|
395
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
396
|
+
return (
|
|
397
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
398
|
+
<Chart>
|
|
399
|
+
<ChartHeader>
|
|
400
|
+
<ChartTitle>Linear interpolation</ChartTitle>
|
|
401
|
+
</ChartHeader>
|
|
402
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
403
|
+
<MultiLegend />
|
|
404
|
+
<LineChartBody>
|
|
405
|
+
<LineChartGrid />
|
|
406
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
407
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
408
|
+
{multiSeries.map(s => (
|
|
409
|
+
<LineChartLine key={s.key} seriesKey={s.key} curve='linear' />
|
|
410
|
+
))}
|
|
411
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
412
|
+
</LineChartBody>
|
|
413
|
+
</LineChart>
|
|
414
|
+
</Chart>
|
|
415
|
+
|
|
416
|
+
<Chart>
|
|
417
|
+
<ChartHeader>
|
|
418
|
+
<ChartTitle>Mixed curves — monotone vs linear</ChartTitle>
|
|
419
|
+
</ChartHeader>
|
|
420
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
421
|
+
<MultiLegend />
|
|
422
|
+
<LineChartBody>
|
|
423
|
+
<LineChartGrid />
|
|
424
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
425
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
426
|
+
<LineChartLine seriesKey='requests' curve='monotone' />
|
|
427
|
+
<LineChartLine seriesKey='errors' curve='linear' />
|
|
428
|
+
<LineChartLine seriesKey='latency' curve='linear' />
|
|
429
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
430
|
+
</LineChartBody>
|
|
431
|
+
</LineChart>
|
|
432
|
+
</Chart>
|
|
433
|
+
</div>
|
|
434
|
+
);
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* A dashed series against a solid one — the way to separate a threshold or a projection from
|
|
439
|
+
* measured data — and a CSS colour string for a series whose colour is decided elsewhere.
|
|
440
|
+
*/
|
|
441
|
+
export const LineStyling: StoryFn<typeof meta> = () => {
|
|
442
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
443
|
+
return (
|
|
444
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
445
|
+
<Chart>
|
|
446
|
+
<ChartHeader>
|
|
447
|
+
<ChartTitle>Solid + dashed series</ChartTitle>
|
|
448
|
+
</ChartHeader>
|
|
449
|
+
<LineChart data={hourlyData24} series={dashedSeries} xKey='timestamp'>
|
|
450
|
+
<MultiLegend series={dashedSeries} />
|
|
451
|
+
<LineChartBody>
|
|
452
|
+
<LineChartGrid />
|
|
453
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
454
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
455
|
+
{dashedSeries.map(s => (
|
|
456
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
457
|
+
))}
|
|
458
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
459
|
+
</LineChartBody>
|
|
460
|
+
</LineChart>
|
|
461
|
+
</Chart>
|
|
462
|
+
|
|
463
|
+
<Chart>
|
|
464
|
+
<ChartHeader>
|
|
465
|
+
<ChartTitle>Custom palette via CSS color string</ChartTitle>
|
|
466
|
+
</ChartHeader>
|
|
467
|
+
<LineChart data={hourlyData24} series={customColorSeries} xKey='timestamp'>
|
|
468
|
+
<MultiLegend series={customColorSeries} />
|
|
469
|
+
<LineChartBody>
|
|
470
|
+
<LineChartGrid />
|
|
471
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
472
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
473
|
+
{customColorSeries.map(s => (
|
|
474
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
475
|
+
))}
|
|
476
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
477
|
+
</LineChartBody>
|
|
478
|
+
</LineChart>
|
|
479
|
+
</Chart>
|
|
480
|
+
</div>
|
|
481
|
+
);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* The three shapes that break naive charts: a sparkline with no chrome at all, a single data
|
|
486
|
+
* point, and a series with null gaps, which has to break the line rather than bridge it.
|
|
487
|
+
*/
|
|
488
|
+
export const EdgeCases: StoryFn<typeof meta> = () => {
|
|
489
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
490
|
+
return (
|
|
491
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
492
|
+
<Chart>
|
|
493
|
+
<ChartHeader>
|
|
494
|
+
<ChartTitle>Sparkline — no chrome</ChartTitle>
|
|
495
|
+
</ChartHeader>
|
|
496
|
+
<LineChart data={hourlyData24} series={singleSeries} xKey='timestamp'>
|
|
497
|
+
<LineChartBody>
|
|
498
|
+
<LineChartLine seriesKey='requests' />
|
|
499
|
+
</LineChartBody>
|
|
500
|
+
</LineChart>
|
|
501
|
+
</Chart>
|
|
502
|
+
|
|
503
|
+
<Chart>
|
|
504
|
+
<ChartHeader>
|
|
505
|
+
<ChartTitle>Single data point</ChartTitle>
|
|
506
|
+
</ChartHeader>
|
|
507
|
+
<LineChart data={singlePointData} series={singleSeries} xKey='timestamp'>
|
|
508
|
+
<LineChartBody>
|
|
509
|
+
<LineChartGrid />
|
|
510
|
+
<LineChartXAxis tickFormatter={formatHour} />
|
|
511
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
512
|
+
<LineChartLine seriesKey='requests' />
|
|
513
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
514
|
+
</LineChartBody>
|
|
515
|
+
</LineChart>
|
|
516
|
+
</Chart>
|
|
517
|
+
|
|
518
|
+
<Chart>
|
|
519
|
+
<ChartHeader>
|
|
520
|
+
<ChartTitle>Series with null gaps</ChartTitle>
|
|
521
|
+
</ChartHeader>
|
|
522
|
+
<LineChart data={dataWithErrorGaps} series={multiSeries} xKey='timestamp'>
|
|
523
|
+
<MultiLegend />
|
|
524
|
+
<LineChartBody>
|
|
525
|
+
<LineChartGrid />
|
|
526
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
527
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
528
|
+
{multiSeries.map(s => (
|
|
529
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
530
|
+
))}
|
|
531
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
532
|
+
</LineChartBody>
|
|
533
|
+
</LineChart>
|
|
534
|
+
</Chart>
|
|
535
|
+
</div>
|
|
536
|
+
);
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Composing the hover popover yourself, a `LineChartHoverPopoverRow` per series, for when a
|
|
541
|
+
* value needs its unit rather than the default name-and-number.
|
|
542
|
+
*/
|
|
543
|
+
export const CustomTooltip: StoryFn<typeof meta> = () => {
|
|
544
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
545
|
+
return (
|
|
546
|
+
<div className='w-560'>
|
|
547
|
+
<Chart>
|
|
548
|
+
<ChartHeader>
|
|
549
|
+
<ChartTitle>Custom tooltip with units</ChartTitle>
|
|
550
|
+
</ChartHeader>
|
|
551
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
552
|
+
<LineChartLegend>
|
|
553
|
+
{multiSeries.map(s => (
|
|
554
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
555
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
556
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
557
|
+
</LineChartLegendItem>
|
|
558
|
+
))}
|
|
559
|
+
</LineChartLegend>
|
|
560
|
+
<LineChartBody>
|
|
561
|
+
<LineChartGrid />
|
|
562
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
563
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
564
|
+
{multiSeries.map(s => (
|
|
565
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
566
|
+
))}
|
|
567
|
+
<LineChartTooltip>
|
|
568
|
+
{({ rows, xValue }) => (
|
|
569
|
+
<LineChartHoverPopover>
|
|
570
|
+
<LineChartHoverPopoverTimestamp>
|
|
571
|
+
{formatHourWithTimezone(xValue)}
|
|
572
|
+
</LineChartHoverPopoverTimestamp>
|
|
573
|
+
{rows.map(({ series: s, value: raw }) => {
|
|
574
|
+
const value = typeof raw === 'number' ? raw : 0;
|
|
575
|
+
const unit = unitsByKey[s.key] ?? '';
|
|
576
|
+
return (
|
|
577
|
+
<LineChartHoverPopoverRow
|
|
578
|
+
key={s.key}
|
|
579
|
+
series={s}
|
|
580
|
+
value={value}
|
|
581
|
+
formatValue={v =>
|
|
582
|
+
`${typeof v === 'number' ? formatFullNumber(v) : String(v ?? '')}${unit}`
|
|
583
|
+
}
|
|
584
|
+
/>
|
|
585
|
+
);
|
|
586
|
+
})}
|
|
587
|
+
</LineChartHoverPopover>
|
|
588
|
+
)}
|
|
589
|
+
</LineChartTooltip>
|
|
590
|
+
</LineChartBody>
|
|
591
|
+
</LineChart>
|
|
592
|
+
</Chart>
|
|
593
|
+
</div>
|
|
594
|
+
);
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Legend placement is structural rather than a prop: JSX order picks top or bottom, and
|
|
599
|
+
* wrapping the body and the legend in an `HStack` picks left or right, where a vertical
|
|
600
|
+
* orientation stacks its rows.
|
|
601
|
+
*/
|
|
602
|
+
export const LegendPlacements: StoryFn<typeof meta> = () => {
|
|
603
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
604
|
+
return (
|
|
605
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
606
|
+
<Chart>
|
|
607
|
+
<ChartHeader>
|
|
608
|
+
<ChartTitle>Top — JSX order</ChartTitle>
|
|
609
|
+
</ChartHeader>
|
|
610
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
611
|
+
<LineChartLegend>
|
|
612
|
+
{multiSeries.map(s => (
|
|
613
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
614
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
615
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
616
|
+
</LineChartLegendItem>
|
|
617
|
+
))}
|
|
618
|
+
</LineChartLegend>
|
|
619
|
+
<LineChartBody>
|
|
620
|
+
<LineChartGrid />
|
|
621
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
622
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
623
|
+
{multiSeries.map(s => (
|
|
624
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
625
|
+
))}
|
|
626
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
627
|
+
</LineChartBody>
|
|
628
|
+
</LineChart>
|
|
629
|
+
</Chart>
|
|
630
|
+
|
|
631
|
+
<Chart>
|
|
632
|
+
<ChartHeader>
|
|
633
|
+
<ChartTitle>Bottom — JSX order</ChartTitle>
|
|
634
|
+
</ChartHeader>
|
|
635
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
636
|
+
<LineChartBody>
|
|
637
|
+
<LineChartGrid />
|
|
638
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
639
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
640
|
+
{multiSeries.map(s => (
|
|
641
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
642
|
+
))}
|
|
643
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
644
|
+
</LineChartBody>
|
|
645
|
+
<LineChartLegend>
|
|
646
|
+
{multiSeries.map(s => (
|
|
647
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
648
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
649
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
650
|
+
</LineChartLegendItem>
|
|
651
|
+
))}
|
|
652
|
+
</LineChartLegend>
|
|
653
|
+
</LineChart>
|
|
654
|
+
</Chart>
|
|
655
|
+
|
|
656
|
+
<Chart>
|
|
657
|
+
<ChartHeader>
|
|
658
|
+
<ChartTitle>Left — wrapped in HStack</ChartTitle>
|
|
659
|
+
</ChartHeader>
|
|
660
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
661
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
662
|
+
<LineChartLegend orientation='vertical'>
|
|
663
|
+
{multiSeries.map(s => (
|
|
664
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
665
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
666
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
667
|
+
</LineChartLegendItem>
|
|
668
|
+
))}
|
|
669
|
+
</LineChartLegend>
|
|
670
|
+
<LineChartBody>
|
|
671
|
+
<LineChartGrid />
|
|
672
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
673
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
674
|
+
{multiSeries.map(s => (
|
|
675
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
676
|
+
))}
|
|
677
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
678
|
+
</LineChartBody>
|
|
679
|
+
</HStack>
|
|
680
|
+
</LineChart>
|
|
681
|
+
</Chart>
|
|
682
|
+
|
|
683
|
+
<Chart>
|
|
684
|
+
<ChartHeader>
|
|
685
|
+
<ChartTitle>Right — wrapped in HStack</ChartTitle>
|
|
686
|
+
</ChartHeader>
|
|
687
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
688
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
689
|
+
<LineChartBody>
|
|
690
|
+
<LineChartGrid />
|
|
691
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
692
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
693
|
+
{multiSeries.map(s => (
|
|
694
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
695
|
+
))}
|
|
696
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
697
|
+
</LineChartBody>
|
|
698
|
+
<LineChartLegend orientation='vertical'>
|
|
699
|
+
{multiSeries.map(s => (
|
|
700
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
701
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
702
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
703
|
+
</LineChartLegendItem>
|
|
704
|
+
))}
|
|
705
|
+
</LineChartLegend>
|
|
706
|
+
</HStack>
|
|
707
|
+
</LineChart>
|
|
708
|
+
</Chart>
|
|
709
|
+
</div>
|
|
710
|
+
);
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
LegendPlacements.parameters = {
|
|
714
|
+
layout: 'padded',
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Clicking a legend row isolates that series and clicking another adds it back, with the
|
|
719
|
+
* header's clear control appearing while anything is hidden.
|
|
720
|
+
*/
|
|
721
|
+
export const Filterable: StoryFn<typeof meta> = () => {
|
|
722
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
723
|
+
const [hidden, setHidden] = useState<string[]>([]);
|
|
724
|
+
// First click on a fully-visible chart isolates the clicked series (hides
|
|
725
|
+
// every other one); after that, clicks toggle individual series in and out.
|
|
726
|
+
const toggle = (key: string) => {
|
|
727
|
+
setHidden(prev => {
|
|
728
|
+
if (prev.length === 0) return multiSeries.filter(s => s.key !== key).map(s => s.key);
|
|
729
|
+
if (prev.includes(key)) return prev.filter(k => k !== key);
|
|
730
|
+
return [...prev, key];
|
|
731
|
+
});
|
|
732
|
+
};
|
|
733
|
+
const filtered = hidden.length > 0;
|
|
734
|
+
|
|
735
|
+
return (
|
|
736
|
+
<div className='w-560'>
|
|
737
|
+
<Chart data-testid='chart'>
|
|
738
|
+
<ChartHeader>
|
|
739
|
+
<ChartTitle>Click a row to isolate, click another to add</ChartTitle>
|
|
740
|
+
<ChartActions alwaysVisible={filtered}>
|
|
741
|
+
{filtered && (
|
|
742
|
+
<Tooltip>
|
|
743
|
+
<TooltipTrigger asChild>
|
|
744
|
+
<Button
|
|
745
|
+
variant='ghost'
|
|
746
|
+
color='neutral'
|
|
747
|
+
size='small'
|
|
748
|
+
aria-label='Clear filter'
|
|
749
|
+
onClick={() => setHidden([])}
|
|
750
|
+
>
|
|
751
|
+
<FilterX />
|
|
752
|
+
</Button>
|
|
753
|
+
</TooltipTrigger>
|
|
754
|
+
<TooltipContent>Remove filter</TooltipContent>
|
|
755
|
+
</Tooltip>
|
|
756
|
+
)}
|
|
757
|
+
</ChartActions>
|
|
758
|
+
</ChartHeader>
|
|
759
|
+
<LineChart
|
|
760
|
+
data-testid='line-chart'
|
|
761
|
+
data={hourlyData24}
|
|
762
|
+
series={multiSeries}
|
|
763
|
+
xKey='timestamp'
|
|
764
|
+
filteredKeys={hidden}
|
|
765
|
+
>
|
|
766
|
+
<LineChartLegend>
|
|
767
|
+
{multiSeries.map(s => (
|
|
768
|
+
<Tooltip key={s.key}>
|
|
769
|
+
<TooltipTrigger asChild>
|
|
770
|
+
<LineChartLegendItem seriesKey={s.key} onClick={() => toggle(s.key)}>
|
|
771
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
772
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
773
|
+
</LineChartLegendItem>
|
|
774
|
+
</TooltipTrigger>
|
|
775
|
+
<TooltipContent>
|
|
776
|
+
{hidden.includes(s.key) ? 'Remove filter' : 'Click to filter'}
|
|
777
|
+
</TooltipContent>
|
|
778
|
+
</Tooltip>
|
|
779
|
+
))}
|
|
780
|
+
</LineChartLegend>
|
|
781
|
+
<LineChartBody>
|
|
782
|
+
<LineChartGrid />
|
|
783
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
784
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
785
|
+
{multiSeries.map(s => (
|
|
786
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
787
|
+
))}
|
|
788
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
789
|
+
</LineChartBody>
|
|
790
|
+
</LineChart>
|
|
791
|
+
</Chart>
|
|
792
|
+
</div>
|
|
793
|
+
);
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Two cards sharing a pointer, and it takes two mechanisms: `syncId` lines up the cursor and
|
|
798
|
+
* tooltip through recharts, while `activeKey` shares the series highlight through our own
|
|
799
|
+
* context.
|
|
800
|
+
*/
|
|
801
|
+
export const CrossChartHoverSync: StoryFn<typeof meta> = () => {
|
|
802
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
803
|
+
// `syncId` syncs the *cursor X* (tooltip + brush) via recharts' own redux
|
|
804
|
+
// middleware. `activeKey` + `onActiveKeyChange` sync the *series highlight*
|
|
805
|
+
// (line dimming + legend hover) via our context. The two pair cleanly —
|
|
806
|
+
// each owns the surface it controls and neither reinvents the other.
|
|
807
|
+
const [activeKey, setActiveKey] = useState<string | null>(null);
|
|
808
|
+
|
|
809
|
+
return (
|
|
810
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
811
|
+
<Chart>
|
|
812
|
+
<ChartHeader>
|
|
813
|
+
<ChartTitle>Region A</ChartTitle>
|
|
814
|
+
</ChartHeader>
|
|
815
|
+
<LineChart
|
|
816
|
+
data={hourlyDataA}
|
|
817
|
+
series={multiSeries}
|
|
818
|
+
xKey='timestamp'
|
|
819
|
+
syncId='regions'
|
|
820
|
+
activeKey={activeKey}
|
|
821
|
+
onActiveKeyChange={setActiveKey}
|
|
822
|
+
>
|
|
823
|
+
<LineChartLegend>
|
|
824
|
+
{multiSeries.map(s => (
|
|
825
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
826
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
827
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
828
|
+
</LineChartLegendItem>
|
|
829
|
+
))}
|
|
830
|
+
</LineChartLegend>
|
|
831
|
+
<LineChartBody>
|
|
832
|
+
<LineChartGrid />
|
|
833
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
834
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
835
|
+
{multiSeries.map(s => (
|
|
836
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
837
|
+
))}
|
|
838
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
839
|
+
</LineChartBody>
|
|
840
|
+
</LineChart>
|
|
841
|
+
</Chart>
|
|
842
|
+
|
|
843
|
+
<Chart>
|
|
844
|
+
<ChartHeader>
|
|
845
|
+
<ChartTitle>Region B</ChartTitle>
|
|
846
|
+
</ChartHeader>
|
|
847
|
+
<LineChart
|
|
848
|
+
data={hourlyDataB}
|
|
849
|
+
series={multiSeries}
|
|
850
|
+
xKey='timestamp'
|
|
851
|
+
syncId='regions'
|
|
852
|
+
activeKey={activeKey}
|
|
853
|
+
onActiveKeyChange={setActiveKey}
|
|
854
|
+
>
|
|
855
|
+
<LineChartLegend>
|
|
856
|
+
{multiSeries.map(s => (
|
|
857
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
858
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
859
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
860
|
+
</LineChartLegendItem>
|
|
861
|
+
))}
|
|
862
|
+
</LineChartLegend>
|
|
863
|
+
<LineChartBody>
|
|
864
|
+
<LineChartGrid />
|
|
865
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
866
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
867
|
+
{multiSeries.map(s => (
|
|
868
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
869
|
+
))}
|
|
870
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
871
|
+
</LineChartBody>
|
|
872
|
+
</LineChart>
|
|
873
|
+
</Chart>
|
|
874
|
+
</div>
|
|
875
|
+
);
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
const ZoomControlledChart = () => {
|
|
879
|
+
const { formatDate, formatDateWithTimezone } = useChartTimeFormatters();
|
|
880
|
+
const [visibleData, setVisibleData] = useState(dailyData60);
|
|
881
|
+
const handleZoom = useCallback((range: LineChartZoomRange | null) => {
|
|
882
|
+
if (!range) {
|
|
883
|
+
setVisibleData(dailyData60);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
setVisibleData(prev => prev.slice(range.fromIndex, range.toIndex + 1));
|
|
887
|
+
}, []);
|
|
888
|
+
const isZoomed = visibleData !== dailyData60;
|
|
889
|
+
// Daily data — time is always 00:00 so the zoom popover renders date-only.
|
|
890
|
+
const formatDateOnlyRange = useMemo(() => formatRange(formatDate), [formatDate]);
|
|
891
|
+
|
|
892
|
+
const chartRef = useRef<HTMLDivElement>(null);
|
|
893
|
+
|
|
894
|
+
useEffect(() => {
|
|
895
|
+
if (!isZoomed) return;
|
|
896
|
+
|
|
897
|
+
const handleKey = (event: KeyboardEvent) => {
|
|
898
|
+
if (event.key !== 'Escape') return;
|
|
899
|
+
const target = event.target;
|
|
900
|
+
const isAmbient =
|
|
901
|
+
target === null || target === document.body || target === document.documentElement;
|
|
902
|
+
const isInChart = target instanceof Node && chartRef.current?.contains(target);
|
|
903
|
+
if (!isAmbient && !isInChart) return;
|
|
904
|
+
event.preventDefault();
|
|
905
|
+
handleZoom(null);
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
window.addEventListener('keydown', handleKey);
|
|
909
|
+
|
|
910
|
+
return () => window.removeEventListener('keydown', handleKey);
|
|
911
|
+
}, [isZoomed, handleZoom]);
|
|
912
|
+
|
|
913
|
+
return (
|
|
914
|
+
<Chart ref={chartRef} data-testid='chart'>
|
|
915
|
+
<ChartHeader>
|
|
916
|
+
<ChartTitle>Drag on the plot, then click "Zoom in" — Esc to cancel</ChartTitle>
|
|
917
|
+
<ChartActions alwaysVisible={isZoomed}>
|
|
918
|
+
{isZoomed && (
|
|
919
|
+
<Tooltip>
|
|
920
|
+
<TooltipTrigger asChild>
|
|
921
|
+
<Button
|
|
922
|
+
variant='ghost'
|
|
923
|
+
color='neutral'
|
|
924
|
+
size='small'
|
|
925
|
+
aria-label='Reset time selection'
|
|
926
|
+
onClick={() => handleZoom(null)}
|
|
927
|
+
>
|
|
928
|
+
<ZoomOut />
|
|
929
|
+
</Button>
|
|
930
|
+
</TooltipTrigger>
|
|
931
|
+
<TooltipContent>Reset time selection</TooltipContent>
|
|
932
|
+
</Tooltip>
|
|
933
|
+
)}
|
|
934
|
+
</ChartActions>
|
|
935
|
+
</ChartHeader>
|
|
936
|
+
<LineChart
|
|
937
|
+
data-testid='line-chart'
|
|
938
|
+
data={visibleData}
|
|
939
|
+
series={multiSeries}
|
|
940
|
+
xKey='timestamp'
|
|
941
|
+
onZoomChange={handleZoom}
|
|
942
|
+
>
|
|
943
|
+
<MultiLegend />
|
|
944
|
+
<LineChartBody height={220}>
|
|
945
|
+
<LineChartGrid />
|
|
946
|
+
<LineChartXAxis tickFormatter={formatDate} minTickGap={48} />
|
|
947
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
948
|
+
{multiSeries.map(s => (
|
|
949
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
950
|
+
))}
|
|
951
|
+
<LineChartTooltip xTickFormatter={formatDateWithTimezone} />
|
|
952
|
+
<LineChartZoomBrush formatRange={formatDateOnlyRange} />
|
|
953
|
+
</LineChartBody>
|
|
954
|
+
</LineChart>
|
|
955
|
+
</Chart>
|
|
956
|
+
);
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Drag across the plot to choose a range, then confirm in the popover — Enter or the button
|
|
961
|
+
* emits `onZoomChange`, while Escape, an outside click or a new drag dismisses it. Slicing the
|
|
962
|
+
* data to that range is yours, and so is the way back out.
|
|
963
|
+
*/
|
|
964
|
+
export const Zoom: StoryFn<typeof meta> = () => (
|
|
965
|
+
<div className='w-560'>
|
|
966
|
+
<ZoomControlledChart />
|
|
967
|
+
</div>
|
|
968
|
+
);
|
|
969
|
+
|
|
970
|
+
const LoadingLegend = ({ orientation }: { orientation?: 'horizontal' | 'vertical' }) => (
|
|
971
|
+
<LineChartLegend orientation={orientation}>
|
|
972
|
+
{[0, 1, 2].map(i => (
|
|
973
|
+
<LineChartLegendItem key={i} seriesKey={`skeleton-${i}`}>
|
|
974
|
+
<Skeleton width='72px' height='20px' rounded={4} />
|
|
975
|
+
</LineChartLegendItem>
|
|
976
|
+
))}
|
|
977
|
+
</LineChartLegend>
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* There is no `loading` prop: the state is composed from the same primitives as a populated
|
|
982
|
+
* chart — `Skeleton` chips inside the legend and a bare `LineChartEmpty` for the dashed plot —
|
|
983
|
+
* with `aria-busy` on the `Chart` left to the caller.
|
|
984
|
+
*/
|
|
985
|
+
export const Loading: StoryFn<typeof meta> = () => (
|
|
986
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
987
|
+
<Chart aria-busy='true' aria-live='polite'>
|
|
988
|
+
<ChartHeader>
|
|
989
|
+
<ChartTitle>No legend</ChartTitle>
|
|
990
|
+
</ChartHeader>
|
|
991
|
+
<LineChartEmpty />
|
|
992
|
+
</Chart>
|
|
993
|
+
|
|
994
|
+
<Chart aria-busy='true' aria-live='polite'>
|
|
995
|
+
<ChartHeader>
|
|
996
|
+
<ChartTitle>Top — JSX order</ChartTitle>
|
|
997
|
+
</ChartHeader>
|
|
998
|
+
<LoadingLegend />
|
|
999
|
+
<LineChartEmpty />
|
|
1000
|
+
</Chart>
|
|
1001
|
+
|
|
1002
|
+
<Chart aria-busy='true' aria-live='polite'>
|
|
1003
|
+
<ChartHeader>
|
|
1004
|
+
<ChartTitle>Bottom — JSX order</ChartTitle>
|
|
1005
|
+
</ChartHeader>
|
|
1006
|
+
<LineChartEmpty />
|
|
1007
|
+
<LoadingLegend />
|
|
1008
|
+
</Chart>
|
|
1009
|
+
|
|
1010
|
+
<Chart aria-busy='true' aria-live='polite'>
|
|
1011
|
+
<ChartHeader>
|
|
1012
|
+
<ChartTitle>Left — wrapped in HStack</ChartTitle>
|
|
1013
|
+
</ChartHeader>
|
|
1014
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
1015
|
+
<LoadingLegend orientation='vertical' />
|
|
1016
|
+
<LineChartEmpty className='flex-1 min-w-0' />
|
|
1017
|
+
</HStack>
|
|
1018
|
+
</Chart>
|
|
1019
|
+
|
|
1020
|
+
<Chart aria-busy='true' aria-live='polite'>
|
|
1021
|
+
<ChartHeader>
|
|
1022
|
+
<ChartTitle>Right — wrapped in HStack</ChartTitle>
|
|
1023
|
+
</ChartHeader>
|
|
1024
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
1025
|
+
<LineChartEmpty className='flex-1 min-w-0' />
|
|
1026
|
+
<LoadingLegend orientation='vertical' />
|
|
1027
|
+
</HStack>
|
|
1028
|
+
</Chart>
|
|
1029
|
+
</div>
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
Loading.parameters = {
|
|
1033
|
+
design: {
|
|
1034
|
+
type: 'figma',
|
|
1035
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=7519-2617&m=dev',
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
type RefreshingPlacement = 'none' | 'top' | 'bottom' | 'left' | 'right';
|
|
1040
|
+
|
|
1041
|
+
const RefreshingChart = ({
|
|
1042
|
+
placement,
|
|
1043
|
+
title,
|
|
1044
|
+
}: {
|
|
1045
|
+
placement: RefreshingPlacement;
|
|
1046
|
+
title: string;
|
|
1047
|
+
}) => {
|
|
1048
|
+
const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
|
|
1049
|
+
const [loading, setLoading] = useState(true);
|
|
1050
|
+
|
|
1051
|
+
useEffect(() => {
|
|
1052
|
+
if (!loading) return;
|
|
1053
|
+
const id = setTimeout(() => setLoading(false), 2000);
|
|
1054
|
+
return () => clearTimeout(id);
|
|
1055
|
+
}, [loading]);
|
|
1056
|
+
|
|
1057
|
+
const isSide = placement === 'left' || placement === 'right';
|
|
1058
|
+
const orientation = isSide ? 'vertical' : 'horizontal';
|
|
1059
|
+
|
|
1060
|
+
const legend = loading ? (
|
|
1061
|
+
<LoadingLegend orientation={orientation} />
|
|
1062
|
+
) : (
|
|
1063
|
+
<LineChartLegend orientation={orientation}>
|
|
1064
|
+
{multiSeries.map(s => (
|
|
1065
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
1066
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
1067
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
1068
|
+
</LineChartLegendItem>
|
|
1069
|
+
))}
|
|
1070
|
+
</LineChartLegend>
|
|
1071
|
+
);
|
|
1072
|
+
|
|
1073
|
+
const body = loading ? (
|
|
1074
|
+
<LineChartEmpty className={isSide ? 'flex-1 min-w-0' : undefined} />
|
|
1075
|
+
) : (
|
|
1076
|
+
<LineChartBody>
|
|
1077
|
+
<LineChartGrid />
|
|
1078
|
+
<LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
|
|
1079
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
1080
|
+
{multiSeries.map(s => (
|
|
1081
|
+
<LineChartLine key={s.key} seriesKey={s.key} />
|
|
1082
|
+
))}
|
|
1083
|
+
<LineChartTooltip xTickFormatter={formatHourWithTimezone} />
|
|
1084
|
+
</LineChartBody>
|
|
1085
|
+
);
|
|
1086
|
+
|
|
1087
|
+
let inner: ReactNode;
|
|
1088
|
+
if (placement === 'none') {
|
|
1089
|
+
inner = body;
|
|
1090
|
+
} else if (placement === 'top') {
|
|
1091
|
+
inner = (
|
|
1092
|
+
<>
|
|
1093
|
+
{legend}
|
|
1094
|
+
{body}
|
|
1095
|
+
</>
|
|
1096
|
+
);
|
|
1097
|
+
} else if (placement === 'bottom') {
|
|
1098
|
+
inner = (
|
|
1099
|
+
<>
|
|
1100
|
+
{body}
|
|
1101
|
+
{legend}
|
|
1102
|
+
</>
|
|
1103
|
+
);
|
|
1104
|
+
} else if (placement === 'left') {
|
|
1105
|
+
inner = (
|
|
1106
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
1107
|
+
{legend}
|
|
1108
|
+
{body}
|
|
1109
|
+
</HStack>
|
|
1110
|
+
);
|
|
1111
|
+
} else {
|
|
1112
|
+
inner = (
|
|
1113
|
+
<HStack flexGrow gap={12} align='stretch'>
|
|
1114
|
+
{body}
|
|
1115
|
+
{legend}
|
|
1116
|
+
</HStack>
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
return (
|
|
1121
|
+
<Chart aria-busy={loading} aria-live='polite'>
|
|
1122
|
+
<ChartHeader>
|
|
1123
|
+
<ChartTitle>{title}</ChartTitle>
|
|
1124
|
+
<ChartActions alwaysVisible>
|
|
1125
|
+
<Tooltip disabled={loading}>
|
|
1126
|
+
<TooltipTrigger asChild>
|
|
1127
|
+
<Button
|
|
1128
|
+
variant='ghost'
|
|
1129
|
+
color='neutral'
|
|
1130
|
+
size='small'
|
|
1131
|
+
aria-label='Reload'
|
|
1132
|
+
disabled={loading}
|
|
1133
|
+
onClick={() => setLoading(true)}
|
|
1134
|
+
>
|
|
1135
|
+
<RefreshCcw />
|
|
1136
|
+
</Button>
|
|
1137
|
+
</TooltipTrigger>
|
|
1138
|
+
<TooltipContent>Reload</TooltipContent>
|
|
1139
|
+
</Tooltip>
|
|
1140
|
+
</ChartActions>
|
|
1141
|
+
</ChartHeader>
|
|
1142
|
+
{loading ? (
|
|
1143
|
+
inner
|
|
1144
|
+
) : (
|
|
1145
|
+
<LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
|
|
1146
|
+
{inner}
|
|
1147
|
+
</LineChart>
|
|
1148
|
+
)}
|
|
1149
|
+
</Chart>
|
|
1150
|
+
);
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Each panel loads for two seconds before swapping to data, and the refresh button replays it.
|
|
1155
|
+
* The skeleton and the real chart share an outer layout, so nothing but the content moves on
|
|
1156
|
+
* the swap.
|
|
1157
|
+
*/
|
|
1158
|
+
export const Refreshing: StoryFn<typeof meta> = () => (
|
|
1159
|
+
<div className='grid grid-cols-2 gap-16 w-1120'>
|
|
1160
|
+
<RefreshingChart placement='none' title='No legend' />
|
|
1161
|
+
<RefreshingChart placement='top' title='Top — JSX order' />
|
|
1162
|
+
<RefreshingChart placement='bottom' title='Bottom — JSX order' />
|
|
1163
|
+
<RefreshingChart placement='left' title='Left — wrapped in HStack' />
|
|
1164
|
+
<RefreshingChart placement='right' title='Right — wrapped in HStack' />
|
|
1165
|
+
</div>
|
|
1166
|
+
);
|
|
1167
|
+
|
|
1168
|
+
/**
|
|
1169
|
+
* `LineChartEmpty` keeps the dashed plot frame and puts the message inside it, so a card with
|
|
1170
|
+
* no data still reads as a chart rather than as something broken.
|
|
1171
|
+
*/
|
|
1172
|
+
export const Empty: StoryFn<typeof meta> = () => (
|
|
1173
|
+
<div className='w-560'>
|
|
1174
|
+
<Chart>
|
|
1175
|
+
<ChartHeader>
|
|
1176
|
+
<ChartTitle>No data</ChartTitle>
|
|
1177
|
+
</ChartHeader>
|
|
1178
|
+
<LineChartEmpty>No data</LineChartEmpty>
|
|
1179
|
+
</Chart>
|
|
1180
|
+
</div>
|
|
1181
|
+
);
|
|
1182
|
+
|
|
1183
|
+
Empty.parameters = {
|
|
1184
|
+
design: {
|
|
1185
|
+
type: 'figma',
|
|
1186
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=8670-2594&m=dev',
|
|
1187
|
+
},
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
const LongTimeRangeChart = () => {
|
|
1191
|
+
const { formatDate, formatDateTime, formatDateTimeWithTimezone } = useChartTimeFormatters();
|
|
1192
|
+
const formatDateTimeRangeText = useMemo(() => formatRange(formatDateTime), [formatDateTime]);
|
|
1193
|
+
const [range, setRange] = useState<LineChartZoomRange | null>(null);
|
|
1194
|
+
const visibleData = useMemo(() => {
|
|
1195
|
+
if (!range) return hourlyData1000;
|
|
1196
|
+
return hourlyData1000.slice(range.fromIndex, range.toIndex + 1);
|
|
1197
|
+
}, [range]);
|
|
1198
|
+
|
|
1199
|
+
return (
|
|
1200
|
+
<Chart>
|
|
1201
|
+
<ChartHeader>
|
|
1202
|
+
<ChartTitle>1,000 hourly samples — drag to zoom</ChartTitle>
|
|
1203
|
+
<ChartActions alwaysVisible={range !== null}>
|
|
1204
|
+
{range !== null && (
|
|
1205
|
+
<Tooltip>
|
|
1206
|
+
<TooltipTrigger asChild>
|
|
1207
|
+
<Button
|
|
1208
|
+
variant='ghost'
|
|
1209
|
+
color='neutral'
|
|
1210
|
+
size='small'
|
|
1211
|
+
aria-label='Reset time selection'
|
|
1212
|
+
onClick={() => setRange(null)}
|
|
1213
|
+
>
|
|
1214
|
+
<ZoomOut />
|
|
1215
|
+
</Button>
|
|
1216
|
+
</TooltipTrigger>
|
|
1217
|
+
<TooltipContent>Reset time selection</TooltipContent>
|
|
1218
|
+
</Tooltip>
|
|
1219
|
+
)}
|
|
1220
|
+
</ChartActions>
|
|
1221
|
+
</ChartHeader>
|
|
1222
|
+
<LineChart data={visibleData} series={multiSeries} xKey='timestamp' onZoomChange={setRange}>
|
|
1223
|
+
<LineChartLegend>
|
|
1224
|
+
{multiSeries.map(s => (
|
|
1225
|
+
<LineChartLegendItem key={s.key} seriesKey={s.key}>
|
|
1226
|
+
<LineChartHoverPopoverDot color={s.color} />
|
|
1227
|
+
<span className='text-xs font-mono text-text-primary'>{s.label}</span>
|
|
1228
|
+
</LineChartLegendItem>
|
|
1229
|
+
))}
|
|
1230
|
+
</LineChartLegend>
|
|
1231
|
+
<LineChartBody height={220}>
|
|
1232
|
+
<LineChartGrid />
|
|
1233
|
+
<LineChartXAxis tickFormatter={formatDate} minTickGap={64} />
|
|
1234
|
+
<LineChartYAxis tickFormatter={formatYTick} />
|
|
1235
|
+
{multiSeries.map(s => (
|
|
1236
|
+
<LineChartLine key={s.key} seriesKey={s.key} disableAnimation />
|
|
1237
|
+
))}
|
|
1238
|
+
<LineChartTooltip xTickFormatter={formatDateTimeWithTimezone} />
|
|
1239
|
+
<LineChartZoomBrush formatRange={formatDateTimeRangeText} />
|
|
1240
|
+
</LineChartBody>
|
|
1241
|
+
</LineChart>
|
|
1242
|
+
</Chart>
|
|
1243
|
+
);
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* A thousand hourly samples in one card: drag to zoom and the header's control restores the
|
|
1248
|
+
* full range. The story slices the data itself, exactly as a consumer has to.
|
|
1249
|
+
*/
|
|
1250
|
+
export const LongTimeRange: StoryFn<typeof meta> = () => (
|
|
1251
|
+
<div className='w-720'>
|
|
1252
|
+
<LongTimeRangeChart />
|
|
1253
|
+
</div>
|
|
1254
|
+
);
|
|
1255
|
+
```
|
|
1256
|
+
|
|
1257
|
+
### ../utils/abbreviateNumber.ts
|
|
1258
|
+
|
|
1259
|
+
```tsx
|
|
1260
|
+
/**
|
|
1261
|
+
* Suffix tiers: [minAbsValue, divisor, suffix].
|
|
1262
|
+
* Sorted descending so the first match wins.
|
|
1263
|
+
*
|
|
1264
|
+
* Boundaries use "rounding-aware" thresholds:
|
|
1265
|
+
* 999,500 rounds to 1M (not 999.5k), 999,499 stays 999k.
|
|
1266
|
+
*/
|
|
1267
|
+
const tiers: [threshold: number, divisor: number, suffix: string][] = [
|
|
1268
|
+
[999_500_000_000, 1e12, 'T'],
|
|
1269
|
+
[999_500_000, 1e9, 'B'],
|
|
1270
|
+
[999_500, 1e6, 'M'],
|
|
1271
|
+
[1_000, 1e3, 'k'],
|
|
1272
|
+
];
|
|
1273
|
+
|
|
1274
|
+
const fullFormatter = new Intl.NumberFormat('en-US');
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Abbreviate a number for table cells: `12042` → `"12k"`, `59614283` → `"59.6M"`.
|
|
1278
|
+
*
|
|
1279
|
+
* Rules (from the Number display & abbreviation guide):
|
|
1280
|
+
* - Suffixes: k (10³), M (10⁶), B (10⁹), T (10¹²) — k lowercase, rest uppercase, no space
|
|
1281
|
+
* - Boundary: moves to next suffix when rounding would reach 1000×
|
|
1282
|
+
* - Precision: ≥100 → 0 decimals; 10–99 → 1 decimal (drop .0); 1–9.9 → 1 decimal
|
|
1283
|
+
* - Negative numbers supported
|
|
1284
|
+
*/
|
|
1285
|
+
export const abbreviateNumber = (value: number): string => {
|
|
1286
|
+
if (value === 0) return '0';
|
|
1287
|
+
|
|
1288
|
+
const sign = value < 0 ? '-' : '';
|
|
1289
|
+
const abs = Math.abs(value);
|
|
1290
|
+
|
|
1291
|
+
if (abs < 1_000) return String(value);
|
|
1292
|
+
|
|
1293
|
+
const tier = tiers.find(([threshold]) => abs >= threshold);
|
|
1294
|
+
|
|
1295
|
+
if (!tier) return String(value);
|
|
1296
|
+
|
|
1297
|
+
const [, divisor, suffix] = tier;
|
|
1298
|
+
const scaled = abs / divisor;
|
|
1299
|
+
|
|
1300
|
+
// ≥100 → 0 decimals; <100 → 1 decimal (drop trailing .0)
|
|
1301
|
+
const precision = scaled >= 100 ? 0 : 1;
|
|
1302
|
+
const rounded = Math.round(scaled * 10 ** precision) / 10 ** precision;
|
|
1303
|
+
const formatted = rounded % 1 === 0 ? String(rounded) : rounded.toFixed(1);
|
|
1304
|
+
|
|
1305
|
+
return `${sign}${formatted}${suffix}`;
|
|
1306
|
+
};
|
|
1307
|
+
|
|
1308
|
+
/**
|
|
1309
|
+
* Format a number with thousand separators for tooltips: `59614283` → `"59,614,283"`.
|
|
1310
|
+
*/
|
|
1311
|
+
export const formatFullNumber = (value: number): string => fullFormatter.format(value);
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Format a percentage with boundary safety:
|
|
1315
|
+
* - Never show 100% when real value < 100 → ">99%" (or ">99.9%" etc.)
|
|
1316
|
+
* - Never show 0% when real value > 0 → "<1%" (or "<0.1%" etc.)
|
|
1317
|
+
* - `decimals` controls fractional precision (default 0)
|
|
1318
|
+
*/
|
|
1319
|
+
export const formatPercent = (value: number, decimals = 0): string => {
|
|
1320
|
+
if (value === 0) return '0%';
|
|
1321
|
+
if (value === 100) return '100%';
|
|
1322
|
+
|
|
1323
|
+
const factor = 10 ** decimals;
|
|
1324
|
+
const rounded = Math.round(value * factor) / factor;
|
|
1325
|
+
|
|
1326
|
+
// Boundary safety: value > 0 but rounds to 0
|
|
1327
|
+
if (value > 0 && rounded === 0) {
|
|
1328
|
+
const threshold = 1 / factor;
|
|
1329
|
+
return `<${threshold}%`;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// Boundary safety: value < 100 but rounds to 100
|
|
1333
|
+
if (value < 100 && rounded === 100) {
|
|
1334
|
+
const max = 100 - 1 / factor;
|
|
1335
|
+
return `>${decimals > 0 ? max.toFixed(decimals) : String(max)}%`;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
return `${decimals > 0 ? rounded.toFixed(decimals) : String(rounded)}%`;
|
|
1339
|
+
};
|
|
1340
|
+
|
|
1341
|
+
/**
|
|
1342
|
+
* Byte-formatting tiers: [minValue, divisor, suffix].
|
|
1343
|
+
* Uses decimal (SI) units: KB = 1000, MB = 1e6, etc.
|
|
1344
|
+
*/
|
|
1345
|
+
const byteTiers: [threshold: number, divisor: number, suffix: string][] = [
|
|
1346
|
+
[999_500_000_000, 1e12, 'TB'],
|
|
1347
|
+
[999_500_000, 1e9, 'GB'],
|
|
1348
|
+
[999_500, 1e6, 'MB'],
|
|
1349
|
+
[1_000, 1e3, 'KB'],
|
|
1350
|
+
];
|
|
1351
|
+
|
|
1352
|
+
/**
|
|
1353
|
+
* Format bytes using decimal (SI) units: 512 B, 3.4 KB, 12.7 MB, 2.3 GB, 1.1 TB.
|
|
1354
|
+
* Same decimal precision rules as abbreviateNumber.
|
|
1355
|
+
* Returns `{ display, full }` where `full` = "2,345,678,901 bytes".
|
|
1356
|
+
*/
|
|
1357
|
+
export const formatBytes = (value: number): { display: string; full: string } => {
|
|
1358
|
+
const full = `${fullFormatter.format(value)} bytes`;
|
|
1359
|
+
|
|
1360
|
+
if (value < 1_000) {
|
|
1361
|
+
return { display: `${value} B`, full };
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
const tier = byteTiers.find(([threshold]) => value >= threshold);
|
|
1365
|
+
|
|
1366
|
+
if (!tier) {
|
|
1367
|
+
return { display: `${value} B`, full };
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
const [, divisor, suffix] = tier;
|
|
1371
|
+
const scaled = value / divisor;
|
|
1372
|
+
|
|
1373
|
+
const precision = scaled >= 100 ? 0 : 1;
|
|
1374
|
+
const rounded = Math.round(scaled * 10 ** precision) / 10 ** precision;
|
|
1375
|
+
const formatted = rounded % 1 === 0 ? String(rounded) : rounded.toFixed(1);
|
|
1376
|
+
|
|
1377
|
+
return { display: `${formatted} ${suffix}`, full };
|
|
1378
|
+
};
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
### SimpleCharts/LineChart/lib/formatRange.ts
|
|
1382
|
+
|
|
1383
|
+
```tsx
|
|
1384
|
+
/** Higher-order range formatter — joins `format(from)` and `format(to)` with `→`. */
|
|
1385
|
+
export const formatRange =
|
|
1386
|
+
(format: (value: unknown) => string) =>
|
|
1387
|
+
(range: { from: unknown; to: unknown }): string =>
|
|
1388
|
+
`${format(range.from)} → ${format(range.to)}`;
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
### SimpleCharts/LineChart/lib/sampleData.ts
|
|
1392
|
+
|
|
1393
|
+
```tsx
|
|
1394
|
+
import type { LineChartDatum, LineChartSeries } from '../LineChartContext';
|
|
1395
|
+
|
|
1396
|
+
// Deterministic pseudo-random in [0, 1) so the same `(i, seed, salt)` produces
|
|
1397
|
+
// the same value across runs — keeps screenshot tests stable while letting us
|
|
1398
|
+
// add point-to-point jitter that monotone smooths out and linear preserves.
|
|
1399
|
+
const jitter = (i: number, seed: number, salt: number): number => {
|
|
1400
|
+
const v = Math.sin((i + seed) * salt) * 43758.5453;
|
|
1401
|
+
return v - Math.floor(v);
|
|
1402
|
+
};
|
|
1403
|
+
|
|
1404
|
+
export const genHourly = (count: number, seed = 1): LineChartDatum[] => {
|
|
1405
|
+
// Local-time anchor so the first sample reads `00:00` in the viewer's
|
|
1406
|
+
// timezone instead of drifting by the UTC offset.
|
|
1407
|
+
const start = new Date(2025, 0, 1, 0, 0, 0).getTime();
|
|
1408
|
+
const out: LineChartDatum[] = [];
|
|
1409
|
+
for (let i = 0; i < count; i++) {
|
|
1410
|
+
const t = start + i * 60 * 60 * 1000;
|
|
1411
|
+
const requests = Math.round(
|
|
1412
|
+
120 + Math.sin((i + seed) / 4) * 30 + (jitter(i, seed, 12.9898) - 0.5) * 80,
|
|
1413
|
+
);
|
|
1414
|
+
const errors = Math.round(
|
|
1415
|
+
24 + Math.cos((i + seed) / 5) * 10 + (jitter(i, seed, 78.233) - 0.5) * 32,
|
|
1416
|
+
);
|
|
1417
|
+
const latency = Math.round(
|
|
1418
|
+
80 + Math.sin((i + seed) / 6) * 14 + (jitter(i, seed, 39.346) - 0.5) * 40,
|
|
1419
|
+
);
|
|
1420
|
+
out.push({ timestamp: t, requests, errors, latency });
|
|
1421
|
+
}
|
|
1422
|
+
return out;
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
export const genDaily = (count: number): LineChartDatum[] => {
|
|
1426
|
+
const start = new Date(2024, 0, 1, 0, 0, 0).getTime();
|
|
1427
|
+
const out: LineChartDatum[] = [];
|
|
1428
|
+
for (let i = 0; i < count; i++) {
|
|
1429
|
+
const t = start + i * 24 * 60 * 60 * 1000;
|
|
1430
|
+
const requests = Math.round(1000 + Math.sin(i / 9) * 400 + (i % 13) * 12);
|
|
1431
|
+
const errors = Math.round(80 + Math.cos(i / 11) * 30 + (i % 7) * 3);
|
|
1432
|
+
out.push({ timestamp: t, requests, errors });
|
|
1433
|
+
}
|
|
1434
|
+
return out;
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
export const singleSeries: LineChartSeries[] = [
|
|
1438
|
+
{ key: 'requests', label: 'Requests', color: 'brand' },
|
|
1439
|
+
];
|
|
1440
|
+
|
|
1441
|
+
export const multiSeries: LineChartSeries[] = [
|
|
1442
|
+
{ key: 'requests', label: 'Requests', color: 'brand' },
|
|
1443
|
+
{ key: 'errors', label: 'Errors', color: 'red' },
|
|
1444
|
+
{ key: 'latency', label: 'Latency', color: 'blue' },
|
|
1445
|
+
];
|
|
1446
|
+
|
|
1447
|
+
export const dashedSeries: LineChartSeries[] = [
|
|
1448
|
+
{ key: 'requests', label: 'Requests', color: 'brand' },
|
|
1449
|
+
{ key: 'errors', label: 'Errors (target)', color: 'red', variant: 'dashed' },
|
|
1450
|
+
];
|
|
1451
|
+
|
|
1452
|
+
export const customColorSeries: LineChartSeries[] = [
|
|
1453
|
+
{ key: 'requests', label: 'Requests', color: 'var(--color-violet-500)' },
|
|
1454
|
+
{ key: 'errors', label: 'Errors', color: 'var(--color-emerald-500)' },
|
|
1455
|
+
];
|
|
1456
|
+
|
|
1457
|
+
export const hourlyData24 = genHourly(24);
|
|
1458
|
+
export const hourlyDataA = genHourly(24, 1);
|
|
1459
|
+
export const hourlyDataB = genHourly(24, 7);
|
|
1460
|
+
export const dailyData60 = genDaily(60);
|
|
1461
|
+
export const hourlyData1000 = genHourly(1000);
|
|
1462
|
+
|
|
1463
|
+
export const singlePointData: LineChartDatum[] = [
|
|
1464
|
+
{ timestamp: new Date(2025, 0, 1, 12, 0, 0).getTime(), requests: 142 },
|
|
1465
|
+
];
|
|
1466
|
+
|
|
1467
|
+
export const dataWithErrorGaps: LineChartDatum[] = hourlyData24.map((d, i) => {
|
|
1468
|
+
if ((i >= 6 && i <= 8) || (i >= 15 && i <= 16)) {
|
|
1469
|
+
return { ...d, errors: null };
|
|
1470
|
+
}
|
|
1471
|
+
return d;
|
|
1472
|
+
});
|
|
1473
|
+
|
|
1474
|
+
export const unitsByKey: Record<string, string> = {
|
|
1475
|
+
requests: ' req',
|
|
1476
|
+
errors: ' err',
|
|
1477
|
+
latency: ' ms',
|
|
1478
|
+
};
|
|
1479
|
+
```
|