@shortlink-org/portolan 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -205
- package/cli/init.mjs +285 -0
- package/cli/init.test.mjs +158 -0
- package/cli/portolan.mjs +37 -73
- package/index.html +19 -0
- package/package.json +5 -10
- package/plugins/README.md +66 -27
- package/plugins/portolan-go.wasm +0 -0
- package/portolan.json +52 -73
- package/public/landing/cats/bug-hunter.webp +0 -0
- package/public/landing/cats/compass-nap.webp +0 -0
- package/public/landing/cats/diagrammer.webp +0 -0
- package/public/landing/cats/docs-reader.webp +0 -0
- package/public/landing/cats/laptop.webp +0 -0
- package/public/landing/cats/map-inspector.webp +0 -0
- package/public/landing/cats/server-break.webp +0 -0
- package/public/landing/cats/star-mapper.webp +0 -0
- package/public/landing/cats/system-builder.webp +0 -0
- package/public/landing/cats/thread-tangle.webp +0 -0
- package/public/og.png +0 -0
- package/public/readme-header.webp +0 -0
- package/schema/portolan.schema.json +180 -0
- package/scripts/builtin-plugins.mjs +14 -0
- package/scripts/delivery-presets.mjs +353 -0
- package/scripts/gen.mjs +37 -4
- package/scripts/history.mjs +126 -0
- package/scripts/history.test.mjs +110 -0
- package/scripts/host-plugins/fetch-bsr.mjs +351 -0
- package/{plugins/fetch-bsr/options.schema.json → scripts/host-plugins/fetch-bsr.options.json} +4 -0
- package/scripts/host-plugins/fetch-bsr.test.mjs +212 -0
- package/scripts/host-plugins/fetch-csr.mjs +386 -0
- package/scripts/host-plugins/fetch-csr.test.mjs +178 -0
- package/scripts/host-plugins/fetch-git.mjs +379 -0
- package/scripts/host-plugins/fetch-git.test.mjs +210 -0
- package/scripts/local-api.mjs +22 -4
- package/scripts/local-api.test.mjs +84 -2
- package/scripts/manifest.mjs +3 -2
- package/scripts/package-smoke.mjs +6 -2
- package/scripts/plugin-host.mjs +77 -18
- package/scripts/plugin-host.test.mjs +50 -1
- package/scripts/plugin-wasm-worker.mjs +6 -3
- package/scripts/run-builtin.mjs +6 -26
- package/scripts/schema.mjs +6 -1
- package/src/app/App.tsx +24 -429
- package/src/app/Breadcrumbs.test.ts +7 -0
- package/src/app/Breadcrumbs.tsx +15 -2
- package/src/app/CatalogApp.tsx +436 -0
- package/src/app/Sidebar.tsx +0 -1
- package/src/chat/ChatPanel.tsx +98 -41
- package/src/chat/Composer.tsx +4 -2
- package/src/chat/Conversation.tsx +79 -15
- package/src/chat/Header.tsx +43 -9
- package/src/chat/Starter.tsx +64 -3
- package/src/chat/Steps.tsx +1 -1
- package/src/chat/flags.test.ts +51 -14
- package/src/chat/flags.ts +8 -2
- package/src/chat/page-context.test.ts +51 -0
- package/src/chat/page-context.ts +128 -0
- package/src/chat/prompt.test.ts +49 -1
- package/src/chat/prompt.ts +42 -1
- package/src/chat/tools.ts +7 -2
- package/src/chat/transport.ts +16 -4
- package/src/components/ProblemRow.tsx +182 -0
- package/src/data.ts +20 -5
- package/src/er/ErCanvas.tsx +1 -1
- package/src/graph/DependencyGraph.tsx +10 -1
- package/src/graph/FocusedEventGraph.tsx +1 -1
- package/src/graph/GraphToolbar.tsx +2 -4
- package/src/index.css +220 -2
- package/src/landing/DraggableReveal.tsx +168 -0
- package/src/landing/EstateGraph.tsx +28 -0
- package/src/landing/FlowPlayback.tsx +282 -0
- package/src/landing/HeroMap.tsx +128 -0
- package/src/landing/LandingPage.tsx +757 -0
- package/src/landing/ProductFrame.tsx +68 -0
- package/src/landing/ProductTour.tsx +371 -0
- package/src/landing/catalog.ts +25 -0
- package/src/landing/motion.tsx +52 -0
- package/src/lib/all-problems.ts +28 -0
- package/src/lib/local-api.ts +35 -1
- package/src/lib/setup-info.test.ts +8 -0
- package/src/lib/setup-info.ts +3 -2
- package/src/lib/source-code.ts +2 -1
- package/src/likec4/C4View.tsx +5 -0
- package/src/likec4/InteractiveView.tsx +5 -1
- package/src/map/ContextMapGraph.tsx +47 -20
- package/src/pages/ContextMap.tsx +5 -1
- package/src/pages/FlowDetail.tsx +24 -7
- package/src/pages/Overview.tsx +68 -12
- package/src/pages/Problems.tsx +6 -193
- package/src/pages/Settings.tsx +133 -108
- package/src/pages/settings/DeliverySettings.tsx +229 -0
- package/src/pages/settings/PreferencesSettings.tsx +101 -0
- package/src/routes.test.ts +20 -0
- package/src/routes.ts +13 -1
- package/vite.config.ts +12 -8
- package/catalog/enum_test.go +0 -46
- package/catalog/model.go +0 -932
- package/catalog/roundtrip_test.go +0 -185
- package/catalog/via_test.go +0 -38
- package/go.mod +0 -14
- package/go.sum +0 -14
- package/internal/commands/cargo.go +0 -154
- package/internal/commands/commands.go +0 -143
- package/internal/commands/commands_test.go +0 -323
- package/internal/commands/gradle.go +0 -77
- package/internal/commands/justfile.go +0 -82
- package/internal/commands/makefile.go +0 -106
- package/internal/commands/maven.go +0 -93
- package/internal/commands/packagejson.go +0 -159
- package/internal/commands/pyproject.go +0 -169
- package/internal/commands/taskfile.go +0 -101
- package/internal/commands/testdata/estate/.cargo/config.toml +0 -7
- package/internal/commands/testdata/estate/Makefile +0 -33
- package/internal/commands/testdata/estate/Taskfile.yml +0 -21
- package/internal/commands/testdata/estate/build.gradle.kts +0 -21
- package/internal/commands/testdata/estate/justfile +0 -20
- package/internal/commands/testdata/estate/package.json +0 -13
- package/internal/commands/testdata/estate/pom.xml +0 -29
- package/internal/commands/testdata/estate/pyproject.toml +0 -27
- package/internal/commands/testdata/estate/xtask/src/main.rs +0 -27
- package/internal/commands/testdata/golden/commands.json +0 -305
- package/internal/gohttp/analyze.go +0 -2500
- package/internal/gohttp/endpoints.go +0 -1067
- package/internal/gohttp/roots.go +0 -320
- package/internal/gohttp/typed.go +0 -143
- package/internal/goscan/constants.go +0 -85
- package/internal/goscan/goscan_test.go +0 -227
- package/internal/goscan/names.go +0 -52
- package/internal/goscan/parse_test.go +0 -11
- package/internal/goscan/source.go +0 -36
- package/internal/goscan/tree.go +0 -155
- package/internal/goscan/types.go +0 -99
- package/internal/wsdl/ids.go +0 -127
- package/internal/wsdl/ids_test.go +0 -21
- package/internal/wsdl/model.go +0 -62
- package/internal/wsdl/parse.go +0 -920
- package/internal/wsdl/parse_test.go +0 -133
- package/plugin/describe.go +0 -107
- package/plugin/describe_test.go +0 -114
- package/plugin/protocol.go +0 -117
- package/plugin/schematest/schematest.go +0 -126
- package/plugins/extract-adr/describe.go +0 -19
- package/plugins/extract-adr/describe_test.go +0 -11
- package/plugins/extract-adr/extract.go +0 -153
- package/plugins/extract-adr/extract_test.go +0 -350
- package/plugins/extract-adr/history.go +0 -99
- package/plugins/extract-adr/main.go +0 -65
- package/plugins/extract-adr/parse.go +0 -642
- package/plugins/extract-adr/parse_test.go +0 -405
- package/plugins/extract-asyncapi/describe.go +0 -19
- package/plugins/extract-asyncapi/describe_test.go +0 -11
- package/plugins/extract-asyncapi/extract.go +0 -315
- package/plugins/extract-asyncapi/extract_test.go +0 -197
- package/plugins/extract-asyncapi/main.go +0 -48
- package/plugins/extract-asyncapi/spec.go +0 -151
- package/plugins/extract-commands/describe.go +0 -19
- package/plugins/extract-commands/describe_test.go +0 -11
- package/plugins/extract-commands/extract.go +0 -79
- package/plugins/extract-commands/extract_test.go +0 -92
- package/plugins/extract-commands/main.go +0 -55
- package/plugins/extract-csr/avro.go +0 -258
- package/plugins/extract-csr/describe.go +0 -19
- package/plugins/extract-csr/describe_test.go +0 -11
- package/plugins/extract-csr/extract.go +0 -338
- package/plugins/extract-csr/extract_test.go +0 -374
- package/plugins/extract-csr/jsonschema.go +0 -343
- package/plugins/extract-csr/lock.go +0 -25
- package/plugins/extract-csr/main.go +0 -84
- package/plugins/extract-csr/subject.go +0 -102
- package/plugins/extract-flows/describe.go +0 -19
- package/plugins/extract-flows/describe_test.go +0 -11
- package/plugins/extract-flows/extract.go +0 -91
- package/plugins/extract-flows/main.go +0 -45
- package/plugins/extract-flows/parse.go +0 -593
- package/plugins/extract-flows/parse_test.go +0 -204
- package/plugins/extract-glossary/describe.go +0 -19
- package/plugins/extract-glossary/describe_test.go +0 -11
- package/plugins/extract-glossary/extract.go +0 -115
- package/plugins/extract-glossary/extract_test.go +0 -220
- package/plugins/extract-glossary/main.go +0 -59
- package/plugins/extract-glossary/parse.go +0 -214
- package/plugins/extract-glossary/parse_test.go +0 -203
- package/plugins/extract-go/aggregate.go +0 -214
- package/plugins/extract-go/client.go +0 -409
- package/plugins/extract-go/client_test.go +0 -266
- package/plugins/extract-go/describe.go +0 -19
- package/plugins/extract-go/describe_test.go +0 -11
- package/plugins/extract-go/enum.go +0 -195
- package/plugins/extract-go/enum_test.go +0 -82
- package/plugins/extract-go/event.go +0 -99
- package/plugins/extract-go/extract.go +0 -191
- package/plugins/extract-go/extract_test.go +0 -261
- package/plugins/extract-go/flow.go +0 -1441
- package/plugins/extract-go/flow_test.go +0 -609
- package/plugins/extract-go/httpclient.go +0 -174
- package/plugins/extract-go/httpclient_test.go +0 -296
- package/plugins/extract-go/ids.go +0 -92
- package/plugins/extract-go/layout.go +0 -225
- package/plugins/extract-go/layout_test.go +0 -125
- package/plugins/extract-go/lifecycle.go +0 -324
- package/plugins/extract-go/lifecycle_test.go +0 -108
- package/plugins/extract-go/main.go +0 -79
- package/plugins/extract-go/operation.go +0 -157
- package/plugins/extract-go/source.go +0 -316
- package/plugins/extract-go/transport.go +0 -321
- package/plugins/extract-go/transport_test.go +0 -145
- package/plugins/extract-go/wiring.go +0 -434
- package/plugins/extract-go-nats/describe.go +0 -19
- package/plugins/extract-go-nats/describe_test.go +0 -11
- package/plugins/extract-go-nats/extract.go +0 -177
- package/plugins/extract-go-nats/extract_test.go +0 -389
- package/plugins/extract-go-nats/index.go +0 -379
- package/plugins/extract-go-nats/main.go +0 -42
- package/plugins/extract-go-nats/resolve.go +0 -161
- package/plugins/extract-go-nats/sites.go +0 -224
- package/plugins/extract-graphql/describe.go +0 -19
- package/plugins/extract-graphql/describe_test.go +0 -11
- package/plugins/extract-graphql/extract.go +0 -433
- package/plugins/extract-graphql/extract_test.go +0 -256
- package/plugins/extract-graphql/ids.go +0 -49
- package/plugins/extract-graphql/lex.go +0 -237
- package/plugins/extract-graphql/main.go +0 -51
- package/plugins/extract-graphql/parse.go +0 -621
- package/plugins/extract-graphql/parse_test.go +0 -122
- package/plugins/extract-http-clients/describe.go +0 -19
- package/plugins/extract-http-clients/describe_test.go +0 -11
- package/plugins/extract-http-clients/extract.go +0 -705
- package/plugins/extract-http-clients/extract_test.go +0 -1263
- package/plugins/extract-http-clients/main.go +0 -42
- package/plugins/extract-openapi/describe.go +0 -19
- package/plugins/extract-openapi/describe_test.go +0 -11
- package/plugins/extract-openapi/discover.go +0 -243
- package/plugins/extract-openapi/extract.go +0 -526
- package/plugins/extract-openapi/extract_test.go +0 -545
- package/plugins/extract-openapi/main.go +0 -75
- package/plugins/extract-openapi/spec.go +0 -350
- package/plugins/extract-project/describe.go +0 -19
- package/plugins/extract-project/describe_test.go +0 -11
- package/plugins/extract-project/extract.go +0 -221
- package/plugins/extract-project/extract_test.go +0 -109
- package/plugins/extract-project/main.go +0 -41
- package/plugins/extract-proto/ast.go +0 -125
- package/plugins/extract-proto/consumes.go +0 -77
- package/plugins/extract-proto/describe.go +0 -19
- package/plugins/extract-proto/extract.go +0 -293
- package/plugins/extract-proto/extract_test.go +0 -459
- package/plugins/extract-proto/ids.go +0 -89
- package/plugins/extract-proto/ids_test.go +0 -57
- package/plugins/extract-proto/lex.go +0 -285
- package/plugins/extract-proto/main.go +0 -100
- package/plugins/extract-proto/module.go +0 -120
- package/plugins/extract-proto/parse.go +0 -720
- package/plugins/extract-proto/parse_test.go +0 -307
- package/plugins/extract-proto/provides.go +0 -236
- package/plugins/extract-proto/resolve.go +0 -222
- package/plugins/extract-proto/resolve_test.go +0 -119
- package/plugins/extract-redis/describe.go +0 -19
- package/plugins/extract-redis/describe_test.go +0 -11
- package/plugins/extract-redis/extract.go +0 -183
- package/plugins/extract-redis/extract_test.go +0 -168
- package/plugins/extract-redis/keyspaces.go +0 -469
- package/plugins/extract-redis/main.go +0 -44
- package/plugins/extract-river/describe.go +0 -19
- package/plugins/extract-river/describe_test.go +0 -11
- package/plugins/extract-river/extract.go +0 -507
- package/plugins/extract-river/extract_test.go +0 -132
- package/plugins/extract-river/main.go +0 -42
- package/plugins/extract-sql/ddl.go +0 -893
- package/plugins/extract-sql/ddl_test.go +0 -401
- package/plugins/extract-sql/describe.go +0 -19
- package/plugins/extract-sql/describe_test.go +0 -11
- package/plugins/extract-sql/layout.go +0 -221
- package/plugins/extract-sql/layout_test.go +0 -55
- package/plugins/extract-sql/lineage.go +0 -107
- package/plugins/extract-sql/main.go +0 -141
- package/plugins/extract-sql/maps.go +0 -564
- package/plugins/extract-sql/maps_java.go +0 -117
- package/plugins/extract-sql/maps_rust.go +0 -333
- package/plugins/extract-sql/maps_rust_test.go +0 -70
- package/plugins/extract-sql/maps_test.go +0 -204
- package/plugins/extract-sql/maps_ts.go +0 -398
- package/plugins/extract-sql/maps_ts_test.go +0 -136
- package/plugins/extract-sql/projection.go +0 -70
- package/plugins/extract-sql/projection_test.go +0 -50
- package/plugins/extract-sql/store.go +0 -420
- package/plugins/extract-sql/store_test.go +0 -233
- package/plugins/extract-sql/view.go +0 -295
- package/plugins/extract-watermill/describe.go +0 -19
- package/plugins/extract-watermill/describe_test.go +0 -11
- package/plugins/extract-watermill/extract.go +0 -1228
- package/plugins/extract-watermill/extract_test.go +0 -234
- package/plugins/extract-watermill/main.go +0 -41
- package/plugins/extract-wsdl/describe.go +0 -19
- package/plugins/extract-wsdl/describe_test.go +0 -11
- package/plugins/extract-wsdl/extract.go +0 -148
- package/plugins/extract-wsdl/extract_test.go +0 -45
- package/plugins/extract-wsdl/main.go +0 -53
- package/plugins/fetch-bsr/auth.go +0 -114
- package/plugins/fetch-bsr/bsr.go +0 -240
- package/plugins/fetch-bsr/cache.go +0 -66
- package/plugins/fetch-bsr/describe.go +0 -19
- package/plugins/fetch-bsr/fetch.go +0 -192
- package/plugins/fetch-bsr/fetch_test.go +0 -465
- package/plugins/fetch-bsr/lock.go +0 -71
- package/plugins/fetch-bsr/main.go +0 -117
- package/plugins/fetch-csr/auth.go +0 -95
- package/plugins/fetch-csr/cache.go +0 -69
- package/plugins/fetch-csr/describe.go +0 -19
- package/plugins/fetch-csr/describe_test.go +0 -11
- package/plugins/fetch-csr/fetch.go +0 -254
- package/plugins/fetch-csr/fetch_test.go +0 -494
- package/plugins/fetch-csr/lock.go +0 -95
- package/plugins/fetch-csr/main.go +0 -122
- package/plugins/fetch-csr/registry.go +0 -209
- package/plugins/fetch-git/cache.go +0 -65
- package/plugins/fetch-git/describe.go +0 -19
- package/plugins/fetch-git/describe_test.go +0 -11
- package/plugins/fetch-git/fetch.go +0 -181
- package/plugins/fetch-git/fetch_test.go +0 -332
- package/plugins/fetch-git/git.go +0 -169
- package/plugins/fetch-git/lock.go +0 -72
- package/plugins/fetch-git/main.go +0 -127
- package/plugins/fetch-git/offline.go +0 -39
- package/plugins/fetch-git/pin.go +0 -90
- package/plugins/fetch-git/pin_test.go +0 -74
- package/plugins/gen-backstage/describe.go +0 -17
- package/plugins/gen-backstage/main.go +0 -22
- package/plugins/gen-backstage/plugin.go +0 -473
- package/plugins/gen-backstage/plugin_test.go +0 -145
- package/plugins/gen-backstage.wasm +0 -0
- package/plugins/gen-markdown/adr.go +0 -162
- package/plugins/gen-markdown/aggregate.go +0 -362
- package/plugins/gen-markdown/canonical.go +0 -93
- package/plugins/gen-markdown/context.go +0 -90
- package/plugins/gen-markdown/coverage_test.go +0 -89
- package/plugins/gen-markdown/describe.go +0 -19
- package/plugins/gen-markdown/describe_test.go +0 -11
- package/plugins/gen-markdown/external.go +0 -71
- package/plugins/gen-markdown/flow.go +0 -277
- package/plugins/gen-markdown/glossary.go +0 -76
- package/plugins/gen-markdown/glossary_test.go +0 -148
- package/plugins/gen-markdown/llms.go +0 -302
- package/plugins/gen-markdown/main.go +0 -22
- package/plugins/gen-markdown/markdown.go +0 -254
- package/plugins/gen-markdown/markdown_test.go +0 -100
- package/plugins/gen-markdown/module.go +0 -107
- package/plugins/gen-markdown/plugin.go +0 -39
- package/plugins/gen-markdown/quality_test.go +0 -176
- package/plugins/gen-markdown/redis_test.go +0 -38
- package/plugins/gen-markdown/render.go +0 -344
- package/plugins/gen-markdown/render_test.go +0 -186
- package/plugins/gen-markdown/service.go +0 -456
- package/plugins/gen-markdown/source.go +0 -177
- package/plugins/gen-markdown/store.go +0 -201
- package/plugins/gen-markdown.wasm +0 -0
- package/plugins/gen-mermaid/describe.go +0 -17
- package/plugins/gen-mermaid/main.go +0 -22
- package/plugins/gen-mermaid/plugin.go +0 -104
- package/plugins/gen-mermaid/plugin_test.go +0 -33
- package/plugins/gen-mermaid.wasm +0 -0
- package/plugins/openapi/ids.go +0 -261
- package/plugins/openapi/ids_test.go +0 -98
- package/plugins/verify-codeowners/describe.go +0 -19
- package/plugins/verify-codeowners/describe_test.go +0 -11
- package/plugins/verify-codeowners/main.go +0 -75
- package/plugins/verify-codeowners/match.go +0 -85
- package/plugins/verify-codeowners/match_test.go +0 -47
- package/plugins/verify-codeowners/owners.go +0 -164
- package/plugins/verify-codeowners/owners_test.go +0 -225
- package/plugins/verify-codeowners/parse.go +0 -90
- package/plugins/verify-codeowners/parse_test.go +0 -62
- package/plugins/verify-otel/describe.go +0 -19
- package/plugins/verify-otel/describe_test.go +0 -11
- package/plugins/verify-otel/main.go +0 -53
- package/plugins/verify-otel/match.go +0 -336
- package/plugins/verify-otel/otlp.go +0 -200
- package/plugins/verify-otel/verify.go +0 -734
- package/plugins/verify-otel/verify_test.go +0 -460
- /package/{plugins/fetch-csr/options.schema.json → scripts/host-plugins/fetch-csr.options.json} +0 -0
- /package/{plugins/fetch-git/options.schema.json → scripts/host-plugins/fetch-git.options.json} +0 -0
package/src/index.css
CHANGED
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
--accent-lo: #1a5ec9;
|
|
33
33
|
--accent-hi: #3d86f5;
|
|
34
34
|
|
|
35
|
+
/* Product action, deliberately separate from event amber. In the light
|
|
36
|
+
theme it gives onboarding and AI entry points a warmer invitation without
|
|
37
|
+
teaching readers that an event/status colour means “click me”. */
|
|
38
|
+
--product-action: #c76a1b;
|
|
39
|
+
--product-action-ink: #6f350a;
|
|
40
|
+
|
|
35
41
|
/* Source preview syntax. These are semantic roles rather than one imported
|
|
36
42
|
editor theme, so code follows Portolan's light and dark palettes. */
|
|
37
43
|
--syntax-comment: #6a737d;
|
|
@@ -149,6 +155,8 @@
|
|
|
149
155
|
--accent: #5b9dff;
|
|
150
156
|
--accent-lo: #3d7fe0;
|
|
151
157
|
--accent-hi: #7ab2ff;
|
|
158
|
+
--product-action: #5b9dff;
|
|
159
|
+
--product-action-ink: #e3e8ee;
|
|
152
160
|
|
|
153
161
|
--syntax-comment: #8b97a4;
|
|
154
162
|
--syntax-keyword: #c6a0f6;
|
|
@@ -574,23 +582,147 @@
|
|
|
574
582
|
.btn-accent:hover {
|
|
575
583
|
filter: brightness(1.06);
|
|
576
584
|
}
|
|
585
|
+
|
|
586
|
+
/* The landing's primary action should feel like a control from the map,
|
|
587
|
+
not a bright rectangle pasted over it. The depth is always present; the
|
|
588
|
+
brief chart-line sweep only appears when a reader points at the action. */
|
|
589
|
+
.landing-primary,
|
|
590
|
+
.product-primary {
|
|
591
|
+
@apply mono flex items-center gap-1.5 rounded-control px-3 py-1.5;
|
|
592
|
+
position: relative;
|
|
593
|
+
isolation: isolate;
|
|
594
|
+
overflow: hidden;
|
|
595
|
+
color: var(--fg);
|
|
596
|
+
border: 1px solid color-mix(in srgb, var(--accent) 48%, var(--border));
|
|
597
|
+
background:
|
|
598
|
+
radial-gradient(
|
|
599
|
+
circle at 18% 0%,
|
|
600
|
+
rgb(255 255 255 / 0.1),
|
|
601
|
+
transparent 42%
|
|
602
|
+
),
|
|
603
|
+
linear-gradient(
|
|
604
|
+
to bottom,
|
|
605
|
+
color-mix(in srgb, var(--surface-2) 76%, var(--accent)),
|
|
606
|
+
color-mix(in srgb, var(--surface) 84%, var(--accent))
|
|
607
|
+
);
|
|
608
|
+
box-shadow:
|
|
609
|
+
inset 0 1px 0 rgb(255 255 255 / 0.18),
|
|
610
|
+
inset 0 -1px 0 rgb(0 0 0 / 0.2),
|
|
611
|
+
0 1px 2px rgb(0 0 0 / 0.2),
|
|
612
|
+
0 12px 28px -18px color-mix(in srgb, var(--accent) 82%, transparent);
|
|
613
|
+
text-shadow: 0 1px 0 color-mix(in srgb, var(--bg) 55%, transparent);
|
|
614
|
+
transition:
|
|
615
|
+
transform var(--dur-micro) var(--ease-out),
|
|
616
|
+
border-color var(--dur-micro) var(--ease-out),
|
|
617
|
+
box-shadow var(--dur-panel) var(--ease-out);
|
|
618
|
+
}
|
|
619
|
+
:root:not(.dark) :is(.landing-primary, .product-primary) {
|
|
620
|
+
color: var(--product-action-ink);
|
|
621
|
+
border-color: color-mix(in srgb, var(--product-action) 52%, var(--border));
|
|
622
|
+
background:
|
|
623
|
+
radial-gradient(
|
|
624
|
+
circle at 18% 0%,
|
|
625
|
+
rgb(255 255 255 / 0.68),
|
|
626
|
+
transparent 44%
|
|
627
|
+
),
|
|
628
|
+
linear-gradient(
|
|
629
|
+
to bottom,
|
|
630
|
+
color-mix(in srgb, var(--product-action) 13%, white),
|
|
631
|
+
color-mix(in srgb, var(--product-action) 28%, white)
|
|
632
|
+
);
|
|
633
|
+
box-shadow:
|
|
634
|
+
inset 0 1px 0 rgb(255 255 255 / 0.82),
|
|
635
|
+
inset 0 -1px 0 color-mix(in srgb, var(--product-action) 22%, transparent),
|
|
636
|
+
0 1px 2px rgb(91 45 8 / 0.1),
|
|
637
|
+
0 12px 28px -18px color-mix(in srgb, var(--product-action) 70%, transparent);
|
|
638
|
+
text-shadow: 0 1px 0 rgb(255 255 255 / 0.55);
|
|
639
|
+
}
|
|
640
|
+
:is(.landing-primary, .product-primary)::before {
|
|
641
|
+
position: absolute;
|
|
642
|
+
inset: -1px;
|
|
643
|
+
z-index: 0;
|
|
644
|
+
pointer-events: none;
|
|
645
|
+
content: "";
|
|
646
|
+
background: linear-gradient(
|
|
647
|
+
112deg,
|
|
648
|
+
transparent 28%,
|
|
649
|
+
rgb(255 255 255 / 0.03) 39%,
|
|
650
|
+
rgb(255 255 255 / 0.3) 48%,
|
|
651
|
+
rgb(255 255 255 / 0.05) 57%,
|
|
652
|
+
transparent 70%
|
|
653
|
+
);
|
|
654
|
+
transform: translateX(-135%);
|
|
655
|
+
transition: transform 600ms var(--ease-out);
|
|
656
|
+
}
|
|
657
|
+
:is(.landing-primary, .product-primary):hover {
|
|
658
|
+
filter: none;
|
|
659
|
+
border-color: color-mix(in srgb, var(--accent) 82%, white);
|
|
660
|
+
box-shadow:
|
|
661
|
+
inset 0 1px 0 rgb(255 255 255 / 0.24),
|
|
662
|
+
inset 0 -1px 0 rgb(0 0 0 / 0.2),
|
|
663
|
+
0 2px 4px rgb(0 0 0 / 0.22),
|
|
664
|
+
0 16px 34px -17px color-mix(in srgb, var(--accent) 95%, transparent);
|
|
665
|
+
transform: translateY(-1px);
|
|
666
|
+
}
|
|
667
|
+
:root:not(.dark) :is(.landing-primary, .product-primary):hover {
|
|
668
|
+
border-color: color-mix(in srgb, var(--product-action) 78%, white);
|
|
669
|
+
box-shadow:
|
|
670
|
+
inset 0 1px 0 rgb(255 255 255 / 0.9),
|
|
671
|
+
inset 0 -1px 0 color-mix(in srgb, var(--product-action) 25%, transparent),
|
|
672
|
+
0 2px 4px rgb(91 45 8 / 0.12),
|
|
673
|
+
0 16px 34px -17px color-mix(in srgb, var(--product-action) 76%, transparent);
|
|
674
|
+
}
|
|
675
|
+
:is(.landing-primary, .product-primary):hover::before {
|
|
676
|
+
transform: translateX(135%);
|
|
677
|
+
}
|
|
678
|
+
.landing-primary svg:last-child {
|
|
679
|
+
transition: transform var(--dur-micro) var(--ease-out);
|
|
680
|
+
}
|
|
681
|
+
.landing-primary:hover svg:last-child {
|
|
682
|
+
transform: translateX(2px);
|
|
683
|
+
}
|
|
684
|
+
:is(.landing-primary, .product-primary):active {
|
|
685
|
+
transform: translateY(0);
|
|
686
|
+
}
|
|
687
|
+
:is(.landing-primary, .product-primary):focus-visible {
|
|
688
|
+
outline: 2px solid color-mix(in srgb, var(--accent) 55%, white);
|
|
689
|
+
outline-offset: 3px;
|
|
690
|
+
}
|
|
577
691
|
.btn-accent:disabled,
|
|
692
|
+
.product-primary:disabled,
|
|
578
693
|
.tbtn:disabled {
|
|
579
694
|
cursor: not-allowed;
|
|
580
695
|
opacity: 0.55;
|
|
581
696
|
}
|
|
582
697
|
|
|
698
|
+
@media (prefers-reduced-motion: reduce) {
|
|
699
|
+
.landing-primary,
|
|
700
|
+
.product-primary,
|
|
701
|
+
.landing-primary::before,
|
|
702
|
+
.product-primary::before,
|
|
703
|
+
.landing-primary svg:last-child {
|
|
704
|
+
transition: none;
|
|
705
|
+
}
|
|
706
|
+
.landing-primary:hover,
|
|
707
|
+
.product-primary:hover,
|
|
708
|
+
.landing-primary:hover svg:last-child {
|
|
709
|
+
transform: none;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
583
713
|
/* A group of related controls reads as one object: a single border around
|
|
584
714
|
the set, hairlines only between its members. */
|
|
585
715
|
.seg {
|
|
586
|
-
@apply flex items-center overflow-hidden rounded-control border border-line;
|
|
716
|
+
@apply flex shrink-0 items-center overflow-hidden rounded-control border border-line;
|
|
587
717
|
}
|
|
588
718
|
.seg > * + * {
|
|
589
719
|
border-left: 1px solid var(--border);
|
|
590
720
|
}
|
|
721
|
+
/* A member never breaks its line: a toolbar that runs out of room wraps
|
|
722
|
+
whole segments, not the word inside one. */
|
|
591
723
|
.seg > button,
|
|
592
724
|
.seg > a {
|
|
593
|
-
@apply mono px-2 py-1 text-muted;
|
|
725
|
+
@apply mono px-2 py-1 whitespace-nowrap text-muted;
|
|
594
726
|
transition:
|
|
595
727
|
background-color var(--dur-micro) var(--ease-out),
|
|
596
728
|
color var(--dur-micro) var(--ease-out);
|
|
@@ -654,6 +786,68 @@
|
|
|
654
786
|
background: color-mix(in srgb, currentColor 12%, transparent);
|
|
655
787
|
}
|
|
656
788
|
|
|
789
|
+
/* Landing-only presentation surfaces. They reuse the application's canvas
|
|
790
|
+
and status tokens, but carry no catalog data or diagram runtime. */
|
|
791
|
+
.landing-grid {
|
|
792
|
+
background-color: var(--flow-pane);
|
|
793
|
+
background-image: radial-gradient(var(--flow-dot) 1px, transparent 1px);
|
|
794
|
+
background-size: 18px 18px;
|
|
795
|
+
}
|
|
796
|
+
.landing-product-shadow {
|
|
797
|
+
box-shadow:
|
|
798
|
+
0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent),
|
|
799
|
+
0 28px 80px -34px color-mix(in srgb, var(--accent) 42%, transparent),
|
|
800
|
+
var(--shadow-md);
|
|
801
|
+
}
|
|
802
|
+
.landing-hero {
|
|
803
|
+
background-image: radial-gradient(
|
|
804
|
+
70% 85% at 72% 22%,
|
|
805
|
+
color-mix(in srgb, var(--accent) 9%, transparent),
|
|
806
|
+
transparent 70%
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
.landing-final {
|
|
810
|
+
background-image: radial-gradient(
|
|
811
|
+
55% 100% at 50% 100%,
|
|
812
|
+
color-mix(in srgb, var(--accent) 10%, transparent),
|
|
813
|
+
transparent 72%
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
.landing-orbit {
|
|
817
|
+
position: absolute;
|
|
818
|
+
border: 1px solid color-mix(in srgb, var(--accent) 10%, transparent);
|
|
819
|
+
border-radius: 9999px;
|
|
820
|
+
pointer-events: none;
|
|
821
|
+
}
|
|
822
|
+
.landing-orbit-one {
|
|
823
|
+
width: 700px;
|
|
824
|
+
height: 700px;
|
|
825
|
+
top: -430px;
|
|
826
|
+
right: -140px;
|
|
827
|
+
}
|
|
828
|
+
.landing-orbit-two {
|
|
829
|
+
width: 980px;
|
|
830
|
+
height: 980px;
|
|
831
|
+
top: -570px;
|
|
832
|
+
right: -280px;
|
|
833
|
+
}
|
|
834
|
+
.landing-hero .landing-canvas .react-flow__edge-path {
|
|
835
|
+
stroke-width: 1.75 !important;
|
|
836
|
+
}
|
|
837
|
+
.landing-hero-title {
|
|
838
|
+
line-height: 0.96 !important;
|
|
839
|
+
}
|
|
840
|
+
@media (min-width: 1024px) and (max-height: 760px) {
|
|
841
|
+
.landing-hero-grid {
|
|
842
|
+
padding-top: 2rem !important;
|
|
843
|
+
padding-bottom: 2rem !important;
|
|
844
|
+
}
|
|
845
|
+
.landing-hero-title {
|
|
846
|
+
font-size: clamp(3.5rem, 4.8vw, 3.9rem) !important;
|
|
847
|
+
line-height: 0.94 !important;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
657
851
|
/* Non-navigable header for a group of leaves inside an aggregate. */
|
|
658
852
|
.group-row {
|
|
659
853
|
@apply mono flex w-full items-center gap-1.5 py-[3px] pr-2 text-left text-muted hover:bg-surface;
|
|
@@ -1525,6 +1719,30 @@ h3 {
|
|
|
1525
1719
|
font-family: var(--font-sans);
|
|
1526
1720
|
}
|
|
1527
1721
|
|
|
1722
|
+
/* How a canvas of this app arrives and changes. The boxes rise in as elk
|
|
1723
|
+
places them and the lines follow a beat later, so the picture is drawn
|
|
1724
|
+
rather than dropped in over the skeleton; anything a selection, a focus or
|
|
1725
|
+
a playback dims fades rather than snaps. The node's own transform is its
|
|
1726
|
+
position, so what rises is the card inside it, never the node. Opt-in by
|
|
1727
|
+
class: LikeC4 draws its canvases with the same library and its own motion,
|
|
1728
|
+
and must not inherit this. */
|
|
1729
|
+
.canvas-motion .react-flow__node {
|
|
1730
|
+
animation: fade-in var(--dur-narrative) var(--ease-out) both;
|
|
1731
|
+
transition: opacity var(--dur-narrative) var(--ease-in-out);
|
|
1732
|
+
}
|
|
1733
|
+
.canvas-motion .react-flow__node > * {
|
|
1734
|
+
animation: row-in var(--dur-narrative) var(--ease-out) both;
|
|
1735
|
+
}
|
|
1736
|
+
.canvas-motion .react-flow__edge {
|
|
1737
|
+
animation: fade-in var(--dur-narrative) var(--ease-out) both;
|
|
1738
|
+
animation-delay: 180ms;
|
|
1739
|
+
}
|
|
1740
|
+
.canvas-motion .react-flow__edge-path {
|
|
1741
|
+
transition:
|
|
1742
|
+
opacity var(--dur-narrative) var(--ease-in-out),
|
|
1743
|
+
stroke-width var(--dur-micro) var(--ease-out);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1528
1746
|
/* Selection is the ring, on the node's own box. The event pill is the one
|
|
1529
1747
|
node that is not the shape of its box - it is a capsule, and at fit zooms
|
|
1530
1748
|
it shrinks to an icon inside the box - so it draws the ring itself. */
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { useId, useState } from "react";
|
|
2
|
+
import type { KeyboardEvent, ReactNode } from "react";
|
|
3
|
+
import { animate, useDragControls, useMotionValue } from "motion/react";
|
|
4
|
+
import type { PanInfo } from "motion/react";
|
|
5
|
+
import { m } from "../lib/motion";
|
|
6
|
+
|
|
7
|
+
const cats = [
|
|
8
|
+
"thread-tangle.webp",
|
|
9
|
+
"map-inspector.webp",
|
|
10
|
+
"laptop.webp",
|
|
11
|
+
"diagrammer.webp",
|
|
12
|
+
"compass-nap.webp",
|
|
13
|
+
"docs-reader.webp",
|
|
14
|
+
"bug-hunter.webp",
|
|
15
|
+
"system-builder.webp",
|
|
16
|
+
"server-break.webp",
|
|
17
|
+
"star-mapper.webp",
|
|
18
|
+
].map((file) => `${import.meta.env.BASE_URL}landing/cats/${file}`);
|
|
19
|
+
|
|
20
|
+
const X_LIMIT = 300;
|
|
21
|
+
const Y_LIMIT = 190;
|
|
22
|
+
const KEYBOARD_STEP = 24;
|
|
23
|
+
|
|
24
|
+
type RevealEdge = "top" | "right" | "bottom" | "left";
|
|
25
|
+
|
|
26
|
+
const catPlacement: Record<RevealEdge, string> = {
|
|
27
|
+
top: "items-start justify-center",
|
|
28
|
+
right: "items-center justify-end",
|
|
29
|
+
bottom: "items-end justify-center",
|
|
30
|
+
left: "items-center justify-start",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function clamp(value: number, min: number, max: number) {
|
|
34
|
+
return Math.min(max, Math.max(min, value));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function DraggableReveal({
|
|
38
|
+
children,
|
|
39
|
+
handleClassName = "inset-x-0",
|
|
40
|
+
label = "Movable product preview",
|
|
41
|
+
}: {
|
|
42
|
+
children: ReactNode;
|
|
43
|
+
handleClassName?: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
}) {
|
|
46
|
+
const controls = useDragControls();
|
|
47
|
+
const descriptionId = useId();
|
|
48
|
+
const x = useMotionValue(0);
|
|
49
|
+
const y = useMotionValue(0);
|
|
50
|
+
const [dragging, setDragging] = useState(false);
|
|
51
|
+
const [revealEdge, setRevealEdge] = useState<RevealEdge>("right");
|
|
52
|
+
const [cat] = useState(
|
|
53
|
+
() => cats[Math.floor(Math.random() * cats.length)] ?? cats[0],
|
|
54
|
+
);
|
|
55
|
+
const [mirrored] = useState(() => Math.random() < 0.5);
|
|
56
|
+
|
|
57
|
+
const returnToOrigin = () => {
|
|
58
|
+
const transition = {
|
|
59
|
+
duration: 0.78,
|
|
60
|
+
ease: [0.22, 1, 0.36, 1] as const,
|
|
61
|
+
};
|
|
62
|
+
animate(x, 0, transition);
|
|
63
|
+
animate(y, 0, transition);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
|
|
67
|
+
const moves: Partial<Record<string, [number, number]>> = {
|
|
68
|
+
ArrowLeft: [-KEYBOARD_STEP, 0],
|
|
69
|
+
ArrowRight: [KEYBOARD_STEP, 0],
|
|
70
|
+
ArrowUp: [0, -KEYBOARD_STEP],
|
|
71
|
+
ArrowDown: [0, KEYBOARD_STEP],
|
|
72
|
+
};
|
|
73
|
+
const move = moves[event.key];
|
|
74
|
+
if (move) {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
if (Math.abs(move[0]) > Math.abs(move[1])) {
|
|
77
|
+
setRevealEdge(move[0] < 0 ? "right" : "left");
|
|
78
|
+
} else {
|
|
79
|
+
setRevealEdge(move[1] < 0 ? "bottom" : "top");
|
|
80
|
+
}
|
|
81
|
+
x.set(clamp(x.get() + move[0], -X_LIMIT, X_LIMIT));
|
|
82
|
+
y.set(clamp(y.get() + move[1], -Y_LIMIT, Y_LIMIT));
|
|
83
|
+
} else if (event.key === "Escape") {
|
|
84
|
+
x.set(0);
|
|
85
|
+
y.set(0);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const onDrag = (
|
|
90
|
+
_event: MouseEvent | TouchEvent | PointerEvent,
|
|
91
|
+
info: PanInfo,
|
|
92
|
+
) => {
|
|
93
|
+
if (Math.hypot(info.offset.x, info.offset.y) < 16) return;
|
|
94
|
+
if (Math.abs(info.offset.x) >= Math.abs(info.offset.y)) {
|
|
95
|
+
setRevealEdge(info.offset.x < 0 ? "right" : "left");
|
|
96
|
+
} else {
|
|
97
|
+
setRevealEdge(info.offset.y < 0 ? "bottom" : "top");
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div className="relative isolate">
|
|
103
|
+
<div
|
|
104
|
+
aria-hidden
|
|
105
|
+
className={`pointer-events-none absolute inset-0 z-0 flex ${catPlacement[revealEdge]}`}
|
|
106
|
+
>
|
|
107
|
+
<m.img
|
|
108
|
+
layout="position"
|
|
109
|
+
src={cat}
|
|
110
|
+
alt=""
|
|
111
|
+
width={800}
|
|
112
|
+
height={800}
|
|
113
|
+
decoding="async"
|
|
114
|
+
style={{ scaleX: mirrored ? -1 : 1 }}
|
|
115
|
+
animate={{
|
|
116
|
+
opacity: dragging ? 1 : 0.84,
|
|
117
|
+
scale: dragging ? 1 : 0.96,
|
|
118
|
+
y: dragging ? -3 : 0,
|
|
119
|
+
}}
|
|
120
|
+
transition={{
|
|
121
|
+
layout: { type: "spring", stiffness: 260, damping: 28 },
|
|
122
|
+
opacity: { duration: 0.22 },
|
|
123
|
+
scale: { duration: 0.28 },
|
|
124
|
+
y: { duration: 0.28 },
|
|
125
|
+
}}
|
|
126
|
+
className="max-h-[72%] w-[36%] object-contain drop-shadow-[0_18px_26px_rgba(0,0,0,0.14)]"
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
<span id={descriptionId} className="sr-only">
|
|
130
|
+
Move this preview with the arrow keys. Press Escape to return it to its
|
|
131
|
+
starting position.
|
|
132
|
+
</span>
|
|
133
|
+
<m.div
|
|
134
|
+
drag
|
|
135
|
+
dragControls={controls}
|
|
136
|
+
dragListener={false}
|
|
137
|
+
dragConstraints={{
|
|
138
|
+
left: -X_LIMIT,
|
|
139
|
+
right: X_LIMIT,
|
|
140
|
+
top: -Y_LIMIT,
|
|
141
|
+
bottom: Y_LIMIT,
|
|
142
|
+
}}
|
|
143
|
+
dragElastic={0.08}
|
|
144
|
+
dragMomentum={false}
|
|
145
|
+
style={{ x, y }}
|
|
146
|
+
whileDrag={{ scale: 0.985 }}
|
|
147
|
+
tabIndex={0}
|
|
148
|
+
aria-label={label}
|
|
149
|
+
aria-describedby={descriptionId}
|
|
150
|
+
onKeyDown={onKeyDown}
|
|
151
|
+
onDragStart={() => setDragging(true)}
|
|
152
|
+
onDrag={onDrag}
|
|
153
|
+
onDragEnd={() => {
|
|
154
|
+
setDragging(false);
|
|
155
|
+
window.requestAnimationFrame(returnToOrigin);
|
|
156
|
+
}}
|
|
157
|
+
className="relative z-10 rounded-[18px] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-accent"
|
|
158
|
+
>
|
|
159
|
+
{children}
|
|
160
|
+
<div
|
|
161
|
+
aria-hidden
|
|
162
|
+
className={`absolute top-0 z-20 h-11 cursor-grab touch-none rounded-t-[18px] active:cursor-grabbing ${handleClassName}`}
|
|
163
|
+
onPointerDown={(event) => controls.start(event)}
|
|
164
|
+
/>
|
|
165
|
+
</m.div>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// The tour's first stop: the dependency graph, the real one. Its toolbar,
|
|
2
|
+
// its two modes, its focus and export, on the example estate. Nothing here
|
|
3
|
+
// is a mock-up of the product; it is the product, in a smaller box.
|
|
4
|
+
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
6
|
+
import { catalog } from "../data";
|
|
7
|
+
import { DependencyGraphPane } from "../graph/DependencyGraph";
|
|
8
|
+
import type { GraphMode } from "../graph/dependency-layout";
|
|
9
|
+
import { eventGraph } from "../lib/event-graph";
|
|
10
|
+
import { useSelectionCleared } from "./catalog";
|
|
11
|
+
|
|
12
|
+
export function EstateGraph() {
|
|
13
|
+
const graph = useMemo(() => eventGraph(catalog), []);
|
|
14
|
+
const [mode, setMode] = useState<GraphMode>("compact");
|
|
15
|
+
useSelectionCleared();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className="h-[470px]">
|
|
19
|
+
<DependencyGraphPane
|
|
20
|
+
graph={graph}
|
|
21
|
+
mode={mode}
|
|
22
|
+
onMode={setMode}
|
|
23
|
+
fitKey={mode}
|
|
24
|
+
zoomOnScroll={false}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|