@storyshelf/app 0.6.2 → 0.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 +42 -4
- package/dist/app-types.d.mts +2 -6
- package/dist/asset-manifest.mjs +14 -7
- package/dist/asset-manifest.mjs.map +1 -1
- package/dist/assets/{htmx.min.js → htmx.mjs} +9 -1
- package/dist/assets/htmx.mjs.map +1 -0
- package/dist/assets/mark.mjs +9 -0
- package/dist/assets/mark.mjs.map +1 -0
- package/dist/boot-tasks.mjs +79 -0
- package/dist/boot-tasks.mjs.map +1 -0
- package/dist/build-state-flags.mjs +17 -0
- package/dist/build-state-flags.mjs.map +1 -0
- package/dist/build-state-setup.mjs +74 -0
- package/dist/build-state-setup.mjs.map +1 -0
- package/dist/capture-alerts.mjs +45 -0
- package/dist/capture-alerts.mjs.map +1 -0
- package/dist/capture-process.mjs +58 -0
- package/dist/capture-process.mjs.map +1 -0
- package/dist/capture-setup.mjs +96 -119
- package/dist/capture-setup.mjs.map +1 -1
- package/dist/connections.mjs +33 -0
- package/dist/connections.mjs.map +1 -0
- package/dist/consumer-setup.mjs +57 -0
- package/dist/consumer-setup.mjs.map +1 -0
- package/dist/credential-keys.mjs +1 -2
- package/dist/credentials.mjs +1 -2
- package/dist/git-status.mjs +45 -0
- package/dist/git-status.mjs.map +1 -0
- package/dist/hidden-data.mjs +23 -0
- package/dist/hidden-data.mjs.map +1 -0
- package/dist/index.d.mts +3 -5
- package/dist/index.mjs +204 -127
- package/dist/index.mjs.map +1 -1
- package/dist/insights/budget.mjs +48 -0
- package/dist/insights/budget.mjs.map +1 -0
- package/dist/insights/deps.mjs +20 -0
- package/dist/insights/deps.mjs.map +1 -0
- package/dist/insights/errors.mjs +21 -0
- package/dist/insights/errors.mjs.map +1 -0
- package/dist/insights/health-panel.mjs +39 -0
- package/dist/insights/health-panel.mjs.map +1 -0
- package/dist/insights/job.mjs +102 -0
- package/dist/insights/job.mjs.map +1 -0
- package/dist/insights/load-health.mjs +58 -0
- package/dist/insights/load-health.mjs.map +1 -0
- package/dist/insights/load-triage.mjs +97 -0
- package/dist/insights/load-triage.mjs.map +1 -0
- package/dist/insights/panel.mjs +27 -0
- package/dist/insights/panel.mjs.map +1 -0
- package/dist/insights/request.mjs +112 -0
- package/dist/insights/request.mjs.map +1 -0
- package/dist/insights/stale.mjs +20 -0
- package/dist/insights/stale.mjs.map +1 -0
- package/dist/insights/usage-report.mjs +59 -0
- package/dist/insights/usage-report.mjs.map +1 -0
- package/dist/insights/view.mjs +47 -0
- package/dist/insights/view.mjs.map +1 -0
- package/dist/job-canceller.mjs +13 -0
- package/dist/job-canceller.mjs.map +1 -0
- package/dist/job-queue.mjs +50 -0
- package/dist/job-queue.mjs.map +1 -0
- package/dist/jobs-setup.mjs +131 -0
- package/dist/jobs-setup.mjs.map +1 -0
- package/dist/lifecycle.mjs +93 -22
- package/dist/lifecycle.mjs.map +1 -1
- package/dist/middleware/auth-gate.mjs +5 -4
- package/dist/middleware/auth-gate.mjs.map +1 -1
- package/dist/middleware/csrf.mjs +1 -2
- package/dist/middleware/rate-limit.mjs +42 -35
- package/dist/middleware/rate-limit.mjs.map +1 -1
- package/dist/middleware/request-log.mjs +4 -4
- package/dist/middleware/request-log.mjs.map +1 -1
- package/dist/middleware/require-review.mjs +50 -0
- package/dist/middleware/require-review.mjs.map +1 -0
- package/dist/middleware/require-testing.mjs +40 -0
- package/dist/middleware/require-testing.mjs.map +1 -0
- package/dist/middleware/server-timing.mjs +1 -2
- package/dist/middleware/setup-gate.mjs +1 -2
- package/dist/middleware/setup-gate.mjs.map +1 -1
- package/dist/middleware/store-scope.mjs +13 -4
- package/dist/middleware/store-scope.mjs.map +1 -1
- package/dist/notifications-pause.mjs +32 -0
- package/dist/notifications-pause.mjs.map +1 -0
- package/dist/notify.d.mts +3 -4
- package/dist/notify.mjs +79 -41
- package/dist/notify.mjs.map +1 -1
- package/dist/pages/a11y-violations.mjs +115 -0
- package/dist/pages/a11y-violations.mjs.map +1 -0
- package/dist/pages/admin-ai.mjs +77 -0
- package/dist/pages/admin-ai.mjs.map +1 -0
- package/dist/pages/admin-system-origin.mjs +132 -0
- package/dist/pages/admin-system-origin.mjs.map +1 -0
- package/dist/pages/admin-system-targets.mjs +52 -0
- package/dist/pages/admin-system-targets.mjs.map +1 -0
- package/dist/pages/admin-system.mjs +64 -15
- package/dist/pages/admin-system.mjs.map +1 -1
- package/dist/pages/build-detail.mjs +105 -78
- package/dist/pages/build-detail.mjs.map +1 -1
- package/dist/pages/build-diff-actions.mjs +88 -35
- package/dist/pages/build-diff-actions.mjs.map +1 -1
- package/dist/pages/build-diff-comments.mjs +17 -16
- package/dist/pages/build-diff-comments.mjs.map +1 -1
- package/dist/pages/build-diff-default.mjs +53 -0
- package/dist/pages/build-diff-default.mjs.map +1 -0
- package/dist/pages/build-diff-environment.mjs +81 -0
- package/dist/pages/build-diff-environment.mjs.map +1 -0
- package/dist/pages/build-diff-header.mjs +23 -6
- package/dist/pages/build-diff-header.mjs.map +1 -1
- package/dist/pages/build-diff-insight.mjs +112 -0
- package/dist/pages/build-diff-insight.mjs.map +1 -0
- package/dist/pages/build-diff-model.mjs +74 -12
- package/dist/pages/build-diff-model.mjs.map +1 -1
- package/dist/pages/build-diff-nav.mjs +29 -14
- package/dist/pages/build-diff-nav.mjs.map +1 -1
- package/dist/pages/build-diff-reference.mjs +84 -0
- package/dist/pages/build-diff-reference.mjs.map +1 -0
- package/dist/pages/build-diff-shortcuts.mjs +6 -3
- package/dist/pages/build-diff-shortcuts.mjs.map +1 -1
- package/dist/pages/build-diff-stale.mjs +1 -2
- package/dist/pages/build-diff-usage.mjs +62 -0
- package/dist/pages/build-diff-usage.mjs.map +1 -0
- package/dist/pages/build-diff-viewer.mjs +97 -14
- package/dist/pages/build-diff-viewer.mjs.map +1 -1
- package/dist/pages/build-diff.mjs +37 -22
- package/dist/pages/build-diff.mjs.map +1 -1
- package/dist/pages/build-tests.mjs +73 -0
- package/dist/pages/build-tests.mjs.map +1 -0
- package/dist/pages/component-detail.mjs +248 -0
- package/dist/pages/component-detail.mjs.map +1 -0
- package/dist/pages/component-stories.mjs +167 -0
- package/dist/pages/component-stories.mjs.map +1 -0
- package/dist/pages/compute-jobs.mjs +14 -28
- package/dist/pages/compute-jobs.mjs.map +1 -1
- package/dist/pages/design-links.mjs +181 -0
- package/dist/pages/design-links.mjs.map +1 -0
- package/dist/pages/environment-change.mjs +52 -0
- package/dist/pages/environment-change.mjs.map +1 -0
- package/dist/pages/health-panel.mjs +125 -0
- package/dist/pages/health-panel.mjs.map +1 -0
- package/dist/pages/invite.mjs +1 -2
- package/dist/pages/label-detail.mjs +1 -2
- package/dist/pages/library-grid.mjs +104 -0
- package/dist/pages/library-grid.mjs.map +1 -0
- package/dist/pages/library-model.mjs +46 -0
- package/dist/pages/library-model.mjs.map +1 -0
- package/dist/pages/library-snapshots.mjs +129 -0
- package/dist/pages/library-snapshots.mjs.map +1 -0
- package/dist/pages/library.mjs +113 -220
- package/dist/pages/library.mjs.map +1 -1
- package/dist/pages/login.mjs +1 -2
- package/dist/pages/notifications-paused.mjs +21 -0
- package/dist/pages/notifications-paused.mjs.map +1 -0
- package/dist/pages/passkey-ceremony.mjs +1 -2
- package/dist/pages/profile.mjs +54 -50
- package/dist/pages/profile.mjs.map +1 -1
- package/dist/pages/project-builds-table.mjs +3 -4
- package/dist/pages/project-builds-table.mjs.map +1 -1
- package/dist/pages/project-builds.mjs +52 -23
- package/dist/pages/project-builds.mjs.map +1 -1
- package/dist/pages/project-create.mjs +1 -2
- package/dist/pages/project-settings.mjs +52 -14
- package/dist/pages/project-settings.mjs.map +1 -1
- package/dist/pages/projects-card.mjs +15 -3
- package/dist/pages/projects-card.mjs.map +1 -1
- package/dist/pages/projects.mjs +7 -4
- package/dist/pages/projects.mjs.map +1 -1
- package/dist/pages/review-changeset.mjs +115 -0
- package/dist/pages/review-changeset.mjs.map +1 -0
- package/dist/pages/review-comments.mjs +102 -0
- package/dist/pages/review-comments.mjs.map +1 -0
- package/dist/pages/review-verdict.mjs +101 -0
- package/dist/pages/review-verdict.mjs.map +1 -0
- package/dist/pages/root.mjs +1 -2
- package/dist/pages/settings-ai.mjs +68 -0
- package/dist/pages/settings-ai.mjs.map +1 -0
- package/dist/pages/settings-capture.mjs +123 -0
- package/dist/pages/settings-capture.mjs.map +1 -0
- package/dist/pages/settings-design-credential.mjs +98 -0
- package/dist/pages/settings-design-credential.mjs.map +1 -0
- package/dist/pages/settings-design-links.mjs +178 -0
- package/dist/pages/settings-design-links.mjs.map +1 -0
- package/dist/pages/settings-design.mjs +47 -0
- package/dist/pages/settings-design.mjs.map +1 -0
- package/dist/pages/settings-general.mjs +47 -23
- package/dist/pages/settings-general.mjs.map +1 -1
- package/dist/pages/settings-labels.mjs +44 -4
- package/dist/pages/settings-labels.mjs.map +1 -1
- package/dist/pages/settings-links.mjs +111 -0
- package/dist/pages/settings-links.mjs.map +1 -0
- package/dist/pages/settings-members.mjs +1 -2
- package/dist/pages/settings-notifications-git.mjs +127 -0
- package/dist/pages/settings-notifications-git.mjs.map +1 -0
- package/dist/pages/settings-notifications.mjs +80 -44
- package/dist/pages/settings-notifications.mjs.map +1 -1
- package/dist/pages/settings-tests.mjs +34 -4
- package/dist/pages/settings-tests.mjs.map +1 -1
- package/dist/pages/settings-tokens.mjs +1 -2
- package/dist/pages/settings-webhooks.mjs +1 -2
- package/dist/pages/storybook.mjs +1 -2
- package/dist/pages/target-choices.mjs +38 -0
- package/dist/pages/target-choices.mjs.map +1 -0
- package/dist/publish-setup.mjs +88 -0
- package/dist/publish-setup.mjs.map +1 -0
- package/dist/retention-timer.mjs +12 -12
- package/dist/retention-timer.mjs.map +1 -1
- package/dist/review-events.mjs +47 -0
- package/dist/review-events.mjs.map +1 -0
- package/dist/routers/admin-pages.mjs +46 -5
- package/dist/routers/admin-pages.mjs.map +1 -1
- package/dist/routers/admin-public-origin.mjs +92 -0
- package/dist/routers/admin-public-origin.mjs.map +1 -0
- package/dist/routers/admin.mjs +8 -4
- package/dist/routers/admin.mjs.map +1 -1
- package/dist/routers/assets.mjs +10 -4
- package/dist/routers/assets.mjs.map +1 -1
- package/dist/routers/attempts.mjs +1 -2
- package/dist/routers/auth-sync.mjs +1 -2
- package/dist/routers/auth.mjs +2 -3
- package/dist/routers/baseline-guard.mjs +4 -5
- package/dist/routers/baseline-guard.mjs.map +1 -1
- package/dist/routers/baseline-reference.mjs +72 -0
- package/dist/routers/baseline-reference.mjs.map +1 -0
- package/dist/routers/baselines.handlers.mjs +63 -0
- package/dist/routers/baselines.handlers.mjs.map +1 -0
- package/dist/routers/baselines.mjs +124 -0
- package/dist/routers/baselines.mjs.map +1 -0
- package/dist/routers/build-cancel.mjs +67 -0
- package/dist/routers/build-cancel.mjs.map +1 -0
- package/dist/routers/build-changeset.mjs +69 -0
- package/dist/routers/build-changeset.mjs.map +1 -0
- package/dist/routers/build-reviews.handlers.mjs +85 -0
- package/dist/routers/build-reviews.handlers.mjs.map +1 -0
- package/dist/routers/build-reviews.mjs +73 -0
- package/dist/routers/build-reviews.mjs.map +1 -0
- package/dist/routers/builds.handlers.mjs +65 -60
- package/dist/routers/builds.handlers.mjs.map +1 -1
- package/dist/routers/builds.mjs +77 -19
- package/dist/routers/builds.mjs.map +1 -1
- package/dist/routers/capture-cache.mjs +29 -0
- package/dist/routers/capture-cache.mjs.map +1 -0
- package/dist/routers/capture-config.mjs +34 -0
- package/dist/routers/capture-config.mjs.map +1 -0
- package/dist/routers/comments.mjs +42 -17
- package/dist/routers/comments.mjs.map +1 -1
- package/dist/routers/comparison-image.mjs +29 -0
- package/dist/routers/comparison-image.mjs.map +1 -0
- package/dist/routers/component-catalog.handlers.mjs +70 -0
- package/dist/routers/component-catalog.handlers.mjs.map +1 -0
- package/dist/routers/component.handlers.mjs +120 -0
- package/dist/routers/component.handlers.mjs.map +1 -0
- package/dist/routers/connections.mjs +117 -0
- package/dist/routers/connections.mjs.map +1 -0
- package/dist/routers/design-connect.handlers.mjs +43 -0
- package/dist/routers/design-connect.handlers.mjs.map +1 -0
- package/dist/routers/design.handlers.mjs +113 -0
- package/dist/routers/design.handlers.mjs.map +1 -0
- package/dist/routers/flash.mjs +1 -2
- package/dist/routers/health-report.mjs +3 -5
- package/dist/routers/health-report.mjs.map +1 -1
- package/dist/routers/health.mjs +5 -5
- package/dist/routers/health.mjs.map +1 -1
- package/dist/routers/helpers.mjs +20 -5
- package/dist/routers/helpers.mjs.map +1 -1
- package/dist/routers/htmx.mjs +1 -2
- package/dist/routers/insights-ui.mjs +63 -0
- package/dist/routers/insights-ui.mjs.map +1 -0
- package/dist/routers/insights.handlers.mjs +44 -0
- package/dist/routers/insights.handlers.mjs.map +1 -0
- package/dist/routers/insights.mjs +188 -0
- package/dist/routers/insights.mjs.map +1 -0
- package/dist/routers/labels.mjs +1 -2
- package/dist/routers/links.handlers.mjs +79 -0
- package/dist/routers/links.handlers.mjs.map +1 -0
- package/dist/routers/links.mjs +138 -0
- package/dist/routers/links.mjs.map +1 -0
- package/dist/routers/media.mjs +30 -7
- package/dist/routers/media.mjs.map +1 -1
- package/dist/routers/members.mjs +3 -3
- package/dist/routers/members.mjs.map +1 -1
- package/dist/routers/notification-channels.mjs +18 -25
- package/dist/routers/notification-channels.mjs.map +1 -1
- package/dist/routers/notification-subscriptions.mjs +1 -2
- package/dist/routers/oauth-state.mjs +44 -0
- package/dist/routers/oauth-state.mjs.map +1 -0
- package/dist/routers/preview-base.mjs +37 -0
- package/dist/routers/preview-base.mjs.map +1 -0
- package/dist/routers/preview-token.mjs +50 -0
- package/dist/routers/preview-token.mjs.map +1 -0
- package/dist/routers/profile.mjs +4 -3
- package/dist/routers/profile.mjs.map +1 -1
- package/dist/routers/projects.mjs +18 -3
- package/dist/routers/projects.mjs.map +1 -1
- package/dist/routers/publish-upload.mjs +85 -0
- package/dist/routers/publish-upload.mjs.map +1 -0
- package/dist/routers/published-access.mjs +51 -0
- package/dist/routers/published-access.mjs.map +1 -0
- package/dist/routers/published-compression.mjs +109 -0
- package/dist/routers/published-compression.mjs.map +1 -0
- package/dist/routers/published-files.mjs +69 -0
- package/dist/routers/published-files.mjs.map +1 -0
- package/dist/routers/review-forms.mjs +71 -0
- package/dist/routers/review-forms.mjs.map +1 -0
- package/dist/routers/review-next.mjs +1 -2
- package/dist/routers/review-section.handlers.mjs +84 -0
- package/dist/routers/review-section.handlers.mjs.map +1 -0
- package/dist/routers/review-switch-off.mjs +28 -0
- package/dist/routers/review-switch-off.mjs.map +1 -0
- package/dist/routers/schemas.mjs +141 -24
- package/dist/routers/schemas.mjs.map +1 -1
- package/dist/routers/scoped-models.mjs +21 -0
- package/dist/routers/scoped-models.mjs.map +1 -0
- package/dist/routers/settings-ai.mjs +34 -0
- package/dist/routers/settings-ai.mjs.map +1 -0
- package/dist/routers/settings-capture.mjs +76 -0
- package/dist/routers/settings-capture.mjs.map +1 -0
- package/dist/routers/settings-design.mjs +102 -0
- package/dist/routers/settings-design.mjs.map +1 -0
- package/dist/routers/settings-general.mjs +56 -12
- package/dist/routers/settings-general.mjs.map +1 -1
- package/dist/routers/settings-git-channel.mjs +76 -0
- package/dist/routers/settings-git-channel.mjs.map +1 -0
- package/dist/routers/settings-labels.mjs +28 -3
- package/dist/routers/settings-labels.mjs.map +1 -1
- package/dist/routers/settings-links.mjs +62 -0
- package/dist/routers/settings-links.mjs.map +1 -0
- package/dist/routers/settings-members.mjs +5 -9
- package/dist/routers/settings-members.mjs.map +1 -1
- package/dist/routers/settings-notifications.mjs +16 -12
- package/dist/routers/settings-notifications.mjs.map +1 -1
- package/dist/routers/settings-tokens.mjs +3 -7
- package/dist/routers/settings-tokens.mjs.map +1 -1
- package/dist/routers/settings-webhooks.mjs +8 -26
- package/dist/routers/settings-webhooks.mjs.map +1 -1
- package/dist/routers/settings.handlers.mjs +108 -28
- package/dist/routers/settings.handlers.mjs.map +1 -1
- package/dist/routers/settings.mjs +17 -6
- package/dist/routers/settings.mjs.map +1 -1
- package/dist/routers/signed-storybook.mjs +55 -0
- package/dist/routers/signed-storybook.mjs.map +1 -0
- package/dist/routers/snapshot-groups.mjs +62 -0
- package/dist/routers/snapshot-groups.mjs.map +1 -0
- package/dist/routers/snapshots.mjs +104 -7
- package/dist/routers/snapshots.mjs.map +1 -1
- package/dist/routers/storybook.mjs +57 -104
- package/dist/routers/storybook.mjs.map +1 -1
- package/dist/routers/tokens.mjs +3 -7
- package/dist/routers/tokens.mjs.map +1 -1
- package/dist/routers/ui.mjs +38 -7
- package/dist/routers/ui.mjs.map +1 -1
- package/dist/routers/webhooks.mjs +6 -13
- package/dist/routers/webhooks.mjs.map +1 -1
- package/dist/routers/well-known.mjs +12 -6
- package/dist/routers/well-known.mjs.map +1 -1
- package/dist/routes/api-routes.mjs +92 -0
- package/dist/routes/api-routes.mjs.map +1 -0
- package/dist/routes/classification.mjs +37 -0
- package/dist/routes/classification.mjs.map +1 -0
- package/dist/routes/openapi-classes.mjs +21 -0
- package/dist/routes/openapi-classes.mjs.map +1 -0
- package/dist/routes/page-routes.mjs +103 -0
- package/dist/routes/page-routes.mjs.map +1 -0
- package/dist/runtime.mjs +19 -15
- package/dist/runtime.mjs.map +1 -1
- package/dist/serverless.mjs +4 -0
- package/dist/store.mjs +20 -3
- package/dist/store.mjs.map +1 -1
- package/dist/targets.mjs +45 -0
- package/dist/targets.mjs.map +1 -0
- package/dist/ui/avatar.mjs +1 -2
- package/dist/ui/buttons.mjs +17 -5
- package/dist/ui/buttons.mjs.map +1 -1
- package/dist/ui/code-block.mjs +1 -2
- package/dist/ui/compare-stage.mjs +86 -54
- package/dist/ui/compare-stage.mjs.map +1 -1
- package/dist/ui/csrf-field.mjs +1 -2
- package/dist/ui/css.mjs +1 -2
- package/dist/ui/design-reference.mjs +96 -0
- package/dist/ui/design-reference.mjs.map +1 -0
- package/dist/ui/document.mjs +2 -4
- package/dist/ui/document.mjs.map +1 -1
- package/dist/ui/dropdown.mjs +1 -2
- package/dist/ui/feedback.mjs +1 -2
- package/dist/ui/filter-input.mjs +1 -2
- package/dist/ui/forms.mjs +7 -7
- package/dist/ui/forms.mjs.map +1 -1
- package/dist/ui/icons/icon.mjs +1 -2
- package/dist/ui/icons/paths.mjs +2 -2
- package/dist/ui/icons/paths.mjs.map +1 -1
- package/dist/ui/icons/sprite.mjs +1 -2
- package/dist/ui/kbd.mjs +1 -2
- package/dist/ui/layout.mjs +1 -2
- package/dist/ui/preview-embed.mjs +81 -0
- package/dist/ui/preview-embed.mjs.map +1 -0
- package/dist/ui/progress.mjs +1 -2
- package/dist/ui/segmented.mjs +1 -2
- package/dist/ui/shell/account.mjs +1 -2
- package/dist/ui/shell/bare.mjs +1 -2
- package/dist/ui/shell/boot-script.mjs +1 -2
- package/dist/ui/shell/client-script.mjs +86 -2
- package/dist/ui/shell/client-script.mjs.map +1 -1
- package/dist/ui/shell/nav.mjs +13 -10
- package/dist/ui/shell/nav.mjs.map +1 -1
- package/dist/ui/shell/review-script.mjs +25 -3
- package/dist/ui/shell/review-script.mjs.map +1 -1
- package/dist/ui/shell/sidebar.mjs +3 -4
- package/dist/ui/shell/sidebar.mjs.map +1 -1
- package/dist/ui/shell/topbar.mjs +1 -2
- package/dist/ui/stacks.mjs +1 -2
- package/dist/ui/styles/base.mjs +1 -2
- package/dist/ui/styles/behavior.mjs +1 -2
- package/dist/ui/styles/review-layout.mjs +1 -2
- package/dist/ui/styles/review.mjs +1 -2
- package/dist/ui/styles/tokens.mjs +1 -2
- package/dist/ui/styles.mjs +1 -2
- package/dist/ui/subnav.mjs +1 -2
- package/dist/ui/table.mjs +1 -2
- package/dist/ui/theme.mjs +1 -2
- package/dist/ui/thumbnail.mjs +1 -2
- package/dist/ui/time.mjs +1 -2
- package/package.json +14 -12
- package/dist/asset-paths.mjs +0 -23
- package/dist/asset-paths.mjs.map +0 -1
- package/dist/assets/mark.svg +0 -1
- package/dist/pages/settings-status.mjs +0 -137
- package/dist/pages/settings-status.mjs.map +0 -1
- package/dist/routers/settings-status.mjs +0 -77
- package/dist/routers/settings-status.mjs.map +0 -1
- package/dist/routers/status-configs.mjs +0 -108
- package/dist/routers/status-configs.mjs.map +0 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { Alert } from "../ui/feedback.mjs";
|
|
5
|
+
import { Segmented } from "../ui/segmented.mjs";
|
|
6
|
+
import { CompareStage } from "../ui/compare-stage.mjs";
|
|
7
|
+
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
8
|
+
// src/pages/build-diff-reference.tsx
|
|
9
|
+
function BaselineReferenceNotice(props) {
|
|
10
|
+
const reference = props.reference;
|
|
11
|
+
if (reference.kind === "none") return /* @__PURE__ */ jsx(Alert, {
|
|
12
|
+
tone: "info",
|
|
13
|
+
title: "No baseline at capture",
|
|
14
|
+
children: "This was a new comparison; no baseline existed when it was captured."
|
|
15
|
+
});
|
|
16
|
+
if (reference.kind === "unavailable") return /* @__PURE__ */ jsx(Alert, {
|
|
17
|
+
tone: "warning",
|
|
18
|
+
title: "Baseline reference unavailable",
|
|
19
|
+
children: "The original baseline details or image are unavailable or have changed since this diff was computed. For older records, any image shown may be the current baseline rather than the one used for the diff."
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsxs(Alert, {
|
|
22
|
+
tone: "info",
|
|
23
|
+
title: "Comparison baseline",
|
|
24
|
+
children: [
|
|
25
|
+
reference.defaultBranch ? "Default branch" : "Accepted branch",
|
|
26
|
+
": ",
|
|
27
|
+
reference.branch,
|
|
28
|
+
". Baseline updated ",
|
|
29
|
+
reference.updatedAt,
|
|
30
|
+
".",
|
|
31
|
+
reference.imageAvailable ? "" : " The baseline image is unavailable.",
|
|
32
|
+
reference.build ? ` Reference build ${reference.build.id}, commit ${reference.build.gitSha.slice(0, 7)}.` : " Reference build and commit are unavailable."
|
|
33
|
+
]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** What the Design source is, shown under its controls. */
|
|
37
|
+
const DESIGN_NOTE = "Design reference: not a test. Scaled to the screenshot’s width.";
|
|
38
|
+
/**
|
|
39
|
+
* The comparison stage with a source switch. The baseline stage is always there; each cached design
|
|
40
|
+
* render adds a stage (hidden until chosen) that compares the screenshot with the design using the
|
|
41
|
+
* same side-by-side, swipe and onion tools. A reference only: no diff, score or verdict. Without a
|
|
42
|
+
* render, only the baseline stage is rendered.
|
|
43
|
+
*/
|
|
44
|
+
function ComparisonSources(props) {
|
|
45
|
+
const { baseline, sources, currentSrc, subject } = props;
|
|
46
|
+
if (sources.length === 0) return baseline;
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
48
|
+
"data-compare-sources": true,
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsx(Segmented, {
|
|
51
|
+
label: "Compare against",
|
|
52
|
+
"data-compare-source-switch": true,
|
|
53
|
+
items: [{
|
|
54
|
+
label: "Baseline",
|
|
55
|
+
value: "baseline",
|
|
56
|
+
active: true
|
|
57
|
+
}, ...sources.map((source) => ({
|
|
58
|
+
label: source.label,
|
|
59
|
+
value: source.value
|
|
60
|
+
}))]
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ jsx("div", {
|
|
63
|
+
"data-compare-source": "baseline",
|
|
64
|
+
children: baseline
|
|
65
|
+
}),
|
|
66
|
+
sources.map((source) => /* @__PURE__ */ jsx("div", {
|
|
67
|
+
"data-compare-source": source.value,
|
|
68
|
+
hidden: true,
|
|
69
|
+
children: /* @__PURE__ */ jsx(CompareStage, {
|
|
70
|
+
variant: "design",
|
|
71
|
+
baselineLabel: source.name ? `${source.providerName} · ${source.name}` : "Design",
|
|
72
|
+
baselineSrc: source.src,
|
|
73
|
+
currentSrc,
|
|
74
|
+
diffSrc: null,
|
|
75
|
+
subject,
|
|
76
|
+
note: DESIGN_NOTE
|
|
77
|
+
})
|
|
78
|
+
}, source.value))
|
|
79
|
+
]
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
export { BaselineReferenceNotice, ComparisonSources };
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=build-diff-reference.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-diff-reference.mjs","names":[],"sources":["../../src/pages/build-diff-reference.tsx"],"sourcesContent":["import type { HtmlEscapedString } from \"hono/utils/html\";\nimport type { BaselineReference } from \"../routers/baseline-reference.ts\";\nimport { Alert, CompareStage, Segmented } from \"../ui/components.tsx\";\nimport type { DesignSource } from \"./build-diff-model.ts\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HTML or a promise */\nexport function BaselineReferenceNotice(props: {\n reference: BaselineReference;\n}): HtmlEscapedString | Promise<HtmlEscapedString> {\n const reference = props.reference;\n if (reference.kind === \"none\")\n return (\n <Alert tone=\"info\" title=\"No baseline at capture\">\n This was a new comparison; no baseline existed when it was captured.\n </Alert>\n );\n if (reference.kind === \"unavailable\")\n return (\n <Alert tone=\"warning\" title=\"Baseline reference unavailable\">\n The original baseline details or image are unavailable or have changed since this diff was\n computed. For older records, any image shown may be the current baseline rather than the one\n used for the diff.\n </Alert>\n );\n return (\n <Alert tone=\"info\" title=\"Comparison baseline\">\n {reference.defaultBranch ? \"Default branch\" : \"Accepted branch\"}: {reference.branch}. Baseline\n updated {reference.updatedAt}.\n {reference.imageAvailable ? \"\" : \" The baseline image is unavailable.\"}\n {reference.build\n ? ` Reference build ${reference.build.id}, commit ${reference.build.gitSha.slice(0, 7)}.`\n : \" Reference build and commit are unavailable.\"}\n </Alert>\n );\n}\n\n/** What the Design source is, shown under its controls. */\nconst DESIGN_NOTE = \"Design reference: not a test. Scaled to the screenshot’s width.\";\n\n/**\n * The comparison stage with a source switch. The baseline stage is always there; each cached design\n * render adds a stage (hidden until chosen) that compares the screenshot with the design using the\n * same side-by-side, swipe and onion tools. A reference only: no diff, score or verdict. Without a\n * render, only the baseline stage is rendered.\n */\nexport function ComparisonSources(props: {\n /** The baseline comparison stage. */\n baseline: HtmlEscapedString | Promise<HtmlEscapedString>;\n sources: DesignSource[];\n currentSrc: string;\n /** Accessible description shared by the images, e.g. \"Button / Primary\". */\n subject: string;\n}): HtmlEscapedString | Promise<HtmlEscapedString> {\n const { baseline, sources, currentSrc, subject } = props;\n if (sources.length === 0) return baseline;\n return (\n <div data-compare-sources>\n <Segmented\n label=\"Compare against\"\n data-compare-source-switch\n items={[\n { label: \"Baseline\", value: \"baseline\", active: true },\n ...sources.map((source) => ({ label: source.label, value: source.value })),\n ]}\n />\n <div data-compare-source=\"baseline\">{baseline}</div>\n {sources.map((source) => (\n <div key={source.value} data-compare-source={source.value} hidden>\n <CompareStage\n variant=\"design\"\n baselineLabel={source.name ? `${source.providerName} · ${source.name}` : \"Design\"}\n baselineSrc={source.src}\n currentSrc={currentSrc}\n diffSrc={null}\n subject={subject}\n note={DESIGN_NOTE}\n />\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAMA,SAAgB,wBAAwB,OAEW;CACjD,MAAM,YAAY,MAAM;CACxB,IAAI,UAAU,SAAS,QACrB,OACE,oBAAC,OAAD;EAAO,MAAK;EAAO,OAAM;EAAyB,UAAA;CAE3C,CAAA;CAEX,IAAI,UAAU,SAAS,eACrB,OACE,oBAAC,OAAD;EAAO,MAAK;EAAU,OAAM;EAAiC,UAAA;CAItD,CAAA;CAEX,OACE,qBAAC,OAAD;EAAO,MAAK;EAAO,OAAM;EAAzB,UAAA;GACG,UAAU,gBAAgB,mBAAmB;GAAkB;GAAG,UAAU;GAAO;GAC3E,UAAU;GAAU;GAC5B,UAAU,iBAAiB,KAAK;GAChC,UAAU,QACP,oBAAoB,UAAU,MAAM,GAAG,WAAW,UAAU,MAAM,OAAO,MAAM,GAAG,CAAC,EAAE,KACrF;EACC;;AAEX;;AAGA,MAAM,cAAc;;;;;;;AAQpB,SAAgB,kBAAkB,OAOiB;CACjD,MAAM,EAAE,UAAU,SAAS,YAAY,YAAY;CACnD,IAAI,QAAQ,WAAW,GAAG,OAAO;CACjC,OACE,qBAAC,OAAD;EAAK,wBAAA;EAAL,UAAA;GACE,oBAAC,WAAD;IACE,OAAM;IACN,8BAAA;IACA,OAAO,CACL;KAAE,OAAO;KAAY,OAAO;KAAY,QAAQ;IAAK,GACrD,GAAG,QAAQ,KAAK,YAAY;KAAE,OAAO,OAAO;KAAO,OAAO,OAAO;IAAM,EAAE,CAC3E;GACD,CAAA;GACD,oBAAC,OAAD;IAAK,uBAAoB;IAAY,UAAA;GAAc,CAAA;GAClD,QAAQ,KAAK,WACZ,oBAAC,OAAD;IAAwB,uBAAqB,OAAO;IAAO,QAAA;IACzD,UAAA,oBAAC,cAAD;KACE,SAAQ;KACR,eAAe,OAAO,OAAO,GAAG,OAAO,aAAa,KAAK,OAAO,SAAS;KACzE,aAAa,OAAO;KACR;KACZ,SAAS;KACA;KACT,MAAM;IACP,CAAA;GACE,GAVK,OAAO,KAUZ,CACN;EACE;;AAET"}
|
|
@@ -5,7 +5,7 @@ import { Button } from "../ui/buttons.mjs";
|
|
|
5
5
|
import { Kbd } from "../ui/kbd.mjs";
|
|
6
6
|
import { shortcutsDialog } from "../ui/styles/review-layout.mjs";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
8
|
-
|
|
8
|
+
// src/pages/build-diff-shortcuts.tsx
|
|
9
9
|
const SHORTCUTS = [
|
|
10
10
|
{
|
|
11
11
|
keys: ["j", "→"],
|
|
@@ -15,9 +15,13 @@ const SHORTCUTS = [
|
|
|
15
15
|
keys: ["k", "←"],
|
|
16
16
|
action: "Previous snapshot"
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
keys: ["[", "]"],
|
|
20
|
+
action: "Previous / next browser of this story"
|
|
21
|
+
},
|
|
18
22
|
{
|
|
19
23
|
keys: ["a"],
|
|
20
|
-
action: "Approve"
|
|
24
|
+
action: "Approve (all browsers of the story and mode)"
|
|
21
25
|
},
|
|
22
26
|
{
|
|
23
27
|
keys: ["r"],
|
|
@@ -72,7 +76,6 @@ function ShortcutsDialog() {
|
|
|
72
76
|
]
|
|
73
77
|
});
|
|
74
78
|
}
|
|
75
|
-
//#endregion
|
|
76
79
|
export { ShortcutsDialog };
|
|
77
80
|
|
|
78
81
|
//# sourceMappingURL=build-diff-shortcuts.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-diff-shortcuts.mjs","names":[],"sources":["../../src/pages/build-diff-shortcuts.tsx"],"sourcesContent":["import type { HtmlEscapedString } from \"hono/utils/html\";\nimport { Button, Kbd } from \"../ui/components.tsx\";\nimport { shortcutsDialog } from \"../ui/styles/review-layout.ts\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\nconst SHORTCUTS: { keys: string[]; action: string }[] = [\n { keys: [\"j\", \"→\"], action: \"Next snapshot\" },\n { keys: [\"k\", \"←\"], action: \"Previous snapshot\" },\n { keys: [\"a\"], action: \"Approve\" },\n { keys: [\"r\"], action: \"Reject\" },\n { keys: [\"1\", \"–\", \"5\"], action: \"Side by side, swipe, onion skin, diff, flip\" },\n { keys: [\"f\"], action: \"Cycle zoom (fit, 100%, 200%, 400%)\" },\n { keys: [\"+\", \"–\"], action: \"Zoom in / out\" },\n { keys: [\"t\"], action: \"Flip baseline / current\" },\n { keys: [\"?\"], action: \"Show this help\" },\n];\n\n/** Native dialog listing the review keyboard shortcuts (opened with `?`). */\nexport function ShortcutsDialog(): HtmlEscapedString | Promise<HtmlEscapedString> {\n return (\n <dialog class={shortcutsDialog} data-shortcuts aria-labelledby=\"shortcuts-title\">\n <h2 id=\"shortcuts-title\">Keyboard shortcuts</h2>\n <dl>\n {SHORTCUTS.map((item) => (\n <>\n <dt>\n <Kbd keys={item.keys} />\n </dt>\n <dd>{item.action}</dd>\n </>\n ))}\n </dl>\n <form method=\"dialog\">\n <Button variant=\"secondary\" size=\"sm\" type=\"submit\">\n Close\n </Button>\n </form>\n </dialog>\n );\n}\n"],"mappings":";;;;;;;;AAMA,MAAM,YAAkD;CACtD;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAgB;CAC5C;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAoB;CAChD;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"build-diff-shortcuts.mjs","names":[],"sources":["../../src/pages/build-diff-shortcuts.tsx"],"sourcesContent":["import type { HtmlEscapedString } from \"hono/utils/html\";\nimport { Button, Kbd } from \"../ui/components.tsx\";\nimport { shortcutsDialog } from \"../ui/styles/review-layout.ts\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\nconst SHORTCUTS: { keys: string[]; action: string }[] = [\n { keys: [\"j\", \"→\"], action: \"Next snapshot\" },\n { keys: [\"k\", \"←\"], action: \"Previous snapshot\" },\n { keys: [\"[\", \"]\"], action: \"Previous / next browser of this story\" },\n { keys: [\"a\"], action: \"Approve (all browsers of the story and mode)\" },\n { keys: [\"r\"], action: \"Reject\" },\n { keys: [\"1\", \"–\", \"5\"], action: \"Side by side, swipe, onion skin, diff, flip\" },\n { keys: [\"f\"], action: \"Cycle zoom (fit, 100%, 200%, 400%)\" },\n { keys: [\"+\", \"–\"], action: \"Zoom in / out\" },\n { keys: [\"t\"], action: \"Flip baseline / current\" },\n { keys: [\"?\"], action: \"Show this help\" },\n];\n\n/** Native dialog listing the review keyboard shortcuts (opened with `?`). */\nexport function ShortcutsDialog(): HtmlEscapedString | Promise<HtmlEscapedString> {\n return (\n <dialog class={shortcutsDialog} data-shortcuts aria-labelledby=\"shortcuts-title\">\n <h2 id=\"shortcuts-title\">Keyboard shortcuts</h2>\n <dl>\n {SHORTCUTS.map((item) => (\n <>\n <dt>\n <Kbd keys={item.keys} />\n </dt>\n <dd>{item.action}</dd>\n </>\n ))}\n </dl>\n <form method=\"dialog\">\n <Button variant=\"secondary\" size=\"sm\" type=\"submit\">\n Close\n </Button>\n </form>\n </dialog>\n );\n}\n"],"mappings":";;;;;;;;AAMA,MAAM,YAAkD;CACtD;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAgB;CAC5C;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAoB;CAChD;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAwC;CACpE;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;CAA+C;CACtE;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;CAAS;CAChC;EAAE,MAAM;GAAC;GAAK;GAAK;EAAG;EAAG,QAAQ;CAA8C;CAC/E;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;CAAqC;CAC5D;EAAE,MAAM,CAAC,KAAK,GAAG;EAAG,QAAQ;CAAgB;CAC5C;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;CAA0B;CACjD;EAAE,MAAM,CAAC,GAAG;EAAG,QAAQ;CAAiB;AAC1C;;AAGA,SAAgB,kBAAkE;CAChF,OACE,qBAAC,UAAD;EAAQ,OAAO;EAAiB,kBAAA;EAAe,mBAAgB;EAA/D,UAAA;GACE,oBAAC,MAAD;IAAI,IAAG;IAAkB,UAAA;GAAsB,CAAA;GAC/C,oBAAC,MAAD,EAAA,UACG,UAAU,KAAK,SACd,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UACE,oBAAC,KAAD,EAAK,MAAM,KAAK,KAAO,CAAA,EACrB,CAAA,GACJ,oBAAC,MAAD,EAAA,UAAK,KAAK,OAAW,CAAA,CACrB,EAAA,CAAA,CACH,EACC,CAAA;GACJ,oBAAC,QAAD;IAAM,QAAO;IACX,UAAA,oBAAC,QAAD;KAAQ,SAAQ;KAAY,MAAK;KAAK,MAAK;KAAS,UAAA;IAE5C,CAAA;GACJ,CAAA;EACA;;AAEZ"}
|
|
@@ -5,7 +5,7 @@ import { Button } from "../ui/buttons.mjs";
|
|
|
5
5
|
import { Alert, Meta } from "../ui/feedback.mjs";
|
|
6
6
|
import { HStack, VStack } from "../ui/stacks.mjs";
|
|
7
7
|
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
8
|
-
|
|
8
|
+
// src/pages/build-diff-stale.tsx
|
|
9
9
|
/**
|
|
10
10
|
* Warns that undecided snapshots were compared with a baseline that has since changed.
|
|
11
11
|
* Builds are never recaptured automatically, so the reviewer chooses how to refresh.
|
|
@@ -64,7 +64,6 @@ function StaleSnapshotNotice(props) {
|
|
|
64
64
|
]
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
|
-
//#endregion
|
|
68
67
|
export { StaleBaselineNotice, StaleSnapshotNotice };
|
|
69
68
|
|
|
70
69
|
//# sourceMappingURL=build-diff-stale.mjs.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { Button } from "../ui/buttons.mjs";
|
|
5
|
+
import { Badge } from "../ui/feedback.mjs";
|
|
6
|
+
import { HStack } from "../ui/stacks.mjs";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
8
|
+
import { createUrlBuilder } from "@storyshelf/core/urls";
|
|
9
|
+
// src/pages/build-diff-usage.tsx
|
|
10
|
+
/** Deep link to the upstream component's published story (or its Storybook root). */
|
|
11
|
+
function upstreamPreviewUrl(item, publishedBaseDomain) {
|
|
12
|
+
if (!item.upstreamBuildId) return null;
|
|
13
|
+
const base = createUrlBuilder("/", publishedBaseDomain).storybookBuild(item.upstreamSlug, item.upstreamBuildId);
|
|
14
|
+
return item.upstreamStoryId ? `${base}?storyId=${encodeURIComponent(item.upstreamStoryId)}` : base;
|
|
15
|
+
}
|
|
16
|
+
/** "Uses @acme/ds v2.4.0" provenance badge with Preview and History deep links. */
|
|
17
|
+
function LinkedUsage(props) {
|
|
18
|
+
const urls = createUrlBuilder("/", props.publishedBaseDomain);
|
|
19
|
+
return /* @__PURE__ */ jsx(Fragment, { children: props.usage.map((item) => {
|
|
20
|
+
const preview = upstreamPreviewUrl(item, props.publishedBaseDomain);
|
|
21
|
+
return /* @__PURE__ */ jsxs(HStack, {
|
|
22
|
+
wrap: false,
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsxs(Badge, {
|
|
25
|
+
tone: "info",
|
|
26
|
+
children: [
|
|
27
|
+
"Uses ",
|
|
28
|
+
item.package,
|
|
29
|
+
item.version ? ` v${item.version}` : ""
|
|
30
|
+
]
|
|
31
|
+
}),
|
|
32
|
+
preview ? /* @__PURE__ */ jsx(Button, {
|
|
33
|
+
variant: "ghost",
|
|
34
|
+
size: "sm",
|
|
35
|
+
href: preview,
|
|
36
|
+
target: "_blank",
|
|
37
|
+
rel: "noreferrer",
|
|
38
|
+
children: "Preview"
|
|
39
|
+
}) : null,
|
|
40
|
+
item.upstreamImportPath ? /* @__PURE__ */ jsx(Button, {
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
size: "sm",
|
|
43
|
+
href: urls.component(item.upstreamSlug, item.upstreamImportPath),
|
|
44
|
+
target: "_blank",
|
|
45
|
+
rel: "noreferrer",
|
|
46
|
+
children: "Story →"
|
|
47
|
+
}) : null,
|
|
48
|
+
/* @__PURE__ */ jsx(Button, {
|
|
49
|
+
variant: "ghost",
|
|
50
|
+
size: "sm",
|
|
51
|
+
href: urls.library(item.upstreamSlug),
|
|
52
|
+
target: "_blank",
|
|
53
|
+
rel: "noreferrer",
|
|
54
|
+
children: "History"
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}, item.package);
|
|
58
|
+
}) });
|
|
59
|
+
}
|
|
60
|
+
export { LinkedUsage, upstreamPreviewUrl };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=build-diff-usage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-diff-usage.mjs","names":[],"sources":["../../src/pages/build-diff-usage.tsx"],"sourcesContent":["import { createUrlBuilder } from \"@storyshelf/core/urls\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport { Badge, Button, HStack } from \"../ui/components.tsx\";\n\n/** A linked package a story uses, resolved against its upstream project. */\nexport interface LinkedUsageItem {\n package: string;\n version: string | null;\n upstreamSlug: string;\n /** Latest approved default build of the upstream project, when it has one. */\n upstreamBuildId: string | null;\n /** Upstream story the package module maps to; null when nothing matched. */\n upstreamStoryId: string | null;\n /** Story file of the matched upstream story, for its component page. */\n upstreamImportPath?: string | null;\n}\n\n/** Deep link to the upstream component's published story (or its Storybook root). */\nexport function upstreamPreviewUrl(\n item: LinkedUsageItem,\n publishedBaseDomain?: string,\n): string | null {\n if (!item.upstreamBuildId) {\n return null;\n }\n const base = createUrlBuilder(\"/\", publishedBaseDomain).storybookBuild(\n item.upstreamSlug,\n item.upstreamBuildId,\n );\n return item.upstreamStoryId\n ? `${base}?storyId=${encodeURIComponent(item.upstreamStoryId)}`\n : base;\n}\n\n/** \"Uses @acme/ds v2.4.0\" provenance badge with Preview and History deep links. */\nexport function LinkedUsage(props: {\n usage: LinkedUsageItem[];\n publishedBaseDomain?: string;\n}): HtmlEscapedString | Promise<HtmlEscapedString> {\n const urls = createUrlBuilder(\"/\", props.publishedBaseDomain);\n return (\n <>\n {props.usage.map((item): HtmlEscapedString | Promise<HtmlEscapedString> => {\n const preview = upstreamPreviewUrl(item, props.publishedBaseDomain);\n return (\n <HStack key={item.package} wrap={false}>\n <Badge tone=\"info\">\n Uses {item.package}\n {item.version ? ` v${item.version}` : \"\"}\n </Badge>\n {preview ? (\n <Button variant=\"ghost\" size=\"sm\" href={preview} target=\"_blank\" rel=\"noreferrer\">\n Preview\n </Button>\n ) : null}\n {item.upstreamImportPath ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n href={urls.component(item.upstreamSlug, item.upstreamImportPath)}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n Story →\n </Button>\n ) : null}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n href={urls.library(item.upstreamSlug)}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n History\n </Button>\n </HStack>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAkBA,SAAgB,mBACd,MACA,qBACe;CACf,IAAI,CAAC,KAAK,iBACR,OAAO;CAET,MAAM,OAAO,iBAAiB,KAAK,mBAAmB,CAAC,CAAC,eACtD,KAAK,cACL,KAAK,eACP;CACA,OAAO,KAAK,kBACR,GAAG,KAAK,WAAW,mBAAmB,KAAK,eAAe,MAC1D;AACN;;AAGA,SAAgB,YAAY,OAGuB;CACjD,MAAM,OAAO,iBAAiB,KAAK,MAAM,mBAAmB;CAC5D,OACE,oBAAA,UAAA,EAAA,UACG,MAAM,MAAM,KAAK,SAAyD;EACzE,MAAM,UAAU,mBAAmB,MAAM,MAAM,mBAAmB;EAClE,OACE,qBAAC,QAAD;GAA2B,MAAM;GAAjC,UAAA;IACE,qBAAC,OAAD;KAAO,MAAK;KAAZ,UAAA;MAAmB;MACX,KAAK;MACV,KAAK,UAAU,KAAK,KAAK,YAAY;KACjC;;IACN,UACC,oBAAC,QAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAK,MAAM;KAAS,QAAO;KAAS,KAAI;KAAa,UAAA;IAE1E,CAAA,IACN;IACH,KAAK,qBACJ,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,MAAM,KAAK,UAAU,KAAK,cAAc,KAAK,kBAAkB;KAC/D,QAAO;KACP,KAAI;KACL,UAAA;IAEO,CAAA,IACN;IACJ,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,MAAM,KAAK,QAAQ,KAAK,YAAY;KACpC,QAAO;KACP,KAAI;KACL,UAAA;IAEO,CAAA;GACF;EA9BK,GAAA,KAAK,OA8BV;CAEZ,CAAC,EACD,CAAA;AAEN"}
|
|
@@ -1,21 +1,58 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { Button } from "../ui/buttons.mjs";
|
|
4
5
|
import { Badge, statusTone } from "../ui/feedback.mjs";
|
|
5
6
|
import { VStack } from "../ui/stacks.mjs";
|
|
7
|
+
import { Segmented } from "../ui/segmented.mjs";
|
|
6
8
|
import { CompareStage } from "../ui/compare-stage.mjs";
|
|
9
|
+
import { A11yViolationsNotice, a11yCarrierOf } from "./a11y-violations.mjs";
|
|
10
|
+
import { designSources, diffPercent, snapshotImageUrl, snapshotPageUrl, snapshotVariant } from "./build-diff-model.mjs";
|
|
7
11
|
import { StaleSnapshotNotice } from "./build-diff-stale.mjs";
|
|
12
|
+
import { LinkedUsage } from "./build-diff-usage.mjs";
|
|
13
|
+
import { DesignReferences, DesignStrip } from "./design-links.mjs";
|
|
8
14
|
import { viewerHead, viewerMeta, viewerTitle } from "../ui/styles/review-layout.mjs";
|
|
9
|
-
import {
|
|
15
|
+
import { EnvironmentChangeSnapshotNotice } from "./build-diff-environment.mjs";
|
|
16
|
+
import { DefaultComparisonView } from "./build-diff-default.mjs";
|
|
17
|
+
import { BaselineReferenceNotice, ComparisonSources } from "./build-diff-reference.mjs";
|
|
10
18
|
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
11
|
-
|
|
19
|
+
import { createUrlBuilder } from "@storyshelf/core/urls";
|
|
20
|
+
// src/pages/build-diff-viewer.tsx
|
|
12
21
|
/** Why a snapshot has no diff image, phrased for the empty pane. */
|
|
13
22
|
function diffEmptyText(status) {
|
|
14
23
|
return status === "unchanged" || status === "approved" ? "No diff — within threshold" : "No diff yet";
|
|
15
24
|
}
|
|
25
|
+
/** Browser tabs (one link per engine) when the story/mode was captured on several. */
|
|
26
|
+
function BrowserTabs(props) {
|
|
27
|
+
const { project, build, selected, siblings } = props;
|
|
28
|
+
if (siblings.length < 2) return null;
|
|
29
|
+
return /* @__PURE__ */ jsx(Segmented, {
|
|
30
|
+
label: "Browser",
|
|
31
|
+
"data-browser-tabs": true,
|
|
32
|
+
items: siblings.map((snap) => ({
|
|
33
|
+
label: `${snap.browser ?? "chromium"} · ${snap.status}`,
|
|
34
|
+
value: snap.id,
|
|
35
|
+
href: snapshotPageUrl(project, build, snap.id),
|
|
36
|
+
active: snap.id === selected.id
|
|
37
|
+
}))
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** Link to the story file's component page, anchored at the story. */
|
|
41
|
+
function ViewComponentButton(props) {
|
|
42
|
+
const { project, selected, base } = props;
|
|
43
|
+
if (!selected.storyImportPath) return null;
|
|
44
|
+
const urls = createUrlBuilder("/", base);
|
|
45
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
46
|
+
variant: "ghost",
|
|
47
|
+
size: "sm",
|
|
48
|
+
href: `${urls.component(project.slug, selected.storyImportPath)}#${selected.storyId}`,
|
|
49
|
+
children: "View component"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
16
52
|
/** Story heading plus the comparison stage for the selected snapshot. */
|
|
17
53
|
function DiffViewer(props) {
|
|
18
|
-
const { project, build, selected,
|
|
54
|
+
const { project, build, selected, drifted, usage, design, publishedBaseDomain } = props;
|
|
55
|
+
const siblings = props.siblings ?? [selected];
|
|
19
56
|
const percent = diffPercent(selected);
|
|
20
57
|
return /* @__PURE__ */ jsxs(VStack, { children: [
|
|
21
58
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -36,7 +73,7 @@ function DiffViewer(props) {
|
|
|
36
73
|
children: selected.status
|
|
37
74
|
}),
|
|
38
75
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
39
|
-
selected
|
|
76
|
+
snapshotVariant(selected),
|
|
40
77
|
" · ",
|
|
41
78
|
selected.viewportWidth,
|
|
42
79
|
"×",
|
|
@@ -49,22 +86,68 @@ function DiffViewer(props) {
|
|
|
49
86
|
percent ? /* @__PURE__ */ jsx("span", {
|
|
50
87
|
class: "mono",
|
|
51
88
|
children: percent
|
|
52
|
-
}) : null
|
|
89
|
+
}) : null,
|
|
90
|
+
/* @__PURE__ */ jsx(ViewComponentButton, {
|
|
91
|
+
project,
|
|
92
|
+
selected,
|
|
93
|
+
base: publishedBaseDomain
|
|
94
|
+
})
|
|
53
95
|
]
|
|
54
96
|
})]
|
|
55
97
|
}),
|
|
98
|
+
props.reference ? /* @__PURE__ */ jsx(BaselineReferenceNotice, { reference: props.reference }) : null,
|
|
99
|
+
/* @__PURE__ */ jsx(BrowserTabs, {
|
|
100
|
+
project,
|
|
101
|
+
build,
|
|
102
|
+
selected,
|
|
103
|
+
siblings
|
|
104
|
+
}),
|
|
56
105
|
drifted ? /* @__PURE__ */ jsx(StaleSnapshotNotice, { status: drifted }) : null,
|
|
57
|
-
/* @__PURE__ */ jsx(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
106
|
+
/* @__PURE__ */ jsx(EnvironmentChangeSnapshotNotice, {
|
|
107
|
+
snapshot: selected,
|
|
108
|
+
migrated: build.isDefault
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ jsx(A11yViolationsNotice, { snapshot: a11yCarrierOf(selected, siblings) }),
|
|
111
|
+
usage && usage.length > 0 ? /* @__PURE__ */ jsx(LinkedUsage, {
|
|
112
|
+
usage,
|
|
113
|
+
publishedBaseDomain
|
|
114
|
+
}) : null,
|
|
115
|
+
design && design.length > 0 ? /* @__PURE__ */ jsx(DesignStrip, { items: design }) : null,
|
|
116
|
+
/* @__PURE__ */ jsx(PrimaryComparison, { ...props }),
|
|
117
|
+
/* @__PURE__ */ jsx(SecondaryComparison, { ...props }),
|
|
118
|
+
design && design.length > 0 ? /* @__PURE__ */ jsx(DesignReferences, { items: design }) : null
|
|
65
119
|
] });
|
|
66
120
|
}
|
|
67
|
-
|
|
121
|
+
function SecondaryComparison(props) {
|
|
122
|
+
if (!props.defaultComparison) return null;
|
|
123
|
+
return /* @__PURE__ */ jsx(DefaultComparisonView, {
|
|
124
|
+
...props,
|
|
125
|
+
snapshot: props.selected,
|
|
126
|
+
comparison: props.defaultComparison
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function baselineUrl(props) {
|
|
130
|
+
const { hasBaseline, selected, reference, project, build } = props;
|
|
131
|
+
return hasBaseline[selected.id] && reference?.kind !== "none" && !(reference?.kind === "known" && !reference.imageAvailable) && !(reference?.kind === "unavailable" && selected.baselineVersion !== null) ? snapshotImageUrl(project, build, selected, "baseline") : null;
|
|
132
|
+
}
|
|
133
|
+
function PrimaryComparison(props) {
|
|
134
|
+
const { project, build, selected, reference } = props;
|
|
135
|
+
const stage = /* @__PURE__ */ jsx(CompareStage, {
|
|
136
|
+
baselineSrc: baselineUrl(props),
|
|
137
|
+
baselineEmpty: reference?.kind === "unavailable" || reference?.kind === "known" && !reference.imageAvailable ? "The original baseline image is unavailable." : void 0,
|
|
138
|
+
currentSrc: snapshotImageUrl(project, build, selected, "image"),
|
|
139
|
+
diffSrc: selected.diffPath ? snapshotImageUrl(project, build, selected, "diff") : null,
|
|
140
|
+
subject: `${selected.storyTitle} / ${selected.storyName}`,
|
|
141
|
+
diffEmpty: diffEmptyText(selected.status),
|
|
142
|
+
diffMeta: diffPercent(selected) ?? void 0
|
|
143
|
+
});
|
|
144
|
+
return /* @__PURE__ */ jsx(ComparisonSources, {
|
|
145
|
+
baseline: stage,
|
|
146
|
+
sources: designSources(props.design ?? []),
|
|
147
|
+
currentSrc: snapshotImageUrl(project, build, selected, "image"),
|
|
148
|
+
subject: `${selected.storyTitle} / ${selected.storyName}`
|
|
149
|
+
});
|
|
150
|
+
}
|
|
68
151
|
export { DiffViewer };
|
|
69
152
|
|
|
70
153
|
//# sourceMappingURL=build-diff-viewer.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-diff-viewer.mjs","names":[],"sources":["../../src/pages/build-diff-viewer.tsx"],"sourcesContent":["import type { Build, Project, Snapshot } from \"@storyshelf/core/schema\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport { Badge, CompareStage, VStack, statusTone } from \"../ui/components.tsx\";\nimport { viewerHead, viewerMeta, viewerTitle } from \"../ui/styles/review-layout.ts\";\nimport { diffPercent, snapshotImageUrl } from \"./build-diff-model.ts\";\nimport { StaleSnapshotNotice } from \"./build-diff-stale.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n/** Viewer props for the selected snapshot. */\nexport interface DiffViewerProps {\n project: Project;\n build: Build;\n selected: Snapshot;\n hasBaseline: Record<string, boolean>;\n /** Set when the baseline changed after this snapshot's diff was computed. */\n drifted?: \"stale\" | \"removed\";\n}\n\n/** Why a snapshot has no diff image, phrased for the empty pane. */\nfunction diffEmptyText(status: string): string {\n return status === \"unchanged\" || status === \"approved\"\n ? \"No diff — within threshold\"\n : \"No diff yet\";\n}\n\n/** Story heading plus the comparison stage for the selected snapshot. */\nexport function DiffViewer(props: DiffViewerProps): HtmlEscapedString | Promise<HtmlEscapedString> {\n const { project, build, selected, hasBaseline, drifted } = props;\n const percent = diffPercent(selected);\n return (\n <VStack>\n <div class={viewerHead}>\n <h2 class={viewerTitle}>\n {selected.storyTitle} / {selected.storyName}\n </h2>\n <p class={viewerMeta}>\n <Badge tone={statusTone(selected.status)} icon>\n {selected.status}\n </Badge>\n <span>\n {selected.viewportName} · {selected.viewportWidth}×{selected.viewportHeight}\n </span>\n {selected.diffPixels === null || selected.diffPixels === undefined ? null : (\n <span class=\"mono\">{selected.diffPixels} px</span>\n )}\n {percent ? <span class=\"mono\">{percent}</span> : null}\n </p>\n </div>\n {drifted ? <StaleSnapshotNotice status={drifted} /> : null}\n <CompareStage\n baselineSrc={\n hasBaseline[selected.id] ? snapshotImageUrl(project, build, selected, \"baseline\") : null\n }\n currentSrc={snapshotImageUrl(project, build, selected, \"image\")}\n diffSrc={selected.diffPath ? snapshotImageUrl(project, build, selected, \"diff\") : null}\n subject={`${selected.storyTitle} / ${selected.storyName}`}\n diffEmpty={diffEmptyText(selected.status)}\n diffMeta={percent ?? undefined}\n />\n </VStack>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,SAAS,cAAc,QAAwB;CAC7C,OAAO,WAAW,eAAe,WAAW,aACxC,+BACA;AACN;;AAGA,SAAgB,WAAW,OAAwE;CACjG,MAAM,EAAE,SAAS,OAAO,UAAU,aAAa,YAAY;CAC3D,MAAM,UAAU,YAAY,QAAQ;CACpC,OACE,qBAAC,QAAD,EAAA,UAAA;EACE,qBAAC,OAAD;GAAK,OAAO;GAAZ,UAAA,CACE,qBAAC,MAAD;IAAI,OAAO;IAAX,UAAA;KACG,SAAS;KAAW;KAAI,SAAS;IAChC;GACJ,CAAA,GAAA,qBAAC,KAAD;IAAG,OAAO;IAAV,UAAA;KACE,oBAAC,OAAD;MAAO,MAAM,WAAW,SAAS,MAAM;MAAG,MAAA;MACvC,UAAA,SAAS;KACL,CAAA;KACP,qBAAC,QAAD,EAAA,UAAA;MACG,SAAS;MAAa;MAAI,SAAS;MAAc;MAAE,SAAS;KACzD,EAAA,CAAA;KACL,SAAS,eAAe,QAAQ,SAAS,eAAe,KAAA,IAAY,OACnE,qBAAC,QAAD;MAAM,OAAM;MAAZ,UAAA,CAAoB,SAAS,YAAW,KAAS;;KAElD,UAAU,oBAAC,QAAD;MAAM,OAAM;MAAQ,UAAA;KAAc,CAAA,IAAI;IAChD;GACA,CAAA,CAAA;;EACJ,UAAU,oBAAC,qBAAD,EAAqB,QAAQ,QAAU,CAAA,IAAI;EACtD,oBAAC,cAAD;GACE,aACE,YAAY,SAAS,MAAM,iBAAiB,SAAS,OAAO,UAAU,UAAU,IAAI;GAEtF,YAAY,iBAAiB,SAAS,OAAO,UAAU,OAAO;GAC9D,SAAS,SAAS,WAAW,iBAAiB,SAAS,OAAO,UAAU,MAAM,IAAI;GAClF,SAAS,GAAG,SAAS,WAAW,KAAK,SAAS;GAC9C,WAAW,cAAc,SAAS,MAAM;GACxC,UAAU,WAAW,KAAA;EACtB,CAAA;CACK,EAAA,CAAA;AAEZ"}
|
|
1
|
+
{"version":3,"file":"build-diff-viewer.mjs","names":[],"sources":["../../src/pages/build-diff-viewer.tsx"],"sourcesContent":["import type { Build, Project, Snapshot } from \"@storyshelf/core/schema\";\nimport { createUrlBuilder } from \"@storyshelf/core/urls\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport type { BaselineReference, DefaultComparison } from \"../routers/baseline-reference.ts\";\nimport { Badge, Button, CompareStage, Segmented, VStack, statusTone } from \"../ui/components.tsx\";\nimport { viewerHead, viewerMeta, viewerTitle } from \"../ui/styles/review-layout.ts\";\nimport { A11yViolationsNotice, a11yCarrierOf } from \"./a11y-violations.tsx\";\nimport { DefaultComparisonView } from \"./build-diff-default.tsx\";\nimport { EnvironmentChangeSnapshotNotice } from \"./build-diff-environment.tsx\";\nimport {\n designSources,\n diffPercent,\n snapshotImageUrl,\n snapshotPageUrl,\n snapshotVariant,\n} from \"./build-diff-model.ts\";\nimport { BaselineReferenceNotice, ComparisonSources } from \"./build-diff-reference.tsx\";\nimport { StaleSnapshotNotice } from \"./build-diff-stale.tsx\";\nimport { LinkedUsage, type LinkedUsageItem } from \"./build-diff-usage.tsx\";\nimport { DesignReferences, DesignStrip, type DesignItem } from \"./design-links.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n/** Viewer props for the selected snapshot. */\nexport interface DiffViewerProps {\n project: Project;\n build: Build;\n selected: Snapshot;\n /** The selected story/mode's snapshots on every engine (browser tabs when more than one). */\n siblings?: Snapshot[];\n hasBaseline: Record<string, boolean>;\n reference?: BaselineReference;\n defaultComparison?: DefaultComparison | null;\n /** Set when the baseline changed after this snapshot's diff was computed. */\n drifted?: \"stale\" | \"removed\";\n /** Linked packages the story uses (provenance badges + upstream deep links). */\n usage?: LinkedUsageItem[];\n /** Resolved design links of the story's component (open-in-Figma + stale/deleted notices). */\n design?: DesignItem[];\n publishedBaseDomain?: string;\n}\n\n/** Why a snapshot has no diff image, phrased for the empty pane. */\nfunction diffEmptyText(status: string): string {\n return status === \"unchanged\" || status === \"approved\"\n ? \"No diff — within threshold\"\n : \"No diff yet\";\n}\n\n/** Browser tabs (one link per engine) when the story/mode was captured on several. */\nfunction BrowserTabs(props: {\n project: Project;\n build: Build;\n selected: Snapshot;\n siblings: Snapshot[];\n}): HtmlEscapedString | Promise<HtmlEscapedString> | null {\n const { project, build, selected, siblings } = props;\n if (siblings.length < 2) return null;\n return (\n <Segmented\n label=\"Browser\"\n data-browser-tabs\n items={siblings.map((snap) => ({\n label: `${snap.browser ?? \"chromium\"} · ${snap.status}`,\n value: snap.id,\n href: snapshotPageUrl(project, build, snap.id),\n active: snap.id === selected.id,\n }))}\n />\n );\n}\n\n/** Link to the story file's component page, anchored at the story. */\nfunction ViewComponentButton(props: {\n project: Project;\n selected: Snapshot;\n base?: string;\n}): HtmlEscapedString | Promise<HtmlEscapedString> | null {\n const { project, selected, base } = props;\n if (!selected.storyImportPath) return null;\n const urls = createUrlBuilder(\"/\", base);\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n href={`${urls.component(project.slug, selected.storyImportPath)}#${selected.storyId}`}\n >\n View component\n </Button>\n );\n}\n\n/** Story heading plus the comparison stage for the selected snapshot. */\nexport function DiffViewer(props: DiffViewerProps): HtmlEscapedString | Promise<HtmlEscapedString> {\n const { project, build, selected, drifted, usage, design, publishedBaseDomain } = props;\n const siblings = props.siblings ?? [selected];\n const percent = diffPercent(selected);\n return (\n <VStack>\n <div class={viewerHead}>\n <h2 class={viewerTitle}>\n {selected.storyTitle} / {selected.storyName}\n </h2>\n <p class={viewerMeta}>\n <Badge tone={statusTone(selected.status)} icon>\n {selected.status}\n </Badge>\n <span>\n {snapshotVariant(selected)} · {selected.viewportWidth}×{selected.viewportHeight}\n </span>\n {selected.diffPixels === null || selected.diffPixels === undefined ? null : (\n <span class=\"mono\">{selected.diffPixels} px</span>\n )}\n {percent ? <span class=\"mono\">{percent}</span> : null}\n <ViewComponentButton project={project} selected={selected} base={publishedBaseDomain} />\n </p>\n </div>\n {props.reference ? <BaselineReferenceNotice reference={props.reference} /> : null}\n <BrowserTabs project={project} build={build} selected={selected} siblings={siblings} />\n {drifted ? <StaleSnapshotNotice status={drifted} /> : null}\n <EnvironmentChangeSnapshotNotice snapshot={selected} migrated={build.isDefault} />\n <A11yViolationsNotice snapshot={a11yCarrierOf(selected, siblings)} />\n {usage && usage.length > 0 ? (\n <LinkedUsage usage={usage} publishedBaseDomain={publishedBaseDomain} />\n ) : null}\n {design && design.length > 0 ? <DesignStrip items={design} /> : null}\n <PrimaryComparison {...props} />\n <SecondaryComparison {...props} />\n {design && design.length > 0 ? <DesignReferences items={design} /> : null}\n </VStack>\n );\n}\n\nfunction SecondaryComparison(\n props: DiffViewerProps,\n): HtmlEscapedString | Promise<HtmlEscapedString> | null {\n if (!props.defaultComparison) return null;\n return (\n <DefaultComparisonView\n {...props}\n snapshot={props.selected}\n comparison={props.defaultComparison}\n />\n );\n}\n\nfunction baselineUrl(props: DiffViewerProps): string | null {\n const { hasBaseline, selected, reference, project, build } = props;\n return hasBaseline[selected.id] &&\n reference?.kind !== \"none\" &&\n !(reference?.kind === \"known\" && !reference.imageAvailable) &&\n !(reference?.kind === \"unavailable\" && selected.baselineVersion !== null)\n ? snapshotImageUrl(project, build, selected, \"baseline\")\n : null;\n}\n\nfunction PrimaryComparison(props: DiffViewerProps): HtmlEscapedString | Promise<HtmlEscapedString> {\n const { project, build, selected, reference } = props;\n const stage = (\n <CompareStage\n baselineSrc={baselineUrl(props)}\n baselineEmpty={\n reference?.kind === \"unavailable\" ||\n (reference?.kind === \"known\" && !reference.imageAvailable)\n ? \"The original baseline image is unavailable.\"\n : undefined\n }\n currentSrc={snapshotImageUrl(project, build, selected, \"image\")}\n diffSrc={selected.diffPath ? snapshotImageUrl(project, build, selected, \"diff\") : null}\n subject={`${selected.storyTitle} / ${selected.storyName}`}\n diffEmpty={diffEmptyText(selected.status)}\n diffMeta={diffPercent(selected) ?? undefined}\n />\n );\n return (\n <ComparisonSources\n baseline={stage}\n sources={designSources(props.design ?? [])}\n currentSrc={snapshotImageUrl(project, build, selected, \"image\")}\n subject={`${selected.storyTitle} / ${selected.storyName}`}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2CA,SAAS,cAAc,QAAwB;CAC7C,OAAO,WAAW,eAAe,WAAW,aACxC,+BACA;AACN;;AAGA,SAAS,YAAY,OAKqC;CACxD,MAAM,EAAE,SAAS,OAAO,UAAU,aAAa;CAC/C,IAAI,SAAS,SAAS,GAAG,OAAO;CAChC,OACE,oBAAC,WAAD;EACE,OAAM;EACN,qBAAA;EACA,OAAO,SAAS,KAAK,UAAU;GAC7B,OAAO,GAAG,KAAK,WAAW,WAAW,KAAK,KAAK;GAC/C,OAAO,KAAK;GACZ,MAAM,gBAAgB,SAAS,OAAO,KAAK,EAAE;GAC7C,QAAQ,KAAK,OAAO,SAAS;EAC/B,EAAE;CACH,CAAA;AAEL;;AAGA,SAAS,oBAAoB,OAI6B;CACxD,MAAM,EAAE,SAAS,UAAU,SAAS;CACpC,IAAI,CAAC,SAAS,iBAAiB,OAAO;CACtC,MAAM,OAAO,iBAAiB,KAAK,IAAI;CACvC,OACE,oBAAC,QAAD;EACE,SAAQ;EACR,MAAK;EACL,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,SAAS,eAAe,EAAE,GAAG,SAAS;EAC7E,UAAA;CAEO,CAAA;AAEZ;;AAGA,SAAgB,WAAW,OAAwE;CACjG,MAAM,EAAE,SAAS,OAAO,UAAU,SAAS,OAAO,QAAQ,wBAAwB;CAClF,MAAM,WAAW,MAAM,YAAY,CAAC,QAAQ;CAC5C,MAAM,UAAU,YAAY,QAAQ;CACpC,OACE,qBAAC,QAAD,EAAA,UAAA;EACE,qBAAC,OAAD;GAAK,OAAO;GAAZ,UAAA,CACE,qBAAC,MAAD;IAAI,OAAO;IAAX,UAAA;KACG,SAAS;KAAW;KAAI,SAAS;IAChC;GACJ,CAAA,GAAA,qBAAC,KAAD;IAAG,OAAO;IAAV,UAAA;KACE,oBAAC,OAAD;MAAO,MAAM,WAAW,SAAS,MAAM;MAAG,MAAA;MACvC,UAAA,SAAS;KACL,CAAA;KACP,qBAAC,QAAD,EAAA,UAAA;MACG,gBAAgB,QAAQ;MAAE;MAAI,SAAS;MAAc;MAAE,SAAS;KAC7D,EAAA,CAAA;KACL,SAAS,eAAe,QAAQ,SAAS,eAAe,KAAA,IAAY,OACnE,qBAAC,QAAD;MAAM,OAAM;MAAZ,UAAA,CAAoB,SAAS,YAAW,KAAS;;KAElD,UAAU,oBAAC,QAAD;MAAM,OAAM;MAAQ,UAAA;KAAc,CAAA,IAAI;KACjD,oBAAC,qBAAD;MAA8B;MAAmB;MAAU,MAAM;KAAsB,CAAA;IACtF;GACA,CAAA,CAAA;;EACJ,MAAM,YAAY,oBAAC,yBAAD,EAAyB,WAAW,MAAM,UAAY,CAAA,IAAI;EAC7E,oBAAC,aAAD;GAAsB;GAAgB;GAAiB;GAAoB;EAAW,CAAA;EACrF,UAAU,oBAAC,qBAAD,EAAqB,QAAQ,QAAU,CAAA,IAAI;EACtD,oBAAC,iCAAD;GAAiC,UAAU;GAAU,UAAU,MAAM;EAAY,CAAA;EACjF,oBAAC,sBAAD,EAAsB,UAAU,cAAc,UAAU,QAAQ,EAAI,CAAA;EACnE,SAAS,MAAM,SAAS,IACvB,oBAAC,aAAD;GAAoB;GAA4B;EAAsB,CAAA,IACpE;EACH,UAAU,OAAO,SAAS,IAAI,oBAAC,aAAD,EAAa,OAAO,OAAS,CAAA,IAAI;EAChE,oBAAC,mBAAD,EAAmB,GAAI,MAAQ,CAAA;EAC/B,oBAAC,qBAAD,EAAqB,GAAI,MAAQ,CAAA;EAChC,UAAU,OAAO,SAAS,IAAI,oBAAC,kBAAD,EAAkB,OAAO,OAAS,CAAA,IAAI;CAC/D,EAAA,CAAA;AAEZ;AAEA,SAAS,oBACP,OACuD;CACvD,IAAI,CAAC,MAAM,mBAAmB,OAAO;CACrC,OACE,oBAAC,uBAAD;EACE,GAAI;EACJ,UAAU,MAAM;EAChB,YAAY,MAAM;CACnB,CAAA;AAEL;AAEA,SAAS,YAAY,OAAuC;CAC1D,MAAM,EAAE,aAAa,UAAU,WAAW,SAAS,UAAU;CAC7D,OAAO,YAAY,SAAS,OAC1B,WAAW,SAAS,UACpB,EAAE,WAAW,SAAS,WAAW,CAAC,UAAU,mBAC5C,EAAE,WAAW,SAAS,iBAAiB,SAAS,oBAAoB,QAClE,iBAAiB,SAAS,OAAO,UAAU,UAAU,IACrD;AACN;AAEA,SAAS,kBAAkB,OAAwE;CACjG,MAAM,EAAE,SAAS,OAAO,UAAU,cAAc;CAChD,MAAM,QACJ,oBAAC,cAAD;EACE,aAAa,YAAY,KAAK;EAC9B,eACE,WAAW,SAAS,iBACnB,WAAW,SAAS,WAAW,CAAC,UAAU,iBACvC,gDACA,KAAA;EAEN,YAAY,iBAAiB,SAAS,OAAO,UAAU,OAAO;EAC9D,SAAS,SAAS,WAAW,iBAAiB,SAAS,OAAO,UAAU,MAAM,IAAI;EAClF,SAAS,GAAG,SAAS,WAAW,KAAK,SAAS;EAC9C,WAAW,cAAc,SAAS,MAAM;EACxC,UAAU,YAAY,QAAQ,KAAK,KAAA;CACpC,CAAA;CAEH,OACE,oBAAC,mBAAD;EACE,UAAU;EACV,SAAS,cAAc,MAAM,UAAU,CAAC,CAAC;EACzC,YAAY,iBAAiB,SAAS,OAAO,UAAU,OAAO;EAC9D,SAAS,GAAG,SAAS,WAAW,KAAK,SAAS;CAC/C,CAAA;AAEL"}
|
|
@@ -3,19 +3,26 @@ import "node:url";
|
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { EmptyState } from "../ui/feedback.mjs";
|
|
5
5
|
import { DocumentLayout } from "../ui/document.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { InsightSlot } from "./build-diff-insight.mjs";
|
|
7
|
+
import { groupOf, reviewProgress } from "./build-diff-model.mjs";
|
|
8
|
+
import { DiffComments } from "./build-diff-comments.mjs";
|
|
7
9
|
import { canvasColumn, workspace } from "../ui/styles/review-layout.mjs";
|
|
8
10
|
import { DiffActionBar } from "./build-diff-actions.mjs";
|
|
9
|
-
import {
|
|
11
|
+
import { ReviewNotices } from "./build-diff-environment.mjs";
|
|
10
12
|
import { DiffHeader } from "./build-diff-header.mjs";
|
|
11
13
|
import { DiffNav } from "./build-diff-nav.mjs";
|
|
12
14
|
import { ShortcutsDialog } from "./build-diff-shortcuts.mjs";
|
|
13
15
|
import { DiffViewer } from "./build-diff-viewer.mjs";
|
|
14
16
|
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
15
|
-
|
|
17
|
+
// src/pages/build-diff.tsx
|
|
18
|
+
/** The snapshot the review page shows: the requested one, else the first needing review. */
|
|
19
|
+
function selectedSnapshot(snapshots, selectedId) {
|
|
20
|
+
return snapshots.find((s) => s.id === selectedId) ?? snapshots.find((s) => s.status === "changed" || s.status === "new") ?? snapshots[0];
|
|
21
|
+
}
|
|
16
22
|
/** Snapshot nav plus the viewer/comments column for the selected snapshot. */
|
|
17
23
|
function DiffReviewGrid(props) {
|
|
18
24
|
const { project, build, snapshots, comments, selected, canReview, hasBaseline, drifted } = props;
|
|
25
|
+
const { usage, design, publishedBaseDomain } = props;
|
|
19
26
|
return /* @__PURE__ */ jsxs("div", {
|
|
20
27
|
class: workspace,
|
|
21
28
|
children: [/* @__PURE__ */ jsx(DiffNav, {
|
|
@@ -30,13 +37,20 @@ function DiffReviewGrid(props) {
|
|
|
30
37
|
project,
|
|
31
38
|
build,
|
|
32
39
|
selected,
|
|
40
|
+
siblings: groupOf(snapshots, selected.id)?.members,
|
|
33
41
|
hasBaseline,
|
|
34
|
-
|
|
42
|
+
reference: props.reference,
|
|
43
|
+
defaultComparison: props.defaultComparison,
|
|
44
|
+
drifted: drifted[selected.id],
|
|
45
|
+
usage,
|
|
46
|
+
design,
|
|
47
|
+
publishedBaseDomain
|
|
35
48
|
}),
|
|
36
|
-
/* @__PURE__ */ jsx(DiffComments, {
|
|
49
|
+
project.reviewEnabled === false ? null : /* @__PURE__ */ jsx(DiffComments, {
|
|
37
50
|
project,
|
|
38
51
|
build,
|
|
39
52
|
selectedId: selected.id,
|
|
53
|
+
selectedStoryId: selected.storyId,
|
|
40
54
|
comments,
|
|
41
55
|
canReview
|
|
42
56
|
}),
|
|
@@ -46,7 +60,7 @@ function DiffReviewGrid(props) {
|
|
|
46
60
|
snapshots,
|
|
47
61
|
selected,
|
|
48
62
|
canReview,
|
|
49
|
-
drifted
|
|
63
|
+
drifted
|
|
50
64
|
})
|
|
51
65
|
] }) : /* @__PURE__ */ jsx(EmptyState, { description: "Select a snapshot to review." })
|
|
52
66
|
})]
|
|
@@ -66,9 +80,9 @@ function reviewNav(project, build) {
|
|
|
66
80
|
}
|
|
67
81
|
/** Three-up diff review page: baseline, current, and diff with keyboard review. */
|
|
68
82
|
function renderBuildDiffPage(data) {
|
|
69
|
-
const { project, build, snapshots,
|
|
70
|
-
const selected = snapshots
|
|
71
|
-
const
|
|
83
|
+
const { project, build, snapshots, selectedId, canReview, drifted } = data;
|
|
84
|
+
const selected = selectedSnapshot(snapshots, selectedId);
|
|
85
|
+
const pendingGroups = reviewProgress(snapshots).pending;
|
|
72
86
|
return /* @__PURE__ */ jsxs(DocumentLayout, {
|
|
73
87
|
title: `Review · ${build.gitBranch}`,
|
|
74
88
|
nav: reviewNav(project, build),
|
|
@@ -78,33 +92,34 @@ function renderBuildDiffPage(data) {
|
|
|
78
92
|
project,
|
|
79
93
|
build,
|
|
80
94
|
snapshots,
|
|
81
|
-
pendingCount:
|
|
95
|
+
pendingCount: pendingGroups,
|
|
82
96
|
canReview
|
|
83
97
|
}),
|
|
84
|
-
|
|
98
|
+
/* @__PURE__ */ jsx(ReviewNotices, {
|
|
85
99
|
project,
|
|
86
100
|
build,
|
|
87
|
-
|
|
101
|
+
snapshots,
|
|
102
|
+
drifted,
|
|
88
103
|
canReview
|
|
89
|
-
})
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ jsx(InsightSlot, {
|
|
106
|
+
project,
|
|
107
|
+
build,
|
|
108
|
+
data: data.insight
|
|
109
|
+
}),
|
|
90
110
|
snapshots.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
|
|
91
111
|
title: "No snapshots",
|
|
92
112
|
description: "This build has no snapshots yet. Capture may still be running."
|
|
93
113
|
}) : /* @__PURE__ */ jsx(DiffReviewGrid, {
|
|
94
|
-
|
|
95
|
-
build,
|
|
96
|
-
snapshots,
|
|
97
|
-
comments,
|
|
114
|
+
...data,
|
|
98
115
|
selected,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
drifted
|
|
116
|
+
usage: data.usage ?? [],
|
|
117
|
+
design: data.design ?? []
|
|
102
118
|
}),
|
|
103
119
|
/* @__PURE__ */ jsx(ShortcutsDialog, {})
|
|
104
120
|
]
|
|
105
121
|
});
|
|
106
122
|
}
|
|
107
|
-
|
|
108
|
-
export { renderBuildDiffPage };
|
|
123
|
+
export { renderBuildDiffPage, selectedSnapshot };
|
|
109
124
|
|
|
110
125
|
//# sourceMappingURL=build-diff.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-diff.mjs","names":[],"sources":["../../src/pages/build-diff.tsx"],"sourcesContent":["import type { Build } from \"@storyshelf/core/schema\";\nimport type { Comment } from \"@storyshelf/core/schema\";\nimport type { Project } from \"@storyshelf/core/schema\";\nimport type { Snapshot } from \"@storyshelf/core/schema\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport { EmptyState } from \"../ui/components.tsx\";\nimport { DocumentLayout, type NavConfig, type RenderedContent } from \"../ui/document.tsx\";\nimport { canvasColumn, workspace } from \"../ui/styles/review-layout.ts\";\nimport { DiffActionBar } from \"./build-diff-actions.tsx\";\nimport { DiffComments } from \"./build-diff-comments.tsx\";\nimport { DiffHeader } from \"./build-diff-header.tsx\";\nimport { DiffNav } from \"./build-diff-nav.tsx\";\nimport { ShortcutsDialog } from \"./build-diff-shortcuts.tsx\";\nimport {
|
|
1
|
+
{"version":3,"file":"build-diff.mjs","names":[],"sources":["../../src/pages/build-diff.tsx"],"sourcesContent":["import type { Build } from \"@storyshelf/core/schema\";\nimport type { Comment } from \"@storyshelf/core/schema\";\nimport type { Project } from \"@storyshelf/core/schema\";\nimport type { Snapshot } from \"@storyshelf/core/schema\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport type { InsightPanelData } from \"../insights/panel.ts\";\nimport type { BaselineReference, DefaultComparison } from \"../routers/baseline-reference.ts\";\nimport { EmptyState } from \"../ui/components.tsx\";\nimport { DocumentLayout, type NavConfig, type RenderedContent } from \"../ui/document.tsx\";\nimport { canvasColumn, workspace } from \"../ui/styles/review-layout.ts\";\nimport { DiffActionBar } from \"./build-diff-actions.tsx\";\nimport { DiffComments } from \"./build-diff-comments.tsx\";\nimport { ReviewNotices } from \"./build-diff-environment.tsx\";\nimport { DiffHeader } from \"./build-diff-header.tsx\";\nimport { InsightSlot } from \"./build-diff-insight.tsx\";\nimport { groupOf, reviewProgress } from \"./build-diff-model.ts\";\nimport { DiffNav } from \"./build-diff-nav.tsx\";\nimport { ShortcutsDialog } from \"./build-diff-shortcuts.tsx\";\nimport type { LinkedUsageItem } from \"./build-diff-usage.tsx\";\nimport { DiffViewer } from \"./build-diff-viewer.tsx\";\nimport type { DesignItem } from \"./design-links.tsx\";\n\n/** Data required to render the three-up build diff review page. */\nexport interface BuildDiffData {\n project: Project;\n build: Build;\n snapshots: Snapshot[];\n comments: Comment[];\n selectedId?: string;\n canReview: boolean;\n hasBaseline: Record<string, boolean>;\n reference?: BaselineReference;\n defaultComparison?: DefaultComparison | null;\n /** Open snapshots whose baseline changed after their diff was computed. */\n drifted: Record<string, \"stale\" | \"removed\">;\n /** AI triage panel data; omitted/null hides the panel. */\n insight?: InsightPanelData | null;\n /** Linked packages the selected snapshot's story uses; omitted/empty hides the badges. */\n usage?: LinkedUsageItem[];\n /** Design links the selected snapshot's component resolves to; omitted/empty hides the strip. */\n design?: DesignItem[];\n /** Base domain for published Storybook deep links. */\n publishedBaseDomain?: string;\n}\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ninterface DiffReviewGridProps {\n project: Project;\n build: Build;\n snapshots: Snapshot[];\n comments: Comment[];\n selected?: Snapshot;\n canReview: boolean;\n hasBaseline: Record<string, boolean>;\n reference?: BaselineReference;\n defaultComparison?: DefaultComparison | null;\n drifted: Record<string, \"stale\" | \"removed\">;\n usage: LinkedUsageItem[];\n design: DesignItem[];\n publishedBaseDomain?: string;\n}\n\n/** The snapshot the review page shows: the requested one, else the first needing review. */\nexport function selectedSnapshot(snapshots: Snapshot[], selectedId?: string): Snapshot | undefined {\n return (\n snapshots.find((s) => s.id === selectedId) ??\n snapshots.find((s) => s.status === \"changed\" || s.status === \"new\") ??\n snapshots[0]\n );\n}\n\n/** Snapshot nav plus the viewer/comments column for the selected snapshot. */\nfunction DiffReviewGrid(\n props: DiffReviewGridProps,\n): HtmlEscapedString | Promise<HtmlEscapedString> {\n const { project, build, snapshots, comments, selected, canReview, hasBaseline, drifted } = props;\n const { usage, design, publishedBaseDomain } = props;\n return (\n <div class={workspace}>\n <DiffNav project={project} build={build} snapshots={snapshots} selectedId={selected?.id} />\n <div class={canvasColumn}>\n {selected ? (\n <>\n <DiffViewer\n project={project}\n build={build}\n selected={selected}\n siblings={groupOf(snapshots, selected.id)?.members}\n hasBaseline={hasBaseline}\n reference={props.reference}\n defaultComparison={props.defaultComparison}\n drifted={drifted[selected.id]}\n usage={usage}\n design={design}\n publishedBaseDomain={publishedBaseDomain}\n />\n {project.reviewEnabled === false ? null : (\n <DiffComments\n project={project}\n build={build}\n selectedId={selected.id}\n selectedStoryId={selected.storyId}\n comments={comments}\n canReview={canReview}\n />\n )}\n <DiffActionBar\n project={project}\n build={build}\n snapshots={snapshots}\n selected={selected}\n canReview={canReview}\n drifted={drifted}\n />\n </>\n ) : (\n <EmptyState description=\"Select a snapshot to review.\" />\n )}\n </div>\n </div>\n );\n}\n\n/** Sidebar/breadcrumb context for the review page: Builds / <build> / Review. */\nfunction reviewNav(project: Project, build: Build): NavConfig {\n return {\n active: \"builds\",\n projectSlug: project.slug,\n projectName: project.name,\n trail: [\n {\n label: `${build.gitBranch} · ${build.gitSha.slice(0, 7)}`,\n href: `/projects/${project.slug}/builds/${build.id}`,\n },\n { label: \"Review\" },\n ],\n };\n}\n\n/** Three-up diff review page: baseline, current, and diff with keyboard review. */\nexport function renderBuildDiffPage(data: BuildDiffData): RenderedContent {\n const { project, build, snapshots, selectedId, canReview, drifted } = data;\n const selected = selectedSnapshot(snapshots, selectedId);\n const pendingGroups = reviewProgress(snapshots).pending;\n return (\n <DocumentLayout\n title={`Review · ${build.gitBranch}`}\n nav={reviewNav(project, build)}\n layout=\"wide\"\n >\n <DiffHeader\n project={project}\n build={build}\n snapshots={snapshots}\n pendingCount={pendingGroups}\n canReview={canReview}\n />\n <ReviewNotices\n project={project}\n build={build}\n snapshots={snapshots}\n drifted={drifted}\n canReview={canReview}\n />\n <InsightSlot project={project} build={build} data={data.insight} />\n {snapshots.length === 0 ? (\n <EmptyState\n title=\"No snapshots\"\n description=\"This build has no snapshots yet. Capture may still be running.\"\n />\n ) : (\n <DiffReviewGrid\n {...data}\n selected={selected}\n usage={data.usage ?? []}\n design={data.design ?? []}\n />\n )}\n <ShortcutsDialog />\n </DocumentLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgEA,SAAgB,iBAAiB,WAAuB,YAA2C;CACjG,OACE,UAAU,MAAM,MAAM,EAAE,OAAO,UAAU,KACzC,UAAU,MAAM,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW,KAAK,KAClE,UAAU;AAEd;;AAGA,SAAS,eACP,OACgD;CAChD,MAAM,EAAE,SAAS,OAAO,WAAW,UAAU,UAAU,WAAW,aAAa,YAAY;CAC3F,MAAM,EAAE,OAAO,QAAQ,wBAAwB;CAC/C,OACE,qBAAC,OAAD;EAAK,OAAO;EAAZ,UAAA,CACE,oBAAC,SAAD;GAAkB;GAAgB;GAAkB;GAAW,YAAY,UAAU;EAAK,CAAA,GAC1F,oBAAC,OAAD;GAAK,OAAO;GACT,UAAA,WACC,qBAAA,UAAA,EAAA,UAAA;IACE,oBAAC,YAAD;KACW;KACF;KACG;KACV,UAAU,QAAQ,WAAW,SAAS,EAAE,CAAC,EAAE;KAC9B;KACb,WAAW,MAAM;KACjB,mBAAmB,MAAM;KACzB,SAAS,QAAQ,SAAS;KACnB;KACC;KACa;IACtB,CAAA;IACA,QAAQ,kBAAkB,QAAQ,OACjC,oBAAC,cAAD;KACW;KACF;KACP,YAAY,SAAS;KACrB,iBAAiB,SAAS;KAChB;KACC;IACZ,CAAA;IAEH,oBAAC,eAAD;KACW;KACF;KACI;KACD;KACC;KACF;IACV,CAAA;GACD,EAAA,CAAA,IAEF,oBAAC,YAAD,EAAY,aAAY,+BAAgC,CAAA;EAEvD,CAAA,CACF;;AAET;;AAGA,SAAS,UAAU,SAAkB,OAAyB;CAC5D,OAAO;EACL,QAAQ;EACR,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,OAAO,CACL;GACE,OAAO,GAAG,MAAM,UAAU,KAAK,MAAM,OAAO,MAAM,GAAG,CAAC;GACtD,MAAM,aAAa,QAAQ,KAAK,UAAU,MAAM;EAClD,GACA,EAAE,OAAO,SAAS,CACpB;CACF;AACF;;AAGA,SAAgB,oBAAoB,MAAsC;CACxE,MAAM,EAAE,SAAS,OAAO,WAAW,YAAY,WAAW,YAAY;CACtE,MAAM,WAAW,iBAAiB,WAAW,UAAU;CACvD,MAAM,gBAAgB,eAAe,SAAS,CAAC,CAAC;CAChD,OACE,qBAAC,gBAAD;EACE,OAAO,YAAY,MAAM;EACzB,KAAK,UAAU,SAAS,KAAK;EAC7B,QAAO;EAHT,UAAA;GAKE,oBAAC,YAAD;IACW;IACF;IACI;IACX,cAAc;IACH;GACZ,CAAA;GACD,oBAAC,eAAD;IACW;IACF;IACI;IACF;IACE;GACZ,CAAA;GACD,oBAAC,aAAD;IAAsB;IAAgB;IAAO,MAAM,KAAK;GAAU,CAAA;GACjE,UAAU,WAAW,IACpB,oBAAC,YAAD;IACE,OAAM;IACN,aAAY;GACb,CAAA,IAED,oBAAC,gBAAD;IACE,GAAI;IACM;IACV,OAAO,KAAK,SAAS,CAAC;IACtB,QAAQ,KAAK,UAAU,CAAC;GACzB,CAAA;GAEH,oBAAC,iBAAD,CAAkB,CAAA;EACJ;;AAEpB"}
|