@godxjp/ui 31.13.0 → 31.14.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/agent/START-HERE.md +4 -4
- package/agent/components/Image.json +18 -2
- package/agent/components.json +18 -2
- package/agent/index.json +4 -4
- package/agent/llms.txt +5 -5
- package/agent/tokens.json +6 -0
- package/dist/components/data-display/image.d.ts +6 -1
- package/dist/components/data-display/image.js +90 -49
- package/dist/contracts/measurement.json +1 -1
- package/dist/props/components/data-display.prop.d.ts +27 -0
- package/dist/props/registry.d.ts +26 -0
- package/dist/props/registry.js +19 -0
- package/dist/styles/data-display-layout.css +52 -0
- package/dist/styles/layers.json +1 -1
- package/dist/tokens/components/data-display.css +1 -0
- package/docs/DESIGN-AUTHORITY.md +6 -0
- package/docs/FRAME-COVERAGE-REPORT.md +1 -1
- package/docs/data-display/image.tsx +40 -0
- package/package.json +2 -2
package/agent/START-HERE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
You are about to write code against a design system you did not author. This file is the whole
|
|
4
4
|
contract. Read it before you write JSX.
|
|
5
5
|
|
|
6
|
-
**This catalog describes `@godxjp/ui` 31.
|
|
6
|
+
**This catalog describes `@godxjp/ui` 31.14.0.** If the project you are editing has a different
|
|
7
7
|
version in its `package.json`, read the pinned catalog for THAT version instead
|
|
8
8
|
(`…/v<their-version>/agent/…`). A catalog newer than the installed package describes props that do
|
|
9
9
|
not exist yet; older, and it hides props that do. Neither failure announces itself.
|
|
@@ -56,10 +56,10 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
|
|
|
56
56
|
its `importPath`, and its examples. Fetch only the handful you picked in step 1.
|
|
57
57
|
3. `rules.json` — 50 cardinal rules. The ones about raw HTML and hardcoded colour are not
|
|
58
58
|
style advice.
|
|
59
|
-
4. `tokens.json` —
|
|
59
|
+
4. `tokens.json` — 2119 design tokens, each tagged with its `tier`. **If you were handed a
|
|
60
60
|
brand, read the 211 `foundation` entries first** — `--primary`, `--background`,
|
|
61
61
|
`--radius`, `--font-size-base` are the handful everything else derives from. The
|
|
62
|
-
|
|
62
|
+
1804 `component` entries are per-part knobs; reach for one only when a role is
|
|
63
63
|
right everywhere except one component.
|
|
64
64
|
5. `anti-ai-tells.json` — 26 shapes that make generated UI look generated, each with the
|
|
65
65
|
fix. Read before you reach for a gradient hero or a wall of coloured chips.
|
|
@@ -145,7 +145,7 @@ has stopped following the brand.
|
|
|
145
145
|
|---|---|---|---|
|
|
146
146
|
| `foundation` | 211 | the seeds — `--primary`, `--background`, `--foreground`, `--radius`, `--font-size-base`, `--shadow-color`. Everything below is derived from these | **yes — this is the main road.** Handed a brand colour, this is where it goes: `:root { --primary: <H> <S>% <L>%; }` (HSL components, no `hsl()` wrapper) |
|
|
147
147
|
| `semantic` | 104 | named roles that follow the seeds — `--ring`, `--text-link`, `--primary-hover`, `--overlay-background` | only when the seed is right and ONE role must differ. That role then stops following a later brand change |
|
|
148
|
-
| `component` |
|
|
148
|
+
| `component` | 1804 | per-part knobs, `--{component}-{part}-{property}` | rarely. Most are declared `initial` with the real default at the call site — deliberate, so a scoped override re-resolves instead of freezing at `:root` |
|
|
149
149
|
|
|
150
150
|
A token whose `value` is `initial` is not empty and not broken: `initial` is the guaranteed-invalid
|
|
151
151
|
value, so the real default is computed where the element paints it. Set it and yours wins.
|
|
@@ -31,10 +31,25 @@
|
|
|
31
31
|
"type": "ReactNode | boolean"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"description": "
|
|
34
|
+
"description": "antd Image: size the FRAME (number = px, or a CSS length); the picture fills it. `width` alone keeps the picture's ratio; a fixed height crops per `fit`. Also set on the img.",
|
|
35
35
|
"name": "width / height",
|
|
36
36
|
"type": "number | string"
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
"description": "Thumbnail frame on the Thumbnail height scale (64 / 96 / 160px) at `--thumbnail-width-ratio` (4 / 3), cropped to fill. godx extension; `width`/`height` override the side they name.",
|
|
40
|
+
"name": "size",
|
|
41
|
+
"type": "\"sm\" | \"md\" | \"lg\""
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"description": "object-fit inside a fixed frame. Default `cover` once the height is fixed (size or height).",
|
|
45
|
+
"name": "fit",
|
|
46
|
+
"type": "\"cover\" | \"contain\""
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"description": "Text under the picture in a figure held to the picture's width — a long file name truncates instead of widening the tile. godx extension.",
|
|
50
|
+
"name": "caption",
|
|
51
|
+
"type": "ReactNode"
|
|
52
|
+
},
|
|
38
53
|
{
|
|
39
54
|
"description": "Class on the wrapper (the button).",
|
|
40
55
|
"name": "className",
|
|
@@ -78,7 +93,8 @@
|
|
|
78
93
|
"DO pass `preview={false}` for a logo or icon inside that body so it neither opens nor counts.",
|
|
79
94
|
"DO use `Image.PreviewGroup` or `ImagePreviewGroup` — the same component.",
|
|
80
95
|
"DON'T hand-roll a lightbox from Dialog + Carousel: it has no zoom, no arrow keys and a 32rem box. That composition is what this replaces.",
|
|
81
|
-
"DON'T nest an Image inside a link or button: the thumbnail is itself a button."
|
|
96
|
+
"DON'T nest an Image inside a link or button: the thumbnail is itself a button.",
|
|
97
|
+
"DO size an attachment gallery with `size=\"md\"` (96px, 4:3, cropped) and put the file name in `caption` — never an inline style reading `--thumbnail-block-size`."
|
|
82
98
|
],
|
|
83
99
|
"useCases": [
|
|
84
100
|
"Screenshots in a test result or wiki page that the reader opens large and pages through.",
|
package/agent/components.json
CHANGED
|
@@ -15808,10 +15808,25 @@
|
|
|
15808
15808
|
"type": "ReactNode | boolean"
|
|
15809
15809
|
},
|
|
15810
15810
|
{
|
|
15811
|
-
"description": "
|
|
15811
|
+
"description": "antd Image: size the FRAME (number = px, or a CSS length); the picture fills it. `width` alone keeps the picture's ratio; a fixed height crops per `fit`. Also set on the img.",
|
|
15812
15812
|
"name": "width / height",
|
|
15813
15813
|
"type": "number | string"
|
|
15814
15814
|
},
|
|
15815
|
+
{
|
|
15816
|
+
"description": "Thumbnail frame on the Thumbnail height scale (64 / 96 / 160px) at `--thumbnail-width-ratio` (4 / 3), cropped to fill. godx extension; `width`/`height` override the side they name.",
|
|
15817
|
+
"name": "size",
|
|
15818
|
+
"type": "\"sm\" | \"md\" | \"lg\""
|
|
15819
|
+
},
|
|
15820
|
+
{
|
|
15821
|
+
"description": "object-fit inside a fixed frame. Default `cover` once the height is fixed (size or height).",
|
|
15822
|
+
"name": "fit",
|
|
15823
|
+
"type": "\"cover\" | \"contain\""
|
|
15824
|
+
},
|
|
15825
|
+
{
|
|
15826
|
+
"description": "Text under the picture in a figure held to the picture's width — a long file name truncates instead of widening the tile. godx extension.",
|
|
15827
|
+
"name": "caption",
|
|
15828
|
+
"type": "ReactNode"
|
|
15829
|
+
},
|
|
15815
15830
|
{
|
|
15816
15831
|
"description": "Class on the wrapper (the button).",
|
|
15817
15832
|
"name": "className",
|
|
@@ -15855,7 +15870,8 @@
|
|
|
15855
15870
|
"DO pass `preview={false}` for a logo or icon inside that body so it neither opens nor counts.",
|
|
15856
15871
|
"DO use `Image.PreviewGroup` or `ImagePreviewGroup` — the same component.",
|
|
15857
15872
|
"DON'T hand-roll a lightbox from Dialog + Carousel: it has no zoom, no arrow keys and a 32rem box. That composition is what this replaces.",
|
|
15858
|
-
"DON'T nest an Image inside a link or button: the thumbnail is itself a button."
|
|
15873
|
+
"DON'T nest an Image inside a link or button: the thumbnail is itself a button.",
|
|
15874
|
+
"DO size an attachment gallery with `size=\"md\"` (96px, 4:3, cropped) and put the file name in `caption` — never an inline style reading `--thumbnail-block-size`."
|
|
15859
15875
|
],
|
|
15860
15876
|
"useCases": [
|
|
15861
15877
|
"Screenshots in a test result or wiki page that the reader opens large and pages through.",
|
package/agent/index.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"components": 178,
|
|
5
5
|
"patterns": 21,
|
|
6
6
|
"rules": 50,
|
|
7
|
-
"tokens":
|
|
7
|
+
"tokens": 2119,
|
|
8
8
|
"vocabulary": 14
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
@@ -48,19 +48,19 @@
|
|
|
48
48
|
"note": "Pin to the tag that matches the @godxjp/ui version you installed. A catalog newer than your package describes props you do not have; older, and it hides props you do.",
|
|
49
49
|
"read": {
|
|
50
50
|
"live": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json",
|
|
51
|
-
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.
|
|
51
|
+
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.14.0/agent/index.json"
|
|
52
52
|
},
|
|
53
53
|
"source": "mcp/src/data — the same data @godxjp/ui-mcp serves — plus the foundation and semantic token tiers, read from src/tokens/*.css",
|
|
54
54
|
"start": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md",
|
|
55
55
|
"tokenTiers": {
|
|
56
56
|
"component": "per-part knobs, --{component}-{part}-{property}; usually leave these alone",
|
|
57
57
|
"counts": {
|
|
58
|
-
"component":
|
|
58
|
+
"component": 1804,
|
|
59
59
|
"foundation": 211,
|
|
60
60
|
"semantic": 104
|
|
61
61
|
},
|
|
62
62
|
"foundation": "the seeds a consumer is invited to set — --primary, --background, --radius",
|
|
63
63
|
"semantic": "named roles that follow the seeds — --ring, --text-link, --overlay-background"
|
|
64
64
|
},
|
|
65
|
-
"version": "31.
|
|
65
|
+
"version": "31.14.0"
|
|
66
66
|
}
|
package/agent/llms.txt
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @godxjp/ui
|
|
2
2
|
|
|
3
|
-
> A Japanese-enterprise React design system: 178 components,
|
|
4
|
-
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.
|
|
3
|
+
> A Japanese-enterprise React design system: 178 components, 2119 design tokens,
|
|
4
|
+
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.14.0.
|
|
5
5
|
|
|
6
6
|
If your client can run a process, do not read these files — run the MCP server instead
|
|
7
|
-
(`npx @godxjp/ui-mcp@31.
|
|
7
|
+
(`npx @godxjp/ui-mcp@31.14.0`). It is searchable and version-locked. These files exist for agents
|
|
8
8
|
that can only fetch URLs.
|
|
9
9
|
|
|
10
10
|
## Start
|
|
@@ -18,7 +18,7 @@ that can only fetch URLs.
|
|
|
18
18
|
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 48 KB — all 178 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
|
|
19
19
|
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–36 KB, median 6 KB). Read the index, then fetch only the ones you chose — this is the selective route, and the reason you do not need the blob.
|
|
20
20
|
- [components.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json): 1.2 MB — every entry in one file. Most URL fetchers truncate a response this size without saying so; prefer the per-component files.
|
|
21
|
-
- [tokens.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json): every design token with its value, the reason it exists, and its `tier` — 211 `foundation` seeds (`--primary`, `--background`, `--radius`: set these when you are handed a brand), 104 `semantic` roles,
|
|
21
|
+
- [tokens.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json): every design token with its value, the reason it exists, and its `tier` — 211 `foundation` seeds (`--primary`, `--background`, `--radius`: set these when you are handed a brand), 104 `semantic` roles, 1804 `component` knobs.
|
|
22
22
|
- [vocabulary.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json): the controlled prop vocabulary — which prop name means what, across every component.
|
|
23
23
|
- [rules.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/rules.json): 50 cardinal rules.
|
|
24
24
|
- [anti-ai-tells.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/anti-ai-tells.json): 26 shapes that make generated UI look generated, each with its fix.
|
|
@@ -26,7 +26,7 @@ that can only fetch URLs.
|
|
|
26
26
|
## Pinning
|
|
27
27
|
|
|
28
28
|
Every URL above tracks `main`. To pin to the release a project actually installed, swap `main` for
|
|
29
|
-
the tag: `.../godx-jp/godxjp-ui/v31.
|
|
29
|
+
the tag: `.../godx-jp/godxjp-ui/v31.14.0/agent/...`. A catalog that does not match the installed
|
|
30
30
|
package describes props that are absent, or hides props that are present, and says nothing either way.
|
|
31
31
|
|
|
32
32
|
Pinned catalogs only exist for releases whose tag actually contains `agent/`. If `…/v<version>/agent/index.json` returns 404, that release predates this catalog: read `…/main/…` instead and compare `index.json` → `version` against the package you have, so you at least know which way it drifted.
|
package/agent/tokens.json
CHANGED
|
@@ -5633,6 +5633,12 @@
|
|
|
5633
5633
|
"tier": "component",
|
|
5634
5634
|
"value": "10rem"
|
|
5635
5635
|
},
|
|
5636
|
+
{
|
|
5637
|
+
"description": "Image `size` frame: width = the Thumbnail height × this ratio.",
|
|
5638
|
+
"name": "--thumbnail-width-ratio",
|
|
5639
|
+
"tier": "component",
|
|
5640
|
+
"value": "4 / 3"
|
|
5641
|
+
},
|
|
5636
5642
|
{
|
|
5637
5643
|
"description": "default = var(--stroke-hairline), resolved at the call site (gh#906)",
|
|
5638
5644
|
"name": "--thumbnail-border-width",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { ImagePreviewConfigProp, ImagePreviewGroupProp } from "../../props/components/data-display.prop.js";
|
|
3
|
-
export type { ImagePreviewConfigProp, ImagePreviewGroupConfigProp, ImagePreviewGroupProp, ImagePreviewGroupProp as ImagePreviewGroupProps, ImagePreviewItemProp, ImageProp, ImageProp as ImageProps, } from "../../props/components/data-display.prop.js";
|
|
3
|
+
export type { ImageFitProp, ImagePreviewConfigProp, ImagePreviewGroupConfigProp, ImagePreviewGroupProp, ImagePreviewGroupProp as ImagePreviewGroupProps, ImagePreviewItemProp, ImageProp, ImageProp as ImageProps, ImageSizeProp, } from "../../props/components/data-display.prop.js";
|
|
4
4
|
/**
|
|
5
5
|
* ImagePreviewGroup — pages one preview across many pictures (antd `Image.PreviewGroup`).
|
|
6
6
|
*
|
|
@@ -15,6 +15,11 @@ export declare const Image: React.ForwardRefExoticComponent<Omit<React.ImgHTMLAt
|
|
|
15
15
|
fallback?: string;
|
|
16
16
|
placeholder?: React.ReactNode | boolean;
|
|
17
17
|
preview?: boolean | ImagePreviewConfigProp;
|
|
18
|
+
width?: number | string;
|
|
19
|
+
height?: number | string;
|
|
20
|
+
size?: import("./image.js").ImageSizeProp;
|
|
21
|
+
fit?: import("./image.js").ImageFitProp;
|
|
22
|
+
caption?: React.ReactNode;
|
|
18
23
|
className?: import("../../props/index.js").ClassNameProp;
|
|
19
24
|
} & React.RefAttributes<HTMLImageElement>> & {
|
|
20
25
|
PreviewGroup: typeof ImagePreviewGroup;
|
|
@@ -386,7 +386,22 @@ function ImagePreviewGroup({
|
|
|
386
386
|
) : null
|
|
387
387
|
] }) });
|
|
388
388
|
}
|
|
389
|
-
const ImageRoot = React.forwardRef(function Image({
|
|
389
|
+
const ImageRoot = React.forwardRef(function Image({
|
|
390
|
+
src,
|
|
391
|
+
alt,
|
|
392
|
+
fallback,
|
|
393
|
+
placeholder,
|
|
394
|
+
preview = true,
|
|
395
|
+
width,
|
|
396
|
+
height,
|
|
397
|
+
size,
|
|
398
|
+
fit,
|
|
399
|
+
caption,
|
|
400
|
+
className,
|
|
401
|
+
onLoad,
|
|
402
|
+
onError,
|
|
403
|
+
...imgProps
|
|
404
|
+
}, ref) {
|
|
390
405
|
const { t } = useTranslation();
|
|
391
406
|
const group = React.useContext(ImageGroupContext);
|
|
392
407
|
const groupDisabled = React.useContext(ImageGroupDisabledContext);
|
|
@@ -420,13 +435,26 @@ const ImageRoot = React.forwardRef(function Image({ src, alt, fallback, placehol
|
|
|
420
435
|
const [visible, setVisible] = useMergedState(config.visible, false, config.onVisibleChange);
|
|
421
436
|
const shownSrc = isError && fallback ? fallback : src;
|
|
422
437
|
const showPlaceholder = placeholder != null && placeholder !== false && status === "loading";
|
|
438
|
+
const sized = size != null || width != null || height != null;
|
|
439
|
+
const frameFit = fit ?? (size != null || height != null ? "cover" : void 0);
|
|
440
|
+
const frame = sized ? {
|
|
441
|
+
"data-sized": "",
|
|
442
|
+
"data-size": size,
|
|
443
|
+
style: {
|
|
444
|
+
...width != null ? { "--image-inline-size": cssLength(width) } : null,
|
|
445
|
+
...height != null ? { "--image-block-size": cssLength(height) } : null
|
|
446
|
+
}
|
|
447
|
+
} : null;
|
|
423
448
|
const picture = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
424
449
|
/* @__PURE__ */ jsx(
|
|
425
450
|
"img",
|
|
426
451
|
{
|
|
427
452
|
...imgProps,
|
|
453
|
+
width,
|
|
454
|
+
height,
|
|
428
455
|
ref: setImgRef,
|
|
429
456
|
"data-slot": "image-img",
|
|
457
|
+
"data-fit": frameFit,
|
|
430
458
|
className: "ui-image-img",
|
|
431
459
|
src: shownSrc,
|
|
432
460
|
alt,
|
|
@@ -442,59 +470,72 @@ const ImageRoot = React.forwardRef(function Image({ src, alt, fallback, placehol
|
|
|
442
470
|
),
|
|
443
471
|
showPlaceholder ? /* @__PURE__ */ jsx("span", { "data-slot": "image-placeholder", className: "ui-image-placeholder", "aria-hidden": "true", children: placeholder === true ? null : placeholder }) : null
|
|
444
472
|
] });
|
|
473
|
+
const withCaption = (image) => caption == null ? image : /* @__PURE__ */ jsxs("figure", { "data-slot": "image-tile", className: "ui-image-tile", ...frame, children: [
|
|
474
|
+
image,
|
|
475
|
+
/* @__PURE__ */ jsx("figcaption", { "data-slot": "image-caption", className: "ui-image-caption", children: caption })
|
|
476
|
+
] });
|
|
445
477
|
if (!canPreview) {
|
|
446
|
-
return
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
478
|
+
return withCaption(
|
|
479
|
+
/* @__PURE__ */ jsx(
|
|
480
|
+
"span",
|
|
481
|
+
{
|
|
482
|
+
ref: wrapperRef,
|
|
483
|
+
"data-slot": "image",
|
|
484
|
+
"data-status": status,
|
|
485
|
+
...frame,
|
|
486
|
+
className: cn("ui-image", className),
|
|
487
|
+
children: picture
|
|
488
|
+
}
|
|
489
|
+
)
|
|
455
490
|
);
|
|
456
491
|
}
|
|
457
|
-
return
|
|
458
|
-
/* @__PURE__ */ jsxs(
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
492
|
+
return withCaption(
|
|
493
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
494
|
+
/* @__PURE__ */ jsxs(
|
|
495
|
+
"button",
|
|
496
|
+
{
|
|
497
|
+
ref: (node) => {
|
|
498
|
+
wrapperRef.current = node;
|
|
499
|
+
},
|
|
500
|
+
type: "button",
|
|
501
|
+
"data-slot": "image",
|
|
502
|
+
"data-status": status,
|
|
503
|
+
"data-preview": "",
|
|
504
|
+
...frame,
|
|
505
|
+
className: cn("ui-image ui-focus-ring", className),
|
|
506
|
+
"aria-label": alt ? t("dataDisplay.image.previewLabel", { alt }) : t("dataDisplay.image.previewUnnamed"),
|
|
507
|
+
"aria-haspopup": "dialog",
|
|
508
|
+
onClick: () => inGroup && group ? group.open(id) : setVisible(true),
|
|
509
|
+
children: [
|
|
510
|
+
picture,
|
|
511
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "image-mask", className: "ui-image-mask", "aria-hidden": "true", children: config.mask ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
512
|
+
/* @__PURE__ */ jsx(Eye, { className: "ui-image-mask-icon" }),
|
|
513
|
+
t("dataDisplay.image.preview")
|
|
514
|
+
] }) })
|
|
515
|
+
]
|
|
516
|
+
}
|
|
517
|
+
),
|
|
518
|
+
inGroup ? null : /* @__PURE__ */ jsx(
|
|
519
|
+
ImagePreviewDialog,
|
|
520
|
+
{
|
|
521
|
+
open: visible,
|
|
522
|
+
onOpenChange: setVisible,
|
|
523
|
+
items: [{ src: previewSrc, alt }],
|
|
524
|
+
current: 0,
|
|
525
|
+
onCurrentChange: () => void 0,
|
|
526
|
+
fallback,
|
|
527
|
+
scaleStep: config.scaleStep,
|
|
528
|
+
minScale: config.minScale,
|
|
529
|
+
maxScale: config.maxScale
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
] })
|
|
533
|
+
);
|
|
496
534
|
});
|
|
497
535
|
ImageRoot.displayName = "Image";
|
|
536
|
+
function cssLength(value) {
|
|
537
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
538
|
+
}
|
|
498
539
|
const Image2 = Object.assign(ImageRoot, { PreviewGroup: ImagePreviewGroup });
|
|
499
540
|
export {
|
|
500
541
|
Image2 as Image,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.14.0",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
|
@@ -1251,8 +1251,35 @@ export type ImageProp = Omit<React.ImgHTMLAttributes<HTMLImageElement>, "alt" |
|
|
|
1251
1251
|
placeholder?: React.ReactNode | boolean;
|
|
1252
1252
|
/** `false` = a plain picture, not clickable, not in its group. Default `true`. */
|
|
1253
1253
|
preview?: boolean | ImagePreviewConfigProp;
|
|
1254
|
+
/**
|
|
1255
|
+
* antd Image `width`: the frame's inline size (number = px, or any CSS length). The picture
|
|
1256
|
+
* fills it; with no `height` its block size follows the picture's ratio. Also set on the `<img>`.
|
|
1257
|
+
*/
|
|
1258
|
+
width?: number | string;
|
|
1259
|
+
/**
|
|
1260
|
+
* antd Image `height`: the frame's block size (number = px, or any CSS length). A fixed height
|
|
1261
|
+
* crops the picture to fill (`fit` defaults to `cover`). Also set on the `<img>`.
|
|
1262
|
+
*/
|
|
1263
|
+
height?: number | string;
|
|
1264
|
+
/**
|
|
1265
|
+
* A thumbnail frame on the `Thumbnail` height scale (`--thumbnail-block-size-sm`, `…-size`,
|
|
1266
|
+
* `…-size-lg`: 64 / 96 / 160px) at `--thumbnail-width-ratio` (4 / 3). godx extension — antd has only
|
|
1267
|
+
* `width`/`height`, which override the preset's side they name.
|
|
1268
|
+
*/
|
|
1269
|
+
size?: ImageSizeProp;
|
|
1270
|
+
/** How the picture fills a fixed frame (`object-fit`). Default `cover` once the height is fixed. */
|
|
1271
|
+
fit?: ImageFitProp;
|
|
1272
|
+
/**
|
|
1273
|
+
* Text under the picture, held to the picture's width, so a long file name truncates instead of
|
|
1274
|
+
* widening the tile. Renders a `<figure>` with a `<figcaption>`. godx extension.
|
|
1275
|
+
*/
|
|
1276
|
+
caption?: React.ReactNode;
|
|
1254
1277
|
className?: ClassNameProp;
|
|
1255
1278
|
};
|
|
1279
|
+
/** `Image` thumbnail frame preset — the `Thumbnail` height scale. */
|
|
1280
|
+
export type ImageSizeProp = Extract<SizeProp, "sm" | "md" | "lg">;
|
|
1281
|
+
/** `Image` `fit` — the picture's `object-fit` inside a fixed frame. */
|
|
1282
|
+
export type ImageFitProp = "cover" | "contain";
|
|
1256
1283
|
/**
|
|
1257
1284
|
* @see ImagePreviewGroup — pages the preview across a set of pictures (antd `Image.PreviewGroup`).
|
|
1258
1285
|
*
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -4065,6 +4065,16 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
4065
4065
|
readonly reason: "antd PreviewGroup `preview.onChange(current, prevCurrent)`, kept verbatim.";
|
|
4066
4066
|
}];
|
|
4067
4067
|
};
|
|
4068
|
+
readonly ImageSizeProp: {
|
|
4069
|
+
readonly group: "data-display";
|
|
4070
|
+
readonly file: "components/data-display.prop.ts";
|
|
4071
|
+
readonly vocabulary: readonly ["SizeProp"];
|
|
4072
|
+
};
|
|
4073
|
+
readonly ImageFitProp: {
|
|
4074
|
+
readonly group: "data-display";
|
|
4075
|
+
readonly file: "components/data-display.prop.ts";
|
|
4076
|
+
readonly vocabulary: readonly [];
|
|
4077
|
+
};
|
|
4068
4078
|
readonly ImageProp: {
|
|
4069
4079
|
readonly group: "data-display";
|
|
4070
4080
|
readonly file: "components/data-display.prop.ts";
|
|
@@ -4084,6 +4094,22 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
4084
4094
|
readonly field: "preview";
|
|
4085
4095
|
readonly local: true;
|
|
4086
4096
|
readonly reason: "antd Image `preview: boolean | PreviewType` — opt-out or configure the preview.";
|
|
4097
|
+
}, "SizeProp", {
|
|
4098
|
+
readonly field: "width";
|
|
4099
|
+
readonly local: true;
|
|
4100
|
+
readonly reason: "antd Image `width` — the frame's inline size.";
|
|
4101
|
+
}, {
|
|
4102
|
+
readonly field: "height";
|
|
4103
|
+
readonly local: true;
|
|
4104
|
+
readonly reason: "antd Image `height` — the frame's block size.";
|
|
4105
|
+
}, {
|
|
4106
|
+
readonly field: "fit";
|
|
4107
|
+
readonly local: true;
|
|
4108
|
+
readonly reason: "CSS `object-fit` of the picture in a fixed frame.";
|
|
4109
|
+
}, {
|
|
4110
|
+
readonly field: "caption";
|
|
4111
|
+
readonly local: true;
|
|
4112
|
+
readonly reason: "A figcaption held to the picture's width (godx extension).";
|
|
4087
4113
|
}];
|
|
4088
4114
|
};
|
|
4089
4115
|
readonly ImagePreviewGroupProp: {
|
package/dist/props/registry.js
CHANGED
|
@@ -4920,6 +4920,16 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
4920
4920
|
}
|
|
4921
4921
|
]
|
|
4922
4922
|
},
|
|
4923
|
+
ImageSizeProp: {
|
|
4924
|
+
group: "data-display",
|
|
4925
|
+
file: "components/data-display.prop.ts",
|
|
4926
|
+
vocabulary: ["SizeProp"]
|
|
4927
|
+
},
|
|
4928
|
+
ImageFitProp: {
|
|
4929
|
+
group: "data-display",
|
|
4930
|
+
file: "components/data-display.prop.ts",
|
|
4931
|
+
vocabulary: []
|
|
4932
|
+
},
|
|
4923
4933
|
ImageProp: {
|
|
4924
4934
|
group: "data-display",
|
|
4925
4935
|
file: "components/data-display.prop.ts",
|
|
@@ -4937,6 +4947,15 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
4937
4947
|
field: "preview",
|
|
4938
4948
|
local: true,
|
|
4939
4949
|
reason: "antd Image `preview: boolean | PreviewType` \u2014 opt-out or configure the preview."
|
|
4950
|
+
},
|
|
4951
|
+
"SizeProp",
|
|
4952
|
+
{ field: "width", local: true, reason: "antd Image `width` \u2014 the frame's inline size." },
|
|
4953
|
+
{ field: "height", local: true, reason: "antd Image `height` \u2014 the frame's block size." },
|
|
4954
|
+
{ field: "fit", local: true, reason: "CSS `object-fit` of the picture in a fixed frame." },
|
|
4955
|
+
{
|
|
4956
|
+
field: "caption",
|
|
4957
|
+
local: true,
|
|
4958
|
+
reason: "A figcaption held to the picture's width (godx extension)."
|
|
4940
4959
|
}
|
|
4941
4960
|
]
|
|
4942
4961
|
},
|
|
@@ -2687,6 +2687,58 @@
|
|
|
2687
2687
|
border-radius: inherit;
|
|
2688
2688
|
}
|
|
2689
2689
|
|
|
2690
|
+
.ui-image[data-sized],
|
|
2691
|
+
.ui-image-tile[data-sized] {
|
|
2692
|
+
inline-size: var(--image-inline-size, auto);
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
.ui-image[data-sized] {
|
|
2696
|
+
block-size: var(--image-block-size, auto);
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
.ui-image[data-sized] > .ui-image-img {
|
|
2700
|
+
inline-size: 100%;
|
|
2701
|
+
max-inline-size: none;
|
|
2702
|
+
block-size: 100%;
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
:is(.ui-image, .ui-image-tile)[data-size="sm"] {
|
|
2706
|
+
--image-block-size: var(--thumbnail-block-size-sm);
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
:is(.ui-image, .ui-image-tile)[data-size="md"] {
|
|
2710
|
+
--image-block-size: var(--thumbnail-block-size);
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
:is(.ui-image, .ui-image-tile)[data-size="lg"] {
|
|
2714
|
+
--image-block-size: var(--thumbnail-block-size-lg);
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
:is(.ui-image, .ui-image-tile)[data-size] {
|
|
2718
|
+
--image-inline-size: calc(var(--image-block-size) * var(--thumbnail-width-ratio));
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
.ui-image-img[data-fit="cover"] {
|
|
2722
|
+
object-fit: cover;
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
.ui-image-img[data-fit="contain"] {
|
|
2726
|
+
object-fit: contain;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
.ui-image-tile {
|
|
2730
|
+
display: inline-flex;
|
|
2731
|
+
flex-direction: column;
|
|
2732
|
+
gap: var(--space-stack-xs);
|
|
2733
|
+
max-inline-size: 100%;
|
|
2734
|
+
margin: 0;
|
|
2735
|
+
vertical-align: top;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
.ui-image-caption {
|
|
2739
|
+
min-inline-size: 0;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2690
2742
|
.ui-image-placeholder {
|
|
2691
2743
|
position: absolute;
|
|
2692
2744
|
inset: 0;
|
package/dist/styles/layers.json
CHANGED
package/docs/DESIGN-AUTHORITY.md
CHANGED
|
@@ -399,6 +399,12 @@ bottomEnd | none` (`TablePaginationPositionProp`, default `['bottomEnd']`), the
|
|
|
399
399
|
would rule every existing tree, including the picker-sized and `size="xs"` outlines where a rule
|
|
400
400
|
every 24px is noise rather than structure. A tree used as page navigation opts in.
|
|
401
401
|
|
|
402
|
+
- **`Image size` / `fit` / `caption` have no antd counterpart.** antd's Image takes `width` /
|
|
403
|
+
`height` on the frame and the picture, and those are ported as antd has them (a fixed height
|
|
404
|
+
crops with `fit`, default `cover`, where antd stretches). godx adds `size?: "sm" | "md" | "lg"`
|
|
405
|
+
— the Thumbnail height scale at `--thumbnail-width-ratio` (4 / 3) — `fit?: "cover" | "contain"`,
|
|
406
|
+
and `caption`, a figcaption held to the picture's width so a file name truncates under it.
|
|
407
|
+
|
|
402
408
|
- **`Timeline density` has no antd counterpart.** antd's Timeline spaces items with one fixed
|
|
403
409
|
token (`itemPaddingBottom`, 20px) and offers no size or density prop. godx adds
|
|
404
410
|
`density?: "default" | "compact"` — the ListRow-shaped subset of `DensityProp` — driving one
|
|
@@ -212,7 +212,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
212
212
|
| Actions | ✓ | · | N/A | N/A | · | · | · | · | · | · |
|
|
213
213
|
| ThoughtChain | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
214
214
|
| OrgChart | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
215
|
-
| Image | ✓ |
|
|
215
|
+
| Image | ✓ | · | N/A | N/A | · | · | · | · | · | · |
|
|
216
216
|
| Attachments | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
217
217
|
| Marquee | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
218
218
|
| Masonry | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
@@ -124,6 +124,46 @@ export default function Demo() {
|
|
|
124
124
|
</Flex>
|
|
125
125
|
</CardContent>
|
|
126
126
|
</Card>
|
|
127
|
+
|
|
128
|
+
<Card>
|
|
129
|
+
<CardHeader>
|
|
130
|
+
<CardTitle level={2}>Thumbnail size · fit · caption</CardTitle>
|
|
131
|
+
<CardDescription>
|
|
132
|
+
size puts the frame on the Thumbnail height scale (sm 64px, md 96px, lg 160px) at 4:3,
|
|
133
|
+
cropped to fill; fit="contain" letterboxes instead. caption keeps a long
|
|
134
|
+
file name under the picture, truncated at the picture's width.
|
|
135
|
+
</CardDescription>
|
|
136
|
+
</CardHeader>
|
|
137
|
+
<CardContent>
|
|
138
|
+
<ImagePreviewGroup>
|
|
139
|
+
<Flex gap="sm" wrap align="start">
|
|
140
|
+
<Image
|
|
141
|
+
src={shotLandscape}
|
|
142
|
+
size="md"
|
|
143
|
+
alt="Dashboard"
|
|
144
|
+
caption={
|
|
145
|
+
<Text size="xs" truncate>
|
|
146
|
+
dashboard-after-the-fix-2026-09-30-full-resolution.png
|
|
147
|
+
</Text>
|
|
148
|
+
}
|
|
149
|
+
/>
|
|
150
|
+
<Image
|
|
151
|
+
src={shotPortrait}
|
|
152
|
+
size="md"
|
|
153
|
+
fit="contain"
|
|
154
|
+
alt="List screen"
|
|
155
|
+
caption={
|
|
156
|
+
<Text size="xs" truncate>
|
|
157
|
+
list-screen.png
|
|
158
|
+
</Text>
|
|
159
|
+
}
|
|
160
|
+
/>
|
|
161
|
+
<Image src={coverTerrain} size="sm" alt="Cover image" />
|
|
162
|
+
<Image src={portraitIris} size="lg" alt="Portrait" />
|
|
163
|
+
</Flex>
|
|
164
|
+
</ImagePreviewGroup>
|
|
165
|
+
</CardContent>
|
|
166
|
+
</Card>
|
|
127
167
|
</Flex>
|
|
128
168
|
</PageContainer>
|
|
129
169
|
);
|