@colixsystems/widget-sdk 0.275.2 → 0.277.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.
@@ -0,0 +1,70 @@
1
+ // sc-15080 — the page `<MarkdownInput>` runs its editor in on iOS and Android.
2
+ //
3
+ // React Native has no editable rich-text surface, so the native field hosts
4
+ // the SAME editor module the web field mounts, inside a WebView. This entry is
5
+ // bundled into ./markdown-editor-html.js by scripts/build-markdown-editor.mjs;
6
+ // nothing imports it at runtime.
7
+ //
8
+ // Messages are JSON strings. In: init, style, set, command, focus. Out:
9
+ // ready, change, height, focus, selection, state.
10
+
11
+ import { createMarkdownEditor } from "./markdown-editor-core.js";
12
+ import { markdownEditorCss } from "./markdown-editor-css.js";
13
+
14
+ const ROOT = "#root";
15
+
16
+ function post(message) {
17
+ if (window.ReactNativeWebView) window.ReactNativeWebView.postMessage(JSON.stringify(message));
18
+ }
19
+
20
+ let instance = null;
21
+ const style = document.createElement("style");
22
+ document.head.appendChild(style);
23
+
24
+ function paint({ tokens, minHeight }) {
25
+ if (tokens && typeof tokens === "object") style.textContent = markdownEditorCss(tokens, ROOT, { minHeight });
26
+ }
27
+
28
+ function init(message) {
29
+ if (instance) return;
30
+ const { markdown, placeholder, label } = message;
31
+ paint(message);
32
+
33
+ const root = document.querySelector(ROOT);
34
+ instance = createMarkdownEditor({
35
+ element: root,
36
+ markdown,
37
+ placeholder,
38
+ label,
39
+ onChange: (next) => post({ type: "change", markdown: next }),
40
+ onFocusChange: (focused) => post({ type: "focus", focused }),
41
+ onState: (state) => post({ type: "state", inTable: state.inTable === true }),
42
+ });
43
+ instance.editor.on("selectionUpdate", () => post({ type: "selection", text: instance.selectedText() }));
44
+
45
+ let lastHeight = 0;
46
+ new ResizeObserver(() => {
47
+ const height = Math.ceil(root.getBoundingClientRect().height);
48
+ if (height !== lastHeight) post({ type: "height", height: (lastHeight = height) });
49
+ }).observe(root);
50
+ }
51
+
52
+ window.mdEditor = {
53
+ receive(raw) {
54
+ let message;
55
+ try {
56
+ message = JSON.parse(raw);
57
+ } catch {
58
+ return;
59
+ }
60
+ if (!message || typeof message !== "object") return;
61
+ if (message.type === "init") init(message);
62
+ else if (message.type === "style") paint(message);
63
+ else if (!instance) return;
64
+ else if (message.type === "set") instance.setMarkdown(message.markdown);
65
+ else if (message.type === "command") instance.command(message.name, message.args);
66
+ else if (message.type === "focus") instance.focus();
67
+ },
68
+ };
69
+
70
+ post({ type: "ready" });
@@ -1,14 +1,14 @@
1
1
  // sc-6970 — the ONE implementation behind the `<MarkdownInput>` SDK primitive.
2
2
  //
3
- // The authoring half of `<RichText>`: a multi-line field whose toolbar wraps the
4
- // author's SELECTION in markdown markers. Widgets previously had only a bare
3
+ // The authoring half of `<RichText>`. Widgets previously had only a bare
5
4
  // `TextInput`, so a widget asked for a formatting toolbar had to splice literal
6
5
  // `<strong>`/`<br>` tags into the text — markup the author then read as tag soup.
7
6
  //
8
- // sc-14974: the field itself is live-styled, so the author edits the formatted
9
- // text directly. Each host binding supplies its own `LiveField` (a TextInput
10
- // with styled children natively, a contentEditable on web); the rendered
11
- // `<RichText>` preview is opt-in for content the field shows only as markers.
7
+ // sc-15080: the author edits the formatted result directly — headings, lists,
8
+ // links and real tables — while the stored value stays markdown. Each host
9
+ // binding supplies its own `EditorField` around the one shared editor (mounted
10
+ // in the page on web, in a WebView natively), so `showPreview` has nothing
11
+ // left to show and is accepted as a no-op.
12
12
  //
13
13
  // The two platform bindings differ ONLY in where the primitives come from; the
14
14
  // component is defined once here so the hosts cannot drift (CLAUDE.md §3, §8).
@@ -16,7 +16,6 @@
16
16
  import React from "react";
17
17
  import { useHostTheme } from "./hooks.js";
18
18
  import { resolveRichTextTokens } from "./richtext-tokens.js";
19
- import { markdownEditOps } from "./markdown-edit.js";
20
19
  import { makeMarkdownLinkDialog } from "./markdown-link-dialog.js";
21
20
 
22
21
  const TOOLS = Object.freeze([
@@ -28,8 +27,7 @@ const TOOLS = Object.freeze([
28
27
  { key: "bullet", label: "•", accessibilityLabel: "Bulleted list" },
29
28
  { key: "ordered", label: "1.", accessibilityLabel: "Numbered list" },
30
29
  { key: "table", label: "Table", accessibilityLabel: "Insert table" },
31
- // sc-7349: the one tool a selection cannot complete — a link needs a target,
32
- // so this button opens the form instead of editing the string directly.
30
+ // sc-7349: a link needs a target no selection supplies, so this opens a form.
33
31
  {
34
32
  key: "link",
35
33
  label: "Link",
@@ -38,17 +36,26 @@ const TOOLS = Object.freeze([
38
36
  },
39
37
  ]);
40
38
 
41
- export function makeMarkdownInput(rn, RichText, Modal, Button, LiveField) {
39
+ // Shown while the caret is in a table: a phone keyboard has no Tab key to
40
+ // grow one, and a table must be removable without selecting around it.
41
+ const TABLE_TOOLS = Object.freeze([
42
+ { key: "addRow", label: "+ Row", accessibilityLabel: "Add row" },
43
+ { key: "addColumn", label: "+ Column", accessibilityLabel: "Add column" },
44
+ { key: "removeRow", label: "− Row", accessibilityLabel: "Remove row" },
45
+ { key: "removeColumn", label: "− Column", accessibilityLabel: "Remove column" },
46
+ { key: "removeTable", label: "Delete table", accessibilityLabel: "Delete table" },
47
+ ]);
48
+
49
+ export function makeMarkdownInput(rn, Modal, Button, EditorField) {
42
50
  const { Text, View, Pressable } = rn;
43
51
  const MarkdownLinkDialog = makeMarkdownLinkDialog(rn, Modal, Button);
44
52
 
53
+ // `previewLabel`, `showPreview` and `renderImage` are accepted for widgets
54
+ // written before the field showed the formatted result itself.
45
55
  function MarkdownInput({
46
56
  value,
47
57
  onChange,
48
58
  placeholder,
49
- previewLabel = "Preview",
50
- showPreview = false,
51
- renderImage,
52
59
  pages,
53
60
  minHeight = 150,
54
61
  maxHeight = 280,
@@ -58,72 +65,34 @@ export function makeMarkdownInput(rn, RichText, Modal, Button, LiveField) {
58
65
  }) {
59
66
  const theme = useHostTheme();
60
67
  const tokens = React.useMemo(() => resolveRichTextTokens(theme), [theme]);
61
- const [selection, setSelection] = React.useState({ start: 0, end: 0 });
62
68
  const fieldRef = React.useRef(null);
63
- const [linkOpen, setLinkOpen] = React.useState(false);
64
-
65
- const text = typeof value === "string" ? value : "";
69
+ const [linkLabel, setLinkLabel] = React.useState(null);
70
+ const [inTable, setInTable] = React.useState(false);
71
+ const onStateChange = React.useCallback((state) => setInTable(state.inTable), []);
66
72
 
67
- const onSelectionChange = React.useCallback((event) => {
68
- const next = event && event.nativeEvent && event.nativeEvent.selection;
69
- if (next) setSelection({ start: next.start, end: next.end });
73
+ const run = React.useCallback((name, args) => {
74
+ const field = fieldRef.current;
75
+ if (field) field.command(name, args);
70
76
  }, []);
71
77
 
72
- const applyTool = React.useCallback(
73
- (toolKey, options) => {
74
- if (typeof onChange !== "function") return;
75
- const edit = markdownEditOps[toolKey];
76
- if (!edit) return;
77
- const next = edit(text, selection, options);
78
- const field = fieldRef.current;
79
- if (field && typeof field.recordEdit === "function") field.recordEdit();
80
- onChange(next.value);
81
- setSelection(next.selection);
82
- },
83
- [onChange, text, selection],
84
- );
85
-
86
78
  const pressTool = React.useCallback(
87
79
  (tool) => {
88
- if (tool.opensDialog) {
89
- setLinkOpen(true);
90
- return;
91
- }
92
- applyTool(tool.key);
80
+ // The selection seeds the form's Link text, so a highlighted phrase
81
+ // stays the label.
82
+ if (tool.opensDialog) setLinkLabel(fieldRef.current ? fieldRef.current.selectedText() : "");
83
+ else run(tool.key);
93
84
  },
94
- [applyTool],
85
+ [run],
95
86
  );
96
87
 
97
88
  const insertLink = React.useCallback(
98
89
  (result) => {
99
- setLinkOpen(false);
100
- applyTool("link", result);
90
+ setLinkLabel(null);
91
+ run("link", result);
101
92
  },
102
- [applyTool],
103
- );
104
-
105
- // The selection seeds the dialog's Link text, so highlighting a phrase and
106
- // pressing Link keeps that phrase as the label.
107
- const selected = text.slice(
108
- Math.min(selection.start, selection.end),
109
- Math.max(selection.start, selection.end),
93
+ [run],
110
94
  );
111
95
 
112
- const fieldStyle = {
113
- fontFamily: tokens.bodyFont,
114
- fontSize: tokens.bodySize,
115
- lineHeight: tokens.lineHeight,
116
- color: tokens.color,
117
- backgroundColor: tokens.surface,
118
- borderWidth: 1,
119
- borderColor: tokens.border,
120
- borderRadius: tokens.radius,
121
- padding: tokens.padding,
122
- minHeight,
123
- maxHeight,
124
- textAlignVertical: "top",
125
- };
126
-
127
96
  return React.createElement(
128
97
  View,
129
98
  { style, testID },
@@ -137,7 +106,7 @@ export function makeMarkdownInput(rn, RichText, Modal, Button, LiveField) {
137
106
  },
138
107
  testID: testID ? `${testID}-toolbar` : undefined,
139
108
  },
140
- TOOLS.map((tool) =>
109
+ (inTable ? [...TOOLS, ...TABLE_TOOLS] : TOOLS).map((tool) =>
141
110
  React.createElement(
142
111
  Pressable,
143
112
  {
@@ -174,51 +143,24 @@ export function makeMarkdownInput(rn, RichText, Modal, Button, LiveField) {
174
143
  ),
175
144
  ),
176
145
  ),
177
- React.createElement(LiveField, {
146
+ React.createElement(EditorField, {
178
147
  ref: fieldRef,
179
- value: text,
148
+ value: typeof value === "string" ? value : "",
180
149
  onChangeText: onChange,
181
- onSelectionChange,
182
- selection,
150
+ onStateChange,
183
151
  placeholder,
184
152
  accessibilityLabel,
185
153
  tokens,
186
- style: fieldStyle,
154
+ minHeight,
155
+ maxHeight,
187
156
  testID: testID ? `${testID}-field` : undefined,
188
157
  }),
189
- showPreview && text.trim()
190
- ? React.createElement(
191
- View,
192
- { style: { marginTop: tokens.padding } },
193
- React.createElement(
194
- Text,
195
- {
196
- style: {
197
- fontFamily: tokens.bodyFont,
198
- fontSize: tokens.codeSize,
199
- color: tokens.mutedColor,
200
- marginBottom: tokens.blockGap,
201
- },
202
- },
203
- previewLabel,
204
- ),
205
- React.createElement(RichText, {
206
- value: text,
207
- renderImage,
208
- // sc-7349: the preview shows the reader's document, but a tap
209
- // must NOT leave the page — that would throw away the draft the
210
- // author is still writing.
211
- followLinks: false,
212
- testID: testID ? `${testID}-preview` : undefined,
213
- }),
214
- )
215
- : null,
216
158
  React.createElement(MarkdownLinkDialog, {
217
- visible: linkOpen,
218
- onClose: () => setLinkOpen(false),
159
+ visible: linkLabel !== null,
160
+ onClose: () => setLinkLabel(null),
219
161
  onSubmit: insertLink,
220
162
  pages,
221
- initialLabel: selected,
163
+ initialLabel: linkLabel || "",
222
164
  testID,
223
165
  }),
224
166
  );
@@ -1,11 +1,10 @@
1
1
  // sc-6970 — `<MarkdownInput>` (web). Binds the shared implementation in
2
- // ./markdown-input-view.js to react-native-web's primitives, the web
3
- // `<RichText>` it renders its preview with, and the web live field.
2
+ // ./markdown-input-view.js to react-native-web's primitives and the web
3
+ // editor field.
4
4
 
5
5
  import { ReactNative } from "./text-scale.js";
6
6
  import { makeMarkdownInput } from "./markdown-input-view.js";
7
- import { MarkdownLiveField } from "./markdown-live-field.js";
8
- import { RichText } from "./richtext.js";
7
+ import { MarkdownEditorField } from "./markdown-editor-field.js";
9
8
  import { Modal } from "./modal.js";
10
9
  import { Button } from "./button.js";
11
10
  import { TextInput } from "./primitives.js";
@@ -13,8 +12,7 @@ import { TextInput } from "./primitives.js";
13
12
  // TextInput stays for the link form, which is built from the same `rn`.
14
13
  export const MarkdownInput = makeMarkdownInput(
15
14
  { ...ReactNative, TextInput },
16
- RichText,
17
15
  Modal,
18
16
  Button,
19
- MarkdownLiveField,
17
+ MarkdownEditorField,
20
18
  );
@@ -1,12 +1,11 @@
1
1
  // sc-6970 — `<MarkdownInput>` (native). Binds the shared implementation in
2
2
  // ./markdown-input-view.js to React Native's own primitives and the native
3
- // `<RichText>`. Only the imports differ from the web mirror.
3
+ // editor field. Only the imports differ from the web mirror.
4
4
 
5
5
  import { View, Pressable, ScrollView } from "react-native";
6
6
  import { Text, TextInput } from "./bounded-text.native.js";
7
7
  import { makeMarkdownInput } from "./markdown-input-view.js";
8
- import { MarkdownLiveField } from "./markdown-live-field.native.js";
9
- import { RichText } from "./richtext.native.js";
8
+ import { MarkdownEditorField } from "./markdown-editor-field.native.js";
10
9
  import { Modal } from "./modal.native.js";
11
10
  import { Button } from "./button.native.js";
12
11
 
@@ -14,8 +13,7 @@ import { Button } from "./button.native.js";
14
13
  // scroll rather than grow an app's every page past the panel.
15
14
  export const MarkdownInput = makeMarkdownInput(
16
15
  { Text, View, Pressable, TextInput, ScrollView },
17
- RichText,
18
16
  Modal,
19
17
  Button,
20
- MarkdownLiveField,
18
+ MarkdownEditorField,
21
19
  );
package/dist/markdown.js CHANGED
@@ -196,8 +196,7 @@ const PLAIN_PATTERN =
196
196
  * Splits one line into positioned tokens: `{ type: "text", start, end }`, or
197
197
  * `{ type: "bold"|"italic"|"code", start, end, contentStart, contentEnd }`, or
198
198
  * `{ type: "link", start, end, contentStart, contentEnd, href }` whose content
199
- * is the RAW label. `parseInline` and the live editor both read these, so the
200
- * editor cannot style a construct the renderer would not draw.
199
+ * is the RAW label.
201
200
  */
202
201
  function scanInline(source) {
203
202
  const tokens = [];
@@ -532,116 +531,6 @@ export function parseMarkdown(text, options) {
532
531
  return blocks;
533
532
  }
534
533
 
535
- const LIVE_STYLE_KEYS = ["marker", "bold", "italic", "code", "href", "heading"];
536
-
537
- function sameLiveStyle(a, b) {
538
- return LIVE_STYLE_KEYS.every((key) => (a[key] || false) === (b[key] || false));
539
- }
540
-
541
- /**
542
- * sc-14974 — `text` cut into styled runs for the live editor. Joining every
543
- * run's `text` gives back `text` byte for byte: nothing is trimmed or joined,
544
- * and markdown markers stay in place flagged `marker` so the editor can dim
545
- * them. Each run is `{ text, marker?, bold?, italic?, code?, href?, heading? }`
546
- * with `heading` the level. Lines are classified in `parseMarkdown`'s order.
547
- */
548
- export function markdownLiveSegments(text) {
549
- const source = typeof text === "string" ? text : "";
550
- const runs = [];
551
- const push = (value, style) => {
552
- if (!value) return;
553
- const last = runs[runs.length - 1];
554
- if (last && sameLiveStyle(last, style)) last.text += value;
555
- else runs.push({ text: value, ...style });
556
- };
557
- const inline = (value, base) => {
558
- for (const token of scanInline(value)) {
559
- if (token.type === "text") {
560
- push(value.slice(token.start, token.end), base);
561
- continue;
562
- }
563
- const content = value.slice(token.contentStart, token.contentEnd);
564
- push(value.slice(token.start, token.contentStart), { ...base, marker: true });
565
- if (token.type === "link") inline(content, { ...base, href: token.href });
566
- else push(content, { ...base, [token.type]: true });
567
- push(value.slice(token.contentEnd, token.end), { ...base, marker: true });
568
- }
569
- };
570
- const tableRow = (line, base) => {
571
- let cellStart = 0;
572
- for (let k = 0; k < line.length; k += 1) {
573
- if (line.charAt(k) === "\\" && line.charAt(k + 1) === "|") k += 1;
574
- else if (line.charAt(k) === "|") {
575
- inline(line.slice(cellStart, k), base);
576
- push("|", { marker: true });
577
- cellStart = k + 1;
578
- }
579
- }
580
- inline(line.slice(cellStart), base);
581
- };
582
-
583
- const lines = source.split("\n");
584
- let inFence = false;
585
- let tableStart = -1;
586
- let tableEnd = -1;
587
- for (let i = 0; i < lines.length; i += 1) {
588
- if (i > 0) push("\n", {});
589
- const line = lines[i];
590
- const trimmed = line.trimEnd();
591
- const tail = line.slice(trimmed.length);
592
-
593
- if (inFence) {
594
- if (FENCE_CLOSE_RE.test(line)) inFence = false;
595
- push(line, inFence ? { code: true } : { marker: true });
596
- continue;
597
- }
598
- if (FENCE_OPEN_RE.test(trimmed)) {
599
- inFence = true;
600
- push(line, { marker: true });
601
- continue;
602
- }
603
-
604
- if (i > tableEnd && TABLE_ROW_RE.test(line) && TABLE_DIVIDER_RE.test(lines[i + 1] || "")) {
605
- tableStart = i;
606
- tableEnd = i + 1;
607
- while (tableEnd + 1 < lines.length && TABLE_ROW_RE.test(lines[tableEnd + 1])) tableEnd += 1;
608
- }
609
- if (i <= tableEnd) {
610
- if (i === tableStart + 1) push(line, { marker: true });
611
- else tableRow(line, i === tableStart ? { bold: true } : {});
612
- continue;
613
- }
614
-
615
- const lead = trimmed.length - trimmed.trimStart().length;
616
- const image = IMAGE_RE.exec(trimmed.trimStart());
617
- if (image) {
618
- const altStart = lead + 2;
619
- const altEnd = altStart + image[1].length;
620
- push(line.slice(0, altStart), { marker: true });
621
- push(line.slice(altStart, altEnd), {});
622
- push(line.slice(altEnd, trimmed.length), { marker: true });
623
- push(tail, {});
624
- continue;
625
- }
626
-
627
- const heading = HEADING_RE.exec(trimmed);
628
- const listItem = heading ? null : BULLET_RE.exec(trimmed) || ORDERED_RE.exec(trimmed);
629
- if (heading || listItem) {
630
- const content = heading ? heading[2] : listItem[listItem.length - 1];
631
- const base = heading ? { heading: heading[1].length } : {};
632
- const contentStart = trimmed.length - content.length;
633
- push(trimmed.slice(0, contentStart), { ...base, marker: true });
634
- inline(content, base);
635
- push(tail, base);
636
- continue;
637
- }
638
-
639
- inline(trimmed, {});
640
- push(tail, {});
641
- }
642
- return runs;
643
- }
644
-
645
534
  function spansToText(spans) {
646
535
  return spans.map((span) => span.text).join("");
647
536
  }
@@ -1,11 +1,8 @@
1
- // CommonJS mirror of navigation.js — the CJS compiler and the Mason build runner
2
- // resolve a `theme_config.navigation` block with the SAME rules the web host
3
- // applies, so an app's menu type cannot mean one thing on web and another in the
4
- // exported Expo app.
5
- //
6
- // The BODY below is copied VERBATIM from navigation.js; only the module syntax
7
- // differs. navigation-parity.test.js pins both facts — identical bodies AND
8
- // identical behaviour over a shared case table — so drift fails CI.
1
+ // GENERATED from navigation.js by scripts/generate-cjs.js — DO NOT EDIT.
2
+ // Change navigation.js, then run `npm run generate:cjs` in packages/widget-sdk.
3
+ "use strict";
4
+
5
+ const { CONTRACT, isHexColor, contrastRatio, mixHex, readableTextColor } = require("./contract.cjs");
9
6
 
10
7
  // REQ-NAV-STRUCTURE — the host side of an app's navigation SHAPE and the
11
8
  // tokens its footer strip is painted with.
@@ -25,7 +22,6 @@
25
22
  // the SAME literal, so what a planner may persist and what a host draws cannot
26
23
  // diverge.
27
24
 
28
- const { CONTRACT, isHexColor, contrastRatio, mixHex, readableTextColor } = require("./contract.cjs");
29
25
 
30
26
  // Absent or unknown resolves here, so every app authored before menu types
31
27
  // existed renders and compiles byte-identically.
@@ -895,5 +891,29 @@ function borderWidthOr(...values) {
895
891
  }
896
892
  return BORDER_WIDTH_MIN;
897
893
  }
898
-
899
- module.exports = { normaliseNavigation, menuItemCap, resolveFooterTokens, FOOTER_SIZES, clampFooterSize, FOOTER_HOME_LINE_CLEARANCE_PX, resolveSidebarTokens, resolveTopStripeLayout, resolveTopBarTokens, topStripeShowKey, TOP_STRIPE_ALWAYS_SHOWN_SLOTS, TOP_STRIPE_SLOTS, MIN_TOP_STRIPE_HEIGHT_PX, MAX_TOP_STRIPE_HEIGHT_PX, MIN_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_OFFSET_Y_PX, DEFAULT_TOP_STRIPE_HEIGHT_PX, DEFAULT_TOP_STRIPE_PADDING_X_PX, resolveSidebarUnfold, resolveLocalNavModel, drawsLocalNavAnywhere, isDarkSurface, resolveAppLogo };
894
+ module.exports = {
895
+ normaliseNavigation,
896
+ menuItemCap,
897
+ resolveFooterTokens,
898
+ FOOTER_SIZES,
899
+ clampFooterSize,
900
+ FOOTER_HOME_LINE_CLEARANCE_PX,
901
+ resolveSidebarTokens,
902
+ TOP_STRIPE_SLOTS,
903
+ TOP_STRIPE_ALWAYS_SHOWN_SLOTS,
904
+ MIN_TOP_STRIPE_HEIGHT_PX,
905
+ MAX_TOP_STRIPE_HEIGHT_PX,
906
+ MIN_TOP_STRIPE_PADDING_X_PX,
907
+ MAX_TOP_STRIPE_PADDING_X_PX,
908
+ MAX_TOP_STRIPE_OFFSET_Y_PX,
909
+ DEFAULT_TOP_STRIPE_HEIGHT_PX,
910
+ DEFAULT_TOP_STRIPE_PADDING_X_PX,
911
+ topStripeShowKey,
912
+ resolveTopStripeLayout,
913
+ isDarkSurface,
914
+ resolveAppLogo,
915
+ resolveTopBarTokens,
916
+ resolveSidebarUnfold,
917
+ resolveLocalNavModel,
918
+ drawsLocalNavAnywhere,
919
+ };
@@ -58,7 +58,7 @@ export function resolveRichTextTokens(theme) {
58
58
 
59
59
  export { IMAGE_WIDTH as RICH_TEXT_IMAGE_WIDTH };
60
60
 
61
- /** The style one inline span is drawn with, by `<RichText>` and the editor. */
61
+ /** The style one inline span is drawn with by `<RichText>`. */
62
62
  export function richTextSpanStyle(span, tokens) {
63
63
  return {
64
64
  ...(span.bold ? { fontWeight: "700" } : null),
@@ -71,27 +71,3 @@ export function richTextSpanStyle(span, tokens) {
71
71
  ...(span.href ? { color: tokens.accent, textDecorationLine: "underline" } : null),
72
72
  };
73
73
  }
74
-
75
- /**
76
- * sc-14974 — the style one `markdownLiveSegments` run is drawn with in
77
- * `<MarkdownInput>`: the span's `<RichText>` look, sized as its heading, with
78
- * markers dimmed so the text reads as the result while staying editable.
79
- */
80
- export function markdownLiveRunStyle(run, tokens) {
81
- const headingSize = run.heading
82
- ? tokens.headingSizes[run.heading] || tokens.headingSizes[3]
83
- : null;
84
- return {
85
- ...(headingSize
86
- ? {
87
- fontFamily: tokens.headingFont,
88
- fontWeight: "700",
89
- fontSize: headingSize,
90
- // The field's body leading would overlap a larger heading line.
91
- lineHeight: Math.round(headingSize * 1.3),
92
- }
93
- : null),
94
- ...richTextSpanStyle(run, tokens),
95
- ...(run.marker ? { color: tokens.mutedColor, textDecorationLine: "none" } : null),
96
- };
97
- }