@storyshelf/core 0.1.2 → 0.1.3
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/dist/adapter/auth.mjs.map +1 -1
- package/dist/adapter/git-host/helpers.d.mts +1 -0
- package/dist/adapter/git-host/helpers.mjs +1 -0
- package/dist/adapter/git-host/helpers.mjs.map +1 -1
- package/dist/adapters/capture-queue.d.mts +2 -0
- package/dist/adapters/webhook-events.mjs +8 -0
- package/dist/adapters/webhook-events.mjs.map +1 -1
- package/dist/capture/adapter.d.mts +2 -0
- package/dist/capture/adapter.mjs +3 -0
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/orchestrator.d.mts +7 -0
- package/dist/capture/orchestrator.mjs +6 -0
- package/dist/capture/orchestrator.mjs.map +1 -1
- package/dist/capture/queue.d.mts +2 -0
- package/dist/capture/queue.mjs +1 -0
- package/dist/capture/queue.mjs.map +1 -1
- package/dist/capture/status-fanout.mjs +1 -0
- package/dist/capture/status-fanout.mjs.map +1 -1
- package/dist/capture/storybook.d.mts +1 -0
- package/dist/capture/storybook.mjs +1 -0
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/config.d.mts +27 -20
- package/dist/config.mjs +14 -0
- package/dist/config.mjs.map +1 -1
- package/dist/ddl.d.mts +1 -0
- package/dist/ddl.mjs +1 -0
- package/dist/ddl.mjs.map +1 -1
- package/dist/diff/engine.d.mts +8 -0
- package/dist/diff/engine.mjs +8 -0
- package/dist/diff/engine.mjs.map +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +6 -1
- package/dist/index.mjs.map +1 -1
- package/dist/logger.mjs.map +1 -1
- package/dist/middleware/csrf.mjs +1 -0
- package/dist/middleware/csrf.mjs.map +1 -1
- package/dist/middleware/rate-limit.mjs +1 -0
- package/dist/middleware/rate-limit.mjs.map +1 -1
- package/dist/models/baseline.d.mts +1 -0
- package/dist/models/baseline.mjs +3 -1
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build.d.mts +3 -0
- package/dist/models/build.mjs +3 -1
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/comment.d.mts +2 -0
- package/dist/models/comment.mjs +3 -1
- package/dist/models/comment.mjs.map +1 -1
- package/dist/models/label.mjs +2 -1
- package/dist/models/label.mjs.map +1 -1
- package/dist/models/member.mjs +2 -1
- package/dist/models/member.mjs.map +1 -1
- package/dist/models/project.d.mts +1 -0
- package/dist/models/project.mjs +2 -1
- package/dist/models/project.mjs.map +1 -1
- package/dist/models/snapshot.d.mts +1 -0
- package/dist/models/snapshot.mjs +2 -1
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/status-config.mjs +2 -1
- package/dist/models/status-config.mjs.map +1 -1
- package/dist/models/token.mjs +2 -1
- package/dist/models/token.mjs.map +1 -1
- package/dist/models/webhook.d.mts +1 -0
- package/dist/models/webhook.mjs +2 -1
- package/dist/models/webhook.mjs.map +1 -1
- package/dist/pages/build-detail.mjs +1 -0
- package/dist/pages/build-detail.mjs.map +1 -1
- package/dist/pages/build-diff.mjs +1 -0
- package/dist/pages/build-diff.mjs.map +1 -1
- package/dist/pages/compute-jobs.mjs +2 -0
- package/dist/pages/compute-jobs.mjs.map +1 -1
- package/dist/pages/login.mjs +1 -0
- package/dist/pages/login.mjs.map +1 -1
- package/dist/pages/project-builds.mjs +1 -0
- package/dist/pages/project-builds.mjs.map +1 -1
- package/dist/pages/project-create.mjs +1 -0
- package/dist/pages/project-create.mjs.map +1 -1
- package/dist/pages/project-settings.mjs +1 -0
- package/dist/pages/project-settings.mjs.map +1 -1
- package/dist/pages/projects.mjs +1 -0
- package/dist/pages/projects.mjs.map +1 -1
- package/dist/pages/root.mjs +1 -0
- package/dist/pages/root.mjs.map +1 -1
- package/dist/pages/settings-general.mjs +1 -0
- package/dist/pages/settings-general.mjs.map +1 -1
- package/dist/pages/settings-labels.mjs +1 -0
- package/dist/pages/settings-labels.mjs.map +1 -1
- package/dist/pages/settings-members.mjs +1 -0
- package/dist/pages/settings-members.mjs.map +1 -1
- package/dist/pages/settings-status.mjs +1 -0
- package/dist/pages/settings-status.mjs.map +1 -1
- package/dist/pages/settings-tests.mjs +1 -0
- package/dist/pages/settings-tests.mjs.map +1 -1
- package/dist/pages/settings-tokens.mjs +1 -0
- package/dist/pages/settings-tokens.mjs.map +1 -1
- package/dist/pages/settings-webhooks.mjs +1 -0
- package/dist/pages/settings-webhooks.mjs.map +1 -1
- package/dist/retention/purge.d.mts +3 -0
- package/dist/retention/purge.mjs +2 -1
- package/dist/retention/purge.mjs.map +1 -1
- package/dist/routers/admin.mjs +1 -0
- package/dist/routers/admin.mjs.map +1 -1
- package/dist/routers/assets.mjs +1 -0
- package/dist/routers/assets.mjs.map +1 -1
- package/dist/routers/auth.mjs +1 -0
- package/dist/routers/auth.mjs.map +1 -1
- package/dist/routers/builds.handlers.mjs +10 -0
- package/dist/routers/builds.handlers.mjs.map +1 -1
- package/dist/routers/builds.mjs +1 -0
- package/dist/routers/builds.mjs.map +1 -1
- package/dist/routers/comments.mjs +1 -0
- package/dist/routers/comments.mjs.map +1 -1
- package/dist/routers/helpers.mjs +7 -1
- package/dist/routers/helpers.mjs.map +1 -1
- package/dist/routers/htmx.mjs +2 -0
- package/dist/routers/htmx.mjs.map +1 -1
- package/dist/routers/labels.mjs +1 -0
- package/dist/routers/labels.mjs.map +1 -1
- package/dist/routers/media.mjs +1 -0
- package/dist/routers/media.mjs.map +1 -1
- package/dist/routers/members.mjs +1 -0
- package/dist/routers/members.mjs.map +1 -1
- package/dist/routers/projects.mjs +1 -0
- package/dist/routers/projects.mjs.map +1 -1
- package/dist/routers/schemas.mjs +25 -0
- package/dist/routers/schemas.mjs.map +1 -1
- package/dist/routers/settings.mjs +2 -0
- package/dist/routers/settings.mjs.map +1 -1
- package/dist/routers/snapshots.mjs +1 -0
- package/dist/routers/snapshots.mjs.map +1 -1
- package/dist/routers/status-configs.mjs +1 -0
- package/dist/routers/status-configs.mjs.map +1 -1
- package/dist/routers/storybook.mjs +1 -0
- package/dist/routers/storybook.mjs.map +1 -1
- package/dist/routers/tokens.mjs +1 -0
- package/dist/routers/tokens.mjs.map +1 -1
- package/dist/routers/ui.mjs +1 -0
- package/dist/routers/ui.mjs.map +1 -1
- package/dist/routers/webhooks.mjs +1 -0
- package/dist/routers/webhooks.mjs.map +1 -1
- package/dist/schema-tables.mjs +166 -0
- package/dist/schema-tables.mjs.map +1 -0
- package/dist/schema.d.mts +194 -4420
- package/dist/schema.mjs +26 -138
- package/dist/schema.mjs.map +1 -1
- package/dist/store.mjs +2 -0
- package/dist/store.mjs.map +1 -1
- package/dist/types.d.mts +12 -0
- package/dist/types.mjs +8 -0
- package/dist/types.mjs.map +1 -1
- package/dist/ui/components.mjs +5 -0
- package/dist/ui/components.mjs.map +1 -1
- package/dist/ui/document.d.mts +1 -0
- package/dist/ui/document.mjs +1 -0
- package/dist/ui/document.mjs.map +1 -1
- package/dist/ui/styles.mjs +1 -0
- package/dist/ui/styles.mjs.map +1 -1
- package/dist/ui/theme.mjs +2 -0
- package/dist/ui/theme.mjs.map +1 -1
- package/dist/urls.d.mts +8 -0
- package/dist/urls.mjs +7 -0
- package/dist/urls.mjs.map +1 -1
- package/dist/utils/hash.mjs +3 -0
- package/dist/utils/hash.mjs.map +1 -1
- package/dist/utils/paths.d.mts +5 -0
- package/dist/utils/paths.mjs +5 -0
- package/dist/utils/paths.mjs.map +1 -1
- package/dist/utils/ulid.d.mts +2 -0
- package/dist/utils/ulid.mjs +2 -0
- package/dist/utils/ulid.mjs.map +1 -1
- package/package.json +1 -1
package/dist/ui/styles.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.mjs","names":[],"sources":["../../src/ui/styles.ts"],"sourcesContent":["import type { BrandTheme } from \"./theme.ts\";\n\nexport function baseStyle(light: BrandTheme, dark: BrandTheme): string {\n return `\n :root {\n --accent: ${light.accent};\n --accent-contrast: #fff;\n --surface-base: ${light.surface.base};\n --surface-card: ${light.surface.card};\n --surface-muted: #f4f4f5;\n --text-primary: ${light.text.primary};\n --text-secondary: ${light.text.secondary};\n --border: ${light.border};\n --radius: 10px;\n --radius-sm: 6px;\n --shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 12px rgba(0,0,0,.04);\n --status-approved: ${light.status.approved};\n --status-new: ${light.status.new};\n --status-rejected: ${light.status.rejected};\n --topbar-bg: ${light.accent};\n --sidebar-bg: #ffffff;\n --sidebar-width: 240px;\n }\n [data-theme=\"dark\"] {\n --accent: ${dark.accent};\n --surface-base: ${dark.surface.base};\n --surface-card: ${dark.surface.card};\n --surface-muted: #1e1e22;\n --text-primary: ${dark.text.primary};\n --text-secondary: ${dark.text.secondary};\n --border: ${dark.border};\n --status-approved: ${dark.status.approved};\n --status-new: ${dark.status.new};\n --status-rejected: ${dark.status.rejected};\n --topbar-bg: #0f172a;\n --sidebar-bg: #111113;\n }\n @media (prefers-color-scheme: dark) {\n [data-theme=\"system\"] {\n --accent: ${dark.accent};\n --surface-base: ${dark.surface.base};\n --surface-card: ${dark.surface.card};\n --surface-muted: #1e1e22;\n --text-primary: ${dark.text.primary};\n --text-secondary: ${dark.text.secondary};\n --border: ${dark.border};\n --status-approved: ${dark.status.approved};\n --status-new: ${dark.status.new};\n --status-rejected: ${dark.status.rejected};\n --topbar-bg: #0f172a;\n --sidebar-bg: #111113;\n }\n }\n * { box-sizing: border-box; }\n html { scroll-behavior: smooth; }\n body { margin: 0; font-family: ui-sans-system, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; background: var(--surface-base); color: var(--text-primary); line-height: 1.5; }\n a { color: var(--accent); text-decoration: none; }\n a:hover { text-decoration: underline; }\n a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n .skip-link { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }\n .skip-link:focus { left: 1rem; top: 1rem; width: auto; height: auto; background: var(--surface-card); color: var(--text-primary); padding: .5rem .75rem; border-radius: var(--radius-sm); box-shadow: var(--shadow); z-index: 100; }\n .topbar { position: sticky; top: 0; z-index: 40; background: var(--topbar-bg); color: #fff; border-bottom: 1px solid rgba(255,255,255,.12); }\n .topbar__inner { max-width: 1440px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .6rem 1rem; }\n .topbar__left, .topbar__right { display: flex; align-items: center; gap: .75rem; min-width: 0; }\n .topbar__menu { display: none; background: transparent; border: 1px solid rgba(255,255,255,.3); color: #fff; border-radius: 6px; padding: .35rem .5rem; cursor: pointer; }\n .brand { display: inline-flex; align-items: center; gap: .5rem; color: #fff; font-weight: 650; text-decoration: none; }\n .brand__mark { width: 28px; height: 28px; display: inline-grid; place-items: center; background: rgba(255,255,255,.18); border-radius: 8px; }\n .logo { border-radius: 6px; display: block; }\n .project-crumb { display: inline-flex; align-items: center; gap: .35rem; color: rgba(255,255,255,.9); }\n .project-crumb a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }\n .project-crumb__sep { opacity: .7; }\n .topbar__theme { background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.22); color: #fff; border-radius: 999px; padding: .35rem .6rem; cursor: pointer; display: inline-flex; gap: .25rem; }\n .topbar__theme [data-theme-icon] { display: none; }\n [data-theme=\"light\"] [data-theme-icon=\"light\"], [data-theme=\"dark\"] [data-theme-icon=\"dark\"], [data-theme=\"system\"] [data-theme-icon=\"system\"] { display: inline; }\n .topbar__login { background: #fff; color: var(--accent); padding: .4rem .75rem; border-radius: 999px; font-weight: 600; text-decoration: none; }\n .user-menu { display: inline-flex; align-items: center; gap: .5rem; background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.2); padding: .25rem .5rem .25rem .35rem; border-radius: 999px; }\n .user-menu__avatar { width: 28px; height: 28px; border-radius: 999px; object-fit: cover; background: rgba(255,255,255,.2); }\n .user-menu__avatar--fallback { display: inline-grid; place-items: center; font-weight: 700; color: #fff; }\n .user-menu__name { color: #fff; font-weight: 600; max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .user-menu__role { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; background: rgba(255,255,255,.2); color: #fff; padding: .15rem .4rem; border-radius: 999px; }\n .user-menu__logout { color: #fff; font-size: .85rem; text-decoration: underline; text-underline-offset: 2px; margin-left: .25rem; }\n .shell { max-width: 1440px; margin: 0 auto; display: grid; grid-template-columns: var(--sidebar-width) 1fr; min-height: calc(100vh - 56px); }\n .sidebar { background: var(--sidebar-bg); border-right: 1px solid var(--border); padding: 1rem .75rem; position: sticky; top: 56px; height: calc(100vh - 56px); overflow: auto; }\n .sidebar__nav { display: flex; flex-direction: column; gap: .25rem; }\n .sidebar__section { margin: 1rem 0 .35rem; font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-secondary); padding: 0 .5rem; }\n .sidebar__link { display: flex; align-items: center; gap: .5rem; padding: .5rem .6rem; border-radius: 8px; color: var(--text-primary); text-decoration: none; }\n .sidebar__link:hover { background: var(--surface-muted); text-decoration: none; }\n .sidebar__link--active { background: var(--surface-muted); font-weight: 600; }\n .content { padding: 1.25rem 1.5rem 2rem; min-width: 0; max-width: 1100px; }\n .page-header { margin-bottom: 1.25rem; }\n .page-header__row { display: flex; gap: 1rem; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }\n .page-header__title { margin: 0; font-size: 1.6rem; line-height: 1.2; letter-spacing: -0.02em; }\n .page-header__desc { margin: .35rem 0 0; color: var(--text-secondary); max-width: 60ch; }\n .page-header__actions { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }\n .breadcrumbs ol { list-style: none; padding: 0; margin: 0 0 .5rem; display: flex; gap: .4rem; flex-wrap: wrap; color: var(--text-secondary); font-size: .85rem; }\n .breadcrumbs li + li::before { content: \"/\"; margin-right: .4rem; color: var(--text-secondary); }\n .card { background: var(--surface-card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }\n .card--padded { padding: 1rem; }\n .btn { appearance: none; border: 1px solid transparent; border-radius: 8px; padding: .55rem .85rem; font-weight: 600; font-size: .9rem; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; gap: .4rem; line-height: 1; }\n .btn--primary { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }\n .btn--primary:hover { filter: brightness(1.05); text-decoration: none; }\n .btn--secondary { background: var(--surface-card); color: var(--text-primary); border-color: var(--border); }\n .btn--ghost { background: transparent; color: var(--text-primary); border-color: transparent; }\n .btn--danger { background: var(--status-rejected); color: #fff; border-color: var(--status-rejected); }\n .btn:disabled { opacity: .6; cursor: not-allowed; }\n .badge { display: inline-flex; align-items: center; padding: .15rem .5rem; border-radius: 999px; font-size: .75rem; font-weight: 650; letter-spacing: .02em; border: 1px solid var(--border); background: var(--surface-muted); color: var(--text-secondary); }\n .badge--success { background: color-mix(in srgb, var(--status-approved) 14%, var(--surface-card)); color: var(--status-approved); border-color: color-mix(in srgb, var(--status-approved) 30%, var(--border)); }\n .badge--warning { background: color-mix(in srgb, var(--status-new) 14%, var(--surface-card)); color: var(--status-new); border-color: color-mix(in srgb, var(--status-new) 30%, var(--border)); }\n .badge--danger { background: color-mix(in srgb, var(--status-rejected) 14%, var(--surface-card)); color: var(--status-rejected); border-color: color-mix(in srgb, var(--status-rejected) 30%, var(--border)); }\n .badge--info { background: color-mix(in srgb, var(--accent) 10%, var(--surface-card)); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 25%, var(--border)); }\n .badge--neutral { background: var(--surface-muted); color: var(--text-secondary); }\n .field { display: grid; gap: .35rem; margin-bottom: .9rem; }\n .field__label { font-weight: 600; font-size: .9rem; }\n .field__input { width: 100%; padding: .6rem .7rem; border-radius: 8px; border: 1px solid var(--border); background: var(--surface-card); color: var(--text-primary); font: inherit; }\n .field__input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }\n .field__input--error { border-color: var(--status-rejected); }\n .field__input--textarea { resize: vertical; }\n .field__hint { margin: 0; color: var(--text-secondary); font-size: .85rem; }\n .field__error { margin: 0; color: var(--status-rejected); font-size: .85rem; }\n .alert { border-radius: 8px; padding: .75rem .85rem; border: 1px solid var(--border); background: var(--surface-card); }\n .alert--info { border-color: color-mix(in srgb, var(--accent) 22%, var(--border)); background: color-mix(in srgb, var(--accent) 7%, var(--surface-card)); }\n .alert--success { border-color: color-mix(in srgb, var(--status-approved) 22%, var(--border)); background: color-mix(in srgb, var(--status-approved) 7%, var(--surface-card)); }\n .alert--warning { border-color: color-mix(in srgb, var(--status-new) 22%, var(--border)); background: color-mix(in srgb, var(--status-new) 7%, var(--surface-card)); }\n .alert--danger { border-color: color-mix(in srgb, var(--status-rejected) 22%, var(--border)); background: color-mix(in srgb, var(--status-rejected) 7%, var(--surface-card)); }\n .alert__title { display: block; margin-bottom: .2rem; }\n .tabs { display: flex; gap: .25rem; border-bottom: 1px solid var(--border); margin-bottom: 1rem; overflow-x: auto; }\n .tabs__link { padding: .6rem .75rem; border-bottom: 2px solid transparent; color: var(--text-secondary); text-decoration: none; white-space: nowrap; font-weight: 600; }\n .tabs__link:hover { color: var(--text-primary); text-decoration: none; }\n .tabs__link--active { color: var(--text-primary); border-bottom-color: var(--accent); }\n .empty { text-align: center; padding: 2rem 1rem; border: 1px dashed var(--border); border-radius: var(--radius); background: var(--surface-card); }\n .empty__title { margin: 0 0 .3rem; font-size: 1.1rem; }\n .empty__desc { margin: 0 auto; color: var(--text-secondary); max-width: 50ch; }\n .empty__action { margin-top: 1rem; }\n .grid { display: grid; gap: 1rem; }\n .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n @media (max-width: 880px) { .grid--2, .grid--3 { grid-template-columns: 1fr; } }\n .table-wrap { overflow: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-card); }\n table { width: 100%; border-collapse: collapse; font-size: .9rem; }\n th, td { text-align: left; padding: .65rem .75rem; border-bottom: 1px solid var(--border); vertical-align: top; }\n th { background: var(--surface-muted); font-weight: 650; color: var(--text-secondary); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; }\n tr:last-child td { border-bottom: 0; }\n .stat { text-align: center; padding: .5rem; }\n .stat__value { font-size: 1.4rem; font-weight: 750; line-height: 1; }\n .stat__label { color: var(--text-secondary); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; }\n .snapshot-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }\n .snapshot-card { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface-card); display: flex; flex-direction: column; }\n .snapshot-card__head { padding: .6rem .75rem; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; gap: .5rem; align-items: center; }\n .snapshot-card__meta { font-size: .8rem; color: var(--text-secondary); }\n .snapshot-card__body { padding: .5rem; display: grid; gap: .5rem; }\n .diff-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; }\n @media (max-width: 900px) { .diff-grid { grid-template-columns: 1fr; } }\n .diff-pane { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface-card); }\n .diff-pane__label { padding: .4rem .6rem; font-weight: 650; font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-secondary); background: var(--surface-muted); border-bottom: 1px solid var(--border); }\n .diff-pane__img { display: block; width: 100%; height: auto; background: repeating-conic-gradient(#e5e7eb 0% 25%, #f9fafb 0% 50%) 0 0 / 16px 16px; }\n .comment { border: 1px solid var(--border); border-radius: var(--radius); padding: .75rem; background: var(--surface-card); }\n .comment__head { display: flex; gap: .5rem; align-items: center; font-size: .85rem; color: var(--text-secondary); }\n .comment__body { margin: .5rem 0 0; white-space: pre-wrap; word-break: break-word; }\n @media (max-width: 880px) {\n .topbar__menu { display: inline-flex; }\n .shell { grid-template-columns: 1fr; }\n .sidebar { display: none; position: fixed; inset: 56px 0 0 0; z-index: 30; height: auto; }\n .sidebar--open { display: block; }\n .content { padding: 1rem; }\n }\n `;\n}"],"mappings":";;;;AAEA,SAAgB,UAAU,OAAmB,MAA0B;CACrE,OAAO;;kBAES,MAAM,OAAO;;wBAEP,MAAM,QAAQ,KAAK;wBACnB,MAAM,QAAQ,KAAK;;wBAEnB,MAAM,KAAK,QAAQ;0BACjB,MAAM,KAAK,UAAU;kBAC7B,MAAM,OAAO;;;;2BAIJ,MAAM,OAAO,SAAS;sBAC3B,MAAM,OAAO,IAAI;2BACZ,MAAM,OAAO,SAAS;qBAC5B,MAAM,OAAO;;;;;kBAKhB,KAAK,OAAO;wBACN,KAAK,QAAQ,KAAK;wBAClB,KAAK,QAAQ,KAAK;;wBAElB,KAAK,KAAK,QAAQ;0BAChB,KAAK,KAAK,UAAU;kBAC5B,KAAK,OAAO;2BACH,KAAK,OAAO,SAAS;sBAC1B,KAAK,OAAO,IAAI;2BACX,KAAK,OAAO,SAAS;;;;;;oBAM5B,KAAK,OAAO;0BACN,KAAK,QAAQ,KAAK;0BAClB,KAAK,QAAQ,KAAK;;0BAElB,KAAK,KAAK,QAAQ;4BAChB,KAAK,KAAK,UAAU;oBAC5B,KAAK,OAAO;6BACH,KAAK,OAAO,SAAS;wBAC1B,KAAK,OAAO,IAAI;6BACX,KAAK,OAAO,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsHlD"}
|
|
1
|
+
{"version":3,"file":"styles.mjs","names":[],"sources":["../../src/ui/styles.ts"],"sourcesContent":["import type { BrandTheme } from \"./theme.ts\";\n\n/** Build the global CSS stylesheet from the light and dark brand themes. */\nexport function baseStyle(light: BrandTheme, dark: BrandTheme): string {\n return `\n :root {\n --accent: ${light.accent};\n --accent-contrast: #fff;\n --surface-base: ${light.surface.base};\n --surface-card: ${light.surface.card};\n --surface-muted: #f4f4f5;\n --text-primary: ${light.text.primary};\n --text-secondary: ${light.text.secondary};\n --border: ${light.border};\n --radius: 10px;\n --radius-sm: 6px;\n --shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 12px rgba(0,0,0,.04);\n --status-approved: ${light.status.approved};\n --status-new: ${light.status.new};\n --status-rejected: ${light.status.rejected};\n --topbar-bg: ${light.accent};\n --sidebar-bg: #ffffff;\n --sidebar-width: 240px;\n }\n [data-theme=\"dark\"] {\n --accent: ${dark.accent};\n --surface-base: ${dark.surface.base};\n --surface-card: ${dark.surface.card};\n --surface-muted: #1e1e22;\n --text-primary: ${dark.text.primary};\n --text-secondary: ${dark.text.secondary};\n --border: ${dark.border};\n --status-approved: ${dark.status.approved};\n --status-new: ${dark.status.new};\n --status-rejected: ${dark.status.rejected};\n --topbar-bg: #0f172a;\n --sidebar-bg: #111113;\n }\n @media (prefers-color-scheme: dark) {\n [data-theme=\"system\"] {\n --accent: ${dark.accent};\n --surface-base: ${dark.surface.base};\n --surface-card: ${dark.surface.card};\n --surface-muted: #1e1e22;\n --text-primary: ${dark.text.primary};\n --text-secondary: ${dark.text.secondary};\n --border: ${dark.border};\n --status-approved: ${dark.status.approved};\n --status-new: ${dark.status.new};\n --status-rejected: ${dark.status.rejected};\n --topbar-bg: #0f172a;\n --sidebar-bg: #111113;\n }\n }\n * { box-sizing: border-box; }\n html { scroll-behavior: smooth; }\n body { margin: 0; font-family: ui-sans-system, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; background: var(--surface-base); color: var(--text-primary); line-height: 1.5; }\n a { color: var(--accent); text-decoration: none; }\n a:hover { text-decoration: underline; }\n a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n .skip-link { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }\n .skip-link:focus { left: 1rem; top: 1rem; width: auto; height: auto; background: var(--surface-card); color: var(--text-primary); padding: .5rem .75rem; border-radius: var(--radius-sm); box-shadow: var(--shadow); z-index: 100; }\n .topbar { position: sticky; top: 0; z-index: 40; background: var(--topbar-bg); color: #fff; border-bottom: 1px solid rgba(255,255,255,.12); }\n .topbar__inner { max-width: 1440px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .6rem 1rem; }\n .topbar__left, .topbar__right { display: flex; align-items: center; gap: .75rem; min-width: 0; }\n .topbar__menu { display: none; background: transparent; border: 1px solid rgba(255,255,255,.3); color: #fff; border-radius: 6px; padding: .35rem .5rem; cursor: pointer; }\n .brand { display: inline-flex; align-items: center; gap: .5rem; color: #fff; font-weight: 650; text-decoration: none; }\n .brand__mark { width: 28px; height: 28px; display: inline-grid; place-items: center; background: rgba(255,255,255,.18); border-radius: 8px; }\n .logo { border-radius: 6px; display: block; }\n .project-crumb { display: inline-flex; align-items: center; gap: .35rem; color: rgba(255,255,255,.9); }\n .project-crumb a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }\n .project-crumb__sep { opacity: .7; }\n .topbar__theme { background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.22); color: #fff; border-radius: 999px; padding: .35rem .6rem; cursor: pointer; display: inline-flex; gap: .25rem; }\n .topbar__theme [data-theme-icon] { display: none; }\n [data-theme=\"light\"] [data-theme-icon=\"light\"], [data-theme=\"dark\"] [data-theme-icon=\"dark\"], [data-theme=\"system\"] [data-theme-icon=\"system\"] { display: inline; }\n .topbar__login { background: #fff; color: var(--accent); padding: .4rem .75rem; border-radius: 999px; font-weight: 600; text-decoration: none; }\n .user-menu { display: inline-flex; align-items: center; gap: .5rem; background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.2); padding: .25rem .5rem .25rem .35rem; border-radius: 999px; }\n .user-menu__avatar { width: 28px; height: 28px; border-radius: 999px; object-fit: cover; background: rgba(255,255,255,.2); }\n .user-menu__avatar--fallback { display: inline-grid; place-items: center; font-weight: 700; color: #fff; }\n .user-menu__name { color: #fff; font-weight: 600; max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .user-menu__role { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; background: rgba(255,255,255,.2); color: #fff; padding: .15rem .4rem; border-radius: 999px; }\n .user-menu__logout { color: #fff; font-size: .85rem; text-decoration: underline; text-underline-offset: 2px; margin-left: .25rem; }\n .shell { max-width: 1440px; margin: 0 auto; display: grid; grid-template-columns: var(--sidebar-width) 1fr; min-height: calc(100vh - 56px); }\n .sidebar { background: var(--sidebar-bg); border-right: 1px solid var(--border); padding: 1rem .75rem; position: sticky; top: 56px; height: calc(100vh - 56px); overflow: auto; }\n .sidebar__nav { display: flex; flex-direction: column; gap: .25rem; }\n .sidebar__section { margin: 1rem 0 .35rem; font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-secondary); padding: 0 .5rem; }\n .sidebar__link { display: flex; align-items: center; gap: .5rem; padding: .5rem .6rem; border-radius: 8px; color: var(--text-primary); text-decoration: none; }\n .sidebar__link:hover { background: var(--surface-muted); text-decoration: none; }\n .sidebar__link--active { background: var(--surface-muted); font-weight: 600; }\n .content { padding: 1.25rem 1.5rem 2rem; min-width: 0; max-width: 1100px; }\n .page-header { margin-bottom: 1.25rem; }\n .page-header__row { display: flex; gap: 1rem; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }\n .page-header__title { margin: 0; font-size: 1.6rem; line-height: 1.2; letter-spacing: -0.02em; }\n .page-header__desc { margin: .35rem 0 0; color: var(--text-secondary); max-width: 60ch; }\n .page-header__actions { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }\n .breadcrumbs ol { list-style: none; padding: 0; margin: 0 0 .5rem; display: flex; gap: .4rem; flex-wrap: wrap; color: var(--text-secondary); font-size: .85rem; }\n .breadcrumbs li + li::before { content: \"/\"; margin-right: .4rem; color: var(--text-secondary); }\n .card { background: var(--surface-card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }\n .card--padded { padding: 1rem; }\n .btn { appearance: none; border: 1px solid transparent; border-radius: 8px; padding: .55rem .85rem; font-weight: 600; font-size: .9rem; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; gap: .4rem; line-height: 1; }\n .btn--primary { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }\n .btn--primary:hover { filter: brightness(1.05); text-decoration: none; }\n .btn--secondary { background: var(--surface-card); color: var(--text-primary); border-color: var(--border); }\n .btn--ghost { background: transparent; color: var(--text-primary); border-color: transparent; }\n .btn--danger { background: var(--status-rejected); color: #fff; border-color: var(--status-rejected); }\n .btn:disabled { opacity: .6; cursor: not-allowed; }\n .badge { display: inline-flex; align-items: center; padding: .15rem .5rem; border-radius: 999px; font-size: .75rem; font-weight: 650; letter-spacing: .02em; border: 1px solid var(--border); background: var(--surface-muted); color: var(--text-secondary); }\n .badge--success { background: color-mix(in srgb, var(--status-approved) 14%, var(--surface-card)); color: var(--status-approved); border-color: color-mix(in srgb, var(--status-approved) 30%, var(--border)); }\n .badge--warning { background: color-mix(in srgb, var(--status-new) 14%, var(--surface-card)); color: var(--status-new); border-color: color-mix(in srgb, var(--status-new) 30%, var(--border)); }\n .badge--danger { background: color-mix(in srgb, var(--status-rejected) 14%, var(--surface-card)); color: var(--status-rejected); border-color: color-mix(in srgb, var(--status-rejected) 30%, var(--border)); }\n .badge--info { background: color-mix(in srgb, var(--accent) 10%, var(--surface-card)); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 25%, var(--border)); }\n .badge--neutral { background: var(--surface-muted); color: var(--text-secondary); }\n .field { display: grid; gap: .35rem; margin-bottom: .9rem; }\n .field__label { font-weight: 600; font-size: .9rem; }\n .field__input { width: 100%; padding: .6rem .7rem; border-radius: 8px; border: 1px solid var(--border); background: var(--surface-card); color: var(--text-primary); font: inherit; }\n .field__input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }\n .field__input--error { border-color: var(--status-rejected); }\n .field__input--textarea { resize: vertical; }\n .field__hint { margin: 0; color: var(--text-secondary); font-size: .85rem; }\n .field__error { margin: 0; color: var(--status-rejected); font-size: .85rem; }\n .alert { border-radius: 8px; padding: .75rem .85rem; border: 1px solid var(--border); background: var(--surface-card); }\n .alert--info { border-color: color-mix(in srgb, var(--accent) 22%, var(--border)); background: color-mix(in srgb, var(--accent) 7%, var(--surface-card)); }\n .alert--success { border-color: color-mix(in srgb, var(--status-approved) 22%, var(--border)); background: color-mix(in srgb, var(--status-approved) 7%, var(--surface-card)); }\n .alert--warning { border-color: color-mix(in srgb, var(--status-new) 22%, var(--border)); background: color-mix(in srgb, var(--status-new) 7%, var(--surface-card)); }\n .alert--danger { border-color: color-mix(in srgb, var(--status-rejected) 22%, var(--border)); background: color-mix(in srgb, var(--status-rejected) 7%, var(--surface-card)); }\n .alert__title { display: block; margin-bottom: .2rem; }\n .tabs { display: flex; gap: .25rem; border-bottom: 1px solid var(--border); margin-bottom: 1rem; overflow-x: auto; }\n .tabs__link { padding: .6rem .75rem; border-bottom: 2px solid transparent; color: var(--text-secondary); text-decoration: none; white-space: nowrap; font-weight: 600; }\n .tabs__link:hover { color: var(--text-primary); text-decoration: none; }\n .tabs__link--active { color: var(--text-primary); border-bottom-color: var(--accent); }\n .empty { text-align: center; padding: 2rem 1rem; border: 1px dashed var(--border); border-radius: var(--radius); background: var(--surface-card); }\n .empty__title { margin: 0 0 .3rem; font-size: 1.1rem; }\n .empty__desc { margin: 0 auto; color: var(--text-secondary); max-width: 50ch; }\n .empty__action { margin-top: 1rem; }\n .grid { display: grid; gap: 1rem; }\n .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n @media (max-width: 880px) { .grid--2, .grid--3 { grid-template-columns: 1fr; } }\n .table-wrap { overflow: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-card); }\n table { width: 100%; border-collapse: collapse; font-size: .9rem; }\n th, td { text-align: left; padding: .65rem .75rem; border-bottom: 1px solid var(--border); vertical-align: top; }\n th { background: var(--surface-muted); font-weight: 650; color: var(--text-secondary); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; }\n tr:last-child td { border-bottom: 0; }\n .stat { text-align: center; padding: .5rem; }\n .stat__value { font-size: 1.4rem; font-weight: 750; line-height: 1; }\n .stat__label { color: var(--text-secondary); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; }\n .snapshot-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }\n .snapshot-card { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface-card); display: flex; flex-direction: column; }\n .snapshot-card__head { padding: .6rem .75rem; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; gap: .5rem; align-items: center; }\n .snapshot-card__meta { font-size: .8rem; color: var(--text-secondary); }\n .snapshot-card__body { padding: .5rem; display: grid; gap: .5rem; }\n .diff-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; }\n @media (max-width: 900px) { .diff-grid { grid-template-columns: 1fr; } }\n .diff-pane { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface-card); }\n .diff-pane__label { padding: .4rem .6rem; font-weight: 650; font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-secondary); background: var(--surface-muted); border-bottom: 1px solid var(--border); }\n .diff-pane__img { display: block; width: 100%; height: auto; background: repeating-conic-gradient(#e5e7eb 0% 25%, #f9fafb 0% 50%) 0 0 / 16px 16px; }\n .comment { border: 1px solid var(--border); border-radius: var(--radius); padding: .75rem; background: var(--surface-card); }\n .comment__head { display: flex; gap: .5rem; align-items: center; font-size: .85rem; color: var(--text-secondary); }\n .comment__body { margin: .5rem 0 0; white-space: pre-wrap; word-break: break-word; }\n @media (max-width: 880px) {\n .topbar__menu { display: inline-flex; }\n .shell { grid-template-columns: 1fr; }\n .sidebar { display: none; position: fixed; inset: 56px 0 0 0; z-index: 30; height: auto; }\n .sidebar--open { display: block; }\n .content { padding: 1rem; }\n }\n `;\n}"],"mappings":";;;;;AAGA,SAAgB,UAAU,OAAmB,MAA0B;CACrE,OAAO;;kBAES,MAAM,OAAO;;wBAEP,MAAM,QAAQ,KAAK;wBACnB,MAAM,QAAQ,KAAK;;wBAEnB,MAAM,KAAK,QAAQ;0BACjB,MAAM,KAAK,UAAU;kBAC7B,MAAM,OAAO;;;;2BAIJ,MAAM,OAAO,SAAS;sBAC3B,MAAM,OAAO,IAAI;2BACZ,MAAM,OAAO,SAAS;qBAC5B,MAAM,OAAO;;;;;kBAKhB,KAAK,OAAO;wBACN,KAAK,QAAQ,KAAK;wBAClB,KAAK,QAAQ,KAAK;;wBAElB,KAAK,KAAK,QAAQ;0BAChB,KAAK,KAAK,UAAU;kBAC5B,KAAK,OAAO;2BACH,KAAK,OAAO,SAAS;sBAC1B,KAAK,OAAO,IAAI;2BACX,KAAK,OAAO,SAAS;;;;;;oBAM5B,KAAK,OAAO;0BACN,KAAK,QAAQ,KAAK;0BAClB,KAAK,QAAQ,KAAK;;0BAElB,KAAK,KAAK,QAAQ;4BAChB,KAAK,KAAK,UAAU;oBAC5B,KAAK,OAAO;6BACH,KAAK,OAAO,SAAS;wBAC1B,KAAK,OAAO,IAAI;6BACX,KAAK,OAAO,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsHlD"}
|
package/dist/ui/theme.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
//#region src/ui/theme.ts
|
|
5
|
+
/** Default light brand theme. */
|
|
5
6
|
const LIGHT_THEME = {
|
|
6
7
|
accent: "#2b7fff",
|
|
7
8
|
surface: {
|
|
@@ -19,6 +20,7 @@ const LIGHT_THEME = {
|
|
|
19
20
|
rejected: "#dc2626"
|
|
20
21
|
}
|
|
21
22
|
};
|
|
23
|
+
/** Default dark brand theme. */
|
|
22
24
|
const DARK_THEME = {
|
|
23
25
|
accent: "#4f8fff",
|
|
24
26
|
surface: {
|
package/dist/ui/theme.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.mjs","names":[],"sources":["../../src/ui/theme.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"theme.mjs","names":[],"sources":["../../src/ui/theme.ts"],"sourcesContent":["/** Brand theme tokens (accent, surfaces, text, borders, statuses). */\nexport interface BrandTheme {\n accent: string;\n surface: { base: string; card: string };\n text: { primary: string; secondary: string };\n border: string;\n status: { approved: string; new: string; rejected: string };\n}\n\n/** Default light brand theme. */\nexport const LIGHT_THEME: BrandTheme = {\n accent: \"#2b7fff\",\n surface: { base: \"#f6f6f7\", card: \"#ffffff\" },\n text: { primary: \"#09090b\", secondary: \"#71717b\" },\n border: \"#e4e4e7\",\n status: { approved: \"#16a34a\", new: \"#d97706\", rejected: \"#dc2626\" },\n};\n\n/** Default dark brand theme. */\nexport const DARK_THEME: BrandTheme = {\n accent: \"#4f8fff\",\n surface: { base: \"#09090b\", card: \"#18181b\" },\n text: { primary: \"#fafafa\", secondary: \"#9f9fa9\" },\n border: \"#ffffff1a\",\n status: { approved: \"#22c55e\", new: \"#f59e0b\", rejected: \"#ef4444\" },\n};\n"],"mappings":";;;;;AAUA,MAAa,cAA0B;CACrC,QAAQ;CACR,SAAS;EAAE,MAAM;EAAW,MAAM;CAAU;CAC5C,MAAM;EAAE,SAAS;EAAW,WAAW;CAAU;CACjD,QAAQ;CACR,QAAQ;EAAE,UAAU;EAAW,KAAK;EAAW,UAAU;CAAU;AACrE;;AAGA,MAAa,aAAyB;CACpC,QAAQ;CACR,SAAS;EAAE,MAAM;EAAW,MAAM;CAAU;CAC5C,MAAM;EAAE,SAAS;EAAW,WAAW;CAAU;CACjD,QAAQ;CACR,QAAQ;EAAE,UAAU;EAAW,KAAK;EAAW,UAAU;CAAU;AACrE"}
|
package/dist/urls.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
//#region src/urls.d.ts
|
|
4
|
+
/** Type-safe URL builder for project pages and published Storybooks. */
|
|
4
5
|
interface UrlBuilder {
|
|
5
6
|
projectsList(): string;
|
|
6
7
|
project(slug: string): string;
|
|
@@ -13,6 +14,13 @@ interface UrlBuilder {
|
|
|
13
14
|
storybookBuild(slug: string, buildId: string): string;
|
|
14
15
|
settings(slug: string): string;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a URL builder rooted at the given base URL.
|
|
19
|
+
*
|
|
20
|
+
* @param baseUrl - Public root URL of the shelf server.
|
|
21
|
+
* @param publishedBaseDomain - Optional wildcard domain for published Storybooks.
|
|
22
|
+
* @returns The URL builder.
|
|
23
|
+
*/
|
|
16
24
|
declare function createUrlBuilder(baseUrl: string, publishedBaseDomain?: string): UrlBuilder;
|
|
17
25
|
//#endregion
|
|
18
26
|
export { UrlBuilder, createUrlBuilder };
|
package/dist/urls.mjs
CHANGED
|
@@ -2,6 +2,13 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
//#region src/urls.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create a URL builder rooted at the given base URL.
|
|
7
|
+
*
|
|
8
|
+
* @param baseUrl - Public root URL of the shelf server.
|
|
9
|
+
* @param publishedBaseDomain - Optional wildcard domain for published Storybooks.
|
|
10
|
+
* @returns The URL builder.
|
|
11
|
+
*/
|
|
5
12
|
function createUrlBuilder(baseUrl, publishedBaseDomain) {
|
|
6
13
|
const root = baseUrl.replace(/\/+$/u, "");
|
|
7
14
|
return {
|
package/dist/urls.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.mjs","names":[],"sources":["../src/urls.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"urls.mjs","names":[],"sources":["../src/urls.ts"],"sourcesContent":["/** Type-safe URL builder for project pages and published Storybooks. */\nexport interface UrlBuilder {\n projectsList(): string;\n project(slug: string): string;\n buildsList(slug: string): string;\n build(slug: string, buildId: string): string;\n labels(slug: string): string;\n label(slug: string, key: string, value: string): string;\n storybook(slug: string): string;\n storybookLabel(slug: string, key: string, value: string): string;\n storybookBuild(slug: string, buildId: string): string;\n settings(slug: string): string;\n}\n\n/**\n * Create a URL builder rooted at the given base URL.\n *\n * @param baseUrl - Public root URL of the shelf server.\n * @param publishedBaseDomain - Optional wildcard domain for published Storybooks.\n * @returns The URL builder.\n */\nexport function createUrlBuilder(baseUrl: string, publishedBaseDomain?: string): UrlBuilder {\n const root = baseUrl.replace(/\\/+$/u, \"\");\n\n return {\n projectsList: () => root,\n project: (slug) => `${root}/projects/${slug}`,\n buildsList: (slug) => `${root}/projects/${slug}/builds`,\n build: (slug, buildId) => `${root}/projects/${slug}/builds/${buildId}`,\n labels: (slug) => `${root}/projects/${slug}/labels`,\n label: (slug, key, value) => `${root}/projects/${slug}/labels/${encodeURIComponent(key)}/${encodeURI(value)}`,\n storybook: (slug) => (publishedBaseDomain ? `https://${slug}.${publishedBaseDomain}` : `${root}/projects/${slug}/storybook`),\n storybookLabel: (slug, key, value) => `${root}/projects/${slug}/storybook/${encodeURIComponent(key)}/${encodeURI(value)}`,\n storybookBuild: (slug, buildId) =>\n publishedBaseDomain ? `https://${buildId}.${slug}.${publishedBaseDomain}` : `${root}/projects/${slug}/storybook/build/${buildId}`,\n settings: (slug) => `${root}/projects/${slug}/settings`,\n };\n}\n"],"mappings":";;;;;;;;;;;AAqBA,SAAgB,iBAAiB,SAAiB,qBAA0C;CAC1F,MAAM,OAAO,QAAQ,QAAQ,SAAS,EAAE;CAExC,OAAO;EACL,oBAAoB;EACpB,UAAU,SAAS,GAAG,KAAK,YAAY;EACvC,aAAa,SAAS,GAAG,KAAK,YAAY,KAAK;EAC/C,QAAQ,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,UAAU;EAC7D,SAAS,SAAS,GAAG,KAAK,YAAY,KAAK;EAC3C,QAAQ,MAAM,KAAK,UAAU,GAAG,KAAK,YAAY,KAAK,UAAU,mBAAmB,GAAG,EAAE,GAAG,UAAU,KAAK;EAC1G,YAAY,SAAU,sBAAsB,WAAW,KAAK,GAAG,wBAAwB,GAAG,KAAK,YAAY,KAAK;EAChH,iBAAiB,MAAM,KAAK,UAAU,GAAG,KAAK,YAAY,KAAK,aAAa,mBAAmB,GAAG,EAAE,GAAG,UAAU,KAAK;EACtH,iBAAiB,MAAM,YACrB,sBAAsB,WAAW,QAAQ,GAAG,KAAK,GAAG,wBAAwB,GAAG,KAAK,YAAY,KAAK,mBAAmB;EAC1H,WAAW,SAAS,GAAG,KAAK,YAAY,KAAK;CAC/C;AACF"}
|
package/dist/utils/hash.mjs
CHANGED
|
@@ -3,12 +3,15 @@ import "node:url";
|
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
5
5
|
//#region src/utils/hash.ts
|
|
6
|
+
/** Hash a value with SHA-256, returning lowercase hex. */
|
|
6
7
|
function sha256(value) {
|
|
7
8
|
return createHash("sha256").update(value).digest("hex");
|
|
8
9
|
}
|
|
10
|
+
/** Sign a value with HMAC-SHA-256, returning lowercase hex. */
|
|
9
11
|
function hmacSha256(secret, value) {
|
|
10
12
|
return createHmac("sha256", secret).update(value).digest("hex");
|
|
11
13
|
}
|
|
14
|
+
/** Generate a prefixed random token and its SHA-256 hash. */
|
|
12
15
|
function randomToken(prefix) {
|
|
13
16
|
const value = `${prefix}${randomBytes(24).toString("base64url")}`;
|
|
14
17
|
return {
|
package/dist/utils/hash.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.mjs","names":[],"sources":["../../src/utils/hash.ts"],"sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nexport function sha256(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport function hmacSha256(secret: string, value: string): string {\n return createHmac(\"sha256\", secret).update(value).digest(\"hex\");\n}\n\nexport function randomToken(prefix: string): { value: string; hash: string } {\n const value = `${prefix}${randomBytes(24).toString(\"base64url\")}`;\n return { value, hash: sha256(value) };\n}\n\nexport function timingSafeEqualString(a: string, b: string): boolean {\n const ab = Buffer.from(a);\n const bb = Buffer.from(b);\n return ab.length === bb.length && timingSafeEqual(ab, bb);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"hash.mjs","names":[],"sources":["../../src/utils/hash.ts"],"sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\n\n/** Hash a value with SHA-256, returning lowercase hex. */\nexport function sha256(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\n/** Sign a value with HMAC-SHA-256, returning lowercase hex. */\nexport function hmacSha256(secret: string, value: string): string {\n return createHmac(\"sha256\", secret).update(value).digest(\"hex\");\n}\n\n/** Generate a prefixed random token and its SHA-256 hash. */\nexport function randomToken(prefix: string): { value: string; hash: string } {\n const value = `${prefix}${randomBytes(24).toString(\"base64url\")}`;\n return { value, hash: sha256(value) };\n}\n\n/** Compare two strings in constant time to avoid timing leaks. */\nexport function timingSafeEqualString(a: string, b: string): boolean {\n const ab = Buffer.from(a);\n const bb = Buffer.from(b);\n return ab.length === bb.length && timingSafeEqual(ab, bb);\n}\n"],"mappings":";;;;;;AAGA,SAAgB,OAAO,OAAuB;CAC5C,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK;AACxD;;AAGA,SAAgB,WAAW,QAAgB,OAAuB;CAChE,OAAO,WAAW,UAAU,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK;AAChE;;AAGA,SAAgB,YAAY,QAAiD;CAC3E,MAAM,QAAQ,GAAG,SAAS,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;CAC9D,OAAO;EAAE;EAAO,MAAM,OAAO,KAAK;CAAE;AACtC"}
|
package/dist/utils/paths.d.mts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
//#region src/utils/paths.d.ts
|
|
4
|
+
/** Storage path for a captured snapshot screenshot. */
|
|
4
5
|
declare function screenshotPath(projectId: string, buildId: string, storyId: string, viewport: string): string;
|
|
6
|
+
/** Storage path for a snapshot diff overlay image. */
|
|
5
7
|
declare function diffPath(projectId: string, buildId: string, storyId: string, viewport: string): string;
|
|
8
|
+
/** Storage path for a branch baseline screenshot. */
|
|
6
9
|
declare function baselinePath(projectId: string, branch: string, storyId: string, viewport: string): string;
|
|
10
|
+
/** Storage prefix for an extracted published Storybook. */
|
|
7
11
|
declare function storybookDir(projectId: string, buildId: string): string;
|
|
12
|
+
/** Storage path for an uploaded Storybook zip. */
|
|
8
13
|
declare function storybookZipPath(projectId: string, buildId: string): string;
|
|
9
14
|
//#endregion
|
|
10
15
|
export { baselinePath, diffPath, screenshotPath, storybookDir, storybookZipPath };
|
package/dist/utils/paths.mjs
CHANGED
|
@@ -2,18 +2,23 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
//#region src/utils/paths.ts
|
|
5
|
+
/** Storage path for a captured snapshot screenshot. */
|
|
5
6
|
function screenshotPath(projectId, buildId, storyId, viewport) {
|
|
6
7
|
return `${projectId}/builds/${buildId}/screenshots/${storyId}/${viewport}.png`;
|
|
7
8
|
}
|
|
9
|
+
/** Storage path for a snapshot diff overlay image. */
|
|
8
10
|
function diffPath(projectId, buildId, storyId, viewport) {
|
|
9
11
|
return `${projectId}/builds/${buildId}/diffs/${storyId}/${viewport}.png`;
|
|
10
12
|
}
|
|
13
|
+
/** Storage path for a branch baseline screenshot. */
|
|
11
14
|
function baselinePath(projectId, branch, storyId, viewport) {
|
|
12
15
|
return `${projectId}/baselines/${branch}/${storyId}/${viewport}.png`;
|
|
13
16
|
}
|
|
17
|
+
/** Storage prefix for an extracted published Storybook. */
|
|
14
18
|
function storybookDir(projectId, buildId) {
|
|
15
19
|
return `${projectId}/builds/${buildId}/storybook`;
|
|
16
20
|
}
|
|
21
|
+
/** Storage path for an uploaded Storybook zip. */
|
|
17
22
|
function storybookZipPath(projectId, buildId) {
|
|
18
23
|
return `${projectId}/builds/${buildId}/storybook.zip`;
|
|
19
24
|
}
|
package/dist/utils/paths.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.mjs","names":[],"sources":["../../src/utils/paths.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"paths.mjs","names":[],"sources":["../../src/utils/paths.ts"],"sourcesContent":["/** Storage path for a captured snapshot screenshot. */\nexport function screenshotPath(projectId: string, buildId: string, storyId: string, viewport: string): string {\n return `${projectId}/builds/${buildId}/screenshots/${storyId}/${viewport}.png`;\n}\n\n/** Storage path for a snapshot diff overlay image. */\nexport function diffPath(projectId: string, buildId: string, storyId: string, viewport: string): string {\n return `${projectId}/builds/${buildId}/diffs/${storyId}/${viewport}.png`;\n}\n\n/** Storage path for a branch baseline screenshot. */\nexport function baselinePath(projectId: string, branch: string, storyId: string, viewport: string): string {\n return `${projectId}/baselines/${branch}/${storyId}/${viewport}.png`;\n}\n\n/** Storage prefix for an extracted published Storybook. */\nexport function storybookDir(projectId: string, buildId: string): string {\n return `${projectId}/builds/${buildId}/storybook`;\n}\n\n/** Storage path for an uploaded Storybook zip. */\nexport function storybookZipPath(projectId: string, buildId: string): string {\n return `${projectId}/builds/${buildId}/storybook.zip`;\n}\n"],"mappings":";;;;;AACA,SAAgB,eAAe,WAAmB,SAAiB,SAAiB,UAA0B;CAC5G,OAAO,GAAG,UAAU,UAAU,QAAQ,eAAe,QAAQ,GAAG,SAAS;AAC3E;;AAGA,SAAgB,SAAS,WAAmB,SAAiB,SAAiB,UAA0B;CACtG,OAAO,GAAG,UAAU,UAAU,QAAQ,SAAS,QAAQ,GAAG,SAAS;AACrE;;AAGA,SAAgB,aAAa,WAAmB,QAAgB,SAAiB,UAA0B;CACzG,OAAO,GAAG,UAAU,aAAa,OAAO,GAAG,QAAQ,GAAG,SAAS;AACjE;;AAGA,SAAgB,aAAa,WAAmB,SAAyB;CACvE,OAAO,GAAG,UAAU,UAAU,QAAQ;AACxC;;AAGA,SAAgB,iBAAiB,WAAmB,SAAyB;CAC3E,OAAO,GAAG,UAAU,UAAU,QAAQ;AACxC"}
|
package/dist/utils/ulid.d.mts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
//#region src/utils/ulid.d.ts
|
|
4
|
+
/** Generate a sortable, collision-resistant ULID. */
|
|
4
5
|
declare function ulid(): string;
|
|
6
|
+
/** Convert a name to a URL-safe slug of at most 63 characters. */
|
|
5
7
|
declare function slugify(value: string): string;
|
|
6
8
|
//#endregion
|
|
7
9
|
export { slugify, ulid };
|
package/dist/utils/ulid.mjs
CHANGED
|
@@ -29,9 +29,11 @@ function encodeRandom(bytes) {
|
|
|
29
29
|
if (bits > 0) out += CROCKFORD.charAt(buffer << 5 - bits & 31);
|
|
30
30
|
return out;
|
|
31
31
|
}
|
|
32
|
+
/** Generate a sortable, collision-resistant ULID. */
|
|
32
33
|
function ulid() {
|
|
33
34
|
return encodeTime(Date.now()) + encodeRandom(randomBytes(10));
|
|
34
35
|
}
|
|
36
|
+
/** Convert a name to a URL-safe slug of at most 63 characters. */
|
|
35
37
|
function slugify(value) {
|
|
36
38
|
return value.toLowerCase().replaceAll(/[^a-z0-9]+/gu, "-").replaceAll(/^-+|-+$/gu, "").slice(0, 63);
|
|
37
39
|
}
|
package/dist/utils/ulid.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/utils/ulid.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\nconst CROCKFORD = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction encodeTime(time: number): string {\n let out = \"\";\n let remaining = time;\n for (let i = 9; i >= 0; i -= 1) {\n const mod = remaining % 32;\n out = CROCKFORD.charAt(mod) + out;\n remaining = (remaining - mod) / 32;\n }\n return out;\n}\n\n/* eslint-disable no-bitwise, no-non-null-assertion -- ULID encoding is inherently bitwise. */\nfunction encodeRandom(bytes: Buffer): string {\n let out = \"\";\n let buffer = 0;\n let bits = 0;\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD.charAt((buffer >>> (bits - 5)) & 31);\n bits -= 5;\n }\n }\n if (bits > 0) {\n out += CROCKFORD.charAt((buffer << (5 - bits)) & 31);\n }\n return out;\n}\n/* eslint-enable no-bitwise, no-non-null-assertion */\n\nexport function ulid(): string {\n return encodeTime(Date.now()) + encodeRandom(randomBytes(10));\n}\n\nexport function slugify(value: string): string {\n return value\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gu, \"-\")\n .replaceAll(/^-+|-+$/gu, \"\")\n .slice(0, 63);\n}\n"],"mappings":";;;;;AAEA,MAAM,YAAY;AAElB,SAAS,WAAW,MAAsB;CACxC,IAAI,MAAM;CACV,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG;EAC9B,MAAM,MAAM,YAAY;EACxB,MAAM,UAAU,OAAO,GAAG,IAAI;EAC9B,aAAa,YAAY,OAAO;CAClC;CACA,OAAO;AACT;AAGA,SAAS,aAAa,OAAuB;CAC3C,IAAI,MAAM;CACV,IAAI,SAAS;CACb,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAU,UAAU,IAAK;EACzB,QAAQ;EACR,OAAO,QAAQ,GAAG;GAChB,OAAO,UAAU,OAAQ,WAAY,OAAO,IAAM,EAAE;GACpD,QAAQ;EACV;CACF;CACA,IAAI,OAAO,GACT,OAAO,UAAU,OAAQ,UAAW,IAAI,OAAS,EAAE;CAErD,OAAO;AACT
|
|
1
|
+
{"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/utils/ulid.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\nconst CROCKFORD = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction encodeTime(time: number): string {\n let out = \"\";\n let remaining = time;\n for (let i = 9; i >= 0; i -= 1) {\n const mod = remaining % 32;\n out = CROCKFORD.charAt(mod) + out;\n remaining = (remaining - mod) / 32;\n }\n return out;\n}\n\n/* eslint-disable no-bitwise, no-non-null-assertion -- ULID encoding is inherently bitwise. */\nfunction encodeRandom(bytes: Buffer): string {\n let out = \"\";\n let buffer = 0;\n let bits = 0;\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD.charAt((buffer >>> (bits - 5)) & 31);\n bits -= 5;\n }\n }\n if (bits > 0) {\n out += CROCKFORD.charAt((buffer << (5 - bits)) & 31);\n }\n return out;\n}\n/* eslint-enable no-bitwise, no-non-null-assertion */\n\n/** Generate a sortable, collision-resistant ULID. */\nexport function ulid(): string {\n return encodeTime(Date.now()) + encodeRandom(randomBytes(10));\n}\n\n/** Convert a name to a URL-safe slug of at most 63 characters. */\nexport function slugify(value: string): string {\n return value\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gu, \"-\")\n .replaceAll(/^-+|-+$/gu, \"\")\n .slice(0, 63);\n}\n"],"mappings":";;;;;AAEA,MAAM,YAAY;AAElB,SAAS,WAAW,MAAsB;CACxC,IAAI,MAAM;CACV,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG;EAC9B,MAAM,MAAM,YAAY;EACxB,MAAM,UAAU,OAAO,GAAG,IAAI;EAC9B,aAAa,YAAY,OAAO;CAClC;CACA,OAAO;AACT;AAGA,SAAS,aAAa,OAAuB;CAC3C,IAAI,MAAM;CACV,IAAI,SAAS;CACb,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAU,UAAU,IAAK;EACzB,QAAQ;EACR,OAAO,QAAQ,GAAG;GAChB,OAAO,UAAU,OAAQ,WAAY,OAAO,IAAM,EAAE;GACpD,QAAQ;EACV;CACF;CACA,IAAI,OAAO,GACT,OAAO,UAAU,OAAQ,UAAW,IAAI,OAAS,EAAE;CAErD,OAAO;AACT;;AAIA,SAAgB,OAAe;CAC7B,OAAO,WAAW,KAAK,IAAI,CAAC,IAAI,aAAa,YAAY,EAAE,CAAC;AAC9D;;AAGA,SAAgB,QAAQ,OAAuB;CAC7C,OAAO,MACJ,YAAY,CAAC,CACb,WAAW,gBAAgB,GAAG,CAAC,CAC/B,WAAW,aAAa,EAAE,CAAC,CAC3B,MAAM,GAAG,EAAE;AAChB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyshelf/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "StoryShelf core: Hono router, adapter interfaces, models, capture pipeline, diff, retention.",
|
|
5
5
|
"homepage": "https://github.com/GuptaSiddhant/StoryShelf#readme",
|
|
6
6
|
"bugs": {
|