@cloudgrid-io/ui 0.18.1 → 0.20.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/dist/blocks/compare-table.d.ts.map +1 -1
- package/dist/blocks/compare-table.js +10 -8
- package/dist/blocks/compare-table.js.map +1 -1
- package/dist/blocks/drop-zone.js +2 -2
- package/dist/blocks/drop-zone.js.map +1 -1
- package/dist/blocks/entity-card.d.ts +190 -13
- package/dist/blocks/entity-card.d.ts.map +1 -1
- package/dist/blocks/entity-card.js +223 -52
- package/dist/blocks/entity-card.js.map +1 -1
- package/dist/blocks/eyebrow.d.ts +43 -0
- package/dist/blocks/eyebrow.d.ts.map +1 -0
- package/dist/blocks/eyebrow.js +53 -0
- package/dist/blocks/eyebrow.js.map +1 -0
- package/dist/blocks/feature-cells.d.ts +12 -7
- package/dist/blocks/feature-cells.d.ts.map +1 -1
- package/dist/blocks/feature-cells.js +11 -11
- package/dist/blocks/feature-cells.js.map +1 -1
- package/dist/blocks/icons.d.ts +68 -10
- package/dist/blocks/icons.d.ts.map +1 -1
- package/dist/blocks/icons.js +68 -10
- package/dist/blocks/icons.js.map +1 -1
- package/dist/blocks/onboarding-question.js +2 -2
- package/dist/blocks/onboarding-question.js.map +1 -1
- package/dist/blocks/page-heading.d.ts +5 -0
- package/dist/blocks/page-heading.d.ts.map +1 -1
- package/dist/blocks/page-heading.js +7 -1
- package/dist/blocks/page-heading.js.map +1 -1
- package/dist/blocks/phosphor-marks.d.ts +99 -22
- package/dist/blocks/phosphor-marks.d.ts.map +1 -1
- package/dist/blocks/phosphor-marks.js +155 -25
- package/dist/blocks/phosphor-marks.js.map +1 -1
- package/dist/blocks/pricing-tier-cards.d.ts +6 -3
- package/dist/blocks/pricing-tier-cards.d.ts.map +1 -1
- package/dist/blocks/pricing-tier-cards.js +2 -2
- package/dist/blocks/pricing-tier-cards.js.map +1 -1
- package/dist/blocks/token-specimen.d.ts +59 -0
- package/dist/blocks/token-specimen.d.ts.map +1 -0
- package/dist/blocks/token-specimen.js +61 -0
- package/dist/blocks/token-specimen.js.map +1 -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/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +2 -2
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/button.d.ts +1 -1
- package/dist/ui/checkbox.d.ts.map +1 -1
- package/dist/ui/checkbox.js +2 -2
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/code-block.js +1 -1
- package/dist/ui/code-block.js.map +1 -1
- package/dist/ui/combobox.js +3 -3
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +2 -2
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +1 -1
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/number-field.js +1 -1
- package/dist/ui/number-field.js.map +1 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +1 -1
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sonner.js +5 -5
- package/dist/ui/sonner.js.map +1 -1
- package/package.json +1 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Card } from "../ui/card.js";
|
|
3
3
|
import { EntityIdentity } from "./entity-identity.js";
|
|
4
|
-
import { KindAgentIcon, KindAppIcon, KindInspirationIcon, OpenLiveIcon,
|
|
4
|
+
import { EntityDashboardIcon, KindAgentIcon, KindAppIcon, KindInspirationIcon, OpenLiveIcon, } from "./icons.js";
|
|
5
5
|
import { cn } from "../lib/cloudgrid-cn.js";
|
|
6
6
|
/**
|
|
7
7
|
* What an entity IS. Three kinds, and they are the product's, not this file's:
|
|
@@ -34,6 +34,75 @@ export const ENTITY_KIND_LABEL = {
|
|
|
34
34
|
inspiration: "Inspiration",
|
|
35
35
|
app: "App",
|
|
36
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* The sizes, in the order they get smaller. Read from the console census
|
|
39
|
+
* (2026-09-08) rather than invented: `default` is the 360px track, `compact`
|
|
40
|
+
* covers the 260 and 280 ones, `row` is the list surfaces, the rails and the
|
|
41
|
+
* sidebar.
|
|
42
|
+
*
|
|
43
|
+
* The array is the source and the type is derived from it, the same arrangement
|
|
44
|
+
* `ENTITY_KIND_ORDER` uses: a size added here is immediately missing from
|
|
45
|
+
* `SIZE_STYLE` and typecheck says so.
|
|
46
|
+
*/
|
|
47
|
+
export const ENTITY_CARD_SIZE_ORDER = ["default", "compact", "row"];
|
|
48
|
+
/**
|
|
49
|
+
* WHAT EACH SIZE CHANGES, in one table.
|
|
50
|
+
*
|
|
51
|
+
* Every entry is a type or spacing utility, never a colour: a size is a
|
|
52
|
+
* measurement, and a card that changed hue when it got smaller would be a
|
|
53
|
+
* second design rather than the same one at another scale. That is also what
|
|
54
|
+
* keeps the literals gate honest here — there is nothing in this table a token
|
|
55
|
+
* does not already own.
|
|
56
|
+
*
|
|
57
|
+
* It is a table rather than a run of ternaries at the call sites because the
|
|
58
|
+
* whole point of the axis is that the sizes stay comparable. Three ternaries in
|
|
59
|
+
* three places is how one of them silently stops matching the other two.
|
|
60
|
+
*
|
|
61
|
+
* `row` builds its own composition below, so its `stats`, `reveal` and
|
|
62
|
+
* `revealTitle` entries are empty: a row has no stat rule and no reveal panel.
|
|
63
|
+
* They are present rather than omitted so the record stays total and a fourth
|
|
64
|
+
* size cannot be half-added.
|
|
65
|
+
*/
|
|
66
|
+
const SIZE_STYLE = {
|
|
67
|
+
default: {
|
|
68
|
+
cardSpacing: "",
|
|
69
|
+
body: "gap-3",
|
|
70
|
+
title: "text-body-sm",
|
|
71
|
+
description: "text-body-sm",
|
|
72
|
+
stats: "gap-4 pt-3",
|
|
73
|
+
reveal: "gap-1.5 p-3",
|
|
74
|
+
revealTitle: "text-body-sm",
|
|
75
|
+
},
|
|
76
|
+
compact: {
|
|
77
|
+
cardSpacing: "[--card-spacing:--spacing(3)]",
|
|
78
|
+
body: "gap-2",
|
|
79
|
+
title: "text-caption",
|
|
80
|
+
description: "text-caption",
|
|
81
|
+
stats: "gap-3 pt-2",
|
|
82
|
+
reveal: "gap-1 p-2",
|
|
83
|
+
revealTitle: "text-caption",
|
|
84
|
+
},
|
|
85
|
+
row: {
|
|
86
|
+
cardSpacing: "[--card-spacing:--spacing(3)]",
|
|
87
|
+
body: "gap-0.5",
|
|
88
|
+
title: "text-body-sm",
|
|
89
|
+
description: "text-caption",
|
|
90
|
+
stats: "",
|
|
91
|
+
reveal: "",
|
|
92
|
+
revealTitle: "",
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The row thumbnail's width. Fixed rather than a fraction, so every row in a
|
|
97
|
+
* list starts its text at the same x — which is what makes a list of these
|
|
98
|
+
* scannable, and what a percentage width would lose the moment the column
|
|
99
|
+
* resized.
|
|
100
|
+
*
|
|
101
|
+
* 128px against the 1200/630 ratio is a 67px picture, so a row is a little over
|
|
102
|
+
* 90px tall with its padding. A 28px kind badge would cover a fifth of that
|
|
103
|
+
* thumbnail, which is why the row uses the small one.
|
|
104
|
+
*/
|
|
105
|
+
const ROW_THUMBNAIL = "w-32";
|
|
37
106
|
/**
|
|
38
107
|
* Make a caller's URL safe to sit inside a CSS `url("…")` string — and nothing
|
|
39
108
|
* more than that.
|
|
@@ -95,16 +164,159 @@ function EntityKindBadge({ kind, size = "md", className, ...props }) {
|
|
|
95
164
|
border: "1px solid color-mix(in srgb, var(--cg-ink) 12%, transparent)",
|
|
96
165
|
}, ...props, children: [_jsx(Icon, { className: size === "md" ? "size-4" : "size-3.5" }), _jsx("span", { className: "sr-only", children: ENTITY_KIND_LABEL[kind] })] }));
|
|
97
166
|
}
|
|
98
|
-
function EntityCard({ title, slug, description, titleLines = 2, descriptionLines = 1, status, stats, seed, previewUrl, kind, reveal = false, settingsHref, creator, href, ariaLabel, meta, footer, className, children, ...props }) {
|
|
167
|
+
function EntityCard({ title, slug, description, size = "default", titleLines = 2, descriptionLines = 1, status, headerActions, stats, seed, previewUrl, kind, reveal = false, dashboardHref, settingsHref, creator, href, ariaLabel, meta, footer, className, children, ...props }) {
|
|
168
|
+
const sized = SIZE_STYLE[size];
|
|
99
169
|
// The reveal owns the preview and spends the `href`, so it only exists when
|
|
100
170
|
// both are there. Asked for without a `seed` it would be a panel over nothing;
|
|
101
171
|
// asked for without an `href` its Open action would be an anchor with no
|
|
102
172
|
// target, which renders as a link, is not focusable, and does nothing when
|
|
103
173
|
// clicked. Silently off in both cases rather than half-built.
|
|
104
|
-
|
|
174
|
+
//
|
|
175
|
+
// A `row` never reveals, whatever the caller passed. Not a limitation: the row
|
|
176
|
+
// already shows everything the panel carries, so there is nothing to reveal —
|
|
177
|
+
// see the size note at the top. Its two actions are rendered at the end of the
|
|
178
|
+
// row and appear on hover, which is the half of the behaviour that survives.
|
|
179
|
+
const revealed = reveal && Boolean(seed) && Boolean(href) && size !== "row";
|
|
180
|
+
// One target, two prop names, for one minor. `settingsHref` is the old name
|
|
181
|
+
// (#182 renamed the action to Dashboard, because the console page it opens is
|
|
182
|
+
// a dashboard and not a settings screen), and it is resolved here rather than
|
|
183
|
+
// at the render site so there is exactly one place the alias exists and one
|
|
184
|
+
// place to delete when it goes. `??`, not `||`: an empty string is a caller
|
|
185
|
+
// saying "no target", and coalescing it to the deprecated name would resurrect
|
|
186
|
+
// a link the caller had switched off.
|
|
187
|
+
const dashboardTarget = dashboardHref ?? settingsHref;
|
|
188
|
+
// Compact keeps the stat ROW and shows one stat in it, rather than dropping
|
|
189
|
+
// the row. The row is a hairline plus a number, and a listing where some cards
|
|
190
|
+
// carry it and some do not has two card heights in one grid. Which stat
|
|
191
|
+
// survives is the caller's order, not a rule here: a card that reordered its
|
|
192
|
+
// caller's stats would be deciding which one matters.
|
|
193
|
+
const shownStats = stats && size === "compact" ? stats.slice(0, 1) : stats;
|
|
194
|
+
// One line on compact and on row, whatever the caller asked for. See the note
|
|
195
|
+
// on the prop: this is a height rule, not a preference.
|
|
196
|
+
const clampDescription = size === "default" && descriptionLines === 2 ? "line-clamp-2" : "truncate";
|
|
197
|
+
/**
|
|
198
|
+
* THE TWO ACTIONS. One pair, written once, used by the reveal panel and by the
|
|
199
|
+
* row alike — because #182's premise is that every entity card offers the same
|
|
200
|
+
* two doors, and two copies of a pair is how one of them quietly grows a third.
|
|
201
|
+
*
|
|
202
|
+
* Both halves of the hit model travel with them, and both are load-bearing:
|
|
203
|
+
*
|
|
204
|
+
* Open carries `after:absolute after:inset-0`, which stretches it over its
|
|
205
|
+
* nearest POSITIONED ancestor. That is the reveal panel on a media card (the
|
|
206
|
+
* panel is `absolute`) and the card itself on a row (which declares `relative`
|
|
207
|
+
* for exactly this). Either way a click anywhere on the card opens the entity,
|
|
208
|
+
* including on a phone where nothing ever hovers. The anchor itself must not
|
|
209
|
+
* be positioned or the stretched layer would size to the pill.
|
|
210
|
+
*
|
|
211
|
+
* Dashboard is `relative`, which lifts it above that stretched layer — and
|
|
212
|
+
* because it is lifted it must not be live while it is invisible.
|
|
213
|
+
* `opacity-0` is a paint state, not a pointer state, so at rest the pill was
|
|
214
|
+
* a region of the card that went somewhere different from every pixel around
|
|
215
|
+
* it, with nothing to see (#171). `pointer-events-none` until hover or
|
|
216
|
+
* focus-within, and Open's overlay untouched, is the whole fix.
|
|
217
|
+
*/
|
|
218
|
+
const actionPair = (_jsxs(_Fragment, { children: [_jsxs("a", { href: href, "data-slot": "entity-card-open", className: "inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline after:absolute after:inset-0 after:content-[''] focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(OpenLiveIcon, { className: "size-3.5" }), "Open"] }), dashboardTarget ? (_jsxs("a", { href: dashboardTarget, "data-slot": "entity-card-dashboard", className: "pointer-events-none relative inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline group-hover/card:pointer-events-auto group-focus-within/card:pointer-events-auto focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(EntityDashboardIcon, { className: "size-3.5" }), "Dashboard"] })) : null] }));
|
|
105
219
|
const body = children ??
|
|
106
|
-
(_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block
|
|
107
|
-
|
|
220
|
+
(_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block font-medium break-words text-ink", sized.title, titleLines === 1 ? "truncate" : "line-clamp-2"), children: [kind && !seed ? (_jsx(EntityKindBadge, { kind: kind, size: "sm", className: "mr-1.5 align-[-0.2em]" })) : null, title] }), slug ? (_jsx("span", { dir: "auto", "data-slot": "entity-card-slug", title: slug, className: "mt-0.5 block truncate font-mono text-caption text-faint", children: slug })) : null] }), status ? _jsx("div", { className: "shrink-0", children: status }) : null, headerActions ? (_jsx("div", { "data-slot": "entity-card-actions",
|
|
221
|
+
// items-center against the title's first line, and -mt-1 to pull an
|
|
222
|
+
// icon button's own padding back so the glyph optically lines up
|
|
223
|
+
// with the title rather than sitting a couple of pixels low.
|
|
224
|
+
className: "-mt-1 flex shrink-0 items-center gap-1", children: headerActions })) : null] }), description ? (_jsx("p", { dir: "auto", "data-slot": "entity-card-description", title: description, className: cn("m-0 text-body", sized.description, clampDescription), children: description })) : null, meta, _jsx("div", { "aria-hidden": "true", className: "grow" }), shownStats && shownStats.length > 0 ? (_jsx("div", { "data-slot": "entity-card-stats", className: cn("flex flex-wrap items-center border-t border-hairline text-caption text-body", sized.stats), children: shownStats.map((stat) => (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [stat.icon ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex [&>svg]:size-4", children: stat.icon })) : null, stat.value, _jsx("span", { className: "sr-only", children: stat.label })] }, stat.label))) })) : null, footer] }));
|
|
225
|
+
/**
|
|
226
|
+
* The preview region, shared by all three sizes.
|
|
227
|
+
*
|
|
228
|
+
* A function rather than a second copy, because the two things that differ
|
|
229
|
+
* between the stacked sizes and the row are its shape and whether a panel goes
|
|
230
|
+
* over it. Everything that is easy to get wrong — the capture painting over
|
|
231
|
+
* the identity rather than instead of it, the badge sitting after the panel so
|
|
232
|
+
* the scrim does not smudge it, the badge not eating a click meant for the
|
|
233
|
+
* link — is written once and is the same picture in every size.
|
|
234
|
+
*/
|
|
235
|
+
const previewRegion = (shape, badgeSize, panel) => seed ? (_jsxs("div", { "data-slot": "entity-card-preview", className: cn("relative shrink-0", shape), children: [_jsx(EntityIdentity, { seed: seed, name: title }), previewUrl ? (_jsx("div", { "data-slot": "entity-card-capture", "aria-hidden": "true", className: "absolute inset-0 bg-cover bg-center",
|
|
236
|
+
// A background image, not an <img>: a URL that 404s paints nothing
|
|
237
|
+
// and the identity tile below shows through, with no state and no
|
|
238
|
+
// client boundary. The URL goes out exactly as the caller wrote it —
|
|
239
|
+
// `cssUrlString` escapes only the quote and backslash that would
|
|
240
|
+
// break out of url("..."), and never re-encodes an already-encoded
|
|
241
|
+
// URL (ui#178).
|
|
242
|
+
style: { backgroundImage: `url("${cssUrlString(previewUrl)}")` } })) : null, panel, kind ? (_jsx(EntityKindBadge, { kind: kind, size: badgeSize, className: cn("pointer-events-none absolute", badgeSize === "md" ? "top-2 right-2" : "top-1 right-1") })) : null] })) : null;
|
|
243
|
+
/**
|
|
244
|
+
* The reveal panel, which belongs to the stacked sizes only.
|
|
245
|
+
*
|
|
246
|
+
* Extracted to a variable rather than left inline because `previewRegion`
|
|
247
|
+
* above is now shared with the row, and the row deliberately has no panel to
|
|
248
|
+
* pass it. The alternative — a boolean the region branches on — would put the
|
|
249
|
+
* decision in two places instead of one.
|
|
250
|
+
*/
|
|
251
|
+
const revealPanel = revealed ? (_jsxs("div", { "data-slot": "entity-card-reveal", "data-cg-surface": "ink", className: cn("absolute inset-0 flex flex-col justify-end bg-scrim-strong text-ink",
|
|
252
|
+
// The only thing compact changes about this panel is its
|
|
253
|
+
// measurements. Same scrim, same ink surface, same two
|
|
254
|
+
// foregrounds — a panel that got smaller AND paler would be
|
|
255
|
+
// trading contrast for space, which is the one thing the
|
|
256
|
+
// guardrail exists to stop.
|
|
257
|
+
sized.reveal,
|
|
258
|
+
// opacity-0, not hidden: the panel is in the tab order at all
|
|
259
|
+
// times, so tabbing into Open is what reveals it, and a touch
|
|
260
|
+
// user with no hover still has a live tap target.
|
|
261
|
+
"opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
|
|
262
|
+
// Reduced motion removes the FADE, not the panel. Someone who
|
|
263
|
+
// has asked for less movement still needs the actions.
|
|
264
|
+
"motion-reduce:transition-none"), children: [_jsx("span", { "data-slot": "entity-card-reveal-title", dir: "auto", className: cn("truncate font-medium", sized.revealTitle), children: title }), description ? (_jsx("p", { "data-slot": "entity-card-reveal-description", dir: "auto",
|
|
265
|
+
// text-body, never text-faint. The secondary measures 6.18:1
|
|
266
|
+
// on this scrim and the guardrail holds it there; the muted
|
|
267
|
+
// rung measures 4.06:1, under AA, and is deliberately outside
|
|
268
|
+
// that assertion because it is documented as non-essential
|
|
269
|
+
// text. So there is no muted tier available on this panel.
|
|
270
|
+
className: "m-0 truncate text-caption text-body", children: description })) : null, creator || status ? (_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-reveal-creator", className: "flex min-w-0 items-center gap-1.5 text-caption text-body", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : (_jsx("span", {})), status ? _jsx("span", { className: "shrink-0", children: status }) : null] })) : null, _jsx("div", { className: "flex items-center gap-2 pt-0.5", children: actionPair })] })) : null;
|
|
271
|
+
/**
|
|
272
|
+
* THE ROW. The same card, running across instead of down.
|
|
273
|
+
*
|
|
274
|
+
* Its own return rather than a set of conditionals threaded through the
|
|
275
|
+
* stacked one, because almost nothing about the arrangement survives the
|
|
276
|
+
* rotation: the preview is beside the text rather than above it, the title,
|
|
277
|
+
* the description and the creator are one column of single lines, and the
|
|
278
|
+
* state, the header's controls and the two actions form a cluster at the end.
|
|
279
|
+
* Threading that through would leave a body that reads as neither shape.
|
|
280
|
+
*
|
|
281
|
+
* What IS shared is shared for real: `previewRegion` paints the same picture,
|
|
282
|
+
* `actionPair` is the same two anchors, and `SIZE_STYLE.row` is a column of
|
|
283
|
+
* the same table. Nothing about a row is a second implementation of something
|
|
284
|
+
* the media card already does.
|
|
285
|
+
*
|
|
286
|
+
* ## The hit model, which is the media card's with one thing moved
|
|
287
|
+
*
|
|
288
|
+
* `relative` on the card is load-bearing: it is what Open's stretched
|
|
289
|
+
* `::after` sizes to, so a click anywhere on the row opens the entity, exactly
|
|
290
|
+
* as a click anywhere on a thumbnail does. That also means a row is never
|
|
291
|
+
* wrapped in a whole-card anchor — the actions are anchors, and an anchor
|
|
292
|
+
* inside an anchor is invalid HTML that browsers repair by closing the outer
|
|
293
|
+
* one.
|
|
294
|
+
*
|
|
295
|
+
* `headerActions` is the thing that moves. On a media card it sits in the body
|
|
296
|
+
* and nothing is stretched over it. Here it sits inside Open's hit area, so it
|
|
297
|
+
* carries `relative z-10` to stay above it. That is safe in a way the same
|
|
298
|
+
* treatment on the panel's Dashboard was not (#171): these controls are
|
|
299
|
+
* VISIBLE at rest, so a tap landing on the save toggle rather than on the row
|
|
300
|
+
* is what a reader can see is going to happen. The invisible-at-rest rule
|
|
301
|
+
* still binds the two actions, which is why Dashboard keeps its
|
|
302
|
+
* `pointer-events-none`.
|
|
303
|
+
*
|
|
304
|
+
* `stats` and `footer` are not rendered here — see the size note at the top.
|
|
305
|
+
*/
|
|
306
|
+
if (size === "row") {
|
|
307
|
+
return (_jsxs(Card, { "data-slot": "entity-card", "data-entity-size": "row", className: cn("relative flex-row items-center gap-3 p-(--card-spacing)", sized.cardSpacing, className), ...props, children: [previewRegion(
|
|
308
|
+
// A left thumbnail, so it rounds on all four corners rather than
|
|
309
|
+
// sharing the card's top edge, and it carries a full hairline rather
|
|
310
|
+
// than the media card's single bottom rule.
|
|
311
|
+
cn("overflow-hidden rounded-lg border border-hairline", ROW_THUMBNAIL), "sm", null), _jsx("div", { className: cn("flex w-0 min-w-0 flex-1 flex-col", sized.body), children: children ?? (_jsxs(_Fragment, { children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block truncate font-medium text-ink", sized.title), children: [kind && !seed ? (_jsx(EntityKindBadge, { kind: kind, size: "sm", className: "mr-1.5 align-[-0.2em]" })) : null, title] }), slug ? (_jsx("span", { dir: "auto", "data-slot": "entity-card-slug", title: slug, className: "block truncate font-mono text-caption text-faint", children: slug })) : null, description ? (_jsx("p", { dir: "auto", "data-slot": "entity-card-description", title: description, className: cn("m-0 truncate text-body", sized.description), children: description })) : null, creator || meta ? (_jsxs("div", { className: "flex min-w-0 items-center gap-2 text-caption text-body", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-creator", className: "flex min-w-0 items-center gap-1.5", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : null, meta] })) : null] })) }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [status ? _jsx("span", { className: "shrink-0", children: status }) : null, headerActions ? (_jsx("div", { "data-slot": "entity-card-actions", className: "relative z-10 flex shrink-0 items-center gap-1", children: headerActions })) : null, href ? (_jsx("div", { "data-slot": "entity-card-row-actions", className: cn("flex shrink-0 items-center gap-2",
|
|
312
|
+
// The row's whole hover behaviour, and all of it: the
|
|
313
|
+
// information is already on screen, so what arrives is the two
|
|
314
|
+
// actions and nothing else.
|
|
315
|
+
"opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
|
|
316
|
+
// Reduced motion removes the FADE, not the actions.
|
|
317
|
+
"motion-reduce:transition-none"), children: actionPair })) : null] })] }));
|
|
318
|
+
}
|
|
319
|
+
const card = (_jsxs(Card, { "data-slot": "entity-card", "data-entity-size": size,
|
|
108
320
|
// gap-0 py-0: `Card` pads itself for a header/content/footer stack, and
|
|
109
321
|
// this card's preview is full bleed to the top edge. The padding moves
|
|
110
322
|
// inside, onto the body, so the preview can touch the corners.
|
|
@@ -118,53 +330,12 @@ function EntityCard({ title, slug, description, titleLines = 2, descriptionLines
|
|
|
118
330
|
// anchor. As a direct grid item it must NOT be h-full: a grid area has a
|
|
119
331
|
// definite height, so height:100% pins the card to the tallest card in the
|
|
120
332
|
// row even when the grid was told `items-start`.
|
|
121
|
-
className: cn("gap-0 py-0", href && !revealed && "h-full", className), ...props, children: [
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// A background image, not an <img>: a URL that 404s paints
|
|
128
|
-
// nothing and the identity tile below shows through, with no
|
|
129
|
-
// state and no client boundary. The URL goes out exactly as the
|
|
130
|
-
// caller wrote it — `cssUrlString` escapes only the quote and
|
|
131
|
-
// backslash that would break out of url("..."), and never
|
|
132
|
-
// re-encodes an already-encoded URL (ui#178).
|
|
133
|
-
style: { backgroundImage: `url("${cssUrlString(previewUrl)}")` } })) : null, revealed ? (_jsxs("div", { "data-slot": "entity-card-reveal", "data-cg-surface": "ink", className: cn("absolute inset-0 flex flex-col justify-end gap-1.5 bg-scrim-strong p-3 text-ink",
|
|
134
|
-
// opacity-0, not hidden: the panel is in the tab order at all
|
|
135
|
-
// times, so tabbing into Open is what reveals it, and a touch
|
|
136
|
-
// user with no hover still has a live tap target.
|
|
137
|
-
"opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
|
|
138
|
-
// Reduced motion removes the FADE, not the panel. Someone who
|
|
139
|
-
// has asked for less movement still needs the actions.
|
|
140
|
-
"motion-reduce:transition-none"), children: [_jsx("span", { "data-slot": "entity-card-reveal-title", dir: "auto", className: "truncate text-body-sm font-medium", children: title }), description ? (_jsx("p", { "data-slot": "entity-card-reveal-description", dir: "auto",
|
|
141
|
-
// text-body, never text-faint. The secondary measures 6.18:1
|
|
142
|
-
// on this scrim and the guardrail holds it there; the muted
|
|
143
|
-
// rung measures 4.06:1, under AA, and is deliberately outside
|
|
144
|
-
// that assertion because it is documented as non-essential
|
|
145
|
-
// text. So there is no muted tier available on this panel.
|
|
146
|
-
className: "m-0 truncate text-caption text-body", children: description })) : null, creator || status ? (_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-reveal-creator", className: "flex min-w-0 items-center gap-1.5 text-caption text-body", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : (_jsx("span", {})), status ? _jsx("span", { className: "shrink-0", children: status }) : null] })) : null, _jsxs("div", { className: "flex items-center gap-2 pt-0.5", children: [_jsxs("a", { href: href, "data-slot": "entity-card-open",
|
|
147
|
-
// after:inset-0 makes this link the whole panel, so a click
|
|
148
|
-
// anywhere on the thumbnail opens the entity. The anchor
|
|
149
|
-
// itself must NOT be positioned or the stretched layer sizes
|
|
150
|
-
// to the anchor instead of to the panel — the panel is already
|
|
151
|
-
// absolute, so it is the containing block. Settings comes
|
|
152
|
-
// later in the DOM and IS positioned, so it stacks above the
|
|
153
|
-
// stretched layer rather than under it.
|
|
154
|
-
className: "inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline after:absolute after:inset-0 after:content-[''] focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(OpenLiveIcon, { className: "size-3.5" }), "Open"] }), settingsHref ? (_jsxs("a", { href: settingsHref, "data-slot": "entity-card-settings",
|
|
155
|
-
// relative, and that is load-bearing: it lifts this link
|
|
156
|
-
// above Open's stretched ::after, which otherwise covers the
|
|
157
|
-
// whole panel and would swallow every click meant for here.
|
|
158
|
-
//
|
|
159
|
-
// And because it is lifted, it must not be live while the
|
|
160
|
-
// panel is invisible: opacity-0 is a paint state, so at rest
|
|
161
|
-
// this pill was a region of the thumbnail that went to
|
|
162
|
-
// Settings on a tap instead of opening the entity (#171).
|
|
163
|
-
// pointer-events-none until the panel is actually revealed —
|
|
164
|
-
// the same reasoning the kind mark carries. Open keeps its
|
|
165
|
-
// stretched hit area at all times, so the touch fallback is
|
|
166
|
-
// untouched.
|
|
167
|
-
className: "pointer-events-none relative inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline group-hover/card:pointer-events-auto group-focus-within/card:pointer-events-auto focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(SettingsIcon, { className: "size-3.5" }), "Settings"] })) : null] })] })) : null, kind ? (_jsx(EntityKindBadge, { kind: kind, className: "pointer-events-none absolute top-2 right-2" })) : null] })) : null, _jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-3 p-(--card-spacing)", children: body })] }));
|
|
333
|
+
className: cn("gap-0 py-0", sized.cardSpacing, href && !revealed && "h-full", className), ...props, children: [previewRegion(
|
|
334
|
+
// rounded-t-xl is the same --cg-radius-xl the card rounds to, and
|
|
335
|
+
// overflow-hidden is what keeps the reveal panel inside it. The card
|
|
336
|
+
// already clips; stating it here means the panel can never paint a
|
|
337
|
+
// corner the card does not have.
|
|
338
|
+
"overflow-hidden rounded-t-xl border-b border-hairline", "md", revealPanel), _jsx("div", { className: cn("flex min-h-0 flex-1 flex-col p-(--card-spacing)", sized.body), children: body })] }));
|
|
168
339
|
// A revealed card is never wrapped: the panel's Open action is already an
|
|
169
340
|
// anchor, and an anchor inside an anchor is invalid HTML that browsers repair
|
|
170
341
|
// by closing the outer one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-card.js","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,YAAY,
|
|
1
|
+
{"version":3,"file":"entity-card.js","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The small label that sits above something and names the part of the page it
|
|
3
|
+
* belongs to. A section label, a specimen caption, the word over a lockup.
|
|
4
|
+
*
|
|
5
|
+
* ## Why it exists as its own thing (#176)
|
|
6
|
+
*
|
|
7
|
+
* The recipe was already in this library — `text-label font-medium text-faint`,
|
|
8
|
+
* written inline inside `PageHeading` and reachable only by rendering a whole
|
|
9
|
+
* page lockup. So a surface that wanted the label and not the display heading
|
|
10
|
+
* had two options, and both are wrong in the same way: hand-build the three
|
|
11
|
+
* classes, or borrow the nearest primitive that is not this one.
|
|
12
|
+
*
|
|
13
|
+
* The console's styleguide did the second. Its section labels render as
|
|
14
|
+
* `Badge variant="outline"`, which is a pill — the right colour, the wrong
|
|
15
|
+
* shape, and a reference page for a design system teaching its reader that
|
|
16
|
+
* building your own furniture is normal. That is what cloudgrid-console#654
|
|
17
|
+
* filed and what this answers.
|
|
18
|
+
*
|
|
19
|
+
* `PageHeading` renders this rather than repeating the classes, so there is one
|
|
20
|
+
* definition of what an eyebrow looks like and retuning it is one edit here.
|
|
21
|
+
*
|
|
22
|
+
* ## What it is not
|
|
23
|
+
*
|
|
24
|
+
* Not a heading. It is a `<p>`, and it takes no `level`: an eyebrow is a label
|
|
25
|
+
* for the thing under it, so promoting it to `<h2>` would put a second entry in
|
|
26
|
+
* the document outline for one section and announce the label instead of the
|
|
27
|
+
* title. When the eyebrow and a heading belong together, put both in a
|
|
28
|
+
* `PageHeading`, which stacks them and keeps the heading the heading.
|
|
29
|
+
*
|
|
30
|
+
* Not uppercase. `--cg-label-size` carries its own weight and leading through
|
|
31
|
+
* `text-label`, and the brand's uppercase treatment belongs to the display face
|
|
32
|
+
* — the heading — rather than to the small print above it. A caller who wants
|
|
33
|
+
* caps has `className`.
|
|
34
|
+
*
|
|
35
|
+
* ## Type
|
|
36
|
+
*
|
|
37
|
+
* `text-label` rather than `text-caption`, deliberately: the label step exists
|
|
38
|
+
* on the brand ramp with its own weight companion (`--cg-label-weight`), and a
|
|
39
|
+
* caption is body copy set small. They render close and mean different things.
|
|
40
|
+
*/
|
|
41
|
+
declare function Eyebrow({ className, ...props }: React.ComponentProps<"p">): import("react").JSX.Element;
|
|
42
|
+
export { Eyebrow };
|
|
43
|
+
//# sourceMappingURL=eyebrow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eyebrow.d.ts","sourceRoot":"","sources":["../../src/blocks/eyebrow.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,+BAalE;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cloudgrid-cn.js";
|
|
3
|
+
/**
|
|
4
|
+
* The small label that sits above something and names the part of the page it
|
|
5
|
+
* belongs to. A section label, a specimen caption, the word over a lockup.
|
|
6
|
+
*
|
|
7
|
+
* ## Why it exists as its own thing (#176)
|
|
8
|
+
*
|
|
9
|
+
* The recipe was already in this library — `text-label font-medium text-faint`,
|
|
10
|
+
* written inline inside `PageHeading` and reachable only by rendering a whole
|
|
11
|
+
* page lockup. So a surface that wanted the label and not the display heading
|
|
12
|
+
* had two options, and both are wrong in the same way: hand-build the three
|
|
13
|
+
* classes, or borrow the nearest primitive that is not this one.
|
|
14
|
+
*
|
|
15
|
+
* The console's styleguide did the second. Its section labels render as
|
|
16
|
+
* `Badge variant="outline"`, which is a pill — the right colour, the wrong
|
|
17
|
+
* shape, and a reference page for a design system teaching its reader that
|
|
18
|
+
* building your own furniture is normal. That is what cloudgrid-console#654
|
|
19
|
+
* filed and what this answers.
|
|
20
|
+
*
|
|
21
|
+
* `PageHeading` renders this rather than repeating the classes, so there is one
|
|
22
|
+
* definition of what an eyebrow looks like and retuning it is one edit here.
|
|
23
|
+
*
|
|
24
|
+
* ## What it is not
|
|
25
|
+
*
|
|
26
|
+
* Not a heading. It is a `<p>`, and it takes no `level`: an eyebrow is a label
|
|
27
|
+
* for the thing under it, so promoting it to `<h2>` would put a second entry in
|
|
28
|
+
* the document outline for one section and announce the label instead of the
|
|
29
|
+
* title. When the eyebrow and a heading belong together, put both in a
|
|
30
|
+
* `PageHeading`, which stacks them and keeps the heading the heading.
|
|
31
|
+
*
|
|
32
|
+
* Not uppercase. `--cg-label-size` carries its own weight and leading through
|
|
33
|
+
* `text-label`, and the brand's uppercase treatment belongs to the display face
|
|
34
|
+
* — the heading — rather than to the small print above it. A caller who wants
|
|
35
|
+
* caps has `className`.
|
|
36
|
+
*
|
|
37
|
+
* ## Type
|
|
38
|
+
*
|
|
39
|
+
* `text-label` rather than `text-caption`, deliberately: the label step exists
|
|
40
|
+
* on the brand ramp with its own weight companion (`--cg-label-weight`), and a
|
|
41
|
+
* caption is body copy set small. They render close and mean different things.
|
|
42
|
+
*/
|
|
43
|
+
function Eyebrow({ className, ...props }) {
|
|
44
|
+
return (_jsx("p", { "data-slot": "eyebrow",
|
|
45
|
+
// m-0 because a consumer without Tailwind's preflight — a prose block, an
|
|
46
|
+
// Astro page with its own base sheet — inherits a paragraph margin and the
|
|
47
|
+
// label drifts away from the thing it labels. This library's own pages are
|
|
48
|
+
// preflighted, so the margin is invisible here and only ever wrong
|
|
49
|
+
// downstream, which is the failure worth carrying three characters for.
|
|
50
|
+
className: cn("m-0 text-label font-medium text-faint", className), ...props }));
|
|
51
|
+
}
|
|
52
|
+
export { Eyebrow };
|
|
53
|
+
//# sourceMappingURL=eyebrow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eyebrow.js","sourceRoot":"","sources":["../../src/blocks/eyebrow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,SAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA6B;IACjE,OAAO,CACL,yBACY,SAAS;QACnB,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,mEAAmE;QACnE,wEAAwE;QACxE,SAAS,EAAE,EAAE,CAAC,uCAAuC,EAAE,SAAS,CAAC,KAC7D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -7,16 +7,21 @@
|
|
|
7
7
|
* structure, because the copy reads as a sequence of commitments rather than a
|
|
8
8
|
* feature race.
|
|
9
9
|
*
|
|
10
|
-
* ##
|
|
10
|
+
* ## The glyphs are Phosphor, through the library's own names
|
|
11
11
|
*
|
|
12
12
|
* v0 inlined ten Phosphor SVGs as raw strings, because Astro can import SVG via
|
|
13
13
|
* Vite's `?raw` and React bundlers cannot, and rendered them with
|
|
14
|
-
* `dangerouslySetInnerHTML`.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* `
|
|
18
|
-
*
|
|
19
|
-
*
|
|
14
|
+
* `dangerouslySetInnerHTML`. This renders the same family, without either
|
|
15
|
+
* problem: `scripts/generate-phosphor-marks.mjs` reads the path data out of
|
|
16
|
+
* `@phosphor-icons/core` and inlines it as components, and this file names roles
|
|
17
|
+
* — `AiIcon`, `MemoryIcon`, `ScheduleIcon` — rather than glyphs, so a repick is
|
|
18
|
+
* one slug in the generator and no edit here (#167).
|
|
19
|
+
*
|
|
20
|
+
* The interim between the two was lucide, chosen when this registry declared
|
|
21
|
+
* `iconLibrary: lucide`. It no longer does: Phosphor is the only icon library,
|
|
22
|
+
* every equivalent was an approximation of a mark the designer had already
|
|
23
|
+
* picked, and `dangerouslySetInnerHTML` for decoration remains a sharp tool used
|
|
24
|
+
* for nothing.
|
|
20
25
|
*
|
|
21
26
|
* ## The matcher, and its escape hatch
|
|
22
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-cells.d.ts","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"AAeA
|
|
1
|
+
{"version":3,"file":"feature-cells.d.ts","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,KAAK,gBAAgB,GAAG;IACtB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,mDAAmD;IACnD,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnD,CAAA;AA+BD,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,OAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG;IAC3C,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAC7B,+BA4DA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { AiIcon, DatabaseIcon, FastIcon, MemoryIcon, PeopleIcon, PlugIcon, ScheduleIcon, SecretIcon, StorageIcon, WebIcon, } from "./icons.js";
|
|
3
3
|
import { cn } from "../lib/cloudgrid-cn.js";
|
|
4
4
|
const MATCHERS = [
|
|
5
|
-
[/\bai\b|model|gateway/i,
|
|
6
|
-
[/database|postgres/i,
|
|
7
|
-
[/storage|files?\b/i,
|
|
8
|
-
[/memory|brain/i,
|
|
9
|
-
[/live|url|domain/i,
|
|
10
|
-
[/key|sign-?in|auth|secret/i,
|
|
11
|
-
[/cron|schedule|clock/i,
|
|
12
|
-
[/found|shared|picked|player|people/i,
|
|
13
|
-
[/cache|fast|instant/i,
|
|
5
|
+
[/\bai\b|model|gateway/i, AiIcon],
|
|
6
|
+
[/database|postgres/i, DatabaseIcon],
|
|
7
|
+
[/storage|files?\b/i, StorageIcon],
|
|
8
|
+
[/memory|brain/i, MemoryIcon],
|
|
9
|
+
[/live|url|domain/i, WebIcon],
|
|
10
|
+
[/key|sign-?in|auth|secret/i, SecretIcon],
|
|
11
|
+
[/cron|schedule|clock/i, ScheduleIcon],
|
|
12
|
+
[/found|shared|picked|player|people/i, PeopleIcon],
|
|
13
|
+
[/cache|fast|instant/i, FastIcon],
|
|
14
14
|
];
|
|
15
15
|
function glyphFor(item) {
|
|
16
16
|
if (item.icon)
|
|
17
17
|
return item.icon;
|
|
18
18
|
const text = `${item.q} ${item.a}`;
|
|
19
|
-
return MATCHERS.find(([re]) => re.test(text))?.[1] ??
|
|
19
|
+
return MATCHERS.find(([re]) => re.test(text))?.[1] ?? PlugIcon;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* The three-tint cycle. Tints are mixed against the page surface rather than
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-cells.js","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"feature-cells.js","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"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"}
|