@cloudgrid-io/ui 0.30.0 → 0.31.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 +63 -0
- package/dist/blocks/cloudgrid-install.d.ts +67 -0
- package/dist/blocks/cloudgrid-install.d.ts.map +1 -0
- package/dist/blocks/cloudgrid-install.js +192 -0
- package/dist/blocks/cloudgrid-install.js.map +1 -0
- package/dist/blocks/entity-card.d.ts +81 -24
- package/dist/blocks/entity-card.d.ts.map +1 -1
- package/dist/blocks/entity-card.js +235 -126
- package/dist/blocks/entity-card.js.map +1 -1
- package/dist/blocks/icons.d.ts +10 -1
- package/dist/blocks/icons.d.ts.map +1 -1
- package/dist/blocks/icons.js +10 -1
- package/dist/blocks/icons.js.map +1 -1
- package/dist/blocks/install-content.d.ts +228 -0
- package/dist/blocks/install-content.d.ts.map +1 -0
- package/dist/blocks/install-content.js +464 -0
- package/dist/blocks/install-content.js.map +1 -0
- package/dist/blocks/logo.d.ts +70 -1
- package/dist/blocks/logo.d.ts.map +1 -1
- package/dist/blocks/logo.js +75 -2
- package/dist/blocks/logo.js.map +1 -1
- package/dist/blocks/phosphor-marks.d.ts +2 -0
- package/dist/blocks/phosphor-marks.d.ts.map +1 -1
- package/dist/blocks/phosphor-marks.js +3 -0
- package/dist/blocks/phosphor-marks.js.map +1 -1
- package/dist/blocks/prompt-block.d.ts +13 -5
- package/dist/blocks/prompt-block.d.ts.map +1 -1
- package/dist/blocks/prompt-block.js +16 -7
- package/dist/blocks/prompt-block.js.map +1 -1
- package/dist/blocks/stage-panel.d.ts +19 -0
- package/dist/blocks/stage-panel.d.ts.map +1 -1
- package/dist/blocks/stage-panel.js +2 -4
- package/dist/blocks/stage-panel.js.map +1 -1
- package/dist/blocks/tool-logo.d.ts.map +1 -1
- package/dist/blocks/tool-logo.js +10 -6
- package/dist/blocks/tool-logo.js.map +1 -1
- package/dist/blocks/tool-setup.d.ts +12 -6
- package/dist/blocks/tool-setup.d.ts.map +1 -1
- package/dist/blocks/tool-setup.js.map +1 -1
- package/dist/brand/mark-180.png +0 -0
- package/dist/brand/mark-192.png +0 -0
- package/dist/brand/mark-32.png +0 -0
- package/dist/brand/mark-512.png +0 -0
- package/dist/brand/mark-inverted-180.png +0 -0
- package/dist/brand/mark-inverted-192.png +0 -0
- package/dist/brand/mark-inverted-32.png +0 -0
- package/dist/brand/mark-inverted-512.png +0 -0
- package/dist/brand/mark-inverted.svg +8 -0
- package/dist/brand/mark.svg +7 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -93,6 +93,29 @@ what `text-ink` is doing above. Borders and backgrounds flip on their own. Text
|
|
|
93
93
|
There is no dark mode here, and this is not a substitute for one. Dark surfaces are a
|
|
94
94
|
property of a container, never a page-level theme.
|
|
95
95
|
|
|
96
|
+
## The install panel
|
|
97
|
+
|
|
98
|
+
Every CloudGrid install panel comes from this package, content and design both. Nothing is
|
|
99
|
+
fetched.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { CloudGridInstall, INSTALL_PRESETS, installToolPreset } from "@cloudgrid-io/ui"
|
|
103
|
+
|
|
104
|
+
<CloudGridInstall /> // the whole panel
|
|
105
|
+
<CloudGridInstall preset={INSTALL_PRESETS.onboarding} onValueChange={recordTool} />
|
|
106
|
+
<CloudGridInstall preset={installToolPreset("cursor")} />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
There are no props for the words. A page chooses what is on screen (`tools`, `methods`,
|
|
110
|
+
`defaultTool`, `defaultMethod`, `showFetchPrompt`, `showFooter`, or a `preset`) and what only
|
|
111
|
+
it can know (the selected tool and method, the heading level, a Continue action). Tool values
|
|
112
|
+
are stable identifiers, safe to record: `claude-code`, `cursor`, `codex`, `antigravity`,
|
|
113
|
+
`gemini`, `chatgpt`, `claude-web`.
|
|
114
|
+
|
|
115
|
+
`CloudGridFetchPrompt` and `CloudGridInstallFooter` render on their own. Without React, take the
|
|
116
|
+
strings from `@cloudgrid-io/ui/install-content` (`INSTALL_TOOLS`, `INSTALL_COMMANDS` and the
|
|
117
|
+
rest).
|
|
118
|
+
|
|
96
119
|
## Entry points
|
|
97
120
|
|
|
98
121
|
| | |
|
|
@@ -104,9 +127,49 @@ property of a container, never a page-level theme.
|
|
|
104
127
|
| `@cloudgrid-io/ui/fonts.css` | the three self-hosted families |
|
|
105
128
|
| `@cloudgrid-io/ui/prose.css` | long-form text |
|
|
106
129
|
| `@cloudgrid-io/ui/tokens.json` | the same values, machine-readable |
|
|
130
|
+
| `@cloudgrid-io/ui/install-content` | the install content as plain data, no React |
|
|
107
131
|
|
|
108
132
|
The JSON sets under `tokens/` are DTCG and are the source the CSS is compiled from.
|
|
109
133
|
|
|
134
|
+
## The CloudGrid sign as files
|
|
135
|
+
|
|
136
|
+
The socket glyph in a rounded square, as static files for a browser tab, a home screen or
|
|
137
|
+
a web manifest. Two colourways: `mark` is the brand sign (purple square, white glyph, what
|
|
138
|
+
the site uses) and `mark-inverted` is white with a purple glyph (what the Console's tab uses).
|
|
139
|
+
|
|
140
|
+
| | |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `@cloudgrid-io/ui/brand/mark.svg` | SVG favicon, purple |
|
|
143
|
+
| `@cloudgrid-io/ui/brand/mark-inverted.svg` | SVG favicon, white |
|
|
144
|
+
| `@cloudgrid-io/ui/brand/mark-32.png`, `mark-inverted-32.png` | PNG favicon fallback |
|
|
145
|
+
| `@cloudgrid-io/ui/brand/mark-180.png`, `mark-inverted-180.png` | `apple-touch-icon`, full bleed: iOS rounds it |
|
|
146
|
+
| `@cloudgrid-io/ui/brand/mark-192.png`, `mark-inverted-192.png` | web manifest |
|
|
147
|
+
| `@cloudgrid-io/ui/brand/mark-512.png`, `mark-inverted-512.png` | web manifest |
|
|
148
|
+
|
|
149
|
+
A browser needs a URL, so copy them into your public folder or import them through your
|
|
150
|
+
bundler:
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
// Next.js app router, e.g. app/layout.tsx
|
|
154
|
+
import favicon from "@cloudgrid-io/ui/brand/mark-inverted.svg"
|
|
155
|
+
import appleTouch from "@cloudgrid-io/ui/brand/mark-inverted-180.png"
|
|
156
|
+
|
|
157
|
+
export const metadata = {
|
|
158
|
+
title: "CloudGrid",
|
|
159
|
+
icons: { icon: favicon.src, apple: appleTouch.src },
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<link rel="icon" href="/mark-inverted.svg" type="image/svg+xml">
|
|
165
|
+
<link rel="icon" href="/mark-inverted-32.png" sizes="32x32" type="image/png">
|
|
166
|
+
<link rel="apple-touch-icon" href="/mark-inverted-180.png">
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Inside a page, use the component instead: `<LogoMark tone="inverted" size={32} />`. It draws
|
|
170
|
+
the same glyph from the same constant as `Logo`, and the files are generated from that
|
|
171
|
+
constant and the brand token by `scripts/generate-brand-mark.mjs`, so the three cannot drift.
|
|
172
|
+
|
|
110
173
|
## Versioning
|
|
111
174
|
|
|
112
175
|
Semver. Token value changes are minor; removals are major.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type InstallFilter, type InstallMethodValue, type InstallToolValue } from "./install-content.js";
|
|
3
|
+
import { PageHeading } from "./page-heading.js";
|
|
4
|
+
import { type ToolSetupGroup, type ToolSetupTool } from "./tool-setup.js";
|
|
5
|
+
/**
|
|
6
|
+
* The content's tools as `ToolSetup` takes them, in the order asked for, with
|
|
7
|
+
* every vendor mark and every body rendered.
|
|
8
|
+
*
|
|
9
|
+
* Exported for a page that composes `ToolSetup` itself, which is what the
|
|
10
|
+
* library gallery's `ToolSetup` specimens do. A method missing from `methods`
|
|
11
|
+
* is dropped from each tool, so a tool with nothing left leaves the strip.
|
|
12
|
+
*
|
|
13
|
+
* 15px marks, which is what the strip draws. A mark carries no size of its own,
|
|
14
|
+
* so every call site states one.
|
|
15
|
+
*/
|
|
16
|
+
export declare function installSetupTools(tools?: readonly InstallToolValue[], methods?: readonly InstallMethodValue[]): ToolSetupTool[];
|
|
17
|
+
/** The two runs, each drawn as its glyph and named by its words. */
|
|
18
|
+
export declare function installSetupGroups(): ToolSetupGroup[];
|
|
19
|
+
/**
|
|
20
|
+
* "Not sure? Copy this prompt and paste it to your AI agent." over the one
|
|
21
|
+
* command an agent can act on.
|
|
22
|
+
*
|
|
23
|
+
* The outline pill, as the Console drew it under the panel, so it reads the
|
|
24
|
+
* surface it sits on. `showIntro={false}` is the standalone pill, which is what
|
|
25
|
+
* the old `fetch-prompt` block was.
|
|
26
|
+
*/
|
|
27
|
+
declare function CloudGridFetchPrompt({ showIntro, ...props }: Omit<React.ComponentProps<"div">, "ref" | "children"> & {
|
|
28
|
+
/** The "Not sure?" line over the pill. */
|
|
29
|
+
showIntro?: boolean;
|
|
30
|
+
}): React.JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* The source line: one sentence, then the two repositories.
|
|
33
|
+
*
|
|
34
|
+
* `text-body` and not `text-faint`: faint is large-text-legal only (#232), and
|
|
35
|
+
* this is 15px. Every colour is a token, so it flips on the panel and on ink with
|
|
36
|
+
* the rest of the block; a container that sets `data-cg-surface` still owes its
|
|
37
|
+
* own `text-ink` (rule 3).
|
|
38
|
+
*/
|
|
39
|
+
declare function CloudGridInstallFooter({ className, ...props }: Omit<React.ComponentProps<"footer">, "ref" | "children">): React.JSX.Element;
|
|
40
|
+
declare function CloudGridInstall({ preset, tools, methods, defaultTool, defaultMethod, showFetchPrompt, showFooter, value, onValueChange, method, onMethodChange, level, headingSize, continueLabel, onContinue, canContinue, className, ...props }: Omit<React.ComponentProps<"div">, "ref" | "children" | "defaultValue" | "onChange"> & InstallFilter & {
|
|
41
|
+
/**
|
|
42
|
+
* A named configuration: `INSTALL_PRESETS.hub`, `.onboarding`, `.console`,
|
|
43
|
+
* `.makeGame`, `.makeAppAgent`, `.makeDeckPage`, or `installToolPreset(tool)`.
|
|
44
|
+
* Any filter prop passed alongside overrides that field of it.
|
|
45
|
+
*/
|
|
46
|
+
preset?: InstallFilter;
|
|
47
|
+
/** The selected tool, controlled. Pair with `onValueChange`. */
|
|
48
|
+
value?: InstallToolValue;
|
|
49
|
+
/** Reports the tool on screen, in the content's slugs (`gemini`, `claude-web`). */
|
|
50
|
+
onValueChange?: (value: InstallToolValue) => void;
|
|
51
|
+
/** The selected method, controlled. Pair with `onMethodChange`. */
|
|
52
|
+
method?: InstallMethodValue;
|
|
53
|
+
onMethodChange?: (method: InstallMethodValue) => void;
|
|
54
|
+
/** `2` for a section inside a larger page. */
|
|
55
|
+
level?: 1 | 2;
|
|
56
|
+
headingSize?: React.ComponentProps<typeof PageHeading>["size"];
|
|
57
|
+
/**
|
|
58
|
+
* A Continue button under the panel, for a flow. `null`, the default, draws
|
|
59
|
+
* none: with no handler a button is a dead end, and neither surface that
|
|
60
|
+
* renders this today has anything to continue to from inside it.
|
|
61
|
+
*/
|
|
62
|
+
continueLabel?: string | null;
|
|
63
|
+
onContinue?: () => void;
|
|
64
|
+
canContinue?: boolean;
|
|
65
|
+
}): React.JSX.Element;
|
|
66
|
+
export { CloudGridFetchPrompt, CloudGridInstall, CloudGridInstallFooter };
|
|
67
|
+
//# sourceMappingURL=cloudgrid-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudgrid-install.d.ts","sourceRoot":"","sources":["../../src/blocks/cloudgrid-install.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,OAAO,EAQL,KAAK,aAAa,EAGlB,KAAK,kBAAkB,EAGvB,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAGxD,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAA;AAyGjC;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,GAAE,SAAS,gBAAgB,EAAsC,EACtE,OAAO,GAAE,SAAS,kBAAkB,EAAwC,GAC3E,aAAa,EAAE,CAqBjB;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAMrD;AAED;;;;;;;GAOG;AACH,iBAAS,oBAAoB,CAAC,EAC5B,SAAgB,EAChB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,GAAG;IACzD,0CAA0C;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,qBAWA;AAED;;;;;;;GAOG;AACH,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,qBA0B1D;AAUD,iBAAS,gBAAgB,CAAC,EACxB,MAAM,EACN,KAAK,EACL,OAAO,EACP,WAAW,EACX,aAAa,EACb,eAAe,EACf,UAAU,EACV,KAAK,EACL,aAAa,EACb,MAAM,EACN,cAAc,EACd,KAAS,EACT,WAAW,EACX,aAAoB,EACpB,UAAU,EACV,WAAkB,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,cAAc,GAAG,UAAU,CAAC,GACpF,aAAa,GAAG;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,gEAAgE;IAChE,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,mFAAmF;IACnF,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjD,mEAAmE;IACnE,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;IACrD,8CAA8C;IAC9C,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACb,WAAW,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9D;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,qBAqEF;AAED,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAA"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { AgentPrompt } from "./agent-prompt.js";
|
|
4
|
+
import { Button } from "../ui/button.js";
|
|
5
|
+
import { ChatAppIcon, DownloadIcon, GithubIcon, OpenLiveIcon, TerminalIcon, } from "./icons.js";
|
|
6
|
+
import { INSTALL_FETCH_PROMPT, INSTALL_FOOTER, INSTALL_GROUPS, INSTALL_HEADING, INSTALL_METHODS, INSTALL_PRESETS, INSTALL_TOOLS, } from "./install-content.js";
|
|
7
|
+
import { PageHeading } from "./page-heading.js";
|
|
8
|
+
import { ToolLogo } from "./tool-logo.js";
|
|
9
|
+
import { TOOL_MARKS } from "./tool-marks.js";
|
|
10
|
+
import { ToolSetup, } from "./tool-setup.js";
|
|
11
|
+
import { cn } from "../lib/cloudgrid-cn.js";
|
|
12
|
+
/**
|
|
13
|
+
* THE INSTALL PANEL, COMPLETE. Content and design both from this library (#266).
|
|
14
|
+
*
|
|
15
|
+
* `<CloudGridInstall />` with no props renders the whole thing: the heading, the
|
|
16
|
+
* method pills, the grouped tool strip, every pane, the "Not sure?" fetch prompt
|
|
17
|
+
* and the source footer. Nothing is fetched and nothing is passed in, because the
|
|
18
|
+
* content is `install-content.ts` and ships in the same package.
|
|
19
|
+
*
|
|
20
|
+
* Founder ruling, 2026-10-05: every install panel on every surface takes its
|
|
21
|
+
* content and its design from here. The Console's `/drop` page and onboarding
|
|
22
|
+
* step, and later the landing site, drop this in and choose a configuration.
|
|
23
|
+
*
|
|
24
|
+
* ## Configurations, not content props
|
|
25
|
+
*
|
|
26
|
+
* What a surface MAY choose is which part of the content is on screen: the
|
|
27
|
+
* tools, the methods, the defaults, and whether the fetch prompt and footer show.
|
|
28
|
+
* Pass a named `preset` (`INSTALL_PRESETS.onboarding`, `installToolPreset("cursor")`)
|
|
29
|
+
* and override any field of it with the same-named prop.
|
|
30
|
+
*
|
|
31
|
+
* What a surface may NOT choose is the words. There is no `title`, `sub`, `tools`
|
|
32
|
+
* array or step override, deliberately: a prop that replaces content is a second
|
|
33
|
+
* source of content, and two sources is how the old panel and the library came
|
|
34
|
+
* to say different things about the same setup.
|
|
35
|
+
*
|
|
36
|
+
* ## What a page still passes
|
|
37
|
+
*
|
|
38
|
+
* The things only the page can know. Which tool is selected (`value` /
|
|
39
|
+
* `onValueChange`: onboarding records it as `tool_selected`, in the snapshot's
|
|
40
|
+
* slugs), which method (`method` / `onMethodChange`), the heading's level and
|
|
41
|
+
* size for where it sits, and a Continue action when the panel is a step.
|
|
42
|
+
*
|
|
43
|
+
* ## Not a client module, on purpose
|
|
44
|
+
*
|
|
45
|
+
* Nothing here holds state; `ToolSetup` and `AgentPrompt` carry their own
|
|
46
|
+
* `"use client"`. So a React Server Component can render this with a preset, and
|
|
47
|
+
* the gallery, which is a server module, can call `installSetupTools` below
|
|
48
|
+
* rather than keeping a second copy of the mapping.
|
|
49
|
+
*/
|
|
50
|
+
// Every mark name the content uses is a real key in the vendor-mark set. The
|
|
51
|
+
// content module spells them out so it can stay free of React types; this is the
|
|
52
|
+
// compile-time half of that bargain.
|
|
53
|
+
const MARKS = TOOL_MARKS;
|
|
54
|
+
const ICONS = {
|
|
55
|
+
terminal: TerminalIcon,
|
|
56
|
+
chat: ChatAppIcon,
|
|
57
|
+
github: GithubIcon,
|
|
58
|
+
download: DownloadIcon,
|
|
59
|
+
external: OpenLiveIcon,
|
|
60
|
+
};
|
|
61
|
+
function Glyph({ icon, className }) {
|
|
62
|
+
const Mark = ICONS[icon];
|
|
63
|
+
return _jsx(Mark, { className: className });
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Body runs to nodes. A bold run is a menu path or a folder and reads at medium
|
|
67
|
+
* weight in the ink colour; a code run is a command typed inline and reads in
|
|
68
|
+
* the mono face at the size around it. Both are tokens, so both flip per surface.
|
|
69
|
+
*/
|
|
70
|
+
function Body({ runs }) {
|
|
71
|
+
return (_jsx(_Fragment, { children: runs.map((run, i) => typeof run === "string" ? (_jsx(React.Fragment, { children: run }, i)) : "bold" in run ? (_jsx("b", { className: "font-medium text-ink", children: run.bold }, i)) : (_jsx("code", { "data-slot": "cloudgrid-install-code", className: "font-mono text-ink", children: run.code }, i))) }));
|
|
72
|
+
}
|
|
73
|
+
function toSetupStep(step) {
|
|
74
|
+
return {
|
|
75
|
+
...(step.label ? { label: step.label } : {}),
|
|
76
|
+
title: step.title,
|
|
77
|
+
...(step.body ? { body: _jsx(Body, { runs: step.body }) } : {}),
|
|
78
|
+
...(step.prompt ? { prompt: step.prompt } : {}),
|
|
79
|
+
...(step.code ? { code: step.code } : {}),
|
|
80
|
+
...(step.link
|
|
81
|
+
? {
|
|
82
|
+
link: {
|
|
83
|
+
label: step.link.label,
|
|
84
|
+
href: step.link.href,
|
|
85
|
+
...(step.link.icon ? { icon: _jsx(Glyph, { icon: step.link.icon }) } : {}),
|
|
86
|
+
...(step.link.primary ? { primary: true } : {}),
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
: {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The content's tools as `ToolSetup` takes them, in the order asked for, with
|
|
94
|
+
* every vendor mark and every body rendered.
|
|
95
|
+
*
|
|
96
|
+
* Exported for a page that composes `ToolSetup` itself, which is what the
|
|
97
|
+
* library gallery's `ToolSetup` specimens do. A method missing from `methods`
|
|
98
|
+
* is dropped from each tool, so a tool with nothing left leaves the strip.
|
|
99
|
+
*
|
|
100
|
+
* 15px marks, which is what the strip draws. A mark carries no size of its own,
|
|
101
|
+
* so every call site states one.
|
|
102
|
+
*/
|
|
103
|
+
export function installSetupTools(tools = INSTALL_TOOLS.map((t) => t.value), methods = INSTALL_METHODS.map((m) => m.value)) {
|
|
104
|
+
return tools.flatMap((value) => {
|
|
105
|
+
const tool = INSTALL_TOOLS.find((t) => t.value === value);
|
|
106
|
+
if (!tool)
|
|
107
|
+
return [];
|
|
108
|
+
const steps = {};
|
|
109
|
+
for (const method of methods) {
|
|
110
|
+
const pane = tool.steps[method];
|
|
111
|
+
if (pane?.length)
|
|
112
|
+
steps[method] = pane.map(toSetupStep);
|
|
113
|
+
}
|
|
114
|
+
if (Object.keys(steps).length === 0)
|
|
115
|
+
return [];
|
|
116
|
+
const { Mark, hex } = MARKS[tool.mark];
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
value: tool.value,
|
|
120
|
+
label: tool.label,
|
|
121
|
+
group: tool.group,
|
|
122
|
+
mark: _jsx(ToolLogo, { name: tool.mark, hex: hex, mark: _jsx(Mark, {}), size: 15 }),
|
|
123
|
+
steps,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/** The two runs, each drawn as its glyph and named by its words. */
|
|
129
|
+
export function installSetupGroups() {
|
|
130
|
+
return INSTALL_GROUPS.map((group) => ({
|
|
131
|
+
value: group.value,
|
|
132
|
+
label: group.label,
|
|
133
|
+
icon: _jsx(Glyph, { icon: group.icon }),
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* "Not sure? Copy this prompt and paste it to your AI agent." over the one
|
|
138
|
+
* command an agent can act on.
|
|
139
|
+
*
|
|
140
|
+
* The outline pill, as the Console drew it under the panel, so it reads the
|
|
141
|
+
* surface it sits on. `showIntro={false}` is the standalone pill, which is what
|
|
142
|
+
* the old `fetch-prompt` block was.
|
|
143
|
+
*/
|
|
144
|
+
function CloudGridFetchPrompt({ showIntro = true, ...props }) {
|
|
145
|
+
return (_jsx(AgentPrompt, { "data-part": "cloudgrid-fetch-prompt", variant: "outline", ...(showIntro ? { label: INSTALL_FETCH_PROMPT.intro } : {}), command: INSTALL_FETCH_PROMPT.command, copyLabel: "Copy fetch prompt", ...props }));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The source line: one sentence, then the two repositories.
|
|
149
|
+
*
|
|
150
|
+
* `text-body` and not `text-faint`: faint is large-text-legal only (#232), and
|
|
151
|
+
* this is 15px. Every colour is a token, so it flips on the panel and on ink with
|
|
152
|
+
* the rest of the block; a container that sets `data-cg-surface` still owes its
|
|
153
|
+
* own `text-ink` (rule 3).
|
|
154
|
+
*/
|
|
155
|
+
function CloudGridInstallFooter({ className, ...props }) {
|
|
156
|
+
return (_jsxs("footer", { "data-slot": "cloudgrid-install-footer", className: cn("flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-body-sm text-body", className), ...props, children: [_jsx("span", { children: INSTALL_FOOTER.note }), INSTALL_FOOTER.links.map((link) => (_jsxs("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "data-slot": "cloudgrid-install-footer-link", className: "inline-flex items-center gap-1.5 text-body underline underline-offset-4 hover:text-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", children: [link.icon ? _jsx(Glyph, { icon: link.icon, className: "size-4 shrink-0" }) : null, link.label] }, link.href)))] }));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Keep the caller's order and drop what does not exist, so a preset naming a
|
|
160
|
+
* method or tool this content does not have cannot put an empty tab on screen.
|
|
161
|
+
*/
|
|
162
|
+
function known(asked, all) {
|
|
163
|
+
return asked ? asked.filter((v) => all.includes(v)) : [...all];
|
|
164
|
+
}
|
|
165
|
+
function CloudGridInstall({ preset, tools, methods, defaultTool, defaultMethod, showFetchPrompt, showFooter, value, onValueChange, method, onMethodChange, level = 1, headingSize, continueLabel = null, onContinue, canContinue = true, className, ...props }) {
|
|
166
|
+
const base = { ...INSTALL_PRESETS.hub, ...preset };
|
|
167
|
+
const toolValues = known(tools ?? base.tools, INSTALL_TOOLS.map((t) => t.value));
|
|
168
|
+
const methodValues = known(methods ?? base.methods, INSTALL_METHODS.map((m) => m.value));
|
|
169
|
+
const withFetchPrompt = showFetchPrompt ?? base.showFetchPrompt ?? true;
|
|
170
|
+
const withFooter = showFooter ?? base.showFooter ?? true;
|
|
171
|
+
const setupTools = installSetupTools(toolValues, methodValues);
|
|
172
|
+
// A default the filter has removed is dropped rather than passed on. Handed
|
|
173
|
+
// through, `ToolSetup` would fall back to the first tab AND report that
|
|
174
|
+
// fallback, which would reach an analytics handler as a selection nobody made.
|
|
175
|
+
const askedTool = defaultTool ?? base.defaultTool;
|
|
176
|
+
const firstTool = setupTools.some((t) => t.value === askedTool) ? askedTool : undefined;
|
|
177
|
+
const askedMethod = defaultMethod ?? base.defaultMethod;
|
|
178
|
+
const firstMethod = askedMethod && methodValues.includes(askedMethod) ? askedMethod : undefined;
|
|
179
|
+
const setupMethods = INSTALL_METHODS.filter((m) => methodValues.includes(m.value))
|
|
180
|
+
// The caller's order, not the content's.
|
|
181
|
+
.sort((a, b) => methodValues.indexOf(a.value) - methodValues.indexOf(b.value));
|
|
182
|
+
return (_jsxs("div", { "data-slot": "cloudgrid-install", className: cn("flex flex-col gap-6", className), ...props, children: [_jsx(ToolSetup, { title: INSTALL_HEADING.title, sub: INSTALL_HEADING.sub, level: level, ...(headingSize ? { headingSize } : {}), tools: setupTools, methods: setupMethods, groups: installSetupGroups(), ...(value !== undefined ? { value } : {}), ...(firstTool ? { defaultValue: firstTool } : {}), ...(onValueChange
|
|
183
|
+
? { onValueChange: (next) => onValueChange(next) }
|
|
184
|
+
: {}), ...(method !== undefined ? { method } : {}), ...(firstMethod ? { defaultMethod: firstMethod } : {}), ...(onMethodChange
|
|
185
|
+
? { onMethodChange: (next) => onMethodChange(next) }
|
|
186
|
+
: {}),
|
|
187
|
+
// The panel's own action row sits under the fetch prompt and the footer,
|
|
188
|
+
// below, so the step's primary action is the last thing on it.
|
|
189
|
+
continueLabel: null }), withFetchPrompt ? _jsx(CloudGridFetchPrompt, {}) : null, withFooter ? _jsx(CloudGridInstallFooter, {}) : null, continueLabel !== null ? (_jsx("div", { "data-slot": "cloudgrid-install-actions", className: "flex flex-col items-start gap-4", children: _jsx(Button, { type: "button", size: "lg", "data-slot": "cloudgrid-install-continue", onClick: onContinue, disabled: !canContinue, children: continueLabel }) })) : null] }));
|
|
190
|
+
}
|
|
191
|
+
export { CloudGridFetchPrompt, CloudGridInstall, CloudGridInstallFooter };
|
|
192
|
+
//# sourceMappingURL=cloudgrid-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudgrid-install.js","sourceRoot":"","sources":["../../src/blocks/cloudgrid-install.tsx"],"names":[],"mappings":"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"}
|
|
@@ -140,10 +140,29 @@ import * as React from "react";
|
|
|
140
140
|
* an `sr-only` span, because "agent" is information and a decorative mark is not
|
|
141
141
|
* a way to convey it.
|
|
142
142
|
*
|
|
143
|
+
* ## A click opens the details page (#268)
|
|
144
|
+
*
|
|
145
|
+
* Founder, 2026-10-05: *clicking an app card on any page opens the app's page
|
|
146
|
+
* in the console*, not the live app. So when `dashboardHref` is set, the
|
|
147
|
+
* DETAILS link owns the card's one stretched hit area — the whole card,
|
|
148
|
+
* thumbnail included — whether or not the entity is live, and the live link is
|
|
149
|
+
* the small secondary arrow, still `target="_blank"`, named "Open live app".
|
|
150
|
+
* The details link is named "Details" and wears `EntityDetailsIcon`
|
|
151
|
+
* (`list-magnifying-glass`); it renders through `linkComponent` when one is
|
|
152
|
+
* passed, so a router can navigate client-side.
|
|
153
|
+
*
|
|
154
|
+
* Two things did not change. With no `dashboardHref` the live link owns the
|
|
155
|
+
* click as it always did, and `primaryAction="live"` restores the whole
|
|
156
|
+
* pre-#268 model for a consumer that wants it. Much of the history below
|
|
157
|
+
* describes the live link as "Open" and the details link as "Dashboard"; those
|
|
158
|
+
* are the same two doors under their old names, and every rule about them — the
|
|
159
|
+
* new tab, the `rel`, the #171 gating of whichever door is secondary, the #193
|
|
160
|
+
* disabled state — carries over unchanged.
|
|
161
|
+
*
|
|
143
162
|
* ## The panel, and the rule it supersedes
|
|
144
163
|
*
|
|
145
164
|
* `reveal` puts a WHITE panel over the bottom of the card carrying the title,
|
|
146
|
-
* the state dot, two real links (
|
|
165
|
+
* the state dot, two real links (details and live), the description, the
|
|
147
166
|
* creator and the card's own controls. It shows on hover and on `:focus-within`,
|
|
148
167
|
* and it respects `prefers-reduced-motion` by arriving without the fade rather
|
|
149
168
|
* than not at all.
|
|
@@ -154,16 +173,18 @@ import * as React from "react";
|
|
|
154
173
|
* laid over the lower half of the picture, the type is the page's own ink, and
|
|
155
174
|
* the picture above it stays a picture.
|
|
156
175
|
*
|
|
157
|
-
* **The
|
|
176
|
+
* **The details action is not a gear.** Founder direction
|
|
158
177
|
* 2026-09-08 (#182). The door it opens is the entity's page in the console,
|
|
159
178
|
* which shows analytics and what runs under the hood — so what it promises is
|
|
160
179
|
* "look inside", and a gear promises "change how this is configured". Those are
|
|
161
180
|
* different pages and a reader who takes one for the other has been misled by
|
|
162
|
-
* the icon rather than by the label. The mark
|
|
181
|
+
* the icon rather than by the label. The mark was `EntityDashboardIcon`
|
|
163
182
|
* (Phosphor `chart-line-up` since #221 — `gauge` at #182, `engine` at #200, and
|
|
164
183
|
* each was unpicked by looking at it: a dial reads as a speed, an engine reads
|
|
165
|
-
* as machinery, and neither is the number a person opened the page for)
|
|
166
|
-
*
|
|
184
|
+
* as machinery, and neither is the number a person opened the page for), and
|
|
185
|
+
* since #268 it is `EntityDetailsIcon`, a list under a lens, because the page
|
|
186
|
+
* is findings rather than a chart. `SettingsIcon` is still exported for the
|
|
187
|
+
* surfaces that really are settings.
|
|
167
188
|
*
|
|
168
189
|
* The prop is `dashboardHref`. `settingsHref` is kept as a deprecated alias for
|
|
169
190
|
* this minor and maps straight to it, so no caller breaks on the rename — see
|
|
@@ -233,19 +254,23 @@ import * as React from "react";
|
|
|
233
254
|
* instead of on a wrapper, because an `<a>` inside an `<a>` is invalid HTML and
|
|
234
255
|
* browsers repair it by closing the outer one — which silently unlinks the card
|
|
235
256
|
* and leaves the actions where the parser decides to put them. The panel is the
|
|
236
|
-
* link surface instead:
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* reveal
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
257
|
+
* link surface instead: the door that owns the click (details since #268,
|
|
258
|
+
* live without a `dashboardHref`) stretches across the whole card with an
|
|
259
|
+
* `::after`, and the other door sits above it. Until #268 that stretch covered
|
|
260
|
+
* only the panel, so the top of the thumbnail was dead; the panel now sits in a
|
|
261
|
+
* transparent full-card layer, which is what the stretch sizes to. Every
|
|
262
|
+
* existing caller is unaffected — `reveal` defaults off and the wrapper behaves
|
|
263
|
+
* exactly as it did. (With no `href` at all, the live link is disabled — see
|
|
264
|
+
* "The reveal never depends on data" below.)
|
|
265
|
+
*
|
|
266
|
+
* **The panel stays clickable while it is invisible — except the secondary
|
|
267
|
+
* door.** `opacity-0` is a paint state, not a pointer state, so a touch user
|
|
268
|
+
* with no hover at all still gets the card's door by tapping the thumbnail.
|
|
269
|
+
* Gating the stretched link's pointer events on hover would make the card do
|
|
270
|
+
* nothing on a phone.
|
|
271
|
+
*
|
|
272
|
+
* The secondary door (Dashboard, below, before #268; the live arrow since) is
|
|
273
|
+
* the one exception, and it has to be. It is `relative`, so it
|
|
249
274
|
* stacks above Open's stretched hit area; live at rest, that made a pill-sized
|
|
250
275
|
* region of an invisible panel go to that link on a tap — different from every
|
|
251
276
|
* pixel around it, and impossible to see (#171). So it carries
|
|
@@ -445,7 +470,7 @@ declare function EntityKindBadge({ kind, size, className, ...props }: Omit<React
|
|
|
445
470
|
kind: EntityKind;
|
|
446
471
|
size?: "sm" | "md";
|
|
447
472
|
}): React.JSX.Element;
|
|
448
|
-
declare function EntityCard({ title, slug, description, size, titleLines, descriptionLines, status, statusDot, headerActions, stats, seed, previewUrl, kind, reveal, openDisabledReason, dashboardHref, settingsHref, creator, panelMeta, href, ariaLabel, meta, footer, className, children, ...props }: Omit<React.ComponentProps<"div">, "ref" | "title"> & {
|
|
473
|
+
declare function EntityCard({ title, slug, description, size, titleLines, descriptionLines, status, statusDot, headerActions, stats, seed, previewUrl, kind, reveal, openDisabledReason, dashboardHref, settingsHref, primaryAction, linkComponent, creator, panelMeta, href, ariaLabel, meta, footer, className, children, ...props }: Omit<React.ComponentProps<"div">, "ref" | "title"> & {
|
|
449
474
|
title: string;
|
|
450
475
|
/** The entity's address, in the mono utility face. */
|
|
451
476
|
slug?: string;
|
|
@@ -551,13 +576,17 @@ declare function EntityCard({ title, slug, description, size, titleLines, descri
|
|
|
551
576
|
*/
|
|
552
577
|
openDisabledReason?: React.ReactNode;
|
|
553
578
|
/**
|
|
554
|
-
* The
|
|
555
|
-
*
|
|
579
|
+
* The details action's target: the entity's page in the console — Overview,
|
|
580
|
+
* insights, and what runs under the hood.
|
|
581
|
+
*
|
|
582
|
+
* Since #268 this is the card's CLICK. When it is set, the details link owns
|
|
583
|
+
* the stretched hit area, so a click or tap anywhere on the card, thumbnail
|
|
584
|
+
* included, goes here; the live entity becomes the small secondary icon. See
|
|
585
|
+
* `primaryAction` for the one way to keep the old live-first behaviour.
|
|
556
586
|
*
|
|
557
587
|
* Read wherever the action pair renders — the panel on a stacked card, the end
|
|
558
|
-
* of the cluster on a `row` (#182).
|
|
559
|
-
*
|
|
560
|
-
* takes the stretched hit area (#193).
|
|
588
|
+
* of the cluster on a `row` (#182). The prop keeps its #182 name: renaming it
|
|
589
|
+
* would break every caller for a word, and what it points at did not move.
|
|
561
590
|
*/
|
|
562
591
|
dashboardHref?: string;
|
|
563
592
|
/**
|
|
@@ -569,6 +598,34 @@ declare function EntityCard({ title, slug, description, size, titleLines, descri
|
|
|
569
598
|
* next major; the fix is one word at each call site.
|
|
570
599
|
*/
|
|
571
600
|
settingsHref?: string;
|
|
601
|
+
/**
|
|
602
|
+
* Which door the card's click opens. `"details"` by default (#268, founder
|
|
603
|
+
* 2026-10-05): a click on an entity card opens its page in the console, and
|
|
604
|
+
* the live entity is the secondary icon, still opening in a new tab.
|
|
605
|
+
*
|
|
606
|
+
* `"live"` restores the pre-#268 model for a consumer that needs it: the live
|
|
607
|
+
* link owns the stretched hit area and the details link is the lifted
|
|
608
|
+
* secondary. The console does not pass it.
|
|
609
|
+
*
|
|
610
|
+
* Only a preference between two doors that both exist. With no
|
|
611
|
+
* `dashboardHref` the live link owns the click whatever this says, and with
|
|
612
|
+
* no `href` the details link does (#193), because a card's one stretched
|
|
613
|
+
* layer always belongs to a door that can be opened.
|
|
614
|
+
*/
|
|
615
|
+
primaryAction?: "details" | "live";
|
|
616
|
+
/**
|
|
617
|
+
* The element the DETAILS link renders as. A plain `<a>` by default.
|
|
618
|
+
*
|
|
619
|
+
* Pass your router's link — Next's `Link`, for the console — so a card click
|
|
620
|
+
* navigates client-side instead of reloading the page. It receives `href`,
|
|
621
|
+
* `className`, `data-*` attributes and children, which is the anchor subset
|
|
622
|
+
* every router link forwards to the `<a>` it renders.
|
|
623
|
+
*
|
|
624
|
+
* Only the details link. The live link stays a plain `<a target="_blank">`:
|
|
625
|
+
* it leaves for a tenant's own app in a new tab, which no client router can
|
|
626
|
+
* or should handle.
|
|
627
|
+
*/
|
|
628
|
+
linkComponent?: React.ElementType;
|
|
572
629
|
/**
|
|
573
630
|
* Who made it, shown on the reveal panel. `avatar` is a node so a consumer can
|
|
574
631
|
* pass its own image, initials tile or `EntityIdentity`; this card does not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-card.d.ts","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgB9B
|
|
1
|
+
{"version":3,"file":"entity-card.d.ts","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":"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"}
|