@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,104 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { getStore } from "../store.mjs";
|
|
5
|
+
import { Button } from "../ui/buttons.mjs";
|
|
6
|
+
import { Badge, Meta } from "../ui/feedback.mjs";
|
|
7
|
+
import { Card, CardSection, SectionTitle } from "../ui/layout.mjs";
|
|
8
|
+
import { HStack, VStack } from "../ui/stacks.mjs";
|
|
9
|
+
import { SnapshotCards } from "./library-snapshots.mjs";
|
|
10
|
+
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
11
|
+
import { createUrlBuilder } from "@storyshelf/core/urls";
|
|
12
|
+
// src/pages/library-grid.tsx
|
|
13
|
+
/** The component cards of a build; `layer` is present only with `testing` and captured snapshots. */
|
|
14
|
+
function LibraryGrid(props) {
|
|
15
|
+
return /* @__PURE__ */ jsx(VStack, { children: props.groups.map((group) => /* @__PURE__ */ jsx(LibraryCard, {
|
|
16
|
+
group,
|
|
17
|
+
project: props.project,
|
|
18
|
+
build: props.build,
|
|
19
|
+
layer: props.layer
|
|
20
|
+
}, group.title)) });
|
|
21
|
+
}
|
|
22
|
+
function LibraryCard(props) {
|
|
23
|
+
const { group, project, build, layer } = props;
|
|
24
|
+
const href = componentHref(project, group);
|
|
25
|
+
const captured = layer ? group.stories.flatMap((story) => layer.byStory.get(story.id) ?? []) : [];
|
|
26
|
+
const plain = group.stories.filter((story) => !layer?.byStory.has(story.id));
|
|
27
|
+
return /* @__PURE__ */ jsxs(Card, {
|
|
28
|
+
padded: false,
|
|
29
|
+
"data-filter-item": true,
|
|
30
|
+
"data-filter-text": `${group.title} ${group.stories.map((story) => story.name).join(" ")}`,
|
|
31
|
+
children: [/* @__PURE__ */ jsxs(CardSection, {
|
|
32
|
+
divider: true,
|
|
33
|
+
children: [/* @__PURE__ */ jsx(SectionTitle, { children: href ? /* @__PURE__ */ jsx("a", {
|
|
34
|
+
href,
|
|
35
|
+
children: group.title
|
|
36
|
+
}) : group.title }), /* @__PURE__ */ jsxs(HStack, { children: [
|
|
37
|
+
group.tags.map((tag) => /* @__PURE__ */ jsx(Badge, {
|
|
38
|
+
tone: "neutral",
|
|
39
|
+
children: tag
|
|
40
|
+
}, tag)),
|
|
41
|
+
/* @__PURE__ */ jsxs(Meta, {
|
|
42
|
+
as: "span",
|
|
43
|
+
children: [
|
|
44
|
+
group.stories.length,
|
|
45
|
+
" ",
|
|
46
|
+
group.stories.length === 1 ? "story" : "stories"
|
|
47
|
+
]
|
|
48
|
+
}),
|
|
49
|
+
/* @__PURE__ */ jsx(DocsLink, {
|
|
50
|
+
group,
|
|
51
|
+
project,
|
|
52
|
+
build
|
|
53
|
+
})
|
|
54
|
+
] })]
|
|
55
|
+
}), /* @__PURE__ */ jsx(CardSection, { children: /* @__PURE__ */ jsxs(VStack, { children: [layer && captured.length > 0 ? /* @__PURE__ */ jsx(SnapshotCards, {
|
|
56
|
+
snapshots: captured,
|
|
57
|
+
project,
|
|
58
|
+
buildId: build.id,
|
|
59
|
+
layer,
|
|
60
|
+
componentHref: href
|
|
61
|
+
}) : null, plain.length > 0 ? /* @__PURE__ */ jsx(StoryLinks, {
|
|
62
|
+
stories: plain,
|
|
63
|
+
project,
|
|
64
|
+
build
|
|
65
|
+
}) : null] }) })]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Component page of a group (its story file), when the index names one. */
|
|
69
|
+
function componentHref(project, group) {
|
|
70
|
+
return group.importPath ? createUrlBuilder("/", getStore().config.publishedBaseDomain).component(project.slug, group.importPath) : void 0;
|
|
71
|
+
}
|
|
72
|
+
function DocsLink(props) {
|
|
73
|
+
const docs = props.group.docs[0];
|
|
74
|
+
if (!docs) return null;
|
|
75
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
76
|
+
variant: "ghost",
|
|
77
|
+
size: "sm",
|
|
78
|
+
icon: "book",
|
|
79
|
+
href: `/projects/${props.project.slug}/storybook/build/${props.build.id}/?storyId=${encodeURIComponent(docs.id)}&viewMode=docs`,
|
|
80
|
+
target: "_blank",
|
|
81
|
+
rel: "noopener",
|
|
82
|
+
children: "Docs"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/** Links into the published Storybook, one per story, for stories without a snapshot. */
|
|
86
|
+
function StoryLinks(props) {
|
|
87
|
+
const base = createUrlBuilder("/", getStore().config.publishedBaseDomain).storybookBuild(props.project.slug, props.build.id);
|
|
88
|
+
return /* @__PURE__ */ jsx(HStack, { children: props.stories.map((story) => /* @__PURE__ */ jsx("span", {
|
|
89
|
+
"data-filter-item": true,
|
|
90
|
+
"data-filter-text": `${story.title} ${story.name}`,
|
|
91
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
92
|
+
variant: "ghost",
|
|
93
|
+
size: "sm",
|
|
94
|
+
icon: "external-link",
|
|
95
|
+
href: `${base}/?storyId=${encodeURIComponent(story.id)}`,
|
|
96
|
+
target: "_blank",
|
|
97
|
+
rel: "noopener",
|
|
98
|
+
children: story.name
|
|
99
|
+
})
|
|
100
|
+
}, story.id)) });
|
|
101
|
+
}
|
|
102
|
+
export { LibraryGrid };
|
|
103
|
+
|
|
104
|
+
//# sourceMappingURL=library-grid.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-grid.mjs","names":[],"sources":["../../src/pages/library-grid.tsx"],"sourcesContent":["/** The library's component list: one card per title, from the catalog, with snapshots layered on. */\nimport type { Build, Project } from \"@storyshelf/core/schema\";\nimport { createUrlBuilder } from \"@storyshelf/core/urls\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport { getStore } from \"../store.ts\";\nimport {\n Badge,\n Button,\n Card,\n CardSection,\n HStack,\n Meta,\n SectionTitle,\n VStack,\n} from \"../ui/components.tsx\";\nimport type { LibraryGroup } from \"./library-model.ts\";\nimport { SnapshotCards, type SnapshotLayer } from \"./library-snapshots.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype Rendered = HtmlEscapedString | Promise<HtmlEscapedString>;\n\n/** The component cards of a build; `layer` is present only with `testing` and captured snapshots. */\nexport function LibraryGrid(props: {\n groups: LibraryGroup[];\n project: Project;\n build: Build;\n layer: SnapshotLayer | null;\n}): Rendered {\n return (\n <VStack>\n {props.groups.map((group): Rendered => (\n <LibraryCard\n key={group.title}\n group={group}\n project={props.project}\n build={props.build}\n layer={props.layer}\n />\n ))}\n </VStack>\n );\n}\n\nfunction LibraryCard(props: {\n group: LibraryGroup;\n project: Project;\n build: Build;\n layer: SnapshotLayer | null;\n}): Rendered {\n const { group, project, build, layer } = props;\n const href = componentHref(project, group);\n const captured = layer ? group.stories.flatMap((story) => layer.byStory.get(story.id) ?? []) : [];\n const plain = group.stories.filter((story) => !layer?.byStory.has(story.id));\n return (\n <Card\n padded={false}\n data-filter-item\n data-filter-text={`${group.title} ${group.stories.map((story) => story.name).join(\" \")}`}\n >\n <CardSection divider>\n <SectionTitle>{href ? <a href={href}>{group.title}</a> : group.title}</SectionTitle>\n <HStack>\n {group.tags.map((tag) => (\n <Badge key={tag} tone=\"neutral\">\n {tag}\n </Badge>\n ))}\n <Meta as=\"span\">\n {group.stories.length} {group.stories.length === 1 ? \"story\" : \"stories\"}\n </Meta>\n <DocsLink group={group} project={project} build={build} />\n </HStack>\n </CardSection>\n <CardSection>\n <VStack>\n {layer && captured.length > 0 ? (\n <SnapshotCards\n snapshots={captured}\n project={project}\n buildId={build.id}\n layer={layer}\n componentHref={href}\n />\n ) : null}\n {plain.length > 0 ? <StoryLinks stories={plain} project={project} build={build} /> : null}\n </VStack>\n </CardSection>\n </Card>\n );\n}\n\n/** Component page of a group (its story file), when the index names one. */\nfunction componentHref(project: Project, group: LibraryGroup): string | undefined {\n return group.importPath\n ? createUrlBuilder(\"/\", getStore().config.publishedBaseDomain).component(\n project.slug,\n group.importPath,\n )\n : undefined;\n}\n\nfunction DocsLink(props: { group: LibraryGroup; project: Project; build: Build }): Rendered | null {\n const docs = props.group.docs[0];\n if (!docs) {\n return null;\n }\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"book\"\n href={`/projects/${props.project.slug}/storybook/build/${props.build.id}/?storyId=${encodeURIComponent(docs.id)}&viewMode=docs`}\n target=\"_blank\"\n rel=\"noopener\"\n >\n Docs\n </Button>\n );\n}\n\n/** Links into the published Storybook, one per story, for stories without a snapshot. */\nfunction StoryLinks(props: {\n stories: LibraryGroup[\"stories\"];\n project: Project;\n build: Build;\n}): Rendered {\n const base = createUrlBuilder(\"/\", getStore().config.publishedBaseDomain).storybookBuild(\n props.project.slug,\n props.build.id,\n );\n return (\n <HStack>\n {props.stories.map((story): Rendered => (\n <span key={story.id} data-filter-item data-filter-text={`${story.title} ${story.name}`}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"external-link\"\n href={`${base}/?storyId=${encodeURIComponent(story.id)}`}\n target=\"_blank\"\n rel=\"noopener\"\n >\n {story.name}\n </Button>\n </span>\n ))}\n </HStack>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { normalizeImportPath } from "@storyshelf/core/models";
|
|
5
|
+
// src/pages/library-model.ts
|
|
6
|
+
/** Tags Storybook adds on its own; they say nothing about the component. */
|
|
7
|
+
const STORYBOOK_TAGS = /* @__PURE__ */ new Set([
|
|
8
|
+
"dev",
|
|
9
|
+
"test",
|
|
10
|
+
"autodocs",
|
|
11
|
+
"play-fn",
|
|
12
|
+
"manifest",
|
|
13
|
+
"attached-mdx",
|
|
14
|
+
"unattached-mdx"
|
|
15
|
+
]);
|
|
16
|
+
/** Group catalog entries by title, ordered by title; stories keep index order. */
|
|
17
|
+
function groupLibrary(entries) {
|
|
18
|
+
return [...Map.groupBy(entries, (entry) => entry.title).entries()].map(([title, group]) => {
|
|
19
|
+
return {
|
|
20
|
+
title,
|
|
21
|
+
importPath: group.find((entry) => entry.importPath !== "")?.importPath ?? "",
|
|
22
|
+
stories: group.filter((entry) => entry.type === "story"),
|
|
23
|
+
docs: group.filter((entry) => entry.type === "docs"),
|
|
24
|
+
tags: [...new Set(group.flatMap((entry) => entry.tags))].filter((tag) => !STORYBOOK_TAGS.has(tag))
|
|
25
|
+
};
|
|
26
|
+
}).toSorted((a, b) => a.title.localeCompare(b.title));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Entries rebuilt from a build's snapshots, for a captured build whose Storybook index is gone
|
|
30
|
+
* (statics purged): the pages still list what was captured.
|
|
31
|
+
*/
|
|
32
|
+
function entriesFromSnapshots(snapshots) {
|
|
33
|
+
const seen = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const snap of snapshots) if (!seen.has(snap.storyId)) seen.set(snap.storyId, {
|
|
35
|
+
id: snap.storyId,
|
|
36
|
+
title: snap.storyTitle || "Untitled",
|
|
37
|
+
name: snap.storyName,
|
|
38
|
+
importPath: snap.storyImportPath ? normalizeImportPath(snap.storyImportPath) : "",
|
|
39
|
+
type: "story",
|
|
40
|
+
tags: []
|
|
41
|
+
});
|
|
42
|
+
return [...seen.values()];
|
|
43
|
+
}
|
|
44
|
+
export { entriesFromSnapshots, groupLibrary };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=library-model.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-model.mjs","names":[],"sources":["../../src/pages/library-model.ts"],"sourcesContent":["import type { CatalogEntry } from \"@storyshelf/core/capture\";\nimport { normalizeImportPath } from \"@storyshelf/core/models\";\nimport type { Snapshot } from \"@storyshelf/core/schema\";\n\n/** Tags Storybook adds on its own; they say nothing about the component. */\nconst STORYBOOK_TAGS: ReadonlySet<string> = new Set([\n \"dev\",\n \"test\",\n \"autodocs\",\n \"play-fn\",\n \"manifest\",\n \"attached-mdx\",\n \"unattached-mdx\",\n]);\n\n/** The library's unit: every entry that shares a title, grouped like Storybook's sidebar. */\nexport interface LibraryGroup {\n title: string;\n /** Story file of the first entry that has one; empty when the index names none. */\n importPath: string;\n stories: CatalogEntry[];\n /** Docs entries; the first is the component's docs page. */\n docs: CatalogEntry[];\n /** Tags worth showing, in first-seen order. */\n tags: string[];\n}\n\n/** Group catalog entries by title, ordered by title; stories keep index order. */\nexport function groupLibrary(entries: readonly CatalogEntry[]): LibraryGroup[] {\n const groups = Map.groupBy(entries, (entry) => entry.title);\n return [...groups.entries()]\n .map(([title, group]): LibraryGroup => {\n return {\n title,\n importPath: group.find((entry) => entry.importPath !== \"\")?.importPath ?? \"\",\n stories: group.filter((entry) => entry.type === \"story\"),\n docs: group.filter((entry) => entry.type === \"docs\"),\n tags: [...new Set(group.flatMap((entry) => entry.tags))].filter(\n (tag) => !STORYBOOK_TAGS.has(tag),\n ),\n };\n })\n .toSorted((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Entries rebuilt from a build's snapshots, for a captured build whose Storybook index is gone\n * (statics purged): the pages still list what was captured.\n */\nexport function entriesFromSnapshots(snapshots: readonly Snapshot[]): CatalogEntry[] {\n const seen = new Map<string, CatalogEntry>();\n for (const snap of snapshots) {\n if (!seen.has(snap.storyId)) {\n seen.set(snap.storyId, {\n id: snap.storyId,\n title: snap.storyTitle || \"Untitled\",\n name: snap.storyName,\n importPath: snap.storyImportPath ? normalizeImportPath(snap.storyImportPath) : \"\",\n type: \"story\",\n tags: [],\n });\n }\n }\n return [...seen.values()];\n}\n"],"mappings":";;;;;;AAKA,MAAM,iCAAsC,IAAI,IAAI;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAeD,SAAgB,aAAa,SAAkD;CAE7E,OAAO,CAAC,GADO,IAAI,QAAQ,UAAU,UAAU,MAAM,KACrC,CAAC,CAAC,QAAQ,CAAC,CAAC,CACzB,KAAK,CAAC,OAAO,WAAyB;EACrC,OAAO;GACL;GACA,YAAY,MAAM,MAAM,UAAU,MAAM,eAAe,EAAE,CAAC,EAAE,cAAc;GAC1E,SAAS,MAAM,QAAQ,UAAU,MAAM,SAAS,OAAO;GACvD,MAAM,MAAM,QAAQ,UAAU,MAAM,SAAS,MAAM;GACnD,MAAM,CAAC,GAAG,IAAI,IAAI,MAAM,SAAS,UAAU,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,QACtD,QAAQ,CAAC,eAAe,IAAI,GAAG,CAClC;EACF;CACF,CAAC,CAAC,CACD,UAAU,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AACtD;;;;;AAMA,SAAgB,qBAAqB,WAAgD;CACnF,MAAM,uBAAO,IAAI,IAA0B;CAC3C,KAAK,MAAM,QAAQ,WACjB,IAAI,CAAC,KAAK,IAAI,KAAK,OAAO,GACxB,KAAK,IAAI,KAAK,SAAS;EACrB,IAAI,KAAK;EACT,OAAO,KAAK,cAAc;EAC1B,MAAM,KAAK;EACX,YAAY,KAAK,kBAAkB,oBAAoB,KAAK,eAAe,IAAI;EAC/E,MAAM;EACN,MAAM,CAAC;CACT,CAAC;CAGL,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { getStore } from "../store.mjs";
|
|
5
|
+
import { css } from "../ui/css.mjs";
|
|
6
|
+
import { Button } from "../ui/buttons.mjs";
|
|
7
|
+
import { Badge, statusTone } from "../ui/feedback.mjs";
|
|
8
|
+
import { SectionTitle } from "../ui/layout.mjs";
|
|
9
|
+
import { HStack } from "../ui/stacks.mjs";
|
|
10
|
+
import { designUrlsFor, loadDesignPreviews, loadDesignResolutions, loadProjectDesignLinks, providerNameFor } from "../routers/design.handlers.mjs";
|
|
11
|
+
import { diffPaneImg, snapshotCard, snapshotCardBody, snapshotCardHead, snapshotCardMeta, snapshotGrid } from "../ui/styles/review.mjs";
|
|
12
|
+
import { A11yViolationsDetails } from "./a11y-violations.mjs";
|
|
13
|
+
import { groupSnapshots } from "./build-diff-model.mjs";
|
|
14
|
+
import { DesignButtons } from "./design-links.mjs";
|
|
15
|
+
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
16
|
+
import { createUrlBuilder } from "@storyshelf/core/urls";
|
|
17
|
+
// src/pages/library-snapshots.tsx
|
|
18
|
+
/** Snapshot image with library height cap, extending the shared diff pane image. */
|
|
19
|
+
const snapshotImg = css`
|
|
20
|
+
/* snapshot-img */
|
|
21
|
+
${diffPaneImg}
|
|
22
|
+
max-height: 240px;
|
|
23
|
+
object-fit: contain;
|
|
24
|
+
`;
|
|
25
|
+
const NO_DESIGN = {
|
|
26
|
+
bySnapshot: /* @__PURE__ */ new Map(),
|
|
27
|
+
previews: /* @__PURE__ */ new Map(),
|
|
28
|
+
projectLinks: []
|
|
29
|
+
};
|
|
30
|
+
/** The layer for a build's snapshots; design data that cannot be loaded leaves the library plain. */
|
|
31
|
+
async function loadSnapshotLayer(project, snapshots) {
|
|
32
|
+
const primary = groupSnapshots(snapshots).map((group) => group.primary);
|
|
33
|
+
const design = await loadLibraryDesign(project, primary).catch(() => NO_DESIGN);
|
|
34
|
+
return {
|
|
35
|
+
byStory: Map.groupBy(primary, (snap) => snap.storyId),
|
|
36
|
+
design,
|
|
37
|
+
multipleViewports: new Set(primary.map((snap) => snap.viewportName)).size > 1
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async function loadLibraryDesign(project, snapshots) {
|
|
41
|
+
const [resolutions, projectLinks] = await Promise.all([loadDesignResolutions(project, snapshots), loadProjectDesignLinks(project)]);
|
|
42
|
+
const bySnapshot = new Map(snapshots.map((snap) => [snap.id, designUrlsFor(resolutions, snap)]));
|
|
43
|
+
return {
|
|
44
|
+
bySnapshot,
|
|
45
|
+
previews: await loadDesignPreviews(project, [...bySnapshot.values()].flat()),
|
|
46
|
+
projectLinks
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Snapshot cards of a component's captured stories, one grid per viewport. */
|
|
50
|
+
function SnapshotCards(props) {
|
|
51
|
+
const byViewport = Map.groupBy(props.snapshots, (snap) => snap.viewportName);
|
|
52
|
+
return /* @__PURE__ */ jsx(Fragment, { children: [...byViewport.keys()].toSorted().map((name) => /* @__PURE__ */ jsxs("div", { children: [props.layer.multipleViewports ? /* @__PURE__ */ jsx(SectionTitle, {
|
|
53
|
+
level: 3,
|
|
54
|
+
children: name
|
|
55
|
+
}) : null, /* @__PURE__ */ jsx("div", {
|
|
56
|
+
class: snapshotGrid,
|
|
57
|
+
children: (byViewport.get(name) ?? []).toSorted((a, b) => a.storyName.localeCompare(b.storyName)).map((snap) => /* @__PURE__ */ jsx(SnapshotCardItem, {
|
|
58
|
+
snap,
|
|
59
|
+
...props
|
|
60
|
+
}, snap.id))
|
|
61
|
+
})] }, name)) });
|
|
62
|
+
}
|
|
63
|
+
function SnapshotCardItem(props) {
|
|
64
|
+
const { snap, project, buildId } = props;
|
|
65
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
66
|
+
class: snapshotCard,
|
|
67
|
+
"data-filter-item": true,
|
|
68
|
+
"data-filter-text": `${snap.storyTitle} ${snap.storyName}`,
|
|
69
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
70
|
+
class: snapshotCardHead,
|
|
71
|
+
children: [/* @__PURE__ */ jsx("strong", { children: snap.storyName }), /* @__PURE__ */ jsxs("span", {
|
|
72
|
+
class: snapshotCardMeta,
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
75
|
+
tone: statusTone(snap.status),
|
|
76
|
+
children: snap.status
|
|
77
|
+
}),
|
|
78
|
+
" ",
|
|
79
|
+
snap.viewportWidth,
|
|
80
|
+
"×",
|
|
81
|
+
snap.viewportHeight
|
|
82
|
+
]
|
|
83
|
+
})]
|
|
84
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
85
|
+
class: snapshotCardBody,
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsx("img", {
|
|
88
|
+
class: snapshotImg,
|
|
89
|
+
src: `/api/v1/projects/${project.slug}/builds/${buildId}/snapshots/${snap.id}/image`,
|
|
90
|
+
alt: `${snap.storyTitle} / ${snap.storyName}`,
|
|
91
|
+
loading: "lazy"
|
|
92
|
+
}),
|
|
93
|
+
/* @__PURE__ */ jsx(A11yViolationsDetails, { snapshot: snap }),
|
|
94
|
+
/* @__PURE__ */ jsx(SnapshotActions, { ...props })
|
|
95
|
+
]
|
|
96
|
+
})]
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function SnapshotActions(props) {
|
|
100
|
+
const { snap, project, buildId, layer } = props;
|
|
101
|
+
const urls = createUrlBuilder("/", getStore().config.publishedBaseDomain);
|
|
102
|
+
return /* @__PURE__ */ jsxs(HStack, { children: [
|
|
103
|
+
/* @__PURE__ */ jsx(Button, {
|
|
104
|
+
variant: "secondary",
|
|
105
|
+
size: "sm",
|
|
106
|
+
icon: "columns",
|
|
107
|
+
href: `${urls.buildDiff(project.slug, buildId)}?snapshot=${snap.id}`,
|
|
108
|
+
children: "Review"
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ jsx(Button, {
|
|
111
|
+
variant: "ghost",
|
|
112
|
+
size: "sm",
|
|
113
|
+
icon: "external-link",
|
|
114
|
+
href: `${urls.storybookBuild(project.slug, buildId)}/?storyId=${encodeURIComponent(snap.storyId)}`,
|
|
115
|
+
target: "_blank",
|
|
116
|
+
rel: "noopener",
|
|
117
|
+
children: "Preview"
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ jsx(DesignButtons, {
|
|
120
|
+
urls: layer.design.bySnapshot.get(snap.id) ?? [],
|
|
121
|
+
providerName: providerNameFor,
|
|
122
|
+
previews: layer.design.previews,
|
|
123
|
+
componentHref: props.componentHref
|
|
124
|
+
})
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
127
|
+
export { SnapshotCards, loadSnapshotLayer };
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=library-snapshots.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-snapshots.mjs","names":[],"sources":["../../src/pages/library-snapshots.tsx"],"sourcesContent":["/** The snapshot layer of the library: what `testing` adds on top of the catalog (ADR 0006, decision 9). */\nimport type { Project, Snapshot } from \"@storyshelf/core/schema\";\nimport { createUrlBuilder } from \"@storyshelf/core/urls\";\nimport type { HtmlEscapedString } from \"hono/utils/html\";\nimport {\n loadDesignResolutions,\n designUrlsFor,\n loadDesignPreviews,\n loadProjectDesignLinks,\n providerNameFor,\n} from \"../routers/design.handlers.ts\";\nimport { getStore } from \"../store.ts\";\nimport { Badge, Button, HStack, SectionTitle, statusTone } from \"../ui/components.tsx\";\nimport { css } from \"../ui/css.ts\";\nimport {\n diffPaneImg,\n snapshotCard,\n snapshotCardBody,\n snapshotCardHead,\n snapshotCardMeta,\n snapshotGrid,\n} from \"../ui/styles/review.ts\";\nimport { A11yViolationsDetails } from \"./a11y-violations.tsx\";\nimport { groupSnapshots } from \"./build-diff-model.ts\";\nimport { DesignButtons, type DesignPreviewInfo, type ProjectDesignLink } from \"./design-links.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype Rendered = HtmlEscapedString | Promise<HtmlEscapedString>;\n\n/** Snapshot image with library height cap, extending the shared diff pane image. */\nconst snapshotImg = css`\n /* snapshot-img */\n ${diffPaneImg}\n max-height: 240px;\n object-fit: contain;\n`;\n\n/** Design data of the library: per-snapshot component links plus project-level file links. */\nexport interface LibraryDesign {\n bySnapshot: Map<string, string[]>;\n previews: Map<string, DesignPreviewInfo>;\n projectLinks: ProjectDesignLink[];\n}\n\n/** Snapshots and design links of the build, by story; layered onto the catalog's stories. */\nexport interface SnapshotLayer {\n /** One snapshot per story and mode (the primary engine's; other browsers are review detail). */\n byStory: Map<string, Snapshot[]>;\n design: LibraryDesign;\n /** Whether the build has more than one viewport (so the cards name theirs). */\n multipleViewports: boolean;\n}\n\nconst NO_DESIGN: LibraryDesign = { bySnapshot: new Map(), previews: new Map(), projectLinks: [] };\n\n/** The layer for a build's snapshots; design data that cannot be loaded leaves the library plain. */\nexport async function loadSnapshotLayer(\n project: Project,\n snapshots: Snapshot[],\n): Promise<SnapshotLayer> {\n const primary = groupSnapshots(snapshots).map((group) => group.primary);\n const design = await loadLibraryDesign(project, primary).catch(() => NO_DESIGN);\n return {\n byStory: Map.groupBy(primary, (snap) => snap.storyId),\n design,\n multipleViewports: new Set(primary.map((snap) => snap.viewportName)).size > 1,\n };\n}\n\nasync function loadLibraryDesign(project: Project, snapshots: Snapshot[]): Promise<LibraryDesign> {\n const [resolutions, projectLinks] = await Promise.all([\n loadDesignResolutions(project, snapshots),\n loadProjectDesignLinks(project),\n ]);\n const bySnapshot = new Map(\n snapshots.map((snap) => [snap.id, designUrlsFor(resolutions, snap)] as const),\n );\n const previews = await loadDesignPreviews(project, [...bySnapshot.values()].flat());\n return { bySnapshot, previews, projectLinks };\n}\n\n/** Snapshot cards of a component's captured stories, one grid per viewport. */\nexport function SnapshotCards(props: {\n snapshots: Snapshot[];\n project: Project;\n buildId: string;\n layer: SnapshotLayer;\n componentHref: string | undefined;\n}): Rendered {\n const byViewport = Map.groupBy(props.snapshots, (snap) => snap.viewportName);\n return (\n <>\n {[...byViewport.keys()].toSorted().map((name): Rendered => (\n <div key={name}>\n {props.layer.multipleViewports ? <SectionTitle level={3}>{name}</SectionTitle> : null}\n <div class={snapshotGrid}>\n {(byViewport.get(name) ?? [])\n .toSorted((a, b) => a.storyName.localeCompare(b.storyName))\n .map((snap) => (\n <SnapshotCardItem key={snap.id} snap={snap} {...props} />\n ))}\n </div>\n </div>\n ))}\n </>\n );\n}\n\nfunction SnapshotCardItem(props: {\n snap: Snapshot;\n project: Project;\n buildId: string;\n layer: SnapshotLayer;\n componentHref: string | undefined;\n}): Rendered {\n const { snap, project, buildId } = props;\n return (\n <div\n class={snapshotCard}\n data-filter-item\n data-filter-text={`${snap.storyTitle} ${snap.storyName}`}\n >\n <div class={snapshotCardHead}>\n <strong>{snap.storyName}</strong>\n <span class={snapshotCardMeta}>\n <Badge tone={statusTone(snap.status)}>{snap.status}</Badge> {snap.viewportWidth}×\n {snap.viewportHeight}\n </span>\n </div>\n <div class={snapshotCardBody}>\n <img\n class={snapshotImg}\n src={`/api/v1/projects/${project.slug}/builds/${buildId}/snapshots/${snap.id}/image`}\n alt={`${snap.storyTitle} / ${snap.storyName}`}\n loading=\"lazy\"\n />\n <A11yViolationsDetails snapshot={snap} />\n <SnapshotActions {...props} />\n </div>\n </div>\n );\n}\n\nfunction SnapshotActions(props: {\n snap: Snapshot;\n project: Project;\n buildId: string;\n layer: SnapshotLayer;\n componentHref: string | undefined;\n}): Rendered {\n const { snap, project, buildId, layer } = props;\n const urls = createUrlBuilder(\"/\", getStore().config.publishedBaseDomain);\n return (\n <HStack>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n icon=\"columns\"\n href={`${urls.buildDiff(project.slug, buildId)}?snapshot=${snap.id}`}\n >\n Review\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"external-link\"\n href={`${urls.storybookBuild(project.slug, buildId)}/?storyId=${encodeURIComponent(snap.storyId)}`}\n target=\"_blank\"\n rel=\"noopener\"\n >\n Preview\n </Button>\n <DesignButtons\n urls={layer.design.bySnapshot.get(snap.id) ?? []}\n providerName={providerNameFor}\n previews={layer.design.previews}\n componentHref={props.componentHref}\n />\n </HStack>\n );\n}\n"],"mappings":"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"}
|