@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,1533 @@
|
|
|
1
|
+
# CodeEditor story sources
|
|
2
|
+
|
|
3
|
+
### CodeEditor/CodeEditor.stories.tsx
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { type ReactNode, useState } from 'react';
|
|
7
|
+
import type { Meta, StoryFn } from 'storybook-react-rsbuild';
|
|
8
|
+
import { Info, Skull, TriangleAlert } from '../../icons';
|
|
9
|
+
import { Button } from '../Button';
|
|
10
|
+
import {
|
|
11
|
+
CodeSnippetActions,
|
|
12
|
+
CodeSnippetAdapterProvider,
|
|
13
|
+
CodeSnippetCode,
|
|
14
|
+
CodeSnippetContent,
|
|
15
|
+
CodeSnippetCopyButton,
|
|
16
|
+
CodeSnippetFullscreenButton,
|
|
17
|
+
CodeSnippetHeader,
|
|
18
|
+
CodeSnippetLineNumbers,
|
|
19
|
+
CodeSnippetRoot,
|
|
20
|
+
CodeSnippetShowMoreButton,
|
|
21
|
+
type CodeSnippetSize,
|
|
22
|
+
CodeSnippetTab,
|
|
23
|
+
CodeSnippetTabs,
|
|
24
|
+
CodeSnippetTitle,
|
|
25
|
+
CodeSnippetWrapButton,
|
|
26
|
+
type FoldRegion,
|
|
27
|
+
getHttpFolds,
|
|
28
|
+
type LineConfig,
|
|
29
|
+
loadPrismAdapter,
|
|
30
|
+
loadShikiAdapter,
|
|
31
|
+
} from '../CodeSnippet';
|
|
32
|
+
import {
|
|
33
|
+
Drawer,
|
|
34
|
+
DrawerBody,
|
|
35
|
+
DrawerContent,
|
|
36
|
+
DrawerHeader,
|
|
37
|
+
DrawerTitle,
|
|
38
|
+
DrawerTrigger,
|
|
39
|
+
} from '../Drawer';
|
|
40
|
+
import { VStack } from '../Stack';
|
|
41
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip';
|
|
42
|
+
import { CodeEditorContent } from './CodeEditorContent';
|
|
43
|
+
import { CodeEditorRoot } from './CodeEditorRoot';
|
|
44
|
+
import { EditingWorkflowDemo } from './story-content/_storyEditingWorkflow';
|
|
45
|
+
import { LongDocumentDemo } from './story-content/_storyLongDocument';
|
|
46
|
+
import { TabsKeepHistoryDemo } from './story-content/_storyTabsKeepHistory';
|
|
47
|
+
import type { CodeEditorDiagnostic, CodeEditorLanguage } from './types';
|
|
48
|
+
|
|
49
|
+
const DESCRIPTION = [
|
|
50
|
+
'An editable code surface that is visually the same component as `CodeSnippet` and reuses its header, tabs, actions and show-more — reach for `CodeSnippet` whenever the code is only read, since a page that never renders `CodeEditorContent` never loads the editor engine.',
|
|
51
|
+
'Colours come from the same `CodeSnippetAdapterProvider` (plain text without one), so a read-only editor matches the snippet except for a native thin scrollbar, a caret and selection drawn by the editor, and an HTTP JSON body that stays coloured when `Content-Type` has parameters or the body has blank lines.',
|
|
52
|
+
'The adapter re-tokenizes the whole document after each pause in typing, which stays within a frame up to about 2 000 lines with Prism; longer documents still edit smoothly, their colours just settle a moment later.',
|
|
53
|
+
'Like the snippet, the editor sits inside a `display: contents` wrapper that keeps it mounted across fullscreen, so space editors with their own `className` (for example `mt-16`) or a `gap` on the parent — not `space-*`, `divide-*` or child selectors on the parent.',
|
|
54
|
+
'`lines`, `folds`, `completions` and `schema` are compared by identity, so memoise them or hoist them to module constants — a new value on every render reconfigures the editor.',
|
|
55
|
+
'Autocomplete suggests language keywords and words already in the document for every language; HTTP methods and headers and JSON Schema values have their own contextual suggestions. Pass `completions` to add application-specific results.',
|
|
56
|
+
'Syntax errors are best-effort: JSON reports the `JSON.parse` message, JavaScript and TypeScript use Babel, Lua uses luaparse (first error only), YAML and Python use their Lezer parsers, which still flag a few valid Python forms such as `lambda a, /, b` and parenthesised `with` items.',
|
|
57
|
+
'`lines` and `folds` stay on their line numbers while typing; to keep a decoration on a piece of text, recompute it from `value` (for example `useMemo(() => linesFor(value), [value])`, or a `folds` function such as `getHttpFolds`).',
|
|
58
|
+
'The editor injects `<style>` tags, so under a strict Content Security Policy pass `cspNonce`.',
|
|
59
|
+
'Tab indents, so keyboard users leave with Escape, then Tab, or press Ctrl+M (Alt+Shift+M on macOS) to switch Tab between indenting and moving focus — point `aria-describedby` at text holding `CODE_EDITOR_KEYBOARD_HINT` to tell screen-reader users.',
|
|
60
|
+
].join(' ');
|
|
61
|
+
|
|
62
|
+
const meta = {
|
|
63
|
+
title: 'Data Display/CodeEditor',
|
|
64
|
+
component: CodeEditorRoot,
|
|
65
|
+
parameters: {
|
|
66
|
+
layout: 'padded',
|
|
67
|
+
docs: { description: { component: DESCRIPTION } },
|
|
68
|
+
design: {
|
|
69
|
+
type: 'figma',
|
|
70
|
+
url: 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=3087-29516&m=dev',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
tags: ['autodocs'],
|
|
74
|
+
} satisfies Meta<typeof CodeEditorRoot>;
|
|
75
|
+
|
|
76
|
+
export default meta;
|
|
77
|
+
|
|
78
|
+
// --- Sample documents ---
|
|
79
|
+
|
|
80
|
+
const jsonCode = `{
|
|
81
|
+
"name": "@wallarm-org/sdk",
|
|
82
|
+
"version": "1.0.0",
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"react": "^19.0.0",
|
|
85
|
+
"typescript": "^5.0.0"
|
|
86
|
+
}
|
|
87
|
+
}`;
|
|
88
|
+
|
|
89
|
+
const sampleCode = `const greeting = "Hello, World!";
|
|
90
|
+
console.log(greeting);
|
|
91
|
+
|
|
92
|
+
function add(a, b) {
|
|
93
|
+
return a + b;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default add;`;
|
|
97
|
+
|
|
98
|
+
const colorsCode = `Line 1: Default (no color)
|
|
99
|
+
Line 2: Danger color
|
|
100
|
+
Line 3: Warning color
|
|
101
|
+
Line 4: Info color
|
|
102
|
+
Line 5: Success color
|
|
103
|
+
Line 6: Brand color
|
|
104
|
+
Line 7: AI color
|
|
105
|
+
Line 8: Neutral color`;
|
|
106
|
+
|
|
107
|
+
const diffCode = `const greeting = "Hello";
|
|
108
|
+
console.log("old message");
|
|
109
|
+
console.log("new message");
|
|
110
|
+
console.log("another new line");
|
|
111
|
+
|
|
112
|
+
export default greeting;`;
|
|
113
|
+
|
|
114
|
+
const annotatedHeadersCode = `Host: inventory.example.com
|
|
115
|
+
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
|
116
|
+
AppleWebKit/537.36
|
|
117
|
+
Accept: application/json, text/plain, */*
|
|
118
|
+
Accept-Language: en-US,en;q=0.9
|
|
119
|
+
Connection: keep-alive
|
|
120
|
+
Cache-Control: no-cache`;
|
|
121
|
+
|
|
122
|
+
const rangesCode = `GET /api/v2/users HTTP/1.1
|
|
123
|
+
Host: inventory.example.com
|
|
124
|
+
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
|
125
|
+
Accept: application/json, text/plain, */*
|
|
126
|
+
Accept-Language: en-US,en;q=0.9
|
|
127
|
+
Connection: keep-alive
|
|
128
|
+
X-Forwarded-For: 192.168.1.100
|
|
129
|
+
Cache-Control: no-cache`;
|
|
130
|
+
|
|
131
|
+
const httpRequestCode = `POST /api/v2/rules HTTP/1.1
|
|
132
|
+
Host: api.wallarm.com
|
|
133
|
+
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
|
|
134
|
+
Content-Type: application/json
|
|
135
|
+
Accept: application/json
|
|
136
|
+
|
|
137
|
+
{
|
|
138
|
+
"action": "block",
|
|
139
|
+
"point": ["header", "X-Forwarded-For"],
|
|
140
|
+
"enabled": true
|
|
141
|
+
}`;
|
|
142
|
+
|
|
143
|
+
const httpResponseCode = `HTTP/1.1 200 OK
|
|
144
|
+
Content-Type: application/json; charset=utf-8
|
|
145
|
+
X-Request-Id: abc-123-def-456
|
|
146
|
+
Cache-Control: no-store
|
|
147
|
+
|
|
148
|
+
{
|
|
149
|
+
"users": [
|
|
150
|
+
{ "id": 1, "name": "Alice" },
|
|
151
|
+
{ "id": 2, "name": "Bob" }
|
|
152
|
+
],
|
|
153
|
+
"total": 42
|
|
154
|
+
}`;
|
|
155
|
+
|
|
156
|
+
const foldableRequestCode = `GET /api/v2/users HTTP/1.1
|
|
157
|
+
Host: api.example.com
|
|
158
|
+
Accept: application/json
|
|
159
|
+
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9
|
|
160
|
+
X-Request-ID: abc-123
|
|
161
|
+
Content-Type: application/json
|
|
162
|
+
Cache-Control: no-cache
|
|
163
|
+
|
|
164
|
+
{
|
|
165
|
+
"filter": {
|
|
166
|
+
"status": "active",
|
|
167
|
+
"role": "admin"
|
|
168
|
+
},
|
|
169
|
+
"pagination": {
|
|
170
|
+
"page": 1,
|
|
171
|
+
"limit": 50
|
|
172
|
+
}
|
|
173
|
+
}`;
|
|
174
|
+
|
|
175
|
+
const foldableResponseCode = `HTTP/1.1 200 OK
|
|
176
|
+
Content-Type: application/json; charset=utf-8
|
|
177
|
+
X-Request-ID: abc-123
|
|
178
|
+
X-RateLimit-Remaining: 98
|
|
179
|
+
Cache-Control: private, max-age=0
|
|
180
|
+
|
|
181
|
+
{
|
|
182
|
+
"data": [
|
|
183
|
+
{ "id": 1, "name": "Alice", "role": "admin" },
|
|
184
|
+
{ "id": 2, "name": "Bob", "role": "admin" }
|
|
185
|
+
],
|
|
186
|
+
"meta": {
|
|
187
|
+
"total": 2,
|
|
188
|
+
"page": 1,
|
|
189
|
+
"limit": 50
|
|
190
|
+
}
|
|
191
|
+
}`;
|
|
192
|
+
|
|
193
|
+
const showMoreCode = `Host: inventory.example.com
|
|
194
|
+
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
|
195
|
+
Referer: https://app.example.com/dashboard
|
|
196
|
+
Accept: application/json, text/plain, */*
|
|
197
|
+
Accept-Language: en-US,en;q=0.9
|
|
198
|
+
Connection: keep-alive
|
|
199
|
+
Cache-Control: no-cache
|
|
200
|
+
Referer: https://app.example.com/dashboard
|
|
201
|
+
Accept: application/json, text/plain, */*
|
|
202
|
+
Accept-Language: en-US,en;q=0.9
|
|
203
|
+
Connection: keep-alive
|
|
204
|
+
Cache-Control: no-cache`;
|
|
205
|
+
|
|
206
|
+
const showMoreThresholdCode = `Host: inventory.example.com
|
|
207
|
+
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
|
208
|
+
Referer: https://app.example.com/dashboard
|
|
209
|
+
Accept: application/json, text/plain, */*
|
|
210
|
+
Accept-Language: en-US,en;q=0.9
|
|
211
|
+
Connection: keep-alive
|
|
212
|
+
Cache-Control: no-cache
|
|
213
|
+
Authorization: Bearer token123
|
|
214
|
+
X-Request-ID: abc-def-ghi`;
|
|
215
|
+
|
|
216
|
+
const longCode = `const veryLongVariableName = "This is a very long string that will demonstrate line wrapping behavior when the content exceeds the container width";
|
|
217
|
+
console.log(veryLongVariableName);`;
|
|
218
|
+
|
|
219
|
+
const bashCode = `npm install @wallarm-org/sdk
|
|
220
|
+
npm run build
|
|
221
|
+
npm run test`;
|
|
222
|
+
|
|
223
|
+
const tabDocuments = {
|
|
224
|
+
request: httpRequestCode,
|
|
225
|
+
response: `HTTP/1.1 201 Created
|
|
226
|
+
Content-Type: application/json
|
|
227
|
+
Location: /api/v2/rules/42
|
|
228
|
+
|
|
229
|
+
{
|
|
230
|
+
"id": 42,
|
|
231
|
+
"action": "block"
|
|
232
|
+
}`,
|
|
233
|
+
} satisfies Record<string, string>;
|
|
234
|
+
|
|
235
|
+
type TabId = keyof typeof tabDocuments;
|
|
236
|
+
|
|
237
|
+
const isTabId = (value: string): value is TabId => value === 'request' || value === 'response';
|
|
238
|
+
|
|
239
|
+
// --- Shared line configs and fold functions ---
|
|
240
|
+
|
|
241
|
+
const tooltipPrefix = (icon: ReactNode, text: string): ReactNode => (
|
|
242
|
+
<Tooltip>
|
|
243
|
+
<TooltipTrigger>{icon}</TooltipTrigger>
|
|
244
|
+
<TooltipContent>{text}</TooltipContent>
|
|
245
|
+
</Tooltip>
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const colorLines: Record<number, LineConfig> = {
|
|
249
|
+
2: { color: 'danger' },
|
|
250
|
+
3: { color: 'warning' },
|
|
251
|
+
4: { color: 'info' },
|
|
252
|
+
5: { color: 'success' },
|
|
253
|
+
6: { color: 'brand' },
|
|
254
|
+
7: { color: 'ai' },
|
|
255
|
+
8: { color: 'neutral' },
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const diffLines: Record<number, LineConfig> = {
|
|
259
|
+
2: { color: 'danger', prefix: '-' },
|
|
260
|
+
3: { color: 'success', prefix: '+' },
|
|
261
|
+
4: { color: 'success', prefix: '+' },
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const iconLines: Record<number, LineConfig> = {
|
|
265
|
+
3: { color: 'danger', prefix: tooltipPrefix(<Skull />, 'Malicious user agent') },
|
|
266
|
+
5: { color: 'warning', prefix: tooltipPrefix(<TriangleAlert />, 'Unusual language list') },
|
|
267
|
+
7: { color: 'info', prefix: tooltipPrefix(<Info />, 'Caching disabled') },
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const rangeLines: Record<number, LineConfig> = {
|
|
271
|
+
4: { color: 'danger', ranges: [{ start: 8, end: 24 }] },
|
|
272
|
+
7: { color: 'info', ranges: [{ start: 17, end: 30 }] },
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const wrapDiffLines: Record<number, LineConfig> = {
|
|
276
|
+
1: { color: 'danger', prefix: '-' },
|
|
277
|
+
2: { color: 'success', prefix: '+' },
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const parityColorLines: Record<number, LineConfig> = {
|
|
281
|
+
...colorLines,
|
|
282
|
+
1: { prefix: tooltipPrefix(<Info />, 'Untouched line') },
|
|
283
|
+
2: { color: 'danger', prefix: '-' },
|
|
284
|
+
5: { color: 'success', prefix: '+' },
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
/** Module-level so the function identity is stable across renders. */
|
|
288
|
+
const foldRequestHeadersCollapsed = (
|
|
289
|
+
value: string,
|
|
290
|
+
{ startingLineNumber }: { startingLineNumber: number },
|
|
291
|
+
): FoldRegion[] => getHttpFolds(value, { startingLineNumber, headers: { defaultCollapsed: true } });
|
|
292
|
+
|
|
293
|
+
const foldHttp = (
|
|
294
|
+
value: string,
|
|
295
|
+
{ startingLineNumber }: { startingLineNumber: number },
|
|
296
|
+
): FoldRegion[] => getHttpFolds(value, { startingLineNumber });
|
|
297
|
+
|
|
298
|
+
const parityCollapsedFolds = getHttpFolds(foldableRequestCode, {
|
|
299
|
+
headers: { defaultCollapsed: true },
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// --- Core stories ---
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* A controlled editor: `value` plus `onChange`, like any input. With no adapter in scope the
|
|
306
|
+
* text is plain, exactly as `CodeSnippet` renders it without a provider.
|
|
307
|
+
*/
|
|
308
|
+
export const Default: StoryFn<typeof meta> = () => {
|
|
309
|
+
const [value, setValue] = useState(jsonCode);
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<div style={{ width: '600px' }}>
|
|
313
|
+
<CodeEditorRoot
|
|
314
|
+
value={value}
|
|
315
|
+
onChange={setValue}
|
|
316
|
+
language='json'
|
|
317
|
+
data-testid='code-editor-default'
|
|
318
|
+
>
|
|
319
|
+
<CodeEditorContent lineNumbers aria-label='Package manifest' />
|
|
320
|
+
</CodeEditorRoot>
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* The `CodeSnippet` header works unchanged: a title and the copy, wrap and fullscreen buttons.
|
|
327
|
+
* Copy puts the edited value on the clipboard, and fullscreen keeps the undo history.
|
|
328
|
+
*/
|
|
329
|
+
export const WithHeader: StoryFn<typeof meta> = () => {
|
|
330
|
+
const [value, setValue] = useState(jsonCode);
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<div style={{ width: '600px' }}>
|
|
334
|
+
<CodeEditorRoot
|
|
335
|
+
value={value}
|
|
336
|
+
onChange={setValue}
|
|
337
|
+
language='json'
|
|
338
|
+
data-testid='code-editor-with-header'
|
|
339
|
+
>
|
|
340
|
+
<CodeSnippetHeader>
|
|
341
|
+
<CodeSnippetTitle>rule.json</CodeSnippetTitle>
|
|
342
|
+
<CodeSnippetActions>
|
|
343
|
+
<CodeSnippetCopyButton />
|
|
344
|
+
<CodeSnippetWrapButton />
|
|
345
|
+
<CodeSnippetFullscreenButton />
|
|
346
|
+
</CodeSnippetActions>
|
|
347
|
+
</CodeSnippetHeader>
|
|
348
|
+
<CodeEditorContent lineNumbers aria-label='Rule JSON' />
|
|
349
|
+
</CodeEditorRoot>
|
|
350
|
+
</div>
|
|
351
|
+
);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Without a header, `CodeSnippetActions` as a direct child floats over the top-right of the
|
|
356
|
+
* editor, as it does over a snippet.
|
|
357
|
+
*/
|
|
358
|
+
export const FloatingActions: StoryFn<typeof meta> = () => {
|
|
359
|
+
const [value, setValue] = useState(sampleCode);
|
|
360
|
+
|
|
361
|
+
return (
|
|
362
|
+
<div style={{ width: '320px' }}>
|
|
363
|
+
<CodeEditorRoot
|
|
364
|
+
value={value}
|
|
365
|
+
onChange={setValue}
|
|
366
|
+
language='text'
|
|
367
|
+
data-testid='code-editor-floating-actions'
|
|
368
|
+
>
|
|
369
|
+
<CodeSnippetActions>
|
|
370
|
+
<CodeSnippetWrapButton />
|
|
371
|
+
<CodeSnippetCopyButton />
|
|
372
|
+
</CodeSnippetActions>
|
|
373
|
+
<CodeEditorContent lineNumbers aria-label='Sample code' />
|
|
374
|
+
</CodeEditorRoot>
|
|
375
|
+
</div>
|
|
376
|
+
);
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* `lineNumbers` on `CodeEditorContent` is the equivalent of `CodeSnippetLineNumbers`, and
|
|
381
|
+
* `startingLineNumber` renumbers the gutter for a fragment taken from a longer file.
|
|
382
|
+
*/
|
|
383
|
+
export const LineNumbersAndStartingLine: StoryFn<typeof meta> = () => (
|
|
384
|
+
<VStack gap={16}>
|
|
385
|
+
<VStack align='start' gap={4}>
|
|
386
|
+
<span className='sb-annotation'>lineNumbers</span>
|
|
387
|
+
<div style={{ width: '600px' }}>
|
|
388
|
+
<CodeEditorRoot
|
|
389
|
+
defaultValue={sampleCode}
|
|
390
|
+
language='text'
|
|
391
|
+
data-testid='code-editor-line-numbers'
|
|
392
|
+
>
|
|
393
|
+
<CodeEditorContent lineNumbers aria-label='Sample code' />
|
|
394
|
+
</CodeEditorRoot>
|
|
395
|
+
</div>
|
|
396
|
+
</VStack>
|
|
397
|
+
<VStack align='start' gap={4}>
|
|
398
|
+
<span className='sb-annotation'>startingLineNumber = 97</span>
|
|
399
|
+
<div style={{ width: '600px' }}>
|
|
400
|
+
<CodeEditorRoot
|
|
401
|
+
defaultValue={sampleCode}
|
|
402
|
+
language='text'
|
|
403
|
+
startingLineNumber={97}
|
|
404
|
+
data-testid='code-editor-starting-line'
|
|
405
|
+
>
|
|
406
|
+
<CodeEditorContent lineNumbers aria-label='Sample code from line 97' />
|
|
407
|
+
</CodeEditorRoot>
|
|
408
|
+
</div>
|
|
409
|
+
</VStack>
|
|
410
|
+
</VStack>
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* `lines` uses the same `LineConfig` as CodeSnippet: seven semantic colours, text prefixes for a
|
|
415
|
+
* hand-made diff, and ReactNode prefixes such as a tooltipped icon. Lines are static and tied
|
|
416
|
+
* to line numbers, so they stay on their number while you type.
|
|
417
|
+
*/
|
|
418
|
+
export const LineColorsAndPrefixes: StoryFn<typeof meta> = () => (
|
|
419
|
+
<VStack gap={16}>
|
|
420
|
+
<VStack align='start' gap={4}>
|
|
421
|
+
<span className='sb-annotation'>colours</span>
|
|
422
|
+
<div style={{ width: '600px' }}>
|
|
423
|
+
<CodeEditorRoot
|
|
424
|
+
defaultValue={colorsCode}
|
|
425
|
+
language='text'
|
|
426
|
+
lines={colorLines}
|
|
427
|
+
data-testid='code-editor-line-colors'
|
|
428
|
+
>
|
|
429
|
+
<CodeEditorContent lineNumbers aria-label='Line colours' />
|
|
430
|
+
</CodeEditorRoot>
|
|
431
|
+
</div>
|
|
432
|
+
</VStack>
|
|
433
|
+
<VStack align='start' gap={4}>
|
|
434
|
+
<span className='sb-annotation'>text prefixes</span>
|
|
435
|
+
<div style={{ width: '600px' }}>
|
|
436
|
+
<CodeEditorRoot
|
|
437
|
+
defaultValue={diffCode}
|
|
438
|
+
language='text'
|
|
439
|
+
lines={diffLines}
|
|
440
|
+
data-testid='code-editor-line-diff'
|
|
441
|
+
>
|
|
442
|
+
<CodeEditorContent lineNumbers aria-label='Diff prefixes' />
|
|
443
|
+
</CodeEditorRoot>
|
|
444
|
+
</div>
|
|
445
|
+
</VStack>
|
|
446
|
+
<VStack align='start' gap={4}>
|
|
447
|
+
<span className='sb-annotation'>ReactNode prefixes with tooltips</span>
|
|
448
|
+
<div style={{ width: '600px' }}>
|
|
449
|
+
<CodeEditorRoot
|
|
450
|
+
defaultValue={annotatedHeadersCode}
|
|
451
|
+
language='text'
|
|
452
|
+
lines={iconLines}
|
|
453
|
+
data-testid='code-editor-line-icons'
|
|
454
|
+
>
|
|
455
|
+
<CodeEditorContent lineNumbers aria-label='Annotated headers' />
|
|
456
|
+
</CodeEditorRoot>
|
|
457
|
+
</div>
|
|
458
|
+
</VStack>
|
|
459
|
+
</VStack>
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* `ranges` colours character offsets inside a line (start inclusive, end exclusive). The line
|
|
464
|
+
* keeps its background, and only the range gets the colour.
|
|
465
|
+
*/
|
|
466
|
+
export const Ranges: StoryFn<typeof meta> = () => (
|
|
467
|
+
<div style={{ width: '600px' }}>
|
|
468
|
+
<CodeEditorRoot
|
|
469
|
+
defaultValue={rangesCode}
|
|
470
|
+
language='text'
|
|
471
|
+
lines={rangeLines}
|
|
472
|
+
data-testid='code-editor-ranges'
|
|
473
|
+
>
|
|
474
|
+
<CodeEditorContent lineNumbers aria-label='Request with ranges' />
|
|
475
|
+
</CodeEditorRoot>
|
|
476
|
+
</div>
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* `language='http'` under Prism. The colours come from the adapter and the structure (start
|
|
481
|
+
* line, headers, JSON body) comes from the editor's own HTTP grammar.
|
|
482
|
+
*/
|
|
483
|
+
export const HttpRequestWithPrism: StoryFn<typeof meta> = () => {
|
|
484
|
+
const [value, setValue] = useState(httpRequestCode);
|
|
485
|
+
|
|
486
|
+
return (
|
|
487
|
+
<CodeSnippetAdapterProvider adapter={loadPrismAdapter}>
|
|
488
|
+
<div style={{ width: '600px' }}>
|
|
489
|
+
<CodeEditorRoot
|
|
490
|
+
value={value}
|
|
491
|
+
onChange={setValue}
|
|
492
|
+
language='http'
|
|
493
|
+
data-testid='code-editor-http-request'
|
|
494
|
+
>
|
|
495
|
+
<CodeEditorContent lineNumbers aria-label='HTTP request' />
|
|
496
|
+
</CodeEditorRoot>
|
|
497
|
+
</div>
|
|
498
|
+
</CodeSnippetAdapterProvider>
|
|
499
|
+
);
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* The response side under Shiki. After an edit, highlighting is repainted in the background,
|
|
504
|
+
* so for a moment you may see the previous colours mapped through your change.
|
|
505
|
+
*/
|
|
506
|
+
export const HttpResponseWithShiki: StoryFn<typeof meta> = () => {
|
|
507
|
+
const [value, setValue] = useState(httpResponseCode);
|
|
508
|
+
|
|
509
|
+
return (
|
|
510
|
+
<CodeSnippetAdapterProvider adapter={loadShikiAdapter}>
|
|
511
|
+
<div style={{ width: '600px' }}>
|
|
512
|
+
<CodeEditorRoot
|
|
513
|
+
value={value}
|
|
514
|
+
onChange={setValue}
|
|
515
|
+
language='http'
|
|
516
|
+
data-testid='code-editor-http-response'
|
|
517
|
+
>
|
|
518
|
+
<CodeEditorContent lineNumbers aria-label='HTTP response' />
|
|
519
|
+
</CodeEditorRoot>
|
|
520
|
+
</div>
|
|
521
|
+
</CodeSnippetAdapterProvider>
|
|
522
|
+
);
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* `folds` as a function of the value: `getHttpFolds` runs again after edits, so adding a header
|
|
527
|
+
* grows the headers fold. Collapsed state is kept by fold `id`. The second editor starts at
|
|
528
|
+
* line 100, and the fold function gets the same offset.
|
|
529
|
+
*/
|
|
530
|
+
export const HttpFolds: StoryFn<typeof meta> = () => {
|
|
531
|
+
const [request, setRequest] = useState(foldableRequestCode);
|
|
532
|
+
const [response, setResponse] = useState(foldableResponseCode);
|
|
533
|
+
|
|
534
|
+
return (
|
|
535
|
+
<VStack gap={16}>
|
|
536
|
+
<VStack align='start' gap={4}>
|
|
537
|
+
<span className='sb-annotation'>headers collapsed by default</span>
|
|
538
|
+
<div style={{ width: '600px' }}>
|
|
539
|
+
<CodeEditorRoot
|
|
540
|
+
value={request}
|
|
541
|
+
onChange={setRequest}
|
|
542
|
+
language='http'
|
|
543
|
+
folds={foldRequestHeadersCollapsed}
|
|
544
|
+
data-testid='code-editor-http-folds-request'
|
|
545
|
+
>
|
|
546
|
+
<CodeEditorContent lineNumbers aria-label='Foldable HTTP request' />
|
|
547
|
+
</CodeEditorRoot>
|
|
548
|
+
</div>
|
|
549
|
+
</VStack>
|
|
550
|
+
<VStack align='start' gap={4}>
|
|
551
|
+
<span className='sb-annotation'>startingLineNumber = 100</span>
|
|
552
|
+
<div style={{ width: '600px' }}>
|
|
553
|
+
<CodeEditorRoot
|
|
554
|
+
value={response}
|
|
555
|
+
onChange={setResponse}
|
|
556
|
+
language='http'
|
|
557
|
+
startingLineNumber={100}
|
|
558
|
+
folds={foldHttp}
|
|
559
|
+
data-testid='code-editor-http-folds-response'
|
|
560
|
+
>
|
|
561
|
+
<CodeEditorContent lineNumbers aria-label='Foldable HTTP response' />
|
|
562
|
+
</CodeEditorRoot>
|
|
563
|
+
</div>
|
|
564
|
+
</VStack>
|
|
565
|
+
</VStack>
|
|
566
|
+
);
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* `maxLines` limits the height, and the editor scrolls inside it (no rows are removed). The
|
|
571
|
+
* button appears on its own when at least three lines are hidden. Render
|
|
572
|
+
* `CodeSnippetShowMoreButton` yourself only to pass props to the real button.
|
|
573
|
+
*/
|
|
574
|
+
export const ShowMore: StoryFn<typeof meta> = () => (
|
|
575
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '24px', width: '500px' }}>
|
|
576
|
+
<div>
|
|
577
|
+
<p className='sb-annotation mb-8'>12 lines, clamped at 7 — 5 hidden</p>
|
|
578
|
+
<CodeEditorRoot
|
|
579
|
+
defaultValue={showMoreCode}
|
|
580
|
+
language='text'
|
|
581
|
+
maxLines={7}
|
|
582
|
+
data-testid='code-editor-show-more'
|
|
583
|
+
>
|
|
584
|
+
<CodeEditorContent aria-label='Request headers' />
|
|
585
|
+
</CodeEditorRoot>
|
|
586
|
+
</div>
|
|
587
|
+
<div>
|
|
588
|
+
<p className='sb-annotation mb-8'>9 lines, clamped at 7 — 2 hidden, no button</p>
|
|
589
|
+
<CodeEditorRoot
|
|
590
|
+
defaultValue={showMoreThresholdCode}
|
|
591
|
+
language='text'
|
|
592
|
+
maxLines={7}
|
|
593
|
+
data-testid='code-editor-show-more-threshold'
|
|
594
|
+
>
|
|
595
|
+
<CodeEditorContent aria-label='Request headers' />
|
|
596
|
+
</CodeEditorRoot>
|
|
597
|
+
</div>
|
|
598
|
+
<div>
|
|
599
|
+
<p className='sb-annotation mb-8'>the button rendered by hand</p>
|
|
600
|
+
<CodeEditorRoot
|
|
601
|
+
defaultValue={showMoreCode}
|
|
602
|
+
language='text'
|
|
603
|
+
maxLines={7}
|
|
604
|
+
data-testid='code-editor-show-more-manual'
|
|
605
|
+
>
|
|
606
|
+
<CodeEditorContent aria-label='Request headers' />
|
|
607
|
+
<CodeSnippetShowMoreButton data-analytics-id='CODE_EDITOR_SHOW_MORE' />
|
|
608
|
+
</CodeEditorRoot>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Wrapping can be uncontrolled (`defaultWrapLines`, driven by the wrap button) or controlled
|
|
615
|
+
* (`wrapLines` plus `onWrapLinesChange`). Colour sticks and prefixes stay on the first visual row.
|
|
616
|
+
*/
|
|
617
|
+
export const Wrap: StoryFn<typeof meta> = () => {
|
|
618
|
+
const [wrap, setWrap] = useState(true);
|
|
619
|
+
|
|
620
|
+
return (
|
|
621
|
+
<VStack gap={16}>
|
|
622
|
+
<VStack align='start' gap={4}>
|
|
623
|
+
<span className='sb-annotation'>no wrapping</span>
|
|
624
|
+
<div style={{ width: '600px' }}>
|
|
625
|
+
<CodeEditorRoot
|
|
626
|
+
defaultValue={longCode}
|
|
627
|
+
language='text'
|
|
628
|
+
lines={wrapDiffLines}
|
|
629
|
+
data-testid='code-editor-wrap-off'
|
|
630
|
+
>
|
|
631
|
+
<CodeEditorContent lineNumbers aria-label='Long lines' />
|
|
632
|
+
</CodeEditorRoot>
|
|
633
|
+
</div>
|
|
634
|
+
</VStack>
|
|
635
|
+
<VStack align='start' gap={4}>
|
|
636
|
+
<span className='sb-annotation'>defaultWrapLines + wrap button</span>
|
|
637
|
+
<div style={{ width: '600px' }}>
|
|
638
|
+
<CodeEditorRoot
|
|
639
|
+
defaultValue={longCode}
|
|
640
|
+
language='text'
|
|
641
|
+
defaultWrapLines
|
|
642
|
+
lines={wrapDiffLines}
|
|
643
|
+
data-testid='code-editor-wrap-uncontrolled'
|
|
644
|
+
>
|
|
645
|
+
<CodeSnippetActions>
|
|
646
|
+
<CodeSnippetWrapButton />
|
|
647
|
+
</CodeSnippetActions>
|
|
648
|
+
<CodeEditorContent lineNumbers aria-label='Long lines, wrapped' />
|
|
649
|
+
</CodeEditorRoot>
|
|
650
|
+
</div>
|
|
651
|
+
</VStack>
|
|
652
|
+
<VStack align='start' gap={4}>
|
|
653
|
+
<span className='sb-annotation'>controlled — wrapLines = {String(wrap)}</span>
|
|
654
|
+
<div style={{ width: '600px' }}>
|
|
655
|
+
<CodeEditorRoot
|
|
656
|
+
defaultValue={longCode}
|
|
657
|
+
language='text'
|
|
658
|
+
wrapLines={wrap}
|
|
659
|
+
onWrapLinesChange={setWrap}
|
|
660
|
+
data-testid='code-editor-wrap-controlled'
|
|
661
|
+
>
|
|
662
|
+
<CodeSnippetActions>
|
|
663
|
+
<CodeSnippetWrapButton />
|
|
664
|
+
</CodeSnippetActions>
|
|
665
|
+
<CodeEditorContent lineNumbers aria-label='Long lines, controlled wrap' />
|
|
666
|
+
</CodeEditorRoot>
|
|
667
|
+
</div>
|
|
668
|
+
</VStack>
|
|
669
|
+
</VStack>
|
|
670
|
+
);
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* The same three sizes as CodeSnippet: `sm` (12px, default), `md` (14px) and `lg` (16px), each
|
|
675
|
+
* on 20px rows.
|
|
676
|
+
*/
|
|
677
|
+
export const Sizes: StoryFn<typeof meta> = () => (
|
|
678
|
+
<VStack gap={16}>
|
|
679
|
+
<VStack align='start' gap={4}>
|
|
680
|
+
<span className='sb-annotation'>sm (default)</span>
|
|
681
|
+
<div style={{ width: '600px' }}>
|
|
682
|
+
<CodeEditorRoot
|
|
683
|
+
defaultValue={bashCode}
|
|
684
|
+
language='bash'
|
|
685
|
+
size='sm'
|
|
686
|
+
data-testid='code-editor-size-sm'
|
|
687
|
+
>
|
|
688
|
+
<CodeEditorContent lineNumbers aria-label='Install commands, small' />
|
|
689
|
+
</CodeEditorRoot>
|
|
690
|
+
</div>
|
|
691
|
+
</VStack>
|
|
692
|
+
<VStack align='start' gap={4}>
|
|
693
|
+
<span className='sb-annotation'>md</span>
|
|
694
|
+
<div style={{ width: '600px' }}>
|
|
695
|
+
<CodeEditorRoot
|
|
696
|
+
defaultValue={bashCode}
|
|
697
|
+
language='bash'
|
|
698
|
+
size='md'
|
|
699
|
+
data-testid='code-editor-size-md'
|
|
700
|
+
>
|
|
701
|
+
<CodeEditorContent lineNumbers aria-label='Install commands, medium' />
|
|
702
|
+
</CodeEditorRoot>
|
|
703
|
+
</div>
|
|
704
|
+
</VStack>
|
|
705
|
+
<VStack align='start' gap={4}>
|
|
706
|
+
<span className='sb-annotation'>lg</span>
|
|
707
|
+
<div style={{ width: '600px' }}>
|
|
708
|
+
<CodeEditorRoot
|
|
709
|
+
defaultValue={bashCode}
|
|
710
|
+
language='bash'
|
|
711
|
+
size='lg'
|
|
712
|
+
data-testid='code-editor-size-lg'
|
|
713
|
+
>
|
|
714
|
+
<CodeEditorContent lineNumbers aria-label='Install commands, large' />
|
|
715
|
+
</CodeEditorRoot>
|
|
716
|
+
</div>
|
|
717
|
+
</VStack>
|
|
718
|
+
</VStack>
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* `readOnly` lets you select, search and copy without focusing the code or showing a caret. Use it when the value
|
|
723
|
+
* can change elsewhere but not here. If it never changes, use `CodeSnippet`.
|
|
724
|
+
*/
|
|
725
|
+
export const ReadOnly: StoryFn<typeof meta> = () => (
|
|
726
|
+
<div style={{ width: '600px' }}>
|
|
727
|
+
<CodeEditorRoot
|
|
728
|
+
value={httpResponseCode}
|
|
729
|
+
language='http'
|
|
730
|
+
readOnly
|
|
731
|
+
data-testid='code-editor-read-only'
|
|
732
|
+
>
|
|
733
|
+
<CodeSnippetHeader>
|
|
734
|
+
<CodeSnippetTitle>Response</CodeSnippetTitle>
|
|
735
|
+
<CodeSnippetActions>
|
|
736
|
+
<CodeSnippetCopyButton />
|
|
737
|
+
</CodeSnippetActions>
|
|
738
|
+
</CodeSnippetHeader>
|
|
739
|
+
<CodeEditorContent lineNumbers aria-label='HTTP response, read only' />
|
|
740
|
+
</CodeEditorRoot>
|
|
741
|
+
</div>
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Tabs swap `value`, and `documentId` swaps the editor's whole state with it, so each tab keeps
|
|
746
|
+
* its own undo history, selection and collapsed folds.
|
|
747
|
+
*/
|
|
748
|
+
export const Tabs: StoryFn<typeof meta> = () => {
|
|
749
|
+
const [tab, setTab] = useState<TabId>('request');
|
|
750
|
+
const [docs, setDocs] = useState<Record<TabId, string>>(tabDocuments);
|
|
751
|
+
|
|
752
|
+
return (
|
|
753
|
+
<div style={{ width: '600px' }}>
|
|
754
|
+
<CodeEditorRoot
|
|
755
|
+
documentId={tab}
|
|
756
|
+
value={docs[tab]}
|
|
757
|
+
onChange={value => setDocs(prev => ({ ...prev, [tab]: value }))}
|
|
758
|
+
language='http'
|
|
759
|
+
data-testid='code-editor-tabs'
|
|
760
|
+
>
|
|
761
|
+
<CodeSnippetHeader>
|
|
762
|
+
<CodeSnippetTabs
|
|
763
|
+
value={tab}
|
|
764
|
+
onValueChange={value => {
|
|
765
|
+
if (isTabId(value)) setTab(value);
|
|
766
|
+
}}
|
|
767
|
+
>
|
|
768
|
+
<CodeSnippetTab value='request' data-testid='code-editor-tabs--tab-request'>
|
|
769
|
+
Request
|
|
770
|
+
</CodeSnippetTab>
|
|
771
|
+
<CodeSnippetTab value='response' data-testid='code-editor-tabs--tab-response'>
|
|
772
|
+
Response
|
|
773
|
+
</CodeSnippetTab>
|
|
774
|
+
</CodeSnippetTabs>
|
|
775
|
+
<CodeSnippetActions>
|
|
776
|
+
<CodeSnippetCopyButton />
|
|
777
|
+
</CodeSnippetActions>
|
|
778
|
+
</CodeSnippetHeader>
|
|
779
|
+
<CodeEditorContent lineNumbers aria-label='HTTP message' />
|
|
780
|
+
</CodeEditorRoot>
|
|
781
|
+
</div>
|
|
782
|
+
);
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
// --- Parity stories: CodeSnippet above, read-only CodeEditor below, identical props ---
|
|
786
|
+
|
|
787
|
+
interface ParityPairProps {
|
|
788
|
+
testId: string;
|
|
789
|
+
code: string;
|
|
790
|
+
language: CodeEditorLanguage;
|
|
791
|
+
lines?: Record<number, LineConfig>;
|
|
792
|
+
folds?: FoldRegion[];
|
|
793
|
+
/** Initial wrapping for both (the wrap button toggles each one) */
|
|
794
|
+
wrapLines?: boolean;
|
|
795
|
+
size?: CodeSnippetSize;
|
|
796
|
+
maxLines?: number;
|
|
797
|
+
/** Shared chrome (header, tabs, actions), rendered before the content in both roots */
|
|
798
|
+
children?: ReactNode;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
const ParityPair = ({
|
|
802
|
+
testId,
|
|
803
|
+
code,
|
|
804
|
+
language,
|
|
805
|
+
lines,
|
|
806
|
+
folds,
|
|
807
|
+
wrapLines,
|
|
808
|
+
size,
|
|
809
|
+
maxLines,
|
|
810
|
+
children,
|
|
811
|
+
}: ParityPairProps) => (
|
|
812
|
+
<VStack gap={16}>
|
|
813
|
+
<VStack align='start' gap={4}>
|
|
814
|
+
<span className='sb-annotation'>CodeSnippet</span>
|
|
815
|
+
<div style={{ width: '600px' }}>
|
|
816
|
+
<CodeSnippetRoot
|
|
817
|
+
code={code}
|
|
818
|
+
language={language}
|
|
819
|
+
lines={lines}
|
|
820
|
+
folds={folds}
|
|
821
|
+
wrapLines={wrapLines}
|
|
822
|
+
size={size}
|
|
823
|
+
maxLines={maxLines}
|
|
824
|
+
data-testid={`${testId}-snippet`}
|
|
825
|
+
>
|
|
826
|
+
{children}
|
|
827
|
+
<CodeSnippetContent>
|
|
828
|
+
<CodeSnippetLineNumbers />
|
|
829
|
+
<CodeSnippetCode />
|
|
830
|
+
</CodeSnippetContent>
|
|
831
|
+
</CodeSnippetRoot>
|
|
832
|
+
</div>
|
|
833
|
+
</VStack>
|
|
834
|
+
<VStack align='start' gap={4}>
|
|
835
|
+
<span className='sb-annotation'>CodeEditor (readOnly)</span>
|
|
836
|
+
<div style={{ width: '600px' }}>
|
|
837
|
+
<CodeEditorRoot
|
|
838
|
+
value={code}
|
|
839
|
+
language={language}
|
|
840
|
+
lines={lines}
|
|
841
|
+
folds={folds}
|
|
842
|
+
defaultWrapLines={wrapLines}
|
|
843
|
+
size={size}
|
|
844
|
+
maxLines={maxLines}
|
|
845
|
+
readOnly
|
|
846
|
+
data-testid={`${testId}-editor`}
|
|
847
|
+
>
|
|
848
|
+
{children}
|
|
849
|
+
<CodeEditorContent lineNumbers aria-label='Parity editor' />
|
|
850
|
+
</CodeEditorRoot>
|
|
851
|
+
</div>
|
|
852
|
+
</VStack>
|
|
853
|
+
</VStack>
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
/** Header with tabs, a title-less tab strip and header actions — the same element in both roots. */
|
|
857
|
+
const PARITY_HEADER_FRAME = (
|
|
858
|
+
<CodeSnippetHeader>
|
|
859
|
+
<CodeSnippetTabs defaultValue='request'>
|
|
860
|
+
<CodeSnippetTab value='request'>Request</CodeSnippetTab>
|
|
861
|
+
<CodeSnippetTab value='response'>Response</CodeSnippetTab>
|
|
862
|
+
</CodeSnippetTabs>
|
|
863
|
+
<CodeSnippetActions>
|
|
864
|
+
<CodeSnippetWrapButton />
|
|
865
|
+
<CodeSnippetCopyButton />
|
|
866
|
+
<CodeSnippetFullscreenButton />
|
|
867
|
+
</CodeSnippetActions>
|
|
868
|
+
</CodeSnippetHeader>
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
/** Floating actions (no header) — the same element in both roots. */
|
|
872
|
+
const PARITY_FLOATING_FRAME = (
|
|
873
|
+
<CodeSnippetActions>
|
|
874
|
+
<CodeSnippetWrapButton />
|
|
875
|
+
<CodeSnippetCopyButton />
|
|
876
|
+
</CodeSnippetActions>
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Parity check: the same code and props in CodeSnippet and in a read-only CodeEditor should look
|
|
881
|
+
* identical. Accepted differences: a native thin scrollbar, and CodeMirror's caret and selection
|
|
882
|
+
* layer (shown only while focused).
|
|
883
|
+
*/
|
|
884
|
+
export const ParityDefault: StoryFn<typeof meta> = () => (
|
|
885
|
+
<ParityPair testId='parity-default' code={sampleCode} language='text' />
|
|
886
|
+
);
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Parity check with line colours, text prefixes and a tooltipped icon prefix: same stick, same
|
|
890
|
+
* tint, same prefix column.
|
|
891
|
+
*/
|
|
892
|
+
export const ParityLineColors: StoryFn<typeof meta> = () => (
|
|
893
|
+
<ParityPair
|
|
894
|
+
testId='parity-line-colors'
|
|
895
|
+
code={colorsCode}
|
|
896
|
+
language='text'
|
|
897
|
+
lines={parityColorLines}
|
|
898
|
+
/>
|
|
899
|
+
);
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* Parity check with the headers fold collapsed: same chevrons and the same summary row in place
|
|
903
|
+
* of the hidden lines.
|
|
904
|
+
*/
|
|
905
|
+
export const ParityFoldsCollapsed: StoryFn<typeof meta> = () => (
|
|
906
|
+
<ParityPair
|
|
907
|
+
testId='parity-folds-collapsed'
|
|
908
|
+
code={foldableRequestCode}
|
|
909
|
+
language='text'
|
|
910
|
+
folds={parityCollapsedFolds}
|
|
911
|
+
/>
|
|
912
|
+
);
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Parity check for an HTTP request with a JSON body, both under the same Prism provider: token
|
|
916
|
+
* colours come from the same adapter.
|
|
917
|
+
*/
|
|
918
|
+
export const ParityHttpPrism: StoryFn<typeof meta> = () => (
|
|
919
|
+
<CodeSnippetAdapterProvider adapter={loadPrismAdapter}>
|
|
920
|
+
<ParityPair testId='parity-http-prism' code={httpRequestCode} language='http' />
|
|
921
|
+
</CodeSnippetAdapterProvider>
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Parity check for `ranges`: the same bold, coloured spans inside the same tinted lines.
|
|
926
|
+
*/
|
|
927
|
+
export const ParityRanges: StoryFn<typeof meta> = () => (
|
|
928
|
+
<ParityPair testId='parity-ranges' code={rangesCode} language='text' lines={rangeLines} />
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Parity check for wrapped lines: long lines break at the same points and line numbers stay on
|
|
933
|
+
* the first row of each wrapped line.
|
|
934
|
+
*/
|
|
935
|
+
export const ParityWrap: StoryFn<typeof meta> = () => (
|
|
936
|
+
<ParityPair testId='parity-wrap' code={longCode} language='text' wrapLines />
|
|
937
|
+
);
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Parity check for the three sizes: the same font size, line height and gutter padding per size.
|
|
941
|
+
*/
|
|
942
|
+
export const ParitySizes: StoryFn<typeof meta> = () => (
|
|
943
|
+
<VStack gap={24}>
|
|
944
|
+
<ParityPair testId='parity-size-sm' code={bashCode} language='bash' size='sm' />
|
|
945
|
+
<ParityPair testId='parity-size-md' code={bashCode} language='bash' size='md' />
|
|
946
|
+
<ParityPair testId='parity-size-lg' code={bashCode} language='bash' size='lg' />
|
|
947
|
+
</VStack>
|
|
948
|
+
);
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Parity check for the shared frame: a header with tabs and actions, and floating actions
|
|
952
|
+
* without a header, sit in the same place with the same spacing.
|
|
953
|
+
*/
|
|
954
|
+
export const ParityFrame: StoryFn<typeof meta> = () => (
|
|
955
|
+
<VStack gap={24}>
|
|
956
|
+
<ParityPair testId='parity-frame-header' code={sampleCode} language='text'>
|
|
957
|
+
{PARITY_HEADER_FRAME}
|
|
958
|
+
</ParityPair>
|
|
959
|
+
<ParityPair testId='parity-frame-floating' code={sampleCode} language='text'>
|
|
960
|
+
{PARITY_FLOATING_FRAME}
|
|
961
|
+
</ParityPair>
|
|
962
|
+
</VStack>
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Parity check for `maxLines`: the same clamped height and the same "Show N more lines" button.
|
|
967
|
+
*/
|
|
968
|
+
export const ParityShowMore: StoryFn<typeof meta> = () => (
|
|
969
|
+
<ParityPair testId='parity-show-more' code={showMoreCode} language='text' maxLines={7} />
|
|
970
|
+
);
|
|
971
|
+
|
|
972
|
+
// --- Languages ---
|
|
973
|
+
|
|
974
|
+
const PYTHON_SAMPLE = `from dataclasses import dataclass
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
@dataclass
|
|
978
|
+
class Rule:
|
|
979
|
+
action: str
|
|
980
|
+
point: list[str]
|
|
981
|
+
enabled: bool = True
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
def active(rules: list[Rule]) -> list[Rule]:
|
|
985
|
+
return [r for r in rules if r.enabled]
|
|
986
|
+
`;
|
|
987
|
+
const LUA_SAMPLE = `local cjson = require("cjson")
|
|
988
|
+
|
|
989
|
+
local BLOCKED = { "10.0.0.1", "10.0.0.2" }
|
|
990
|
+
|
|
991
|
+
local function check(ctx)
|
|
992
|
+
local ip = ngx.var.remote_addr
|
|
993
|
+
for _, blocked in pairs(BLOCKED) do
|
|
994
|
+
if ip ~= blocked then goto continue end
|
|
995
|
+
ngx.log(ngx.WARN, "blocked ", ip)
|
|
996
|
+
ngx.exit(403)
|
|
997
|
+
::continue::
|
|
998
|
+
end
|
|
999
|
+
ngx.say(cjson.encode({ ok = true, count = #BLOCKED }))
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
return { check = check }
|
|
1003
|
+
`;
|
|
1004
|
+
const JSON_SAMPLE = `{
|
|
1005
|
+
"action": "block",
|
|
1006
|
+
"point": ["header", "X-Forwarded-For"],
|
|
1007
|
+
"enabled": true,
|
|
1008
|
+
"threshold": 42
|
|
1009
|
+
}
|
|
1010
|
+
`;
|
|
1011
|
+
const JAVASCRIPT_SAMPLE = `export async function fetchRules(client, { limit = 50 } = {}) {
|
|
1012
|
+
const res = await client.get('/api/v2/rules', { params: { limit } });
|
|
1013
|
+
return res.data.filter(rule => rule.enabled);
|
|
1014
|
+
}
|
|
1015
|
+
`;
|
|
1016
|
+
const TYPESCRIPT_SAMPLE = `interface Rule {
|
|
1017
|
+
action: 'block' | 'monitor';
|
|
1018
|
+
point: string[];
|
|
1019
|
+
enabled: boolean;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
export const activeRules = (rules: readonly Rule[]): Rule[] =>
|
|
1023
|
+
rules.filter((rule): rule is Rule => rule.enabled);
|
|
1024
|
+
`;
|
|
1025
|
+
const YAML_SAMPLE = `rules:
|
|
1026
|
+
- action: block
|
|
1027
|
+
point: [header, X-Forwarded-For]
|
|
1028
|
+
enabled: true
|
|
1029
|
+
- action: monitor
|
|
1030
|
+
point: [query, id]
|
|
1031
|
+
enabled: false
|
|
1032
|
+
`;
|
|
1033
|
+
|
|
1034
|
+
interface LanguageSample {
|
|
1035
|
+
id: string;
|
|
1036
|
+
label: string;
|
|
1037
|
+
language: CodeEditorLanguage;
|
|
1038
|
+
value: string;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const LANGUAGE_SAMPLES = [
|
|
1042
|
+
{ id: 'python', label: 'Python', language: 'python', value: PYTHON_SAMPLE },
|
|
1043
|
+
{ id: 'json', label: 'JSON', language: 'json', value: JSON_SAMPLE },
|
|
1044
|
+
{ id: 'javascript', label: 'JavaScript', language: 'javascript', value: JAVASCRIPT_SAMPLE },
|
|
1045
|
+
{ id: 'typescript', label: 'TypeScript', language: 'typescript', value: TYPESCRIPT_SAMPLE },
|
|
1046
|
+
{ id: 'yaml', label: 'YAML', language: 'yaml', value: YAML_SAMPLE },
|
|
1047
|
+
{ id: 'lua', label: 'Lua', language: 'lua', value: LUA_SAMPLE },
|
|
1048
|
+
] as const satisfies readonly LanguageSample[];
|
|
1049
|
+
|
|
1050
|
+
const LanguageExample = ({ sample }: { sample: LanguageSample }) => {
|
|
1051
|
+
const [value, setValue] = useState(sample.value);
|
|
1052
|
+
|
|
1053
|
+
return (
|
|
1054
|
+
<VStack align='start' gap={4}>
|
|
1055
|
+
<span className='sb-annotation'>{sample.label}</span>
|
|
1056
|
+
<div style={{ width: '600px' }}>
|
|
1057
|
+
<CodeEditorRoot
|
|
1058
|
+
value={value}
|
|
1059
|
+
onChange={setValue}
|
|
1060
|
+
language={sample.language}
|
|
1061
|
+
data-testid={`lang-${sample.id}`}
|
|
1062
|
+
>
|
|
1063
|
+
<CodeSnippetHeader>
|
|
1064
|
+
<CodeSnippetTitle>{sample.label}</CodeSnippetTitle>
|
|
1065
|
+
<CodeSnippetActions>
|
|
1066
|
+
<CodeSnippetCopyButton />
|
|
1067
|
+
</CodeSnippetActions>
|
|
1068
|
+
</CodeSnippetHeader>
|
|
1069
|
+
<CodeEditorContent lineNumbers aria-label={`${sample.label} example`} />
|
|
1070
|
+
</CodeEditorRoot>
|
|
1071
|
+
</div>
|
|
1072
|
+
</VStack>
|
|
1073
|
+
);
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Colours come from the adapter (Shiki here); JavaScript, TypeScript, Python and Lua parsers load
|
|
1078
|
+
* on first use.
|
|
1079
|
+
*/
|
|
1080
|
+
export const Languages: StoryFn<typeof meta> = () => (
|
|
1081
|
+
<CodeSnippetAdapterProvider adapter={loadShikiAdapter}>
|
|
1082
|
+
<VStack gap={16}>
|
|
1083
|
+
{LANGUAGE_SAMPLES.map(sample => (
|
|
1084
|
+
<LanguageExample key={sample.id} sample={sample} />
|
|
1085
|
+
))}
|
|
1086
|
+
</VStack>
|
|
1087
|
+
</CodeSnippetAdapterProvider>
|
|
1088
|
+
);
|
|
1089
|
+
|
|
1090
|
+
// --- Syntax errors ---
|
|
1091
|
+
|
|
1092
|
+
interface SyntaxErrorSample {
|
|
1093
|
+
language: CodeEditorLanguage;
|
|
1094
|
+
label: string;
|
|
1095
|
+
value: string;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/** One intentionally broken sample per language with a structure parser. */
|
|
1099
|
+
const SYNTAX_ERROR_SAMPLES = [
|
|
1100
|
+
{ language: 'json', label: 'JSON', value: '{\n "action": "block"\n "enabled": true\n}\n' },
|
|
1101
|
+
{ language: 'yaml', label: 'YAML', value: 'rules:\n - action: block\n point: [header, id\n' },
|
|
1102
|
+
{
|
|
1103
|
+
language: 'javascript',
|
|
1104
|
+
label: 'JavaScript',
|
|
1105
|
+
value: 'function fetchRules( {\n return client.get("/api/v2/rules");\n}\n',
|
|
1106
|
+
},
|
|
1107
|
+
{ language: 'typescript', label: 'TypeScript', value: 'let limit: = 50;\n' },
|
|
1108
|
+
{ language: 'python', label: 'Python', value: 'def active(:\n pass\n' },
|
|
1109
|
+
{ language: 'lua', label: 'Lua', value: 'local limit = = 50\nreturn limit\n' },
|
|
1110
|
+
{
|
|
1111
|
+
language: 'http',
|
|
1112
|
+
label: 'HTTP',
|
|
1113
|
+
value: 'POST /rules HTTP/1.1\nContent-Type: application/json\n\n{\n "action": "block",\n}\n',
|
|
1114
|
+
},
|
|
1115
|
+
] as const satisfies readonly SyntaxErrorSample[];
|
|
1116
|
+
|
|
1117
|
+
const SyntaxErrorExample = ({ sample }: { sample: SyntaxErrorSample }) => {
|
|
1118
|
+
const [value, setValue] = useState(sample.value);
|
|
1119
|
+
const [diagnostics, setDiagnostics] = useState<CodeEditorDiagnostic[]>([]);
|
|
1120
|
+
const testId = `syntax-${sample.language}`;
|
|
1121
|
+
|
|
1122
|
+
return (
|
|
1123
|
+
<VStack align='start' gap={4}>
|
|
1124
|
+
<span className='sb-annotation'>{sample.label}</span>
|
|
1125
|
+
<div style={{ width: '600px' }}>
|
|
1126
|
+
<CodeEditorRoot
|
|
1127
|
+
value={value}
|
|
1128
|
+
onChange={setValue}
|
|
1129
|
+
language={sample.language}
|
|
1130
|
+
onDiagnosticsChange={setDiagnostics}
|
|
1131
|
+
data-testid={testId}
|
|
1132
|
+
>
|
|
1133
|
+
<CodeEditorContent lineNumbers aria-label={`Broken ${sample.label} example`} />
|
|
1134
|
+
</CodeEditorRoot>
|
|
1135
|
+
</div>
|
|
1136
|
+
<span className='sb-annotation' data-testid={`${testId}--count`}>
|
|
1137
|
+
{diagnostics.length === 1 ? '1 diagnostic' : `${diagnostics.length} diagnostics`}
|
|
1138
|
+
</span>
|
|
1139
|
+
</VStack>
|
|
1140
|
+
);
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Syntax errors for every language with a structure parser: JSON and an HTTP JSON body use the
|
|
1145
|
+
* precise `JSON.parse` message, JavaScript and TypeScript use Babel, Lua uses luaparse (first error only), YAML and Python report
|
|
1146
|
+
* Lezer error nodes. Hover an underline to read the message; the count below each editor comes from
|
|
1147
|
+
* `onDiagnosticsChange`. Bash and plain text have no syntax diagnostics.
|
|
1148
|
+
*/
|
|
1149
|
+
export const SyntaxErrors: StoryFn<typeof meta> = () => (
|
|
1150
|
+
<CodeSnippetAdapterProvider adapter={loadShikiAdapter}>
|
|
1151
|
+
<VStack gap={16}>
|
|
1152
|
+
{SYNTAX_ERROR_SAMPLES.map(sample => (
|
|
1153
|
+
<SyntaxErrorExample key={sample.language} sample={sample} />
|
|
1154
|
+
))}
|
|
1155
|
+
</VStack>
|
|
1156
|
+
</CodeSnippetAdapterProvider>
|
|
1157
|
+
);
|
|
1158
|
+
|
|
1159
|
+
const DIFF_ORIGINAL = `POST /api/v2/users HTTP/1.1
|
|
1160
|
+
Host: api.wallarm.com
|
|
1161
|
+
Content-Type: application/json
|
|
1162
|
+
X-Request-Id: 42
|
|
1163
|
+
|
|
1164
|
+
{
|
|
1165
|
+
"name": "Ann",
|
|
1166
|
+
"role": "viewer"
|
|
1167
|
+
}`;
|
|
1168
|
+
|
|
1169
|
+
const DIFF_MODIFIED = `POST /api/v2/users HTTP/1.1
|
|
1170
|
+
Host: api.wallarm.com
|
|
1171
|
+
Content-Type: application/json
|
|
1172
|
+
Authorization: Bearer <token>
|
|
1173
|
+
|
|
1174
|
+
{
|
|
1175
|
+
"name": "Ann",
|
|
1176
|
+
"role": "admin"
|
|
1177
|
+
}`;
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* `original` turns on diff mode: added and changed lines read as `success` lines with a `+`,
|
|
1181
|
+
* removed lines as `danger` rows with a `-` and no line number. The rows stay editable, and the
|
|
1182
|
+
* diff updates as you type.
|
|
1183
|
+
*/
|
|
1184
|
+
export const Diff: StoryFn<typeof meta> = () => {
|
|
1185
|
+
const [value, setValue] = useState(DIFF_MODIFIED);
|
|
1186
|
+
|
|
1187
|
+
return (
|
|
1188
|
+
<CodeEditorRoot
|
|
1189
|
+
data-testid='code-editor-diff'
|
|
1190
|
+
language='http'
|
|
1191
|
+
original={DIFF_ORIGINAL}
|
|
1192
|
+
value={value}
|
|
1193
|
+
onChange={setValue}
|
|
1194
|
+
>
|
|
1195
|
+
<CodeEditorContent aria-label='Request draft compared with the stored request' lineNumbers />
|
|
1196
|
+
</CodeEditorRoot>
|
|
1197
|
+
);
|
|
1198
|
+
};
|
|
1199
|
+
|
|
1200
|
+
const DIFF_WRAP_ORIGINAL = `GET /api/v2/rules HTTP/1.1
|
|
1201
|
+
Host: api.wallarm.com
|
|
1202
|
+
X-Debug-Trace: gateway=eu-central-1;route=/api/v2/rules;upstream=rules-service;sampled=true;span=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
|
|
1203
|
+
Accept: application/json`;
|
|
1204
|
+
|
|
1205
|
+
const DIFF_WRAP_MODIFIED = `GET /api/v2/rules HTTP/1.1
|
|
1206
|
+
Host: api.wallarm.com
|
|
1207
|
+
Accept: application/json`;
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
* With wrapping on, a removed line longer than the frame wraps inside its `danger` row and its
|
|
1211
|
+
* `-` marker stays on the first visual row, beside where the line starts.
|
|
1212
|
+
*/
|
|
1213
|
+
export const DiffWrapLines: StoryFn<typeof meta> = () => {
|
|
1214
|
+
const [value, setValue] = useState(DIFF_WRAP_MODIFIED);
|
|
1215
|
+
|
|
1216
|
+
return (
|
|
1217
|
+
<div className='w-480'>
|
|
1218
|
+
<CodeEditorRoot
|
|
1219
|
+
data-testid='code-editor-diff-wrap'
|
|
1220
|
+
language='http'
|
|
1221
|
+
original={DIFF_WRAP_ORIGINAL}
|
|
1222
|
+
value={value}
|
|
1223
|
+
onChange={setValue}
|
|
1224
|
+
defaultWrapLines
|
|
1225
|
+
>
|
|
1226
|
+
<CodeEditorContent aria-label='Request without the debug header' lineNumbers />
|
|
1227
|
+
</CodeEditorRoot>
|
|
1228
|
+
</div>
|
|
1229
|
+
);
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
const analyticsRequest = `POST /api/v1/rules HTTP/1.1
|
|
1233
|
+
Host: api.example.com
|
|
1234
|
+
Content-Type: application/json
|
|
1235
|
+
Authorization: Bearer token123
|
|
1236
|
+
|
|
1237
|
+
{
|
|
1238
|
+
"action": "block"
|
|
1239
|
+
}`;
|
|
1240
|
+
|
|
1241
|
+
const analyticsFolds: FoldRegion[] = [
|
|
1242
|
+
{
|
|
1243
|
+
id: 'headers',
|
|
1244
|
+
startLine: 2,
|
|
1245
|
+
endLine: 4,
|
|
1246
|
+
label: 'Headers',
|
|
1247
|
+
toggleProps: { 'data-analytics-id': 'CODE_EDITOR_FOLD_HEADERS' },
|
|
1248
|
+
summaryProps: { 'data-analytics-id': 'CODE_EDITOR_EXPAND_HEADERS' },
|
|
1249
|
+
},
|
|
1250
|
+
];
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Where analytics attributes land. `data-*` / `aria-*` / `id` on `CodeEditorContent`
|
|
1254
|
+
* reach the typing surface (`role="textbox"`), chrome buttons take them directly, and
|
|
1255
|
+
* fold buttons take them through `toggleProps` / `summaryProps`. Popups drawn by the
|
|
1256
|
+
* editor (autocomplete, tooltips, search panel) are not attributable — see
|
|
1257
|
+
* `CodeEditor/ANALYTICS_GAPS.md`.
|
|
1258
|
+
*/
|
|
1259
|
+
export const AnalyticsAttributes: StoryFn<typeof meta> = () => (
|
|
1260
|
+
<CodeEditorRoot
|
|
1261
|
+
data-testid='analytics-editor'
|
|
1262
|
+
language='http'
|
|
1263
|
+
defaultValue={analyticsRequest}
|
|
1264
|
+
folds={analyticsFolds}
|
|
1265
|
+
>
|
|
1266
|
+
<CodeSnippetHeader>
|
|
1267
|
+
<CodeSnippetTitle>Request</CodeSnippetTitle>
|
|
1268
|
+
<CodeSnippetActions>
|
|
1269
|
+
<CodeSnippetCopyButton data-analytics-id='CODE_EDITOR_COPY' />
|
|
1270
|
+
<CodeSnippetWrapButton data-analytics-id='CODE_EDITOR_WRAP' />
|
|
1271
|
+
<CodeSnippetFullscreenButton data-analytics-id='CODE_EDITOR_FULLSCREEN' />
|
|
1272
|
+
</CodeSnippetActions>
|
|
1273
|
+
</CodeSnippetHeader>
|
|
1274
|
+
<CodeEditorContent
|
|
1275
|
+
aria-label='HTTP request'
|
|
1276
|
+
lineNumbers
|
|
1277
|
+
data-analytics-id='CODE_EDITOR_REQUEST'
|
|
1278
|
+
data-analytics-props='{"surface":"rule-editor"}'
|
|
1279
|
+
/>
|
|
1280
|
+
</CodeEditorRoot>
|
|
1281
|
+
);
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* A controlled HTTP request with header and body folds and a JSON Schema on the body —
|
|
1285
|
+
* `retries` breaks the schema's maximum on purpose, so the underline and its hover message
|
|
1286
|
+
* are part of the example. The editor's description points at `CODE_EDITOR_KEYBOARD_HINT`.
|
|
1287
|
+
*/
|
|
1288
|
+
export const EditingWorkflow: StoryFn<typeof meta> = () => <EditingWorkflowDemo />;
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* Each tab passes its own `documentId`, so switching swaps in that document's undo history,
|
|
1292
|
+
* selection and collapsed folds instead of replacing the text of one shared document.
|
|
1293
|
+
*/
|
|
1294
|
+
export const TabsKeepHistory: StoryFn<typeof meta> = () => <TabsKeepHistoryDemo />;
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* 2 000 read-only lines clamped by `maxLines` — the top of the envelope the colour painter is
|
|
1298
|
+
* built for, where `readOnly` still lets the text be selected, searched and copied.
|
|
1299
|
+
*/
|
|
1300
|
+
export const LongDocument: StoryFn<typeof meta> = () => <LongDocumentDemo />;
|
|
1301
|
+
|
|
1302
|
+
/**
|
|
1303
|
+
* Fullscreen opened from a modal `Drawer` stacks above it: the editor and its buttons take
|
|
1304
|
+
* pointer and keyboard input, and Escape leaves fullscreen while the drawer stays open.
|
|
1305
|
+
*/
|
|
1306
|
+
export const FullscreenInsideDrawer: StoryFn<typeof meta> = () => {
|
|
1307
|
+
const [value, setValue] = useState(jsonCode);
|
|
1308
|
+
|
|
1309
|
+
return (
|
|
1310
|
+
<Drawer>
|
|
1311
|
+
<DrawerTrigger asChild>
|
|
1312
|
+
<Button variant='outline' color='neutral'>
|
|
1313
|
+
Open Drawer
|
|
1314
|
+
</Button>
|
|
1315
|
+
</DrawerTrigger>
|
|
1316
|
+
<DrawerContent>
|
|
1317
|
+
<DrawerHeader>
|
|
1318
|
+
<DrawerTitle>Rule</DrawerTitle>
|
|
1319
|
+
</DrawerHeader>
|
|
1320
|
+
<DrawerBody>
|
|
1321
|
+
<CodeEditorRoot value={value} onChange={setValue} language='json'>
|
|
1322
|
+
<CodeSnippetHeader>
|
|
1323
|
+
<CodeSnippetTitle>rule.json</CodeSnippetTitle>
|
|
1324
|
+
<CodeSnippetActions>
|
|
1325
|
+
<CodeSnippetFullscreenButton />
|
|
1326
|
+
<CodeSnippetCopyButton />
|
|
1327
|
+
</CodeSnippetActions>
|
|
1328
|
+
</CodeSnippetHeader>
|
|
1329
|
+
<CodeEditorContent lineNumbers aria-label='Rule JSON' />
|
|
1330
|
+
</CodeEditorRoot>
|
|
1331
|
+
</DrawerBody>
|
|
1332
|
+
</DrawerContent>
|
|
1333
|
+
</Drawer>
|
|
1334
|
+
);
|
|
1335
|
+
};
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
### CodeEditor/story-content/_storyEditingWorkflow.tsx
|
|
1339
|
+
|
|
1340
|
+
```tsx
|
|
1341
|
+
import { type FC, useState } from 'react';
|
|
1342
|
+
import { CodeSnippetActions } from '../../CodeSnippet/CodeSnippetActions';
|
|
1343
|
+
import { CodeSnippetCopyButton } from '../../CodeSnippet/CodeSnippetCopyButton';
|
|
1344
|
+
import { CodeSnippetFullscreenButton } from '../../CodeSnippet/CodeSnippetFullscreenButton';
|
|
1345
|
+
import { CodeSnippetHeader } from '../../CodeSnippet/CodeSnippetHeader';
|
|
1346
|
+
import { CodeSnippetTitle } from '../../CodeSnippet/CodeSnippetTitle';
|
|
1347
|
+
import { CodeSnippetWrapButton } from '../../CodeSnippet/CodeSnippetWrapButton';
|
|
1348
|
+
import { CodeEditorContent } from '../CodeEditorContent';
|
|
1349
|
+
import { CodeEditorRoot } from '../CodeEditorRoot';
|
|
1350
|
+
import { CODE_EDITOR_KEYBOARD_HINT } from '../lib/keyboardHint';
|
|
1351
|
+
import { EDITING_REQUEST, httpFolds, RULE_SCHEMA } from './_storyFixtures';
|
|
1352
|
+
|
|
1353
|
+
const HINT_ID = 'code-editor-editing-workflow-hint';
|
|
1354
|
+
|
|
1355
|
+
export const EditingWorkflowDemo: FC = () => {
|
|
1356
|
+
const [value, setValue] = useState(EDITING_REQUEST);
|
|
1357
|
+
|
|
1358
|
+
return (
|
|
1359
|
+
<div className='w-640'>
|
|
1360
|
+
<CodeEditorRoot
|
|
1361
|
+
value={value}
|
|
1362
|
+
onChange={setValue}
|
|
1363
|
+
language='http'
|
|
1364
|
+
folds={httpFolds}
|
|
1365
|
+
schema={RULE_SCHEMA}
|
|
1366
|
+
data-testid='editing'
|
|
1367
|
+
>
|
|
1368
|
+
<CodeSnippetHeader>
|
|
1369
|
+
<CodeSnippetTitle>Request</CodeSnippetTitle>
|
|
1370
|
+
<CodeSnippetActions>
|
|
1371
|
+
<CodeSnippetFullscreenButton />
|
|
1372
|
+
<CodeSnippetWrapButton />
|
|
1373
|
+
<CodeSnippetCopyButton />
|
|
1374
|
+
</CodeSnippetActions>
|
|
1375
|
+
</CodeSnippetHeader>
|
|
1376
|
+
<CodeEditorContent lineNumbers aria-label='HTTP request' aria-describedby={HINT_ID} />
|
|
1377
|
+
</CodeEditorRoot>
|
|
1378
|
+
<span id={HINT_ID} className='sr-only'>
|
|
1379
|
+
{CODE_EDITOR_KEYBOARD_HINT}
|
|
1380
|
+
</span>
|
|
1381
|
+
</div>
|
|
1382
|
+
);
|
|
1383
|
+
};
|
|
1384
|
+
|
|
1385
|
+
EditingWorkflowDemo.displayName = 'EditingWorkflowDemo';
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
### CodeEditor/story-content/_storyLongDocument.tsx
|
|
1389
|
+
|
|
1390
|
+
```tsx
|
|
1391
|
+
import type { FC } from 'react';
|
|
1392
|
+
import { CodeEditorContent } from '../CodeEditorContent';
|
|
1393
|
+
import { CodeEditorRoot } from '../CodeEditorRoot';
|
|
1394
|
+
import { LONG_DOCUMENT } from './_storyFixtures';
|
|
1395
|
+
|
|
1396
|
+
export const LongDocumentDemo: FC = () => (
|
|
1397
|
+
<div className='w-640'>
|
|
1398
|
+
<CodeEditorRoot
|
|
1399
|
+
defaultValue={LONG_DOCUMENT}
|
|
1400
|
+
readOnly
|
|
1401
|
+
language='json'
|
|
1402
|
+
maxLines={12}
|
|
1403
|
+
data-testid='long-document'
|
|
1404
|
+
>
|
|
1405
|
+
<CodeEditorContent lineNumbers aria-label='Access log' />
|
|
1406
|
+
</CodeEditorRoot>
|
|
1407
|
+
</div>
|
|
1408
|
+
);
|
|
1409
|
+
|
|
1410
|
+
LongDocumentDemo.displayName = 'LongDocumentDemo';
|
|
1411
|
+
```
|
|
1412
|
+
|
|
1413
|
+
### CodeEditor/story-content/_storyTabsKeepHistory.tsx
|
|
1414
|
+
|
|
1415
|
+
```tsx
|
|
1416
|
+
import { type FC, useState } from 'react';
|
|
1417
|
+
import { CodeSnippetHeader } from '../../CodeSnippet/CodeSnippetHeader';
|
|
1418
|
+
import { CodeSnippetTab } from '../../CodeSnippet/CodeSnippetTab';
|
|
1419
|
+
import { CodeSnippetTabs } from '../../CodeSnippet/CodeSnippetTabs';
|
|
1420
|
+
import { CodeEditorContent } from '../CodeEditorContent';
|
|
1421
|
+
import { CodeEditorRoot } from '../CodeEditorRoot';
|
|
1422
|
+
import { isTabId, TAB_DOCUMENTS, type TabId } from './_storyFixtures';
|
|
1423
|
+
|
|
1424
|
+
export const TabsKeepHistoryDemo: FC = () => {
|
|
1425
|
+
const [tab, setTab] = useState<TabId>('request');
|
|
1426
|
+
const [documents, setDocuments] = useState<Record<TabId, string>>(TAB_DOCUMENTS);
|
|
1427
|
+
|
|
1428
|
+
return (
|
|
1429
|
+
<div className='w-480'>
|
|
1430
|
+
<CodeEditorRoot
|
|
1431
|
+
documentId={tab}
|
|
1432
|
+
value={documents[tab]}
|
|
1433
|
+
onChange={value => setDocuments(previous => ({ ...previous, [tab]: value }))}
|
|
1434
|
+
language='json'
|
|
1435
|
+
data-testid='tabs-editor'
|
|
1436
|
+
>
|
|
1437
|
+
<CodeSnippetHeader>
|
|
1438
|
+
<CodeSnippetTabs
|
|
1439
|
+
value={tab}
|
|
1440
|
+
onValueChange={next => {
|
|
1441
|
+
if (isTabId(next)) setTab(next);
|
|
1442
|
+
}}
|
|
1443
|
+
>
|
|
1444
|
+
<CodeSnippetTab value='request' data-testid='tabs-editor--tab-request'>
|
|
1445
|
+
Request
|
|
1446
|
+
</CodeSnippetTab>
|
|
1447
|
+
<CodeSnippetTab value='response' data-testid='tabs-editor--tab-response'>
|
|
1448
|
+
Response
|
|
1449
|
+
</CodeSnippetTab>
|
|
1450
|
+
</CodeSnippetTabs>
|
|
1451
|
+
</CodeSnippetHeader>
|
|
1452
|
+
<CodeEditorContent lineNumbers aria-label='Rule check payload' />
|
|
1453
|
+
</CodeEditorRoot>
|
|
1454
|
+
</div>
|
|
1455
|
+
);
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
TabsKeepHistoryDemo.displayName = 'TabsKeepHistoryDemo';
|
|
1459
|
+
```
|
|
1460
|
+
|
|
1461
|
+
### CodeEditor/story-content/_storyFixtures.ts
|
|
1462
|
+
|
|
1463
|
+
```tsx
|
|
1464
|
+
import { getHttpFolds } from '../../CodeSnippet/lib/httpFolds';
|
|
1465
|
+
import type { CodeEditorFolds, JsonSchema } from '../types';
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* Line map the E2E suite relies on (`CodeEditor.e2e.ts`): 1 start line, 2 `Host`,
|
|
1469
|
+
* 4 `X-Env: staging`, 7 `"name"`, 9 `"retries": 9` (breaks the schema maximum),
|
|
1470
|
+
* 10 a line longer than the frame. `staging` appears exactly twice (lines 4 and 8).
|
|
1471
|
+
*/
|
|
1472
|
+
export const EDITING_REQUEST = [
|
|
1473
|
+
'POST /api/v1/rules HTTP/1.1',
|
|
1474
|
+
'Host: api.wallarm.example',
|
|
1475
|
+
'Content-Type: application/json',
|
|
1476
|
+
'X-Env: staging',
|
|
1477
|
+
'',
|
|
1478
|
+
'{',
|
|
1479
|
+
' "name": "Block scanners",',
|
|
1480
|
+
' "env": "staging",',
|
|
1481
|
+
' "retries": 9,',
|
|
1482
|
+
' "description": "Blocks requests from known vulnerability scanners on every public endpoint of the API gateway, including the legacy routes kept only for older mobile clients"',
|
|
1483
|
+
'}',
|
|
1484
|
+
].join('\n');
|
|
1485
|
+
|
|
1486
|
+
/** Applies to the JSON body of `EDITING_REQUEST`. Module-level so its identity is stable. */
|
|
1487
|
+
export const RULE_SCHEMA: JsonSchema = {
|
|
1488
|
+
type: 'object',
|
|
1489
|
+
required: ['name', 'env'],
|
|
1490
|
+
properties: {
|
|
1491
|
+
name: { type: 'string', title: 'Rule name' },
|
|
1492
|
+
env: { enum: ['staging', 'production'], description: 'Where the rule is deployed.' },
|
|
1493
|
+
retries: {
|
|
1494
|
+
type: 'integer',
|
|
1495
|
+
minimum: 0,
|
|
1496
|
+
maximum: 5,
|
|
1497
|
+
description: 'How many times a failed check is retried.',
|
|
1498
|
+
},
|
|
1499
|
+
description: { type: 'string' },
|
|
1500
|
+
},
|
|
1501
|
+
};
|
|
1502
|
+
|
|
1503
|
+
/** Headers and body folds recomputed from the edited value (stable reference). */
|
|
1504
|
+
export const httpFolds: CodeEditorFolds = (value, { startingLineNumber }) =>
|
|
1505
|
+
getHttpFolds(value, { startingLineNumber });
|
|
1506
|
+
|
|
1507
|
+
export type TabId = 'request' | 'response';
|
|
1508
|
+
|
|
1509
|
+
export const isTabId = (value: string): value is TabId =>
|
|
1510
|
+
value === 'request' || value === 'response';
|
|
1511
|
+
|
|
1512
|
+
/** Line 3 of each document ends with a quoted string the E2E suite edits. */
|
|
1513
|
+
export const TAB_DOCUMENTS: Record<TabId, string> = {
|
|
1514
|
+
request: ['{', ' "action": "block",', ' "path": "/login"', '}'].join('\n'),
|
|
1515
|
+
response: ['{', ' "status": 403,', ' "reason": "blocked"', '}'].join('\n'),
|
|
1516
|
+
};
|
|
1517
|
+
|
|
1518
|
+
const LONG_DOCUMENT_EVENTS = 1996;
|
|
1519
|
+
|
|
1520
|
+
/** Exactly 2 000 lines — the top of the adapter painter's performance envelope. */
|
|
1521
|
+
export const LONG_DOCUMENT = [
|
|
1522
|
+
'{',
|
|
1523
|
+
' "events": [',
|
|
1524
|
+
...Array.from({ length: LONG_DOCUMENT_EVENTS }, (_, index) => {
|
|
1525
|
+
const id = index + 1;
|
|
1526
|
+
const status = id % 7 === 0 ? 403 : 200;
|
|
1527
|
+
const comma = id === LONG_DOCUMENT_EVENTS ? '' : ',';
|
|
1528
|
+
return ` { "id": ${id}, "method": "GET", "path": "/api/v1/items/${id}", "status": ${status} }${comma}`;
|
|
1529
|
+
}),
|
|
1530
|
+
' ]',
|
|
1531
|
+
'}',
|
|
1532
|
+
].join('\n');
|
|
1533
|
+
```
|