@mieweb/ui 0.11.0-dev.54 → 0.11.0-dev.56
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/README.md +2 -2
- package/agent/agents/mieweb-ui-design.agent.md +12 -2
- package/agent/agents/mieweb-ui-grids.agent.md +87 -0
- package/agent/agents/mieweb-ui-richtext.agent.md +86 -0
- package/agent/evals/README.md +2 -0
- package/agent/evals/grids.md +241 -0
- package/agent/evals/richtext.md +229 -0
- package/agent/skills/mieweb-ui-datavis-api/SKILL.md +173 -0
- package/agent/skills/mieweb-ui-kerebron/SKILL.md +173 -0
- package/package.json +1 -1
package/agent/README.md
CHANGED
|
@@ -22,8 +22,8 @@ governing spec: later tickets cite it instead of re-deciding.
|
|
|
22
22
|
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
23
|
| [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
|
|
24
24
|
| [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh all targets. `--experimental-agents` additionally installs the agent team below. |
|
|
25
|
-
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n` + `mieweb-ui-migration`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`.
|
|
26
|
-
| [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4`, `mieweb-ui-a11y-checklist`, `mieweb-ui-i18n-checklist` (hand-written). Installed to `.github/skills/` behind `--experimental-agents`. |
|
|
25
|
+
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n` + `mieweb-ui-migration` + `mieweb-ui-richtext` + `mieweb-ui-grids`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`. |
|
|
26
|
+
| [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4`, `mieweb-ui-a11y-checklist`, `mieweb-ui-i18n-checklist`, `mieweb-ui-kerebron`, `mieweb-ui-datavis-api` (hand-written). Installed to `.github/skills/` behind `--experimental-agents`. |
|
|
27
27
|
| `evals/` _(Phase 2+)_ | Golden-question eval sets per specialist; the regression harness for agent knowledge. |
|
|
28
28
|
|
|
29
29
|
Rule content is sourced from [lessons/component-policy.md](../lessons/component-policy.md);
|
|
@@ -23,6 +23,14 @@ handoffs:
|
|
|
23
23
|
agent: MIE UI Migration Agent
|
|
24
24
|
prompt: Audit the code discussed above for @mieweb/ui compliance (raw HTML elements, custom modal/card/badge patterns, hand-rolled icons, CSS foundation) and report findings with a prioritized replacement plan.
|
|
25
25
|
send: false
|
|
26
|
+
- label: Rich text editors
|
|
27
|
+
agent: MIE UI Rich Text Agent
|
|
28
|
+
prompt: Handle the rich-text question above (Kerebron editors, install legs, WASM/patches, collaboration, markdown round-trip, EmailEditor) and report the minimal fix.
|
|
29
|
+
send: false
|
|
30
|
+
- label: Grids & eSheet
|
|
31
|
+
agent: MIE UI Grids Agent
|
|
32
|
+
prompt: Handle the grid/eSheet question above (DataVis NITRO sources, columns, features, operations, eSheet Builder/Renderer) and report the minimal fix.
|
|
33
|
+
send: false
|
|
26
34
|
---
|
|
27
35
|
|
|
28
36
|
# MIE UI Design Agent (orchestrator)
|
|
@@ -60,9 +68,11 @@ comparison tables) and `mieweb-ui-icons` (icon aliases and conventions):
|
|
|
60
68
|
| ARIA, keyboard nav, screen readers, contrast | MIE UI A11y Agent |
|
|
61
69
|
| translations, locale bundles, Intl formats, RTL | MIE UI i18n Agent |
|
|
62
70
|
| migrating code to @mieweb/ui, raw-HTML compliance | MIE UI Migration Agent |
|
|
71
|
+
| rich text editors (RichEditor, TextAreaRich, EmailEditor), Kerebron peers/WASM/patches, collab, Markdown rendering | MIE UI Rich Text Agent |
|
|
72
|
+
| DataVis NITRO config (sources, columns, features, operations), eSheet Builder/Renderer, grid debugging | MIE UI Grids Agent |
|
|
63
73
|
|
|
64
|
-
More specialists (
|
|
65
|
-
SuperChat
|
|
74
|
+
More specialists (DataVis, Views,
|
|
75
|
+
SuperChat) land in later phases; until one ships, answer its domain
|
|
66
76
|
from the skills and the component docs, or defer (below).
|
|
67
77
|
|
|
68
78
|
**Tie-breakers:**
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: MIE UI Grids Agent
|
|
3
|
+
description: Grids specialist for the @mieweb/ui design system — DataVis NITRO (DataVisNitroSource/Grid/Graph, column API, feature flags, grouping/aggregates, operations palette, perspectives) and the eSheet form pair (Builder/Renderer, clinical fields, EncounterVisit). Invoke for configuring or debugging a NITRO grid or graph, source/column/feature questions, row selection and mass operations, grid performance with large datasets, AGGrid deprecation questions, and eSheet Builder/Renderer integration.
|
|
4
|
+
tools: ['search', 'codebase', 'fetch', 'runInTerminal']
|
|
5
|
+
handoffs:
|
|
6
|
+
- label: Apply Fixes
|
|
7
|
+
agent: agent
|
|
8
|
+
prompt: Apply the grid/eSheet integration fixes identified above to the codebase.
|
|
9
|
+
send: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MIE UI Grids Agent
|
|
13
|
+
|
|
14
|
+
You are the grids specialist for the **@mieweb/ui** design system. Consumers
|
|
15
|
+
come to you after they have a grid (or know they need one) — to configure
|
|
16
|
+
columns, sources and features, to wire selection and mass operations, to
|
|
17
|
+
debug an empty or misbehaving grid, and to integrate the eSheet
|
|
18
|
+
Builder/Renderer pair. You diagnose from evidence and report a minimal fix —
|
|
19
|
+
you do not edit files (offer the **Apply Fixes** handoff instead).
|
|
20
|
+
|
|
21
|
+
## Your sources of truth (never inline-duplicate them)
|
|
22
|
+
|
|
23
|
+
- **`mieweb-ui-datavis-api` skill** — the domain bible: the grid policy,
|
|
24
|
+
Source/Grid/Graph architecture and context coupling, source types
|
|
25
|
+
(`http`/`local`/`file`) and declarative `groupBy`/`aggregates`, the curated
|
|
26
|
+
grid props (chrome, columns, features, operations, perspectives), the
|
|
27
|
+
no-virtualization reality, orders-grid composition patterns, the eSheet
|
|
28
|
+
pair and clinical fields, and the symptom→fix troubleshooting table. Start
|
|
29
|
+
every answer here.
|
|
30
|
+
- **`mieweb-ui-catalog` skill** — entry points, the Grids family "Which one?"
|
|
31
|
+
table, and per-entry peer requirements.
|
|
32
|
+
- **`mieweb-ui-kerebron` skill** — when EncounterVisit's RichEdit mode or
|
|
33
|
+
eSheet narrative fields drag in the Kerebron editor stack.
|
|
34
|
+
|
|
35
|
+
## Workflow
|
|
36
|
+
|
|
37
|
+
1. **Enforce the policy before configuring.** Any plain `<table>` growing
|
|
38
|
+
sort/filter/page/export features, any new `AGGrid` usage, or `Pagination`
|
|
39
|
+
bolted onto a NITRO grid is the real finding — redirect to NITRO first,
|
|
40
|
+
then configure.
|
|
41
|
+
2. **Check the coupling before the props.** An empty or dead grid is usually
|
|
42
|
+
structural: Grid/Graph not nested inside a `DataVisNitroSource`, a
|
|
43
|
+
`local` source whose global isn't set at mount, or `datavis-ace` failing
|
|
44
|
+
to resolve.
|
|
45
|
+
3. **Prefer declarative configuration.** `groupBy`/`aggregates` on the
|
|
46
|
+
Source, `features`/`columns`/`operations` on the Grid. Imperative
|
|
47
|
+
`setGroup`/`setAggregate` through `DataVisNitroContext` is library-internal
|
|
48
|
+
composition, not consumer API.
|
|
49
|
+
4. **Be honest about limits.** There is no row virtualization and no
|
|
50
|
+
server-side row model — all operations run client-side over the fetched
|
|
51
|
+
dataset. For very large data, the fix is upstream (serve less, group,
|
|
52
|
+
aggregate), not a grid prop. Treat genuine capability gaps as NITRO
|
|
53
|
+
feature requests, never as a reason to reach for AGGrid.
|
|
54
|
+
5. **Match the skill's troubleshooting table**, then report root cause,
|
|
55
|
+
evidence, and the smallest fix. Offer **Apply Fixes** for the edit.
|
|
56
|
+
|
|
57
|
+
## Redirects
|
|
58
|
+
|
|
59
|
+
- "Which component should I use?" → **MIE UI Design Agent** (selection is the
|
|
60
|
+
orchestrator's domain; you own configuration, APIs and debugging of a
|
|
61
|
+
chosen grid).
|
|
62
|
+
- Install plumbing — Tailwind setup, `styles.css`, peer errors outside
|
|
63
|
+
`datavis-ace`/`@esheet/*` → **MIE UI Install Agent**.
|
|
64
|
+
- Token/Tailwind/brand theming of surrounding UI → **MIE UI Styling Agent**.
|
|
65
|
+
- Grid accessibility audits → **MIE UI A11y Agent** — but always carry the
|
|
66
|
+
caveat yourself: the engine's DOM is not screen-reader friendly; keep
|
|
67
|
+
critical actions reachable outside the grid.
|
|
68
|
+
- Charts beyond the NITRO Graph (YChart, Deck, Globe, maps) → the DataVis
|
|
69
|
+
specialist once it ships; until then the orchestrator answers from the
|
|
70
|
+
catalog skill.
|
|
71
|
+
|
|
72
|
+
## Rules
|
|
73
|
+
|
|
74
|
+
1. Never invent grid props, feature flags, or engine capabilities — the grid
|
|
75
|
+
surface is deliberately curated; verify against the skill or the installed
|
|
76
|
+
types before recommending a prop.
|
|
77
|
+
2. `AGGrid` is deprecated: never recommend it for new work; when NITRO lacks
|
|
78
|
+
a capability, say so and point to filing a NITRO feature request.
|
|
79
|
+
3. Never tell a consumer to call `setGroup`/`setAggregate` on
|
|
80
|
+
`DataVisNitroContext` — declarative props only.
|
|
81
|
+
4. eSheet Builder/Renderer never persist — storage always lives with the
|
|
82
|
+
host. Submission is either the Renderer's opt-in `onSubmit` button or a
|
|
83
|
+
host-driven `getValidResponse()` read (which returns
|
|
84
|
+
`{ response, errors }`, not a bare `FormResponse`) — never both.
|
|
85
|
+
5. Prefer the smallest change that fixes the root cause; no grid rewrites.
|
|
86
|
+
6. The installed `mieweb-ui.instructions.md` rules apply to any code you
|
|
87
|
+
recommend.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: MIE UI Rich Text Agent
|
|
3
|
+
description: Rich-text editing specialist for the @mieweb/ui design system — the Kerebron entry (RichEditor, CodeEditor, TextAreaRich), the Kerebron-backed main-barrel Textarea, EmailEditor, MarkdownRenderer, Yjs collaboration, WASM grammar serving, the exact-0.8.12 peer set with ProseMirror overrides, and the consumer-side @kerebron patches. Invoke for integrating or configuring any rich-text editor, typing/toolbar/WASM/collab failures, markdown round-trip or value-contract questions, and email-safe editing.
|
|
4
|
+
tools: ['search', 'codebase', 'fetch', 'runInTerminal']
|
|
5
|
+
handoffs:
|
|
6
|
+
- label: Apply Fixes
|
|
7
|
+
agent: agent
|
|
8
|
+
prompt: Apply the rich-text integration fixes identified above to the codebase.
|
|
9
|
+
send: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MIE UI Rich Text Agent
|
|
13
|
+
|
|
14
|
+
You are the rich-text editing specialist for the **@mieweb/ui** design
|
|
15
|
+
system. Consumers come to you to wire a Kerebron editor into their app, to
|
|
16
|
+
pick the right configuration for a surface they have already chosen, and when
|
|
17
|
+
an editor misbehaves — typing throws, toolbars are dead, grammars 404, marks
|
|
18
|
+
vanish on save, collaboration silently stops syncing. You diagnose from
|
|
19
|
+
evidence and report a minimal fix — you do not edit files (offer the
|
|
20
|
+
**Apply Fixes** handoff instead).
|
|
21
|
+
|
|
22
|
+
## Your sources of truth (never inline-duplicate them)
|
|
23
|
+
|
|
24
|
+
- **`mieweb-ui-kerebron` skill** — the domain bible: surfaces and their value
|
|
25
|
+
contracts, the three-legged install (exact-0.8.12 peers, ProseMirror
|
|
26
|
+
overrides, CSS + WASM assets), the consumer-side patches and what breaks
|
|
27
|
+
without each, RichEditor integration facts (read-once props, `getContent()`
|
|
28
|
+
on submit, `mediaUpload`, `omitExtensions`), collaboration and its degrade
|
|
29
|
+
path, Textarea-on-Kerebron behaviour changes, EmailEditor constraints, and
|
|
30
|
+
the symptom→fix troubleshooting table. Start every answer here.
|
|
31
|
+
- **`mieweb-ui-catalog` skill** — entry-point map and per-entry peer/CSS
|
|
32
|
+
requirements across the whole library.
|
|
33
|
+
- **`mieweb-ui-tailwind4` skill** — general install/CSS foundation when the
|
|
34
|
+
problem is upstream of the editors (missing `kerebron.css` is yours;
|
|
35
|
+
missing `styles.css` plumbing is Install's).
|
|
36
|
+
|
|
37
|
+
## Workflow
|
|
38
|
+
|
|
39
|
+
1. **Settle the value contract first.** Markdown → `RichEditor`; HTML in
|
|
40
|
+
textarea chrome → Kerebron `TextAreaRich`; plain text → `Textarea`; email
|
|
41
|
+
blocks → `EmailEditor`; display-only Markdown → `MarkdownRenderer`. Most
|
|
42
|
+
misconfigurations are a surface/format mismatch — e.g. echoing flattened
|
|
43
|
+
`Textarea` output back into a rich surface.
|
|
44
|
+
2. **Check the three install legs before the component.** Peers at exactly
|
|
45
|
+
0.8.12, the four ProseMirror overrides in the host, `kerebron.css` +
|
|
46
|
+
WASM assets at `/kerebron-wasm`. `pnpm why prosemirror-model` (or
|
|
47
|
+
`npm ls`/`yarn why`) must show a single version.
|
|
48
|
+
3. **Then the patches.** Dead toolbar dropdowns, dropped
|
|
49
|
+
highlight/sup/sub marks, and the axe `select-name` failure are all
|
|
50
|
+
missing-host-patch symptoms — the library's own `patchedDependencies` do
|
|
51
|
+
not propagate.
|
|
52
|
+
4. **Match the skill's troubleshooting table** before reasoning from scratch;
|
|
53
|
+
it covers the known failure modes with their issue numbers.
|
|
54
|
+
5. **Report, then hand off.** State root cause, evidence, and the smallest
|
|
55
|
+
fix. Offer **Apply Fixes** for the edit.
|
|
56
|
+
|
|
57
|
+
## Redirects
|
|
58
|
+
|
|
59
|
+
- "Which editor/component should I use?" → **MIE UI Design Agent** (selection
|
|
60
|
+
is the orchestrator's domain; you own configuration, APIs and debugging of
|
|
61
|
+
a chosen surface).
|
|
62
|
+
- Library-wide install plumbing — Tailwind setup, `styles.css`, dark mode,
|
|
63
|
+
brand CSS, non-editor peer errors → **MIE UI Install Agent**. You own the
|
|
64
|
+
Kerebron legs (peers/overrides/WASM/patches/`kerebron.css`).
|
|
65
|
+
- Token choices and visual theming of editor chrome → **MIE UI Styling
|
|
66
|
+
Agent**.
|
|
67
|
+
- Accessibility audits beyond the editor-specific facts you carry (labelling
|
|
68
|
+
via `aria-label`, the codecrock patch) → **MIE UI A11y Agent**.
|
|
69
|
+
|
|
70
|
+
## Rules
|
|
71
|
+
|
|
72
|
+
1. Never invent editor props, extension names, or Kerebron APIs — verify
|
|
73
|
+
against the skill, the library's types, or the consumer's installed
|
|
74
|
+
packages.
|
|
75
|
+
2. The legacy `RichTextEditor` and legacy `TextAreaRich` are deprecated
|
|
76
|
+
(mieweb/ui#692): never recommend them for new work; steer to the Kerebron
|
|
77
|
+
surfaces and flag any new usage you encounter.
|
|
78
|
+
3. Respect read-once props: any answer that changes `collab`, `mediaUpload`,
|
|
79
|
+
`modifyMenu` or `omitExtensions` at runtime must say "remount via `key`".
|
|
80
|
+
4. If documents persist anywhere, insist on an upload hook — base64
|
|
81
|
+
embedding is a data-size defect, not a style choice. The hook is
|
|
82
|
+
`mediaUpload.uploadHandler` on the surfaces that expose it (`RichEditor`,
|
|
83
|
+
Kerebron `TextAreaRich`); `EmailEditor`'s is `onUploadImage`.
|
|
84
|
+
5. Prefer the smallest change that fixes the root cause; no editor rewrites.
|
|
85
|
+
6. The installed `mieweb-ui.instructions.md` rules apply to any code you
|
|
86
|
+
recommend.
|
package/agent/evals/README.md
CHANGED
|
@@ -20,6 +20,8 @@ These files are maintainer-side quality tooling. They are **not** shipped by
|
|
|
20
20
|
| [a11y.md](./a11y.md) | Accessibility | MIE UI A11y Agent |
|
|
21
21
|
| [i18n.md](./i18n.md) | Internationalization / RTL | MIE UI i18n Agent |
|
|
22
22
|
| [migration.md](./migration.md) | Migration / compliance (incl. icons) | MIE UI Migration Agent |
|
|
23
|
+
| [richtext.md](./richtext.md) | Rich text / Kerebron editors | MIE UI Rich Text Agent |
|
|
24
|
+
| [grids.md](./grids.md) | DataVis NITRO + eSheet grids | MIE UI Grids Agent |
|
|
23
25
|
|
|
24
26
|
## Entry format
|
|
25
27
|
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Evals — DataVis NITRO + eSheet grids
|
|
2
|
+
|
|
3
|
+
Primary agent: **MIE UI Grids Agent**. See [README.md](./README.md) for
|
|
4
|
+
format and scoring. Selection-level grid questions (Table vs NITRO) live in
|
|
5
|
+
[selection.md](./selection.md); these cover configuration, APIs and
|
|
6
|
+
debugging of a chosen grid.
|
|
7
|
+
|
|
8
|
+
### GRD-1 — Minimal NITRO setup
|
|
9
|
+
|
|
10
|
+
- **Ask:** "What's the minimal code to show a sortable, filterable grid over a JSON endpoint?"
|
|
11
|
+
- **Expect:** `DataVisNitroGrid` nested inside
|
|
12
|
+
`<DataVisNitroSource type="http" url="…">` from `@mieweb/ui/datavis`;
|
|
13
|
+
parsing/type-inference automatic; sort/filter/group/export come from the
|
|
14
|
+
engine. No extra installs (`@mieweb/datavis` is bundled, `datavis-ace`
|
|
15
|
+
arrives as a dependency) and no extra CSS (base stylesheet already imports
|
|
16
|
+
the datavis styles).
|
|
17
|
+
- **Agent:** MIE UI Grids Agent
|
|
18
|
+
- **Source:** agent/skills/mieweb-ui-datavis-api/SKILL.md — Architecture/Source; DataVisNITRO MAINTAINERS.md
|
|
19
|
+
|
|
20
|
+
### GRD-2 — Empty grid, no error
|
|
21
|
+
|
|
22
|
+
- **Ask:** "My DataVisNitroGrid renders nothing and the console is clean."
|
|
23
|
+
- **Expect:** Structural first: the Grid must render **inside** a
|
|
24
|
+
`DataVisNitroSource` (they're coupled through `DataVisNitroContext`); for
|
|
25
|
+
`type="local"`, `window[varName]` must be set (shaped `{ typeInfo, data }`)
|
|
26
|
+
before mount.
|
|
27
|
+
- **Agent:** MIE UI Grids Agent
|
|
28
|
+
- **Source:** datavis-api skill — troubleshooting; DataVisNitro.tsx
|
|
29
|
+
|
|
30
|
+
### GRD-3 — Source is not a constructor
|
|
31
|
+
|
|
32
|
+
- **Ask:** "I get `datavis_ace.Source is not a constructor` at runtime."
|
|
33
|
+
- **Expect:** `datavis-ace` is a hard runtime requirement of
|
|
34
|
+
`DataVisNitroSource`, shipped as a regular dependency of `@mieweb/ui`
|
|
35
|
+
(external in the bundle) — it's missing or mis-resolved. Reinstall / check
|
|
36
|
+
`pnpm why datavis-ace`; never import it directly or add it manually as a
|
|
37
|
+
workaround.
|
|
38
|
+
- **Agent:** MIE UI Grids Agent
|
|
39
|
+
- **Source:** DataVisNITRO MAINTAINERS.md — Dependencies
|
|
40
|
+
|
|
41
|
+
### GRD-4 — Local data without a server
|
|
42
|
+
|
|
43
|
+
- **Ask:** "How do I feed an in-memory array of rows to a NITRO grid?"
|
|
44
|
+
- **Expect:** `type="local"` + `varName`: set
|
|
45
|
+
`window[varName] = { typeInfo, data }` before mounting and delete it on
|
|
46
|
+
unmount; the engine reads the global. Changing `varName` rebuilds the
|
|
47
|
+
source.
|
|
48
|
+
- **Agent:** MIE UI Grids Agent
|
|
49
|
+
- **Source:** DataVisNitro.tsx — LocalDataVisNitroSourceProps; demo stories LocalDataset
|
|
50
|
+
|
|
51
|
+
### GRD-5 — Column API
|
|
52
|
+
|
|
53
|
+
- **Ask:** "How do I pin a column, set a header label, and render HTML in cells?"
|
|
54
|
+
- **Expect:** `columns` on the grid: string = bare field name; object form
|
|
55
|
+
`{ field, header, pinned, allowHtml, … }` (plus
|
|
56
|
+
width/minWidth/maxWidth, visible, align, className,
|
|
57
|
+
typeInfo/sortable/filterable).
|
|
58
|
+
- **Agent:** MIE UI Grids Agent
|
|
59
|
+
- **Source:** nitro-columns.ts — DataVisNitroColumn; table/types.ts — TableColumn
|
|
60
|
+
|
|
61
|
+
### GRD-6 — Grouping declaratively
|
|
62
|
+
|
|
63
|
+
- **Ask:** "I'm calling `view.setGroup(…)` through DataVisNitroContext to group my grid — is that right?"
|
|
64
|
+
- **Expect:** No — configure declaratively via the Source's
|
|
65
|
+
`groupBy={[ 'status' ]}` (or `{ field, functionName }`) and `aggregates`
|
|
66
|
+
(`{ functionName, fields }`). Imperative context calls are
|
|
67
|
+
library-internal composition (e.g. `OrdersGroupPresets`), not consumer
|
|
68
|
+
API, and fight the declarative props.
|
|
69
|
+
- **Agent:** MIE UI Grids Agent
|
|
70
|
+
- **Source:** DataVisNITRO MAINTAINERS.md — gotchas; datavis-api skill — Source
|
|
71
|
+
|
|
72
|
+
### GRD-7 — Checkbox selection + bulk actions
|
|
73
|
+
|
|
74
|
+
- **Ask:** "Users need to select multiple rows and run a bulk delete."
|
|
75
|
+
- **Expect:** `features={{ rowSelection: 'checkbox' }}` (tri-state select-all
|
|
76
|
+
over the currently filtered rows) + an `operations` array —
|
|
77
|
+
`{ label, icon?, category?, callback(ctx) }` with `ctx.rows` as the
|
|
78
|
+
selection; surfaces in the operations palette. `onSelectionChange` for
|
|
79
|
+
host-side tracking.
|
|
80
|
+
- **Agent:** MIE UI Grids Agent
|
|
81
|
+
- **Source:** table/types.ts — TableFeatures; DataVisNITRO.stories.tsx — Operations
|
|
82
|
+
|
|
83
|
+
### GRD-8 — Feature flags inventory
|
|
84
|
+
|
|
85
|
+
- **Ask:** "What built-in behaviours can I toggle on the grid without custom code?"
|
|
86
|
+
- **Expect:** `features`: columnResize, columnReorder, stickyHeaders,
|
|
87
|
+
rowSelection (true | 'checkbox'), headerContextMenu, zebraStripe,
|
|
88
|
+
keyboardNav (j/k), drillDown, showMore, rowMode ('wrapped' | 'clipped').
|
|
89
|
+
Not an invented list — anything else needs verification against the types.
|
|
90
|
+
- **Agent:** MIE UI Grids Agent
|
|
91
|
+
- **Source:** table/types.ts — TableFeatures
|
|
92
|
+
|
|
93
|
+
### GRD-9 — Virtualization
|
|
94
|
+
|
|
95
|
+
- **Ask:** "How do I turn on row virtualization for my 50k-row grid?"
|
|
96
|
+
- **Expect:** You can't — the engine has **no row virtualization**; `height`
|
|
97
|
+
+ show-more/limit is the scrolling story. For very large data, fix it
|
|
98
|
+
upstream: serve a narrower dataset at the http `url`, group/aggregate, or
|
|
99
|
+
page before the grid. Honest-limit answers pass; invented virtualization
|
|
100
|
+
props FAIL.
|
|
101
|
+
- **Agent:** MIE UI Grids Agent
|
|
102
|
+
- **Source:** datavis-api skill — Grid chrome/troubleshooting (verified: no virtualization in packages/datavis)
|
|
103
|
+
|
|
104
|
+
### GRD-10 — Server-side rows?
|
|
105
|
+
|
|
106
|
+
- **Ask:** "Does NITRO support a server-side row model like AG Grid Enterprise?"
|
|
107
|
+
- **Expect:** No — `type="http"` fetches the dataset and **all operations run
|
|
108
|
+
client-side** over it. The server-side pattern is serving the right
|
|
109
|
+
dataset at `url`. No new AGGrid usage either (deprecated); a genuine gap
|
|
110
|
+
is a NITRO feature request.
|
|
111
|
+
- **Agent:** MIE UI Grids Agent
|
|
112
|
+
- **Source:** datavis-api skill — Source; MAINTAINERS.md — Prefer NITRO over AGGrid
|
|
113
|
+
|
|
114
|
+
### GRD-11 — Detail rows
|
|
115
|
+
|
|
116
|
+
- **Ask:** "Can a row expand to show a full-width detail panel?"
|
|
117
|
+
- **Expect:** `renderDetailRow` (adds a disclosure toggle per plain-mode row)
|
|
118
|
+
+ `detailRowsExpanded` to expand/collapse all; leave undefined for per-row
|
|
119
|
+
control.
|
|
120
|
+
- **Agent:** MIE UI Grids Agent
|
|
121
|
+
- **Source:** DataGrid.tsx — renderDetailRow/detailRowsExpanded
|
|
122
|
+
|
|
123
|
+
### GRD-12 — Minimal chrome
|
|
124
|
+
|
|
125
|
+
- **Ask:** "I want the grid without the title bar — just the table with a floating menu."
|
|
126
|
+
- **Expect:** `mode="minimal"` (floating hamburger over the table);
|
|
127
|
+
`minimalMode` is deprecated in its favor. `'full'` restores the classic
|
|
128
|
+
title bar with row count and inline buttons; `titleActions` adds custom
|
|
129
|
+
title-bar controls (hidden in minimal mode).
|
|
130
|
+
- **Agent:** MIE UI Grids Agent
|
|
131
|
+
- **Source:** DataGrid.tsx — mode/minimalMode/titleActions
|
|
132
|
+
|
|
133
|
+
### GRD-13 — Perspectives on shared devices
|
|
134
|
+
|
|
135
|
+
- **Ask:** "We deploy on shared kiosk machines — users' pinned grid views are leaking between logins."
|
|
136
|
+
- **Expect:** Pinned-perspective names persist to localStorage by default;
|
|
137
|
+
set `persistPinnedPerspectives={false}` so pins stay in memory for the
|
|
138
|
+
session.
|
|
139
|
+
- **Agent:** MIE UI Grids Agent
|
|
140
|
+
- **Source:** DataGrid.tsx — persistPinnedPerspectives
|
|
141
|
+
|
|
142
|
+
### GRD-14 — Grid + chart over one fetch
|
|
143
|
+
|
|
144
|
+
- **Ask:** "A dashboard needs the same records as a grid and a chart the user can reconfigure — do I fetch twice?"
|
|
145
|
+
- **Expect:** No — Grid and Graph are two renderers over the same
|
|
146
|
+
`DataVisNitroSource`/view; render `DataVisNitroGraph`
|
|
147
|
+
(`config`/`onConfigChange` for user-changed axes/chart type) beside the
|
|
148
|
+
grid inside one Source. Tiny inline trend → `Sparkline` instead.
|
|
149
|
+
- **Agent:** MIE UI Grids Agent
|
|
150
|
+
- **Source:** Grids.mdx — How they fit together; DataVisNitroGraph.tsx
|
|
151
|
+
|
|
152
|
+
### GRD-15 — i18n of the grid
|
|
153
|
+
|
|
154
|
+
- **Ask:** "How do I localize the grid's labels and number/date formats?"
|
|
155
|
+
- **Expect:** `locale` (BCP-47) drives number/date formatting;
|
|
156
|
+
`DataVisNitroLanguageSelector` switches the engine's own UI language
|
|
157
|
+
(toolbar/table strings). `trans` only customizes built-in
|
|
158
|
+
grouping-function labels — answers presenting it as a general grid
|
|
159
|
+
translator FAIL. Deeper string audits → i18n agent.
|
|
160
|
+
- **Agent:** MIE UI Grids Agent
|
|
161
|
+
- **Source:** DataVisNitro.tsx — trans/locale; stories LocalizedGrid
|
|
162
|
+
|
|
163
|
+
### GRD-16 — Grid accessibility
|
|
164
|
+
|
|
165
|
+
- **Ask:** "Is the NITRO grid screen-reader accessible?"
|
|
166
|
+
- **Expect:** Honest caveat: the engine's DOM is **not** screen-reader
|
|
167
|
+
friendly and automated a11y checks are disabled on the NITRO pages. Keep
|
|
168
|
+
critical actions reachable outside the grid; provide textual summaries for
|
|
169
|
+
charts. Full audit → A11y agent.
|
|
170
|
+
- **Agent:** MIE UI Grids Agent
|
|
171
|
+
- **Source:** Grids.mdx — Shared limitations
|
|
172
|
+
|
|
173
|
+
### GRD-17 — Hover row actions
|
|
174
|
+
|
|
175
|
+
- **Ask:** "I need per-row edit/delete buttons that appear on hover, consistent with our Table rows."
|
|
176
|
+
- **Expect:** `RowActionToolbar` (main barrel) with `group="grid"` composes
|
|
177
|
+
with NITRO cells — same component as `Table` rows use.
|
|
178
|
+
- **Agent:** MIE UI Grids Agent
|
|
179
|
+
- **Source:** Grids.mdx — How they fit together
|
|
180
|
+
|
|
181
|
+
### GRD-18 — Pagination on a NITRO grid
|
|
182
|
+
|
|
183
|
+
- **Ask:** "Which component adds page controls under my NITRO grid?"
|
|
184
|
+
- **Expect:** None — `Pagination` is for server-paged `Table`/card lists;
|
|
185
|
+
rows already in a NITRO grid never need it (filter/group/show-more replace
|
|
186
|
+
paging).
|
|
187
|
+
- **Agent:** MIE UI Grids Agent
|
|
188
|
+
- **Source:** Grids.mdx — Which one? (Pagination row)
|
|
189
|
+
|
|
190
|
+
### GRD-19 — eSheet pair contract
|
|
191
|
+
|
|
192
|
+
- **Ask:** "How do Builder and Renderer hand data to each other, and where's the submit button?"
|
|
193
|
+
- **Expect:** Builder `onChange` emits a `FormDefinition`; Renderer takes it
|
|
194
|
+
as `formDataInput`. Reading answers: the ref's `getValidResponse()`
|
|
195
|
+
returns `{ response: FormResponse | null, errors }` (store `response`, not
|
|
196
|
+
the wrapper), or opt into the built-in submit button via
|
|
197
|
+
`onSubmit`/`submitLabel`. Persistence is host-owned either way. Entry
|
|
198
|
+
`@mieweb/ui/esheet` needs **all four** matching `@esheet/*` peers
|
|
199
|
+
(`core`/`fields`/`builder`/`renderer`, `>=0.0.6-17`) even for
|
|
200
|
+
renderer-only use.
|
|
201
|
+
- **Agent:** MIE UI Grids Agent
|
|
202
|
+
- **Source:** CompositeForms.mdx — the eSheet pair; src/esheet.ts
|
|
203
|
+
|
|
204
|
+
### GRD-20 — Clinical fields unknown
|
|
205
|
+
|
|
206
|
+
- **Ask:** "My eSheet definition uses `medicationList` but the Renderer shows an unknown field type."
|
|
207
|
+
- **Expect:** Call `registerMieEsheetFields()` once before rendering
|
|
208
|
+
definitions that use the Healthcare list fields (`medicationList`,
|
|
209
|
+
`allergyList`, …) — it plugs them into both Builder and Renderer.
|
|
210
|
+
- **Agent:** MIE UI Grids Agent
|
|
211
|
+
- **Source:** src/esheet.ts; CompositeForms.mdx — two install surfaces
|
|
212
|
+
|
|
213
|
+
### GRD-21 — EncounterVisit RichEdit stack
|
|
214
|
+
|
|
215
|
+
- **Ask:** "EncounterVisit's RichEdit mode won't load in my app — what does it need beyond @esheet?"
|
|
216
|
+
- **Expect:** RichEdit rides the Kerebron editor: the `@kerebron/*` peers at
|
|
217
|
+
exactly 0.8.12 + ProseMirror overrides, `@mieweb/ui/kerebron.css`, and the
|
|
218
|
+
WASM assets at `/kerebron-wasm` — the full kerebron-skill install legs
|
|
219
|
+
(route depth to the Rich Text agent / kerebron skill).
|
|
220
|
+
- **Agent:** MIE UI Grids Agent
|
|
221
|
+
- **Source:** src/esheet.ts header; MIGRATION.md — eSheet and EncounterVisit
|
|
222
|
+
|
|
223
|
+
### GRD-22 — AGGrid escape hatch
|
|
224
|
+
|
|
225
|
+
- **Ask:** "NITRO doesn't do X that AG Grid does — can I use `@mieweb/ui/ag-grid` for this one grid?"
|
|
226
|
+
- **Expect:** No — `AGGrid` is deprecated, never for new work. Treat the gap
|
|
227
|
+
as a NITRO feature request (file an issue) so usages can move back; the
|
|
228
|
+
maintainers' stated policy is to close gaps in NITRO, not fall back.
|
|
229
|
+
- **Agent:** MIE UI Grids Agent
|
|
230
|
+
- **Source:** MAINTAINERS.md — Prefer NITRO over AGGrid; Grids.mdx policy
|
|
231
|
+
|
|
232
|
+
### GRD-23 — Orders grids as the pattern
|
|
233
|
+
|
|
234
|
+
- **Ask:** "We're building an order-history grid with group-by chips and bulk status updates — is there prior art?"
|
|
235
|
+
- **Expect:** `ChartOrdersGrid`/`EncounterOrdersGrid` (datavis entry) over
|
|
236
|
+
the HealthSurveillance order history, with `OrdersGroupPresets` chips and
|
|
237
|
+
native NITRO `rowSelection: 'checkbox'` + `operations` for mass updates;
|
|
238
|
+
pure row builders (`buildChartOrderRows`/`buildEncounterOrderRows`) in the
|
|
239
|
+
main entry. Copy the composition, don't re-implement it.
|
|
240
|
+
- **Agent:** MIE UI Grids Agent
|
|
241
|
+
- **Source:** src/datavis.ts; ordersGridShared.tsx
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Evals — Rich text / Kerebron editors
|
|
2
|
+
|
|
3
|
+
Primary agent: **MIE UI Rich Text Agent**. See [README.md](./README.md) for
|
|
4
|
+
format and scoring.
|
|
5
|
+
|
|
6
|
+
### RT-1 — Which editor for the stored format
|
|
7
|
+
|
|
8
|
+
- **Ask:** "I need a rich input whose saved value is HTML, looking like a plain textarea until the user asks for the toolbar. Which component?"
|
|
9
|
+
- **Expect:** Kerebron `TextAreaRich` from `@mieweb/ui/kerebron` (HTML
|
|
10
|
+
contract, one Input row tall, auto-grows, toolbar hidden until asked) — not
|
|
11
|
+
`RichEditor` (Markdown contract) and not the deprecated main-barrel
|
|
12
|
+
`TextAreaRich`. Selection may be answered by the orchestrator directly.
|
|
13
|
+
- **Agent:** MIE UI Design Agent (selection) → MIE UI Rich Text Agent for config
|
|
14
|
+
- **Source:** src/catalog/Editors.mdx — Which one? table; agent/skills/mieweb-ui-kerebron/SKILL.md — Surfaces
|
|
15
|
+
|
|
16
|
+
### RT-2 — Install legs
|
|
17
|
+
|
|
18
|
+
- **Ask:** "What exactly do I install and configure to use RichEditor in my Vite app?"
|
|
19
|
+
- **Expect:** All three legs: (1) `@kerebron/*` peers at **exactly 0.8.12**
|
|
20
|
+
(`--save-exact`; `editor`, `editor-kits`, `extension-basic-editor`,
|
|
21
|
+
`extension-menu`, `wasm`), (2) the four ProseMirror overrides in the host
|
|
22
|
+
(view 1.42.3, model 1.25.9, state 1.4.3, transform 1.10.4), (3)
|
|
23
|
+
`@mieweb/ui/kerebron.css` + serve `@kerebron/wasm/assets` at
|
|
24
|
+
`/kerebron-wasm`. Plus the consumer-side `@kerebron` patches.
|
|
25
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
26
|
+
- **Source:** MIGRATION.md — eSheet and EncounterVisit / 0.12 sections; agent/skills/mieweb-ui-kerebron/SKILL.md — Install
|
|
27
|
+
|
|
28
|
+
### RT-3 — Fragment RangeError
|
|
29
|
+
|
|
30
|
+
- **Ask:** "Typing in any editor throws `RangeError: Can not convert <…> to a Fragment (looks like multiple versions of prosemirror-model were loaded)`. What's wrong?"
|
|
31
|
+
- **Expect:** Split ProseMirror resolution (mieweb/ui#709): Kerebron range
|
|
32
|
+
drifted to 0.8.13+ or transitive `^`-ranges floated on a fresh install. Fix:
|
|
33
|
+
pin `@kerebron/*` to 0.8.12 exactly + add the four overrides;
|
|
34
|
+
`pnpm dedupe` cannot fix it; verify with `pnpm why prosemirror-model`
|
|
35
|
+
(single version).
|
|
36
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
37
|
+
- **Source:** MIGRATION.md — mieweb/ui#709 section; kerebron skill troubleshooting
|
|
38
|
+
|
|
39
|
+
### RT-4 — Why prosemirror-view 1.42.3
|
|
40
|
+
|
|
41
|
+
- **Ask:** "Kerebron pins prosemirror-view 1.40.0 — why does the override force 1.42.3?"
|
|
42
|
+
- **Expect:** The protected MDY link bridge uses 1.42.3; two view instances
|
|
43
|
+
can make decorations incompatible and leave the older view's behavior
|
|
44
|
+
active.
|
|
45
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
46
|
+
- **Source:** MIGRATION.md — prosemirror-view note
|
|
47
|
+
|
|
48
|
+
### RT-5 — WASM 404s
|
|
49
|
+
|
|
50
|
+
- **Ask:** "Code blocks have no syntax highlighting and the console shows 404s for `.wasm` files."
|
|
51
|
+
- **Expect:** The editor loads tree-sitter grammars at runtime from
|
|
52
|
+
`/kerebron-wasm`; serve `@kerebron/wasm`'s `assets/` dir at that path (copy
|
|
53
|
+
or symlink into `public/`, or Storybook `staticDirs`), or pass a custom
|
|
54
|
+
`assetLoad` (`createAssetLoad('/other-path')`).
|
|
55
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
56
|
+
- **Source:** src/kerebron.ts header; RichEditor `assetLoad` prop docs
|
|
57
|
+
|
|
58
|
+
### RT-6 — Dead toolbar dropdowns
|
|
59
|
+
|
|
60
|
+
- **Ask:** "The Heading and List dropdowns in the RichEditor toolbar don't open when clicked."
|
|
61
|
+
- **Expect:** Host is missing the `@kerebron/extension-menu` patch — the
|
|
62
|
+
library's `patchedDependencies` don't propagate; apply
|
|
63
|
+
`patches/@kerebron__extension-menu@0.8.12.patch` in the host (pnpm-format;
|
|
64
|
+
npm/yarn convert for patch-package).
|
|
65
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
66
|
+
- **Source:** RichEditor.stories.tsx docs; patches/; kerebron skill — patches table
|
|
67
|
+
|
|
68
|
+
### RT-7 — Marks dropped on save
|
|
69
|
+
|
|
70
|
+
- **Ask:** "Highlight, superscript and subscript formatting disappears when the document is saved and reloaded."
|
|
71
|
+
- **Expect:** Missing `@kerebron/extension-markdown` patch (mieweb/ui#536):
|
|
72
|
+
the serializer's mark table has no entries for those marks, so they're
|
|
73
|
+
silently dropped on the markdown round-trip; patched they serialize as
|
|
74
|
+
`<mark>`/`<sup>`/`<sub>` inline HTML.
|
|
75
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
76
|
+
- **Source:** patches/@kerebron__extension-markdown@0.8.12.patch; kerebron skill — patches table
|
|
77
|
+
|
|
78
|
+
### RT-8 — Reading the value on submit
|
|
79
|
+
|
|
80
|
+
- **Ask:** "Should I trust my `onChange`-mirrored state when the user hits Save?"
|
|
81
|
+
- **Expect:** No — `onChange` can lag the last keystroke; call the ref's
|
|
82
|
+
`getContent()` on submit (async, awaits the initial load; rejects if setup
|
|
83
|
+
failed — see `onError`).
|
|
84
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
85
|
+
- **Source:** RichEditorHandle docs — getContent
|
|
86
|
+
|
|
87
|
+
### RT-9 — Changing collab/mediaUpload at runtime
|
|
88
|
+
|
|
89
|
+
- **Ask:** "How do I switch the RichEditor to a different collaboration room without reloading the page?"
|
|
90
|
+
- **Expect:** `collab` (like `mediaUpload`, `modifyMenu`, `omitExtensions`)
|
|
91
|
+
is read once at mount — **remount via `key`** to switch rooms; collab mode
|
|
92
|
+
is uncontrolled.
|
|
93
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
94
|
+
- **Source:** RichEditor collab prop docs; kerebron skill — read-once props
|
|
95
|
+
|
|
96
|
+
### RT-10 — Pasted images bloat the document
|
|
97
|
+
|
|
98
|
+
- **Ask:** "A pasted screenshot turned my saved markdown into a 6 MB payload. How do I prevent that?"
|
|
99
|
+
- **Expect:** Set `mediaUpload.uploadHandler` — without it images embed as
|
|
100
|
+
base64 `data:` URLs (and video as reload-dead blob URLs); the handler
|
|
101
|
+
uploads the file and returns a URL so the document carries a link, not
|
|
102
|
+
bytes. Required whenever documents persist.
|
|
103
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
104
|
+
- **Source:** RichEditor mediaUpload prop docs
|
|
105
|
+
|
|
106
|
+
### RT-11 — Removing a feature wholesale
|
|
107
|
+
|
|
108
|
+
- **Ask:** "How do I remove checklists (toolbar button, `- [ ]` shortcut, paste) from the editor in one move?"
|
|
109
|
+
- **Expect:** `omitExtensions={['task_list', 'task_item']}` — toolbar, input
|
|
110
|
+
rules and paste handling are all schema-driven, so dropping the nodes
|
|
111
|
+
removes the whole feature; read once at mount.
|
|
112
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
113
|
+
- **Source:** RichEditor omitExtensions prop docs
|
|
114
|
+
|
|
115
|
+
### RT-12 — Collab silently local
|
|
116
|
+
|
|
117
|
+
- **Ask:** "I pass `collab={{ room }}` but edits don't sync between users, and there's no error."
|
|
118
|
+
- **Expect:** `onUnavailable` reports **kit-load failures only** (optional
|
|
119
|
+
peers `@kerebron/extension-yjs`, `yjs`, `y-protocols` missing): the editor
|
|
120
|
+
mounts as a local one and the callback fires once, before the editor is
|
|
121
|
+
created. A reachable-but-disconnected relay is different — the kit stays
|
|
122
|
+
loaded and the provider retries on its own, with no callback. Fix: install
|
|
123
|
+
the peers and pass `collab.onUnavailable` to surface load failures; for
|
|
124
|
+
connectivity, check the `/yjs` websocket relay (`wsUrl` default
|
|
125
|
+
`<ws|wss>://<location.host>/yjs`).
|
|
126
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
127
|
+
- **Source:** RichEditor collab docs; collabKit.ts; kerebron skill — Collaboration
|
|
128
|
+
|
|
129
|
+
### RT-13 — MISSING_EXPORT at build
|
|
130
|
+
|
|
131
|
+
- **Ask:** "My `vite build` fails with `MISSING_EXPORT` from `@kerebron/extension-yjs` in a `collabKit-*` chunk, but I never use collaboration."
|
|
132
|
+
- **Expect:** Optional collab peers absent + an @mieweb/ui version older than
|
|
133
|
+
the mieweb/ui#706 fix (static named imports in the lazy collab chunk; the
|
|
134
|
+
optional-peer stub has no named exports). Fix: upgrade @mieweb/ui, or
|
|
135
|
+
externalize `/^@kerebron\/extension-yjs/` and `/^y-websocket/`.
|
|
136
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
137
|
+
- **Source:** collabKit.ts header (mieweb/ui#706); tailwind4 + kerebron skill troubleshooting
|
|
138
|
+
|
|
139
|
+
### RT-14 — Legacy RichTextEditor
|
|
140
|
+
|
|
141
|
+
- **Ask:** "Can I use RichTextEditor for a new templated-letter feature? It has `{{variables}}` and dictation."
|
|
142
|
+
- **Expect:** No — `RichTextEditor` (the `document.execCommand` engine) is
|
|
143
|
+
deprecated (mieweb/ui#692), never for new work; use Kerebron `TextAreaRich`
|
|
144
|
+
for HTML with `variableGroups` + dictation, or `RichEditor` for Markdown.
|
|
145
|
+
Note it emits raw unsanitised `innerHTML`.
|
|
146
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
147
|
+
- **Source:** src/catalog/Editors.mdx — deprecated rows (mieweb/ui#692)
|
|
148
|
+
|
|
149
|
+
### RT-15 — Textarea DOM shape
|
|
150
|
+
|
|
151
|
+
- **Ask:** "After upgrading to 0.12 my CSS `textarea { … }` rules and my test's element selectors stopped matching the Textarea."
|
|
152
|
+
- **Expect:** Since 0.12 `Textarea` renders the Kerebron engine: no visible
|
|
153
|
+
`<textarea>` — a ProseMirror `contenteditable` (`role="textbox"`, class
|
|
154
|
+
`kb-editor`) plus a hidden mirror `[data-slot="textarea-mirror"]` carrying
|
|
155
|
+
`name`/`value`. Target the `data-slot` hooks (`[data-slot^="textarea-"]`
|
|
156
|
+
or a concrete slot); `getByRole('textbox')`
|
|
157
|
+
keeps working; `TextAreaPlain` / `richText={false}` restores the native
|
|
158
|
+
element.
|
|
159
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
160
|
+
- **Source:** MIGRATION.md — Textarea is rich text underneath (0.12.0)
|
|
161
|
+
|
|
162
|
+
### RT-16 — maxLength not enforced
|
|
163
|
+
|
|
164
|
+
- **Ask:** "Textarea's `maxLength` no longer blocks typing past the limit — bug?"
|
|
165
|
+
- **Expect:** Known behaviour change (0.12): `maxLength` isn't enforced while
|
|
166
|
+
typing; the `showCount` counter still renders and turns red. Enforce in
|
|
167
|
+
`onChange` or switch to `TextAreaPlain`.
|
|
168
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
169
|
+
- **Source:** MIGRATION.md — Behaviour changes to review
|
|
170
|
+
|
|
171
|
+
### RT-17 — Email checklists vanish
|
|
172
|
+
|
|
173
|
+
- **Ask:** "Why can't users add checklists inside EmailEditor text blocks?"
|
|
174
|
+
- **Expect:** By design (mieweb/ui#695): email `text` blocks are
|
|
175
|
+
`TextAreaRich` with `omitExtensions={['task_list', 'task_item']}` —
|
|
176
|
+
checkbox inputs are sanitizer-forbidden and inert in mail clients, so the
|
|
177
|
+
feature is removed schema-first. Not a bug.
|
|
178
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
179
|
+
- **Source:** EmailBlockSettings.tsx — EMAIL_OMITTED_EXTENSIONS; kerebron skill — EmailEditor
|
|
180
|
+
|
|
181
|
+
### RT-18 — Compiling EmailEditor output
|
|
182
|
+
|
|
183
|
+
- **Ask:** "EmailEditor gives me MJML from `renderEmailMjml` — does @mieweb/ui compile it to email HTML?"
|
|
184
|
+
- **Expect:** No — compile with `mjml` (Node) or `mjml-browser` **host-side**;
|
|
185
|
+
it is not a peer. The editor's document is JSON blocks, not HTML; sending,
|
|
186
|
+
recipients and templates are the host's concern.
|
|
187
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
188
|
+
- **Source:** src/catalog/Editors.mdx — EmailEditor row + peers table
|
|
189
|
+
|
|
190
|
+
### RT-19 — Labelling the editor
|
|
191
|
+
|
|
192
|
+
- **Ask:** "My `<label htmlFor={editorId}>` doesn't give the RichEditor an accessible name."
|
|
193
|
+
- **Expect:** The host is a `div`, not a labelable control — `htmlFor` won't
|
|
194
|
+
associate; use `aria-label` or `aria-labelledby` (the `id` prop is the
|
|
195
|
+
anchor). Deeper audits go to the A11y agent.
|
|
196
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
197
|
+
- **Source:** RichEditor id/aria props docs; Editors.mdx — Labelling
|
|
198
|
+
|
|
199
|
+
### RT-20 — Displaying what RichEditor saved
|
|
200
|
+
|
|
201
|
+
- **Ask:** "What renders the markdown a RichEditor produced, in a read-only record view with mermaid diagrams?"
|
|
202
|
+
- **Expect:** `MarkdownRenderer` (main barrel, `@mieweb/ui/markdown.css`) —
|
|
203
|
+
sanitised HTML, code highlighting, `mermaid`/`csv`/`survey`/`html` fences,
|
|
204
|
+
`streaming` for token-by-token AI output. Conditional deps: `mermaid` for
|
|
205
|
+
the mermaid fence, `papaparse` for csv, `js-yaml` only for YAML-input
|
|
206
|
+
surveys (JSON surveys and the html fence need none). Legacy
|
|
207
|
+
`RichTextEditor` HTML does **not** go through it.
|
|
208
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
209
|
+
- **Source:** src/catalog/Editors.mdx — Markdown row + "Markdown closes the loop"
|
|
210
|
+
|
|
211
|
+
### RT-21 — Controlled value semantics
|
|
212
|
+
|
|
213
|
+
- **Ask:** "I set `value` and `onChange` on RichEditor but rejected edits don't revert like a native controlled input."
|
|
214
|
+
- **Expect:** Default is tolerant of read-once hosts (`getContent()` on
|
|
215
|
+
submit); opt in to native controlled semantics with `strictValue` —
|
|
216
|
+
converges the document to `value` on every render so un-echoed edits
|
|
217
|
+
revert. Also: changing `value` reloads the editor (unless `collab`).
|
|
218
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
219
|
+
- **Source:** RichEditor strictValue/value prop docs
|
|
220
|
+
|
|
221
|
+
### RT-22 — HTML-valued RichEditor
|
|
222
|
+
|
|
223
|
+
- **Ask:** "Can RichEditor speak HTML instead of Markdown without switching components?"
|
|
224
|
+
- **Expect:** Yes — `valueType="text/html"` governs both how `value` is
|
|
225
|
+
parsed and what `onChange`/`getContent()` emit (default
|
|
226
|
+
`'text/x-markdown'`). But if the goal is a textarea-like HTML field,
|
|
227
|
+
`TextAreaRich` is the intended surface.
|
|
228
|
+
- **Agent:** MIE UI Rich Text Agent
|
|
229
|
+
- **Source:** RichEditor valueType prop docs; Editors.mdx — Which one? table
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mieweb-ui-datavis-api
|
|
3
|
+
description: Deep API reference for @mieweb/ui grids — DataVis NITRO (DataVisNitroSource/Grid/Graph, column API, feature flags, grouping/aggregates, operations palette, perspectives) and the eSheet form pair (Builder/Renderer, registerMieEsheetFields, EncounterVisit). USE WHEN configuring or debugging a NITRO grid or graph, choosing columns/features/sources, wiring row selection and mass operations, grouping or aggregating, or integrating eSheet Builder/Renderer and its clinical fields.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DataVis NITRO + eSheet in @mieweb/ui
|
|
7
|
+
|
|
8
|
+
Sourced from `src/catalog/Grids.mdx`, `CompositeForms.mdx`, the DataVisNITRO
|
|
9
|
+
MAINTAINERS notes, `packages/datavis` source and `MIGRATION.md`. Grid
|
|
10
|
+
*selection* policy lives in the catalog skill; this is the configuration/API
|
|
11
|
+
layer.
|
|
12
|
+
|
|
13
|
+
## Policy (non-negotiable)
|
|
14
|
+
|
|
15
|
+
> **Tables and data grids start with DataVis NITRO.** Use `Table` only for a
|
|
16
|
+
> few static rows the user will not sort, filter, page or export. Never
|
|
17
|
+
> hand-roll grid features on a plain table; `AGGrid` is deprecated.
|
|
18
|
+
|
|
19
|
+
`Pagination` is for server-paged `Table`/card lists only — rows already in a
|
|
20
|
+
NITRO grid never need it.
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
- Entry: **`@mieweb/ui/datavis`** — exports `DataVisNitroSource`,
|
|
25
|
+
`DataVisNitroGrid`, `DataVisNitroGraph`, `DataVisNitroContext`,
|
|
26
|
+
`DataVisNitroLanguageSelector`, plus `ChartOrdersGrid`/`EncounterOrdersGrid`
|
|
27
|
+
and `OrdersGroupPresets`.
|
|
28
|
+
- **Two moving parts, zero consumer installs:** `@mieweb/datavis` (the
|
|
29
|
+
engine's React surface) is **bundled into** the entry; `datavis-ace` (the
|
|
30
|
+
data engine: fetch/parse/type-inference/aggregation) is a regular
|
|
31
|
+
**dependency** of `@mieweb/ui` — consumers never install or import either.
|
|
32
|
+
- **Source and Grid are coupled through React context:** a `DataVisNitroGrid`
|
|
33
|
+
must render inside a `DataVisNitroSource` (which creates the source/view
|
|
34
|
+
pair and publishes it through `DataVisNitroContext`). **Grid** and
|
|
35
|
+
**Graph** are two renderers over the same source — a dashboard flips
|
|
36
|
+
between rows and a chart without refetching.
|
|
37
|
+
- Styles: the base `@mieweb/ui/styles.css` already imports
|
|
38
|
+
`@mieweb/datavis/styles.css` — no extra CSS wiring.
|
|
39
|
+
|
|
40
|
+
## DataVisNitroSource
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<DataVisNitroSource type="http" url="/api/orders.json" groupBy={['status']}>
|
|
44
|
+
<DataVisNitroGrid title="Orders" />
|
|
45
|
+
</DataVisNitroSource>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `type: 'http'` — `url` is fetched by the engine; parsing and type inference
|
|
49
|
+
are automatic. **All grid operations (sort/filter/group/aggregate) run
|
|
50
|
+
client-side** over the fetched dataset — there is no server-side row model;
|
|
51
|
+
the "server-side pattern" is serving the right dataset at `url`.
|
|
52
|
+
- `type: 'local'` — `varName` names a global: set
|
|
53
|
+
`window[varName] = { typeInfo, data }` **before** mounting (the engine
|
|
54
|
+
reads it from `globalThis`); clean it up on unmount.
|
|
55
|
+
- `type: 'file'` — user-supplied file (the engine's file picker/parse path).
|
|
56
|
+
- `groupBy?: Array<string | { field, functionName? }>` and
|
|
57
|
+
`aggregates?: Array<{ functionName, fields }>` configure grouped/aggregated
|
|
58
|
+
views **declaratively**. Do not reach into `DataVisNitroContext` to call
|
|
59
|
+
`setGroup`/`setAggregate` — that context is for the library's own
|
|
60
|
+
composition (e.g. `OrdersGroupPresets`), not the consumer API.
|
|
61
|
+
- Changing `type`/`url`/`varName` rebuilds the source; changing
|
|
62
|
+
`groupBy`/`aggregates` reconfigures the live view.
|
|
63
|
+
|
|
64
|
+
## DataVisNitroGrid
|
|
65
|
+
|
|
66
|
+
A curated surface over the engine's `DataGrid` (the maintainers deliberately
|
|
67
|
+
`Omit` `view`/`children`/`allColumns` and re-add a vetted set — do not assume
|
|
68
|
+
an upstream `DataGrid` prop exists here without checking the types):
|
|
69
|
+
|
|
70
|
+
- **Chrome:** `title`, `helpText`, `titleActions` (title-bar React nodes),
|
|
71
|
+
`mode: 'default' | 'full' | 'minimal'` (`minimalMode` is deprecated — use
|
|
72
|
+
`mode="minimal"`), `showToolbar`, `showControls`, `height` (CSS value —
|
|
73
|
+
this plus the engine's show-more/limit is the scrolling story; **there is
|
|
74
|
+
no row virtualization**, so cap very large result sets at the source).
|
|
75
|
+
- **Columns:** `columns?: Array<string | TableColumn>` — a bare string is a
|
|
76
|
+
field name; the object form is
|
|
77
|
+
`{ field, header, width/minWidth/maxWidth, visible, pinned, align,
|
|
78
|
+
className, allowHtml, typeInfo: { type, format }, sortable, filterable }`.
|
|
79
|
+
Column menus, pinning, resize/reorder persistence and saved
|
|
80
|
+
**perspectives** come from the engine (`prefs`,
|
|
81
|
+
`persistPinnedPerspectives={false}` for shared/public devices).
|
|
82
|
+
- **Features** (`features?: TableFeatures`): `columnResize`, `columnReorder`,
|
|
83
|
+
`stickyHeaders`, `rowSelection: true | 'checkbox'` (checkbox mode adds a
|
|
84
|
+
tri-state select-all over the currently *filtered* rows),
|
|
85
|
+
`headerContextMenu`, `zebraStripe`, `keyboardNav` (j/k), `drillDown`,
|
|
86
|
+
`showMore`, `rowMode: 'wrapped' | 'clipped'`.
|
|
87
|
+
- **Rows:** `formatCell`, `onRowClick`, `onRowDoubleClick`,
|
|
88
|
+
`onSelectionChange`, `renderDetailRow` + `detailRowsExpanded` (disclosure
|
|
89
|
+
rows), `onColumnReorder`/`onColumnResize`/`onHeaderContextMenu`.
|
|
90
|
+
- **Mass operations:** `operations?: Operation[]` — each
|
|
91
|
+
`{ label, icon?, category?, callback(ctx) }` surfaces in the operations
|
|
92
|
+
palette; `ctx.rows` is the current selection. Pair with
|
|
93
|
+
`features.rowSelection: 'checkbox'` for bulk edit/delete/export flows.
|
|
94
|
+
- **i18n/formatting:** `locale` (BCP-47) drives number/date formatting.
|
|
95
|
+
`DataVisNitroLanguageSelector` is the UI-language mechanism — it switches
|
|
96
|
+
the engine's own i18next language (toolbar/table strings). `trans` is
|
|
97
|
+
narrower than it looks: it only customizes the built-in grouping-function
|
|
98
|
+
labels; it does **not** translate the general grid UI.
|
|
99
|
+
- **Hover row actions:** `RowActionToolbar` with `group="grid"` (main
|
|
100
|
+
barrel) composes with NITRO cells, same as with `Table` rows.
|
|
101
|
+
|
|
102
|
+
## DataVisNitroGraph
|
|
103
|
+
|
|
104
|
+
Same source, chart renderer: `columns`, `config?: Partial<GraphConfig>` +
|
|
105
|
+
`onConfigChange` (users may change axes/chart type), `locale`, `height`,
|
|
106
|
+
`className`. For a tiny inline dependency-free trend use `Sparkline` (main
|
|
107
|
+
barrel) instead.
|
|
108
|
+
|
|
109
|
+
## Real-world composition (orders grids)
|
|
110
|
+
|
|
111
|
+
`ChartOrdersGrid` / `EncounterOrdersGrid` (this entry) are NITRO grids over
|
|
112
|
+
HealthSurveillance order history; the pure row builders
|
|
113
|
+
(`buildChartOrderRows`/`buildEncounterOrderRows`) live in the **main** entry.
|
|
114
|
+
`OrdersGroupPresets` renders one-click group-by chips. Row selection and mass
|
|
115
|
+
operations there are native NITRO features — the pattern to copy, not
|
|
116
|
+
re-implement.
|
|
117
|
+
|
|
118
|
+
## Accessibility caveat
|
|
119
|
+
|
|
120
|
+
The DataVis engine's DOM is **not screen-reader friendly** and automated a11y
|
|
121
|
+
checks are disabled on the NITRO pages. Keep critical actions reachable
|
|
122
|
+
outside the grid and provide textual summaries for charts. Route full audits
|
|
123
|
+
to the A11y agent.
|
|
124
|
+
|
|
125
|
+
## eSheet (Builder/Renderer)
|
|
126
|
+
|
|
127
|
+
- Entry: **`@mieweb/ui/esheet`**; optional peers are **all four** `@esheet/*`
|
|
128
|
+
packages — `@esheet/core`, `@esheet/fields`, `@esheet/builder`,
|
|
129
|
+
`@esheet/renderer` — at matching versions (`>=0.0.6-17`), even for
|
|
130
|
+
renderer-only use: the shared entry exports the builder too, so all four
|
|
131
|
+
must resolve. Styles: Builder and Renderer import their
|
|
132
|
+
`@esheet/styles` dependency automatically (explicit entry
|
|
133
|
+
`@esheet/styles/styles.css`); keep loading `@mieweb/ui/styles.css` for
|
|
134
|
+
composed UI components.
|
|
135
|
+
- **The pair:** `EsheetBuilder` (`definition`/`onChange`) emits a
|
|
136
|
+
`FormDefinition`; `EsheetRenderer` takes that object as `formDataInput`.
|
|
137
|
+
Answers come back two ways: imperatively via the ref's
|
|
138
|
+
`getValidResponse()`, which returns `{ response: FormResponse | null,
|
|
139
|
+
errors: ValidationError[] }` (`response` is `null` while invalid — store
|
|
140
|
+
`response`, not the wrapper), or via the opt-in built-in submit button —
|
|
141
|
+
pass `onSubmit` (+ `submitLabel`) and the Renderer renders it and calls
|
|
142
|
+
back with the validated `FormResponse`; don't build a duplicate submit
|
|
143
|
+
flow next to it. **Persistence is host-owned either way** — no autosave,
|
|
144
|
+
no `name`, no server calls; the host stores definition and response.
|
|
145
|
+
- **Clinical fields:** `registerMieEsheetFields()` plugs the Healthcare list
|
|
146
|
+
fields (`medicationList`, `allergyList`, …) into both Builder and
|
|
147
|
+
Renderer — call it once before rendering definitions that use them.
|
|
148
|
+
- **EncounterVisit** (same entry) is the coded clinical visit document; its
|
|
149
|
+
RichEdit mode rides the Kerebron editor — the `@kerebron/*` peers, WASM
|
|
150
|
+
assets and `kerebron.css` from the **mieweb-ui-kerebron** skill apply.
|
|
151
|
+
- Known gaps: upstream axe failures (contrast, unlabeled landmarks, role-less
|
|
152
|
+
drag handles) tracked in the mieweb/eSheet repo; no locale/translation
|
|
153
|
+
hooks — built-in strings are English — but layout **does** mirror under an
|
|
154
|
+
inherited `dir="rtl"` (panels swap, toolbar flips), with a handful of
|
|
155
|
+
physical-direction styling gaps tracked as an upstream eSheet RTL
|
|
156
|
+
enhancement; it themes via its own `--msprimary` tokens + `dark`
|
|
157
|
+
class, independent of `ThemeProvider`.
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Symptom | Cause | Fix |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `datavis_ace.Source is not a constructor` | `datavis-ace` missing/unresolved — it is a hard runtime requirement of `DataVisNitroSource` (ships as a regular dependency of `@mieweb/ui`, external in the bundle) | Reinstall; check the host's resolution (`pnpm why datavis-ace`) — never add it as a direct import |
|
|
164
|
+
| Grid renders nothing, no error | `DataVisNitroGrid` not inside a `DataVisNitroSource` (context is null) | Nest Grid/Graph inside the Source |
|
|
165
|
+
| `type="local"` grid is empty | `window[varName]` unset at mount, or not shaped `{ typeInfo, data }` | Set the global before mounting; delete it on unmount |
|
|
166
|
+
| Grouping/aggregation "doesn't stick" | Imperative `setGroup`/`setAggregate` calls on the context fight the declarative props | Use the Source's `groupBy`/`aggregates` props only |
|
|
167
|
+
| Huge dataset scrolls poorly | No virtualization in the engine — `height` + show-more/limit is the mechanism | Reduce the served dataset (http source), group/aggregate, or page upstream |
|
|
168
|
+
| "How do I turn on pagination?" | NITRO has no page controls; `Pagination` is for server-paged `Table`/card lists | Filtering/grouping/show-more replace paging in NITRO |
|
|
169
|
+
| Rows selectable but bulk action missing | `rowSelection` without `operations` | Add `operations` entries — `callback(ctx)` receives `ctx.rows` |
|
|
170
|
+
| Pinned perspectives leak across users on a kiosk | Pins persist to localStorage by default | `persistPinnedPerspectives={false}` |
|
|
171
|
+
| eSheet fields for meds/allergies render as unknown type | `registerMieEsheetFields()` not called | Call it once at startup before rendering such definitions |
|
|
172
|
+
| eSheet looks unstyled | Very old `@esheet/*` versions required manual CSS copying | Upgrade — current Builder/Renderer import `@esheet/styles` automatically |
|
|
173
|
+
| Grid needed AG Grid feature X | `@mieweb/ui/ag-grid` is deprecated | Treat the gap as a NITRO feature request (file an issue); don't start new AGGrid usage |
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mieweb-ui-kerebron
|
|
3
|
+
description: Integrating @mieweb/ui rich-text editors — the Kerebron entry (RichEditor, CodeEditor, TextAreaRich), the Kerebron-backed main-barrel Textarea, EmailEditor, and MarkdownRenderer — including the exact-0.8.12 peer set, ProseMirror version overrides, WASM grammar serving, the consumer-side @kerebron patches, Yjs collaboration and its degrade path. USE WHEN installing or configuring any rich-text editor, typing/toolbar/WASM/collab misbehaves, markdown round-trip drops marks, or an editor value contract (markdown vs HTML vs plain text) is in question.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kerebron rich text in @mieweb/ui
|
|
7
|
+
|
|
8
|
+
Sourced from `MIGRATION.md`, `src/catalog/Editors.mdx`, the RichEditor/Email
|
|
9
|
+
docs and `patches/` in the mieweb/ui repo. Selection guidance ("which
|
|
10
|
+
editor?") lives in the `mieweb-ui-catalog` skill; general install/CSS
|
|
11
|
+
foundation in `mieweb-ui-tailwind4`.
|
|
12
|
+
|
|
13
|
+
## Surfaces and their value contracts
|
|
14
|
+
|
|
15
|
+
The **stored format decides the surface** — this is the first question to
|
|
16
|
+
settle in any integration:
|
|
17
|
+
|
|
18
|
+
| Surface | Entry | Value contract |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `RichEditor` | `@mieweb/ui/kerebron` | **Markdown** in/out (`valueType: 'text/x-markdown'` default; `'text/html'` for an HTML-valued surface) |
|
|
21
|
+
| `CodeEditor` | `@mieweb/ui/kerebron` | Source code (tree-sitter highlighting) |
|
|
22
|
+
| `TextAreaRich` | `@mieweb/ui/kerebron` | **HTML**, textarea-like chrome: one Input row tall, auto-grows, toolbar hidden until asked, markdown block shortcuts, Notion-style `+` gutter menu, `.shortcut` macros |
|
|
23
|
+
| `Textarea` | main barrel | **Plain text** contract over the same engine (since 0.12): `value`/`onChange(event.target.value)` are strings, `name` posts via a hidden mirror `<textarea>`. Opt out per field with `richText={false}` or `TextAreaPlain` |
|
|
24
|
+
| `EmailEditor` + `renderEmailMjml` | main barrel | **JSON blocks** (hero, columns, buttons, images, social, footer) compiled to MJML — not HTML; each `text` block hosts a `TextAreaRich` |
|
|
25
|
+
| `MarkdownRenderer` + blocks, `useMarkdown` | main barrel | **Read-only display** of Markdown (sanitised HTML, code highlighting, `mermaid`/`csv`/`survey`/`html` fences, `streaming` for token-by-token AI output) |
|
|
26
|
+
|
|
27
|
+
**Deprecated — never for new work** (mieweb/ui#692): main-barrel
|
|
28
|
+
`RichTextEditor` and legacy `TextAreaRich` (the `document.execCommand`
|
|
29
|
+
engine). Replacements: Kerebron `TextAreaRich` for HTML (+ `variableGroups` +
|
|
30
|
+
dictation), `RichEditor` for Markdown. `RichTextEditor` emits raw unsanitised
|
|
31
|
+
`innerHTML` and its output does **not** go through `MarkdownRenderer`.
|
|
32
|
+
|
|
33
|
+
## Install — the three-legged stool
|
|
34
|
+
|
|
35
|
+
Every consumer needs all three legs since 0.12 (the main-barrel `Textarea`
|
|
36
|
+
rides the engine, so none of this is optional):
|
|
37
|
+
|
|
38
|
+
**1. Peers at exactly 0.8.12.** `@kerebron/editor`, `editor-kits`,
|
|
39
|
+
`extension-basic-editor`, `extension-menu`, `wasm` are required peers —
|
|
40
|
+
install with `--save-exact`: newer Kerebron (0.8.13+) pins different
|
|
41
|
+
ProseMirror versions, so a `^0.8.12` range drifts and splits
|
|
42
|
+
`prosemirror-model` (mieweb/ui#709). Collab peers stay optional:
|
|
43
|
+
`@kerebron/extension-yjs`, `yjs`, `y-protocols`.
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
npm install --save-exact @kerebron/editor@0.8.12 @kerebron/editor-kits@0.8.12 \
|
|
47
|
+
@kerebron/extension-basic-editor@0.8.12 @kerebron/extension-menu@0.8.12 \
|
|
48
|
+
@kerebron/wasm@0.8.12
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**2. ProseMirror overrides in the host.** Even with matching pins,
|
|
52
|
+
ProseMirror's own `^`-ranged internals float to the newest release on any
|
|
53
|
+
fresh install — the library's own overrides do **not** propagate. Add to the
|
|
54
|
+
host (pnpm 10: `overrides:` in `pnpm-workspace.yaml`; npm: `"overrides"`;
|
|
55
|
+
Yarn: `"resolutions"` — full snippets in
|
|
56
|
+
[MIGRATION.md](https://github.com/mieweb/ui/blob/main/MIGRATION.md#esheet-and-encountervisit)):
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
overrides:
|
|
60
|
+
prosemirror-view: "1.42.3"
|
|
61
|
+
prosemirror-model: "1.25.9"
|
|
62
|
+
prosemirror-state: "1.4.3"
|
|
63
|
+
prosemirror-transform: "1.10.4"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`prosemirror-view` is 1.42.3 (not Kerebron's pinned 1.40.0) for the protected
|
|
67
|
+
MDY link bridge. Verify after install: `pnpm why prosemirror-model` /
|
|
68
|
+
`pnpm why prosemirror-view` (or `npm ls`/`yarn why`) must each show a
|
|
69
|
+
**single** version. `pnpm dedupe` cannot fix a split — only overrides can.
|
|
70
|
+
|
|
71
|
+
**3. CSS + WASM assets.** Import `@mieweb/ui/kerebron.css` beside
|
|
72
|
+
`styles.css` (`markdown.css` too if rendering Markdown). The editor loads
|
|
73
|
+
tree-sitter WASM grammars at runtime from `/kerebron-wasm`: serve
|
|
74
|
+
`@kerebron/wasm`'s `assets/` directory at that path — e.g. copy or symlink it
|
|
75
|
+
into Vite's `public/kerebron-wasm`, or add a Storybook `staticDirs` mapping —
|
|
76
|
+
or pass a custom `assetLoad` (`createAssetLoad('/my-path')`) when it lives
|
|
77
|
+
elsewhere.
|
|
78
|
+
|
|
79
|
+
## The consumer-side patches
|
|
80
|
+
|
|
81
|
+
The repo's [`patches/@kerebron__*`](https://github.com/mieweb/ui/tree/main/patches)
|
|
82
|
+
fixes target `@kerebron/*@0.8.12` exactly and must be applied **in the host
|
|
83
|
+
app** until fixed upstream — the library's own `patchedDependencies` do not
|
|
84
|
+
propagate. They are pnpm-format (list under `patchedDependencies` as-is);
|
|
85
|
+
npm/yarn hosts convert to their patch tool's format (`patch-package` expects
|
|
86
|
+
its own filenames and `node_modules/…` paths). What breaks without each:
|
|
87
|
+
|
|
88
|
+
| Patch | Without it |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `extension-menu` | Toolbar **Heading/List dropdowns do not fire** in browsers (also: full toolbar re-render per transaction) |
|
|
91
|
+
| `extension-markdown` | **highlight/superscript/subscript marks silently dropped** when saving back to Markdown (patched: round-trip as `<mark>`/`<sup>`/`<sub>` inline HTML, mieweb/ui#536) |
|
|
92
|
+
| `extension-codecrock` | Code-block language `<select>` has no accessible name (axe `select-name` failure) |
|
|
93
|
+
|
|
94
|
+
## RichEditor integration facts
|
|
95
|
+
|
|
96
|
+
- **Read on submit, not from mirrored state:** `onChange` can lag the last
|
|
97
|
+
keystroke — use the ref's `getContent()` (async, awaits the initial load).
|
|
98
|
+
- **Read-once props:** `collab`, `mediaUpload`, `modifyMenu`,
|
|
99
|
+
`omitExtensions` are read when the editor mounts — **remount via `key`** to
|
|
100
|
+
change any of them.
|
|
101
|
+
- **`mediaUpload.uploadHandler` is required whenever documents persist.**
|
|
102
|
+
Without it a pasted image embeds as base64 (`~4 MB screenshot → ~5.8 MB of
|
|
103
|
+
markdown`) and video as a dead-on-reload blob URL.
|
|
104
|
+
- **`omitExtensions` removes whole features schema-first** — toolbar, input
|
|
105
|
+
rules and paste handling are all schema-driven, so
|
|
106
|
+
`['task_list', 'task_item']` removes checklists everywhere in one move.
|
|
107
|
+
- **`modifyMenu`** reshapes the stock toolbar (append macros/dictation
|
|
108
|
+
controls, drop stock groups) before first render.
|
|
109
|
+
- **Controlled semantics are opt-in:** default tolerates read-once hosts; set
|
|
110
|
+
`strictValue` for native controlled-input behavior (un-echoed edits
|
|
111
|
+
revert). Changing `value` reloads the editor unless `collab` is set.
|
|
112
|
+
- **Labelling:** the host is a `div`, not a labelable control — `<label
|
|
113
|
+
htmlFor>` won't associate; use `aria-label`/`aria-labelledby` (the `id`
|
|
114
|
+
prop is the anchor).
|
|
115
|
+
|
|
116
|
+
## Collaboration (Yjs)
|
|
117
|
+
|
|
118
|
+
`collab: { room, wsUrl?, params? }` joins one shared document per `room` over
|
|
119
|
+
the `/yjs` websocket relay (default `<ws|wss>://<location.host>/yjs`;
|
|
120
|
+
`params` for auth tokens). Requires the optional peers
|
|
121
|
+
`@kerebron/extension-yjs` + `yjs` + `y-protocols`. **Best-effort degrade:**
|
|
122
|
+
if the Yjs **kit fails to load** (e.g. the optional peers are absent), the
|
|
123
|
+
editor still mounts locally and `collab.onUnavailable` fires once, before
|
|
124
|
+
the editor is created — pass it when users must know they're editing
|
|
125
|
+
unshared. `onUnavailable` is **not for connection trouble**: a reachable
|
|
126
|
+
room that is currently disconnected still has the kit loaded, and the
|
|
127
|
+
provider retries on its own. The kit lazy-loads via dynamic `import` so plain-mode consumers
|
|
128
|
+
never pull Yjs code (versions before the mieweb/ui#706 fix had static named
|
|
129
|
+
imports in the lazy chunk — rolldown-Vite builds failed with
|
|
130
|
+
`MISSING_EXPORT`; fix: upgrade, or externalize
|
|
131
|
+
`/^@kerebron\/extension-yjs/`, `/^y-websocket/`). Pair with the
|
|
132
|
+
`CollabStatus` component (Feedback family) for presence/sync UI. Collab mode
|
|
133
|
+
is uncontrolled — remount via `key` to switch rooms.
|
|
134
|
+
|
|
135
|
+
## Textarea-on-Kerebron behaviour changes (0.12)
|
|
136
|
+
|
|
137
|
+
- `maxLength` no longer enforced while typing (counter still renders/turns
|
|
138
|
+
red) — enforce in `onChange` or use `TextAreaPlain`.
|
|
139
|
+
- `labelVariant="floating"`, `resize`, `autoResize={false}` ignored (one-time
|
|
140
|
+
dev warning).
|
|
141
|
+
- **DOM shape:** no visible `<textarea>` — a ProseMirror `contenteditable`
|
|
142
|
+
(`role="textbox"`, class `kb-editor`) plus hidden mirror
|
|
143
|
+
`[data-slot="textarea-mirror"]` carrying `name`/`value`. `textarea { … }`
|
|
144
|
+
CSS and element refs no longer match; target the `data-slot` hooks
|
|
145
|
+
(`[data-slot^="textarea-"]` prefix selector, or a concrete slot like
|
|
146
|
+
`textarea-wrapper`). `getByRole('textbox')` tests keep working.
|
|
147
|
+
- Controlled transforms of `event.target.value` reset formatting (the
|
|
148
|
+
reported value is flattened plain text).
|
|
149
|
+
|
|
150
|
+
## EmailEditor constraints
|
|
151
|
+
|
|
152
|
+
Email `text` blocks are `TextAreaRich` surfaces with
|
|
153
|
+
`omitExtensions={['task_list', 'task_item']}` — checkbox inputs are
|
|
154
|
+
sanitizer-forbidden and inert in mail clients (mieweb/ui#695), so checklists
|
|
155
|
+
are removed schema-first rather than filtered after the fact. Compile
|
|
156
|
+
`renderEmailMjml` output with `mjml`/`mjml-browser` **host-side** (not a
|
|
157
|
+
peer). Sending, recipients and templates are the host's concern.
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Symptom | Cause | Fix |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| Typing throws `RangeError: Can not convert … to a Fragment (looks like multiple versions of prosemirror-model)` | Split ProseMirror resolution: Kerebron range drifted to 0.8.13+, or transitive `^`-ranges floated on a fresh install (mieweb/ui#709) | Pin `@kerebron/*` 0.8.12 exact + the four overrides; verify single version via `pnpm why prosemirror-model` |
|
|
164
|
+
| `vite build` fails `MISSING_EXPORT` from `@kerebron/extension-yjs` in a `collabKit-*` chunk | Optional collab peers absent + @mieweb/ui older than the #706 fix (static named imports in the lazy chunk) | Upgrade @mieweb/ui; or externalize `/^@kerebron\/extension-yjs/`, `/^y-websocket/` |
|
|
165
|
+
| Code blocks render without highlighting; 404s for `*.wasm` | `@kerebron/wasm/assets` not served at `/kerebron-wasm` | Serve/symlink the assets dir, or pass `assetLoad` with the actual path |
|
|
166
|
+
| Toolbar Heading/List dropdowns don't open | Host missing the `extension-menu` patch | Apply `patches/@kerebron__extension-menu@0.8.12.patch` in the host |
|
|
167
|
+
| Highlight/superscript/subscript lost after save | Host missing the `extension-markdown` patch (marks absent from the serializer table) | Apply the `extension-markdown` patch (mieweb/ui#536) |
|
|
168
|
+
| axe: `select-name` on code blocks | Host missing the `extension-codecrock` patch | Apply the `extension-codecrock` patch |
|
|
169
|
+
| Pasted screenshot balloons the document / image dies on reload | No `mediaUpload.uploadHandler` — base64/blob embedding | Provide `uploadHandler` returning a hosted URL |
|
|
170
|
+
| Edits revert while typing in a controlled host | Host `onChange` doesn't echo into `value` and `strictValue` is set — or the host echoes flattened text back into a rich surface | Echo the value correctly, or drop `strictValue` for read-once + `getContent()` on submit |
|
|
171
|
+
| `collab` set but edits don't sync, no error | Yjs kit failed to load (missing optional peers) → silent local degrade; or the relay is disconnected (kit loaded, provider retrying) | Install the collab peers and pass `collab.onUnavailable` to surface load failures; for connectivity, check the `/yjs` relay — the provider retries on its own |
|
|
172
|
+
| `<label htmlFor>` doesn't focus/name the editor | Editor host is a `div`, not a labelable control | `aria-label` / `aria-labelledby` via the `id` anchor |
|
|
173
|
+
| Checklist items vanish in EmailEditor | By design — `task_list`/`task_item` are email-unsafe (mieweb/ui#695) | Use a different block structure; not a bug |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mieweb/ui",
|
|
3
|
-
"version": "0.11.0-dev.
|
|
3
|
+
"version": "0.11.0-dev.56",
|
|
4
4
|
"description": "A themeable, accessible React component library built with Tailwind CSS",
|
|
5
5
|
"author": "Medical Informatics Engineering, Inc.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|