@godxjp/ui 31.26.1 → 31.27.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 +5 -5
- package/agent/components/BlockEditor.json +83 -0
- package/agent/components/Markdown.json +5 -0
- package/agent/components-index.json +5 -0
- package/agent/components.json +88 -0
- package/agent/index.json +6 -6
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +30 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/styles/data-display-layout.css +225 -2
- package/dist/styles/focus-ring.css +2 -0
- package/dist/styles/layers.json +10 -1
- package/dist/tokens/components/data-display.css +8 -0
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/data-entry/block-editor.tsx +105 -0
- package/docs/i18n/messages/en.json +24 -0
- package/docs/i18n/messages/ja.json +24 -0
- package/docs/i18n/messages/vi.json +24 -0
- package/package.json +25 -4
- package/scripts/prune-css.mjs +1 -1
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.27.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` — 50 KB, all
|
|
50
|
+
1. `components-index.json` — 50 KB, all 182 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
|
|
@@ -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` — 2142 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
|
+
1827 `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` | 1827 | 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.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"docPath": "docs/data-entry/block-editor.tsx",
|
|
3
|
+
"example": "import { BlockEditor } from \"@godxjp/block-editor\";\nimport { FormField } from \"@godxjp/ui/data-entry\";\n\n<FormField id=\"body\" label=\"本文\">\n <BlockEditor\n value={body}\n onValueChange={setBody}\n upload={async (file, { signal }) => ({ url: await media.put(file, { signal }), name: file.name })}\n suggestWikilinks={(q) => pages.search(q)}\n />\n</FormField>",
|
|
4
|
+
"group": "data-entry",
|
|
5
|
+
"importPath": "@godxjp/block-editor",
|
|
6
|
+
"name": "BlockEditor",
|
|
7
|
+
"props": [
|
|
8
|
+
{
|
|
9
|
+
"description": "Controlled Markdown body (with `onValueChange`).",
|
|
10
|
+
"name": "value",
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"description": "Uncontrolled initial body.",
|
|
15
|
+
"name": "defaultValue",
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"description": "Canonical Markdown after each edit — `serialize(editor.getJSON())`, identical to `normalize(body)` from `@godxjp/markdown/codec` (CODEC_ID kit-md@1).",
|
|
20
|
+
"name": "onValueChange",
|
|
21
|
+
"type": "(markdown: string) => void"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"description": "Stores a pasted / dropped / chosen file (return `asset:<id>` if you like). An inline placeholder shows progress; failure offers Retry / Remove; deleting the placeholder aborts `signal`. Images become ``, other files a link.",
|
|
25
|
+
"name": "upload",
|
|
26
|
+
"type": "(file: File, options: { signal: AbortSignal }) => Promise<{ url: string; name?: string }>"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"description": "The host's media library; the `/` Image row opens it instead of a file picker.",
|
|
30
|
+
"name": "pickMedia",
|
|
31
|
+
"type": "() => Promise<{ url: string; name?: string } | null>"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"description": "Refuse files with this message.",
|
|
35
|
+
"name": "uploadBlockedReason",
|
|
36
|
+
"type": "string | null"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"description": "`[[` suggestions from the host's page index; picking inserts `[[target|label]]`.",
|
|
40
|
+
"name": "suggestWikilinks",
|
|
41
|
+
"type": "(query: string) => WikilinkSuggestion[] | Promise<WikilinkSuggestion[]>"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"description": "Renders a block embed `![[target]]`; default is a labelled placeholder.",
|
|
45
|
+
"name": "renderEmbed",
|
|
46
|
+
"type": "(target: string) => ReactNode"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"description": "Resolves a stored image URL (`asset:<id>`) for display; the body keeps the original.",
|
|
50
|
+
"name": "resolveUrl",
|
|
51
|
+
"type": "(url: string) => string | undefined"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"description": "Extra `/` rows ({ key, label, icon, keywords?, run(api) }) — `api.insertMarkdown` inserts through the codec.",
|
|
55
|
+
"name": "actions",
|
|
56
|
+
"type": "BlockEditorAction[]"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"description": "Override any string (defaults: kit ja / en / vi).",
|
|
60
|
+
"name": "labels",
|
|
61
|
+
"type": "Partial<BlockEditorLabels>"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"description": "Not editable; the body still renders as Prose.",
|
|
65
|
+
"name": "disabled / readOnly",
|
|
66
|
+
"type": "boolean"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"related": [
|
|
70
|
+
"MarkdownEditor — a Textarea with Markdown tooling, for raw-Markdown editing.",
|
|
71
|
+
"Markdown — rendering a stored body (same grammar, renderer v4)."
|
|
72
|
+
],
|
|
73
|
+
"rules": [],
|
|
74
|
+
"storyPath": "data-entry/block-editor.tsx",
|
|
75
|
+
"tagline": "Notion / note.com style block editor (sibling package `@godxjp/block-editor`, versioned with the kit) that reads and writes MARKDOWN through `@godxjp/markdown/codec`: what onValueChange returns is byte-for-byte normalize(body). `/` block menu at the caret, ⋮⋮ handle (drag, turn into, duplicate, move, delete), floating format toolbar, `[[` wikilink suggestions, paste / drop uploads through the host, IME-safe, ja / en / vi (gh#1156).",
|
|
76
|
+
"usage": [
|
|
77
|
+
"DO store the Markdown it emits — it is already canonical; compute `normalize()` server-side from the same codec to verify.",
|
|
78
|
+
"DO give it a name: wrap in `FormField` or pass `aria-label` / `aria-labelledby` (the editable is a named `textbox`).",
|
|
79
|
+
"DO pass `upload` (and `pickMedia` for a library) instead of handling paste yourself.",
|
|
80
|
+
"DON'T render Markdown into it via HTML — pass `value`; HTML paste from other apps is handled by the schema.",
|
|
81
|
+
"Keyboard: `/` menu (↑↓ Enter Esc), Alt+Shift+↑/↓ moves a block, Mod+/ opens the block menu, Markdown shortcuts (`# `, `- `, `> `, ```` ``` ````, `---`)."
|
|
82
|
+
]
|
|
83
|
+
}
|
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
"name": "shortCellLength",
|
|
53
53
|
"type": "number | false"
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
"description": "Visible titles for GitHub-alert callouts (`> [!WARNING]`) that carry none of their own. English by default (the package has no i18n); pass localized strings. Grammar v1 (gh#1156): callouts, `:::toggle[summary]`, `::::columns`/`:::column{width=N}`, CJK-friendly emphasis — the same syntax the pure codec at `@godxjp/markdown/codec` (CODEC_ID kit-md@1, parse/serialize/normalize, DOM-free) and @godxjp/block-editor use.",
|
|
57
|
+
"name": "calloutTitles",
|
|
58
|
+
"type": "Partial<Record<'note' | 'tip' | 'important' | 'warning' | 'caution', string>>"
|
|
59
|
+
},
|
|
55
60
|
{
|
|
56
61
|
"defaultValue": "true",
|
|
57
62
|
"description": "`false` keeps ```mermaid fences as code. Diagrams need the optional peer `mermaid`.",
|
|
@@ -311,6 +311,11 @@
|
|
|
311
311
|
"name": "MarkdownEditor",
|
|
312
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
313
|
},
|
|
314
|
+
{
|
|
315
|
+
"group": "data-entry",
|
|
316
|
+
"name": "BlockEditor",
|
|
317
|
+
"tagline": "Notion / note.com style block editor (sibling package `@godxjp/block-editor`, versioned with the kit) that reads and writes MARKDOWN through `@godxjp/markdown/codec`: what onValueChange returns is byte-for-byte normalize(body). `/` block menu at the caret, ⋮⋮ handle (drag, turn into, duplicate, move, delete), floating format toolbar, `[[` wikilink suggestions, paste / drop uploads through the host, IME-safe, ja / en / vi (gh#1156)."
|
|
318
|
+
},
|
|
314
319
|
{
|
|
315
320
|
"group": "data-display",
|
|
316
321
|
"name": "Prose",
|
package/agent/components.json
CHANGED
|
@@ -5061,6 +5061,11 @@
|
|
|
5061
5061
|
"name": "shortCellLength",
|
|
5062
5062
|
"type": "number | false"
|
|
5063
5063
|
},
|
|
5064
|
+
{
|
|
5065
|
+
"description": "Visible titles for GitHub-alert callouts (`> [!WARNING]`) that carry none of their own. English by default (the package has no i18n); pass localized strings. Grammar v1 (gh#1156): callouts, `:::toggle[summary]`, `::::columns`/`:::column{width=N}`, CJK-friendly emphasis — the same syntax the pure codec at `@godxjp/markdown/codec` (CODEC_ID kit-md@1, parse/serialize/normalize, DOM-free) and @godxjp/block-editor use.",
|
|
5066
|
+
"name": "calloutTitles",
|
|
5067
|
+
"type": "Partial<Record<'note' | 'tip' | 'important' | 'warning' | 'caution', string>>"
|
|
5068
|
+
},
|
|
5064
5069
|
{
|
|
5065
5070
|
"defaultValue": "true",
|
|
5066
5071
|
"description": "`false` keeps ```mermaid fences as code. Diagrams need the optional peer `mermaid`.",
|
|
@@ -5148,6 +5153,89 @@
|
|
|
5148
5153
|
"DON'T build a toolbar over a bare Textarea, or a rich-text surface — this is the shared editor."
|
|
5149
5154
|
]
|
|
5150
5155
|
},
|
|
5156
|
+
{
|
|
5157
|
+
"docPath": "docs/data-entry/block-editor.tsx",
|
|
5158
|
+
"example": "import { BlockEditor } from \"@godxjp/block-editor\";\nimport { FormField } from \"@godxjp/ui/data-entry\";\n\n<FormField id=\"body\" label=\"本文\">\n <BlockEditor\n value={body}\n onValueChange={setBody}\n upload={async (file, { signal }) => ({ url: await media.put(file, { signal }), name: file.name })}\n suggestWikilinks={(q) => pages.search(q)}\n />\n</FormField>",
|
|
5159
|
+
"group": "data-entry",
|
|
5160
|
+
"importPath": "@godxjp/block-editor",
|
|
5161
|
+
"name": "BlockEditor",
|
|
5162
|
+
"props": [
|
|
5163
|
+
{
|
|
5164
|
+
"description": "Controlled Markdown body (with `onValueChange`).",
|
|
5165
|
+
"name": "value",
|
|
5166
|
+
"type": "string"
|
|
5167
|
+
},
|
|
5168
|
+
{
|
|
5169
|
+
"description": "Uncontrolled initial body.",
|
|
5170
|
+
"name": "defaultValue",
|
|
5171
|
+
"type": "string"
|
|
5172
|
+
},
|
|
5173
|
+
{
|
|
5174
|
+
"description": "Canonical Markdown after each edit — `serialize(editor.getJSON())`, identical to `normalize(body)` from `@godxjp/markdown/codec` (CODEC_ID kit-md@1).",
|
|
5175
|
+
"name": "onValueChange",
|
|
5176
|
+
"type": "(markdown: string) => void"
|
|
5177
|
+
},
|
|
5178
|
+
{
|
|
5179
|
+
"description": "Stores a pasted / dropped / chosen file (return `asset:<id>` if you like). An inline placeholder shows progress; failure offers Retry / Remove; deleting the placeholder aborts `signal`. Images become ``, other files a link.",
|
|
5180
|
+
"name": "upload",
|
|
5181
|
+
"type": "(file: File, options: { signal: AbortSignal }) => Promise<{ url: string; name?: string }>"
|
|
5182
|
+
},
|
|
5183
|
+
{
|
|
5184
|
+
"description": "The host's media library; the `/` Image row opens it instead of a file picker.",
|
|
5185
|
+
"name": "pickMedia",
|
|
5186
|
+
"type": "() => Promise<{ url: string; name?: string } | null>"
|
|
5187
|
+
},
|
|
5188
|
+
{
|
|
5189
|
+
"description": "Refuse files with this message.",
|
|
5190
|
+
"name": "uploadBlockedReason",
|
|
5191
|
+
"type": "string | null"
|
|
5192
|
+
},
|
|
5193
|
+
{
|
|
5194
|
+
"description": "`[[` suggestions from the host's page index; picking inserts `[[target|label]]`.",
|
|
5195
|
+
"name": "suggestWikilinks",
|
|
5196
|
+
"type": "(query: string) => WikilinkSuggestion[] | Promise<WikilinkSuggestion[]>"
|
|
5197
|
+
},
|
|
5198
|
+
{
|
|
5199
|
+
"description": "Renders a block embed `![[target]]`; default is a labelled placeholder.",
|
|
5200
|
+
"name": "renderEmbed",
|
|
5201
|
+
"type": "(target: string) => ReactNode"
|
|
5202
|
+
},
|
|
5203
|
+
{
|
|
5204
|
+
"description": "Resolves a stored image URL (`asset:<id>`) for display; the body keeps the original.",
|
|
5205
|
+
"name": "resolveUrl",
|
|
5206
|
+
"type": "(url: string) => string | undefined"
|
|
5207
|
+
},
|
|
5208
|
+
{
|
|
5209
|
+
"description": "Extra `/` rows ({ key, label, icon, keywords?, run(api) }) — `api.insertMarkdown` inserts through the codec.",
|
|
5210
|
+
"name": "actions",
|
|
5211
|
+
"type": "BlockEditorAction[]"
|
|
5212
|
+
},
|
|
5213
|
+
{
|
|
5214
|
+
"description": "Override any string (defaults: kit ja / en / vi).",
|
|
5215
|
+
"name": "labels",
|
|
5216
|
+
"type": "Partial<BlockEditorLabels>"
|
|
5217
|
+
},
|
|
5218
|
+
{
|
|
5219
|
+
"description": "Not editable; the body still renders as Prose.",
|
|
5220
|
+
"name": "disabled / readOnly",
|
|
5221
|
+
"type": "boolean"
|
|
5222
|
+
}
|
|
5223
|
+
],
|
|
5224
|
+
"related": [
|
|
5225
|
+
"MarkdownEditor — a Textarea with Markdown tooling, for raw-Markdown editing.",
|
|
5226
|
+
"Markdown — rendering a stored body (same grammar, renderer v4)."
|
|
5227
|
+
],
|
|
5228
|
+
"rules": [],
|
|
5229
|
+
"storyPath": "data-entry/block-editor.tsx",
|
|
5230
|
+
"tagline": "Notion / note.com style block editor (sibling package `@godxjp/block-editor`, versioned with the kit) that reads and writes MARKDOWN through `@godxjp/markdown/codec`: what onValueChange returns is byte-for-byte normalize(body). `/` block menu at the caret, ⋮⋮ handle (drag, turn into, duplicate, move, delete), floating format toolbar, `[[` wikilink suggestions, paste / drop uploads through the host, IME-safe, ja / en / vi (gh#1156).",
|
|
5231
|
+
"usage": [
|
|
5232
|
+
"DO store the Markdown it emits — it is already canonical; compute `normalize()` server-side from the same codec to verify.",
|
|
5233
|
+
"DO give it a name: wrap in `FormField` or pass `aria-label` / `aria-labelledby` (the editable is a named `textbox`).",
|
|
5234
|
+
"DO pass `upload` (and `pickMedia` for a library) instead of handling paste yourself.",
|
|
5235
|
+
"DON'T render Markdown into it via HTML — pass `value`; HTML paste from other apps is handled by the schema.",
|
|
5236
|
+
"Keyboard: `/` menu (↑↓ Enter Esc), Alt+Shift+↑/↓ moves a block, Mod+/ opens the block menu, Markdown shortcuts (`# `, `- `, `> `, ```` ``` ````, `---`)."
|
|
5237
|
+
]
|
|
5238
|
+
},
|
|
5151
5239
|
{
|
|
5152
5240
|
"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>",
|
|
5153
5241
|
"group": "data-display",
|
package/agent/index.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"counts": {
|
|
3
3
|
"anti-ai-tells": 26,
|
|
4
|
-
"components":
|
|
4
|
+
"components": 182,
|
|
5
5
|
"patterns": 21,
|
|
6
6
|
"rules": 50,
|
|
7
|
-
"tokens":
|
|
7
|
+
"tokens": 2142,
|
|
8
8
|
"vocabulary": 14
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
{
|
|
12
12
|
"file": "components-index.json",
|
|
13
|
-
"note": "50 KB — name + group + tagline for all
|
|
13
|
+
"note": "50 KB — name + group + tagline for all 182. 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,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.27.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": 1827,
|
|
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.27.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:
|
|
4
|
-
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.
|
|
3
|
+
> A Japanese-enterprise React design system: 182 components, 2142 design tokens,
|
|
4
|
+
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.27.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.27.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,10 +15,10 @@ 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): 50 KB — all
|
|
18
|
+
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 50 KB — all 182 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, 1827 `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.27.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
|
@@ -5231,6 +5231,36 @@
|
|
|
5231
5231
|
"tier": "component",
|
|
5232
5232
|
"value": "20rem"
|
|
5233
5233
|
},
|
|
5234
|
+
{
|
|
5235
|
+
"description": "Grammar v1 blocks (gh#1156). Columns sit this far apart and stack below 40rem; a toggle's summary is the control that opens it. Callouts reuse the <Callout> geometry (--callout-*).",
|
|
5236
|
+
"name": "--prose-columns-gap",
|
|
5237
|
+
"tier": "component",
|
|
5238
|
+
"value": "var(--space-6)"
|
|
5239
|
+
},
|
|
5240
|
+
{
|
|
5241
|
+
"description": "@godxjp/block-editor (gh#1156): the start gutter the ⋮⋮ / + handle sits in, and the editing surface's minimum height (an empty body is still a target you can click into).",
|
|
5242
|
+
"name": "--block-editor-gutter-inline-size",
|
|
5243
|
+
"tier": "component",
|
|
5244
|
+
"value": "calc(2 * var(--control-height-xs) + var(--space-2))"
|
|
5245
|
+
},
|
|
5246
|
+
{
|
|
5247
|
+
"description": "Data-display component tokens — small-by-design text knobs (rule #45/#46).",
|
|
5248
|
+
"name": "--block-editor-min-height",
|
|
5249
|
+
"tier": "component",
|
|
5250
|
+
"value": "var(--band-height-3xl)"
|
|
5251
|
+
},
|
|
5252
|
+
{
|
|
5253
|
+
"description": "The `/` and `[[` menus: wide enough for a label and its description, tall enough for ~8 rows before the list scrolls.",
|
|
5254
|
+
"name": "--block-editor-menu-inline-size",
|
|
5255
|
+
"tier": "component",
|
|
5256
|
+
"value": "16rem"
|
|
5257
|
+
},
|
|
5258
|
+
{
|
|
5259
|
+
"description": "Data-display component tokens — small-by-design text knobs (rule #45/#46).",
|
|
5260
|
+
"name": "--block-editor-menu-max-block-size",
|
|
5261
|
+
"tier": "component",
|
|
5262
|
+
"value": "20rem"
|
|
5263
|
+
},
|
|
5234
5264
|
{
|
|
5235
5265
|
"description": "gh#888 — φ tier freezes at :root; default = calc(var(--radius) / var(--radius-ratio) / var(--radius-ratio))",
|
|
5236
5266
|
"name": "--prose-code-radius",
|
|
@@ -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.27.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,
|
|
@@ -1142,7 +1142,7 @@
|
|
|
1142
1142
|
background: hsl(var(--muted));
|
|
1143
1143
|
padding: var(--code-block-space-inset);
|
|
1144
1144
|
color: var(--code-block-foreground, hsl(var(--foreground)));
|
|
1145
|
-
font-family: var(--font-mono);
|
|
1145
|
+
font-family: var(--font-family-mono);
|
|
1146
1146
|
font-size: var(--code-block-font-size);
|
|
1147
1147
|
line-height: var(--code-block-line-height);
|
|
1148
1148
|
white-space: pre-wrap;
|
|
@@ -1378,7 +1378,7 @@
|
|
|
1378
1378
|
}
|
|
1379
1379
|
|
|
1380
1380
|
.ui-prose :not(pre) > code {
|
|
1381
|
-
font-family: var(--font-mono);
|
|
1381
|
+
font-family: var(--font-family-mono);
|
|
1382
1382
|
font-size: var(--prose-code-font-size);
|
|
1383
1383
|
background: hsl(var(--muted));
|
|
1384
1384
|
padding-inline: var(--prose-code-space-inline);
|
|
@@ -1425,6 +1425,229 @@
|
|
|
1425
1425
|
max-inline-size: var(--prose-cell-image-max-inline-size);
|
|
1426
1426
|
}
|
|
1427
1427
|
|
|
1428
|
+
.ui-prose :is(th, td) img[width$="%"] {
|
|
1429
|
+
inline-size: auto;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
.ui-prose .ui-prose-callout {
|
|
1433
|
+
margin-block: var(--callout-space-stack);
|
|
1434
|
+
padding-block: var(--callout-space-inset-block);
|
|
1435
|
+
padding-inline: var(--callout-space-inset-inline);
|
|
1436
|
+
border-inline-start: var(--callout-rail-width) solid hsl(var(--info));
|
|
1437
|
+
border-start-end-radius: var(--callout-radius, var(--alert-radius, var(--card-radius, calc(var(--radius) * var(--radius-ratio)))));
|
|
1438
|
+
border-end-end-radius: var(--callout-radius, var(--alert-radius, var(--card-radius, calc(var(--radius) * var(--radius-ratio)))));
|
|
1439
|
+
background-color: var(--surface-info, hsl(var(--info) / var(--alert-bg-alpha)));
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
.ui-prose .ui-prose-callout[data-kind="tip"] {
|
|
1443
|
+
border-inline-start-color: hsl(var(--success));
|
|
1444
|
+
background-color: var(--surface-success, hsl(var(--success) / var(--alert-bg-alpha)));
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
.ui-prose .ui-prose-callout[data-kind="important"] {
|
|
1448
|
+
border-inline-start-color: hsl(var(--primary));
|
|
1449
|
+
background-color: hsl(var(--primary) / var(--alert-bg-alpha));
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.ui-prose .ui-prose-callout[data-kind="warning"] {
|
|
1453
|
+
border-inline-start-color: hsl(var(--warning));
|
|
1454
|
+
background-color: var(--surface-warning, hsl(var(--warning) / var(--alert-bg-alpha)));
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
.ui-prose .ui-prose-callout[data-kind="caution"] {
|
|
1458
|
+
border-inline-start-color: hsl(var(--destructive));
|
|
1459
|
+
background-color: var(--surface-destructive, hsl(var(--destructive) / var(--alert-bg-alpha)));
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
.ui-prose .ui-prose-callout-title {
|
|
1463
|
+
font-weight: var(--font-weight-medium);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
.ui-prose :is(.ui-prose-callout, .ui-prose-column, .ui-prose-toggle) > :first-child {
|
|
1467
|
+
margin-block-start: 0;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
.ui-prose :is(.ui-prose-callout, .ui-prose-column, .ui-prose-toggle) > :last-child {
|
|
1471
|
+
margin-block-end: 0;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
.ui-prose .ui-prose-toggle {
|
|
1475
|
+
margin-block: var(--prose-space-block);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
.ui-prose .ui-prose-toggle-summary {
|
|
1479
|
+
cursor: pointer;
|
|
1480
|
+
font-weight: var(--font-weight-medium);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
.ui-prose .ui-prose-toggle[open] > .ui-prose-toggle-summary {
|
|
1484
|
+
margin-block-end: var(--prose-space-block);
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
.ui-prose .ui-prose-columns {
|
|
1488
|
+
display: flex;
|
|
1489
|
+
gap: var(--prose-columns-gap);
|
|
1490
|
+
margin-block: var(--prose-space-block);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
.ui-prose .ui-prose-column {
|
|
1494
|
+
flex: var(--prose-column-grow, 1) 1 0;
|
|
1495
|
+
min-inline-size: 0;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
@media (width < 40rem) {
|
|
1499
|
+
.ui-prose .ui-prose-columns {
|
|
1500
|
+
flex-direction: column;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
.ui-block-editor {
|
|
1505
|
+
position: relative;
|
|
1506
|
+
padding-inline-start: var(--block-editor-gutter-inline-size);
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
.ui-block-editor-content {
|
|
1510
|
+
min-block-size: var(--block-editor-min-height);
|
|
1511
|
+
outline: none;
|
|
1512
|
+
white-space: pre-wrap;
|
|
1513
|
+
overflow-wrap: break-word;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.ui-block-editor-content .is-empty::before {
|
|
1517
|
+
content: attr(data-placeholder);
|
|
1518
|
+
float: inline-start;
|
|
1519
|
+
block-size: 0;
|
|
1520
|
+
color: hsl(var(--muted-foreground));
|
|
1521
|
+
pointer-events: none;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
.ui-block-editor-handle {
|
|
1525
|
+
position: absolute;
|
|
1526
|
+
inset-inline-start: 0;
|
|
1527
|
+
z-index: 1;
|
|
1528
|
+
display: flex;
|
|
1529
|
+
gap: var(--space-1);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
@media (hover: hover) {
|
|
1533
|
+
.ui-block-editor:not(:hover):not(:focus-within) .ui-block-editor-handle {
|
|
1534
|
+
opacity: 0;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
.ui-block-editor-content .ProseMirror-selectednode {
|
|
1539
|
+
outline: var(--stroke-md) solid hsl(var(--ring));
|
|
1540
|
+
outline-offset: var(--stroke-md);
|
|
1541
|
+
border-radius: calc(var(--radius) / var(--radius-ratio));
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
.ui-block-editor-menu {
|
|
1545
|
+
--popover-surface-inline-size: var(--block-editor-menu-inline-size);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
.ui-block-editor-menu [cmdk-list] {
|
|
1549
|
+
max-block-size: var(--block-editor-menu-max-block-size);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
.ui-block-editor-menu-icon {
|
|
1553
|
+
display: inline-flex;
|
|
1554
|
+
flex-shrink: 0;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
.ui-block-editor-menu-icon svg,
|
|
1558
|
+
.ui-block-editor-toolbar svg {
|
|
1559
|
+
inline-size: var(--control-icon-size);
|
|
1560
|
+
block-size: var(--control-icon-size);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.ui-block-editor-menu-text {
|
|
1564
|
+
display: flex;
|
|
1565
|
+
min-inline-size: 0;
|
|
1566
|
+
flex-direction: column;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
.ui-block-editor-menu-description {
|
|
1570
|
+
color: hsl(var(--muted-foreground));
|
|
1571
|
+
font-size: var(--font-size-xs, var(--font-size-sm));
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
.ui-block-editor-toolbar {
|
|
1575
|
+
z-index: var(--overlay-z-index);
|
|
1576
|
+
padding: var(--space-1);
|
|
1577
|
+
border: var(--stroke-hairline) solid hsl(var(--border));
|
|
1578
|
+
border-radius: var(--popover-radius, var(--radius));
|
|
1579
|
+
background-color: hsl(var(--popover) / var(--popover-alpha, 100%));
|
|
1580
|
+
color: hsl(var(--popover-foreground));
|
|
1581
|
+
box-shadow: var(--popover-shadow, var(--shadow-md));
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
.ui-block-editor-toolbar-row,
|
|
1585
|
+
.ui-block-editor-toolbar-link {
|
|
1586
|
+
display: flex;
|
|
1587
|
+
align-items: center;
|
|
1588
|
+
gap: var(--space-1);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
.ui-block-editor-wikilink {
|
|
1592
|
+
color: hsl(var(--prose-link-color, var(--text-link, var(--primary))));
|
|
1593
|
+
text-decoration-line: underline;
|
|
1594
|
+
text-decoration-style: dotted;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
.ui-block-editor-embed-inline,
|
|
1598
|
+
.ui-block-editor-raw-inline {
|
|
1599
|
+
font-family: var(--font-family-mono);
|
|
1600
|
+
font-size: var(--prose-code-font-size);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
.ui-block-editor-embed,
|
|
1604
|
+
.ui-block-editor-raw-block {
|
|
1605
|
+
margin-block: var(--prose-space-block);
|
|
1606
|
+
padding: var(--space-2) var(--space-3);
|
|
1607
|
+
border: var(--stroke-hairline) dashed hsl(var(--border));
|
|
1608
|
+
border-radius: calc(var(--radius) / var(--radius-ratio));
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
.ui-block-editor-raw-block-head {
|
|
1612
|
+
display: flex;
|
|
1613
|
+
align-items: center;
|
|
1614
|
+
justify-content: space-between;
|
|
1615
|
+
gap: var(--space-2);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
.ui-block-editor-raw-block-source {
|
|
1619
|
+
margin: 0;
|
|
1620
|
+
white-space: pre-wrap;
|
|
1621
|
+
font-family: var(--font-family-mono);
|
|
1622
|
+
font-size: var(--prose-code-font-size);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
.ui-block-editor-upload {
|
|
1626
|
+
display: inline-flex;
|
|
1627
|
+
align-items: center;
|
|
1628
|
+
gap: var(--space-1);
|
|
1629
|
+
vertical-align: middle;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
.ui-block-editor-upload svg {
|
|
1633
|
+
inline-size: var(--control-icon-size);
|
|
1634
|
+
block-size: var(--control-icon-size);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
.ui-block-editor-upload-spinner {
|
|
1638
|
+
animation: spin 1s linear infinite;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1642
|
+
.ui-block-editor-upload-spinner {
|
|
1643
|
+
animation: none;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
.ui-block-editor-status {
|
|
1648
|
+
margin-block-start: var(--space-2);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1428
1651
|
.ui-prose img[data-prose-preview] {
|
|
1429
1652
|
cursor: zoom-in;
|
|
1430
1653
|
}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
.ui-carousel-dot,
|
|
38
38
|
.ui-rating-star,
|
|
39
39
|
.ui-prose img[data-prose-preview],
|
|
40
|
+
.ui-prose .ui-prose-toggle-summary,
|
|
40
41
|
a.ui-list-row,
|
|
41
42
|
|
|
42
43
|
a[data-slot="card"],
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
.ui-carousel-dot,
|
|
108
109
|
.ui-rating-star,
|
|
109
110
|
.ui-prose img[data-prose-preview],
|
|
111
|
+
.ui-prose .ui-prose-toggle-summary,
|
|
110
112
|
a.ui-list-row,
|
|
111
113
|
a[data-slot="card"],
|
|
112
114
|
button[data-slot="card"],
|
package/dist/styles/layers.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "31.
|
|
2
|
+
"version": "31.27.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",
|
|
@@ -215,6 +215,15 @@
|
|
|
215
215
|
"chart-layout.css"
|
|
216
216
|
]
|
|
217
217
|
},
|
|
218
|
+
"BlockEditor": {
|
|
219
|
+
"layers": [
|
|
220
|
+
"control.css",
|
|
221
|
+
"toggle.css",
|
|
222
|
+
"text-layout.css",
|
|
223
|
+
"dialog-layout.css",
|
|
224
|
+
"navigation-layout.css"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
218
227
|
"BranchScopePicker": {
|
|
219
228
|
"layers": [
|
|
220
229
|
"layout.css",
|
|
@@ -57,6 +57,14 @@
|
|
|
57
57
|
--prose-code-space-inline: var(--space-1);
|
|
58
58
|
|
|
59
59
|
--prose-cell-image-max-inline-size: 20rem;
|
|
60
|
+
|
|
61
|
+
--prose-columns-gap: var(--space-6);
|
|
62
|
+
|
|
63
|
+
--block-editor-gutter-inline-size: calc(2 * var(--control-height-xs) + var(--space-2));
|
|
64
|
+
--block-editor-min-height: var(--band-height-3xl);
|
|
65
|
+
|
|
66
|
+
--block-editor-menu-inline-size: 16rem;
|
|
67
|
+
--block-editor-menu-max-block-size: 20rem;
|
|
60
68
|
--prose-code-radius: initial;
|
|
61
69
|
|
|
62
70
|
--prose-link-color: initial;
|
|
@@ -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: **
|
|
7
|
-
- With ≥1 frame: **
|
|
6
|
+
- Public components: **182**
|
|
7
|
+
- With ≥1 frame: **158** · zero-frame: **24**
|
|
8
8
|
- Fully covered (every contract axis declared): **0**
|
|
9
9
|
|
|
10
10
|
## UNTESTED — no `/frame/**` route
|
|
@@ -100,6 +100,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
100
100
|
| CodeBlock | ✓ | · | N/A | N/A | · | · | · | · | · | · |
|
|
101
101
|
| Markdown | ✓ | · | · | · | · | · | · | · | · | · |
|
|
102
102
|
| MarkdownEditor | ✓ | · | · | · | · | · | · | · | · | · |
|
|
103
|
+
| BlockEditor | ✓ | · | · | · | · | · | · | · | · | · |
|
|
103
104
|
| Prose | ✓ | · | N/A | N/A | · | · | · | · | · | · |
|
|
104
105
|
| Timeline | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
|
|
105
106
|
| TimelineGrid | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { BlockEditor } from "@godxjp/block-editor";
|
|
3
|
+
import {
|
|
4
|
+
Card,
|
|
5
|
+
CardContent,
|
|
6
|
+
CardDescription,
|
|
7
|
+
CardHeader,
|
|
8
|
+
CardTitle,
|
|
9
|
+
CodeBlock,
|
|
10
|
+
} from "@godxjp/ui/data-display";
|
|
11
|
+
import { Form, FormField } from "@godxjp/ui/data-entry";
|
|
12
|
+
import { Button } from "@godxjp/ui/general";
|
|
13
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
14
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
15
|
+
|
|
16
|
+
import shot from "../assets/shot-landscape.svg";
|
|
17
|
+
|
|
18
|
+
const initial = `# 議事録 2026-10-05
|
|
19
|
+
|
|
20
|
+
> [!NOTE] 次回まで
|
|
21
|
+
> 決済モジュールの再発行は **税率変更後** のケースを追加する
|
|
22
|
+
|
|
23
|
+
- [ ] 仕様の確認
|
|
24
|
+
- [x] [[Guide|設計ガイド]] の更新
|
|
25
|
+
|
|
26
|
+
:::toggle[詳細]
|
|
27
|
+
「/」でブロックを挿入、⋮⋮ でドラッグ。
|
|
28
|
+
:::
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
/** The host's page index — targets are ids, labels are localized like any other copy. */
|
|
32
|
+
const PAGES = [
|
|
33
|
+
{ target: "Guide", labelKey: "blockEditorDocs.pages.guide" },
|
|
34
|
+
{ target: "Setup", labelKey: "blockEditorDocs.pages.setup" },
|
|
35
|
+
{ target: "Release", labelKey: "blockEditorDocs.pages.release" },
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
/** Stands in for the host's storage: a real app uploads the file and returns `asset:<id>`. */
|
|
39
|
+
async function demoUpload(file: File) {
|
|
40
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
41
|
+
return { url: shot, name: file.name };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @godxjp/block-editor — the block editor (gh#1156). A page form: the editor inside a FormField,
|
|
46
|
+
* the Markdown it saves shown beside it (exactly what `normalize()` returns), files through the
|
|
47
|
+
* host's `upload`, `[[` suggestions from the host's page index.
|
|
48
|
+
*/
|
|
49
|
+
export default function Demo() {
|
|
50
|
+
const { t } = useTranslation();
|
|
51
|
+
const [body, setBody] = React.useState(initial);
|
|
52
|
+
return (
|
|
53
|
+
<PageContainer title="BlockEditor" subtitle={t("blockEditorDocs.subtitle")}>
|
|
54
|
+
<Card>
|
|
55
|
+
<CardHeader>
|
|
56
|
+
<CardTitle level={2}>{t("blockEditorDocs.edit.title")}</CardTitle>
|
|
57
|
+
<CardDescription>{t("blockEditorDocs.edit.description")}</CardDescription>
|
|
58
|
+
</CardHeader>
|
|
59
|
+
<CardContent>
|
|
60
|
+
<Form onSubmit={(event) => event.preventDefault()}>
|
|
61
|
+
<Flex direction="col" gap="md">
|
|
62
|
+
<FormField id="block-body" label={t("blockEditorDocs.edit.label")}>
|
|
63
|
+
<BlockEditor
|
|
64
|
+
value={body}
|
|
65
|
+
onValueChange={setBody}
|
|
66
|
+
upload={demoUpload}
|
|
67
|
+
suggestWikilinks={(query) =>
|
|
68
|
+
PAGES.map((p) => ({ target: p.target, label: t(p.labelKey) })).filter((p) =>
|
|
69
|
+
`${p.target} ${p.label}`.toLowerCase().includes(query.toLowerCase()),
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
/>
|
|
73
|
+
</FormField>
|
|
74
|
+
<Flex justify="end">
|
|
75
|
+
<Button type="submit">{t("blockEditorDocs.edit.save")}</Button>
|
|
76
|
+
</Flex>
|
|
77
|
+
</Flex>
|
|
78
|
+
</Form>
|
|
79
|
+
</CardContent>
|
|
80
|
+
</Card>
|
|
81
|
+
<Card>
|
|
82
|
+
<CardHeader>
|
|
83
|
+
<CardTitle level={2}>{t("blockEditorDocs.markdown.title")}</CardTitle>
|
|
84
|
+
<CardDescription>{t("blockEditorDocs.markdown.description")}</CardDescription>
|
|
85
|
+
</CardHeader>
|
|
86
|
+
<CardContent>
|
|
87
|
+
<CodeBlock language="markdown">{body}</CodeBlock>
|
|
88
|
+
</CardContent>
|
|
89
|
+
</Card>
|
|
90
|
+
<Card>
|
|
91
|
+
<CardHeader>
|
|
92
|
+
<CardTitle level={2}>{t("blockEditorDocs.readOnly.title")}</CardTitle>
|
|
93
|
+
<CardDescription>{t("blockEditorDocs.readOnly.description")}</CardDescription>
|
|
94
|
+
</CardHeader>
|
|
95
|
+
<CardContent>
|
|
96
|
+
<BlockEditor
|
|
97
|
+
defaultValue={initial}
|
|
98
|
+
readOnly
|
|
99
|
+
aria-label={t("blockEditorDocs.readOnly.label")}
|
|
100
|
+
/>
|
|
101
|
+
</CardContent>
|
|
102
|
+
</Card>
|
|
103
|
+
</PageContainer>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -1598,5 +1598,29 @@
|
|
|
1598
1598
|
"description": "The toolbar stays focusable, but its actions do nothing.",
|
|
1599
1599
|
"label": "Body (view only)"
|
|
1600
1600
|
}
|
|
1601
|
+
},
|
|
1602
|
+
"blockEditorDocs": {
|
|
1603
|
+
"subtitle": "@godxjp/block-editor · / block menu · drag handle · format toolbar · saves Markdown",
|
|
1604
|
+
"edit": {
|
|
1605
|
+
"title": "Edit a page",
|
|
1606
|
+
"description": "Type / for blocks, select text for formatting, drag ⋮⋮ to move a block (Alt+Shift+↑↓ from the keyboard).",
|
|
1607
|
+
"label": "Body",
|
|
1608
|
+
"save": "Save"
|
|
1609
|
+
},
|
|
1610
|
+
"markdown": {
|
|
1611
|
+
"title": "What it saves",
|
|
1612
|
+
"description": "The canonical Markdown — exactly what normalize() from @godxjp/markdown/codec returns.",
|
|
1613
|
+
"label": "Markdown"
|
|
1614
|
+
},
|
|
1615
|
+
"readOnly": {
|
|
1616
|
+
"title": "Read-only",
|
|
1617
|
+
"description": "No handle, no menus; the body renders as Prose.",
|
|
1618
|
+
"label": "Body (view only)"
|
|
1619
|
+
},
|
|
1620
|
+
"pages": {
|
|
1621
|
+
"guide": "Design guide",
|
|
1622
|
+
"setup": "Setup",
|
|
1623
|
+
"release": "Release steps"
|
|
1624
|
+
}
|
|
1601
1625
|
}
|
|
1602
1626
|
}
|
|
@@ -1591,5 +1591,29 @@
|
|
|
1591
1591
|
"description": "ツールバーはフォーカスできますが、操作は無効です。",
|
|
1592
1592
|
"label": "本文(閲覧のみ)"
|
|
1593
1593
|
}
|
|
1594
|
+
},
|
|
1595
|
+
"blockEditorDocs": {
|
|
1596
|
+
"subtitle": "@godxjp/block-editor · 「/」でブロック · ドラッグハンドル · 書式ツールバー · Markdown で保存",
|
|
1597
|
+
"edit": {
|
|
1598
|
+
"title": "ページを編集",
|
|
1599
|
+
"description": "「/」でブロックを挿入、文字を選ぶと書式、⋮⋮ でブロックを移動(キーボードは Alt+Shift+↑↓)。",
|
|
1600
|
+
"label": "本文",
|
|
1601
|
+
"save": "保存"
|
|
1602
|
+
},
|
|
1603
|
+
"markdown": {
|
|
1604
|
+
"title": "保存される内容",
|
|
1605
|
+
"description": "正規化された Markdown — @godxjp/markdown/codec の normalize() と同じ結果です。",
|
|
1606
|
+
"label": "Markdown"
|
|
1607
|
+
},
|
|
1608
|
+
"readOnly": {
|
|
1609
|
+
"title": "閲覧のみ",
|
|
1610
|
+
"description": "ハンドルもメニューも出ません。本文は Prose で表示されます。",
|
|
1611
|
+
"label": "本文(閲覧のみ)"
|
|
1612
|
+
},
|
|
1613
|
+
"pages": {
|
|
1614
|
+
"guide": "設計ガイド",
|
|
1615
|
+
"setup": "セットアップ",
|
|
1616
|
+
"release": "リリース手順"
|
|
1617
|
+
}
|
|
1594
1618
|
}
|
|
1595
1619
|
}
|
|
@@ -1591,5 +1591,29 @@
|
|
|
1591
1591
|
"description": "Thanh công cụ vẫn nhận focus nhưng thao tác bị vô hiệu.",
|
|
1592
1592
|
"label": "Nội dung (chỉ xem)"
|
|
1593
1593
|
}
|
|
1594
|
+
},
|
|
1595
|
+
"blockEditorDocs": {
|
|
1596
|
+
"subtitle": "@godxjp/block-editor · menu khối / · tay nắm kéo · thanh định dạng · lưu Markdown",
|
|
1597
|
+
"edit": {
|
|
1598
|
+
"title": "Sửa trang",
|
|
1599
|
+
"description": "Gõ / để chèn khối, chọn chữ để định dạng, kéo ⋮⋮ để di chuyển khối (bàn phím: Alt+Shift+↑↓).",
|
|
1600
|
+
"label": "Nội dung",
|
|
1601
|
+
"save": "Lưu"
|
|
1602
|
+
},
|
|
1603
|
+
"markdown": {
|
|
1604
|
+
"title": "Nội dung được lưu",
|
|
1605
|
+
"description": "Markdown chuẩn hoá — đúng kết quả normalize() của @godxjp/markdown/codec.",
|
|
1606
|
+
"label": "Markdown"
|
|
1607
|
+
},
|
|
1608
|
+
"readOnly": {
|
|
1609
|
+
"title": "Chỉ xem",
|
|
1610
|
+
"description": "Không có tay nắm, không có menu; nội dung hiển thị bằng Prose.",
|
|
1611
|
+
"label": "Nội dung (chỉ xem)"
|
|
1612
|
+
},
|
|
1613
|
+
"pages": {
|
|
1614
|
+
"guide": "Hướng dẫn thiết kế",
|
|
1615
|
+
"setup": "Cài đặt",
|
|
1616
|
+
"release": "Các bước phát hành"
|
|
1617
|
+
}
|
|
1594
1618
|
}
|
|
1595
1619
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "31.
|
|
4
|
-
"godxUiMcp": "31.
|
|
3
|
+
"version": "31.27.0",
|
|
4
|
+
"godxUiMcp": "31.27.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -315,7 +315,7 @@
|
|
|
315
315
|
"audit:component-cases": "node scripts/check-component-case-evidence.mjs",
|
|
316
316
|
"audit:examples": "node scripts/ui-audit.mjs docs",
|
|
317
317
|
"build": "tsup && tsc -p tsconfig.build.json && node scripts/copy-styles.mjs && node scripts/fix-esm-extensions.mjs && node scripts/add-use-client.mjs",
|
|
318
|
-
"build:packages": "cd packages/markdown && node ../../node_modules/tsup/dist/cli-default.js && cd ../editor && node ../../node_modules/tsup/dist/cli-default.js",
|
|
318
|
+
"build:packages": "cd packages/markdown && node ../../node_modules/tsup/dist/cli-default.js && cd ../editor && node ../../node_modules/tsup/dist/cli-default.js && cd ../block-editor && node ../../node_modules/tsup/dist/cli-default.js",
|
|
319
319
|
"build:jis-level1-fonts": "node scripts/build-jis-level1-fonts.mjs",
|
|
320
320
|
"capture:voiceover": "node scripts/capture-voiceover-evidence.mjs",
|
|
321
321
|
"check:agent-catalog": "node scripts/gen-agent-catalog.mjs --check",
|
|
@@ -417,7 +417,7 @@
|
|
|
417
417
|
"test:visual:topbar-collision": "node scripts/topbar-collision-visual.mjs",
|
|
418
418
|
"test:watch": "vitest",
|
|
419
419
|
"typecheck": "node node_modules/typescript-7/bin/tsc --noEmit -p tsconfig.json && pnpm typecheck:packages",
|
|
420
|
-
"typecheck:packages": "node node_modules/typescript-7/bin/tsc --noEmit -p packages/markdown/tsconfig.json && node node_modules/typescript-7/bin/tsc --noEmit -p packages/editor/tsconfig.json",
|
|
420
|
+
"typecheck:packages": "node node_modules/typescript-7/bin/tsc --noEmit -p packages/markdown/tsconfig.json && node node_modules/typescript-7/bin/tsc --noEmit -p packages/editor/tsconfig.json && node node_modules/typescript-7/bin/tsc --noEmit -p packages/block-editor/tsconfig.json",
|
|
421
421
|
"typecheck:docs": "node node_modules/typescript-7/bin/tsc --noEmit -p tsconfig.docs.json",
|
|
422
422
|
"typecheck:mcp": "node node_modules/typescript-7/bin/tsc --noEmit -p mcp/tsconfig.json",
|
|
423
423
|
"typecheck:ts6": "tsc --noEmit -p tsconfig.json",
|
|
@@ -500,6 +500,7 @@
|
|
|
500
500
|
"devDependencies": {
|
|
501
501
|
"@axe-core/playwright": "^4.13.0",
|
|
502
502
|
"@eslint/js": "^10.0.1",
|
|
503
|
+
"@floating-ui/dom": "^1.8.0",
|
|
503
504
|
"@hookform/resolvers": "^5.9.1",
|
|
504
505
|
"@radix-ui/react-accordion": "^1.2.20",
|
|
505
506
|
"@radix-ui/react-avatar": "^1.2.6",
|
|
@@ -515,6 +516,18 @@
|
|
|
515
516
|
"@testing-library/jest-dom": "^7.0.1",
|
|
516
517
|
"@testing-library/react": "^16.3.3",
|
|
517
518
|
"@testing-library/user-event": "^14.6.6",
|
|
519
|
+
"@tiptap/core": "3.31.4",
|
|
520
|
+
"@tiptap/extension-bubble-menu": "3.31.4",
|
|
521
|
+
"@tiptap/extension-details": "3.31.4",
|
|
522
|
+
"@tiptap/extension-image": "3.31.4",
|
|
523
|
+
"@tiptap/extension-list": "3.31.4",
|
|
524
|
+
"@tiptap/extension-table": "3.31.4",
|
|
525
|
+
"@tiptap/extension-text-style": "3.31.4",
|
|
526
|
+
"@tiptap/extensions": "3.31.4",
|
|
527
|
+
"@tiptap/pm": "3.31.4",
|
|
528
|
+
"@tiptap/react": "3.31.4",
|
|
529
|
+
"@tiptap/starter-kit": "3.31.4",
|
|
530
|
+
"@tiptap/suggestion": "3.31.4",
|
|
518
531
|
"@types/hast": "^3.0.5",
|
|
519
532
|
"@types/mdast": "^4.0.4",
|
|
520
533
|
"@types/node": "^26.4.0",
|
|
@@ -531,7 +544,15 @@
|
|
|
531
544
|
"globals": "^17.11.0",
|
|
532
545
|
"jsdom": "^30.0.1",
|
|
533
546
|
"jsqr": "^1.4.0",
|
|
547
|
+
"mdast-util-directive": "^3.1.1",
|
|
548
|
+
"mdast-util-from-markdown": "^2.1.0",
|
|
549
|
+
"mdast-util-gfm": "^3.1.0",
|
|
550
|
+
"mdast-util-to-markdown": "^2.2.0",
|
|
534
551
|
"mermaid": "^11.17.2",
|
|
552
|
+
"micromark-extension-cjk-friendly": "^2.0.2",
|
|
553
|
+
"micromark-extension-directive": "^4.0.0",
|
|
554
|
+
"micromark-extension-gfm": "^3.0.0",
|
|
555
|
+
"micromark-util-types": "^2.0.3",
|
|
535
556
|
"playwright": "^1.62.1",
|
|
536
557
|
"pngjs": "^7.0.0",
|
|
537
558
|
"prettier": "^3.9.6",
|
package/scripts/prune-css.mjs
CHANGED
|
@@ -128,7 +128,7 @@ let sawNamespace = false;
|
|
|
128
128
|
// `@godxjp/editor` / `@godxjp/markdown` too (gh#1114): their components render kit components, and
|
|
129
129
|
// the manifest maps `MarkdownEditor` to the layers those need.
|
|
130
130
|
const IMPORT =
|
|
131
|
-
/(?:import|export)\s+(type\s+)?([^;'"]*?)\s*from\s*["'](@godxjp\/(?:ui|editor|markdown)(?:\/[^"']*)?)["']/g;
|
|
131
|
+
/(?:import|export)\s+(type\s+)?([^;'"]*?)\s*from\s*["'](@godxjp\/(?:ui|editor|block-editor|markdown)(?:\/[^"']*)?)["']/g;
|
|
132
132
|
for (const file of new Set(sources)) {
|
|
133
133
|
const src = readFileSync(file, "utf8");
|
|
134
134
|
for (const m of src.matchAll(IMPORT)) {
|