@signal9/era-ui 7.0.0 → 9.0.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 (226) hide show
  1. package/dist/ai/artifact/artifact-close.svelte +1 -1
  2. package/dist/ai/artifact/artifact-content.svelte +1 -1
  3. package/dist/ai/artifact/artifact-header.svelte +1 -1
  4. package/dist/ai/artifact/artifact.svelte +1 -1
  5. package/dist/ai/chain-of-thought/chain-of-thought-step.svelte +1 -1
  6. package/dist/ai/chain-of-thought/chain-of-thought.svelte +1 -1
  7. package/dist/ai/checkpoint.svelte +1 -1
  8. package/dist/ai/confirmation/confirmation-args.svelte +2 -2
  9. package/dist/ai/confirmation/confirmation.svelte +4 -4
  10. package/dist/ai/context/context.svelte +1 -1
  11. package/dist/ai/conversation/conversation-content.svelte +1 -1
  12. package/dist/ai/conversation/conversation-empty-state.svelte +1 -1
  13. package/dist/ai/conversation/conversation-scroll-button.svelte +2 -2
  14. package/dist/ai/conversations/conversations-group.svelte +1 -1
  15. package/dist/ai/conversations/conversations-item.svelte +7 -7
  16. package/dist/ai/error-panel/error-panel.svelte +4 -4
  17. package/dist/ai/image.svelte +1 -1
  18. package/dist/ai/inline-citation/inline-citation.svelte +2 -2
  19. package/dist/ai/loader.svelte +1 -1
  20. package/dist/ai/message/message-branch-selector.svelte +3 -3
  21. package/dist/ai/message/message-content.svelte +1 -1
  22. package/dist/ai/message/message-usage.svelte +4 -4
  23. package/dist/ai/model-selector/model-selector.svelte +1 -1
  24. package/dist/ai/open-in-chat/open-in-chat.svelte +2 -2
  25. package/dist/ai/plan/plan-content.svelte +1 -1
  26. package/dist/ai/plan/plan-header.svelte +2 -2
  27. package/dist/ai/plan/plan.svelte +1 -1
  28. package/dist/ai/prompt-input/prompt-input-add-attachments.svelte +1 -1
  29. package/dist/ai/prompt-input/prompt-input-attachments.svelte +5 -5
  30. package/dist/ai/prompt-input/prompt-input-submit.svelte +3 -3
  31. package/dist/ai/prompt-input/prompt-input-textarea.svelte +3 -3
  32. package/dist/ai/prompt-input/prompt-input.svelte +1 -1
  33. package/dist/ai/queue/queue-item.svelte +1 -1
  34. package/dist/ai/queue/queue.svelte +1 -1
  35. package/dist/ai/reasoning/reasoning-trigger.svelte +1 -1
  36. package/dist/ai/response/response.svelte +2 -2
  37. package/dist/ai/run-status/run-status.svelte +5 -5
  38. package/dist/ai/runtime-feed/runtime-feed-item.svelte +1 -1
  39. package/dist/ai/sources/source.svelte +1 -1
  40. package/dist/ai/sources/sources-trigger.svelte +1 -1
  41. package/dist/ai/structured-value/structured-value.svelte +1 -1
  42. package/dist/ai/suggestion/suggestion.svelte +2 -2
  43. package/dist/ai/swarm/swarm-agent.svelte +1 -1
  44. package/dist/ai/swarm/swarm-artifact.svelte +1 -1
  45. package/dist/ai/swarm/swarm-barrier.svelte +1 -1
  46. package/dist/ai/swarm/swarm-barriers.svelte +1 -1
  47. package/dist/ai/swarm/swarm-counts.svelte +1 -1
  48. package/dist/ai/swarm/swarm-footer.svelte +1 -1
  49. package/dist/ai/swarm/swarm-grid.svelte +2 -2
  50. package/dist/ai/swarm/swarm-header.svelte +1 -1
  51. package/dist/ai/swarm/swarm-node.svelte +7 -7
  52. package/dist/ai/swarm/swarm-role.svelte +1 -1
  53. package/dist/ai/swarm/swarm-root.svelte +1 -1
  54. package/dist/ai/swarm/swarm-sandbox.svelte +3 -3
  55. package/dist/ai/swarm/swarm-tree.svelte +1 -1
  56. package/dist/ai/task/task-content.svelte +1 -1
  57. package/dist/ai/task/task-trigger.svelte +1 -1
  58. package/dist/ai/tool/tool-chip.svelte +2 -2
  59. package/dist/ai/tool/tool-exec.svelte +3 -3
  60. package/dist/ai/tool/tool-header.svelte +1 -1
  61. package/dist/ai/web-preview/web-preview.svelte +3 -3
  62. package/dist/ai/workflow/canvas.svelte +1 -1
  63. package/dist/ai/workflow/node.svelte +3 -3
  64. package/dist/apps/llm-shell/llm-shell.svelte +7 -7
  65. package/dist/apps/notes/editor/slash-menu.svelte +7 -5
  66. package/dist/apps/notes/note-editor.svelte +7 -364
  67. package/dist/apps/notes/note-editor.svelte.d.ts +1 -0
  68. package/dist/apps/notes/notes.svelte +9 -9
  69. package/dist/dev/audit/audits/_helpers.js +1 -1
  70. package/dist/dev/audit/audits/resting-gap.js +1 -1
  71. package/dist/dev/audit/audits/single-glyph-square.js +2 -2
  72. package/dist/dev/audit-overlay.svelte +7 -7
  73. package/dist/dev/measure.d.ts +1 -1
  74. package/dist/dev/measure.js +1 -1
  75. package/dist/docs/badge.md +1 -1
  76. package/dist/docs/css-utilities.d.ts +1 -1
  77. package/dist/docs/css-utilities.js +8 -8
  78. package/dist/docs/llms-txt.js +1 -1
  79. package/dist/era-ui.css +1 -1
  80. package/dist/generated-docs/badge.md +1 -1
  81. package/dist/generated-docs/bar.md +2 -2
  82. package/dist/generated-docs/chip.md +1 -1
  83. package/dist/generated-docs/input.md +1 -1
  84. package/dist/generated-docs/llms-full.txt +100 -120
  85. package/dist/generated-docs/llms.txt +12 -13
  86. package/dist/generated-docs/manifest.json +52 -65
  87. package/dist/generated-docs/utilities.json +45 -57
  88. package/dist/generated-docs/utilities.md +87 -106
  89. package/dist/os/notification-center.svelte +6 -6
  90. package/dist/os/pane.svelte +7 -5
  91. package/dist/os/taskbar.svelte +10 -10
  92. package/dist/os/toast.svelte +3 -3
  93. package/dist/os/toaster.svelte +1 -1
  94. package/dist/styles/density.css +93 -67
  95. package/dist/styles/index.css +89 -101
  96. package/dist/styles/prose.css +384 -0
  97. package/dist/styles/surfaces/base.css +3 -3
  98. package/dist/styles/surfaces/bevel.css +2 -2
  99. package/dist/ui/accordion/accordion-trigger.svelte +2 -2
  100. package/dist/ui/alert-dialog/alert-dialog-content.svelte +1 -1
  101. package/dist/ui/aspect-ratio/aspect-ratio.svelte +1 -1
  102. package/dist/ui/avatar/avatar-root.svelte +1 -1
  103. package/dist/ui/badge/badge.svelte +1 -1
  104. package/dist/ui/badge/badge.svelte.d.ts +1 -1
  105. package/dist/ui/bar/bar.svelte +23 -15
  106. package/dist/ui/bar/bar.svelte.d.ts +26 -26
  107. package/dist/ui/button/button.svelte +1 -1
  108. package/dist/ui/button/variants.js +18 -18
  109. package/dist/ui/button-group/button-group.svelte +2 -2
  110. package/dist/ui/calendar/calendar-day.svelte +1 -1
  111. package/dist/ui/calendar/calendar-head-cell.svelte +1 -1
  112. package/dist/ui/calendar/calendar-header.svelte +1 -1
  113. package/dist/ui/calendar/calendar-next-button.svelte +1 -1
  114. package/dist/ui/calendar/calendar-prev-button.svelte +1 -1
  115. package/dist/ui/card/card.svelte +5 -5
  116. package/dist/ui/card/card.svelte.d.ts +4 -4
  117. package/dist/ui/checkbox/checkbox.svelte +3 -3
  118. package/dist/ui/chip/chip.svelte +14 -10
  119. package/dist/ui/chip/chip.svelte.d.ts +7 -7
  120. package/dist/ui/code-block/code-block.svelte +6 -6
  121. package/dist/ui/collapsible/collapsible-trigger.svelte +1 -1
  122. package/dist/ui/combobox/combobox-content.svelte +1 -1
  123. package/dist/ui/combobox/combobox-empty.svelte +4 -1
  124. package/dist/ui/combobox/combobox-group-heading.svelte +4 -1
  125. package/dist/ui/combobox/combobox-item.svelte +1 -1
  126. package/dist/ui/combobox/combobox-trigger.svelte +2 -2
  127. package/dist/ui/command/command-group-heading.svelte +4 -1
  128. package/dist/ui/command/command-item.svelte +1 -1
  129. package/dist/ui/command/command-link-item.svelte +1 -1
  130. package/dist/ui/command/command-root.svelte +1 -1
  131. package/dist/ui/command-bar/command-bar.svelte +16 -12
  132. package/dist/ui/context-menu/context-menu-checkbox-item.svelte +1 -1
  133. package/dist/ui/context-menu/context-menu-content.svelte +1 -1
  134. package/dist/ui/context-menu/context-menu-group-heading.svelte +4 -1
  135. package/dist/ui/context-menu/context-menu-item.svelte +1 -1
  136. package/dist/ui/context-menu/context-menu-radio-item.svelte +1 -1
  137. package/dist/ui/context-menu/context-menu-sub-content.svelte +1 -1
  138. package/dist/ui/context-menu/context-menu-sub-trigger.svelte +2 -2
  139. package/dist/ui/copy-button/copy-button.svelte +2 -2
  140. package/dist/ui/cycle/cycle.svelte +1 -1
  141. package/dist/ui/date-field/date-field-segment.svelte +1 -1
  142. package/dist/ui/date-picker/date-picker-content.svelte +1 -1
  143. package/dist/ui/date-picker/date-picker-day.svelte +1 -1
  144. package/dist/ui/date-picker/date-picker-head-cell.svelte +1 -1
  145. package/dist/ui/date-picker/date-picker-header.svelte +1 -1
  146. package/dist/ui/date-picker/date-picker-next-button.svelte +1 -1
  147. package/dist/ui/date-picker/date-picker-prev-button.svelte +1 -1
  148. package/dist/ui/date-picker/date-picker-segment.svelte +1 -1
  149. package/dist/ui/date-picker/date-picker-trigger.svelte +2 -2
  150. package/dist/ui/date-range-field/date-range-field-segment.svelte +1 -1
  151. package/dist/ui/date-range-picker/date-range-picker-content.svelte +1 -1
  152. package/dist/ui/date-range-picker/date-range-picker-day.svelte +1 -1
  153. package/dist/ui/date-range-picker/date-range-picker-head-cell.svelte +1 -1
  154. package/dist/ui/date-range-picker/date-range-picker-header.svelte +1 -1
  155. package/dist/ui/date-range-picker/date-range-picker-next-button.svelte +1 -1
  156. package/dist/ui/date-range-picker/date-range-picker-prev-button.svelte +1 -1
  157. package/dist/ui/date-range-picker/date-range-picker-segment.svelte +1 -1
  158. package/dist/ui/date-range-picker/date-range-picker-trigger.svelte +2 -2
  159. package/dist/ui/dialog/dialog-content.svelte +4 -2
  160. package/dist/ui/dialog/dialog-header.svelte +2 -2
  161. package/dist/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +1 -1
  162. package/dist/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  163. package/dist/ui/dropdown-menu/dropdown-menu-group-heading.svelte +4 -1
  164. package/dist/ui/dropdown-menu/dropdown-menu-item.svelte +1 -1
  165. package/dist/ui/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  166. package/dist/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  167. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
  168. package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte +2 -2
  169. package/dist/ui/file-upload/file-upload.svelte +2 -2
  170. package/dist/ui/input/input.svelte +3 -3
  171. package/dist/ui/input/input.svelte.d.ts +1 -1
  172. package/dist/ui/input/textarea.svelte +1 -1
  173. package/dist/ui/input/variants.d.ts +24 -24
  174. package/dist/ui/input/variants.js +9 -9
  175. package/dist/ui/kv/kv.svelte +2 -2
  176. package/dist/ui/link-preview/link-preview-content.svelte +1 -1
  177. package/dist/ui/menubar/menubar-checkbox-item.svelte +1 -1
  178. package/dist/ui/menubar/menubar-content.svelte +1 -1
  179. package/dist/ui/menubar/menubar-group-heading.svelte +4 -1
  180. package/dist/ui/menubar/menubar-item.svelte +1 -1
  181. package/dist/ui/menubar/menubar-radio-item.svelte +1 -1
  182. package/dist/ui/menubar/menubar-root.svelte +1 -1
  183. package/dist/ui/menubar/menubar-sub-content.svelte +1 -1
  184. package/dist/ui/menubar/menubar-sub-trigger.svelte +2 -2
  185. package/dist/ui/menubar/menubar-trigger.svelte +1 -1
  186. package/dist/ui/meter/meter.svelte +1 -1
  187. package/dist/ui/pagination/pagination-next-button.svelte +1 -1
  188. package/dist/ui/pagination/pagination-prev-button.svelte +1 -1
  189. package/dist/ui/pane/pane-close.svelte +2 -2
  190. package/dist/ui/pane/pane-content.svelte +1 -1
  191. package/dist/ui/pane/pane-handle.svelte +3 -3
  192. package/dist/ui/pane/pane-root.svelte +12 -12
  193. package/dist/ui/pane/pane-tab-list.svelte +1 -1
  194. package/dist/ui/pane/pane-tab-panel.svelte +1 -1
  195. package/dist/ui/pane/pane-tab.svelte +1 -1
  196. package/dist/ui/pane/pane.svelte +1 -1
  197. package/dist/ui/pin-input/pin-input-cell.svelte +1 -1
  198. package/dist/ui/popover/popover-content.svelte +1 -1
  199. package/dist/ui/progress/progress.svelte +1 -1
  200. package/dist/ui/radio-group/radio-group-item.svelte +2 -2
  201. package/dist/ui/rating-group/rating-group-item.svelte +1 -1
  202. package/dist/ui/scroll-area/scroll-area-thumb.svelte +1 -1
  203. package/dist/ui/scroll-area/scroll-area.svelte +1 -1
  204. package/dist/ui/select/select-content.svelte +1 -1
  205. package/dist/ui/select/select-group-heading.svelte +4 -1
  206. package/dist/ui/select/select-item.svelte +1 -1
  207. package/dist/ui/select/select-trigger.svelte +2 -2
  208. package/dist/ui/select/select-value.svelte +1 -1
  209. package/dist/ui/sheet/sheet-content.svelte +3 -3
  210. package/dist/ui/sheet/sheet-content.svelte.d.ts +6 -6
  211. package/dist/ui/skeleton/skeleton.svelte +3 -3
  212. package/dist/ui/skeleton/skeleton.svelte.d.ts +9 -9
  213. package/dist/ui/slider/slider-range.svelte +1 -1
  214. package/dist/ui/slider/slider-thumb.svelte +1 -1
  215. package/dist/ui/step/step-content.svelte +1 -1
  216. package/dist/ui/step/step-summary.svelte +6 -6
  217. package/dist/ui/switch/switch.svelte +3 -3
  218. package/dist/ui/table/table-cell.svelte +1 -1
  219. package/dist/ui/table/table-head-cell.svelte +1 -1
  220. package/dist/ui/time-field/time-field-segment.svelte +1 -1
  221. package/dist/ui/time-range-field/time-range-field-segment.svelte +1 -1
  222. package/dist/ui/toggle-group/toggle-group-item.svelte +1 -1
  223. package/dist/ui/tooltip/tooltip-content.svelte +1 -1
  224. package/dist/ui/video-player/video-player.svelte +44 -44
  225. package/dist/utils/index.js +4 -4
  226. package/package.json +2 -1
@@ -18,6 +18,9 @@
18
18
  import { untrack } from 'svelte';
19
19
  import { Editor, type JSONContent } from '@tiptap/core';
20
20
  import { noteExtensions } from './editor/extensions.js';
21
+ // Side-effect import: mounting the editor should not require the consumer to
22
+ // remember a stylesheet. Also published as `@signal9/era-ui/styles/prose`.
23
+ import '../../styles/prose.css';
21
24
 
22
25
  interface Props {
23
26
  /** Initial document. Later changes are ignored — re-key to reseed. */
@@ -167,367 +170,7 @@
167
170
  <!-- eslint-disable better-tailwindcss/no-unknown-classes -- era-notes-prose is defined in this component's scoped stylesheet -->
168
171
  <div class="era-notes-prose min-w-0 {className ?? ''}" {@attach initEditor}></div>
169
172
 
170
- <style>
171
- /*
172
- * TipTap renders headless: the editable element it creates carries `.tiptap`,
173
- * so every rule here is scoped to that inside this component's wrapper.
174
- *
175
- * Vertical rhythm is ONE value — --era-gap, the library's inter-element gap —
176
- * on every block's bottom margin. A document then breathes at exactly the
177
- * pace the surrounding chrome does, and loosens with density along with it.
178
- *
179
- * Font family is deliberately absent: the [data-font] axis sets it globally
180
- * (with !important, by design), so anything declared here would either lose
181
- * or break the axis promise.
182
- */
183
- .era-notes-prose :global(.tiptap) {
184
- outline: none;
185
- min-height: 100%;
186
- font-size: var(--era-text);
187
- line-height: 1.6;
188
- color: var(--color-fg);
189
-
190
- /*
191
- * The first line's half-leading is not padding, but it reads as padding.
192
- *
193
- * line-height 1.6 puts ~8px of empty box above the first glyph's cap, on
194
- * top of the container's 8px inset — so the document opened 16px from the
195
- * top and 8px from the left, an asymmetry that grows with the first
196
- * block's font size (a note starting with a heading was the worst case).
197
- *
198
- * Trimming the block-start to the cap edge makes the ink itself sit on the
199
- * container's inset, so the first thing you read has the same space above
200
- * it as beside it, whatever block it happens to be. This is the block half
201
- * of what era-text-trim does for single-line controls; only the START is
202
- * trimmed, because the editor scrolls and trimming the end would put the
203
- * last line's descenders past the scrollable area.
204
- *
205
- * Firefox has no text-box yet and keeps the untrimmed leading — the same
206
- * graceful degradation era-text-trim already ships with.
207
- */
208
- text-box-trim: trim-start;
209
- text-box-edge: cap alphabetic;
210
- }
211
-
212
- /* The optical half of the trim. cap trimming is EXACT — the cap sits on the
213
- * container inset to the pixel — but the LEFT side isn't: glyphs start with
214
- * their side bearing (~0.07em of ink-free space inside the line box), so a
215
- * geometrically-equal corner read top-tight. The first block gets that same
216
- * allowance back as margin, in em so a heading's compensation scales with
217
- * the heading — the corner then MEASURES slightly uneven and finally LOOKS
218
- * even, which is the order optics always wins in.
219
- *
220
- * 0.22em, not the ~0.07em side-bearing alone: a first line is usually a
221
- * heavy cap or a heading, and dense ink right at a boundary needs more
222
- * room than a light vertical stem to feel equally far from it — the same
223
- * reason display type sets its top margin above geometric equality. Tuned
224
- * by eye against the left inset. */
225
- .era-notes-prose :global(.tiptap > :first-child) {
226
- margin-top: 0.22em;
227
- }
228
-
229
- /* FALLBACK for engines without text-box (Firefox): the trim above silently
230
- * disappears there, and the first line opened ~0.47em too low (measured:
231
- * cap 16.4px from the top against 8px from the left, dense/mono) — the
232
- * exact asymmetry the trim exists to remove. Approximate the same cut with
233
- * a negative first-block margin: -0.45em is the first line's half-leading
234
- * (0.3em at line-height 1.6) plus the ascent-above-cap of the ui stacks
235
- * (~0.15-0.17em). In em on purpose — it scales with the FIRST BLOCK's own
236
- * size, so a note opening on an h1 and one opening on a paragraph both
237
- * land their cap on the container inset, which one padding value could
238
- * never do for both (the reference terminal app's pt-1 is this same idea,
239
- * tuned only for paragraphs). The margin collapses up through .tiptap and
240
- * stops at the scroll container's padding, which is where it should act.
241
- * Within ~1px of the trimmed geometry; engines with text-box never match
242
- * this block and keep the exact version. */
243
- @supports not ((text-box-trim: trim-start) and (text-box-edge: cap alphabetic)) {
244
- .era-notes-prose :global(.tiptap > :first-child) {
245
- /* -0.45em of untrimmed leading, plus the same +0.22em optical
246
- * allowance the trimmed path adds above. */
247
- margin-top: -0.23em;
248
- }
249
- }
250
-
251
- /* Placeholder, via @tiptap/extension-placeholder */
252
- .era-notes-prose :global(.tiptap p.is-editor-empty:first-child::before) {
253
- content: attr(data-placeholder);
254
- float: left;
255
- height: 0;
256
- color: var(--color-muted);
257
- pointer-events: none;
258
- }
259
-
260
- /* Typography */
261
- .era-notes-prose :global(.tiptap p) {
262
- margin: 0 0 var(--era-gap);
263
- }
264
- .era-notes-prose :global(.tiptap p:last-child) {
265
- margin-bottom: 0;
266
- }
267
- .era-notes-prose :global(.tiptap h1) {
268
- font-size: 1.5em;
269
- }
270
- .era-notes-prose :global(.tiptap h2) {
271
- font-size: 1.25em;
272
- }
273
- .era-notes-prose :global(.tiptap h3) {
274
- font-size: 1.1em;
275
- }
276
- .era-notes-prose :global(.tiptap h1),
277
- .era-notes-prose :global(.tiptap h2),
278
- .era-notes-prose :global(.tiptap h3) {
279
- margin: 0 0 var(--era-gap);
280
- font-weight: 600;
281
- line-height: 1.6;
282
- color: var(--color-bright);
283
- }
284
- .era-notes-prose :global(.tiptap strong) {
285
- font-weight: 600;
286
- color: var(--color-bright);
287
- }
288
- .era-notes-prose :global(.tiptap em) {
289
- font-style: italic;
290
- }
291
- .era-notes-prose :global(.tiptap s) {
292
- text-decoration: line-through;
293
- text-decoration-thickness: 0.5px;
294
- }
295
-
296
- /* Code — inline chips take the xxs radius, blocks the lg one a Card uses. */
297
- .era-notes-prose :global(.tiptap code) {
298
- padding: 1px var(--era-inset-xxs);
299
- border-radius: var(--era-rd-xxs);
300
- background: var(--era-surface-bg-elevated);
301
- }
302
- .era-notes-prose :global(.tiptap pre) {
303
- overflow-x: auto;
304
- margin: 0 0 var(--era-gap);
305
- padding: var(--era-inset-md);
306
- border-radius: var(--era-rd-lg);
307
- background: var(--color-surface);
308
- box-shadow: var(--era-shadow);
309
- }
310
- .era-notes-prose :global(.tiptap pre code) {
311
- padding: 0;
312
- border-radius: 0;
313
- background: transparent;
314
- }
315
-
316
- /* Syntax highlighting — the neutral scale, so it themes with everything else. */
317
- .era-notes-prose :global(.tiptap pre .hljs-keyword),
318
- .era-notes-prose :global(.tiptap pre .hljs-built_in) {
319
- color: var(--color-9);
320
- }
321
- .era-notes-prose :global(.tiptap pre .hljs-string),
322
- .era-notes-prose :global(.tiptap pre .hljs-regexp) {
323
- color: var(--color-10);
324
- }
325
- .era-notes-prose :global(.tiptap pre .hljs-number),
326
- .era-notes-prose :global(.tiptap pre .hljs-literal),
327
- .era-notes-prose :global(.tiptap pre .hljs-type),
328
- .era-notes-prose :global(.tiptap pre .hljs-class) {
329
- color: var(--color-11);
330
- }
331
- .era-notes-prose :global(.tiptap pre .hljs-comment) {
332
- color: var(--color-8);
333
- }
334
- .era-notes-prose :global(.tiptap pre .hljs-function),
335
- .era-notes-prose :global(.tiptap pre .hljs-title) {
336
- font-weight: 600;
337
- color: var(--color-9);
338
- }
339
- .era-notes-prose :global(.tiptap pre .hljs-variable),
340
- .era-notes-prose :global(.tiptap pre .hljs-attr) {
341
- color: var(--color-12);
342
- }
343
- .era-notes-prose :global(.tiptap pre .hljs-params) {
344
- color: var(--color-11);
345
- }
346
- .era-notes-prose :global(.tiptap pre .hljs-meta),
347
- .era-notes-prose :global(.tiptap pre .hljs-tag) {
348
- color: var(--color-10);
349
- }
350
-
351
- /* Blockquote */
352
- .era-notes-prose :global(.tiptap blockquote) {
353
- margin: 0 0 var(--era-gap);
354
- padding-left: var(--era-inset-md);
355
- border-left: 2px solid var(--era-divider-color);
356
- color: var(--color-muted);
357
- }
358
-
359
- /* Lists */
360
- .era-notes-prose :global(.tiptap li),
361
- .era-notes-prose :global(.tiptap li p),
362
- .era-notes-prose :global(.tiptap ul),
363
- .era-notes-prose :global(.tiptap ol) {
364
- margin: 0;
365
- }
366
- .era-notes-prose :global(.tiptap ul) {
367
- padding-left: 1.4em;
368
- list-style-type: disc;
369
- }
370
- .era-notes-prose :global(.tiptap ol) {
371
- padding-left: 1.9em;
372
- list-style-type: decimal;
373
- }
374
-
375
- /* Task list — a checkbox styled like era's Checkbox, at the icon tier. */
376
- .era-notes-prose :global(.tiptap .task-list) {
377
- padding-left: 0;
378
- list-style: none;
379
- }
380
- .era-notes-prose :global(.tiptap .task-item) {
381
- display: flex;
382
- gap: var(--era-gap);
383
- }
384
- .era-notes-prose :global(.tiptap .task-item label) {
385
- /* Match the line box so the box centres against the first line of text. */
386
- display: flex;
387
- align-items: center;
388
- height: calc(var(--era-text) * 1.6);
389
- }
390
- .era-notes-prose :global(.tiptap .task-item input[type='checkbox']) {
391
- flex-shrink: 0;
392
- width: calc(var(--era-h-xs) - 4px);
393
- height: calc(var(--era-h-xs) - 4px);
394
- border-radius: var(--era-rd-xs);
395
- background: var(--era-surface-bg-elevated);
396
- box-shadow: var(--era-shadow-well);
397
- appearance: none;
398
- cursor: pointer;
399
- transition:
400
- background var(--era-duration) var(--era-ease),
401
- box-shadow var(--era-duration) var(--era-ease);
402
- }
403
- .era-notes-prose :global(.tiptap .task-item input[type='checkbox']:hover) {
404
- background: var(--era-highlight);
405
- }
406
- .era-notes-prose :global(.tiptap .task-item input[type='checkbox']:checked) {
407
- background: var(--color-primary);
408
- box-shadow: var(--era-shadow-pressed);
409
- }
410
- .era-notes-prose :global(.tiptap .task-item[data-checked='true'] > div > p) {
411
- color: var(--color-muted);
412
- text-decoration: line-through;
413
- }
414
-
415
- /* Horizontal rule */
416
- .era-notes-prose :global(.tiptap hr) {
417
- margin: var(--era-gap) 0;
418
- border: none;
419
- border-top: 1px solid var(--era-divider-color);
420
- }
421
-
422
- /* Links — the era-link recipe, inlined because ProseMirror owns this DOM. */
423
- .era-notes-prose :global(.tiptap a) {
424
- color: var(--color-link);
425
- text-decoration-line: underline;
426
- text-decoration-color: color-mix(in oklch, currentColor 30%, transparent);
427
- text-underline-offset: 0.2em;
428
- cursor: pointer;
429
- transition: text-decoration-color var(--era-duration) var(--era-ease);
430
- }
431
- .era-notes-prose :global(.tiptap a:hover) {
432
- text-decoration-color: currentColor;
433
- }
434
-
435
- /* Highlight — the warning token PAIR, not a wash of it.
436
- *
437
- * This was a 25% warning tint with `color: inherit`, which is two problems at
438
- * once: at 25% the mark barely separates from the page, and pushing the alpha
439
- * up to fix that puts light body text on yellow, which is worse. The pair
440
- * exists for exactly this — warning-fg is dark in EVERY mode by design
441
- * (see themes.css: yellow cannot carry light text), so a solid fill reads as
442
- * a real highlighter and the text on it stays legible in both modes. */
443
- .era-notes-prose :global(.tiptap mark) {
444
- padding: 1px 0;
445
- background: var(--color-warning);
446
- color: var(--color-warning-fg);
447
- }
448
-
449
- /* Table */
450
- .era-notes-prose :global(.tiptap .note-table) {
451
- width: 100%;
452
- margin: 0 0 var(--era-gap);
453
- border-collapse: collapse;
454
- table-layout: fixed;
455
- }
456
- .era-notes-prose :global(.tiptap .note-table td),
457
- .era-notes-prose :global(.tiptap .note-table th) {
458
- padding: var(--era-inset-sm) var(--era-inset-md);
459
- border: 1px solid var(--era-divider-color);
460
- text-align: left;
461
- vertical-align: top;
462
- }
463
- .era-notes-prose :global(.tiptap .note-table th) {
464
- background: var(--color-surface);
465
- font-weight: 600;
466
- color: var(--color-bright);
467
- }
468
- .era-notes-prose :global(.tiptap .note-table td > p),
469
- .era-notes-prose :global(.tiptap .note-table th > p) {
470
- margin: 0;
471
- }
472
-
473
- /* Details (collapsible) */
474
- .era-notes-prose :global(.tiptap details) {
475
- margin: 0 0 var(--era-gap);
476
- padding: var(--era-inset-sm) var(--era-inset-md);
477
- border-radius: var(--era-rd-md);
478
- background: var(--era-surface-bg-elevated);
479
- box-shadow: var(--era-shadow);
480
- }
481
- .era-notes-prose :global(.tiptap details summary) {
482
- font-weight: 600;
483
- color: var(--color-bright);
484
- cursor: pointer;
485
- }
486
- .era-notes-prose :global(.tiptap details > div) {
487
- margin-top: var(--era-gap);
488
- }
489
-
490
- /* Image */
491
- .era-notes-prose :global(.tiptap img) {
492
- max-width: 100%;
493
- height: auto;
494
- border-radius: var(--era-rd-md);
495
- }
496
-
497
- /*
498
- * ProseMirror ships hardcoded selection colours (#8cf outlines, a black gap
499
- * cursor, rgba(200,200,255,.4) cell selection, #adf resize handles). Each is
500
- * overridden here or the editor shows chrome from a different design system.
501
- */
502
- .era-notes-prose :global(.tiptap .ProseMirror-selectednode) {
503
- outline: 2px solid var(--color-primary);
504
- }
505
- .era-notes-prose :global(.tiptap li.ProseMirror-selectednode) {
506
- outline: none;
507
- }
508
- .era-notes-prose :global(.tiptap li.ProseMirror-selectednode::after) {
509
- border-color: var(--color-primary);
510
- }
511
- .era-notes-prose :global(.ProseMirror-gapcursor::after) {
512
- border-top-color: var(--color-primary);
513
- }
514
- .era-notes-prose :global(.tiptap .selectedCell::after) {
515
- background: var(--era-highlight);
516
- }
517
- .era-notes-prose :global(.tiptap .column-resize-handle) {
518
- background-color: var(--color-primary);
519
- }
520
- /* NO ::selection rule here, deliberately.
521
- *
522
- * era owns text selection as a surface token contract — --era-selection-bg /
523
- * -fg / -shadow (surfaces/base.css), which is how flat gets inverse video,
524
- * glass a glowing wash, and bevel an opaque accent bar. This file used to
525
- * override it with `background: var(--color-4)` and no `color`, which threw
526
- * all of that away AND left body text on a mid-scale grey: the band barely
527
- * separated from the page and the glyphs sat on top of it at whatever
528
- * contrast happened to fall out. Dropping the override restores both the
529
- * contrast (bright fill, --color-1 glyphs) and the per-surface treatment.
530
- *
531
- * The ProseMirror overrides above are still needed — those replace hardcoded
532
- * library chrome that no era token would otherwise reach. */
533
- </style>
173
+ <!-- The document styling lives in ../../styles/prose.css, imported above:
174
+ Svelte would scope a <style> block to this component, which is what made
175
+ era's prose typography unreachable for anyone building their own TipTap
176
+ instance. Same rules, addressable by anyone who sets .era-notes-prose. -->
@@ -1,4 +1,5 @@
1
1
  import { type JSONContent } from '@tiptap/core';
2
+ import '../../styles/prose.css';
2
3
  interface Props {
3
4
  /** Initial document. Later changes are ignored — re-key to reseed. */
4
5
  content: JSONContent;
@@ -295,7 +295,7 @@
295
295
  {#if store.loading}
296
296
  <div class="flex flex-col gap-gutter p-gutter">
297
297
  {#each Array.from({ length: 5 }, (_, i) => i) as i (i)}
298
- <Skeleton class="h-md rounded-md" />
298
+ <Skeleton class="h-control rounded-control" />
299
299
  {/each}
300
300
  </div>
301
301
  {:else if visible.length === 0}
@@ -322,7 +322,7 @@
322
322
  role="option" child of the listbox. A wrapper element there
323
323
  would put a non-option between them and break the relationship
324
324
  screen readers rely on.
325
- rounded-md, not rounded-item: item-rd is the radius for a row
325
+ rounded-control, not rounded-menu-item: item-rd is the radius for a row
326
326
  inside a PANEL (it subtracts the panel's frame inset). A list
327
327
  row on a plain surface takes its own tier radius — the
328
328
  conversations-rail pattern. -->
@@ -331,7 +331,7 @@
331
331
  {#snippet child({ props })}
332
332
  <div
333
333
  {...props}
334
- class="group/row flex h-md cursor-pointer items-center gap-(--era-xxs-inset-md) rounded-md px-(--era-xxs-inset-md) era-text-trim {current
334
+ class="group/row flex h-control cursor-pointer items-center gap-(--era-pill-inset-control) rounded-control px-(--era-pill-inset-control) era-text-trim {current
335
335
  ? 'bg-hover text-bright shadow-(--era-shadow-pressed)'
336
336
  : 'hover:bg-highlight hover:shadow-highlight'}"
337
337
  role="option"
@@ -347,11 +347,11 @@
347
347
  onRowKeydown(e);
348
348
  }}
349
349
  >
350
- <span class="flex size-xxs shrink-0 items-center justify-center">
350
+ <span class="flex size-pill shrink-0 items-center justify-center">
351
351
  {#if note.icon}
352
352
  {note.icon}
353
353
  {:else}
354
- <FileText class="size-(--era-icon-xxs) text-muted" />
354
+ <FileText class="size-(--era-glyph-pill) text-muted" />
355
355
  {/if}
356
356
  </span>
357
357
 
@@ -370,7 +370,7 @@
370
370
  {formatAge(note.updatedAt)}
371
371
  </span>
372
372
  <span
373
- class="hidden shrink-0 items-center gap-(--era-xxs-inset-md) group-hover/row:flex"
373
+ class="hidden shrink-0 items-center gap-(--era-pill-inset-control) group-hover/row:flex"
374
374
  >
375
375
  <Button
376
376
  icon
@@ -405,10 +405,10 @@
405
405
  <ContextMenu.Content>
406
406
  <ContextMenu.Item onSelect={() => store.togglePin(note.id)}>
407
407
  {#if note.pinned}
408
- <PinOff class="size-xs text-muted" />
408
+ <PinOff class="size-icon text-muted" />
409
409
  Unpin note
410
410
  {:else}
411
- <Pin class="size-xs text-muted" />
411
+ <Pin class="size-icon text-muted" />
412
412
  Pin note
413
413
  {/if}
414
414
  </ContextMenu.Item>
@@ -419,7 +419,7 @@
419
419
  uses, not a direct delete: a destructive action should not
420
420
  get easier to reach by arriving from a different gesture. -->
421
421
  <ContextMenu.Item onSelect={() => (pendingDelete = note.id)}>
422
- <Trash2 class="size-xs text-destructive" />
422
+ <Trash2 class="size-icon text-destructive" />
423
423
  Delete note
424
424
  </ContextMenu.Item>
425
425
  </ContextMenu.Content>
@@ -80,7 +80,7 @@ export function tokenPx(el, name) {
80
80
  }
81
81
  /** The five tier heights, in px, in the element's density context. */
82
82
  export function tiers(el) {
83
- return ['--era-h-xs', '--era-h-xxs', '--era-h-sm', '--era-h-md', '--era-h-lg'].map((name) => ({
83
+ return ['--era-h-icon', '--era-h-pill', '--era-h-chip', '--era-h-control', '--era-h-bar'].map((name) => ({
84
84
  name,
85
85
  px: tokenPx(el, name)
86
86
  }));
@@ -12,7 +12,7 @@ import { BOUNDED_TIER_MAX } from '../../measure.js';
12
12
  *
13
13
  * That blind spot shipped: the Switch thumb rested one border-width too far
14
14
  * right at BOTH ends, so the gap at the left end and at the right end differed
15
- * by 2px (dense 5 vs 3, touch 9 vs 7). --era-xs-inset-sm is measured from the
15
+ * by 2px (dense 5 vs 3, touch 9 vs 7). --era-icon-inset-chip is measured from the
16
16
  * track's OUTER edge, but a translate-x starts from the CONTENT box inside the
17
17
  * 1px border, so offsetting by the raw token added the border on one side and
18
18
  * subtracted it on the other. Vertically it was always right, because
@@ -5,8 +5,8 @@ import { BOUNDED_TIER_MAX } from '../../measure.js';
5
5
  *
6
6
  * Rule 5: every element that can hold a single glyph carries a min-width equal to
7
7
  * its tier height, so one character renders as a perfect square (or circle, once
8
- * rounded) instead of a skinny vertical pill. Icon buttons take min-w-(--era-h-md);
9
- * Badge, Chip and the KV value cell take min-w-(--era-h-xxs).
8
+ * rounded) instead of a skinny vertical pill. Icon buttons take min-w-(--era-h-control);
9
+ * Badge, Chip and the KV value cell take min-w-(--era-h-pill).
10
10
  *
11
11
  * Drop the min-width and nothing looks wrong until content happens to BE one
12
12
  * character — a badge showing "1", a count that ticks from 10 down to 9 — and the
@@ -59,10 +59,10 @@
59
59
 
60
60
  {#if dev && open}
61
61
  <div
62
- class="fixed right-4 bottom-4 z-50 flex max-h-[70vh] w-96 flex-col overflow-hidden rounded-(--era-rd-md) bg-surface font-mono text-body shadow-[inset_0_0_0_0.5px_var(--color-border),var(--era-shadow)]"
62
+ class="fixed right-4 bottom-4 z-50 flex max-h-[70vh] w-96 flex-col overflow-hidden rounded-(--era-rd-control) bg-surface font-mono text-body shadow-[inset_0_0_0_0.5px_var(--color-border),var(--era-shadow)]"
63
63
  >
64
64
  <header
65
- class="flex items-center gap-(--era-xs-inset-sm) px-(--era-inset-sm) py-(--era-gap) shadow-[inset_0_-0.5px_0_0_var(--color-border)]"
65
+ class="flex items-center gap-(--era-icon-inset-chip) px-(--era-inset-chip) py-(--era-gap) shadow-[inset_0_-0.5px_0_0_var(--color-border)]"
66
66
  >
67
67
  <strong class="text-bright">audits</strong>
68
68
  <span class="text-muted">
@@ -81,7 +81,7 @@
81
81
  {@const enabled = registry.isEnabled(r.audit.id)}
82
82
  <details open={r.issues.length > 0}>
83
83
  <summary
84
- class="flex cursor-pointer items-center gap-(--era-xs-inset-sm) px-(--era-inset-sm) py-(--era-gap) hover:bg-(--era-highlight)"
84
+ class="flex cursor-pointer items-center gap-(--era-icon-inset-chip) px-(--era-inset-chip) py-(--era-gap) hover:bg-(--era-highlight)"
85
85
  >
86
86
  <input
87
87
  type="checkbox"
@@ -95,13 +95,13 @@
95
95
  </span>
96
96
  </summary>
97
97
  {#if r.issues.length === 0}
98
- <p class="px-(--era-inset-sm) py-(--era-gap) text-muted">
98
+ <p class="px-(--era-inset-chip) py-(--era-gap) text-muted">
99
99
  {r.audit.description}
100
100
  </p>
101
101
  {:else}
102
102
  {#each r.issues as issue, i (i)}
103
103
  <button
104
- class="flex w-full items-start gap-(--era-xs-inset-sm) px-(--era-inset-sm) py-(--era-gap) text-left hover:bg-(--era-highlight)"
104
+ class="flex w-full items-start gap-(--era-icon-inset-chip) px-(--era-inset-chip) py-(--era-gap) text-left hover:bg-(--era-highlight)"
105
105
  onclick={() => highlight(issue.element)}
106
106
  >
107
107
  <span class="text-destructive">●</span>
@@ -114,9 +114,9 @@
114
114
  </div>
115
115
 
116
116
  <footer
117
- class="flex items-center gap-(--era-gap) px-(--era-inset-sm) py-(--era-gap) text-muted shadow-[inset_0_0.5px_0_0_var(--color-border)]"
117
+ class="flex items-center gap-(--era-gap) px-(--era-inset-chip) py-(--era-gap) text-muted shadow-[inset_0_0.5px_0_0_var(--color-border)]"
118
118
  >
119
- <kbd class="rounded-(--era-rd-xs) bg-hover px-(--era-inset-sm) text-fg">
119
+ <kbd class="rounded-(--era-rd-icon) bg-hover px-(--era-inset-chip) text-fg">
120
120
  {isMac ? '⌘' : 'ctrl'}⇧{key.toUpperCase()}
121
121
  </kbd>
122
122
  <span>toggle</span>
@@ -13,7 +13,7 @@ export declare const TOL = 0.5;
13
13
  * that false positive: a Card reported "radius step 5 ≠ implied gap 32.5"
14
14
  * because its 57px optical padding was read as if it were a tier inset.
15
15
  *
16
- * The tallest tier is --era-h-lg, which peaks at 64px on touch.
16
+ * The tallest tier is --era-h-bar, which peaks at 64px on touch.
17
17
  */
18
18
  export declare const BOUNDED_TIER_MAX = 64;
19
19
  /**
@@ -34,7 +34,7 @@ export const TOL = 0.5;
34
34
  * that false positive: a Card reported "radius step 5 ≠ implied gap 32.5"
35
35
  * because its 57px optical padding was read as if it were a tier inset.
36
36
  *
37
- * The tallest tier is --era-h-lg, which peaks at 64px on touch.
37
+ * The tallest tier is --era-h-bar, which peaks at 64px on touch.
38
38
  */
39
39
  export const BOUNDED_TIER_MAX = 64;
40
40
  /**
@@ -15,4 +15,4 @@
15
15
 
16
16
  - Non-interactive. For dismissible tokens use `Chip`. For labelled pairs use `KV`.
17
17
  - Uses the `xxs` tier tokens (height, radius, inset).
18
- - Inter-icon gap tightens to `--era-inset-xxs` when an SVG is present.
18
+ - Inter-icon gap tightens to `--era-inset-pill` when an SVG is present.
@@ -3,7 +3,7 @@ export interface CssUtility {
3
3
  name: string;
4
4
  /**
5
5
  * Every class the doc comment governs. Usually one; a scale documented as a
6
- * run of consecutive `@utility` blocks under a single comment (h-xs … h-lg)
6
+ * run of consecutive `@utility` blocks under a single comment (h-icon … h-bar)
7
7
  * lists the whole ladder.
8
8
  */
9
9
  names: string[];
@@ -65,7 +65,7 @@ function parseFile(file, source) {
65
65
  const names = [match[2]];
66
66
  let end = blockEnd(source, match.index + match[0].length - 1);
67
67
  // One doc comment may govern a RUN of consecutive @utility blocks — a
68
- // ladder like h-xs…h-lg shares one story, and repeating it five times
68
+ // ladder like h-icon…h-bar shares one story, and repeating it five times
69
69
  // would drown the docs. Attach every block that follows the previous one
70
70
  // with nothing but whitespace in between; the next commented block never
71
71
  // matches here because the outer pattern requires the comment.
@@ -100,8 +100,8 @@ export function parseUtilities(sources) {
100
100
  .flatMap(([file, source]) => parseFile(file, source));
101
101
  }
102
102
  const INTRO = [
103
- "era's styling API is pure class names — write `h-md rounded-md px-md shadow`,",
104
- 'never the `h-(--era-h-md)` var-class spelling. Everything below rides along',
103
+ "era's styling API is pure class names — write `h-control rounded-control px-gutter shadow`,",
104
+ 'never the `h-(--era-h-control)` var-class spelling. Everything below rides along',
105
105
  'with the stylesheet and needs no import:',
106
106
  '',
107
107
  '```ts',
@@ -109,7 +109,7 @@ const INTRO = [
109
109
  '```',
110
110
  '',
111
111
  '```svelte',
112
- '<button class="h-md rounded-md px-inset-md shadow text-body">era styled</button>',
112
+ '<button class="h-control rounded-control px-inset-control shadow text-body">era styled</button>',
113
113
  '```',
114
114
  '',
115
115
  'Alongside the `@utility` classes referenced below, era registers named theme',
@@ -119,8 +119,8 @@ const INTRO = [
119
119
  '',
120
120
  '| Stock-looking class | What it resolves to |',
121
121
  '|---|---|',
122
- '| `rounded-xs/xxs/sm/md/lg` | the concentric radius ladder (collapses on `data-corners="square"`) |',
123
- '| `rounded-item` | menu-row radius, concentric inside a `rounded-md` panel |',
122
+ '| `rounded-icon/xxs/sm/md/lg` | the concentric radius ladder (collapses on `data-corners="square"`) |',
123
+ '| `rounded-menu-item` | menu-row radius, concentric inside a `rounded-control` panel |',
124
124
  '| `shadow` / `shadow-lg` | resting control edge / floating panel chrome, per surface |',
125
125
  '| `shadow-well` / `shadow-pressed` / `shadow-highlight` | recessed, pressed/latched, hover-material chrome |',
126
126
  '| `bg-well` / `bg-elevated` / `bg-highlight` / `bg-overlay` | surface fills: resting, raised, transient feedback, modal scrim |',
@@ -130,9 +130,9 @@ const INTRO = [
130
130
  '',
131
131
  "Deliberate gaps: `w-*`/`min-w-*` tier names would shadow Tailwind's container",
132
132
  'scale (`min-w-md` stays 28rem), and the concentric-inset tokens are advanced',
133
- 'enough to stay var-form — `min-w-(--era-h-md)` etc. remain the escape hatch.'
133
+ 'enough to stay var-form — `min-w-(--era-h-control)` etc. remain the escape hatch.'
134
134
  ].join('\n');
135
- /** `h-xs` for a single class, `h-xs · h-xxs · … · h-lg` for a ladder. */
135
+ /** `h-icon` for a single class, `h-icon · h-pill · … · h-bar` for a ladder. */
136
136
  const label = (u) => u.names.join(' · ');
137
137
  /** Renders the utilities reference — the generated `utilities.md` body. */
138
138
  export function buildUtilitiesDoc(utilities) {
@@ -40,7 +40,7 @@ function orientation(origin) {
40
40
  'lg = 4·sp bars, top-level containers 32 / 40 / 48 px',
41
41
  '```',
42
42
  '',
43
- 'Heights (`--era-h-*`), insets (`--era-inset-*`), radii (`--era-rd-*`), and concentric gaps (`--era-xs-inset-sm`, `--era-xxs-inset-md`, …) are all `calc()` chains off `--era-sp`. Never hard-code pixel values — setting `data-mode` on any ancestor re-derives the whole subtree. Type is the second density input (12 px at dense, 14 px above); the spacing atom moves with it.',
43
+ 'Heights (`--era-h-*`), insets (`--era-inset-*`), radii (`--era-rd-*`), and concentric gaps (`--era-icon-inset-chip`, `--era-pill-inset-control`, …) are all `calc()` chains off `--era-sp`. Never hard-code pixel values — setting `data-mode` on any ancestor re-derives the whole subtree. Type is the second density input (12 px at dense, 14 px above); the spacing atom moves with it.',
44
44
  '',
45
45
  '## Per-component docs',
46
46
  '',