@ethisyscore/plugin-ui 1.110.0 → 1.112.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/dist/components/ui/index.cjs +11 -0
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.cts +24 -1
- package/dist/components/ui/index.d.ts +24 -1
- package/dist/components/ui/index.js +10 -1
- package/dist/components/ui/index.js.map +1 -1
- package/dist/markdown/index.d.ts +236 -0
- package/dist/markdown/index.js +524 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/platform-react/index.cjs +43 -7
- package/dist/platform-react/index.cjs.map +1 -1
- package/dist/platform-react/index.d.cts +34 -6
- package/dist/platform-react/index.d.ts +34 -6
- package/dist/platform-react/index.js +44 -9
- package/dist/platform-react/index.js.map +1 -1
- package/package.json +13 -2
- package/styles/markdown.css +284 -0
- package/styles/plugin-base.css +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethisyscore/plugin-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.112.0",
|
|
4
4
|
"description": "Plugin-UI umbrella SDK: client bridge + a11y/l10n primitives + brokered-MCP client (WI 4858).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
"import": "./dist/token/index.js",
|
|
28
28
|
"require": "./dist/token/index.cjs"
|
|
29
29
|
},
|
|
30
|
+
"./markdown": {
|
|
31
|
+
"types": "./dist/markdown/index.d.ts",
|
|
32
|
+
"import": "./dist/markdown/index.js"
|
|
33
|
+
},
|
|
30
34
|
"./platform-react": {
|
|
31
35
|
"types": "./dist/platform-react/index.d.ts",
|
|
32
36
|
"import": "./dist/platform-react/index.js",
|
|
@@ -38,6 +42,7 @@
|
|
|
38
42
|
"require": "./dist/tailwind-preset/index.cjs"
|
|
39
43
|
},
|
|
40
44
|
"./plugin-base.css": "./styles/plugin-base.css",
|
|
45
|
+
"./markdown.css": "./styles/markdown.css",
|
|
41
46
|
"./icons": {
|
|
42
47
|
"types": "./dist/icons/index.d.ts",
|
|
43
48
|
"import": "./dist/icons/index.js",
|
|
@@ -99,7 +104,13 @@
|
|
|
99
104
|
"dependencies": {
|
|
100
105
|
"@ethisyscore/components-react": "^1.69.1",
|
|
101
106
|
"@ethisyscore/core-utils": "^1.69.1",
|
|
102
|
-
"@ethisyscore/extension-runtime": "^1.69.1"
|
|
107
|
+
"@ethisyscore/extension-runtime": "^1.69.1",
|
|
108
|
+
"hast-util-sanitize": "^5.0.2",
|
|
109
|
+
"react-markdown": "^10.1.0",
|
|
110
|
+
"rehype-sanitize": "^6.0.0",
|
|
111
|
+
"remark-breaks": "^4.0.0",
|
|
112
|
+
"remark-gfm": "^4.0.1",
|
|
113
|
+
"unified": "^11.0.5"
|
|
103
114
|
},
|
|
104
115
|
"peerDependencies": {
|
|
105
116
|
"@mui/material": ">=5",
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @ethisyscore/plugin-ui — typography for markdown rendered by `MarkdownView`.
|
|
3
|
+
*
|
|
4
|
+
* USAGE — THERE ARE TWO SANCTIONED IMPORT FORMS, ONE PER CONTEXT.
|
|
5
|
+
*
|
|
6
|
+
* In the HOST app, which owns the document, import it bare:
|
|
7
|
+
*
|
|
8
|
+
* @import "@ethisyscore/plugin-ui/markdown.css";
|
|
9
|
+
*
|
|
10
|
+
* In a PLUGIN, import it into the auto-scoped layer, next to the base stylesheet:
|
|
11
|
+
*
|
|
12
|
+
* @import "@ethisyscore/plugin-ui/plugin-base.css";
|
|
13
|
+
* @import "@ethisyscore/plugin-ui/markdown.css" layer(utilities);
|
|
14
|
+
*
|
|
15
|
+
* WHY THE PLUGIN FORM DIFFERS, AND WHY A BARE IMPORT THERE FAILS THE BUILD. Every
|
|
16
|
+
* selector in this file targets a caller-applied class (`.ethisys-md`), not a plugin
|
|
17
|
+
* root — it has to, because the host app uses the same file and has no
|
|
18
|
+
* `.ehx-plugin-root`. A plugin's compiled CSS is injected into the HOST <head>, so
|
|
19
|
+
* the SDK's `ethisys-scope-plugin-css` guard rejects any selector that is not scoped
|
|
20
|
+
* to a plugin root, and a bare import here fails the build with 31 leaking selectors.
|
|
21
|
+
* `layer(utilities)` is the SDK's documented adoption path for a stylesheet a plugin
|
|
22
|
+
* wants to keep (see `vendor-css.mjs` in any plugin UI): the scoping pass prefixes
|
|
23
|
+
* every selector in that layer with
|
|
24
|
+
* `:where(.ehx-plugin-root, [data-ehx-plugin-portal])` at ZERO added specificity, so
|
|
25
|
+
* the rules ship scoped inside PLUGIN_CSS and the cascade inside the plugin surface
|
|
26
|
+
* is unchanged. Place the import BEFORE the Tailwind utilities import so a utility
|
|
27
|
+
* that ties on specificity still wins on source order.
|
|
28
|
+
*
|
|
29
|
+
* A vite-plugin test (`markdown-css-scope.test.ts`) asserts this very file passes the
|
|
30
|
+
* guard when adopted that way, so the two forms above cannot silently stop working.
|
|
31
|
+
*
|
|
32
|
+
* EITHER WAY, put the class on YOUR OWN wrapper — `MarkdownView` emits no element:
|
|
33
|
+
*
|
|
34
|
+
* <Box className="ethisys-md"> <MarkdownView>{body}</MarkdownView></Box>
|
|
35
|
+
* <Box className="ethisys-md ethisys-md--dense"> …chat bubble… </Box>
|
|
36
|
+
*
|
|
37
|
+
* WHY THIS SHIPS FROM THE SDK rather than from the host's global stylesheet, where
|
|
38
|
+
* its ancestor (`style/plugins/ds-markdown.css`) lived: a plugin whose bubble rhythm
|
|
39
|
+
* comes from host CSS cannot be deployed before the host that defines it, which makes
|
|
40
|
+
* every markdown change a cross-repo release dance. Shipping the styles alongside the
|
|
41
|
+
* component makes each plugin self-contained and the two deploys order-independent.
|
|
42
|
+
*
|
|
43
|
+
* Plain CSS, no `@apply` — matching `plugin-base.css`, so the file is valid wherever
|
|
44
|
+
* it is imported and does not depend on the consumer's Tailwind config being loaded.
|
|
45
|
+
* The literal sizes below are gogo's type scale (base 0.875rem/14px, NOT stock
|
|
46
|
+
* Tailwind's 1rem), carried over from the utilities the previous stylesheet used.
|
|
47
|
+
* Colour comes from the host design tokens by inheritance, as `plugin-base.css` does.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/* --------------------------------------------------------------- */
|
|
51
|
+
/* Document rhythm */
|
|
52
|
+
/* --------------------------------------------------------------- */
|
|
53
|
+
|
|
54
|
+
.ethisys-md {
|
|
55
|
+
font-family: var(--font-body), ui-sans-serif;
|
|
56
|
+
font-weight: 400;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.ethisys-md h1,
|
|
60
|
+
.ethisys-md h2,
|
|
61
|
+
.ethisys-md h3,
|
|
62
|
+
.ethisys-md h4,
|
|
63
|
+
.ethisys-md h5,
|
|
64
|
+
.ethisys-md h6 {
|
|
65
|
+
font-family: var(--font-heading), ui-sans-serif;
|
|
66
|
+
font-weight: 700;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.ethisys-md h1 {
|
|
70
|
+
margin-top: 1.625rem;
|
|
71
|
+
margin-bottom: 0.875rem;
|
|
72
|
+
font-size: 1.625rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.ethisys-md h2 {
|
|
76
|
+
margin-top: 1.5rem;
|
|
77
|
+
margin-bottom: 0.75rem;
|
|
78
|
+
font-size: 1.5rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.ethisys-md h3 {
|
|
82
|
+
margin-top: 1.375rem;
|
|
83
|
+
margin-bottom: 0.625rem;
|
|
84
|
+
font-size: 1.375rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ethisys-md h4 {
|
|
88
|
+
margin-top: 1.25rem;
|
|
89
|
+
margin-bottom: 0.5rem;
|
|
90
|
+
font-size: 1.25rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.ethisys-md h5 {
|
|
94
|
+
margin-top: 1rem;
|
|
95
|
+
margin-bottom: 0.375rem;
|
|
96
|
+
font-size: 1.125rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.ethisys-md h6 {
|
|
100
|
+
margin-top: 0.875rem;
|
|
101
|
+
margin-bottom: 0.25rem;
|
|
102
|
+
font-size: 1rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.ethisys-md p {
|
|
106
|
+
margin-bottom: 0.5rem;
|
|
107
|
+
font-size: 0.875rem;
|
|
108
|
+
font-weight: 400;
|
|
109
|
+
line-height: 1.25rem;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ethisys-md ul,
|
|
113
|
+
.ethisys-md ol {
|
|
114
|
+
margin-bottom: 0.5rem;
|
|
115
|
+
list-style-position: inside;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ethisys-md ul {
|
|
119
|
+
list-style-type: disc;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.ethisys-md ol {
|
|
123
|
+
list-style-type: decimal;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.ethisys-md li {
|
|
127
|
+
line-height: 1.5rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.ethisys-md pre {
|
|
131
|
+
margin-top: 0.25rem;
|
|
132
|
+
margin-bottom: 0.25rem;
|
|
133
|
+
overflow-x: auto;
|
|
134
|
+
border-radius: var(--border-radius-sm);
|
|
135
|
+
padding: 0.5rem;
|
|
136
|
+
background-color: hsl(var(--grey-50));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.ethisys-md code {
|
|
140
|
+
border-radius: var(--border-radius-sm);
|
|
141
|
+
padding-inline: 0.25rem;
|
|
142
|
+
font-family: ui-monospace, monospace;
|
|
143
|
+
font-size: 0.8125rem;
|
|
144
|
+
background-color: hsl(var(--grey-50));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.ethisys-md pre code {
|
|
148
|
+
padding: 0;
|
|
149
|
+
background-color: transparent;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* The placeholder left where an untrusted remote image was blocked. */
|
|
153
|
+
.ethisys-md-blocked-image {
|
|
154
|
+
color: hsl(var(--text-secondary));
|
|
155
|
+
font-style: italic;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* --------------------------------------------------------------- */
|
|
159
|
+
/* Chat-bubble rhythm */
|
|
160
|
+
/* --------------------------------------------------------------- */
|
|
161
|
+
/*
|
|
162
|
+
* Applied ALONGSIDE `.ethisys-md` on a message bubble's content wrapper. It tightens
|
|
163
|
+
* the paragraph and list margins for a dense layout, and carries VERBATIM the two
|
|
164
|
+
* width guards the previous stylesheet documented at length. Both are load-bearing on
|
|
165
|
+
* narrow surfaces (the chat dock popup is ~360px wide, and a bubble inside it is
|
|
166
|
+
* capped at 85% of that):
|
|
167
|
+
*
|
|
168
|
+
* 1. `min-width: 0` on the wrapper. Without it the wrapper's intrinsic min-width is
|
|
169
|
+
* `auto` — equal to its widest atomic child. When the message is a short word with
|
|
170
|
+
* no break opportunities (e.g. "asde") the wrapper refuses to shrink below the
|
|
171
|
+
* paragraph's measured text width. In a flex parent that nominally allows shrink
|
|
172
|
+
* the wrapper still wins and pushes the rightmost glyph past the bubble's rounded
|
|
173
|
+
* corner — the "asde clips the right edge" bug, while "asd" sits inside the safe
|
|
174
|
+
* zone by a pixel or two.
|
|
175
|
+
*
|
|
176
|
+
* 2. `overflow-wrap: anywhere` on paragraphs, code and links. Continuous strings
|
|
177
|
+
* (URLs, code identifiers, joined-no-space text) break inside themselves when the
|
|
178
|
+
* bubble cannot widen further, rather than punching through the right edge. The
|
|
179
|
+
* gentler `anywhere` is preferred over `word-break: break-word`, which would split
|
|
180
|
+
* short words even when the bubble has room.
|
|
181
|
+
*
|
|
182
|
+
* The `max-width: 100%` lines keep the bubble the owner of the width.
|
|
183
|
+
*
|
|
184
|
+
* DROPPED from the previous stylesheet, no longer needed: every `--dsr-*` / `--ds-*`
|
|
185
|
+
* variable, the `.ds-markdown-answer` wrapper overrides, and the
|
|
186
|
+
* `background-color: transparent` reset — all of which existed only to undo
|
|
187
|
+
* ds-markdown's opaque white root. `MarkdownView` emits no wrapper and no background.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
.ethisys-md--dense {
|
|
191
|
+
min-width: 0;
|
|
192
|
+
max-width: 100%;
|
|
193
|
+
font-size: 0.875rem;
|
|
194
|
+
line-height: 1.25rem;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.ethisys-md--dense p {
|
|
198
|
+
margin-bottom: 0;
|
|
199
|
+
max-width: 100%;
|
|
200
|
+
font-size: 0.75rem;
|
|
201
|
+
line-height: 1.25rem;
|
|
202
|
+
overflow-wrap: anywhere;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.ethisys-md--dense p + p {
|
|
206
|
+
margin-top: 0.25rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.ethisys-md--dense ul,
|
|
210
|
+
.ethisys-md--dense ol {
|
|
211
|
+
margin-top: 0.25rem;
|
|
212
|
+
margin-bottom: 0;
|
|
213
|
+
margin-left: 0.5rem;
|
|
214
|
+
padding-left: 1.25rem;
|
|
215
|
+
font-size: 0.75rem;
|
|
216
|
+
line-height: 1.25rem;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.ethisys-md--dense code {
|
|
220
|
+
overflow-wrap: anywhere;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.ethisys-md--dense pre {
|
|
224
|
+
margin-top: 0.25rem;
|
|
225
|
+
margin-bottom: 0.25rem;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.ethisys-md--dense a {
|
|
229
|
+
color: hsl(var(--primary));
|
|
230
|
+
text-decoration-line: underline;
|
|
231
|
+
overflow-wrap: anywhere;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/*
|
|
235
|
+
* Blockquotes and tables.
|
|
236
|
+
*
|
|
237
|
+
* These were missing from the first cut and browser smoke-testing caught it: a `>`
|
|
238
|
+
* quote rendered identically to a paragraph (no rule, no indent, body-coloured text,
|
|
239
|
+
* no `::before`), and GFM table cells had zero borders and zero padding, so a table
|
|
240
|
+
* read as unspaced columns. Markdown that produces no visible change is markdown the
|
|
241
|
+
* author has no reason to trust, so both are styled here rather than per-plugin.
|
|
242
|
+
*/
|
|
243
|
+
|
|
244
|
+
.ethisys-md blockquote {
|
|
245
|
+
margin: 0.5rem 0;
|
|
246
|
+
border-left: 3px solid hsl(var(--grey-100));
|
|
247
|
+
padding-left: 0.75rem;
|
|
248
|
+
/* --text-secondary, not a --grey-* step: the grey scale is surface tones
|
|
249
|
+
(--grey-400 is 79% lightness in light mode) and would be unreadable as text. */
|
|
250
|
+
color: hsl(var(--text-secondary));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
* `display: block` rather than a wrapper element: the table can then scroll on its own
|
|
255
|
+
* when it is wider than the surface, which keeps this a stylesheet-only fix and leaves
|
|
256
|
+
* MarkdownView's component map untouched. The trade-off is that the table stops
|
|
257
|
+
* stretching to fill its container — acceptable, and better than a chat or ticket
|
|
258
|
+
* layout being forced wide by one table.
|
|
259
|
+
*/
|
|
260
|
+
.ethisys-md table {
|
|
261
|
+
display: block;
|
|
262
|
+
overflow-x: auto;
|
|
263
|
+
max-width: 100%;
|
|
264
|
+
margin: 0.5rem 0;
|
|
265
|
+
border-collapse: collapse;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.ethisys-md th,
|
|
269
|
+
.ethisys-md td {
|
|
270
|
+
border: 1px solid hsl(var(--grey-100));
|
|
271
|
+
padding: 0.25rem 0.5rem;
|
|
272
|
+
text-align: left;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.ethisys-md th {
|
|
276
|
+
font-weight: 600;
|
|
277
|
+
background-color: hsl(var(--grey-50));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.ethisys-md hr {
|
|
281
|
+
margin: 1rem 0;
|
|
282
|
+
border: 0;
|
|
283
|
+
border-top: 1px solid hsl(var(--grey-100));
|
|
284
|
+
}
|
package/styles/plugin-base.css
CHANGED
|
@@ -61,6 +61,27 @@
|
|
|
61
61
|
border-radius: var(--border-radius-3xl);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/* Form-field spacing standard — the plugin-side counterpart of the host's
|
|
65
|
+
`.form-fields` class. The FormStack (<form>) and FieldStack (<div>) primitives
|
|
66
|
+
from `@ethisyscore/plugin-ui/components/ui` wear this class to lay their fields
|
|
67
|
+
out in a 24px flex column, so a form gets the standard without having to be a
|
|
68
|
+
MUI Stack in a particular DOM position. Flex column (not block) so adjacent
|
|
69
|
+
field margins can't collapse; the child rule zeroes any control's own bottom
|
|
70
|
+
margin for parity with the host. Root-scoped so it never touches the host's
|
|
71
|
+
own `.form-fields`, and in `@layer components` so a plugin's Tailwind gap/mb
|
|
72
|
+
utilities still win. */
|
|
73
|
+
@layer components {
|
|
74
|
+
.ehx-plugin-root .form-fields {
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
gap: 1.5rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.ehx-plugin-root .form-fields > .MuiFormControl-root {
|
|
81
|
+
margin-bottom: 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
/* Portal container rendered by `PluginPortalScope` at the end of every plugin
|
|
65
86
|
surface. MUI's portalling components (Modal/Popper and everything built on
|
|
66
87
|
them) default to it, which keeps dialogs, menus, poppers and tooltips inside
|