@storyshelf/core 0.3.1 → 0.5.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/README.md +38 -31
- package/dist/adapter/capture-queue.d.mts +29 -1
- package/dist/adapter/capture-runner.d.mts +18 -2
- package/dist/adapter/capture-runner.mjs +12 -1
- package/dist/adapter/capture-runner.mjs.map +1 -0
- package/dist/adapter/database.d.mts +67 -17
- package/dist/adapter/database.mjs +22 -55
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/email-sender.d.mts +27 -0
- package/dist/adapter/email-sender.mjs +4 -0
- package/dist/adapter/metadata.d.mts +21 -15
- package/dist/adapter/notifier.d.mts +7 -0
- package/dist/adapter/notifier.mjs +6 -0
- package/dist/adapter/setup.d.mts +61 -0
- package/dist/adapter/setup.mjs +29 -0
- package/dist/adapter/setup.mjs.map +1 -0
- package/dist/adapter/webhook-events.d.mts +29 -0
- package/dist/adapter/webhook-events.mjs +83 -0
- package/dist/adapter/webhook-events.mjs.map +1 -0
- package/dist/adapters/notifier/events.d.mts +26 -0
- package/dist/adapters/notifier/events.mjs +66 -0
- package/dist/adapters/notifier/events.mjs.map +1 -0
- package/dist/adapters/notifier/format.d.mts +14 -0
- package/dist/adapters/notifier/format.mjs +96 -0
- package/dist/adapters/notifier/format.mjs.map +1 -0
- package/dist/adapters/notifier/provider.d.mts +32 -0
- package/dist/adapters/notifier/types.d.mts +56 -0
- package/dist/adapters/setup-runner.d.mts +23 -0
- package/dist/adapters/setup-runner.mjs +149 -0
- package/dist/adapters/setup-runner.mjs.map +1 -0
- package/dist/adapters/validate.d.mts +30 -0
- package/dist/adapters/validate.mjs +313 -0
- package/dist/adapters/validate.mjs.map +1 -0
- package/dist/auth.d.mts +94 -0
- package/dist/auth.mjs +4 -0
- package/dist/brand-packs.d.mts +16 -0
- package/dist/brand-packs.mjs +130 -0
- package/dist/brand-packs.mjs.map +1 -0
- package/dist/capture/adapter.d.mts +51 -1
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +16 -0
- package/dist/capture/affected.mjs +64 -0
- package/dist/capture/affected.mjs.map +1 -0
- package/dist/capture/diff-record.mjs +30 -0
- package/dist/capture/diff-record.mjs.map +1 -0
- package/dist/capture/dispatch.d.mts +36 -0
- package/dist/capture/dispatch.mjs +88 -31
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/guards.mjs +31 -0
- package/dist/capture/guards.mjs.map +1 -0
- package/dist/capture/orchestrator.d.mts +41 -6
- package/dist/capture/orchestrator.mjs +151 -28
- package/dist/capture/orchestrator.mjs.map +1 -1
- package/dist/capture/pipeline.d.mts +30 -16
- package/dist/capture/pipeline.mjs +143 -39
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/recovery.d.mts +21 -0
- package/dist/capture/recovery.mjs +83 -0
- package/dist/capture/recovery.mjs.map +1 -0
- package/dist/capture/rediff.d.mts +35 -0
- package/dist/capture/rediff.mjs +77 -0
- package/dist/capture/rediff.mjs.map +1 -0
- package/dist/capture/sizing.d.mts +58 -0
- package/dist/capture/sizing.mjs +119 -0
- package/dist/capture/sizing.mjs.map +1 -0
- package/dist/capture/skip-checks.mjs +3 -3
- package/dist/capture/skip-checks.mjs.map +1 -1
- package/dist/capture/statics.d.mts +38 -0
- package/dist/capture/statics.mjs +38 -4
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/status-fanout.mjs +7 -2
- package/dist/capture/status-fanout.mjs.map +1 -1
- package/dist/capture/storybook.d.mts +31 -2
- package/dist/capture/storybook.mjs +77 -2
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture.d.mts +10 -4
- package/dist/capture.mjs +7 -2
- package/dist/config.d.mts +121 -4
- package/dist/config.mjs +55 -8
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.mts +5 -56
- package/dist/index.mjs +4 -284
- package/dist/logger.d.mts +26 -17
- package/dist/logger.mjs +10 -5
- package/dist/logger.mjs.map +1 -1
- package/dist/models/baseline-status.d.mts +29 -0
- package/dist/models/baseline-status.mjs +26 -0
- package/dist/models/baseline-status.mjs.map +1 -0
- package/dist/models/baseline.d.mts +33 -0
- package/dist/models/baseline.mjs +35 -13
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build.d.mts +87 -0
- package/dist/models/build.mjs +83 -35
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +40 -0
- package/dist/models/capture-attempt.mjs +85 -0
- package/dist/models/capture-attempt.mjs.map +1 -0
- package/dist/models/capture-log.d.mts +21 -0
- package/dist/models/capture-log.mjs +44 -0
- package/dist/models/capture-log.mjs.map +1 -0
- package/dist/models/comment.d.mts +29 -0
- package/dist/models/comment.mjs +11 -8
- package/dist/models/comment.mjs.map +1 -1
- package/dist/models/content-ref.d.mts +21 -0
- package/dist/models/content-ref.mjs +49 -0
- package/dist/models/content-ref.mjs.map +1 -0
- package/dist/models/credentials.d.mts +36 -0
- package/dist/models/credentials.mjs +103 -0
- package/dist/models/credentials.mjs.map +1 -0
- package/dist/models/label.d.mts +58 -0
- package/dist/models/label.mjs +32 -27
- package/dist/models/label.mjs.map +1 -1
- package/dist/models/member.d.mts +34 -0
- package/dist/models/member.mjs +20 -11
- package/dist/models/member.mjs.map +1 -1
- package/dist/models/notification-channel.d.mts +52 -0
- package/dist/models/notification-channel.mjs +93 -0
- package/dist/models/notification-channel.mjs.map +1 -0
- package/dist/models/notification-subscription.d.mts +44 -0
- package/dist/models/notification-subscription.mjs +89 -0
- package/dist/models/notification-subscription.mjs.map +1 -0
- package/dist/models/project-group-mapping.d.mts +30 -0
- package/dist/models/project-group-mapping.mjs +46 -0
- package/dist/models/project-group-mapping.mjs.map +1 -0
- package/dist/models/project.d.mts +54 -0
- package/dist/models/project.mjs +15 -11
- package/dist/models/project.mjs.map +1 -1
- package/dist/models/snapshot.d.mts +58 -0
- package/dist/models/snapshot.mjs +13 -7
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/status-config.d.mts +38 -0
- package/dist/models/status-config.mjs +12 -11
- package/dist/models/status-config.mjs.map +1 -1
- package/dist/models/token.d.mts +44 -0
- package/dist/models/token.mjs +18 -15
- package/dist/models/token.mjs.map +1 -1
- package/dist/models/user.d.mts +42 -0
- package/dist/models/user.mjs +65 -0
- package/dist/models/user.mjs.map +1 -0
- package/dist/models/webhook.d.mts +50 -0
- package/dist/models/webhook.mjs +12 -10
- package/dist/models/webhook.mjs.map +1 -1
- package/dist/models.d.mts +22 -0
- package/dist/models.mjs +23 -0
- package/dist/paths.mjs +29 -0
- package/dist/paths.mjs.map +1 -1
- package/dist/retention.d.mts +45 -0
- package/dist/retention.mjs +145 -0
- package/dist/retention.mjs.map +1 -0
- package/dist/schema/baseline.d.mts +1 -0
- package/dist/schema/build.d.mts +8 -0
- package/dist/schema/capture-attempt.d.mts +38 -0
- package/dist/schema/comment.d.mts +1 -1
- package/dist/schema/content-ref.d.mts +13 -0
- package/dist/schema/member.d.mts +2 -0
- package/dist/schema/notification.d.mts +35 -0
- package/dist/schema/project-group-mapping.d.mts +15 -0
- package/dist/schema/project.d.mts +4 -0
- package/dist/schema/snapshot.d.mts +7 -0
- package/dist/schema/token.d.mts +2 -0
- package/dist/schema/user.d.mts +11 -1
- package/dist/schema.d.mts +9 -46
- package/dist/schema.mjs +1 -55
- package/dist/test-helpers/create-project.d.mts +15 -0
- package/dist/test-helpers/create-project.mjs +28 -0
- package/dist/test-helpers/create-project.mjs.map +1 -0
- package/dist/test-helpers/database-contract.d.mts +13 -0
- package/dist/test-helpers/database-contract.mjs +58 -0
- package/dist/test-helpers/database-contract.mjs.map +1 -0
- package/dist/test-helpers/fake-adapters.d.mts +14 -0
- package/dist/test-helpers/fake-adapters.mjs +20 -0
- package/dist/test-helpers/fake-adapters.mjs.map +1 -0
- package/dist/test-helpers/fake-database.d.mts +11 -0
- package/dist/test-helpers/fake-database.mjs +104 -0
- package/dist/test-helpers/fake-database.mjs.map +1 -0
- package/dist/test-helpers/fake-storage.d.mts +14 -0
- package/dist/test-helpers/fake-storage.mjs +49 -0
- package/dist/test-helpers/fake-storage.mjs.map +1 -0
- package/dist/test-helpers/fake-tables.mjs +276 -0
- package/dist/test-helpers/fake-tables.mjs.map +1 -0
- package/dist/test-helpers/git-contract.d.mts +11 -0
- package/dist/test-helpers/git-contract.mjs +34 -0
- package/dist/test-helpers/git-contract.mjs.map +1 -0
- package/dist/test-helpers/notifier-contract.d.mts +11 -0
- package/dist/test-helpers/notifier-contract.mjs +34 -0
- package/dist/test-helpers/notifier-contract.mjs.map +1 -0
- package/dist/test-helpers/queue-contract.d.mts +11 -0
- package/dist/test-helpers/queue-contract.mjs +64 -0
- package/dist/test-helpers/queue-contract.mjs.map +1 -0
- package/dist/test-helpers/runner-contract.d.mts +11 -0
- package/dist/test-helpers/runner-contract.mjs +32 -0
- package/dist/test-helpers/runner-contract.mjs.map +1 -0
- package/dist/test-helpers/sql-chunks.mjs +138 -0
- package/dist/test-helpers/sql-chunks.mjs.map +1 -0
- package/dist/test-helpers/storage-contract.d.mts +11 -0
- package/dist/test-helpers/storage-contract.mjs +87 -0
- package/dist/test-helpers/storage-contract.mjs.map +1 -0
- package/dist/test-helpers.d.mts +13 -0
- package/dist/test-helpers.mjs +14 -0
- package/dist/tracing.mjs +63 -0
- package/dist/tracing.mjs.map +1 -0
- package/dist/types.d.mts +38 -5
- package/dist/types.mjs +18 -5
- package/dist/types.mjs.map +1 -1
- package/dist/urls.d.mts +12 -1
- package/dist/urls.mjs +22 -3
- package/dist/urls.mjs.map +1 -1
- package/dist/utils/encrypt.d.mts +48 -0
- package/dist/utils/encrypt.mjs +67 -13
- package/dist/utils/encrypt.mjs.map +1 -1
- package/dist/utils/hash.d.mts +17 -0
- package/dist/utils/hash.mjs +8 -2
- package/dist/utils/hash.mjs.map +1 -1
- package/dist/utils/http.d.mts +58 -0
- package/dist/utils/http.mjs +147 -0
- package/dist/utils/http.mjs.map +1 -0
- package/dist/utils/mime.d.mts +9 -0
- package/dist/utils/mime.mjs +33 -0
- package/dist/utils/mime.mjs.map +1 -0
- package/dist/utils/path-security.d.mts +12 -0
- package/dist/utils/path-security.mjs +24 -0
- package/dist/utils/path-security.mjs.map +1 -0
- package/dist/utils/redact.d.mts +17 -0
- package/dist/utils/redact.mjs +42 -0
- package/dist/utils/redact.mjs.map +1 -0
- package/dist/utils/timing.d.mts +19 -0
- package/dist/utils/timing.mjs +46 -0
- package/dist/utils/timing.mjs.map +1 -0
- package/dist/utils/ulid.d.mts +10 -0
- package/dist/utils/ulid.mjs +8 -8
- package/dist/utils/ulid.mjs.map +1 -1
- package/dist/utils.d.mts +12 -0
- package/dist/utils.mjs +13 -0
- package/package.json +69 -28
- package/dist/adapter/auth.d.mts +0 -50
- package/dist/adapter/auth.mjs +0 -10
- package/dist/adapter/auth.mjs.map +0 -1
- package/dist/adapter/init.d.mts +0 -58
- package/dist/adapter/init.mjs +0 -93
- package/dist/adapter/init.mjs.map +0 -1
- package/dist/adapters/webhook-events.mjs +0 -55
- package/dist/adapters/webhook-events.mjs.map +0 -1
- package/dist/ddl.d.mts +0 -8
- package/dist/ddl.mjs +0 -158
- package/dist/ddl.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/middleware/auth-gate.mjs +0 -36
- package/dist/middleware/auth-gate.mjs.map +0 -1
- package/dist/middleware/csrf.mjs +0 -40
- package/dist/middleware/csrf.mjs.map +0 -1
- package/dist/middleware/rate-limit.mjs +0 -39
- package/dist/middleware/rate-limit.mjs.map +0 -1
- package/dist/middleware/request-log.mjs +0 -28
- package/dist/middleware/request-log.mjs.map +0 -1
- package/dist/middleware/store-scope.mjs +0 -29
- package/dist/middleware/store-scope.mjs.map +0 -1
- package/dist/pages/build-detail.mjs +0 -339
- package/dist/pages/build-detail.mjs.map +0 -1
- package/dist/pages/build-diff-comments.mjs +0 -113
- package/dist/pages/build-diff-comments.mjs.map +0 -1
- package/dist/pages/build-diff-header.mjs +0 -163
- package/dist/pages/build-diff-header.mjs.map +0 -1
- package/dist/pages/build-diff-nav.mjs +0 -66
- package/dist/pages/build-diff-nav.mjs.map +0 -1
- package/dist/pages/build-diff-viewer.mjs +0 -197
- package/dist/pages/build-diff-viewer.mjs.map +0 -1
- package/dist/pages/build-diff.mjs +0 -90
- package/dist/pages/build-diff.mjs.map +0 -1
- package/dist/pages/compute-jobs.mjs +0 -198
- package/dist/pages/compute-jobs.mjs.map +0 -1
- package/dist/pages/label-detail.mjs +0 -228
- package/dist/pages/label-detail.mjs.map +0 -1
- package/dist/pages/login.mjs +0 -78
- package/dist/pages/login.mjs.map +0 -1
- package/dist/pages/project-builds.mjs +0 -231
- package/dist/pages/project-builds.mjs.map +0 -1
- package/dist/pages/project-create.mjs +0 -169
- package/dist/pages/project-create.mjs.map +0 -1
- package/dist/pages/project-settings.mjs +0 -102
- package/dist/pages/project-settings.mjs.map +0 -1
- package/dist/pages/projects.mjs +0 -184
- package/dist/pages/projects.mjs.map +0 -1
- package/dist/pages/root.mjs +0 -94
- package/dist/pages/root.mjs.map +0 -1
- package/dist/pages/settings-general.mjs +0 -192
- package/dist/pages/settings-general.mjs.map +0 -1
- package/dist/pages/settings-labels.mjs +0 -150
- package/dist/pages/settings-labels.mjs.map +0 -1
- package/dist/pages/settings-members.mjs +0 -125
- package/dist/pages/settings-members.mjs.map +0 -1
- package/dist/pages/settings-status.mjs +0 -152
- package/dist/pages/settings-status.mjs.map +0 -1
- package/dist/pages/settings-tests.mjs +0 -149
- package/dist/pages/settings-tests.mjs.map +0 -1
- package/dist/pages/settings-tokens.mjs +0 -96
- package/dist/pages/settings-tokens.mjs.map +0 -1
- package/dist/pages/settings-webhooks.mjs +0 -150
- package/dist/pages/settings-webhooks.mjs.map +0 -1
- package/dist/pages/storybook.mjs +0 -96
- package/dist/pages/storybook.mjs.map +0 -1
- package/dist/retention/purge.mjs +0 -67
- package/dist/retention/purge.mjs.map +0 -1
- package/dist/routers/admin.mjs +0 -42
- package/dist/routers/admin.mjs.map +0 -1
- package/dist/routers/assets.mjs +0 -25
- package/dist/routers/assets.mjs.map +0 -1
- package/dist/routers/auth.mjs +0 -78
- package/dist/routers/auth.mjs.map +0 -1
- package/dist/routers/builds.handlers.mjs +0 -184
- package/dist/routers/builds.handlers.mjs.map +0 -1
- package/dist/routers/builds.mjs +0 -185
- package/dist/routers/builds.mjs.map +0 -1
- package/dist/routers/comments.mjs +0 -90
- package/dist/routers/comments.mjs.map +0 -1
- package/dist/routers/health.mjs +0 -137
- package/dist/routers/health.mjs.map +0 -1
- package/dist/routers/helpers.mjs +0 -82
- package/dist/routers/helpers.mjs.map +0 -1
- package/dist/routers/htmx.mjs +0 -20
- package/dist/routers/htmx.mjs.map +0 -1
- package/dist/routers/labels.mjs +0 -110
- package/dist/routers/labels.mjs.map +0 -1
- package/dist/routers/media.mjs +0 -55
- package/dist/routers/media.mjs.map +0 -1
- package/dist/routers/members.mjs +0 -102
- package/dist/routers/members.mjs.map +0 -1
- package/dist/routers/projects.mjs +0 -122
- package/dist/routers/projects.mjs.map +0 -1
- package/dist/routers/schemas.mjs +0 -224
- package/dist/routers/schemas.mjs.map +0 -1
- package/dist/routers/settings-general.mjs +0 -95
- package/dist/routers/settings-general.mjs.map +0 -1
- package/dist/routers/settings-labels.mjs +0 -49
- package/dist/routers/settings-labels.mjs.map +0 -1
- package/dist/routers/settings-members.mjs +0 -30
- package/dist/routers/settings-members.mjs.map +0 -1
- package/dist/routers/settings-status.mjs +0 -73
- package/dist/routers/settings-status.mjs.map +0 -1
- package/dist/routers/settings-tokens.mjs +0 -40
- package/dist/routers/settings-tokens.mjs.map +0 -1
- package/dist/routers/settings-webhooks.mjs +0 -63
- package/dist/routers/settings-webhooks.mjs.map +0 -1
- package/dist/routers/settings.handlers.mjs +0 -93
- package/dist/routers/settings.handlers.mjs.map +0 -1
- package/dist/routers/settings.mjs +0 -23
- package/dist/routers/settings.mjs.map +0 -1
- package/dist/routers/snapshots.mjs +0 -144
- package/dist/routers/snapshots.mjs.map +0 -1
- package/dist/routers/status-configs.mjs +0 -101
- package/dist/routers/status-configs.mjs.map +0 -1
- package/dist/routers/storybook.mjs +0 -120
- package/dist/routers/storybook.mjs.map +0 -1
- package/dist/routers/tokens.mjs +0 -81
- package/dist/routers/tokens.mjs.map +0 -1
- package/dist/routers/ui.mjs +0 -165
- package/dist/routers/ui.mjs.map +0 -1
- package/dist/routers/webhooks.mjs +0 -90
- package/dist/routers/webhooks.mjs.map +0 -1
- package/dist/schema/baseline.mjs +0 -22
- package/dist/schema/baseline.mjs.map +0 -1
- package/dist/schema/build.mjs +0 -29
- package/dist/schema/build.mjs.map +0 -1
- package/dist/schema/comment.mjs +0 -26
- package/dist/schema/comment.mjs.map +0 -1
- package/dist/schema/label.mjs +0 -30
- package/dist/schema/label.mjs.map +0 -1
- package/dist/schema/member.mjs +0 -19
- package/dist/schema/member.mjs.map +0 -1
- package/dist/schema/project.mjs +0 -25
- package/dist/schema/project.mjs.map +0 -1
- package/dist/schema/snapshot.mjs +0 -34
- package/dist/schema/snapshot.mjs.map +0 -1
- package/dist/schema/status-config.mjs +0 -20
- package/dist/schema/status-config.mjs.map +0 -1
- package/dist/schema/token.mjs +0 -19
- package/dist/schema/token.mjs.map +0 -1
- package/dist/schema/user.mjs +0 -19
- package/dist/schema/user.mjs.map +0 -1
- package/dist/schema/webhook.mjs +0 -20
- package/dist/schema/webhook.mjs.map +0 -1
- package/dist/schema.mjs.map +0 -1
- package/dist/store.mjs +0 -20
- package/dist/store.mjs.map +0 -1
- package/dist/ui/document.mjs +0 -348
- package/dist/ui/document.mjs.map +0 -1
- package/dist/ui/feedback.mjs +0 -24
- package/dist/ui/feedback.mjs.map +0 -1
- package/dist/ui/forms.mjs +0 -117
- package/dist/ui/forms.mjs.map +0 -1
- package/dist/ui/styles.mjs +0 -174
- package/dist/ui/styles.mjs.map +0 -1
- package/dist/ui/theme.mjs +0 -44
- package/dist/ui/theme.mjs.map +0 -1
package/dist/schema/webhook.mjs
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import "node:path";
|
|
2
|
-
import "node:url";
|
|
3
|
-
import.meta.url;
|
|
4
|
-
import { projects } from "./project.mjs";
|
|
5
|
-
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
6
|
-
//#region src/schema/webhook.ts
|
|
7
|
-
/** Narrow `webhooks` table definition. */
|
|
8
|
-
const webhooks = sqliteTable("webhooks", {
|
|
9
|
-
id: text("id").primaryKey(),
|
|
10
|
-
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
11
|
-
url: text("url").notNull(),
|
|
12
|
-
secretEncrypted: text("secret_encrypted").notNull(),
|
|
13
|
-
events: text("events"),
|
|
14
|
-
createdAt: text("created_at").notNull(),
|
|
15
|
-
updatedAt: text("updated_at").notNull()
|
|
16
|
-
});
|
|
17
|
-
//#endregion
|
|
18
|
-
export { webhooks };
|
|
19
|
-
|
|
20
|
-
//# sourceMappingURL=webhook.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.mjs","names":[],"sources":["../../src/schema/webhook.ts"],"sourcesContent":["import { sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { projects } from \"./project.ts\";\n\n/** Narrow `webhooks` table definition. */\nexport const webhooks = sqliteTable(\"webhooks\", {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n url: text(\"url\").notNull(),\n secretEncrypted: text(\"secret_encrypted\").notNull(),\n events: text(\"events\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** A webhook subscription row. */\nexport interface Webhook {\n id: string;\n projectId: string;\n url: string;\n secretEncrypted: string;\n events: string | null;\n createdAt: string;\n updatedAt: string;\n}\n"],"mappings":";;;;;;;AAIA,MAAa,WAAW,YAAY,YAAY;CAC9C,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,KAAK,KAAK,KAAK,CAAC,CAAC,QAAQ;CACzB,iBAAiB,KAAK,kBAAkB,CAAC,CAAC,QAAQ;CAClD,QAAQ,KAAK,QAAQ;CACrB,WAAW,KAAK,YAAY,CAAC,CAAC,QAAQ;CACtC,WAAW,KAAK,YAAY,CAAC,CAAC,QAAQ;AACxC,CAAC"}
|
package/dist/schema.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","names":["projectsTable","projectStatusConfigsTable","buildsTable","snapshotsTable","baselinesTable","commentsTable","labelTypesTable","buildLabelsTable","tokensTable","webhooksTable","usersTable","projectMembersTable"],"sources":["../src/schema/index.ts"],"sourcesContent":["/**\n * Database schema: table handles, row types, and the schema object passed\n * to the database client.\n */\nimport type { AnySQLiteTable } from \"drizzle-orm/sqlite-core\";\n\nimport { baselines as baselinesTable } from \"./baseline.ts\";\nimport { buildLabels as buildLabelsTable, labelTypes as labelTypesTable } from \"./label.ts\";\nimport { builds as buildsTable } from \"./build.ts\";\nimport { comments as commentsTable } from \"./comment.ts\";\nimport { projectMembers as projectMembersTable } from \"./member.ts\";\nimport { projects as projectsTable } from \"./project.ts\";\nimport { projectStatusConfigs as projectStatusConfigsTable } from \"./status-config.ts\";\nimport { snapshots as snapshotsTable } from \"./snapshot.ts\";\nimport { tokens as tokensTable } from \"./token.ts\";\nimport { users as usersTable } from \"./user.ts\";\nimport { webhooks as webhooksTable } from \"./webhook.ts\";\n\n/**\n * Database schema: table handles, row types, and the schema object passed\n * to the database client.\n *\n * Table handles are explicitly typed (JSR fast-check); exact column types\n * live on the narrow per-entity definitions, and the row interfaces are\n * pinned to them by `schema-types.test.ts`.\n */\nexport type { Baseline } from \"./baseline.ts\";\nexport type { Build } from \"./build.ts\";\nexport type { Comment } from \"./comment.ts\";\nexport type { BuildLabel, LabelType } from \"./label.ts\";\nexport type { ProjectMember } from \"./member.ts\";\nexport type { Project, StorybookMeta } from \"./project.ts\";\nexport type { ProjectStatusConfig } from \"./status-config.ts\";\nexport type { Snapshot } from \"./snapshot.ts\";\nexport type { Token } from \"./token.ts\";\nexport type { User } from \"./user.ts\";\nexport type { Webhook } from \"./webhook.ts\";\n\n/** Projects table (one row per Storybook project). */\nexport const projects: AnySQLiteTable = projectsTable;\n/** Project status-configs table (merge-gate configurations). */\nexport const projectStatusConfigs: AnySQLiteTable = projectStatusConfigsTable;\n/** Builds table (one row per uploaded Storybook build). */\nexport const builds: AnySQLiteTable = buildsTable;\n/** Snapshots table (one row per captured story screenshot). */\nexport const snapshots: AnySQLiteTable = snapshotsTable;\n/** Baselines table (accepted reference snapshots per branch). */\nexport const baselines: AnySQLiteTable = baselinesTable;\n/** Comments table (review comments on snapshots). */\nexport const comments: AnySQLiteTable = commentsTable;\n/** Label-types table (project-defined build label vocabularies). */\nexport const labelTypes: AnySQLiteTable = labelTypesTable;\n/** Build-labels table (labels attached to builds). */\nexport const buildLabels: AnySQLiteTable = buildLabelsTable;\n/** Tokens table (CI token hashes per project). */\nexport const tokens: AnySQLiteTable = tokensTable;\n/** Webhooks table (outgoing build-event subscriptions). */\nexport const webhooks: AnySQLiteTable = webhooksTable;\n/** Users table (dashboard members). */\nexport const users: AnySQLiteTable = usersTable;\n/** Project-members table (per-project memberships and roles). */\nexport const projectMembers: AnySQLiteTable = projectMembersTable;\n\n/** Full Drizzle schema object passed to the database client. */\nexport const schema = {\n projects,\n projectStatusConfigs,\n builds,\n snapshots,\n baselines,\n comments,\n labelTypes,\n buildLabels,\n tokens,\n webhooks,\n users,\n projectMembers,\n};\n\n/** The full database schema type. */\nexport type Schema = typeof schema;\n"],"mappings":";;;;;;;;;;;;;;;;AAuCA,MAAa,WAA2BA;;AAExC,MAAa,uBAAuCC;;AAEpD,MAAa,SAAyBC;;AAEtC,MAAa,YAA4BC;;AAEzC,MAAa,YAA4BC;;AAEzC,MAAa,WAA2BC;;AAExC,MAAa,aAA6BC;;AAE1C,MAAa,cAA8BC;;AAE3C,MAAa,SAAyBC;;AAEtC,MAAa,WAA2BC;;AAExC,MAAa,QAAwBC;;AAErC,MAAa,iBAAiCC;;AAG9C,MAAa,SAAS;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
package/dist/store.mjs
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import "node:path";
|
|
2
|
-
import "node:url";
|
|
3
|
-
import.meta.url;
|
|
4
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
-
//#region src/store.ts
|
|
6
|
-
const storage = new AsyncLocalStorage();
|
|
7
|
-
/** Run a function with the given request store in scope. */
|
|
8
|
-
function runWithStore(store, fn) {
|
|
9
|
-
return storage.run(store, fn);
|
|
10
|
-
}
|
|
11
|
-
/** Return the current request store, throwing outside a request scope. */
|
|
12
|
-
function getStore() {
|
|
13
|
-
const store = storage.getStore();
|
|
14
|
-
if (!store) throw new Error("Store not available. Use runWithStore().");
|
|
15
|
-
return store;
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
export { getStore, runWithStore };
|
|
19
|
-
|
|
20
|
-
//# sourceMappingURL=store.mjs.map
|
package/dist/store.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.mjs","names":[],"sources":["../src/store.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Logger } from \"pino\";\nimport type { AuthUser } from \"./adapters/auth.ts\";\nimport type { CaptureQueue } from \"./adapters/capture-queue.ts\";\nimport type { DatabaseAdapter } from \"./adapters/database.ts\";\nimport type { GitHostProvider } from \"./adapters/git-host/index.ts\";\nimport type { StorageAdapter } from \"./adapters/storage.ts\";\nimport type { ShelfConfig, UIConfig } from \"./config.ts\";\n\n/** Request-scoped dependencies and session state. */\nexport interface Store {\n db: DatabaseAdapter;\n storage: StorageAdapter;\n config: ShelfConfig;\n ui: UIConfig;\n logger: Logger;\n user: AuthUser | null;\n authEnabled: boolean;\n enqueueCapture?: (buildId: string, reqId?: string) => Promise<void>;\n captureQueue?: CaptureQueue | null;\n gitHosts: GitHostProvider[];\n}\n\nconst storage = new AsyncLocalStorage<Store>();\n\n/** Run a function with the given request store in scope. */\nexport function runWithStore<T>(store: Store, fn: () => T): T {\n return storage.run(store, fn);\n}\n\n/** Return the current request store, throwing outside a request scope. */\nexport function getStore(): Store {\n const store = storage.getStore();\n if (!store) {\n throw new Error(\"Store not available. Use runWithStore().\");\n }\n return store;\n}\n"],"mappings":";;;;;AAuBA,MAAM,UAAU,IAAI,kBAAyB;;AAG7C,SAAgB,aAAgB,OAAc,IAAgB;CAC5D,OAAO,QAAQ,IAAI,OAAO,EAAE;AAC9B;;AAGA,SAAgB,WAAkB;CAChC,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,0CAA0C;CAE5D,OAAO;AACT"}
|
package/dist/ui/document.mjs
DELETED
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
import "node:path";
|
|
2
|
-
import "node:url";
|
|
3
|
-
import.meta.url;
|
|
4
|
-
import { getStore } from "../store.mjs";
|
|
5
|
-
import { baseStyle } from "./styles.mjs";
|
|
6
|
-
import { DARK_THEME, LIGHT_THEME } from "./theme.mjs";
|
|
7
|
-
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
8
|
-
//#region src/ui/document.tsx
|
|
9
|
-
/** Full HTML document shell with top bar, sidebar, theme, and HTMX. */
|
|
10
|
-
const DocumentLayout = ({ title, nav, children }) => {
|
|
11
|
-
const { ui } = getStore();
|
|
12
|
-
const name = ui.name ?? "StoryShelf";
|
|
13
|
-
const light = ui.lightTheme ?? LIGHT_THEME;
|
|
14
|
-
const dark = ui.darkTheme ?? DARK_THEME;
|
|
15
|
-
return /* @__PURE__ */ jsxs("html", {
|
|
16
|
-
lang: "en",
|
|
17
|
-
"data-theme": "system",
|
|
18
|
-
children: [/* @__PURE__ */ jsxs("head", { children: [
|
|
19
|
-
/* @__PURE__ */ jsx("meta", { charset: "utf-8" }),
|
|
20
|
-
/* @__PURE__ */ jsx("meta", {
|
|
21
|
-
name: "viewport",
|
|
22
|
-
content: "width=device-width, initial-scale=1"
|
|
23
|
-
}),
|
|
24
|
-
/* @__PURE__ */ jsx("meta", {
|
|
25
|
-
name: "color-scheme",
|
|
26
|
-
content: "light dark"
|
|
27
|
-
}),
|
|
28
|
-
ui.favicon ? /* @__PURE__ */ jsx("link", {
|
|
29
|
-
rel: "icon",
|
|
30
|
-
href: ui.favicon
|
|
31
|
-
}) : null,
|
|
32
|
-
/* @__PURE__ */ jsxs("title", { children: [
|
|
33
|
-
title,
|
|
34
|
-
" · ",
|
|
35
|
-
name
|
|
36
|
-
] }),
|
|
37
|
-
/* @__PURE__ */ jsx("style", { children: baseStyle(light, dark) }),
|
|
38
|
-
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: themeScript() } })
|
|
39
|
-
] }), /* @__PURE__ */ jsxs("body", { children: [
|
|
40
|
-
/* @__PURE__ */ jsx("a", {
|
|
41
|
-
class: "skip-link",
|
|
42
|
-
href: "#main-content",
|
|
43
|
-
children: "Skip to content"
|
|
44
|
-
}),
|
|
45
|
-
/* @__PURE__ */ jsx(TopBar, {
|
|
46
|
-
name,
|
|
47
|
-
logo: ui.logo,
|
|
48
|
-
nav
|
|
49
|
-
}),
|
|
50
|
-
/* @__PURE__ */ jsxs("div", {
|
|
51
|
-
class: "shell",
|
|
52
|
-
children: [/* @__PURE__ */ jsx(Sidebar, { nav }), /* @__PURE__ */ jsx("main", {
|
|
53
|
-
id: "main-content",
|
|
54
|
-
class: "content",
|
|
55
|
-
tabindex: -1,
|
|
56
|
-
children
|
|
57
|
-
})]
|
|
58
|
-
}),
|
|
59
|
-
/* @__PURE__ */ jsx("script", { src: "/assets/htmx.js" }),
|
|
60
|
-
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: clientScript() } })
|
|
61
|
-
] })]
|
|
62
|
-
});
|
|
63
|
-
};
|
|
64
|
-
const TopBar = ({ name, logo, nav }) => {
|
|
65
|
-
return /* @__PURE__ */ jsx("header", {
|
|
66
|
-
class: "topbar",
|
|
67
|
-
role: "banner",
|
|
68
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
69
|
-
class: "topbar__inner",
|
|
70
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
71
|
-
class: "topbar__left",
|
|
72
|
-
children: [
|
|
73
|
-
/* @__PURE__ */ jsx("button", {
|
|
74
|
-
class: "topbar__menu",
|
|
75
|
-
type: "button",
|
|
76
|
-
"aria-label": "Toggle navigation",
|
|
77
|
-
"aria-expanded": "false",
|
|
78
|
-
"aria-controls": "sidebar",
|
|
79
|
-
"data-sidebar-toggle": true,
|
|
80
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
81
|
-
"aria-hidden": "true",
|
|
82
|
-
children: "☰"
|
|
83
|
-
})
|
|
84
|
-
}),
|
|
85
|
-
/* @__PURE__ */ jsxs("a", {
|
|
86
|
-
class: "brand",
|
|
87
|
-
href: "/",
|
|
88
|
-
children: [logo ? /* @__PURE__ */ jsx("img", {
|
|
89
|
-
class: "logo",
|
|
90
|
-
src: logo,
|
|
91
|
-
alt: name,
|
|
92
|
-
width: "28",
|
|
93
|
-
height: "28"
|
|
94
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
95
|
-
class: "brand__mark",
|
|
96
|
-
"aria-hidden": "true",
|
|
97
|
-
children: "◆"
|
|
98
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
99
|
-
class: "brand__name",
|
|
100
|
-
children: name
|
|
101
|
-
})]
|
|
102
|
-
}),
|
|
103
|
-
nav?.projectSlug ? /* @__PURE__ */ jsxs("nav", {
|
|
104
|
-
class: "project-crumb",
|
|
105
|
-
"aria-label": "Project",
|
|
106
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
107
|
-
class: "project-crumb__sep",
|
|
108
|
-
"aria-hidden": "true",
|
|
109
|
-
children: "/"
|
|
110
|
-
}), /* @__PURE__ */ jsx("a", {
|
|
111
|
-
href: `/projects/${nav.projectSlug}/builds`,
|
|
112
|
-
children: nav.projectName ?? nav.projectSlug
|
|
113
|
-
})]
|
|
114
|
-
}) : null
|
|
115
|
-
]
|
|
116
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
117
|
-
class: "topbar__right",
|
|
118
|
-
children: [/* @__PURE__ */ jsx(ThemeToggle, {}), /* @__PURE__ */ jsx(AuthMenu, {})]
|
|
119
|
-
})]
|
|
120
|
-
})
|
|
121
|
-
});
|
|
122
|
-
};
|
|
123
|
-
const ThemeToggle = () => {
|
|
124
|
-
return /* @__PURE__ */ jsxs("button", {
|
|
125
|
-
class: "topbar__theme",
|
|
126
|
-
type: "button",
|
|
127
|
-
"aria-label": "Toggle theme",
|
|
128
|
-
"data-theme-toggle": true,
|
|
129
|
-
children: [
|
|
130
|
-
/* @__PURE__ */ jsx("span", {
|
|
131
|
-
"data-theme-icon": "light",
|
|
132
|
-
"aria-hidden": "true",
|
|
133
|
-
children: "☀"
|
|
134
|
-
}),
|
|
135
|
-
/* @__PURE__ */ jsx("span", {
|
|
136
|
-
"data-theme-icon": "dark",
|
|
137
|
-
"aria-hidden": "true",
|
|
138
|
-
children: "☾"
|
|
139
|
-
}),
|
|
140
|
-
/* @__PURE__ */ jsx("span", {
|
|
141
|
-
"data-theme-icon": "system",
|
|
142
|
-
"aria-hidden": "true",
|
|
143
|
-
children: "◐"
|
|
144
|
-
})
|
|
145
|
-
]
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
const AuthMenu = () => {
|
|
149
|
-
const { user, authEnabled } = getStore();
|
|
150
|
-
if (!authEnabled) return null;
|
|
151
|
-
if (!user) return /* @__PURE__ */ jsx("a", {
|
|
152
|
-
class: "topbar__login",
|
|
153
|
-
href: "/auth/login",
|
|
154
|
-
children: "Sign in"
|
|
155
|
-
});
|
|
156
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
157
|
-
class: "user-menu",
|
|
158
|
-
children: [
|
|
159
|
-
user.avatarUrl ? /* @__PURE__ */ jsx("img", {
|
|
160
|
-
class: "user-menu__avatar",
|
|
161
|
-
src: user.avatarUrl,
|
|
162
|
-
alt: "",
|
|
163
|
-
width: "28",
|
|
164
|
-
height: "28"
|
|
165
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
166
|
-
class: "user-menu__avatar user-menu__avatar--fallback",
|
|
167
|
-
"aria-hidden": "true",
|
|
168
|
-
children: user.name.slice(0, 1).toUpperCase()
|
|
169
|
-
}),
|
|
170
|
-
/* @__PURE__ */ jsx("span", {
|
|
171
|
-
class: "user-menu__name",
|
|
172
|
-
children: user.name
|
|
173
|
-
}),
|
|
174
|
-
/* @__PURE__ */ jsx("span", {
|
|
175
|
-
class: `user-menu__role user-menu__role--${user.role}`,
|
|
176
|
-
children: user.role
|
|
177
|
-
}),
|
|
178
|
-
/* @__PURE__ */ jsx("form", {
|
|
179
|
-
method: "post",
|
|
180
|
-
action: "/auth/logout",
|
|
181
|
-
children: /* @__PURE__ */ jsx("button", {
|
|
182
|
-
class: "user-menu__logout",
|
|
183
|
-
type: "submit",
|
|
184
|
-
children: "Sign out"
|
|
185
|
-
})
|
|
186
|
-
})
|
|
187
|
-
]
|
|
188
|
-
});
|
|
189
|
-
};
|
|
190
|
-
const Sidebar = ({ nav }) => {
|
|
191
|
-
return /* @__PURE__ */ jsx("aside", {
|
|
192
|
-
id: "sidebar",
|
|
193
|
-
class: "sidebar",
|
|
194
|
-
"aria-label": "Primary",
|
|
195
|
-
children: /* @__PURE__ */ jsxs("nav", {
|
|
196
|
-
class: "sidebar__nav",
|
|
197
|
-
children: [
|
|
198
|
-
/* @__PURE__ */ jsxs("a", {
|
|
199
|
-
class: `sidebar__link ${nav?.active === "projects" ? "sidebar__link--active" : ""}`,
|
|
200
|
-
href: "/projects",
|
|
201
|
-
"aria-current": nav?.active === "projects" ? "page" : void 0,
|
|
202
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
203
|
-
"aria-hidden": "true",
|
|
204
|
-
children: "▦"
|
|
205
|
-
}), " Projects"]
|
|
206
|
-
}),
|
|
207
|
-
nav?.projectSlug ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
208
|
-
/* @__PURE__ */ jsx("div", {
|
|
209
|
-
class: "sidebar__section",
|
|
210
|
-
children: "Project"
|
|
211
|
-
}),
|
|
212
|
-
/* @__PURE__ */ jsxs("a", {
|
|
213
|
-
class: `sidebar__link ${nav.active === "builds" ? "sidebar__link--active" : ""}`,
|
|
214
|
-
href: `/projects/${nav.projectSlug}/builds`,
|
|
215
|
-
"aria-current": nav.active === "builds" ? "page" : void 0,
|
|
216
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
217
|
-
"aria-hidden": "true",
|
|
218
|
-
children: "◧"
|
|
219
|
-
}), " Builds"]
|
|
220
|
-
}),
|
|
221
|
-
/* @__PURE__ */ jsxs("a", {
|
|
222
|
-
class: `sidebar__link ${nav.active === "jobs" ? "sidebar__link--active" : ""}`,
|
|
223
|
-
href: `/projects/${nav.projectSlug}/jobs`,
|
|
224
|
-
"aria-current": nav.active === "jobs" ? "page" : void 0,
|
|
225
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
226
|
-
"aria-hidden": "true",
|
|
227
|
-
children: "◫"
|
|
228
|
-
}), " Jobs"]
|
|
229
|
-
}),
|
|
230
|
-
/* @__PURE__ */ jsxs("a", {
|
|
231
|
-
class: `sidebar__link ${nav.active === "labels" ? "sidebar__link--active" : ""}`,
|
|
232
|
-
href: `/projects/${nav.projectSlug}/labels`,
|
|
233
|
-
"aria-current": nav.active === "labels" ? "page" : void 0,
|
|
234
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
235
|
-
"aria-hidden": "true",
|
|
236
|
-
children: "⌗"
|
|
237
|
-
}), " Labels"]
|
|
238
|
-
}),
|
|
239
|
-
/* @__PURE__ */ jsxs("a", {
|
|
240
|
-
class: `sidebar__link ${nav.active === "settings" ? "sidebar__link--active" : ""}`,
|
|
241
|
-
href: `/projects/${nav.projectSlug}/settings`,
|
|
242
|
-
"aria-current": nav.active === "settings" ? "page" : void 0,
|
|
243
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
244
|
-
"aria-hidden": "true",
|
|
245
|
-
children: "⚙"
|
|
246
|
-
}), " Settings"]
|
|
247
|
-
})
|
|
248
|
-
] }) : null,
|
|
249
|
-
/* @__PURE__ */ jsx("div", {
|
|
250
|
-
class: "sidebar__section",
|
|
251
|
-
children: "Resources"
|
|
252
|
-
}),
|
|
253
|
-
/* @__PURE__ */ jsxs("a", {
|
|
254
|
-
class: "sidebar__link",
|
|
255
|
-
href: "/api/v1/projects",
|
|
256
|
-
"aria-label": "API (JSON)",
|
|
257
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
258
|
-
"aria-hidden": "true",
|
|
259
|
-
children: "{} "
|
|
260
|
-
}), " API"]
|
|
261
|
-
})
|
|
262
|
-
]
|
|
263
|
-
})
|
|
264
|
-
});
|
|
265
|
-
};
|
|
266
|
-
function themeScript() {
|
|
267
|
-
return `
|
|
268
|
-
(function(){
|
|
269
|
-
var cookieName='storyshelf_theme';
|
|
270
|
-
function readCookie(n){
|
|
271
|
-
var m=document.cookie.match(new RegExp('(?:^|; )'+n.replace(/([.$?*|{}\\[\\]\\\\/\\+^])/gu,'\\\\$1')+'=([^;]*)'));
|
|
272
|
-
return m?decodeURIComponent(m[1]):null;
|
|
273
|
-
}
|
|
274
|
-
function writeCookie(n,v){
|
|
275
|
-
document.cookie=n+'='+encodeURIComponent(v)+'; Path=/; Max-Age=31536000; SameSite=Lax';
|
|
276
|
-
}
|
|
277
|
-
function applyTheme(v){
|
|
278
|
-
var html=document.documentElement;
|
|
279
|
-
if(v==='light'||v==='dark'||v==='system'){ html.setAttribute('data-theme',v); }
|
|
280
|
-
else { html.setAttribute('data-theme','system'); }
|
|
281
|
-
}
|
|
282
|
-
var initial=readCookie(cookieName);
|
|
283
|
-
if(initial){ applyTheme(initial); }
|
|
284
|
-
window.__storyshelfTheme={readCookie:readCookie,writeCookie:writeCookie,applyTheme:applyTheme,cookieName:cookieName};
|
|
285
|
-
})();
|
|
286
|
-
`.trim();
|
|
287
|
-
}
|
|
288
|
-
function clientScript() {
|
|
289
|
-
return `
|
|
290
|
-
(function(){
|
|
291
|
-
var theme=window.__storyshelfTheme;
|
|
292
|
-
var toggle=document.querySelector('[data-theme-toggle]');
|
|
293
|
-
if(toggle&&theme){
|
|
294
|
-
toggle.addEventListener('click',function(){
|
|
295
|
-
var cur=document.documentElement.getAttribute('data-theme')||'system';
|
|
296
|
-
var next=cur==='system'?'light':cur==='light'?'dark':'system';
|
|
297
|
-
theme.applyTheme(next);
|
|
298
|
-
theme.writeCookie(theme.cookieName,next);
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
var menuBtn=document.querySelector('[data-sidebar-toggle]');
|
|
302
|
-
var sidebar=document.getElementById('sidebar');
|
|
303
|
-
if(menuBtn&&sidebar){
|
|
304
|
-
menuBtn.addEventListener('click',function(){
|
|
305
|
-
var open=sidebar.classList.toggle('sidebar--open');
|
|
306
|
-
menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
document.addEventListener('keydown',function(e){
|
|
310
|
-
if(e.key==='Escape'&&sidebar&&sidebar.classList.contains('sidebar--open')){
|
|
311
|
-
sidebar.classList.remove('sidebar--open');
|
|
312
|
-
if(menuBtn) menuBtn.setAttribute('aria-expanded','false');
|
|
313
|
-
menuBtn && menuBtn.focus();
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
// HTMX after swap focus management
|
|
317
|
-
document.body.addEventListener('htmx:afterSwap',function(e){
|
|
318
|
-
var target=e.detail && e.detail.target;
|
|
319
|
-
if(target&&target.querySelector){
|
|
320
|
-
var focusable=target.querySelector('[autofocus], input, select, textarea, button');
|
|
321
|
-
if(focusable) try{ focusable.focus(); }catch(_){}
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
// Diff keyboard shortcuts
|
|
325
|
-
document.addEventListener('keydown',function(e){
|
|
326
|
-
if(e.target instanceof HTMLElement && (e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA'||e.target.isContentEditable)) return;
|
|
327
|
-
var diffRoot=document.querySelector('[data-diff-nav]');
|
|
328
|
-
if(!diffRoot) return;
|
|
329
|
-
if(e.key==='ArrowLeft' || e.key==='ArrowRight'){
|
|
330
|
-
var links=Array.from(diffRoot.querySelectorAll('[data-snapshot-link]'));
|
|
331
|
-
if(links.length===0) return;
|
|
332
|
-
var active=document.activeElement;
|
|
333
|
-
var idx=links.indexOf(active);
|
|
334
|
-
if(idx===-1){
|
|
335
|
-
var current=diffRoot.getAttribute('data-current');
|
|
336
|
-
idx=links.findIndex(function(a){ return a.getAttribute('data-snapshot-id')===current; });
|
|
337
|
-
}
|
|
338
|
-
var nextIdx=e.key==='ArrowRight' ? Math.min(links.length-1, idx+1) : Math.max(0, idx-1);
|
|
339
|
-
if(links[nextIdx]){ e.preventDefault(); links[nextIdx].focus(); links[nextIdx].click(); }
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
})();
|
|
343
|
-
`.trim();
|
|
344
|
-
}
|
|
345
|
-
//#endregion
|
|
346
|
-
export { DocumentLayout };
|
|
347
|
-
|
|
348
|
-
//# sourceMappingURL=document.mjs.map
|
package/dist/ui/document.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"document.mjs","names":[],"sources":["../../src/ui/document.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\nimport { getStore } from \"../store.ts\";\nimport { baseStyle } from \"./styles.ts\";\nimport { DARK_THEME, LIGHT_THEME } from \"./theme.ts\";\n\n/** Rendered HTML content returned by page components. */\nexport type RenderedContent = string | Promise<string>;\n\ninterface NavConfig {\n active?: string;\n projectSlug?: string;\n projectName?: string;\n}\n\n// Hono's JSX.Element is typed as `HtmlEscapedString | Promise<...>`, so JSX-returning\n// Functions can legitimately return a promise; the rule is a false positive here.\n/** Full HTML document shell with top bar, sidebar, theme, and HTMX. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const DocumentLayout: FC<{ title: string; nav?: NavConfig; children?: unknown }> = ({\n title,\n nav,\n children,\n}) => {\n const { ui } = getStore();\n const name = ui.name ?? \"StoryShelf\";\n const light = ui.lightTheme ?? LIGHT_THEME;\n const dark = ui.darkTheme ?? DARK_THEME;\n\n return (\n <html lang=\"en\" data-theme=\"system\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"color-scheme\" content=\"light dark\" />\n {ui.favicon ? <link rel=\"icon\" href={ui.favicon} /> : null}\n <title>\n {title} · {name}\n </title>\n <style>{baseStyle(light, dark)}</style>\n <script dangerouslySetInnerHTML={{ __html: themeScript() }} />\n </head>\n <body>\n <a class=\"skip-link\" href=\"#main-content\">\n Skip to content\n </a>\n <TopBar name={name} logo={ui.logo} nav={nav} />\n <div class=\"shell\">\n <Sidebar nav={nav} />\n <main id=\"main-content\" class=\"content\" tabindex={-1}>\n {children}\n </main>\n </div>\n <script src=\"/assets/htmx.js\" />\n <script dangerouslySetInnerHTML={{ __html: clientScript() }} />\n </body>\n </html>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst TopBar: FC<{ name: string; logo?: string; nav?: NavConfig }> = ({ name, logo, nav }) => {\n return (\n <header class=\"topbar\" role=\"banner\">\n <div class=\"topbar__inner\">\n <div class=\"topbar__left\">\n <button\n class=\"topbar__menu\"\n type=\"button\"\n aria-label=\"Toggle navigation\"\n aria-expanded=\"false\"\n aria-controls=\"sidebar\"\n data-sidebar-toggle\n >\n <span aria-hidden=\"true\">☰</span>\n </button>\n <a class=\"brand\" href=\"/\">\n {logo ? (\n <img class=\"logo\" src={logo} alt={name} width=\"28\" height=\"28\" />\n ) : (\n <span class=\"brand__mark\" aria-hidden=\"true\">\n ◆\n </span>\n )}\n <span class=\"brand__name\">{name}</span>\n </a>\n {nav?.projectSlug ? (\n <nav class=\"project-crumb\" aria-label=\"Project\">\n <span class=\"project-crumb__sep\" aria-hidden=\"true\">\n /\n </span>\n <a href={`/projects/${nav.projectSlug}/builds`}>\n {nav.projectName ?? nav.projectSlug}\n </a>\n </nav>\n ) : null}\n </div>\n <div class=\"topbar__right\">\n <ThemeToggle />\n <AuthMenu />\n </div>\n </div>\n </header>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst ThemeToggle: FC = () => {\n return (\n <button class=\"topbar__theme\" type=\"button\" aria-label=\"Toggle theme\" data-theme-toggle>\n <span data-theme-icon=\"light\" aria-hidden=\"true\">\n ☀\n </span>\n <span data-theme-icon=\"dark\" aria-hidden=\"true\">\n ☾\n </span>\n <span data-theme-icon=\"system\" aria-hidden=\"true\">\n ◐\n </span>\n </button>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst AuthMenu: FC = () => {\n const { user, authEnabled } = getStore();\n if (!authEnabled) {\n return null;\n }\n if (!user) {\n return (\n <a class=\"topbar__login\" href=\"/auth/login\">\n Sign in\n </a>\n );\n }\n return (\n <div class=\"user-menu\">\n {user.avatarUrl ? (\n <img class=\"user-menu__avatar\" src={user.avatarUrl} alt=\"\" width=\"28\" height=\"28\" />\n ) : (\n <span class=\"user-menu__avatar user-menu__avatar--fallback\" aria-hidden=\"true\">\n {user.name.slice(0, 1).toUpperCase()}\n </span>\n )}\n <span class=\"user-menu__name\">{user.name}</span>\n <span class={`user-menu__role user-menu__role--${user.role}`}>{user.role}</span>\n <form method=\"post\" action=\"/auth/logout\">\n <button class=\"user-menu__logout\" type=\"submit\">\n Sign out\n </button>\n </form>\n </div>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst Sidebar: FC<{ nav?: NavConfig }> = ({ nav }) => {\n return (\n <aside id=\"sidebar\" class=\"sidebar\" aria-label=\"Primary\">\n <nav class=\"sidebar__nav\">\n <a\n class={`sidebar__link ${nav?.active === \"projects\" ? \"sidebar__link--active\" : \"\"}`}\n href=\"/projects\"\n aria-current={nav?.active === \"projects\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">▦</span> Projects\n </a>\n {nav?.projectSlug ? (\n <>\n <div class=\"sidebar__section\">Project</div>\n <a\n class={`sidebar__link ${nav.active === \"builds\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/builds`}\n aria-current={nav.active === \"builds\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">◧</span> Builds\n </a>\n <a\n class={`sidebar__link ${nav.active === \"jobs\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/jobs`}\n aria-current={nav.active === \"jobs\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">◫</span> Jobs\n </a>\n <a\n class={`sidebar__link ${nav.active === \"labels\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/labels`}\n aria-current={nav.active === \"labels\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">⌗</span> Labels\n </a>\n <a\n class={`sidebar__link ${nav.active === \"settings\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/settings`}\n aria-current={nav.active === \"settings\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">⚙</span> Settings\n </a>\n </>\n ) : null}\n <div class=\"sidebar__section\">Resources</div>\n <a class=\"sidebar__link\" href=\"/api/v1/projects\" aria-label=\"API (JSON)\">\n <span aria-hidden=\"true\">{\"{} \"}</span> API\n </a>\n </nav>\n </aside>\n );\n};\n\nfunction themeScript(): string {\n return `\n (function(){\n var cookieName='storyshelf_theme';\n function readCookie(n){\n var m=document.cookie.match(new RegExp('(?:^|; )'+n.replace(/([.$?*|{}\\\\[\\\\]\\\\\\\\/\\\\+^])/gu,'\\\\\\\\$1')+'=([^;]*)'));\n return m?decodeURIComponent(m[1]):null;\n }\n function writeCookie(n,v){\n document.cookie=n+'='+encodeURIComponent(v)+'; Path=/; Max-Age=31536000; SameSite=Lax';\n }\n function applyTheme(v){\n var html=document.documentElement;\n if(v==='light'||v==='dark'||v==='system'){ html.setAttribute('data-theme',v); }\n else { html.setAttribute('data-theme','system'); }\n }\n var initial=readCookie(cookieName);\n if(initial){ applyTheme(initial); }\n window.__storyshelfTheme={readCookie:readCookie,writeCookie:writeCookie,applyTheme:applyTheme,cookieName:cookieName};\n })();\n `.trim();\n}\n\nfunction clientScript(): string {\n return `\n (function(){\n var theme=window.__storyshelfTheme;\n var toggle=document.querySelector('[data-theme-toggle]');\n if(toggle&&theme){\n toggle.addEventListener('click',function(){\n var cur=document.documentElement.getAttribute('data-theme')||'system';\n var next=cur==='system'?'light':cur==='light'?'dark':'system';\n theme.applyTheme(next);\n theme.writeCookie(theme.cookieName,next);\n });\n }\n var menuBtn=document.querySelector('[data-sidebar-toggle]');\n var sidebar=document.getElementById('sidebar');\n if(menuBtn&&sidebar){\n menuBtn.addEventListener('click',function(){\n var open=sidebar.classList.toggle('sidebar--open');\n menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false');\n });\n }\n document.addEventListener('keydown',function(e){\n if(e.key==='Escape'&&sidebar&&sidebar.classList.contains('sidebar--open')){\n sidebar.classList.remove('sidebar--open');\n if(menuBtn) menuBtn.setAttribute('aria-expanded','false');\n menuBtn && menuBtn.focus();\n }\n });\n // HTMX after swap focus management\n document.body.addEventListener('htmx:afterSwap',function(e){\n var target=e.detail && e.detail.target;\n if(target&&target.querySelector){\n var focusable=target.querySelector('[autofocus], input, select, textarea, button');\n if(focusable) try{ focusable.focus(); }catch(_){}\n }\n });\n // Diff keyboard shortcuts\n document.addEventListener('keydown',function(e){\n if(e.target instanceof HTMLElement && (e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA'||e.target.isContentEditable)) return;\n var diffRoot=document.querySelector('[data-diff-nav]');\n if(!diffRoot) return;\n if(e.key==='ArrowLeft' || e.key==='ArrowRight'){\n var links=Array.from(diffRoot.querySelectorAll('[data-snapshot-link]'));\n if(links.length===0) return;\n var active=document.activeElement;\n var idx=links.indexOf(active);\n if(idx===-1){\n var current=diffRoot.getAttribute('data-current');\n idx=links.findIndex(function(a){ return a.getAttribute('data-snapshot-id')===current; });\n }\n var nextIdx=e.key==='ArrowRight' ? Math.min(links.length-1, idx+1) : Math.max(0, idx-1);\n if(links[nextIdx]){ e.preventDefault(); links[nextIdx].focus(); links[nextIdx].click(); }\n }\n });\n })();\n `.trim();\n}\n"],"mappings":"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"}
|
package/dist/ui/feedback.mjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import "node:path";
|
|
2
|
-
import "node:url";
|
|
3
|
-
import.meta.url;
|
|
4
|
-
import { jsx } from "hono/jsx/jsx-runtime";
|
|
5
|
-
//#region src/ui/feedback.tsx
|
|
6
|
-
/** Small status pill with a color tone. */
|
|
7
|
-
const Badge = ({ tone = "neutral", children }) => {
|
|
8
|
-
return /* @__PURE__ */ jsx("span", {
|
|
9
|
-
class: `badge badge--${tone}`,
|
|
10
|
-
children
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
|
-
/** Map a build or snapshot status string to its badge tone. */
|
|
14
|
-
function statusTone(status) {
|
|
15
|
-
if (status === "approved" || status === "unchanged") return "success";
|
|
16
|
-
if (status === "rejected" || status === "failed") return "danger";
|
|
17
|
-
if (status === "changed" || status === "new" || status === "reviewing") return "warning";
|
|
18
|
-
if (status === "capturing" || status === "comparing" || status === "pending") return "info";
|
|
19
|
-
return "neutral";
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
|
-
export { Badge, statusTone };
|
|
23
|
-
|
|
24
|
-
//# sourceMappingURL=feedback.mjs.map
|
package/dist/ui/feedback.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.mjs","names":[],"sources":["../../src/ui/feedback.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype BadgeTone = \"neutral\" | \"success\" | \"warning\" | \"danger\" | \"info\";\n\n/** Small status pill with a color tone. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Badge: FC<{ tone?: BadgeTone; children?: unknown }> = ({\n tone = \"neutral\",\n children,\n}) => {\n return <span class={`badge badge--${tone}`}>{children}</span>;\n};\n\n/** Map a build or snapshot status string to its badge tone. */\nexport function statusTone(status: string): BadgeTone {\n if (status === \"approved\" || status === \"unchanged\") {\n return \"success\";\n }\n if (status === \"rejected\" || status === \"failed\") {\n return \"danger\";\n }\n if (status === \"changed\" || status === \"new\" || status === \"reviewing\") {\n return \"warning\";\n }\n if (status === \"capturing\" || status === \"comparing\" || status === \"pending\") {\n return \"info\";\n }\n return \"neutral\";\n}\n\n/** Alert banner with an optional title. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Alert: FC<{ tone?: BadgeTone; title?: string; children?: unknown }> = ({\n tone = \"info\",\n title,\n children,\n}) => {\n return (\n <div class={`alert alert--${tone}`} role=\"alert\">\n {title ? <strong class=\"alert__title\">{title}</strong> : null}\n <div class=\"alert__body\">{children}</div>\n </div>\n );\n};\n\n/** Centered empty state with an optional call-to-action. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const EmptyState: FC<{ title: string; description?: string; action?: unknown }> = ({\n title,\n description,\n action,\n}) => {\n return (\n <div class=\"empty\">\n <h2 class=\"empty__title\">{title}</h2>\n {description ? <p class=\"empty__desc\">{description}</p> : null}\n {action ? <div class=\"empty__action\">{action}</div> : null}\n </div>\n );\n};\n\n/** Centered statistic value with a label. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Stat: FC<{ label: string; value: string | number }> = ({ label, value }) => {\n return (\n <div class=\"stat\">\n <div class=\"stat__value\">{String(value)}</div>\n <div class=\"stat__label\">{label}</div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAQA,MAAa,SAAuD,EAClE,OAAO,WACP,eACI;CACJ,OAAO,oBAAC,QAAD;EAAM,OAAO,gBAAgB;EAAS;CAAe,CAAA;AAC9D;;AAGA,SAAgB,WAAW,QAA2B;CACpD,IAAI,WAAW,cAAc,WAAW,aACtC,OAAO;CAET,IAAI,WAAW,cAAc,WAAW,UACtC,OAAO;CAET,IAAI,WAAW,aAAa,WAAW,SAAS,WAAW,aACzD,OAAO;CAET,IAAI,WAAW,eAAe,WAAW,eAAe,WAAW,WACjE,OAAO;CAET,OAAO;AACT"}
|
package/dist/ui/forms.mjs
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import "node:path";
|
|
2
|
-
import "node:url";
|
|
3
|
-
import.meta.url;
|
|
4
|
-
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
5
|
-
//#region src/ui/forms.tsx
|
|
6
|
-
const FieldAssistant = ({ name, error, hint }) => {
|
|
7
|
-
if (error) return /* @__PURE__ */ jsx("p", {
|
|
8
|
-
class: "field__error",
|
|
9
|
-
id: `${name}-error`,
|
|
10
|
-
role: "alert",
|
|
11
|
-
children: error
|
|
12
|
-
});
|
|
13
|
-
if (hint) return /* @__PURE__ */ jsx("p", {
|
|
14
|
-
class: "field__hint",
|
|
15
|
-
id: `${name}-hint`,
|
|
16
|
-
children: hint
|
|
17
|
-
});
|
|
18
|
-
return null;
|
|
19
|
-
};
|
|
20
|
-
function fieldDescribedBy(name, error, hint) {
|
|
21
|
-
if (error) return `${name}-error`;
|
|
22
|
-
if (hint) return `${name}-hint`;
|
|
23
|
-
}
|
|
24
|
-
/** Labeled text input with error and hint states. */
|
|
25
|
-
const Field = ({ label, name, type = "text", value, placeholder, required, error, hint, autocomplete }) => {
|
|
26
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
27
|
-
class: "field",
|
|
28
|
-
children: [
|
|
29
|
-
/* @__PURE__ */ jsxs("label", {
|
|
30
|
-
class: "field__label",
|
|
31
|
-
for: name,
|
|
32
|
-
children: [label, required ? /* @__PURE__ */ jsx("span", {
|
|
33
|
-
"aria-hidden": "true",
|
|
34
|
-
children: " *"
|
|
35
|
-
}) : null]
|
|
36
|
-
}),
|
|
37
|
-
/* @__PURE__ */ jsx("input", {
|
|
38
|
-
class: `field__input ${error ? "field__input--error" : ""}`,
|
|
39
|
-
id: name,
|
|
40
|
-
name,
|
|
41
|
-
type,
|
|
42
|
-
value,
|
|
43
|
-
placeholder,
|
|
44
|
-
required,
|
|
45
|
-
"aria-invalid": error ? "true" : void 0,
|
|
46
|
-
"aria-describedby": fieldDescribedBy(name, error, hint),
|
|
47
|
-
autocomplete
|
|
48
|
-
}),
|
|
49
|
-
/* @__PURE__ */ jsx(FieldAssistant, {
|
|
50
|
-
name,
|
|
51
|
-
error,
|
|
52
|
-
hint
|
|
53
|
-
})
|
|
54
|
-
]
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
/** Labeled textarea with error and hint states. */
|
|
58
|
-
const TextareaField = ({ label, name, value, placeholder, rows = 3, hint, error }) => {
|
|
59
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
60
|
-
class: "field",
|
|
61
|
-
children: [
|
|
62
|
-
/* @__PURE__ */ jsx("label", {
|
|
63
|
-
class: "field__label",
|
|
64
|
-
for: name,
|
|
65
|
-
children: label
|
|
66
|
-
}),
|
|
67
|
-
/* @__PURE__ */ jsx("textarea", {
|
|
68
|
-
class: `field__input field__input--textarea ${error ? "field__input--error" : ""}`,
|
|
69
|
-
id: name,
|
|
70
|
-
name,
|
|
71
|
-
placeholder,
|
|
72
|
-
rows,
|
|
73
|
-
"aria-invalid": error ? "true" : void 0,
|
|
74
|
-
"aria-describedby": fieldDescribedBy(name, error, hint),
|
|
75
|
-
children: value
|
|
76
|
-
}),
|
|
77
|
-
/* @__PURE__ */ jsx(FieldAssistant, {
|
|
78
|
-
name,
|
|
79
|
-
error,
|
|
80
|
-
hint
|
|
81
|
-
})
|
|
82
|
-
]
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
/** Labeled select dropdown with an optional hint. */
|
|
86
|
-
const SelectField = ({ label, name, value, options, hint }) => {
|
|
87
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
88
|
-
class: "field",
|
|
89
|
-
children: [
|
|
90
|
-
/* @__PURE__ */ jsx("label", {
|
|
91
|
-
class: "field__label",
|
|
92
|
-
for: name,
|
|
93
|
-
children: label
|
|
94
|
-
}),
|
|
95
|
-
/* @__PURE__ */ jsx("select", {
|
|
96
|
-
class: "field__input",
|
|
97
|
-
id: name,
|
|
98
|
-
name,
|
|
99
|
-
"aria-describedby": hint ? `${name}-hint` : void 0,
|
|
100
|
-
children: options.map((opt) => /* @__PURE__ */ jsx("option", {
|
|
101
|
-
value: opt.value,
|
|
102
|
-
selected: opt.value === value,
|
|
103
|
-
children: opt.label
|
|
104
|
-
}))
|
|
105
|
-
}),
|
|
106
|
-
hint ? /* @__PURE__ */ jsx("p", {
|
|
107
|
-
class: "field__hint",
|
|
108
|
-
id: `${name}-hint`,
|
|
109
|
-
children: hint
|
|
110
|
-
}) : null
|
|
111
|
-
]
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
//#endregion
|
|
115
|
-
export { Field, SelectField, TextareaField };
|
|
116
|
-
|
|
117
|
-
//# sourceMappingURL=forms.mjs.map
|
package/dist/ui/forms.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"forms.mjs","names":[],"sources":["../../src/ui/forms.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n// eslint-disable-next-line promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString>\nconst FieldAssistant: FC<{ name: string; error: string | undefined; hint: string | undefined }> = ({\n name,\n error,\n hint,\n}) => {\n if (error) {\n return (\n <p class=\"field__error\" id={`${name}-error`} role=\"alert\">\n {error}\n </p>\n );\n }\n if (hint) {\n return (\n <p class=\"field__hint\" id={`${name}-hint`}>\n {hint}\n </p>\n );\n }\n return null;\n};\n\nfunction fieldDescribedBy(\n name: string,\n error: string | undefined,\n hint: string | undefined,\n): string | undefined {\n if (error) {\n return `${name}-error`;\n }\n if (hint) {\n return `${name}-hint`;\n }\n return undefined;\n}\n\n/** Labeled text input with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Field: FC<{\n label: string;\n name: string;\n type?: string;\n value?: string;\n placeholder?: string;\n required?: boolean;\n error?: string;\n hint?: string;\n autocomplete?: string;\n}> = ({ label, name, type = \"text\", value, placeholder, required, error, hint, autocomplete }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n {required ? <span aria-hidden=\"true\"> *</span> : null}\n </label>\n <input\n class={`field__input ${error ? \"field__input--error\" : \"\"}`}\n id={name}\n name={name}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n autocomplete={autocomplete}\n />\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled textarea with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const TextareaField: FC<{\n label: string;\n name: string;\n value?: string;\n placeholder?: string;\n rows?: number;\n hint?: string;\n error?: string;\n}> = ({ label, name, value, placeholder, rows = 3, hint, error }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n </label>\n <textarea\n class={`field__input field__input--textarea ${error ? \"field__input--error\" : \"\"}`}\n id={name}\n name={name}\n placeholder={placeholder}\n rows={rows}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n >\n {value}\n </textarea>\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled select dropdown with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const SelectField: FC<{\n label: string;\n name: string;\n value?: string;\n options: { value: string; label: string }[];\n hint?: string;\n}> = ({ label, name, value, options, hint }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n </label>\n <select\n class=\"field__input\"\n id={name}\n name={name}\n aria-describedby={hint ? `${name}-hint` : undefined}\n >\n {options.map((opt) => (\n <option value={opt.value} selected={opt.value === value}>\n {opt.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p class=\"field__hint\" id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n"],"mappings":";;;;;AAKA,MAAM,kBAA6F,EACjG,MACA,OACA,WACI;CACJ,IAAI,OACF,OACE,oBAAC,KAAD;EAAG,OAAM;EAAe,IAAI,GAAG,KAAK;EAAS,MAAK;EAC/C,UAAA;CACA,CAAA;CAGP,IAAI,MACF,OACE,oBAAC,KAAD;EAAG,OAAM;EAAc,IAAI,GAAG,KAAK;EAChC,UAAA;CACA,CAAA;CAGP,OAAO;AACT;AAEA,SAAS,iBACP,MACA,OACA,MACoB;CACpB,IAAI,OACF,OAAO,GAAG,KAAK;CAEjB,IAAI,MACF,OAAO,GAAG,KAAK;AAGnB;;AAIA,MAAa,SAUP,EAAE,OAAO,MAAM,OAAO,QAAQ,OAAO,aAAa,UAAU,OAAO,MAAM,mBAAmB;CAChG,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,qBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAAjC,UAAA,CACG,OACA,WAAW,oBAAC,QAAD;KAAM,eAAY;KAAO,UAAA;IAAQ,CAAA,IAAI,IAC5C;;GACP,oBAAC,SAAD;IACE,OAAO,gBAAgB,QAAQ,wBAAwB;IACvD,IAAI;IACE;IACA;IACC;IACM;IACH;IACV,gBAAc,QAAQ,SAAS,KAAA;IAC/B,oBAAkB,iBAAiB,MAAM,OAAO,IAAI;IACtC;GACf,CAAA;GACD,oBAAC,gBAAD;IAAsB;IAAa;IAAa;GAAO,CAAA;EACpD;;AAET;;AAIA,MAAa,iBAQP,EAAE,OAAO,MAAM,OAAO,aAAa,OAAO,GAAG,MAAM,YAAY;CACnE,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,oBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAC9B,UAAA;GACI,CAAA;GACP,oBAAC,YAAD;IACE,OAAO,uCAAuC,QAAQ,wBAAwB;IAC9E,IAAI;IACE;IACO;IACP;IACN,gBAAc,QAAQ,SAAS,KAAA;IAC/B,oBAAkB,iBAAiB,MAAM,OAAO,IAAI;IAEnD,UAAA;GACO,CAAA;GACV,oBAAC,gBAAD;IAAsB;IAAa;IAAa;GAAO,CAAA;EACpD;;AAET;;AAIA,MAAa,eAMP,EAAE,OAAO,MAAM,OAAO,SAAS,WAAW;CAC9C,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,oBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAC9B,UAAA;GACI,CAAA;GACP,oBAAC,UAAD;IACE,OAAM;IACN,IAAI;IACE;IACN,oBAAkB,OAAO,GAAG,KAAK,SAAS,KAAA;IAEzC,UAAA,QAAQ,KAAK,QACZ,oBAAC,UAAD;KAAQ,OAAO,IAAI;KAAO,UAAU,IAAI,UAAU;KAC/C,UAAA,IAAI;IACC,CAAA,CACT;GACK,CAAA;GACP,OACC,oBAAC,KAAD;IAAG,OAAM;IAAc,IAAI,GAAG,KAAK;IAChC,UAAA;GACA,CAAA,IACD;EACD;;AAET"}
|