@damiro/stylo 0.4.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.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/dist/InPlaceView-Ba7JCZ2Y.js +2346 -0
  4. package/dist/InPlaceView-Ba7JCZ2Y.js.map +1 -0
  5. package/dist/Preview-Dxb9zPVv.js +93 -0
  6. package/dist/Preview-Dxb9zPVv.js.map +1 -0
  7. package/dist/SplitView.d.ts +23 -0
  8. package/dist/SplitView.d.ts.map +1 -0
  9. package/dist/Stylo.d.ts +15 -0
  10. package/dist/Stylo.d.ts.map +1 -0
  11. package/dist/callout-oLE630ZP.js +37 -0
  12. package/dist/callout-oLE630ZP.js.map +1 -0
  13. package/dist/callout.d.ts +18 -0
  14. package/dist/callout.d.ts.map +1 -0
  15. package/dist/config-DTBxVhtH.js +101 -0
  16. package/dist/config-DTBxVhtH.js.map +1 -0
  17. package/dist/editor/SourceView.d.ts +17 -0
  18. package/dist/editor/SourceView.d.ts.map +1 -0
  19. package/dist/editor/extensions.d.ts +20 -0
  20. package/dist/editor/extensions.d.ts.map +1 -0
  21. package/dist/editor/highlight.d.ts +19 -0
  22. package/dist/editor/highlight.d.ts.map +1 -0
  23. package/dist/editor/save.d.ts +12 -0
  24. package/dist/editor/save.d.ts.map +1 -0
  25. package/dist/editor/theme.d.ts +3 -0
  26. package/dist/editor/theme.d.ts.map +1 -0
  27. package/dist/editor/useCodeMirror.d.ts +26 -0
  28. package/dist/editor/useCodeMirror.d.ts.map +1 -0
  29. package/dist/frontmatter.d.ts +21 -0
  30. package/dist/frontmatter.d.ts.map +1 -0
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/inplace/InPlaceView.d.ts +30 -0
  34. package/dist/inplace/InPlaceView.d.ts.map +1 -0
  35. package/dist/inplace/autoformat.d.ts +23 -0
  36. package/dist/inplace/autoformat.d.ts.map +1 -0
  37. package/dist/inplace/config.d.ts +57 -0
  38. package/dist/inplace/config.d.ts.map +1 -0
  39. package/dist/inplace/context-menu-actions.d.ts +53 -0
  40. package/dist/inplace/context-menu-actions.d.ts.map +1 -0
  41. package/dist/inplace/context-menu.d.ts +50 -0
  42. package/dist/inplace/context-menu.d.ts.map +1 -0
  43. package/dist/inplace/decorate.d.ts +17 -0
  44. package/dist/inplace/decorate.d.ts.map +1 -0
  45. package/dist/inplace/edit-boundaries.d.ts +59 -0
  46. package/dist/inplace/edit-boundaries.d.ts.map +1 -0
  47. package/dist/inplace/edit-insert-assoc.d.ts +17 -0
  48. package/dist/inplace/edit-insert-assoc.d.ts.map +1 -0
  49. package/dist/inplace/edit-line-prefix.d.ts +23 -0
  50. package/dist/inplace/edit-line-prefix.d.ts.map +1 -0
  51. package/dist/inplace/extension.d.ts +21 -0
  52. package/dist/inplace/extension.d.ts.map +1 -0
  53. package/dist/inplace/frontmatter.d.ts +13 -0
  54. package/dist/inplace/frontmatter.d.ts.map +1 -0
  55. package/dist/inplace/inline-md.d.ts +13 -0
  56. package/dist/inplace/inline-md.d.ts.map +1 -0
  57. package/dist/inplace/lazyInPlace.d.ts +7 -0
  58. package/dist/inplace/lazyInPlace.d.ts.map +1 -0
  59. package/dist/inplace/link-click.d.ts +24 -0
  60. package/dist/inplace/link-click.d.ts.map +1 -0
  61. package/dist/inplace/link-hover.d.ts +11 -0
  62. package/dist/inplace/link-hover.d.ts.map +1 -0
  63. package/dist/inplace/list-guides.d.ts +16 -0
  64. package/dist/inplace/list-guides.d.ts.map +1 -0
  65. package/dist/inplace/long-press.d.ts +39 -0
  66. package/dist/inplace/long-press.d.ts.map +1 -0
  67. package/dist/inplace/math.d.ts +16 -0
  68. package/dist/inplace/math.d.ts.map +1 -0
  69. package/dist/inplace/menu-plugin.d.ts +30 -0
  70. package/dist/inplace/menu-plugin.d.ts.map +1 -0
  71. package/dist/inplace/nodes.d.ts +24 -0
  72. package/dist/inplace/nodes.d.ts.map +1 -0
  73. package/dist/inplace/plugin.d.ts +21 -0
  74. package/dist/inplace/plugin.d.ts.map +1 -0
  75. package/dist/inplace/reveal.d.ts +8 -0
  76. package/dist/inplace/reveal.d.ts.map +1 -0
  77. package/dist/inplace/scan.d.ts +11 -0
  78. package/dist/inplace/scan.d.ts.map +1 -0
  79. package/dist/inplace/selection-bar.d.ts +38 -0
  80. package/dist/inplace/selection-bar.d.ts.map +1 -0
  81. package/dist/inplace/table-cell-dom.d.ts +30 -0
  82. package/dist/inplace/table-cell-dom.d.ts.map +1 -0
  83. package/dist/inplace/table-enter.d.ts +22 -0
  84. package/dist/inplace/table-enter.d.ts.map +1 -0
  85. package/dist/inplace/table-gizmos.d.ts +55 -0
  86. package/dist/inplace/table-gizmos.d.ts.map +1 -0
  87. package/dist/inplace/table-structure.d.ts +23 -0
  88. package/dist/inplace/table-structure.d.ts.map +1 -0
  89. package/dist/inplace/table-widget.d.ts +81 -0
  90. package/dist/inplace/table-widget.d.ts.map +1 -0
  91. package/dist/inplace/tables.d.ts +8 -0
  92. package/dist/inplace/tables.d.ts.map +1 -0
  93. package/dist/inplace/theme.d.ts +14 -0
  94. package/dist/inplace/theme.d.ts.map +1 -0
  95. package/dist/inplace/widgets.d.ts +25 -0
  96. package/dist/inplace/widgets.d.ts.map +1 -0
  97. package/dist/inplace/wikilinks.d.ts +10 -0
  98. package/dist/inplace/wikilinks.d.ts.map +1 -0
  99. package/dist/katex-BfiLlqfN.js +21979 -0
  100. package/dist/katex-BfiLlqfN.js.map +1 -0
  101. package/dist/katex.css +3 -0
  102. package/dist/markdown-N3lRmU2n.js +8524 -0
  103. package/dist/markdown-N3lRmU2n.js.map +1 -0
  104. package/dist/render/Preview.d.ts +10 -0
  105. package/dist/render/Preview.d.ts.map +1 -0
  106. package/dist/render/lazyPreview.d.ts +8 -0
  107. package/dist/render/lazyPreview.d.ts.map +1 -0
  108. package/dist/render/remark-callout.d.ts +10 -0
  109. package/dist/render/remark-callout.d.ts.map +1 -0
  110. package/dist/render/remark-wikilink.d.ts +8 -0
  111. package/dist/render/remark-wikilink.d.ts.map +1 -0
  112. package/dist/styles.css +2 -0
  113. package/dist/stylo.js +293 -0
  114. package/dist/stylo.js.map +1 -0
  115. package/dist/toolbar/Toolbar.d.ts +28 -0
  116. package/dist/toolbar/Toolbar.d.ts.map +1 -0
  117. package/dist/toolbar/block.d.ts +56 -0
  118. package/dist/toolbar/block.d.ts.map +1 -0
  119. package/dist/toolbar/cell-inline.d.ts +16 -0
  120. package/dist/toolbar/cell-inline.d.ts.map +1 -0
  121. package/dist/toolbar/commands.d.ts +25 -0
  122. package/dist/toolbar/commands.d.ts.map +1 -0
  123. package/dist/toolbar/config.d.ts +21 -0
  124. package/dist/toolbar/config.d.ts.map +1 -0
  125. package/dist/toolbar/fence.d.ts +28 -0
  126. package/dist/toolbar/fence.d.ts.map +1 -0
  127. package/dist/toolbar/floating-watchdog.d.ts +18 -0
  128. package/dist/toolbar/floating-watchdog.d.ts.map +1 -0
  129. package/dist/toolbar/icon-paths.d.ts +10 -0
  130. package/dist/toolbar/icon-paths.d.ts.map +1 -0
  131. package/dist/toolbar/icons.d.ts +10 -0
  132. package/dist/toolbar/icons.d.ts.map +1 -0
  133. package/dist/toolbar/inline-ops.d.ts +101 -0
  134. package/dist/toolbar/inline-ops.d.ts.map +1 -0
  135. package/dist/toolbar/inline.d.ts +38 -0
  136. package/dist/toolbar/inline.d.ts.map +1 -0
  137. package/dist/toolbar/keyboard-inset.d.ts +10 -0
  138. package/dist/toolbar/keyboard-inset.d.ts.map +1 -0
  139. package/dist/toolbar/keymap.d.ts +8 -0
  140. package/dist/toolbar/keymap.d.ts.map +1 -0
  141. package/dist/toolbar/labels.d.ts +16 -0
  142. package/dist/toolbar/labels.d.ts.map +1 -0
  143. package/dist/toolbar/table-grid.d.ts +23 -0
  144. package/dist/toolbar/table-grid.d.ts.map +1 -0
  145. package/dist/toolbar/table.d.ts +35 -0
  146. package/dist/toolbar/table.d.ts.map +1 -0
  147. package/dist/toolbar-settings/SortableRow.d.ts +15 -0
  148. package/dist/toolbar-settings/SortableRow.d.ts.map +1 -0
  149. package/dist/toolbar-settings/StyloToolbarSettings.d.ts +29 -0
  150. package/dist/toolbar-settings/StyloToolbarSettings.d.ts.map +1 -0
  151. package/dist/toolbar-settings/index.d.ts +3 -0
  152. package/dist/toolbar-settings/index.d.ts.map +1 -0
  153. package/dist/toolbar-settings/items.d.ts +24 -0
  154. package/dist/toolbar-settings/items.d.ts.map +1 -0
  155. package/dist/toolbar-settings.js +269 -0
  156. package/dist/toolbar-settings.js.map +1 -0
  157. package/dist/types.d.ts +264 -0
  158. package/dist/types.d.ts.map +1 -0
  159. package/dist/useCodeMirror-YnIFkvKn.js +1361 -0
  160. package/dist/useCodeMirror-YnIFkvKn.js.map +1 -0
  161. package/dist/wikilink-BFpTehto.js +42 -0
  162. package/dist/wikilink-BFpTehto.js.map +1 -0
  163. package/dist/wikilink.d.ts +11 -0
  164. package/dist/wikilink.d.ts.map +1 -0
  165. package/package.json +122 -0
@@ -0,0 +1,269 @@
1
+ import { r as e, t } from "./config-DTBxVhtH.js";
2
+ import { useId as n, useState as r } from "react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { DndContext as o, KeyboardSensor as s, PointerSensor as c, closestCenter as l, useSensor as u, useSensors as d } from "@dnd-kit/core";
5
+ import { SortableContext as f, sortableKeyboardCoordinates as p, useSortable as m, verticalListSortingStrategy as h } from "@dnd-kit/sortable";
6
+ import { CSS as g } from "@dnd-kit/utilities";
7
+ //#region src/toolbar/labels.ts
8
+ var _ = {
9
+ undo: "Undo",
10
+ redo: "Redo",
11
+ save: "Save",
12
+ search: "Find / replace",
13
+ h1: "Heading 1",
14
+ h2: "Heading 2",
15
+ h3: "Heading 3",
16
+ body: "Body",
17
+ bold: "Bold",
18
+ italic: "Italic",
19
+ strike: "Strikethrough",
20
+ underline: "Underline",
21
+ code: "Inline code",
22
+ codeBlock: "Code block",
23
+ link: "Link",
24
+ wikilink: "Wikilink",
25
+ quote: "Blockquote",
26
+ bulletList: "Bulleted list",
27
+ orderedList: "Numbered list",
28
+ task: "Task list",
29
+ hr: "Divider",
30
+ frontmatter: "Frontmatter",
31
+ table: "Table",
32
+ math: "Inline math",
33
+ mathBlock: "Block math"
34
+ }, v = Object.keys(_), y = {
35
+ root: "_root_18hcd_3",
36
+ col: "_col_18hcd_17",
37
+ colHead: "_colHead_18hcd_26",
38
+ list: "_list_18hcd_37",
39
+ row: "_row_18hcd_47",
40
+ handle: "_handle_18hcd_73",
41
+ glyph: "_glyph_18hcd_105",
42
+ label: "_label_18hcd_121",
43
+ rowActions: "_rowActions_18hcd_130",
44
+ iconButton: "_iconButton_18hcd_136",
45
+ textButton: "_textButton_18hcd_137",
46
+ footer: "_footer_18hcd_176",
47
+ empty: "_empty_18hcd_184",
48
+ srOnly: "_srOnly_18hcd_190"
49
+ };
50
+ //#endregion
51
+ //#region src/toolbar-settings/SortableRow.tsx
52
+ function b({ id: e, label: t, icon: n, position: r, count: o, actions: s }) {
53
+ let { attributes: c, listeners: l, setNodeRef: u, transform: d, transition: f, isDragging: p } = m({ id: e });
54
+ return /* @__PURE__ */ a("li", {
55
+ ref: u,
56
+ className: y.row,
57
+ style: {
58
+ transform: g.Transform.toString(d),
59
+ transition: f
60
+ },
61
+ "data-dragging": p || void 0,
62
+ children: [
63
+ /* @__PURE__ */ i("button", {
64
+ type: "button",
65
+ className: y.handle,
66
+ "aria-label": `Reorder ${t}, position ${r} of ${o}`,
67
+ ...c,
68
+ ...l,
69
+ children: /* @__PURE__ */ i("span", {
70
+ "aria-hidden": "true",
71
+ children: "⠿"
72
+ })
73
+ }),
74
+ /* @__PURE__ */ i("span", {
75
+ className: y.glyph,
76
+ "aria-hidden": "true",
77
+ children: n
78
+ }),
79
+ /* @__PURE__ */ i("span", {
80
+ className: y.label,
81
+ children: t
82
+ }),
83
+ /* @__PURE__ */ i("span", {
84
+ className: y.rowActions,
85
+ children: s
86
+ })
87
+ ]
88
+ });
89
+ }
90
+ function x(e) {
91
+ return e === "|";
92
+ }
93
+ function S(e) {
94
+ return x(e) ? null : typeof e == "string" ? e : e.id;
95
+ }
96
+ function C(e, t) {
97
+ return S(e) ?? `separator-${t}`;
98
+ }
99
+ function w(t, n) {
100
+ return x(t) ? {
101
+ id: null,
102
+ label: "Separator",
103
+ icon: null
104
+ } : typeof t == "string" ? {
105
+ id: t,
106
+ label: _[t] ?? t,
107
+ icon: n?.[t] ?? e[t] ?? null
108
+ } : {
109
+ id: t.id,
110
+ label: t.title,
111
+ icon: t.icon
112
+ };
113
+ }
114
+ function T(e, t) {
115
+ let n = new Set(t.map(S).filter((e) => e !== null));
116
+ return e.filter((e) => {
117
+ let t = S(e);
118
+ return t !== null && !n.has(t);
119
+ });
120
+ }
121
+ function E(e, t, n) {
122
+ if (n < 0 || n >= e.length || t === n) return e.slice();
123
+ let r = e.slice(), [i] = r.splice(t, 1);
124
+ return r.splice(n, 0, i), r;
125
+ }
126
+ function D(e, t) {
127
+ let n = e.slice();
128
+ return n.splice(t, 1), n;
129
+ }
130
+ function O(e, t) {
131
+ return [...e, t];
132
+ }
133
+ //#endregion
134
+ //#region src/toolbar-settings/StyloToolbarSettings.tsx
135
+ function k({ value: e, onChange: m, available: g, icons: _, className: x }) {
136
+ let S = n(), k = n(), [A, j] = r(""), M = d(u(c, { activationConstraint: { distance: 4 } }), u(s, { coordinateGetter: p })), N = T(g ?? v, e), P = e.map((e, t) => String(t));
137
+ function F({ active: t, over: n }) {
138
+ if (!n || t.id === n.id) return;
139
+ let r = Number(t.id), i = Number(n.id), a = w(e[r], _).label;
140
+ m(E(e, r, i)), j(`${a} moved to position ${i + 1} of ${e.length}`);
141
+ }
142
+ function I(t) {
143
+ let n = w(e[t], _).label;
144
+ m(D(e, t)), j(`${n} removed from the bar`);
145
+ }
146
+ function L(t) {
147
+ m(O(e, t)), j(`${w(t, _).label} added to the bar`);
148
+ }
149
+ function R() {
150
+ m([...t]), j("Toolbar reset to the default set");
151
+ }
152
+ let z = (t, n) => `${w(e[Number(t)], _).label} ${n}`;
153
+ return /* @__PURE__ */ a("div", {
154
+ className: [y.root, x].filter(Boolean).join(" "),
155
+ children: [
156
+ /* @__PURE__ */ a("section", {
157
+ className: y.col,
158
+ children: [
159
+ /* @__PURE__ */ i("h3", {
160
+ className: y.colHead,
161
+ id: S,
162
+ children: "On the bar"
163
+ }),
164
+ /* @__PURE__ */ i(o, {
165
+ sensors: M,
166
+ collisionDetection: l,
167
+ onDragEnd: F,
168
+ accessibility: { announcements: {
169
+ onDragStart: ({ active: e }) => z(e.id, "picked up"),
170
+ onDragOver: ({ active: e, over: t }) => t ? `${z(e.id, "is over position")} ${Number(t.id) + 1}` : "",
171
+ onDragEnd: ({ active: e, over: t }) => t ? `${z(e.id, "dropped at position")} ${Number(t.id) + 1}` : z(e.id, "dropped"),
172
+ onDragCancel: ({ active: e }) => z(e.id, "drag cancelled")
173
+ } },
174
+ children: /* @__PURE__ */ i(f, {
175
+ items: P,
176
+ strategy: h,
177
+ children: /* @__PURE__ */ i("ul", {
178
+ className: y.list,
179
+ "aria-labelledby": S,
180
+ children: e.map((t, n) => {
181
+ let { icon: r, label: a } = w(t, _);
182
+ return /* @__PURE__ */ i(b, {
183
+ id: String(n),
184
+ label: a,
185
+ icon: r,
186
+ position: n + 1,
187
+ count: e.length,
188
+ actions: /* @__PURE__ */ i("button", {
189
+ type: "button",
190
+ className: y.iconButton,
191
+ title: "Remove",
192
+ "aria-label": `Remove ${a} from the bar`,
193
+ onClick: () => I(n),
194
+ children: "✕"
195
+ })
196
+ }, C(t, n));
197
+ })
198
+ })
199
+ })
200
+ }),
201
+ /* @__PURE__ */ a("div", {
202
+ className: y.footer,
203
+ children: [/* @__PURE__ */ i("button", {
204
+ type: "button",
205
+ className: y.textButton,
206
+ onClick: () => L("|"),
207
+ children: "Add separator"
208
+ }), /* @__PURE__ */ i("button", {
209
+ type: "button",
210
+ className: y.textButton,
211
+ onClick: R,
212
+ children: "Reset to default"
213
+ })]
214
+ })
215
+ ]
216
+ }),
217
+ /* @__PURE__ */ a("section", {
218
+ className: y.col,
219
+ children: [/* @__PURE__ */ i("h3", {
220
+ className: y.colHead,
221
+ id: k,
222
+ children: "Available"
223
+ }), /* @__PURE__ */ a("ul", {
224
+ className: y.list,
225
+ "aria-labelledby": k,
226
+ children: [N.length === 0 && /* @__PURE__ */ i("li", {
227
+ className: y.empty,
228
+ children: "Every button is on the bar."
229
+ }), N.map((e, t) => {
230
+ let { icon: n, label: r } = w(e, _);
231
+ return /* @__PURE__ */ a("li", {
232
+ className: y.row,
233
+ children: [
234
+ /* @__PURE__ */ i("span", {
235
+ className: y.glyph,
236
+ "aria-hidden": "true",
237
+ children: n
238
+ }),
239
+ /* @__PURE__ */ i("span", {
240
+ className: y.label,
241
+ children: r
242
+ }),
243
+ /* @__PURE__ */ i("span", {
244
+ className: y.rowActions,
245
+ children: /* @__PURE__ */ i("button", {
246
+ type: "button",
247
+ className: y.textButton,
248
+ "aria-label": `Add ${r} to the bar`,
249
+ onClick: () => L(e),
250
+ children: "Add"
251
+ })
252
+ })
253
+ ]
254
+ }, C(e, t));
255
+ })]
256
+ })]
257
+ }),
258
+ /* @__PURE__ */ i("div", {
259
+ "aria-live": "polite",
260
+ className: y.srOnly,
261
+ children: A
262
+ })
263
+ ]
264
+ });
265
+ }
266
+ //#endregion
267
+ export { k as StyloToolbarSettings };
268
+
269
+ //# sourceMappingURL=toolbar-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar-settings.js","names":[],"sources":["../src/toolbar/labels.ts","../src/toolbar-settings/StyloToolbarSettings.module.css","../src/toolbar-settings/SortableRow.tsx","../src/toolbar-settings/items.ts","../src/toolbar-settings/StyloToolbarSettings.tsx"],"sourcesContent":["import type { ToolbarCommandId } from \"../types\"\n\n/**\n * Display labels for the built-in command ids — the single source of truth for\n * the button title / accessible name. `commands.ts` owns the *behaviour* of each\n * command and imports CodeMirror to do it; this module is pure data, so surfaces\n * that only need to *name* a command (the toolbar customizer, docs tooling) can\n * import it without pulling the editor in.\n *\n * `test/toolbar-settings.test.tsx` asserts these stay in step with\n * `BUILTIN_COMMANDS` — a renamed command title there without a change here fails\n * the build.\n */\nexport const BUILTIN_LABELS: Record<ToolbarCommandId, string> = {\n undo: \"Undo\",\n redo: \"Redo\",\n save: \"Save\",\n search: \"Find / replace\",\n h1: \"Heading 1\",\n h2: \"Heading 2\",\n h3: \"Heading 3\",\n body: \"Body\",\n bold: \"Bold\",\n italic: \"Italic\",\n strike: \"Strikethrough\",\n underline: \"Underline\",\n code: \"Inline code\",\n codeBlock: \"Code block\",\n link: \"Link\",\n wikilink: \"Wikilink\",\n quote: \"Blockquote\",\n bulletList: \"Bulleted list\",\n orderedList: \"Numbered list\",\n task: \"Task list\",\n hr: \"Divider\",\n frontmatter: \"Frontmatter\",\n table: \"Table\",\n math: \"Inline math\",\n mathBlock: \"Block math\",\n}\n\n/** Every built-in command id, in the canonical order labels are declared above. */\nexport const ALL_BUILTIN_IDS = Object.keys(BUILTIN_LABELS) as ToolbarCommandId[]\n","/* Reads the same `--stylo-*` tokens as the editor chrome, so it themes with it\n in light and dark. Structural only — the host controls the palette. */\n.root {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n color: var(--stylo-text);\n font: inherit;\n}\n\n@media (max-width: 460px) {\n .root {\n grid-template-columns: 1fr;\n }\n}\n\n.col {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border: 1px solid var(--stylo-border);\n border-radius: var(--stylo-radius);\n background: var(--stylo-bg);\n}\n\n.colHead {\n margin: 0;\n padding: 8px 12px;\n border-bottom: 1px solid var(--stylo-border);\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--stylo-text-muted);\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 4px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 5px 6px;\n border-radius: calc(var(--stylo-radius) - 3px);\n background: var(--stylo-bg);\n}\n\n.row:focus-visible {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -2px;\n}\n\n.row:hover {\n background: color-mix(in srgb, var(--stylo-border) 30%, transparent);\n}\n\n/* Mid-drag: the sortable clone floats over the list, so give it an opaque\n raised surface and lift the original's contrast down. */\n.row[data-dragging] {\n background: var(--stylo-surface-floating, #fff);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14);\n opacity: 0.9;\n}\n\n.handle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 22px;\n flex: none;\n padding: 0;\n border: 1px solid transparent;\n border-radius: calc(var(--stylo-radius) - 4px);\n background: none;\n color: var(--stylo-text-muted);\n font: inherit;\n line-height: 1;\n cursor: grab;\n touch-action: none;\n}\n\n.handle:hover {\n background: color-mix(in srgb, var(--stylo-border) 45%, transparent);\n color: var(--stylo-text);\n}\n\n.handle:focus-visible {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -1px;\n}\n\n.handle:active {\n cursor: grabbing;\n}\n\n.glyph {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex: none;\n color: var(--stylo-text-muted);\n}\n\n.glyph svg {\n width: 16px;\n height: 16px;\n display: block;\n}\n\n.label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.8125rem;\n}\n\n.rowActions {\n display: flex;\n gap: 2px;\n flex: none;\n}\n\n.iconButton,\n.textButton {\n box-sizing: border-box;\n border: 1px solid transparent;\n border-radius: calc(var(--stylo-radius) - 4px);\n background: none;\n color: var(--stylo-text-muted);\n font: inherit;\n cursor: pointer;\n}\n\n.iconButton {\n width: 22px;\n height: 22px;\n font-size: 0.8125rem;\n line-height: 1;\n}\n\n.textButton {\n padding: 3px 8px;\n font-size: 0.75rem;\n}\n\n.iconButton:hover:not(:disabled),\n.textButton:hover:not(:disabled) {\n background: color-mix(in srgb, var(--stylo-border) 45%, transparent);\n color: var(--stylo-text);\n}\n\n.iconButton:focus-visible,\n.textButton:focus-visible {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -1px;\n}\n\n.iconButton:disabled {\n opacity: 0.35;\n cursor: default;\n}\n\n.footer {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px;\n border-top: 1px solid var(--stylo-border);\n}\n\n.empty {\n padding: 8px 6px;\n font-size: 0.8125rem;\n color: var(--stylo-text-muted);\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n","import type { ReactNode } from \"react\"\nimport { useSortable } from \"@dnd-kit/sortable\"\nimport { CSS } from \"@dnd-kit/utilities\"\nimport styles from \"./StyloToolbarSettings.module.css\"\n\n/**\n * One draggable row in the \"On the bar\" list. The drag handle carries the\n * `@dnd-kit` listeners (pointer and keyboard), so the row's own action buttons\n * stay independently focusable and clickable.\n */\nexport function SortableRow({\n id,\n label,\n icon,\n position,\n count,\n actions,\n}: {\n id: string\n label: string\n icon: ReactNode\n position: number\n count: number\n actions: ReactNode\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id,\n })\n\n return (\n <li\n ref={setNodeRef}\n className={styles.row}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n data-dragging={isDragging || undefined}\n >\n <button\n type=\"button\"\n className={styles.handle}\n aria-label={`Reorder ${label}, position ${position} of ${count}`}\n {...attributes}\n {...listeners}\n >\n <span aria-hidden=\"true\">⠿</span>\n </button>\n <span className={styles.glyph} aria-hidden=\"true\">\n {icon}\n </span>\n <span className={styles.label}>{label}</span>\n <span className={styles.rowActions}>{actions}</span>\n </li>\n )\n}\n","import type { ReactNode } from \"react\"\nimport type { ToolbarCommandId, ToolbarItem } from \"../types\"\nimport { DEFAULT_ICONS } from \"../toolbar/icons\"\nimport { BUILTIN_LABELS } from \"../toolbar/labels\"\n\n/** The `\"|\"` separator slot. */\nexport const SEPARATOR = \"|\" as const\n\nexport function isSeparator(item: ToolbarItem): item is \"|\" {\n return item === SEPARATOR\n}\n\n/** Stable identity of a non-separator item; `null` for a separator. */\nexport function itemId(item: ToolbarItem): string | null {\n if (isSeparator(item)) return null\n return typeof item === \"string\" ? item : item.id\n}\n\n/** React key for a slot — separators fall back to their position. */\nexport function itemKey(item: ToolbarItem, index: number): string {\n return itemId(item) ?? `separator-${index}`\n}\n\ninterface Display {\n /** `null` for a separator. */\n id: string | null\n label: string\n icon: ReactNode\n}\n\n/** Icon + label for a slot, honouring a consumer `icons` override for built-ins. */\nexport function resolveDisplay(\n item: ToolbarItem,\n icons?: Partial<Record<ToolbarCommandId, ReactNode>>,\n): Display {\n if (isSeparator(item)) return { id: null, label: \"Separator\", icon: null }\n if (typeof item !== \"string\") return { id: item.id, label: item.title, icon: item.icon }\n return {\n id: item,\n label: BUILTIN_LABELS[item] ?? item,\n icon: icons?.[item] ?? DEFAULT_ICONS[item] ?? null,\n }\n}\n\n/** Palette entries not already on the bar (matched by id; separators excluded). */\nexport function availableNotOnBar(\n available: readonly ToolbarItem[],\n onBar: readonly ToolbarItem[],\n): ToolbarItem[] {\n const used = new Set(onBar.map(itemId).filter((id): id is string => id !== null))\n return available.filter((item) => {\n const id = itemId(item)\n return id !== null && !used.has(id)\n })\n}\n\nexport function move<T>(arr: readonly T[], from: number, to: number): T[] {\n if (to < 0 || to >= arr.length || from === to) return arr.slice()\n const next = arr.slice()\n const [picked] = next.splice(from, 1)\n next.splice(to, 0, picked as T)\n return next\n}\n\nexport function removeAt<T>(arr: readonly T[], index: number): T[] {\n const next = arr.slice()\n next.splice(index, 1)\n return next\n}\n\nexport function append<T>(arr: readonly T[], value: T): T[] {\n return [...arr, value]\n}\n","import { useId, useState } from \"react\"\nimport type { ReactNode } from \"react\"\nimport {\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\"\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\"\nimport type { ToolbarCommandId, ToolbarItem } from \"../types\"\nimport { DEFAULT_TOOLBAR_ITEMS } from \"../toolbar/config\"\nimport { ALL_BUILTIN_IDS } from \"../toolbar/labels\"\nimport styles from \"./StyloToolbarSettings.module.css\"\nimport { SortableRow } from \"./SortableRow\"\nimport {\n append,\n availableNotOnBar,\n itemKey,\n move,\n removeAt,\n resolveDisplay,\n SEPARATOR,\n} from \"./items\"\n\nexport interface StyloToolbarSettingsProps {\n /** The toolbar items — the same array passed to `<Stylo toolbar={{ items }}>`. */\n value: ToolbarItem[]\n /** Called with the next items array on every change. */\n onChange: (next: ToolbarItem[]) => void\n /**\n * Every item the user may pick from. Defaults to all built-in command ids;\n * pass a list to add `ToolbarCustomItem`s or to hold some built-ins back.\n */\n available?: ToolbarItem[]\n /** Per-id glyph overrides, matching `<Stylo icons>`. */\n icons?: Partial<Record<ToolbarCommandId, ReactNode>>\n /** Extra class on the root element. */\n className?: string\n}\n\n/**\n * A keyboard-accessible editor for the formatting bar's `items`. Controlled:\n * the host owns `value`, persists it, and feeds it to both this component and\n * `<Stylo>`.\n *\n * Reorder a row by dragging its ⠿ handle, or focus the handle and use\n * Space + Arrow keys (`@dnd-kit`'s keyboard sensor). The ✕ / Add buttons move\n * items between the two lists. `@dnd-kit/core`, `/sortable`, and `/utilities`\n * are optional peer dependencies of this entry point.\n */\nexport function StyloToolbarSettings({\n value,\n onChange,\n available,\n icons,\n className,\n}: StyloToolbarSettingsProps) {\n const barHeadId = useId()\n const availHeadId = useId()\n const [message, setMessage] = useState(\"\")\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),\n )\n\n const paletteItems = availableNotOnBar(available ?? ALL_BUILTIN_IDS, value)\n const barIds = value.map((_, i) => String(i))\n\n function onDragEnd({ active, over }: DragEndEvent) {\n if (!over || active.id === over.id) return\n const from = Number(active.id)\n const to = Number(over.id)\n const label = resolveDisplay(value[from]!, icons).label\n onChange(move(value, from, to))\n setMessage(`${label} moved to position ${to + 1} of ${value.length}`)\n }\n\n function removeSlot(index: number) {\n const label = resolveDisplay(value[index]!, icons).label\n onChange(removeAt(value, index))\n setMessage(`${label} removed from the bar`)\n }\n\n function add(item: ToolbarItem) {\n onChange(append(value, item))\n setMessage(`${resolveDisplay(item, icons).label} added to the bar`)\n }\n\n function reset() {\n onChange([...DEFAULT_TOOLBAR_ITEMS])\n setMessage(\"Toolbar reset to the default set\")\n }\n\n const dragAnnounce = (id: string | number, verb: string) =>\n `${resolveDisplay(value[Number(id)]!, icons).label} ${verb}`\n\n return (\n <div className={[styles.root, className].filter(Boolean).join(\" \")}>\n <section className={styles.col}>\n <h3 className={styles.colHead} id={barHeadId}>\n On the bar\n </h3>\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={onDragEnd}\n accessibility={{\n announcements: {\n onDragStart: ({ active }) => dragAnnounce(active.id, \"picked up\"),\n onDragOver: ({ active, over }) =>\n over ? `${dragAnnounce(active.id, \"is over position\")} ${Number(over.id) + 1}` : \"\",\n onDragEnd: ({ active, over }) =>\n over\n ? `${dragAnnounce(active.id, \"dropped at position\")} ${Number(over.id) + 1}`\n : dragAnnounce(active.id, \"dropped\"),\n onDragCancel: ({ active }) => dragAnnounce(active.id, \"drag cancelled\"),\n },\n }}\n >\n <SortableContext items={barIds} strategy={verticalListSortingStrategy}>\n <ul className={styles.list} aria-labelledby={barHeadId}>\n {value.map((item, i) => {\n const { icon, label } = resolveDisplay(item, icons)\n return (\n <SortableRow\n key={itemKey(item, i)}\n id={String(i)}\n label={label}\n icon={icon}\n position={i + 1}\n count={value.length}\n actions={\n <button\n type=\"button\"\n className={styles.iconButton}\n title=\"Remove\"\n aria-label={`Remove ${label} from the bar`}\n onClick={() => removeSlot(i)}\n >\n ✕\n </button>\n }\n />\n )\n })}\n </ul>\n </SortableContext>\n </DndContext>\n <div className={styles.footer}>\n <button type=\"button\" className={styles.textButton} onClick={() => add(SEPARATOR)}>\n Add separator\n </button>\n <button type=\"button\" className={styles.textButton} onClick={reset}>\n Reset to default\n </button>\n </div>\n </section>\n\n <section className={styles.col}>\n <h3 className={styles.colHead} id={availHeadId}>\n Available\n </h3>\n <ul className={styles.list} aria-labelledby={availHeadId}>\n {paletteItems.length === 0 && (\n <li className={styles.empty}>Every button is on the bar.</li>\n )}\n {paletteItems.map((item, i) => {\n const { icon, label } = resolveDisplay(item, icons)\n return (\n <li key={itemKey(item, i)} className={styles.row}>\n <span className={styles.glyph} aria-hidden=\"true\">\n {icon}\n </span>\n <span className={styles.label}>{label}</span>\n <span className={styles.rowActions}>\n <button\n type=\"button\"\n className={styles.textButton}\n aria-label={`Add ${label} to the bar`}\n onClick={() => add(item)}\n >\n Add\n </button>\n </span>\n </li>\n )\n })}\n </ul>\n </section>\n\n <div aria-live=\"polite\" className={styles.srOnly}>\n {message}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,264 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Language, LanguageDescription } from "@codemirror/language";
3
+ import type { EditorState } from "@codemirror/state";
4
+ import type { EditorView } from "@codemirror/view";
5
+ export type StyloMode = "in-place" | "source" | "preview" | "split";
6
+ /**
7
+ * How `preview` (and the preview pane of `split`) treats the leading `---` YAML
8
+ * block. `"hidden"` (default) drops it from the render; `"code"` renders it as a
9
+ * styled `<pre class="stylo-frontmatter">` a consumer can restyle with its own
10
+ * CSS. A parsed key/value panel is deferred (ADR-001, needs a YAML parser).
11
+ */
12
+ export type FrontmatterDisplay = "hidden" | "code";
13
+ /**
14
+ * Built-in toolbar command identifiers. In a `ToolbarConfig["items"]` list,
15
+ * `"|"` inserts a visual separator. See ADR-002 §2.
16
+ */
17
+ export type ToolbarCommandId = "undo" | "redo" | "save" | "search" | "h1" | "h2" | "h3" | "body" | "bold" | "italic" | "strike" | "underline" | "code" | "codeBlock" | "link" | "wikilink" | "quote" | "bulletList" | "orderedList" | "task" | "hr" | "frontmatter" | "table" | "math" | "mathBlock";
18
+ /**
19
+ * A consumer-supplied toolbar button. Mixed into `ToolbarConfig["items"]`
20
+ * alongside the built-in ids. It runs against the same live `EditorView` the
21
+ * built-ins do; `isActive` / `disabled` are read back from the state on every
22
+ * selection, key, and pointer change, exactly like a built-in.
23
+ *
24
+ * No `keys` field: built-in shortcuts are compiled into CodeMirror's keymap at
25
+ * editor construction, so a custom binding would need its own keymap. Bind it
26
+ * yourself against `getView()` for now.
27
+ */
28
+ export interface ToolbarCustomItem {
29
+ /**
30
+ * Stable identity, also the React key. Must not collide with a built-in id
31
+ * (`bold`, `h1`, …) or another custom item.
32
+ */
33
+ id: string;
34
+ /** Tooltip and accessible label. */
35
+ title: string;
36
+ /** Button content — an inline SVG, a glyph, a short label. */
37
+ icon: ReactNode;
38
+ /** Run against the live view. The return value is ignored. */
39
+ run: (view: EditorView) => void;
40
+ /** Reflected as the button's pressed state (`aria-pressed`, `data-active`). */
41
+ isActive?: (state: EditorState) => boolean;
42
+ /** When true, the button is rendered `disabled`. */
43
+ disabled?: (state: EditorState) => boolean;
44
+ }
45
+ /** One rendered slot: a built-in id, a `"|"` separator, or a custom button. */
46
+ export type ToolbarItem = ToolbarCommandId | "|" | ToolbarCustomItem;
47
+ export interface ToolbarConfig {
48
+ /**
49
+ * Ordered toolbar slots — built-in command ids, `"|"` separators, and
50
+ * {@link ToolbarCustomItem} objects, in any order. Omit for the full default
51
+ * bar.
52
+ */
53
+ items?: ToolbarItem[];
54
+ /**
55
+ * Wrap or replace the rendered bar. `bar` is the built-in
56
+ * `<div role="toolbar">` element; return it wrapped, with extra chrome
57
+ * appended, or ignore it entirely and return your own. `view` is `null` until
58
+ * the surface has mounted.
59
+ */
60
+ render?: (bar: ReactNode, ctx: {
61
+ view: EditorView | null;
62
+ }) => ReactNode;
63
+ /**
64
+ * Fix the bar to an edge of the **window** instead of wherever `<Stylo>`
65
+ * sits on the page. `"bottom"` (or `true`) rides above the on-screen
66
+ * keyboard, tracked via the `visualViewport` API; `"top"` pins to the top
67
+ * edge, which needs no keyboard tracking and can't be covered by it or by a
68
+ * platform's own input accessory bar. Off (`false`, the default) is right
69
+ * for a small embedded field; a host opts in deliberately for a
70
+ * full-screen editor. See the toolbar reference's "On touch" section.
71
+ */
72
+ sticky?: boolean | "top" | "bottom";
73
+ /**
74
+ * When `sticky` is set, whether the bar stays on screen the whole time
75
+ * (`"consistent"`, the default) or only while the editing surface actually
76
+ * has focus (`"dynamic"`) — faded out otherwise, so it doesn't sit over the
77
+ * content while the caret is elsewhere. Ignored when `sticky` is off.
78
+ */
79
+ stickyVisibility?: "consistent" | "dynamic";
80
+ }
81
+ /**
82
+ * Grammars for fenced-code sub-highlighting, forwarded verbatim to
83
+ * `@codemirror/lang-markdown`. Stylo ships none by default — a consumer opts in
84
+ * with exactly the set they want (`codeLanguages={languages}` from
85
+ * `@codemirror/language-data`, or a hand-built list). Affects the CodeMirror
86
+ * surfaces only (`source`, `split`, `in-place`); `preview` is a separate
87
+ * pipeline. See the ADR-001 amendment.
88
+ */
89
+ export type CodeLanguages = readonly LanguageDescription[] | ((info: string) => Language | LanguageDescription | null);
90
+ /**
91
+ * Per-construct on/off switches for the in-place canvas. Each key defaults to
92
+ * `true`; setting one `false` leaves that construct as plain source — no
93
+ * decoration, no cursor-reveal behaviour. See ADR-005.
94
+ */
95
+ export interface InPlaceDecorationToggles {
96
+ headings?: boolean;
97
+ emphasis?: boolean;
98
+ links?: boolean;
99
+ wikilinks?: boolean;
100
+ math?: boolean;
101
+ lists?: boolean;
102
+ tasks?: boolean;
103
+ blockquote?: boolean;
104
+ horizontalRule?: boolean;
105
+ code?: boolean;
106
+ frontmatter?: boolean;
107
+ tables?: boolean;
108
+ }
109
+ /**
110
+ * How the in-place canvas handles editing a table.
111
+ * `"source"` (default) reveals the aligned pipe source under the caret;
112
+ * `"cells"` keeps the rendered `<table>` and edits its cells in place.
113
+ */
114
+ export type TableEditing = "source" | "cells";
115
+ /**
116
+ * Whether the in-place canvas shows a construct's Markdown markers when the
117
+ * caret is on its line. `"caret"` (default) reveals them for editing and
118
+ * re-hides them on the way out — Obsidian's Live Preview. `"never"` keeps every
119
+ * inline marker hidden at all times; formatting is changed through the toolbar,
120
+ * the right-click menu, shortcuts, and autoformat-on-type instead. See ADR-007;
121
+ * `"never"` is being rolled out in stages.
122
+ */
123
+ export type RevealMode = "caret" | "never";
124
+ /**
125
+ * What appears when text is selected in the in-place canvas. `"menu"` (default)
126
+ * puts the inline-formatting group in the right-click menu and shows no floating
127
+ * bar; `"bar"` shows a floating bar above the selection and drops that group
128
+ * from the menu so nothing is doubled; `"none"` shows neither and leaves the
129
+ * main toolbar as the only formatting surface. The toolbar is independent of
130
+ * this setting — it is always available (unless hidden via `toolbar`) and always
131
+ * acts on the selection.
132
+ */
133
+ export type SelectionUI = "menu" | "bar" | "none";
134
+ /**
135
+ * The right-click menu's top-level groups. `link` is the internal / external
136
+ * link field rows; `format` the inline-mark submenu; `paragraph` the block-type
137
+ * submenu; `insert` the new-block submenu; `clipboard` cut / copy / paste.
138
+ */
139
+ export type MenuGroupId = "link" | "format" | "paragraph" | "insert" | "clipboard";
140
+ export interface ContextMenuConfig {
141
+ /**
142
+ * Which top-level groups the menu shows, in order. Omit for all five in their
143
+ * default order. `link` and `format` still yield to `selectionUI` when it is
144
+ * not `"menu"` (they move to the floating bar / toolbar).
145
+ */
146
+ groups?: MenuGroupId[];
147
+ }
148
+ export interface InPlaceConfig {
149
+ /** Which decoration types the in-place canvas renders. Read once, at mount. */
150
+ decorations?: InPlaceDecorationToggles;
151
+ /** Table editing mode (see `TableEditing`). Read once, at mount. */
152
+ table?: TableEditing;
153
+ /**
154
+ * Marker reveal behaviour (see `RevealMode`). Optional, defaults to
155
+ * `"caret"`. Read once, at mount.
156
+ */
157
+ reveal?: RevealMode;
158
+ /**
159
+ * Right-click a block for a context menu (inline actions on a selection,
160
+ * block + insert actions otherwise). `false` keeps the browser's own menu; an
161
+ * object picks and orders the menu's groups. Defaults to `true`. Read once,
162
+ * at mount.
163
+ */
164
+ contextMenu?: boolean | ContextMenuConfig;
165
+ /**
166
+ * What a non-empty selection offers (see `SelectionUI`). Defaults to
167
+ * `"menu"`. Read once, at mount.
168
+ */
169
+ selectionUI?: SelectionUI;
170
+ /**
171
+ * Which buttons the floating selection bar shows (`selectionUI: "bar"`), in
172
+ * order. Any of `bold` / `italic` / `strike` / `code` / `link` / `wikilink` /
173
+ * `math`. Omit for all seven. Read once, at mount.
174
+ */
175
+ selectionBarItems?: ToolbarCommandId[];
176
+ }
177
+ export interface StyloProps {
178
+ /** The canonical Markdown document. Stylo never holds a parsed model of it. */
179
+ value: string;
180
+ /** Called with the complete Markdown string on every edit. */
181
+ onChange: (next: string) => void;
182
+ /**
183
+ * Interaction layout. Defaults to `"in-place"` — the live decoration canvas.
184
+ * `"source"` is the plain surface and avoids loading the render chunk.
185
+ */
186
+ mode?: StyloMode;
187
+ /**
188
+ * Called with the full Markdown string when `Mod-s` is pressed on any editing
189
+ * surface; the browser's own save dialog is then suppressed. Omit it and
190
+ * `Mod-s` keeps its default browser behaviour. Stylo holds no dirty state —
191
+ * `value` is yours, so compare it against your last-saved copy.
192
+ */
193
+ onSave?: (value: string) => void;
194
+ /**
195
+ * Called on mount and whenever the leading `---` YAML block changes, with its
196
+ * inner text (no fences), or `null` when there is no block. Stylo does not
197
+ * parse it — pass `raw` to your own YAML parser for a structured panel. The
198
+ * same split is available synchronously as the exported `splitFrontmatter`.
199
+ */
200
+ onFrontmatter?: (raw: string | null) => void;
201
+ /** Invoked when a `[[wikilink]]` is activated in the preview or in-place canvas. */
202
+ onWikiLinkClick?: (target: string) => void;
203
+ /**
204
+ * Invoked by the in-place link editor's "Open link" action with the link's
205
+ * `href`. Stylo does not navigate on its own.
206
+ */
207
+ onLinkClick?: (href: string) => void;
208
+ /** Configures the in-place canvas (ADR-005). Applied when it mounts. */
209
+ inPlace?: InPlaceConfig;
210
+ /**
211
+ * How `preview` (and `split`'s preview pane) shows the leading `---` YAML
212
+ * block. `"hidden"` (default) drops it; `"code"` renders it as a styled
213
+ * `<pre class="stylo-frontmatter">`.
214
+ */
215
+ frontmatter?: FrontmatterDisplay;
216
+ /**
217
+ * Grammars for fenced-code sub-highlighting on the CodeMirror surfaces
218
+ * (`source`, `split`, `in-place`). None by default. Read once, at mount.
219
+ */
220
+ codeLanguages?: CodeLanguages;
221
+ /**
222
+ * Formatting toolbar above the editing surface (`source`, `in-place`,
223
+ * `split`; never `preview`). Omit or `true` for the default bar, `false` to
224
+ * hide it, or an object to choose and order the buttons. See ADR-002 §2.
225
+ */
226
+ toolbar?: boolean | ToolbarConfig;
227
+ /**
228
+ * Replace individual toolbar glyphs, keyed by command id. Any id left out
229
+ * keeps its built-in inline-SVG icon — Stylo ships no icon dependency.
230
+ */
231
+ icons?: Partial<Record<ToolbarCommandId, ReactNode>>;
232
+ /** Render the source surface read-only. */
233
+ readOnly?: boolean;
234
+ /** Placeholder text shown when the document is empty (source surface). */
235
+ placeholder?: string;
236
+ /** Extra class on the root element, alongside the internal classes. */
237
+ className?: string;
238
+ }
239
+ /**
240
+ * Imperative handle exposed on a `ref` to `<Stylo>`. Every method is a no-op —
241
+ * returning `null` / `false` where it has a return value — in `preview` mode or
242
+ * before the editing surface has mounted, since there is no editor then.
243
+ */
244
+ export interface StyloHandle {
245
+ /** Move keyboard focus into the editing surface. */
246
+ focus(): void;
247
+ /**
248
+ * Put the caret at the start of the first ATX heading (`#` … `######`) whose
249
+ * text matches `text` (trimmed, case-insensitive) and scroll it to the top of
250
+ * the viewport. Returns `true` when a heading matched.
251
+ */
252
+ scrollToHeading(text: string): boolean;
253
+ /**
254
+ * Replace the current selection — or insert at the caret when the selection is
255
+ * empty — with `md`. No effect on a `readOnly` surface.
256
+ */
257
+ insertAtCursor(md: string): void;
258
+ /**
259
+ * The underlying CodeMirror `EditorView`, or `null` in `preview` mode or
260
+ * before mount. An escape hatch: not covered by semver.
261
+ */
262
+ getView(): EditorView | null;
263
+ }
264
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;AAEnE;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,CAAA;AAElD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,MAAM,GACN,MAAM,GACN,QAAQ,GACR,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,GACV,OAAO,GACP,YAAY,GACZ,aAAa,GACb,MAAM,GACN,IAAI,GACJ,aAAa,GACb,OAAO,GACP,MAAM,GACN,WAAW,CAAA;AAEf;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAA;IACV,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,IAAI,EAAE,SAAS,CAAA;IACf,8DAA8D;IAC9D,GAAG,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC1C,oDAAoD;IACpD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;CAC3C;AAED,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,GAAG,GAAG,iBAAiB,CAAA;AAEpE,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;IACxE;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAA;IACnC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAC5C;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACvB,SAAS,mBAAmB,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,GAAG,mBAAmB,GAAG,IAAI,CAAC,CAAA;AAE5F;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE7C;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,CAAA;AAE1C;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;AAEjD;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAA;AAElF,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,wBAAwB,CAAA;IACtC,oEAAoE;IACpE,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAA;IACzC;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC5C,oFAAoF;IACpF,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,aAAa,CAAA;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAA;IACpD,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,KAAK,IAAI,IAAI,CAAA;IACb;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACtC;;;OAGG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC;;;OAGG;IACH,OAAO,IAAI,UAAU,GAAG,IAAI,CAAA;CAC7B"}