@maple-kit/ui 0.4.0 → 0.6.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/composer/badge.d.ts +11 -1
- package/dist/composer/badge.js +31 -10
- package/dist/composer/css.js +163 -8
- package/dist/composer/index.d.ts +3 -2
- package/dist/composer/index.js +3 -2
- package/dist/composer/score.d.ts +16 -0
- package/dist/composer/score.js +87 -0
- package/dist/maple.js +2 -1
- package/dist/tokens.js +1 -0
- package/package.json +3 -3
package/dist/composer/badge.d.ts
CHANGED
|
@@ -7,7 +7,17 @@ export interface MapleContextProps extends AsChildProps {
|
|
|
7
7
|
readonly className?: string;
|
|
8
8
|
/** A captured page, or a stored comment's context. Both render identically. */
|
|
9
9
|
readonly context?: CommentContext | PageContext;
|
|
10
|
+
/**
|
|
11
|
+
* Whether it can be folded away. Off keeps it open and draws no control,
|
|
12
|
+
* which is what a stored comment wants: nothing is being typed beside it.
|
|
13
|
+
*/
|
|
14
|
+
readonly collapsible?: boolean;
|
|
10
15
|
}
|
|
11
|
-
/**
|
|
16
|
+
/** What the disclosure is called, in both states. */
|
|
17
|
+
export declare const CONTEXT_LABELS: {
|
|
18
|
+
closed: string;
|
|
19
|
+
open: string;
|
|
20
|
+
};
|
|
21
|
+
/** Labels muted, values aligned, two columns — folded to its first row. */
|
|
12
22
|
export declare const MapleContextBadge: import("react").ForwardRefExoticComponent<MapleContextProps & import("react").RefAttributes<HTMLElement>>;
|
|
13
23
|
//#endregion
|
package/dist/composer/badge.js
CHANGED
|
@@ -1,25 +1,46 @@
|
|
|
1
1
|
import { Slot } from "../slot.js";
|
|
2
2
|
import { Fragment, createElement, forwardRef } from "react";
|
|
3
3
|
import { contextRows } from "@maple-kit/core/overlay";
|
|
4
|
-
import { useMaple } from "@maple-kit/react";
|
|
4
|
+
import { useMaple, useMapleClient } from "@maple-kit/react";
|
|
5
5
|
//#region src/composer/badge.ts
|
|
6
|
+
const CONTEXT_LABELS = {
|
|
7
|
+
closed: "Show what was captured",
|
|
8
|
+
open: "Hide what was captured"
|
|
9
|
+
};
|
|
6
10
|
const MapleContextBadge = forwardRef(function MapleContextBadge(props, ref) {
|
|
7
11
|
const { composer, detail } = useMaple();
|
|
12
|
+
const client = useMapleClient();
|
|
8
13
|
const context = props.context ?? composer.target?.context;
|
|
9
|
-
const Element = props.asChild ? Slot : "
|
|
14
|
+
const Element = props.asChild ? Slot : "section";
|
|
10
15
|
if (!context) return null;
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
props.className
|
|
15
|
-
].filter(Boolean).join(" ");
|
|
16
|
+
const rows = contextRows(context, detail);
|
|
17
|
+
const collapsible = props.collapsible !== false && composer.viewing === void 0;
|
|
18
|
+
const open = !collapsible || composer.contextOpen;
|
|
16
19
|
return createElement(Element, {
|
|
17
20
|
ref,
|
|
18
|
-
className
|
|
19
|
-
|
|
21
|
+
className: [
|
|
22
|
+
"mk-composer-row",
|
|
23
|
+
"mk-ctx-card",
|
|
24
|
+
props.className
|
|
25
|
+
].filter(Boolean).join(" "),
|
|
26
|
+
"data-mk-open": String(open)
|
|
27
|
+
}, collapsible ? head(rows, open, () => client.setContextOpen(!open)) : null, createElement("dl", { className: "mk-ctx" }, ...rows.map(row)));
|
|
20
28
|
});
|
|
29
|
+
function head(rows, open, toggle) {
|
|
30
|
+
const first = rows[0];
|
|
31
|
+
return createElement("button", {
|
|
32
|
+
type: "button",
|
|
33
|
+
className: "mk-ctx-head mk-press",
|
|
34
|
+
"aria-expanded": open,
|
|
35
|
+
"aria-label": open ? CONTEXT_LABELS.open : CONTEXT_LABELS.closed,
|
|
36
|
+
onClick: toggle
|
|
37
|
+
}, createElement("span", { className: "mk-ctx-sum" }, first === void 0 ? "Page" : first.value), createElement("span", {
|
|
38
|
+
className: "mk-ctx-caret",
|
|
39
|
+
"aria-hidden": "true"
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
21
42
|
function row(one) {
|
|
22
43
|
return createElement(Fragment, { key: one.label }, createElement("dt", null, one.label), createElement("dd", one.mono === true ? { className: "mk-mono" } : null, one.value, one.note === void 0 ? null : createElement("em", null, ` · ${one.note}`)));
|
|
23
44
|
}
|
|
24
45
|
//#endregion
|
|
25
|
-
export { MapleContextBadge };
|
|
46
|
+
export { CONTEXT_LABELS, MapleContextBadge };
|
package/dist/composer/css.js
CHANGED
|
@@ -184,22 +184,107 @@ function emojiCss() {
|
|
|
184
184
|
}
|
|
185
185
|
`.trim();
|
|
186
186
|
}
|
|
187
|
-
function
|
|
187
|
+
function scoreCard() {
|
|
188
188
|
return `
|
|
189
|
-
/*
|
|
190
|
-
|
|
191
|
-
.mk-
|
|
189
|
+
/* The judgement, in the slot the context card folded out of. Rows are laid out
|
|
190
|
+
first and filled second, so nothing below moves as they land. */
|
|
191
|
+
.mk-score {
|
|
192
192
|
display: grid;
|
|
193
|
-
grid-template-columns: auto
|
|
194
|
-
|
|
193
|
+
grid-template-columns: auto 68px minmax(0, 1fr);
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 6px 9px;
|
|
195
196
|
margin: 2px 16px 4px;
|
|
196
|
-
padding: 11px
|
|
197
|
+
padding: 10px 11px;
|
|
197
198
|
border: 1px solid var(--mk-line);
|
|
198
199
|
border-radius: var(--mk-r-sm);
|
|
199
200
|
background: var(--mk-sunk);
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
|
|
203
|
+
/* The same line box empty as full: the rung arrives after the bar, and a row
|
|
204
|
+
that grows when its words land moves the field somebody is typing in. */
|
|
205
|
+
.mk-score-rung {
|
|
206
|
+
min-width: 0;
|
|
207
|
+
overflow: hidden;
|
|
208
|
+
color: var(--mk-fg);
|
|
209
|
+
font-size: 11px;
|
|
210
|
+
line-height: 15px;
|
|
211
|
+
text-overflow: ellipsis;
|
|
212
|
+
white-space: nowrap;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* One slot per rung, each filled by the probability it took. Equal widths keep
|
|
216
|
+
*which* rung readable and the fill carries how sure it was, which is why the
|
|
217
|
+
bar needs no key beside it: three pale slots are visibly a shrug. */
|
|
218
|
+
.mk-score-bar {
|
|
219
|
+
display: flex;
|
|
220
|
+
gap: 2px;
|
|
221
|
+
height: 5px;
|
|
222
|
+
margin: 5px 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.mk-score-bar i {
|
|
226
|
+
flex: 1;
|
|
227
|
+
border-radius: 999px;
|
|
228
|
+
background: color-mix(
|
|
229
|
+
in oklab,
|
|
230
|
+
var(--mk-accent) calc(var(--mk-p, 0) * 100%),
|
|
231
|
+
var(--mk-line-firm)
|
|
232
|
+
);
|
|
233
|
+
transition: background-color var(--mk-dur-swap) var(--mk-ease-swap);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Judging is the rows present and empty: a spinner per pillar is five things
|
|
237
|
+
moving beside a field somebody is typing in. */
|
|
238
|
+
.mk-score[data-mk-status="judging"] .mk-score-bar i {
|
|
239
|
+
background: var(--mk-line);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
`.trim();
|
|
243
|
+
}
|
|
244
|
+
function kindChip() {
|
|
245
|
+
return `
|
|
246
|
+
/* The select covers the pill, so the whole chip is the hit area. */
|
|
247
|
+
.mk-kind {
|
|
248
|
+
position: relative;
|
|
249
|
+
grid-column: 1 / -1;
|
|
250
|
+
justify-self: start;
|
|
251
|
+
margin-bottom: 3px;
|
|
252
|
+
border-radius: var(--mk-r-xs);
|
|
253
|
+
background: var(--mk-accent-sub);
|
|
254
|
+
color: var(--mk-accent);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.mk-kind-word {
|
|
258
|
+
display: block;
|
|
259
|
+
padding: 2px 7px;
|
|
260
|
+
font-size: 10px;
|
|
261
|
+
font-weight: 600;
|
|
262
|
+
letter-spacing: 0.02em;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.mk-kind[data-mk-chosen="true"] {
|
|
266
|
+
background: var(--mk-accent);
|
|
267
|
+
color: var(--mk-accent-ink);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.mk-kind-pick {
|
|
271
|
+
position: absolute;
|
|
272
|
+
inset: -6px -4px;
|
|
273
|
+
width: calc(100% + 8px);
|
|
274
|
+
border: 0;
|
|
275
|
+
opacity: 0;
|
|
276
|
+
font: inherit;
|
|
277
|
+
cursor: pointer;
|
|
278
|
+
appearance: none;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.mk-kind:has(.mk-kind-pick:focus-visible) {
|
|
282
|
+
outline: 2px solid var(--mk-accent);
|
|
283
|
+
outline-offset: 2px;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.mk-ctx dt,
|
|
287
|
+
.mk-score-name {
|
|
203
288
|
align-self: baseline;
|
|
204
289
|
color: var(--mk-faint);
|
|
205
290
|
font-size: 9px;
|
|
@@ -293,6 +378,72 @@ function contextAndShots() {
|
|
|
293
378
|
color: color-mix(in oklab, var(--mk-maple) 78%, var(--mk-muted));
|
|
294
379
|
font-weight: 450;
|
|
295
380
|
}
|
|
381
|
+
`.trim();
|
|
382
|
+
}
|
|
383
|
+
function contextAndShots() {
|
|
384
|
+
return `
|
|
385
|
+
/* It folds rather than vanishes: the width is the one fact read off it, so
|
|
386
|
+
the summary keeps that line in both states. */
|
|
387
|
+
.mk-ctx-card {
|
|
388
|
+
margin: 2px 16px 4px;
|
|
389
|
+
border: 1px solid var(--mk-line);
|
|
390
|
+
border-radius: var(--mk-r-sm);
|
|
391
|
+
background: var(--mk-sunk);
|
|
392
|
+
overflow: hidden;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.mk-ctx-head {
|
|
396
|
+
display: flex;
|
|
397
|
+
align-items: center;
|
|
398
|
+
justify-content: space-between;
|
|
399
|
+
gap: 8px;
|
|
400
|
+
width: 100%;
|
|
401
|
+
min-height: 28px;
|
|
402
|
+
padding: 0 11px;
|
|
403
|
+
border: 0;
|
|
404
|
+
background: none;
|
|
405
|
+
color: var(--mk-muted);
|
|
406
|
+
font: inherit;
|
|
407
|
+
font-size: 11px;
|
|
408
|
+
font-variant-numeric: tabular-nums;
|
|
409
|
+
cursor: pointer;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.mk-ctx-head:hover {
|
|
413
|
+
color: var(--mk-fg);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/* Two borders rather than an icon: one control does not earn a second svg. */
|
|
417
|
+
.mk-ctx-caret {
|
|
418
|
+
width: 6px;
|
|
419
|
+
height: 6px;
|
|
420
|
+
border-right: 1.5px solid currentColor;
|
|
421
|
+
border-bottom: 1.5px solid currentColor;
|
|
422
|
+
transform: translateY(1px) rotate(-135deg);
|
|
423
|
+
transition: transform var(--mk-dur-swap) var(--mk-ease-surface);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.mk-ctx-card[data-mk-open="false"] .mk-ctx-caret {
|
|
427
|
+
transform: translateY(-1px) rotate(45deg);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.mk-ctx-card[data-mk-open="false"] .mk-ctx {
|
|
431
|
+
display: none;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/* Two pairs to a row: seven facts one per line ran the card down half the
|
|
435
|
+
panel. Labels keep their own column, so every value still lines up. */
|
|
436
|
+
.mk-ctx {
|
|
437
|
+
display: grid;
|
|
438
|
+
grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
|
|
439
|
+
gap: 7px 10px;
|
|
440
|
+
padding: 11px;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.mk-ctx-head + .mk-ctx {
|
|
444
|
+
padding-top: 3px;
|
|
445
|
+
}
|
|
446
|
+
|
|
296
447
|
`.trim();
|
|
297
448
|
}
|
|
298
449
|
function partsCss() {
|
|
@@ -406,6 +557,10 @@ ${emojiCss()}
|
|
|
406
557
|
|
|
407
558
|
${contextAndShots()}
|
|
408
559
|
|
|
560
|
+
${scoreCard()}
|
|
561
|
+
|
|
562
|
+
${kindChip()}
|
|
563
|
+
|
|
409
564
|
.mk-leave {
|
|
410
565
|
position: absolute;
|
|
411
566
|
top: 12px;
|
package/dist/composer/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SHEET_BREAKPOINT_PX } from "../tokens.js";
|
|
2
2
|
import { CANCEL_LABEL, MapleActions, MapleActionsProps, SEND_LABEL } from "./actions.js";
|
|
3
3
|
import { ATTACH_WORDS, MapleAttachments, MapleAttachmentsProps } from "./attachments.js";
|
|
4
|
-
import { MapleContextBadge, MapleContextProps } from "./badge.js";
|
|
4
|
+
import { CONTEXT_LABELS, MapleContextBadge, MapleContextProps } from "./badge.js";
|
|
5
5
|
import { COMPOSER_PLACEHOLDER, MapleBody, MapleBodyProps } from "./body.js";
|
|
6
6
|
import { LeaveAsk, createLeaveAsk } from "./leave.js";
|
|
7
7
|
import { ComposerScopeError, SheetDetent } from "./scope.js";
|
|
@@ -11,5 +11,6 @@ import { EmojiChoice, REVIEW_EMOJI, SHORTCODE_LIMIT, Shortcode, Written, appende
|
|
|
11
11
|
import { peeks } from "./peek.js";
|
|
12
12
|
import { KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, QUOTE_LIMIT, TARGET_PREFIX, UNNAMED_TARGET, leaveMessage, quotedText, targetName, targetPhrase } from "./phrase.js";
|
|
13
13
|
import { EMOJI_COPY, EMOJI_ICON_PX, EmojiGrid, EmojiGridProps, MapleEmoji, MapleEmojiProps } from "./picker-emoji.js";
|
|
14
|
+
import { KIND_AUTO, KIND_LABEL, MapleScoreCard, MapleScoreProps, SCORE_LABEL } from "./score.js";
|
|
14
15
|
import { CLOSE_LABEL, DETAIL_ATTRIBUTE, MapleTarget, MapleTargetProps } from "./target.js";
|
|
15
|
-
export { ATTACH_WORDS, MapleActions as Actions, MapleAttachments as Attachments, MapleBody as Body, CANCEL_LABEL, CLOSE_LABEL, COMPOSER_LABEL, COMPOSER_PLACEHOLDER, MapleComposer as Composer, ComposerScopeError, MapleContextBadge as Context, DETAIL_ATTRIBUTE, DETENT_LABELS, MapleDetail as Detail, EMOJI_COPY, EMOJI_ICON_PX, MapleEmoji as Emoji, type EmojiChoice, EmojiGrid, type EmojiGridProps, KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, type LeaveAsk, MapleActions, type MapleActionsProps, MapleAttachments, type MapleAttachmentsProps, MapleBody, type MapleBodyProps, MapleComposer, type MapleComposerProps, MapleContextBadge, type MapleContextProps, MapleDetail, type MapleDetailProps, MapleEmoji, type MapleEmojiProps, MapleTarget, type MapleTargetProps, QUOTE_LIMIT, REVIEW_EMOJI, SEND_LABEL, SHEET_BREAKPOINT_PX, SHORTCODE_LIMIT, type SheetDetent, type Shortcode, TARGET_PREFIX, MapleTarget as Target, UNNAMED_TARGET, type Written, appended, createLeaveAsk, detailRows, leaveMessage, peeks, quotedText, searchEmoji, shortcodeAt, targetName, targetPhrase, writeAt };
|
|
16
|
+
export { ATTACH_WORDS, MapleActions as Actions, MapleAttachments as Attachments, MapleBody as Body, CANCEL_LABEL, CLOSE_LABEL, COMPOSER_LABEL, COMPOSER_PLACEHOLDER, CONTEXT_LABELS, MapleComposer as Composer, ComposerScopeError, MapleContextBadge as Context, DETAIL_ATTRIBUTE, DETENT_LABELS, MapleDetail as Detail, EMOJI_COPY, EMOJI_ICON_PX, MapleEmoji as Emoji, type EmojiChoice, EmojiGrid, type EmojiGridProps, KIND_AUTO, KIND_LABEL, KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, type LeaveAsk, MapleActions, type MapleActionsProps, MapleAttachments, type MapleAttachmentsProps, MapleBody, type MapleBodyProps, MapleComposer, type MapleComposerProps, MapleContextBadge, type MapleContextProps, MapleDetail, type MapleDetailProps, MapleEmoji, type MapleEmojiProps, MapleScoreCard, type MapleScoreProps, MapleTarget, type MapleTargetProps, QUOTE_LIMIT, REVIEW_EMOJI, SCORE_LABEL, SEND_LABEL, SHEET_BREAKPOINT_PX, SHORTCODE_LIMIT, MapleScoreCard as Score, type SheetDetent, type Shortcode, TARGET_PREFIX, MapleTarget as Target, UNNAMED_TARGET, type Written, appended, createLeaveAsk, detailRows, leaveMessage, peeks, quotedText, searchEmoji, shortcodeAt, targetName, targetPhrase, writeAt };
|
package/dist/composer/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { SHEET_BREAKPOINT_PX } from "../tokens.js";
|
|
|
2
2
|
import { ComposerScopeError } from "./scope.js";
|
|
3
3
|
import { CANCEL_LABEL, MapleActions, SEND_LABEL } from "./actions.js";
|
|
4
4
|
import { ATTACH_WORDS, MapleAttachments } from "./attachments.js";
|
|
5
|
-
import { MapleContextBadge } from "./badge.js";
|
|
5
|
+
import { CONTEXT_LABELS, MapleContextBadge } from "./badge.js";
|
|
6
6
|
import { REVIEW_EMOJI, SHORTCODE_LIMIT, appended, searchEmoji, shortcodeAt, writeAt } from "./emoji.js";
|
|
7
7
|
import { EMOJI_COPY, EMOJI_ICON_PX, EmojiGrid, MapleEmoji } from "./picker-emoji.js";
|
|
8
8
|
import { COMPOSER_PLACEHOLDER, MapleBody } from "./body.js";
|
|
@@ -11,5 +11,6 @@ import { KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, QUOTE_LIMIT, TARGET_PREFIX, UNNA
|
|
|
11
11
|
import { COMPOSER_LABEL, DETENT_LABELS, MapleComposer } from "./composer.js";
|
|
12
12
|
import { MapleDetail, detailRows } from "./detail.js";
|
|
13
13
|
import { createLeaveAsk } from "./leave.js";
|
|
14
|
+
import { KIND_AUTO, KIND_LABEL, MapleScoreCard, SCORE_LABEL } from "./score.js";
|
|
14
15
|
import { CLOSE_LABEL, DETAIL_ATTRIBUTE, MapleTarget } from "./target.js";
|
|
15
|
-
export { ATTACH_WORDS, MapleActions as Actions, MapleAttachments as Attachments, MapleBody as Body, CANCEL_LABEL, CLOSE_LABEL, COMPOSER_LABEL, COMPOSER_PLACEHOLDER, MapleComposer as Composer, ComposerScopeError, MapleContextBadge as Context, DETAIL_ATTRIBUTE, DETENT_LABELS, MapleDetail as Detail, EMOJI_COPY, EMOJI_ICON_PX, MapleEmoji as Emoji, EmojiGrid, KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, MapleActions, MapleAttachments, MapleBody, MapleComposer, MapleContextBadge, MapleDetail, MapleEmoji, MapleTarget, QUOTE_LIMIT, REVIEW_EMOJI, SEND_LABEL, SHEET_BREAKPOINT_PX, SHORTCODE_LIMIT, TARGET_PREFIX, MapleTarget as Target, UNNAMED_TARGET, appended, createLeaveAsk, detailRows, leaveMessage, peeks, quotedText, searchEmoji, shortcodeAt, targetName, targetPhrase, writeAt };
|
|
16
|
+
export { ATTACH_WORDS, MapleActions as Actions, MapleAttachments as Attachments, MapleBody as Body, CANCEL_LABEL, CLOSE_LABEL, COMPOSER_LABEL, COMPOSER_PLACEHOLDER, CONTEXT_LABELS, MapleComposer as Composer, ComposerScopeError, MapleContextBadge as Context, DETAIL_ATTRIBUTE, DETENT_LABELS, MapleDetail as Detail, EMOJI_COPY, EMOJI_ICON_PX, MapleEmoji as Emoji, EmojiGrid, KIND_AUTO, KIND_LABEL, KIND_WORDS, LEAVE_DISCARD, LEAVE_KEEP, MapleActions, MapleAttachments, MapleBody, MapleComposer, MapleContextBadge, MapleDetail, MapleEmoji, MapleScoreCard, MapleTarget, QUOTE_LIMIT, REVIEW_EMOJI, SCORE_LABEL, SEND_LABEL, SHEET_BREAKPOINT_PX, SHORTCODE_LIMIT, MapleScoreCard as Score, TARGET_PREFIX, MapleTarget as Target, UNNAMED_TARGET, appended, createLeaveAsk, detailRows, leaveMessage, peeks, quotedText, searchEmoji, shortcodeAt, targetName, targetPhrase, writeAt };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AsChildProps } from "../slot.js";
|
|
2
|
+
//#region src/composer/score.d.ts
|
|
3
|
+
/** The card. It draws nothing at all until something has been judged. */
|
|
4
|
+
export interface MapleScoreProps extends AsChildProps {
|
|
5
|
+
readonly className?: string;
|
|
6
|
+
/** The chip that lets a reviewer overrule the guess. On unless asked otherwise. */
|
|
7
|
+
readonly kind?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** What the card calls itself, and what the kind control is called. */
|
|
10
|
+
export declare const SCORE_LABEL = "How this comment reads";
|
|
11
|
+
export declare const KIND_LABEL = "What kind of comment this is";
|
|
12
|
+
/** The option that hands the kind back to the classifier. */
|
|
13
|
+
export declare const KIND_AUTO = "auto";
|
|
14
|
+
/** The card. Renders from `ComposerState` and holds nothing of its own. */
|
|
15
|
+
export declare const MapleScoreCard: import("react").ForwardRefExoticComponent<MapleScoreProps & import("react").RefAttributes<HTMLElement>>;
|
|
16
|
+
//#endregion
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Slot } from "../slot.js";
|
|
2
|
+
import { Fragment, createElement, forwardRef } from "react";
|
|
3
|
+
import { useMaple, useMapleClient } from "@maple-kit/react";
|
|
4
|
+
import { COMMENT_KINDS, FALLBACK_KIND } from "@maple-kit/core/connectors";
|
|
5
|
+
//#region src/composer/score.ts
|
|
6
|
+
const SCORE_LABEL = "How this comment reads";
|
|
7
|
+
const KIND_LABEL = "What kind of comment this is";
|
|
8
|
+
const KIND_AUTO = "auto";
|
|
9
|
+
const RUNNER_UP = .5;
|
|
10
|
+
const MapleScoreCard = forwardRef(function MapleScoreCard(props, ref) {
|
|
11
|
+
const { assist, composer } = useMaple();
|
|
12
|
+
const { scores, status } = composer.assist;
|
|
13
|
+
const Element = props.asChild ? Slot : "section";
|
|
14
|
+
if (!assist || status === "idle" || composer.viewing !== void 0) return null;
|
|
15
|
+
return createElement(Element, {
|
|
16
|
+
ref,
|
|
17
|
+
className: [
|
|
18
|
+
"mk-composer-row",
|
|
19
|
+
"mk-score",
|
|
20
|
+
props.className
|
|
21
|
+
].filter(Boolean).join(" "),
|
|
22
|
+
"data-mk-status": status,
|
|
23
|
+
"aria-label": SCORE_LABEL,
|
|
24
|
+
"aria-busy": status === "judging"
|
|
25
|
+
}, props.kind === false ? null : createElement(KindChip), ...assist.pillars.map((pillar) => pillarRow(pillar, find(scores, pillar.id))));
|
|
26
|
+
});
|
|
27
|
+
function pillarRow(pillar, score) {
|
|
28
|
+
const level = score?.level;
|
|
29
|
+
const reached = level === void 0 ? void 0 : pillar.levels[level];
|
|
30
|
+
return createElement(Fragment, { key: pillar.id }, createElement("span", { className: "mk-score-name" }, pillar.id), createElement("span", {
|
|
31
|
+
className: "mk-score-bar",
|
|
32
|
+
role: "img",
|
|
33
|
+
"aria-label": legend(pillar, score)
|
|
34
|
+
}, ...pillar.levels.map((_, index) => segment(index, score?.distribution[index]))), createElement("span", {
|
|
35
|
+
className: "mk-score-rung",
|
|
36
|
+
title: reached?.description
|
|
37
|
+
}, reached?.label ?? ""));
|
|
38
|
+
}
|
|
39
|
+
function segment(index, share) {
|
|
40
|
+
const fill = Math.round((share ?? 0) * 1e3) / 1e3;
|
|
41
|
+
return createElement("i", {
|
|
42
|
+
key: index,
|
|
43
|
+
style: { "--mk-p": fill }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function legend(pillar, score) {
|
|
47
|
+
if (score === void 0) return `${pillar.id}: not judged yet`;
|
|
48
|
+
const sure = Math.round(score.confidence * 100);
|
|
49
|
+
return `${pillar.id}: ${pillar.levels[score.level]?.label ?? ""}, ${String(sure)}% confident`;
|
|
50
|
+
}
|
|
51
|
+
function KindChip() {
|
|
52
|
+
const { composer } = useMaple();
|
|
53
|
+
const client = useMapleClient();
|
|
54
|
+
const { chosenKind, kind } = composer.assist;
|
|
55
|
+
return createElement("span", {
|
|
56
|
+
className: "mk-kind",
|
|
57
|
+
"data-mk-chosen": String(chosenKind !== void 0)
|
|
58
|
+
}, createElement("span", {
|
|
59
|
+
className: "mk-kind-word",
|
|
60
|
+
"aria-hidden": "true"
|
|
61
|
+
}, word(kind, chosenKind)), createElement("select", {
|
|
62
|
+
className: "mk-kind-pick",
|
|
63
|
+
"aria-label": KIND_LABEL,
|
|
64
|
+
value: chosenKind ?? "auto",
|
|
65
|
+
onChange: (event) => client.setKind(event.target.value === "auto" ? void 0 : event.target.value)
|
|
66
|
+
}, createElement("option", {
|
|
67
|
+
key: KIND_AUTO,
|
|
68
|
+
value: KIND_AUTO
|
|
69
|
+
}, guessed(kind)), ...COMMENT_KINDS.map((one) => createElement("option", {
|
|
70
|
+
key: one,
|
|
71
|
+
value: one
|
|
72
|
+
}, one))));
|
|
73
|
+
}
|
|
74
|
+
function word(kind, chosen) {
|
|
75
|
+
if (chosen !== void 0) return chosen;
|
|
76
|
+
if (kind === null) return "…";
|
|
77
|
+
const [next, share] = COMMENT_KINDS.filter((one) => one !== kind.kind).map((one) => [one, kind.distribution[one] ?? 0]).reduce((best, one) => one[1] > best[1] ? one : best, [FALLBACK_KIND, 0]);
|
|
78
|
+
return share >= (kind.distribution[kind.kind] ?? 1) * RUNNER_UP ? `${kind.kind} or ${next}` : kind.kind;
|
|
79
|
+
}
|
|
80
|
+
function guessed(kind) {
|
|
81
|
+
return kind === null ? "auto" : `auto (${kind.kind})`;
|
|
82
|
+
}
|
|
83
|
+
function find(scores, id) {
|
|
84
|
+
return scores.find((score) => score.pillar === id);
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { KIND_AUTO, KIND_LABEL, MapleScoreCard, SCORE_LABEL };
|
package/dist/maple.js
CHANGED
|
@@ -5,6 +5,7 @@ import { MapleContextBadge } from "./composer/badge.js";
|
|
|
5
5
|
import { MapleBody } from "./composer/body.js";
|
|
6
6
|
import { MapleComposer } from "./composer/composer.js";
|
|
7
7
|
import { MapleDetail } from "./composer/detail.js";
|
|
8
|
+
import { MapleScoreCard } from "./composer/score.js";
|
|
8
9
|
import { MapleTarget } from "./composer/target.js";
|
|
9
10
|
import { PICK_ORDER } from "./island/language.js";
|
|
10
11
|
import { IslandContent } from "./island/content.js";
|
|
@@ -53,7 +54,7 @@ function composer(leave, shots) {
|
|
|
53
54
|
return createElement(MapleComposer, {
|
|
54
55
|
key: "composer",
|
|
55
56
|
...leave === void 0 ? {} : { leave }
|
|
56
|
-
}, createElement(MapleTarget, { key: "target" }), createElement(MapleBody, { key: "body" }), createElement(MapleDetail, { key: "detail" }), createElement(MapleContextBadge, { key: "context" }), createElement(MapleAttachments, {
|
|
57
|
+
}, createElement(MapleTarget, { key: "target" }), createElement(MapleBody, { key: "body" }), createElement(MapleDetail, { key: "detail" }), createElement(MapleScoreCard, { key: "score" }), createElement(MapleContextBadge, { key: "context" }), createElement(MapleAttachments, {
|
|
57
58
|
key: "attachments",
|
|
58
59
|
...shots
|
|
59
60
|
}), createElement(MapleNotice, {
|
package/dist/tokens.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maple-kit/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Maple's composed reviewer parts: the marks, the island and the composer",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"./package.json": "./package.json"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@maple-kit/core": "0.
|
|
36
|
-
"@maple-kit/react": "0.
|
|
35
|
+
"@maple-kit/core": "0.6.0",
|
|
36
|
+
"@maple-kit/react": "0.6.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^18.2.0 || ^19.0.0",
|