@godxjp/ui 31.18.0 → 31.19.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.
@@ -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.18.0.** If the project you are editing has a different
6
+ **This catalog describes `@godxjp/ui` 31.19.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.
@@ -47,7 +47,7 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
47
47
  task is a task** — "build a settings page", "confirm a destructive delete", "a list page with
48
48
  filters" — start HERE, not at the components. Then fetch `patterns/<name>.json` for complete,
49
49
  copy-paste-ready code. A component index answers "does X exist"; it cannot answer "build Y".
50
- 1. `components-index.json` — 49 KB, all 179 components as name + group +
50
+ 1. `components-index.json` — 49 KB, all 181 components as name + group +
51
51
  tagline. Read this when you already know the SHAPE you need. Each entry may carry `absorbed`:
52
52
  names that **do not exist** and map to it — `Combobox`, `Autocomplete`, `CountrySelect` and
53
53
  `SearchSelect` are all `Select`. If you are about to hand-roll something, search this field
@@ -0,0 +1,64 @@
1
+ {
2
+ "docPath": "docs/data-display/markdown.tsx",
3
+ "example": "import { Prose } from \"@godxjp/ui/data-display\";\nimport { Markdown } from \"@godxjp/markdown\";\n\n<Prose measure=\"narrow\">\n <Markdown resolveUrl={(url) => (url.startsWith(\"asset:\") ? assetUrl(url) : undefined)}>\n {page.body}\n </Markdown>\n</Prose>",
4
+ "group": "data-display",
5
+ "importPath": "@godxjp/markdown",
6
+ "name": "Markdown",
7
+ "props": [
8
+ {
9
+ "description": "The Markdown source.",
10
+ "name": "children",
11
+ "required": true,
12
+ "type": "string"
13
+ },
14
+ {
15
+ "description": "Host markers (callouts, embeds), run after GFM. Their output is still sanitised — allow marker attributes with `schema`.",
16
+ "name": "remarkPlugins",
17
+ "type": "PluggableList"
18
+ },
19
+ {
20
+ "description": "Tags / attributes a host plugin needs. ADDITIVE: it can never widen the URL policy or bring raw HTML back.",
21
+ "name": "schema",
22
+ "type": "{ tagNames?: string[]; attributes?: Record<string, …> }"
23
+ },
24
+ {
25
+ "description": "Map a host scheme (`asset:…`, wiki links) to a real URL. Runs BEFORE the sanitiser, which then judges the result.",
26
+ "name": "resolveUrl",
27
+ "type": "(url, key) => string | undefined"
28
+ },
29
+ {
30
+ "description": "Server-assigned anchors instead of GitHub slugs.",
31
+ "name": "headingId",
32
+ "type": "({ depth, text, index }) => string | undefined"
33
+ },
34
+ {
35
+ "description": "Element overrides (react-markdown). A host `pre` replaces the Mermaid default.",
36
+ "name": "components",
37
+ "type": "Components"
38
+ },
39
+ {
40
+ "description": "Run AFTER the sanitiser — presentation only.",
41
+ "name": "rehypePlugins",
42
+ "type": "PluggableList"
43
+ },
44
+ {
45
+ "defaultValue": "true",
46
+ "description": "`false` keeps ```mermaid fences as code. Diagrams need the optional peer `mermaid`.",
47
+ "name": "mermaid",
48
+ "type": "boolean"
49
+ }
50
+ ],
51
+ "related": [
52
+ "Prose — the typography wrapper this renders into.",
53
+ "MarkdownEditor — editing; its preview is this renderer.",
54
+ "CodeBlock — a single block of preformatted text, not a document."
55
+ ],
56
+ "rules": [],
57
+ "storyPath": "data-display/markdown.tsx",
58
+ "tagline": "The one Markdown renderer for GoDX apps (sibling package `@godxjp/markdown`, versioned with the kit): GFM + GitHub heading anchors, one sanitiser schema (no raw HTML; http/https/mailto/relative URLs only), and ```mermaid drawn only after its SVG passes a fail-closed gate (gh#1108). Wrap it in `Prose`.",
59
+ "usage": [
60
+ "DO `<Prose><Markdown>{body}</Markdown></Prose>` for every rendered body (wiki page, issue, mail).",
61
+ "DO record `MARKDOWN_FORMAT` and `RENDERER_VERSION` on stored versions.",
62
+ "DON'T assemble react-markdown + rehype-sanitize per app, add rehype-raw, or render Mermaid yourself — `checkMermaidSvg` is the gate."
63
+ ]
64
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "docPath": "docs/data-entry/markdown-editor.tsx",
3
+ "example": "import { MarkdownEditor } from \"@godxjp/editor\";\nimport { FormField } from \"@godxjp/ui/data-entry\";\n\n<FormField id=\"body\" label=\"本文\">\n <MarkdownEditor\n value={body}\n onValueChange={setBody}\n upload={async (file) => ({ url: await storage.put(file), name: file.name })}\n />\n</FormField>",
4
+ "group": "data-entry",
5
+ "importPath": "@godxjp/editor",
6
+ "name": "MarkdownEditor",
7
+ "props": [
8
+ {
9
+ "description": "Controlled Markdown text (with `onValueChange`).",
10
+ "name": "value",
11
+ "type": "string"
12
+ },
13
+ {
14
+ "description": "Uncontrolled initial text.",
15
+ "name": "defaultValue",
16
+ "type": "string"
17
+ },
18
+ {
19
+ "description": "Every change: typing, toolbar, uploads, undo.",
20
+ "name": "onValueChange",
21
+ "type": "(value: string) => void"
22
+ },
23
+ {
24
+ "description": "Controlled view (with `onModeChange`); `defaultMode` for uncontrolled. Default `write`.",
25
+ "name": "mode",
26
+ "type": "\"write\" | \"preview\" | \"split\""
27
+ },
28
+ {
29
+ "description": "Stores a pasted / dropped / attached file; the HOST decides where. A placeholder becomes `![name](url)` (images) or `[name](url)`; a failure removes it and names the file.",
30
+ "name": "upload",
31
+ "type": "(file: File) => Promise<{ url: string; name?: string }>"
32
+ },
33
+ {
34
+ "description": "Refuses files with this message, with or without `upload`; the attach button carries the reason and shows it instead of opening the picker (gh#1114).",
35
+ "name": "uploadBlockedReason",
36
+ "type": "string | null"
37
+ },
38
+ {
39
+ "description": "Replace the preview (an app with its own embeds).",
40
+ "name": "renderPreview",
41
+ "type": "(value: string) => ReactNode"
42
+ },
43
+ {
44
+ "description": "Extra toolbar actions — the extension point for new block types (`api`: value, selection, edit, insert, focus).",
45
+ "name": "actions",
46
+ "type": "{ key, label, icon, run(api) }[]"
47
+ },
48
+ {
49
+ "description": "Override any string (defaults: the kit's ja / en / vi catalogue).",
50
+ "name": "labels",
51
+ "type": "Partial<MarkdownEditorLabels>"
52
+ }
53
+ ],
54
+ "related": [
55
+ "Textarea — plain multi-line text; this is Textarea plus Markdown tooling.",
56
+ "Markdown — rendering a stored body."
57
+ ],
58
+ "rules": [],
59
+ "storyPath": "data-entry/markdown-editor.tsx",
60
+ "tagline": "Markdown editor (sibling package `@godxjp/editor`, versioned with the kit): the kit's Textarea with a WAI-ARIA formatting toolbar, write / preview / side by side (preview via `@godxjp/markdown`), IME-safe ⌘/Ctrl+B·I·K, one undo step per toolbar edit, and paste / drop / attach through a host `upload` (gh#1109).",
61
+ "usage": [
62
+ "DO put it inside `FormField` — `id` / `aria-*` reach the textarea.",
63
+ "DO keep a host autocomplete (ChatSuggestion) by passing its `onKeyDown`: it runs first, and `preventDefault()` skips the editor's shortcut.",
64
+ "DON'T build a toolbar over a bare Textarea, or a rich-text surface — this is the shared editor."
65
+ ]
66
+ }
@@ -16,6 +16,11 @@
16
16
  "name": "imageSize",
17
17
  "type": "\"fit\" | \"original\""
18
18
  },
19
+ {
20
+ "description": "Reading line length (gh#1112): caps the inline size at the `--page-measure-*` token — the same vocabulary and tokens as `Flex measure` / `PageContainer measure` (narrow 42rem, medium 48rem sit in the 45–75 character band). A cap, not a centred column: the body keeps its start edge under its heading. Use it on a document/wiki/decision body instead of narrowing the whole page column; title and metadata stay full width. Unset = full width.",
21
+ "name": "measure",
22
+ "type": "\"narrow\" | \"medium\" | \"wide\""
23
+ },
19
24
  {
20
25
  "description": "The rendered content.",
21
26
  "name": "children",
@@ -301,6 +301,16 @@
301
301
  "name": "CodeBlock",
302
302
  "tagline": "A block of preformatted text (request and response bodies, console output, snippets): mono, muted surface, soft-wrapped long lines by default, and an optional height cap that scrolls inside the block instead of pushing the page."
303
303
  },
304
+ {
305
+ "group": "data-display",
306
+ "name": "Markdown",
307
+ "tagline": "The one Markdown renderer for GoDX apps (sibling package `@godxjp/markdown`, versioned with the kit): GFM + GitHub heading anchors, one sanitiser schema (no raw HTML; http/https/mailto/relative URLs only), and ```mermaid drawn only after its SVG passes a fail-closed gate (gh#1108). Wrap it in `Prose`."
308
+ },
309
+ {
310
+ "group": "data-entry",
311
+ "name": "MarkdownEditor",
312
+ "tagline": "Markdown editor (sibling package `@godxjp/editor`, versioned with the kit): the kit's Textarea with a WAI-ARIA formatting toolbar, write / preview / side by side (preview via `@godxjp/markdown`), IME-safe ⌘/Ctrl+B·I·K, one undo step per toolbar edit, and paste / drop / attach through a host `upload` (gh#1109)."
313
+ },
304
314
  {
305
315
  "group": "data-display",
306
316
  "name": "Prose",
@@ -4987,6 +4987,136 @@
4987
4987
  "A stack trace in an error detail sheet: `wrap={false}` so frames stay on one line, scrolled horizontally."
4988
4988
  ]
4989
4989
  },
4990
+ {
4991
+ "docPath": "docs/data-display/markdown.tsx",
4992
+ "example": "import { Prose } from \"@godxjp/ui/data-display\";\nimport { Markdown } from \"@godxjp/markdown\";\n\n<Prose measure=\"narrow\">\n <Markdown resolveUrl={(url) => (url.startsWith(\"asset:\") ? assetUrl(url) : undefined)}>\n {page.body}\n </Markdown>\n</Prose>",
4993
+ "group": "data-display",
4994
+ "importPath": "@godxjp/markdown",
4995
+ "name": "Markdown",
4996
+ "props": [
4997
+ {
4998
+ "description": "The Markdown source.",
4999
+ "name": "children",
5000
+ "required": true,
5001
+ "type": "string"
5002
+ },
5003
+ {
5004
+ "description": "Host markers (callouts, embeds), run after GFM. Their output is still sanitised — allow marker attributes with `schema`.",
5005
+ "name": "remarkPlugins",
5006
+ "type": "PluggableList"
5007
+ },
5008
+ {
5009
+ "description": "Tags / attributes a host plugin needs. ADDITIVE: it can never widen the URL policy or bring raw HTML back.",
5010
+ "name": "schema",
5011
+ "type": "{ tagNames?: string[]; attributes?: Record<string, …> }"
5012
+ },
5013
+ {
5014
+ "description": "Map a host scheme (`asset:…`, wiki links) to a real URL. Runs BEFORE the sanitiser, which then judges the result.",
5015
+ "name": "resolveUrl",
5016
+ "type": "(url, key) => string | undefined"
5017
+ },
5018
+ {
5019
+ "description": "Server-assigned anchors instead of GitHub slugs.",
5020
+ "name": "headingId",
5021
+ "type": "({ depth, text, index }) => string | undefined"
5022
+ },
5023
+ {
5024
+ "description": "Element overrides (react-markdown). A host `pre` replaces the Mermaid default.",
5025
+ "name": "components",
5026
+ "type": "Components"
5027
+ },
5028
+ {
5029
+ "description": "Run AFTER the sanitiser — presentation only.",
5030
+ "name": "rehypePlugins",
5031
+ "type": "PluggableList"
5032
+ },
5033
+ {
5034
+ "defaultValue": "true",
5035
+ "description": "`false` keeps ```mermaid fences as code. Diagrams need the optional peer `mermaid`.",
5036
+ "name": "mermaid",
5037
+ "type": "boolean"
5038
+ }
5039
+ ],
5040
+ "related": [
5041
+ "Prose — the typography wrapper this renders into.",
5042
+ "MarkdownEditor — editing; its preview is this renderer.",
5043
+ "CodeBlock — a single block of preformatted text, not a document."
5044
+ ],
5045
+ "rules": [],
5046
+ "storyPath": "data-display/markdown.tsx",
5047
+ "tagline": "The one Markdown renderer for GoDX apps (sibling package `@godxjp/markdown`, versioned with the kit): GFM + GitHub heading anchors, one sanitiser schema (no raw HTML; http/https/mailto/relative URLs only), and ```mermaid drawn only after its SVG passes a fail-closed gate (gh#1108). Wrap it in `Prose`.",
5048
+ "usage": [
5049
+ "DO `<Prose><Markdown>{body}</Markdown></Prose>` for every rendered body (wiki page, issue, mail).",
5050
+ "DO record `MARKDOWN_FORMAT` and `RENDERER_VERSION` on stored versions.",
5051
+ "DON'T assemble react-markdown + rehype-sanitize per app, add rehype-raw, or render Mermaid yourself — `checkMermaidSvg` is the gate."
5052
+ ]
5053
+ },
5054
+ {
5055
+ "docPath": "docs/data-entry/markdown-editor.tsx",
5056
+ "example": "import { MarkdownEditor } from \"@godxjp/editor\";\nimport { FormField } from \"@godxjp/ui/data-entry\";\n\n<FormField id=\"body\" label=\"本文\">\n <MarkdownEditor\n value={body}\n onValueChange={setBody}\n upload={async (file) => ({ url: await storage.put(file), name: file.name })}\n />\n</FormField>",
5057
+ "group": "data-entry",
5058
+ "importPath": "@godxjp/editor",
5059
+ "name": "MarkdownEditor",
5060
+ "props": [
5061
+ {
5062
+ "description": "Controlled Markdown text (with `onValueChange`).",
5063
+ "name": "value",
5064
+ "type": "string"
5065
+ },
5066
+ {
5067
+ "description": "Uncontrolled initial text.",
5068
+ "name": "defaultValue",
5069
+ "type": "string"
5070
+ },
5071
+ {
5072
+ "description": "Every change: typing, toolbar, uploads, undo.",
5073
+ "name": "onValueChange",
5074
+ "type": "(value: string) => void"
5075
+ },
5076
+ {
5077
+ "description": "Controlled view (with `onModeChange`); `defaultMode` for uncontrolled. Default `write`.",
5078
+ "name": "mode",
5079
+ "type": "\"write\" | \"preview\" | \"split\""
5080
+ },
5081
+ {
5082
+ "description": "Stores a pasted / dropped / attached file; the HOST decides where. A placeholder becomes `![name](url)` (images) or `[name](url)`; a failure removes it and names the file.",
5083
+ "name": "upload",
5084
+ "type": "(file: File) => Promise<{ url: string; name?: string }>"
5085
+ },
5086
+ {
5087
+ "description": "Refuses files with this message, with or without `upload`; the attach button carries the reason and shows it instead of opening the picker (gh#1114).",
5088
+ "name": "uploadBlockedReason",
5089
+ "type": "string | null"
5090
+ },
5091
+ {
5092
+ "description": "Replace the preview (an app with its own embeds).",
5093
+ "name": "renderPreview",
5094
+ "type": "(value: string) => ReactNode"
5095
+ },
5096
+ {
5097
+ "description": "Extra toolbar actions — the extension point for new block types (`api`: value, selection, edit, insert, focus).",
5098
+ "name": "actions",
5099
+ "type": "{ key, label, icon, run(api) }[]"
5100
+ },
5101
+ {
5102
+ "description": "Override any string (defaults: the kit's ja / en / vi catalogue).",
5103
+ "name": "labels",
5104
+ "type": "Partial<MarkdownEditorLabels>"
5105
+ }
5106
+ ],
5107
+ "related": [
5108
+ "Textarea — plain multi-line text; this is Textarea plus Markdown tooling.",
5109
+ "Markdown — rendering a stored body."
5110
+ ],
5111
+ "rules": [],
5112
+ "storyPath": "data-entry/markdown-editor.tsx",
5113
+ "tagline": "Markdown editor (sibling package `@godxjp/editor`, versioned with the kit): the kit's Textarea with a WAI-ARIA formatting toolbar, write / preview / side by side (preview via `@godxjp/markdown`), IME-safe ⌘/Ctrl+B·I·K, one undo step per toolbar edit, and paste / drop / attach through a host `upload` (gh#1109).",
5114
+ "usage": [
5115
+ "DO put it inside `FormField` — `id` / `aria-*` reach the textarea.",
5116
+ "DO keep a host autocomplete (ChatSuggestion) by passing its `onKeyDown`: it runs first, and `preventDefault()` skips the editor's shortcut.",
5117
+ "DON'T build a toolbar over a bare Textarea, or a rich-text surface — this is the shared editor."
5118
+ ]
5119
+ },
4990
5120
  {
4991
5121
  "example": "import { Prose } from \"@godxjp/ui/data-display\";\nimport Markdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n\n<Prose size=\"sm\">\n <Markdown remarkPlugins={[remarkGfm]}>{issue.description}</Markdown>\n</Prose>",
4992
5122
  "group": "data-display",
@@ -5005,6 +5135,11 @@
5005
5135
  "name": "imageSize",
5006
5136
  "type": "\"fit\" | \"original\""
5007
5137
  },
5138
+ {
5139
+ "description": "Reading line length (gh#1112): caps the inline size at the `--page-measure-*` token — the same vocabulary and tokens as `Flex measure` / `PageContainer measure` (narrow 42rem, medium 48rem sit in the 45–75 character band). A cap, not a centred column: the body keeps its start edge under its heading. Use it on a document/wiki/decision body instead of narrowing the whole page column; title and metadata stay full width. Unset = full width.",
5140
+ "name": "measure",
5141
+ "type": "\"narrow\" | \"medium\" | \"wide\""
5142
+ },
5008
5143
  {
5009
5144
  "description": "The rendered content.",
5010
5145
  "name": "children",
package/agent/index.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "counts": {
3
3
  "anti-ai-tells": 26,
4
- "components": 179,
4
+ "components": 181,
5
5
  "patterns": 21,
6
6
  "rules": 50,
7
7
  "tokens": 2129,
@@ -10,7 +10,7 @@
10
10
  "files": [
11
11
  {
12
12
  "file": "components-index.json",
13
- "note": "49 KB — name + group + tagline for all 179. FETCH THIS FIRST, then fetch only the components you chose.",
13
+ "note": "49 KB — name + group + tagline for all 181. FETCH THIS FIRST, then fetch only the components you chose.",
14
14
  "url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json"
15
15
  },
16
16
  {
@@ -48,7 +48,7 @@
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.18.0/agent/index.json"
51
+ "pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.19.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",
@@ -62,5 +62,5 @@
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.18.0"
65
+ "version": "31.19.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: 179 components, 2129 design tokens,
4
- > 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.18.0.
3
+ > A Japanese-enterprise React design system: 181 components, 2129 design tokens,
4
+ > 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.19.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.18.0`). It is searchable and version-locked. These files exist for agents
7
+ (`npx @godxjp/ui-mcp@31.19.0`). It is searchable and version-locked. These files exist for agents
8
8
  that can only fetch URLs.
9
9
 
10
10
  ## Start
@@ -15,7 +15,7 @@ that can only fetch URLs.
15
15
  ## Catalog
16
16
 
17
17
  - [patterns-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/patterns-index.json): 21 whole-task patterns (name, tagline, tags). Start here when the task is a TASK — "build a settings page" — then fetch `patterns/<name>.json` for complete code.
18
- - [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 49 KB — all 179 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
18
+ - [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 49 KB — all 181 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
19
19
  - [components/&lt;Name&gt;.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
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, 1814 `component` knobs.
@@ -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.18.0/agent/...`. A catalog that does not match the installed
29
+ the tag: `.../godx-jp/godxjp-ui/v31.19.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.
@@ -1,7 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cn } from "../../lib/utils.js";
4
- const Prose = React.forwardRef(function Prose2({ size = "md", imageSize = "fit", className, children, ...rest }, ref) {
4
+ const Prose = React.forwardRef(function Prose2({ size = "md", imageSize = "fit", measure, className, children, ...rest }, ref) {
5
5
  return /* @__PURE__ */ jsx(
6
6
  "div",
7
7
  {
@@ -9,6 +9,7 @@ const Prose = React.forwardRef(function Prose2({ size = "md", imageSize = "fit",
9
9
  "data-slot": "prose",
10
10
  "data-size": size === "md" ? void 0 : size,
11
11
  "data-image-size": imageSize === "fit" ? void 0 : imageSize,
12
+ "data-measure": measure,
12
13
  className: cn("ui-prose", className),
13
14
  ...rest,
14
15
  children
@@ -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.18.0",
3
+ "version": "31.19.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,
@@ -35,11 +35,20 @@ export type CodeBlockProp = {
35
35
  * @see Prose — typography for rendered content (Markdown, CMS bodies). Styles descendant semantic
36
36
  * HTML from the tokens; it has no opinion about where the HTML comes from.
37
37
  */
38
+ import type { FlexMeasureProp } from "./layout.prop.js";
38
39
  export type ProseProp = {
39
40
  /** Body size. `md` is the page body size; `sm` is the compact step. Default `md`. */
40
41
  size?: Extract<SizeProp, "sm" | "md">;
41
42
  /** `fit` scales images to the column (default); `original` shows them at their authored size. */
42
43
  imageSize?: "fit" | "original";
44
+ /**
45
+ * Caps the line length for reading (gh#1112): `narrow` / `medium` / `wide` read the same
46
+ * `--page-measure-*` tokens as `Flex measure` and `PageContainer measure`, so one theme knob sets
47
+ * every reading column. `narrow` (42rem) and `medium` (48rem) sit in the 45–75 character band.
48
+ * Unlike Flex it does NOT centre: the body keeps its start edge under the heading beside it.
49
+ * Unset = the full width of the container.
50
+ */
51
+ measure?: FlexMeasureProp;
43
52
  className?: ClassNameProp;
44
53
  children?: ChildrenProp;
45
54
  };
@@ -1285,6 +1285,18 @@
1285
1285
  font-size: var(--prose-font-size-sm);
1286
1286
  }
1287
1287
 
1288
+ .ui-prose[data-measure="narrow"] {
1289
+ max-inline-size: var(--page-measure-narrow);
1290
+ }
1291
+
1292
+ .ui-prose[data-measure="medium"] {
1293
+ max-inline-size: var(--page-measure-medium);
1294
+ }
1295
+
1296
+ .ui-prose[data-measure="wide"] {
1297
+ max-inline-size: var(--page-measure-wide);
1298
+ }
1299
+
1288
1300
  .ui-prose[data-image-size="original"] {
1289
1301
  overflow-x: auto;
1290
1302
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "31.18.0",
2
+ "version": "31.19.0",
3
3
  "generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
4
4
  "base": "base.css",
5
5
  "fonts": "fonts.css",
@@ -644,6 +644,21 @@
644
644
  "logo-layout.css"
645
645
  ]
646
646
  },
647
+ "Markdown": {
648
+ "layers": []
649
+ },
650
+ "MarkdownEditor": {
651
+ "layers": [
652
+ "layout.css",
653
+ "control.css",
654
+ "toggle.css",
655
+ "card-layout.css",
656
+ "text-layout.css",
657
+ "dialog-layout.css",
658
+ "data-display-layout.css",
659
+ "navigation-layout.css"
660
+ ]
661
+ },
647
662
  "Marquee": {
648
663
  "layers": [
649
664
  "motion.css",
@@ -3,8 +3,8 @@
3
3
  > Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
4
4
  > Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
5
5
 
6
- - Public components: **179**
7
- - With ≥1 frame: **155** · zero-frame: **24**
6
+ - Public components: **181**
7
+ - With ≥1 frame: **157** · zero-frame: **24**
8
8
  - Fully covered (every contract axis declared): **0**
9
9
 
10
10
  ## UNTESTED — no `/frame/**` route
@@ -98,6 +98,8 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
98
98
  | EmptyState | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
99
99
  | Progress | ✓ | · | N/A | · | · | · | · | · | · | · |
100
100
  | CodeBlock | ✓ | · | N/A | N/A | · | · | · | · | · | · |
101
+ | Markdown | ✓ | · | · | · | · | · | · | · | · | · |
102
+ | MarkdownEditor | ✓ | · | · | · | · | · | · | · | · | · |
101
103
  | Prose | ✓ | · | N/A | N/A | · | · | · | · | · | · |
102
104
  | Timeline | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
103
105
  | TimelineGrid | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "31.18.0",
4
- "godxUiMcp": "31.18.0",
3
+ "version": "31.19.0",
4
+ "godxUiMcp": "31.19.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -125,8 +125,10 @@ const byLength = [...componentNames].sort((a, b) => b.length - a.length);
125
125
 
126
126
  const used = new Set();
127
127
  let sawNamespace = false;
128
+ // `@godxjp/editor` / `@godxjp/markdown` too (gh#1114): their components render kit components, and
129
+ // the manifest maps `MarkdownEditor` to the layers those need.
128
130
  const IMPORT =
129
- /(?:import|export)\s+(type\s+)?([^;'"]*?)\s*from\s*["'](@godxjp\/ui(?:\/[^"']*)?)["']/g;
131
+ /(?:import|export)\s+(type\s+)?([^;'"]*?)\s*from\s*["'](@godxjp\/(?:ui|editor|markdown)(?:\/[^"']*)?)["']/g;
130
132
  for (const file of new Set(sources)) {
131
133
  const src = readFileSync(file, "utf8");
132
134
  for (const m of src.matchAll(IMPORT)) {