@estiva-app/ui 0.63.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -71,7 +71,7 @@ function cn(...inputs) {
71
71
  import { jsx as jsx2 } from "react/jsx-runtime";
72
72
  var COVER_CLASSES = "after:absolute after:inset-0 after:rounded-md focus-visible:outline-none focus-visible:after:[outline-style:auto]";
73
73
  var VARIANT_CLASSES = {
74
- text: "text-info-default underline underline-offset-2 hover:opacity-80",
74
+ text: "text-text-interactive underline underline-offset-2 hover:opacity-80",
75
75
  quiet: "hover:underline",
76
76
  underlined: "underline underline-offset-2 hover:text-text-primary",
77
77
  plain: ""
@@ -2421,28 +2421,52 @@ function InlineChip({ tone = "neutral", icon, href, className, children, ...prop
2421
2421
  return /* @__PURE__ */ jsx33("a", { href, className: classes, ...props, onClick: inApp, children: body });
2422
2422
  }
2423
2423
 
2424
+ // src/codeColours.ts
2425
+ import { createElement } from "react";
2426
+ import { common, createLowlight } from "lowlight";
2427
+ var lowlight = createLowlight(common);
2428
+ function draw(node, key) {
2429
+ if (node.type === "text") return node.value;
2430
+ return createElement("span", { key, className: node.properties?.className?.join(" ") }, (node.children ?? []).map(draw));
2431
+ }
2432
+ function codeColours(text, language) {
2433
+ if (!language || !lowlight.registered(language)) return text;
2434
+ return lowlight.highlight(language, text).children.map(draw);
2435
+ }
2436
+
2424
2437
  // src/RichText.tsx
2425
2438
  import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2426
2439
  var RICH_TEXT_CLASSES = {
2427
- base: "flex flex-col gap-1 break-words text-text-secondary",
2428
- /* A heading binds to what follows it: 12px above (8 and the 4px gap), 8px below (4 and the gap); two headings in a row, 12px apart. Level 3 keeps the text's colour, one step lower. */
2429
- headings: "[&>:is(h1,h2,h3)]:mb-1 [&>:is(h1,h2,h3)]:mt-2 [&>:is(h1,h2,h3):first-child]:mt-0 [&>:is(h1,h2,h3):last-child]:mb-0 [&>:is(h1,h2,h3)+:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2)]:text-text-primary",
2430
- lists: "[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-muted [&_ol]:list-decimal [&_ul]:list-disc",
2440
+ /* Blocks 8px apart (Katerina, 9 October; 4 before). A list's own items stay together. */
2441
+ base: "flex flex-col gap-2 break-words text-text-secondary",
2442
+ /* A heading binds to what follows it: 12px above (4 and the 8px gap), 8px below (the gap); two headings in a row, 12px apart. The same as before the gap grew (Katerina, 9 October: headings do not change). Level 3 keeps the text's colour, one step lower: at the same size as level 2, colour is what tells them apart (Katerina, 9 October). */
2443
+ headings: "[&>:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2,h3):first-child]:mt-0 [&>:is(h1,h2)]:text-text-primary",
2444
+ /* Bullets and numbers in the text's own colour, so a number can be read (Katerina, 9 October; they were the muted grey, 2.4 : 1 in Leaf). */
2445
+ lists: "[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-secondary [&_ol]:list-decimal [&_ul]:list-disc",
2446
+ /* The line in the muted text grey, not the border grey: a border grey was 1.3 : 1 in Leaf (Katerina, 9 October). */
2431
2447
  // eslint-disable-next-line token-spacing/no-restricted-classes -- @estiva-escape: the quote line is Peek's, 3px, between the ramp's 2 and 4
2432
- quote: "[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-border-strong [&_blockquote]:pl-2.5",
2433
- // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.9 of the text around it, so it scales with a heading and with `small`; a named size is fixed
2434
- code: "[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_code]:text-text-primary",
2435
- // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.9 of the text around it; the code inside the block is the block's own size, not 0.9 of it again
2436
- codeBlock: "[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:p-2 [&_pre]:font-mono [&_pre]:text-[0.9em] [&_pre]:text-text-primary",
2437
- divider: "[&_hr]:border-border-default",
2448
+ quote: "[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5",
2449
+ /* Code in a sentence is amber, its own colour (Katerina, 9 October: option I). */
2450
+ // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it, so it scales with a heading and with `small`; a named size is fixed
2451
+ code: "[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-text-code [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
2452
+ /* 12px either side, 10px above and below, looser lines than the text (Katerina, 9 October; 8px all round before). */
2453
+ // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it; the code inside the block is the block's own size, not 0.85 of it again
2454
+ codeBlock: "[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:px-3 [&_pre]:py-2.5 [&_pre]:font-mono [&_pre]:text-[0.85em] [&_pre]:leading-relaxed [&_pre]:text-text-primary",
2455
+ /* Colours inside a code block, by language: the classes `codeColours` gives each word, after highlight.js's own GitHub theme (Katerina, 9 October). */
2456
+ syntax: "[&_:is(.hljs-keyword,.hljs-doctag,.hljs-type,.hljs-template-tag,.hljs-template-variable)]:text-syntax-keyword [&_.hljs-title]:text-syntax-function [&_:is(.hljs-number,.hljs-literal,.hljs-attr,.hljs-attribute,.hljs-meta,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id)]:text-syntax-constant [&_:is(.hljs-string,.hljs-regexp)]:text-syntax-string [&_:is(.hljs-built_in,.hljs-symbol)]:text-syntax-variable [&_.hljs-comment]:text-syntax-comment [&_:is(.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo)]:text-syntax-tag",
2457
+ /* A divider splits the text in two: 16px either side (Katerina, 9 October; 4 before). */
2458
+ divider: "[&_hr]:my-2 [&_hr]:border-border-default",
2438
2459
  table: "[&_:is(th,td)>p]:m-0 [&_:is(th,td)]:border [&_:is(th,td)]:border-border-default [&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1 [&_:is(th,td)]:text-left [&_:is(th,td)]:align-top [&_table]:w-full [&_table]:border-collapse [&_th]:bg-bg-code [&_th]:font-medium [&_th]:text-text-primary",
2439
- marks: "[&_em]:italic [&_strong]:font-semibold [&_u]:underline [&_u]:underline-offset-2",
2440
- default: "text-body-2 [&>:is(h2,h3)]:text-body-2 [&>:is(h2,h3)]:font-semibold [&>h1]:text-h4",
2441
- small: "text-caption leading-snug [&>:is(h2,h3)]:text-caption [&>:is(h2,h3)]:font-semibold [&>h1]:text-body-2 [&>h1]:font-semibold"
2460
+ /* Bold in the heading colour, not only heavier. An underlined word draws a faint line, so it does not read as a link (Katerina, 9 October). */
2461
+ marks: "[&_em]:italic [&_strong]:font-semibold [&_strong]:text-text-primary [&_u]:underline [&_u]:decoration-text-muted [&_u]:underline-offset-2",
2462
+ /* Lines 1.5 apart (Katerina, 9 October; 1.4 before). */
2463
+ default: "text-body-2 leading-normal [&>:is(h2,h3)]:text-body-2 [&>:is(h2,h3)]:font-semibold [&>h1]:text-h4",
2464
+ /* Blocks 6px apart; a heading keeps its 12px above and 8px below. */
2465
+ small: "gap-1.5 text-caption leading-snug [&>:is(h1,h2,h3)]:mb-0.5 [&>:is(h1,h2,h3)]:mt-1.5 [&>:is(h1,h2,h3)+:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2,h3):last-child]:mb-0 [&>:is(h2,h3)]:text-caption [&>:is(h2,h3)]:font-semibold [&>h1]:text-body-2 [&>h1]:font-semibold"
2442
2466
  };
2443
2467
  function richTextClassName(size = "default", className) {
2444
- const { base, headings, lists, quote, code, codeBlock, divider, table, marks } = RICH_TEXT_CLASSES;
2445
- return cn(base, headings, lists, quote, code, codeBlock, divider, table, marks, RICH_TEXT_CLASSES[size], className);
2468
+ const { base, headings, lists, quote, code, codeBlock, syntax, divider, table, marks } = RICH_TEXT_CLASSES;
2469
+ return cn(base, headings, lists, quote, code, codeBlock, syntax, divider, table, marks, RICH_TEXT_CLASSES[size], className);
2446
2470
  }
2447
2471
  var LINK_SPLIT = /(\[[^[\]\n]+\]\((?:https?:\/\/|mailto:)[^\s)]+\)|https?:\/\/[^\s]+)/g;
2448
2472
  var WRITTEN_LINK = /^\[([^[\]\n]+)\]\(((?:https?:\/\/|mailto:)[^\s)]+)\)$/;
@@ -2469,15 +2493,15 @@ function textWithLinks(text, renderText) {
2469
2493
  return part ? /* @__PURE__ */ jsx34("span", { children: renderText(part) }, i) : null;
2470
2494
  });
2471
2495
  }
2472
- function Runs({ runs, draw }) {
2496
+ function Runs({ runs, draw: draw2 }) {
2473
2497
  return /* @__PURE__ */ jsx34(Fragment8, { children: (runs ?? []).map((run, i) => {
2474
- if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw.renderReference(run.reference, run) }, i);
2498
+ if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw2.renderReference(run.reference, run) }, i);
2475
2499
  if (run.marks.includes("code")) {
2476
2500
  return /* @__PURE__ */ jsx34("code", { children: run.text }, i);
2477
2501
  }
2478
2502
  let node = run.text.split("\n").map((line, j) => /* @__PURE__ */ jsxs25("span", { children: [
2479
2503
  j > 0 && /* @__PURE__ */ jsx34("br", {}),
2480
- textWithLinks(line, draw.renderText)
2504
+ textWithLinks(line, draw2.renderText)
2481
2505
  ] }, j));
2482
2506
  if (run.marks.includes("underline")) node = /* @__PURE__ */ jsx34("u", { children: node });
2483
2507
  if (run.marks.includes("italic")) node = /* @__PURE__ */ jsx34("em", { children: node });
@@ -2486,7 +2510,7 @@ function Runs({ runs, draw }) {
2486
2510
  }) });
2487
2511
  }
2488
2512
  var named = (block) => block.typeName ?? block.type;
2489
- function Table({ block, draw }) {
2513
+ function Table({ block, draw: draw2 }) {
2490
2514
  const rows = (block.children ?? []).filter((row) => named(row) === "tableRow");
2491
2515
  if (!rows.length) return null;
2492
2516
  const cells = (row) => (row.children ?? []).map((cell, i) => {
@@ -2500,8 +2524,8 @@ function Table({ block, draw }) {
2500
2524
  colSpan: colspan && colspan > 1 ? colspan : void 0,
2501
2525
  rowSpan: rowspan && rowspan > 1 ? rowspan : void 0,
2502
2526
  children: [
2503
- (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw }, j)),
2504
- /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw })
2527
+ (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw: draw2 }, j)),
2528
+ /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw: draw2 })
2505
2529
  ]
2506
2530
  },
2507
2531
  cell.id ?? i
@@ -2514,10 +2538,10 @@ function Table({ block, draw }) {
2514
2538
  /* @__PURE__ */ jsx34("tbody", { children: (headerRow ? rows.slice(1) : rows).map((row, i) => /* @__PURE__ */ jsx34("tr", { "data-block-id": row.id, children: cells(row) }, row.id ?? i)) })
2515
2539
  ] });
2516
2540
  }
2517
- function Block({ block, draw }) {
2518
- const own = draw.renderBlock?.(block);
2541
+ function Block({ block, draw: draw2 }) {
2542
+ const own = draw2.renderBlock?.(block);
2519
2543
  if (own !== void 0) return own;
2520
- const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw });
2544
+ const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw: draw2 });
2521
2545
  switch (block.type) {
2522
2546
  case "heading": {
2523
2547
  if (block.level === 1) return /* @__PURE__ */ jsx34("h1", { "data-block-id": block.id, children: runs });
@@ -2528,24 +2552,24 @@ function Block({ block, draw }) {
2528
2552
  return /* @__PURE__ */ jsx34("p", { "data-block-id": block.id, children: runs });
2529
2553
  case "bulletList":
2530
2554
  case "orderedList": {
2531
- const items = (block.children ?? []).map((item, i) => /* @__PURE__ */ jsx34("li", { "data-block-id": item.id, children: /* @__PURE__ */ jsx34(Runs, { runs: item.inline, draw }) }, item.id ?? i));
2555
+ const items = (block.children ?? []).map((item, i) => /* @__PURE__ */ jsx34("li", { "data-block-id": item.id, children: /* @__PURE__ */ jsx34(Runs, { runs: item.inline, draw: draw2 }) }, item.id ?? i));
2532
2556
  return block.type === "bulletList" ? /* @__PURE__ */ jsx34("ul", { "data-block-id": block.id, children: items }) : /* @__PURE__ */ jsx34("ol", { "data-block-id": block.id, start: block.start, children: items });
2533
2557
  }
2534
2558
  case "blockquote":
2535
2559
  return /* @__PURE__ */ jsx34("blockquote", { "data-block-id": block.id, children: runs });
2536
2560
  case "codeBlock":
2537
- return /* @__PURE__ */ jsx34("pre", { "data-block-id": block.id, "data-language": block.language, children: /* @__PURE__ */ jsx34("code", { children: (block.inline ?? []).map((run) => run.text).join("") }) });
2561
+ return /* @__PURE__ */ jsx34("pre", { "data-block-id": block.id, "data-language": block.language, children: /* @__PURE__ */ jsx34("code", { children: codeColours((block.inline ?? []).map((run) => run.text).join(""), block.language) }) });
2538
2562
  case "horizontalRule":
2539
2563
  return /* @__PURE__ */ jsx34("hr", { "data-block-id": block.id });
2540
2564
  case "table": {
2541
- const table = /* @__PURE__ */ jsx34(Table, { block, draw });
2565
+ const table = /* @__PURE__ */ jsx34(Table, { block, draw: draw2 });
2542
2566
  if ((block.children ?? []).some((row) => named(row) === "tableRow")) return table;
2543
2567
  break;
2544
2568
  }
2545
2569
  }
2546
2570
  return /* @__PURE__ */ jsxs25("div", { "data-block-id": block.id, "data-block-type": named(block), children: [
2547
2571
  runs,
2548
- (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx34(Block, { block: child, draw }, child.id ?? i))
2572
+ (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx34(Block, { block: child, draw: draw2 }, child.id ?? i))
2549
2573
  ] });
2550
2574
  }
2551
2575
  function RichText({
@@ -2556,8 +2580,8 @@ function RichText({
2556
2580
  renderBlock
2557
2581
  }) {
2558
2582
  if (blocks.length === 0) return null;
2559
- const draw = { renderText, renderReference, renderBlock };
2560
- return /* @__PURE__ */ jsx34("div", { "data-rich-text": true, className: richTextClassName(size), children: blocks.map((block, i) => /* @__PURE__ */ jsx34(Block, { block, draw }, block.id ?? i)) });
2583
+ const draw2 = { renderText, renderReference, renderBlock };
2584
+ return /* @__PURE__ */ jsx34("div", { "data-rich-text": true, className: richTextClassName(size), children: blocks.map((block, i) => /* @__PURE__ */ jsx34(Block, { block, draw: draw2 }, block.id ?? i)) });
2561
2585
  }
2562
2586
 
2563
2587
  // src/KindIcon.tsx