@godxjp/ui 31.17.0 → 31.18.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 +2 -2
- package/agent/components/Actions.json +1 -1
- package/agent/components/Badge.json +2 -2
- package/agent/components/Prose.json +1 -1
- package/agent/components/Textarea.json +1 -1
- package/agent/components-index.json +3 -3
- package/agent/components.json +5 -5
- package/agent/index.json +3 -3
- package/agent/llms.txt +4 -4
- package/dist/components/data-display/badge.js +50 -61
- package/dist/components/data-display/table.js +2 -1
- package/dist/components/feedback/tooltip.js +2 -1
- package/dist/components/general/actions.js +2 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/props/components/general.prop.d.ts +8 -0
- package/dist/styles/layers.json +2 -1
- package/dist/styles/layout.css +5 -0
- package/dist/styles/table-layout.css +16 -4
- package/docs/data-display/markdown.tsx +86 -0
- package/docs/data-entry/markdown-editor.tsx +69 -0
- package/docs/i18n/messages/en.json +26 -1
- package/docs/i18n/messages/ja.json +26 -1
- package/docs/i18n/messages/vi.json +26 -1
- package/package.json +14 -4
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.18.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
|
+
1. `components-index.json` — 49 KB, all 179 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
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"name": "Actions",
|
|
7
7
|
"props": [
|
|
8
8
|
{
|
|
9
|
-
"description": "The actions: { key, label?, icon?, onItemClick?, danger?, subItems?, actionRender? }. `label` is the accessible name AND the tooltip. `subItems` folds the action into a menu; `actionRender` replaces it entirely.",
|
|
9
|
+
"description": "The actions: { key, label?, icon?, onItemClick?, disabled?, danger?, subItems?, actionRender? }. `label` is the accessible name AND the tooltip. `disabled` makes a plain action `aria-disabled` and ignores its click, but keeps it focusable and in the arrow-key order (WAI-ARIA toolbar) — use it for a formatting toolbar while previewing or read-only, not to hide an action (gh#1109). `subItems` folds the action into a menu; `actionRender` replaces it entirely.",
|
|
10
10
|
"name": "items",
|
|
11
11
|
"required": true,
|
|
12
12
|
"type": "ActionsItemsProp[]"
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"type": "React.ComponentType<{ className?: string }> | null"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
|
-
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut,
|
|
52
|
+
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut, opens the full text in the same tooltip as `Text ellipsis={{ tooltip: true }}` — on pointer hover of the label and on keyboard focus of the nearest focusable control around the chip (a row link, a treeitem, a cell button), only while it is actually cut; the chip never becomes a tab stop (gh#1105). A caller's own `title` on the Badge turns the tooltip off. So a Badge in a fixed-width DataTable cell or a narrow Card stays inside it with no extra props; `<Badge><Text ellipsis>` also works. Do not reach for `Text break=\"anywhere\"` to make a chip wrap.",
|
|
53
53
|
"name": "children",
|
|
54
54
|
"type": "ReactNode"
|
|
55
55
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"subParts": [
|
|
75
75
|
"StatusBadge"
|
|
76
76
|
],
|
|
77
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes,
|
|
77
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, and its full text opens in a tooltip on hover or on keyboard focus of the control around the chip (gh#1101, gh#1105).",
|
|
78
78
|
"usage": [
|
|
79
79
|
"DO pick the correct variant semantically: `success` (approved/paid), `warning` (pending/overdue), `destructive` (rejected/error), `secondary` (neutral category), `outline` (subtle label), `default` (primary accent). Never force a colour just for aesthetics — agents and screen readers read the variant as intent.",
|
|
80
80
|
"DO use `status` for entity lifecycle statuses (active, draft, pending, cancelled, failed, scheduled, etc.) so the component resolves the correct tone, icon, and i18n label.",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"rules": [],
|
|
37
37
|
"storyPath": "data-display/Prose.stories.tsx",
|
|
38
|
-
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from.",
|
|
38
|
+
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from. To RENDER Markdown, use the sibling package `@godxjp/markdown` inside it — `<Prose><Markdown>{body}</Markdown></Prose>` — the one GFM renderer + sanitiser + Mermaid gate shared by every GoDX app; do not assemble react-markdown + rehype-sanitize per app (gh#1108).",
|
|
39
39
|
"usage": [
|
|
40
40
|
"DO import from `@godxjp/ui/data-display`: `import { Prose } from \"@godxjp/ui/data-display\";`",
|
|
41
41
|
"DO wrap the OUTPUT of your Markdown pipeline (react-markdown + remark-gfm + rehype-sanitize), a sanitised CMS string via `dangerouslySetInnerHTML`, or plain JSX. Prose styles descendants: h1..h4, p, ul/ol/li, blockquote, code, pre, table/th/td, a, img, hr.",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
],
|
|
105
105
|
"rules": [],
|
|
106
106
|
"storyPath": "data-entry/Textarea.stories.tsx",
|
|
107
|
-
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields.",
|
|
107
|
+
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields. For a Markdown body (wiki page, issue description, mail) use the sibling package `@godxjp/editor` `MarkdownEditor` — this Textarea plus a formatting toolbar, preview through `@godxjp/markdown`, and paste/drop upload through a host `upload` function (gh#1109).",
|
|
108
108
|
"usage": [
|
|
109
109
|
"DO reach for `variant=\"ghost\"` ONLY when a parent surface already draws the box and owns focus — the composer Card, an inline edit cell. A standalone field keeps the default: without its own border it reads as plain text, not something you can type into.",
|
|
110
110
|
"DO always wrap Textarea in FormField when it appears in a form — FormField clones aria-describedby, aria-required, and aria-invalid onto the child, giving error/helper announcements and screen-reader labelling for free. Pass matching id props to both.",
|
|
@@ -239,7 +239,7 @@
|
|
|
239
239
|
{
|
|
240
240
|
"group": "data-display",
|
|
241
241
|
"name": "Badge",
|
|
242
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes,
|
|
242
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, and its full text opens in a tooltip on hover or on keyboard focus of the control around the chip (gh#1101, gh#1105)."
|
|
243
243
|
},
|
|
244
244
|
{
|
|
245
245
|
"group": "data-display",
|
|
@@ -304,7 +304,7 @@
|
|
|
304
304
|
{
|
|
305
305
|
"group": "data-display",
|
|
306
306
|
"name": "Prose",
|
|
307
|
-
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from."
|
|
307
|
+
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from. To RENDER Markdown, use the sibling package `@godxjp/markdown` inside it — `<Prose><Markdown>{body}</Markdown></Prose>` — the one GFM renderer + sanitiser + Mermaid gate shared by every GoDX app; do not assemble react-markdown + rehype-sanitize per app (gh#1108)."
|
|
308
308
|
},
|
|
309
309
|
{
|
|
310
310
|
"group": "data-display",
|
|
@@ -392,7 +392,7 @@
|
|
|
392
392
|
{
|
|
393
393
|
"group": "data-entry",
|
|
394
394
|
"name": "Textarea",
|
|
395
|
-
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields."
|
|
395
|
+
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields. For a Markdown body (wiki page, issue description, mail) use the sibling package `@godxjp/editor` `MarkdownEditor` — this Textarea plus a formatting toolbar, preview through `@godxjp/markdown`, and paste/drop upload through a host `upload` function (gh#1109)."
|
|
396
396
|
},
|
|
397
397
|
{
|
|
398
398
|
"group": "data-entry",
|
package/agent/components.json
CHANGED
|
@@ -4081,7 +4081,7 @@
|
|
|
4081
4081
|
"type": "React.ComponentType<{ className?: string }> | null"
|
|
4082
4082
|
},
|
|
4083
4083
|
{
|
|
4084
|
-
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut,
|
|
4084
|
+
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut, opens the full text in the same tooltip as `Text ellipsis={{ tooltip: true }}` — on pointer hover of the label and on keyboard focus of the nearest focusable control around the chip (a row link, a treeitem, a cell button), only while it is actually cut; the chip never becomes a tab stop (gh#1105). A caller's own `title` on the Badge turns the tooltip off. So a Badge in a fixed-width DataTable cell or a narrow Card stays inside it with no extra props; `<Badge><Text ellipsis>` also works. Do not reach for `Text break=\"anywhere\"` to make a chip wrap.",
|
|
4085
4085
|
"name": "children",
|
|
4086
4086
|
"type": "ReactNode"
|
|
4087
4087
|
},
|
|
@@ -4106,7 +4106,7 @@
|
|
|
4106
4106
|
"subParts": [
|
|
4107
4107
|
"StatusBadge"
|
|
4108
4108
|
],
|
|
4109
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes,
|
|
4109
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, and its full text opens in a tooltip on hover or on keyboard focus of the control around the chip (gh#1101, gh#1105).",
|
|
4110
4110
|
"usage": [
|
|
4111
4111
|
"DO pick the correct variant semantically: `success` (approved/paid), `warning` (pending/overdue), `destructive` (rejected/error), `secondary` (neutral category), `outline` (subtle label), `default` (primary accent). Never force a colour just for aesthetics — agents and screen readers read the variant as intent.",
|
|
4112
4112
|
"DO use `status` for entity lifecycle statuses (active, draft, pending, cancelled, failed, scheduled, etc.) so the component resolves the correct tone, icon, and i18n label.",
|
|
@@ -5024,7 +5024,7 @@
|
|
|
5024
5024
|
],
|
|
5025
5025
|
"rules": [],
|
|
5026
5026
|
"storyPath": "data-display/Prose.stories.tsx",
|
|
5027
|
-
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from.",
|
|
5027
|
+
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from. To RENDER Markdown, use the sibling package `@godxjp/markdown` inside it — `<Prose><Markdown>{body}</Markdown></Prose>` — the one GFM renderer + sanitiser + Mermaid gate shared by every GoDX app; do not assemble react-markdown + rehype-sanitize per app (gh#1108).",
|
|
5028
5028
|
"usage": [
|
|
5029
5029
|
"DO import from `@godxjp/ui/data-display`: `import { Prose } from \"@godxjp/ui/data-display\";`",
|
|
5030
5030
|
"DO wrap the OUTPUT of your Markdown pipeline (react-markdown + remark-gfm + rehype-sanitize), a sanitised CMS string via `dangerouslySetInnerHTML`, or plain JSX. Prose styles descendants: h1..h4, p, ul/ol/li, blockquote, code, pre, table/th/td, a, img, hr.",
|
|
@@ -6892,7 +6892,7 @@
|
|
|
6892
6892
|
],
|
|
6893
6893
|
"rules": [],
|
|
6894
6894
|
"storyPath": "data-entry/Textarea.stories.tsx",
|
|
6895
|
-
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields.",
|
|
6895
|
+
"tagline": "Styled wrapper around native <textarea>. Pair with FormField for labelled fields. For a Markdown body (wiki page, issue description, mail) use the sibling package `@godxjp/editor` `MarkdownEditor` — this Textarea plus a formatting toolbar, preview through `@godxjp/markdown`, and paste/drop upload through a host `upload` function (gh#1109).",
|
|
6896
6896
|
"usage": [
|
|
6897
6897
|
"DO reach for `variant=\"ghost\"` ONLY when a parent surface already draws the box and owns focus — the composer Card, an inline edit cell. A standalone field keeps the default: without its own border it reads as plain text, not something you can type into.",
|
|
6898
6898
|
"DO always wrap Textarea in FormField when it appears in a form — FormField clones aria-describedby, aria-required, and aria-invalid onto the child, giving error/helper announcements and screen-reader labelling for free. Pass matching id props to both.",
|
|
@@ -15678,7 +15678,7 @@
|
|
|
15678
15678
|
"name": "Actions",
|
|
15679
15679
|
"props": [
|
|
15680
15680
|
{
|
|
15681
|
-
"description": "The actions: { key, label?, icon?, onItemClick?, danger?, subItems?, actionRender? }. `label` is the accessible name AND the tooltip. `subItems` folds the action into a menu; `actionRender` replaces it entirely.",
|
|
15681
|
+
"description": "The actions: { key, label?, icon?, onItemClick?, disabled?, danger?, subItems?, actionRender? }. `label` is the accessible name AND the tooltip. `disabled` makes a plain action `aria-disabled` and ignores its click, but keeps it focusable and in the arrow-key order (WAI-ARIA toolbar) — use it for a formatting toolbar while previewing or read-only, not to hide an action (gh#1109). `subItems` folds the action into a menu; `actionRender` replaces it entirely.",
|
|
15682
15682
|
"name": "items",
|
|
15683
15683
|
"required": true,
|
|
15684
15684
|
"type": "ActionsItemsProp[]"
|
package/agent/index.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
{
|
|
12
12
|
"file": "components-index.json",
|
|
13
|
-
"note": "
|
|
13
|
+
"note": "49 KB — name + group + tagline for all 179. 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.
|
|
51
|
+
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.18.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.
|
|
65
|
+
"version": "31.18.0"
|
|
66
66
|
}
|
package/agent/llms.txt
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @godxjp/ui
|
|
2
2
|
|
|
3
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.
|
|
4
|
+
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.18.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.18.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):
|
|
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`).
|
|
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
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.
|
|
29
|
+
the tag: `.../godx-jp/godxjp-ui/v31.18.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,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cva } from "class-variance-authority";
|
|
5
5
|
import {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
XCircle
|
|
15
15
|
} from "lucide-react";
|
|
16
16
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
17
|
+
import { EllipsisTooltip } from "../feedback/tooltip.js";
|
|
17
18
|
import { cn } from "../../lib/utils.js";
|
|
18
19
|
import {
|
|
19
20
|
toneDestructiveClass,
|
|
@@ -105,14 +106,6 @@ const badgeToneClass = {
|
|
|
105
106
|
muted: cn("border-transparent", toneMutedClass),
|
|
106
107
|
neutral: cn("border-transparent", toneNeutralClass)
|
|
107
108
|
};
|
|
108
|
-
function titleTruncatedLabel(event) {
|
|
109
|
-
const label = event.currentTarget;
|
|
110
|
-
if (label.scrollWidth > label.clientWidth) {
|
|
111
|
-
label.title = label.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
112
|
-
} else {
|
|
113
|
-
label.removeAttribute("title");
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
109
|
function Badge({
|
|
117
110
|
as: Element = "div",
|
|
118
111
|
className,
|
|
@@ -148,58 +141,54 @@ function Badge({
|
|
|
148
141
|
const removeLabel = stringLabel ?? (deriveFromDom ? renderedLabel : void 0);
|
|
149
142
|
const named = props["aria-label"] != null || props["aria-labelledby"] != null;
|
|
150
143
|
const nameRole = named && props.role === void 0 && !onRemove ? "img" : void 0;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
"
|
|
178
|
-
{
|
|
179
|
-
|
|
180
|
-
"
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
) : null
|
|
200
|
-
]
|
|
201
|
-
}
|
|
202
|
-
);
|
|
144
|
+
const labelTooltip = resolvedChildren != null && props.title == null;
|
|
145
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
146
|
+
/* @__PURE__ */ jsxs(
|
|
147
|
+
Element,
|
|
148
|
+
{
|
|
149
|
+
"data-slot": "badge",
|
|
150
|
+
role: nameRole,
|
|
151
|
+
"data-tone": tinted ? void 0 : resolvedTone,
|
|
152
|
+
"data-tinted": tinted ? "" : void 0,
|
|
153
|
+
"data-shape": shape ?? "default",
|
|
154
|
+
"data-tabular": tabular ? "" : void 0,
|
|
155
|
+
"data-removable": onRemove ? "" : void 0,
|
|
156
|
+
className: cn(
|
|
157
|
+
badgeVariants({
|
|
158
|
+
// A status tone paints the chip itself (`badgeToneClass` below), so the variant must not
|
|
159
|
+
// also paint one — see the `toned` variant. An EXPLICIT `variant` still wins, which is
|
|
160
|
+
// how `<Badge variant="outline" tone="success">` keeps its border treatment.
|
|
161
|
+
variant: tinted ? "tinted" : variant ?? (resolvedTone === "default" ? "default" : "toned"),
|
|
162
|
+
shape: shape ?? "default"
|
|
163
|
+
}),
|
|
164
|
+
tinted ? void 0 : badgeToneClass[resolvedTone],
|
|
165
|
+
className
|
|
166
|
+
),
|
|
167
|
+
style: tinted ? { ...style, ["--badge-color"]: color } : style,
|
|
168
|
+
...props,
|
|
169
|
+
children: [
|
|
170
|
+
ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { "data-slot": "badge-icon", "aria-hidden": "true" }) : null,
|
|
171
|
+
resolvedChildren != null ? /* @__PURE__ */ jsx("span", { ref: labelRef, "data-slot": "badge-label", children: resolvedChildren }) : null,
|
|
172
|
+
onRemove ? /* @__PURE__ */ jsx(
|
|
173
|
+
"button",
|
|
174
|
+
{
|
|
175
|
+
type: "button",
|
|
176
|
+
"data-slot": "badge-remove",
|
|
177
|
+
className: "ui-control-inline-affix-action ui-badge-remove",
|
|
178
|
+
"aria-label": removeLabelProp ?? (removeLabel != null ? t("navigation.filterBar.removeFilter", { label: removeLabel }) : t("common.delete")),
|
|
179
|
+
onClick: (event) => {
|
|
180
|
+
event.stopPropagation();
|
|
181
|
+
onRemove();
|
|
182
|
+
},
|
|
183
|
+
disabled: removeDisabled,
|
|
184
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
|
|
185
|
+
}
|
|
186
|
+
) : null
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
labelTooltip ? /* @__PURE__ */ jsx(EllipsisTooltip, { anchorRef: labelRef, title: resolvedChildren }) : null
|
|
191
|
+
] });
|
|
203
192
|
}
|
|
204
193
|
const StatusBadge = Badge;
|
|
205
194
|
export {
|
|
@@ -228,6 +228,7 @@ const TableCell = React.forwardRef(
|
|
|
228
228
|
...props
|
|
229
229
|
}, ref) => {
|
|
230
230
|
const preset = React.useContext(TablePresetContext);
|
|
231
|
+
const body = priority === "actions" && preset === "action-collection" ? /* @__PURE__ */ jsx("span", { className: "ui-table-actions-content", children }) : children;
|
|
231
232
|
return /* @__PURE__ */ jsxs(
|
|
232
233
|
"td",
|
|
233
234
|
{
|
|
@@ -248,7 +249,7 @@ const TableCell = React.forwardRef(
|
|
|
248
249
|
...props,
|
|
249
250
|
children: [
|
|
250
251
|
label !== void 0 && children != null && children !== false && children !== "" ? /* @__PURE__ */ jsx("span", { className: "ui-table-stacked-collection-label", "aria-hidden": "true", children: label }) : null,
|
|
251
|
-
|
|
252
|
+
label !== void 0 ? /* @__PURE__ */ jsx("span", { className: "ui-table-stacked-collection-value", children: body }) : body
|
|
252
253
|
]
|
|
253
254
|
}
|
|
254
255
|
);
|
|
@@ -125,7 +125,8 @@ function TooltipContent({
|
|
|
125
125
|
const FOCUS_HOST = 'a[href], button, input, select, textarea, summary, [tabindex]:is([role="treeitem"], [role="gridcell"], [role="row"], [role="option"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="link"], [role="button"], [role="checkbox"], [role="radio"], [role="switch"])';
|
|
126
126
|
function isClipping(node) {
|
|
127
127
|
const box = node.querySelector(':scope > [data-slot="typography-content"]') ?? node;
|
|
128
|
-
|
|
128
|
+
if (box.scrollWidth > box.clientWidth) return true;
|
|
129
|
+
return box.scrollHeight > box.clientHeight && getComputedStyle(box).overflowY !== "visible";
|
|
129
130
|
}
|
|
130
131
|
function isFocusVisible(node) {
|
|
131
132
|
try {
|
|
@@ -58,6 +58,7 @@ const Actions = React.forwardRef(
|
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
const dispatch = (item, keyPath, domEvent) => {
|
|
61
|
+
if (item.disabled) return;
|
|
61
62
|
if (item.onItemClick) {
|
|
62
63
|
item.onItemClick(item);
|
|
63
64
|
return;
|
|
@@ -118,6 +119,7 @@ const Actions = React.forwardRef(
|
|
|
118
119
|
LabelledIconButton,
|
|
119
120
|
{
|
|
120
121
|
label: name,
|
|
122
|
+
"aria-disabled": item.disabled || void 0,
|
|
121
123
|
onClick: (event) => dispatch(item, [item.key], event),
|
|
122
124
|
...shared,
|
|
123
125
|
children: item.icon
|
|
@@ -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.18.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,
|
|
@@ -645,6 +645,14 @@ export type ActionsItemsProp = {
|
|
|
645
645
|
/** Per-item handler. When present it WINS over the strip's `onClick`. Ant Design X `onItemClick`. */
|
|
646
646
|
onItemClick?: (item: ActionsItemsProp) => void;
|
|
647
647
|
/** Paint the action as irreversible. Ant Design X `danger`. */
|
|
648
|
+
/**
|
|
649
|
+
* The action cannot run right now (a formatting toolbar while previewing, a read-only document).
|
|
650
|
+
* It stays FOCUSABLE and in the arrow-key order, as the WAI-ARIA toolbar pattern recommends, so a
|
|
651
|
+
* keyboard or screen-reader user can still find it: it is `aria-disabled="true"` and a click is
|
|
652
|
+
* ignored, rather than a native `disabled` that would drop it from the toolbar's focus order.
|
|
653
|
+
* Applies to a plain action; a `subItems` trigger and an `actionRender` own their own state.
|
|
654
|
+
*/
|
|
655
|
+
disabled?: DisabledProp;
|
|
648
656
|
danger?: boolean;
|
|
649
657
|
/** Nest the action into a menu behind one trigger. Ant Design X `subItems`. */
|
|
650
658
|
subItems?: readonly Omit<ActionsItemsProp, "subItems" | "actionRender">[];
|
package/dist/styles/layers.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "31.
|
|
2
|
+
"version": "31.18.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",
|
|
@@ -196,6 +196,7 @@
|
|
|
196
196
|
},
|
|
197
197
|
"Badge": {
|
|
198
198
|
"layers": [
|
|
199
|
+
"dialog-layout.css",
|
|
199
200
|
"badge-layout.css"
|
|
200
201
|
]
|
|
201
202
|
},
|
package/dist/styles/layout.css
CHANGED
|
@@ -2001,6 +2001,11 @@
|
|
|
2001
2001
|
border-radius: var(--actions-radius, var(--radius));
|
|
2002
2002
|
}
|
|
2003
2003
|
|
|
2004
|
+
.ui-actions [aria-disabled="true"] {
|
|
2005
|
+
opacity: var(--disabled-opacity);
|
|
2006
|
+
cursor: not-allowed;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2004
2009
|
.ui-actions[data-variant="filled"],
|
|
2005
2010
|
.ui-actions[data-variant="outlined"] {
|
|
2006
2011
|
padding-block: var(--actions-padding-block);
|
|
@@ -558,6 +558,10 @@
|
|
|
558
558
|
white-space: normal;
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
+
.ui-table-stacked-collection-value {
|
|
562
|
+
display: contents;
|
|
563
|
+
}
|
|
564
|
+
|
|
561
565
|
.ui-data-table-summary {
|
|
562
566
|
background-color: var(--table-summary-background, hsl(var(--muted)));
|
|
563
567
|
font-weight: var(--font-weight-medium);
|
|
@@ -932,7 +936,9 @@
|
|
|
932
936
|
overflow-wrap: anywhere;
|
|
933
937
|
}
|
|
934
938
|
|
|
935
|
-
[data-collapse-below="sm"] [data-slot="table-cell"]:empty
|
|
939
|
+
[data-collapse-below="sm"] [data-slot="table-cell"]:empty,
|
|
940
|
+
[data-collapse-below="sm"]
|
|
941
|
+
[data-slot="table-cell"]:has(> .ui-table-stacked-collection-value:empty) {
|
|
936
942
|
display: none;
|
|
937
943
|
}
|
|
938
944
|
|
|
@@ -981,7 +987,9 @@
|
|
|
981
987
|
overflow-wrap: anywhere;
|
|
982
988
|
}
|
|
983
989
|
|
|
984
|
-
[data-collapse-below="md"] [data-slot="table-cell"]:empty
|
|
990
|
+
[data-collapse-below="md"] [data-slot="table-cell"]:empty,
|
|
991
|
+
[data-collapse-below="md"]
|
|
992
|
+
[data-slot="table-cell"]:has(> .ui-table-stacked-collection-value:empty) {
|
|
985
993
|
display: none;
|
|
986
994
|
}
|
|
987
995
|
|
|
@@ -1030,7 +1038,9 @@
|
|
|
1030
1038
|
overflow-wrap: anywhere;
|
|
1031
1039
|
}
|
|
1032
1040
|
|
|
1033
|
-
[data-collapse-below="lg"] [data-slot="table-cell"]:empty
|
|
1041
|
+
[data-collapse-below="lg"] [data-slot="table-cell"]:empty,
|
|
1042
|
+
[data-collapse-below="lg"]
|
|
1043
|
+
[data-slot="table-cell"]:has(> .ui-table-stacked-collection-value:empty) {
|
|
1034
1044
|
display: none;
|
|
1035
1045
|
}
|
|
1036
1046
|
|
|
@@ -1079,7 +1089,9 @@
|
|
|
1079
1089
|
overflow-wrap: anywhere;
|
|
1080
1090
|
}
|
|
1081
1091
|
|
|
1082
|
-
[data-collapse-below="xl"] [data-slot="table-cell"]:empty
|
|
1092
|
+
[data-collapse-below="xl"] [data-slot="table-cell"]:empty,
|
|
1093
|
+
[data-collapse-below="xl"]
|
|
1094
|
+
[data-slot="table-cell"]:has(> .ui-table-stacked-collection-value:empty) {
|
|
1083
1095
|
display: none;
|
|
1084
1096
|
}
|
|
1085
1097
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Markdown, RENDERER_VERSION } from "@godxjp/markdown";
|
|
2
|
+
import {
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardDescription,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
Prose,
|
|
9
|
+
} from "@godxjp/ui/data-display";
|
|
10
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
11
|
+
import { PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
12
|
+
|
|
13
|
+
const page = `# 結合テスト計画
|
|
14
|
+
|
|
15
|
+
決済モジュールの請求書再発行シナリオを対象にする。詳細は[設計書](/wiki/設計/決済)を参照[^1]。
|
|
16
|
+
|
|
17
|
+
## 範囲
|
|
18
|
+
|
|
19
|
+
| シナリオ | 担当 | 状態 |
|
|
20
|
+
|:--|:--|--:|
|
|
21
|
+
| 再発行(通常) | 田中 | 完了 |
|
|
22
|
+
| 再発行(税率変更後) | 佐藤 | 進行中 |
|
|
23
|
+
|
|
24
|
+
- [x] テストデータ作成
|
|
25
|
+
- [ ] ステージング反映
|
|
26
|
+
- [ ] 受入レビュー
|
|
27
|
+
|
|
28
|
+
## 流れ
|
|
29
|
+
|
|
30
|
+
\`\`\`mermaid
|
|
31
|
+
graph LR
|
|
32
|
+
A[申請] --> B{承認}
|
|
33
|
+
B -->|承認| C[再発行]
|
|
34
|
+
B -->|差戻し| A
|
|
35
|
+
\`\`\`
|
|
36
|
+
|
|
37
|
+
\`\`\`ts
|
|
38
|
+
await invoices.reissue(id, { reason: "tax-rate" });
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
[^1]: 設計書は 2026-10 版。`;
|
|
42
|
+
|
|
43
|
+
const hostile = `<script>alert(1)</script>
|
|
44
|
+
|
|
45
|
+
[危険なリンク](javascript:alert(1)) と 
|
|
46
|
+
|
|
47
|
+
<img src=x onerror="alert(1)">`;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @godxjp/markdown — the one Markdown renderer (gh#1108). A wiki page body rendered as the
|
|
51
|
+
* published page shows it, and a hostile body rendered by the same component.
|
|
52
|
+
*/
|
|
53
|
+
export default function Demo() {
|
|
54
|
+
const { t } = useTranslation();
|
|
55
|
+
return (
|
|
56
|
+
<PageContainer
|
|
57
|
+
title="Markdown"
|
|
58
|
+
subtitle={t("markdownDocs.subtitle", { version: String(RENDERER_VERSION) })}
|
|
59
|
+
>
|
|
60
|
+
<ResponsiveGrid columns={{ base: 1, lg: 2 }} gap="md">
|
|
61
|
+
<Card>
|
|
62
|
+
<CardHeader>
|
|
63
|
+
<CardTitle level={2}>{t("markdownDocs.page.title")}</CardTitle>
|
|
64
|
+
<CardDescription>{t("markdownDocs.page.description")}</CardDescription>
|
|
65
|
+
</CardHeader>
|
|
66
|
+
<CardContent>
|
|
67
|
+
<Prose>
|
|
68
|
+
<Markdown>{page}</Markdown>
|
|
69
|
+
</Prose>
|
|
70
|
+
</CardContent>
|
|
71
|
+
</Card>
|
|
72
|
+
<Card>
|
|
73
|
+
<CardHeader>
|
|
74
|
+
<CardTitle level={2}>{t("markdownDocs.hostile.title")}</CardTitle>
|
|
75
|
+
<CardDescription>{t("markdownDocs.hostile.description")}</CardDescription>
|
|
76
|
+
</CardHeader>
|
|
77
|
+
<CardContent>
|
|
78
|
+
<Prose>
|
|
79
|
+
<Markdown>{hostile}</Markdown>
|
|
80
|
+
</Prose>
|
|
81
|
+
</CardContent>
|
|
82
|
+
</Card>
|
|
83
|
+
</ResponsiveGrid>
|
|
84
|
+
</PageContainer>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { MarkdownEditor } from "@godxjp/editor";
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
4
|
+
import { Form, FormField } from "@godxjp/ui/data-entry";
|
|
5
|
+
import { Button } from "@godxjp/ui/general";
|
|
6
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
7
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
8
|
+
|
|
9
|
+
import shot from "../assets/shot-landscape.svg";
|
|
10
|
+
|
|
11
|
+
const initial = `## 議事録 2026-10-02
|
|
12
|
+
|
|
13
|
+
- 決済モジュールの再発行は **税率変更後** のケースを追加する
|
|
14
|
+
- 次回レビュー:_10/9_
|
|
15
|
+
|
|
16
|
+
画像はこの欄に貼り付けるか、ドラッグするか、クリップのボタンから添付します。`;
|
|
17
|
+
|
|
18
|
+
/** Stands in for the host's storage: a real app uploads the file and returns its URL. */
|
|
19
|
+
async function demoUpload(file: File) {
|
|
20
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
21
|
+
return { url: shot, name: file.name };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @godxjp/editor — the Markdown editor (gh#1109). A page form: the editor inside a FormField,
|
|
26
|
+
* the preview through @godxjp/markdown, files through the host's `upload`.
|
|
27
|
+
*/
|
|
28
|
+
export default function Demo() {
|
|
29
|
+
const { t } = useTranslation();
|
|
30
|
+
const [body, setBody] = React.useState(initial);
|
|
31
|
+
return (
|
|
32
|
+
<PageContainer title="MarkdownEditor" subtitle={t("markdownEditorDocs.subtitle")}>
|
|
33
|
+
<Card>
|
|
34
|
+
<CardHeader>
|
|
35
|
+
<CardTitle level={2}>{t("markdownEditorDocs.edit.title")}</CardTitle>
|
|
36
|
+
<CardDescription>{t("markdownEditorDocs.edit.description")}</CardDescription>
|
|
37
|
+
</CardHeader>
|
|
38
|
+
<CardContent>
|
|
39
|
+
<Form onSubmit={(event) => event.preventDefault()}>
|
|
40
|
+
<Flex direction="col" gap="md">
|
|
41
|
+
<FormField id="page-body" label={t("markdownEditorDocs.edit.label")}>
|
|
42
|
+
<MarkdownEditor
|
|
43
|
+
value={body}
|
|
44
|
+
onValueChange={setBody}
|
|
45
|
+
upload={demoUpload}
|
|
46
|
+
defaultMode="split"
|
|
47
|
+
/>
|
|
48
|
+
</FormField>
|
|
49
|
+
<Flex justify="end">
|
|
50
|
+
<Button type="submit">{t("markdownEditorDocs.edit.save")}</Button>
|
|
51
|
+
</Flex>
|
|
52
|
+
</Flex>
|
|
53
|
+
</Form>
|
|
54
|
+
</CardContent>
|
|
55
|
+
</Card>
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle level={2}>{t("markdownEditorDocs.readOnly.title")}</CardTitle>
|
|
59
|
+
<CardDescription>{t("markdownEditorDocs.readOnly.description")}</CardDescription>
|
|
60
|
+
</CardHeader>
|
|
61
|
+
<CardContent>
|
|
62
|
+
<FormField id="page-body-readonly" label={t("markdownEditorDocs.readOnly.label")}>
|
|
63
|
+
<MarkdownEditor defaultValue={initial} readOnly />
|
|
64
|
+
</FormField>
|
|
65
|
+
</CardContent>
|
|
66
|
+
</Card>
|
|
67
|
+
</PageContainer>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -1570,8 +1570,33 @@
|
|
|
1570
1570
|
"badgeDocs": {
|
|
1571
1571
|
"longLabels": {
|
|
1572
1572
|
"title": "Long labels",
|
|
1573
|
-
"description": "A chip never wraps: a label wider than its container ends in an ellipsis (gh#1101), and the full text
|
|
1573
|
+
"description": "A chip never wraps: a label wider than its container ends in an ellipsis (gh#1101), and when it was cut the full text opens in a tooltip on hover and on keyboard focus of the link or row around the chip (gh#1105). No extra props in a table cell or a Card.",
|
|
1574
1574
|
"sample": "Via team · Platform infrastructure operations (East Japan region, night-shift rotation group 2)"
|
|
1575
1575
|
}
|
|
1576
|
+
},
|
|
1577
|
+
"markdownDocs": {
|
|
1578
|
+
"subtitle": "@godxjp/markdown · GFM + heading anchors + sanitiser · renderer v{version}",
|
|
1579
|
+
"page": {
|
|
1580
|
+
"title": "Page body",
|
|
1581
|
+
"description": "Tables, checklists, code, footnotes, Mermaid. A Mermaid fence becomes a diagram only after its generated SVG passes the check; until then it shows as code."
|
|
1582
|
+
},
|
|
1583
|
+
"hostile": {
|
|
1584
|
+
"title": "A hostile body",
|
|
1585
|
+
"description": "Raw HTML never becomes elements, and javascript: and data: URLs are removed."
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
"markdownEditorDocs": {
|
|
1589
|
+
"subtitle": "@godxjp/editor · formatting toolbar · write / preview / side by side · paste or drop to attach",
|
|
1590
|
+
"edit": {
|
|
1591
|
+
"title": "Edit a page",
|
|
1592
|
+
"description": "⌘/Ctrl + B, I, K for bold, italic, link. Shortcuts never fire during IME composition.",
|
|
1593
|
+
"label": "Body",
|
|
1594
|
+
"save": "Save"
|
|
1595
|
+
},
|
|
1596
|
+
"readOnly": {
|
|
1597
|
+
"title": "Read-only",
|
|
1598
|
+
"description": "The toolbar stays focusable, but its actions do nothing.",
|
|
1599
|
+
"label": "Body (view only)"
|
|
1600
|
+
}
|
|
1576
1601
|
}
|
|
1577
1602
|
}
|
|
@@ -1563,8 +1563,33 @@
|
|
|
1563
1563
|
"badgeDocs": {
|
|
1564
1564
|
"longLabels": {
|
|
1565
1565
|
"title": "長いラベル",
|
|
1566
|
-
"description": "チップは折り返さず、コンテナより広いラベルは省略記号で切れます(gh#1101
|
|
1566
|
+
"description": "チップは折り返さず、コンテナより広いラベルは省略記号で切れます(gh#1101)。切れたときは、ホバーでも、チップを囲むリンクや行へのキーボードフォーカスでも、全文がツールチップに出ます(gh#1105)。表のセルでも Card でも追加の指定は要りません。",
|
|
1567
1567
|
"sample": "チーム経由 · プラットフォーム基盤運用チーム(東日本リージョン・夜間当番ローテーション第二班)"
|
|
1568
1568
|
}
|
|
1569
|
+
},
|
|
1570
|
+
"markdownDocs": {
|
|
1571
|
+
"subtitle": "@godxjp/markdown · GFM + 見出しアンカー + サニタイズ · renderer v{version}",
|
|
1572
|
+
"page": {
|
|
1573
|
+
"title": "ページ本文",
|
|
1574
|
+
"description": "表・チェックリスト・コード・脚注・Mermaid。Mermaid は生成された SVG が検査を通ったときだけ図になり、それまではコードのまま表示されます。"
|
|
1575
|
+
},
|
|
1576
|
+
"hostile": {
|
|
1577
|
+
"title": "悪意のある本文",
|
|
1578
|
+
"description": "生の HTML は要素にならず、javascript: や data: の URL は取り除かれます。"
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
"markdownEditorDocs": {
|
|
1582
|
+
"subtitle": "@godxjp/editor · 書式ツールバー · 編集 / プレビュー / 並べて表示 · 貼り付け・ドロップで添付",
|
|
1583
|
+
"edit": {
|
|
1584
|
+
"title": "ページを編集",
|
|
1585
|
+
"description": "⌘/Ctrl + B・I・K で太字・斜体・リンク。変換中(IME)はショートカットが働きません。",
|
|
1586
|
+
"label": "本文",
|
|
1587
|
+
"save": "保存"
|
|
1588
|
+
},
|
|
1589
|
+
"readOnly": {
|
|
1590
|
+
"title": "読み取り専用",
|
|
1591
|
+
"description": "ツールバーはフォーカスできますが、操作は無効です。",
|
|
1592
|
+
"label": "本文(閲覧のみ)"
|
|
1593
|
+
}
|
|
1569
1594
|
}
|
|
1570
1595
|
}
|
|
@@ -1563,8 +1563,33 @@
|
|
|
1563
1563
|
"badgeDocs": {
|
|
1564
1564
|
"longLabels": {
|
|
1565
1565
|
"title": "Nhãn dài",
|
|
1566
|
-
"description": "Chip không bao giờ xuống dòng: nhãn rộng hơn khung chứa sẽ kết thúc bằng dấu ba chấm (gh#1101), và khi bị cắt thì toàn văn hiện
|
|
1566
|
+
"description": "Chip không bao giờ xuống dòng: nhãn rộng hơn khung chứa sẽ kết thúc bằng dấu ba chấm (gh#1101), và khi bị cắt thì toàn văn hiện trong tooltip khi rê chuột hoặc khi focus bàn phím vào liên kết/hàng chứa chip (gh#1105). Trong ô bảng hay Card đều không cần thêm prop.",
|
|
1567
1567
|
"sample": "Qua nhóm · Đội vận hành hạ tầng nền tảng (vùng Đông Nhật Bản, ca trực đêm nhóm 2)"
|
|
1568
1568
|
}
|
|
1569
|
+
},
|
|
1570
|
+
"markdownDocs": {
|
|
1571
|
+
"subtitle": "@godxjp/markdown · GFM + neo tiêu đề + sanitize · renderer v{version}",
|
|
1572
|
+
"page": {
|
|
1573
|
+
"title": "Nội dung trang",
|
|
1574
|
+
"description": "Bảng, danh sách việc, mã, chú thích, Mermaid. Khối mermaid chỉ thành sơ đồ khi SVG sinh ra qua được kiểm tra; trước đó hiện dạng mã."
|
|
1575
|
+
},
|
|
1576
|
+
"hostile": {
|
|
1577
|
+
"title": "Nội dung độc hại",
|
|
1578
|
+
"description": "HTML thô không bao giờ thành phần tử; URL javascript: và data: bị loại bỏ."
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
"markdownEditorDocs": {
|
|
1582
|
+
"subtitle": "@godxjp/editor · thanh định dạng · soạn / xem trước / song song · dán hoặc kéo thả để đính kèm",
|
|
1583
|
+
"edit": {
|
|
1584
|
+
"title": "Sửa trang",
|
|
1585
|
+
"description": "⌘/Ctrl + B, I, K: đậm, nghiêng, liên kết. Phím tắt không chạy khi đang gõ IME.",
|
|
1586
|
+
"label": "Nội dung",
|
|
1587
|
+
"save": "Lưu"
|
|
1588
|
+
},
|
|
1589
|
+
"readOnly": {
|
|
1590
|
+
"title": "Chỉ đọc",
|
|
1591
|
+
"description": "Thanh công cụ vẫn nhận focus nhưng thao tác bị vô hiệu.",
|
|
1592
|
+
"label": "Nội dung (chỉ xem)"
|
|
1593
|
+
}
|
|
1569
1594
|
}
|
|
1570
1595
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "31.
|
|
4
|
-
"godxUiMcp": "31.
|
|
3
|
+
"version": "31.18.0",
|
|
4
|
+
"godxUiMcp": "31.18.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"sideEffects": false,
|
|
23
|
-
"description": "@godxjp/ui
|
|
23
|
+
"description": "@godxjp/ui — shared React UI framework (shadcn + Radix + Tailwind v4).",
|
|
24
24
|
"files": [
|
|
25
25
|
"LICENSE",
|
|
26
26
|
"agent",
|
|
@@ -315,6 +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
319
|
"build:jis-level1-fonts": "node scripts/build-jis-level1-fonts.mjs",
|
|
319
320
|
"capture:voiceover": "node scripts/capture-voiceover-evidence.mjs",
|
|
320
321
|
"check:agent-catalog": "node scripts/gen-agent-catalog.mjs --check",
|
|
@@ -415,7 +416,8 @@
|
|
|
415
416
|
"test:visual:table-collection-cjk": "node scripts/table-collection-cjk-visual.mjs",
|
|
416
417
|
"test:visual:topbar-collision": "node scripts/topbar-collision-visual.mjs",
|
|
417
418
|
"test:watch": "vitest",
|
|
418
|
-
"typecheck": "node node_modules/typescript-7/bin/tsc --noEmit -p tsconfig.json",
|
|
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",
|
|
419
421
|
"typecheck:docs": "node node_modules/typescript-7/bin/tsc --noEmit -p tsconfig.docs.json",
|
|
420
422
|
"typecheck:mcp": "node node_modules/typescript-7/bin/tsc --noEmit -p mcp/tsconfig.json",
|
|
421
423
|
"typecheck:ts6": "tsc --noEmit -p tsconfig.json",
|
|
@@ -513,6 +515,8 @@
|
|
|
513
515
|
"@testing-library/jest-dom": "^7.0.1",
|
|
514
516
|
"@testing-library/react": "^16.3.3",
|
|
515
517
|
"@testing-library/user-event": "^14.6.6",
|
|
518
|
+
"@types/hast": "^3.0.5",
|
|
519
|
+
"@types/mdast": "^4.0.4",
|
|
516
520
|
"@types/node": "^26.4.0",
|
|
517
521
|
"@types/pngjs": "^6.0.5",
|
|
518
522
|
"@types/react": "^19.2.18",
|
|
@@ -523,9 +527,11 @@
|
|
|
523
527
|
"eslint": "^10.9.1",
|
|
524
528
|
"eslint-plugin-react": "^7.37.5",
|
|
525
529
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
530
|
+
"github-slugger": "^2.0.0",
|
|
526
531
|
"globals": "^17.11.0",
|
|
527
532
|
"jsdom": "^30.0.1",
|
|
528
533
|
"jsqr": "^1.4.0",
|
|
534
|
+
"mermaid": "^11.17.2",
|
|
529
535
|
"playwright": "^1.62.1",
|
|
530
536
|
"pngjs": "^7.0.0",
|
|
531
537
|
"prettier": "^3.9.6",
|
|
@@ -533,13 +539,17 @@
|
|
|
533
539
|
"react": "^19.2.8",
|
|
534
540
|
"react-dom": "^19.2.8",
|
|
535
541
|
"react-hook-form": "^7.86.0",
|
|
542
|
+
"react-markdown": "^10.1.0",
|
|
536
543
|
"react-router-dom": "^7.18.3",
|
|
537
544
|
"recharts": "^3.10.1",
|
|
545
|
+
"rehype-sanitize": "^6.0.0",
|
|
546
|
+
"remark-gfm": "^4.0.1",
|
|
538
547
|
"tailwindcss": "^4.3.3",
|
|
539
548
|
"tsup": "^8.5.1",
|
|
540
549
|
"typescript": "^6.0.3",
|
|
541
550
|
"typescript-7": "npm:typescript@7.0.2",
|
|
542
551
|
"typescript-eslint": "^8.68.0",
|
|
552
|
+
"unist-util-visit": "^5.1.0",
|
|
543
553
|
"vite": "^8.2.2",
|
|
544
554
|
"vitest": "^4.1.11",
|
|
545
555
|
"zod": "^4.5.4"
|