@estiva-app/ui 0.63.0 → 0.65.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,55 @@ 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 instance;
2428
+ function lowlight() {
2429
+ return instance ??= createLowlight(common);
2430
+ }
2431
+ function draw(node, key) {
2432
+ if (node.type === "text") return node.value;
2433
+ return createElement("span", { key, className: node.properties?.className?.join(" ") }, (node.children ?? []).map(draw));
2434
+ }
2435
+ function codeColours(text, language) {
2436
+ if (!language || !lowlight().registered(language)) return text;
2437
+ return lowlight().highlight(language, text).children.map(draw);
2438
+ }
2439
+
2424
2440
  // src/RichText.tsx
2425
2441
  import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2426
2442
  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",
2443
+ /* Blocks 8px apart (Katerina, 9 October; 4 before). A list's own items stay together. */
2444
+ base: "flex flex-col gap-2 break-words text-text-secondary",
2445
+ /* 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). */
2446
+ headings: "[&>:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2,h3):first-child]:mt-0 [&>:is(h1,h2)]:text-text-primary",
2447
+ /* 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). */
2448
+ lists: "[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-secondary [&_ol]:list-decimal [&_ul]:list-disc",
2449
+ /* The line in the muted text grey, not the border grey: a border grey was 1.3 : 1 in Leaf (Katerina, 9 October). */
2431
2450
  // 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",
2451
+ quote: "[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5",
2452
+ /* Code in a sentence: the code fill and a thin border, in the heading colour (Katerina, 9 October: option B; the amber of 0.64.0 was too much). */
2453
+ // 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
2454
+ 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]:border [&_:not(pre)>code]:border-border-default [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
2455
+ /* 12px either side, 10px above and below, looser lines than the text (Katerina, 9 October; 8px all round before). */
2456
+ // 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
2457
+ 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",
2458
+ /* Colours inside a code block, by language: the classes `codeColours` gives each word, after highlight.js's own GitHub theme (Katerina, 9 October). */
2459
+ 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",
2460
+ /* A divider splits the text in two: 16px either side (Katerina, 9 October; 4 before). */
2461
+ divider: "[&_hr]:my-2 [&_hr]:border-border-default",
2438
2462
  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"
2463
+ /* 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). */
2464
+ marks: "[&_em]:italic [&_strong]:font-semibold [&_strong]:text-text-primary [&_u]:underline [&_u]:decoration-text-muted [&_u]:underline-offset-2",
2465
+ /* Lines 1.5 apart (Katerina, 9 October; 1.4 before). */
2466
+ default: "text-body-2 leading-normal [&>:is(h2,h3)]:text-body-2 [&>:is(h2,h3)]:font-semibold [&>h1]:text-h4",
2467
+ /* Blocks 6px apart; a heading keeps its 12px above and 8px below. */
2468
+ 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
2469
  };
2443
2470
  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);
2471
+ const { base, headings, lists, quote, code, codeBlock, syntax, divider, table, marks } = RICH_TEXT_CLASSES;
2472
+ return cn(base, headings, lists, quote, code, codeBlock, syntax, divider, table, marks, RICH_TEXT_CLASSES[size], className);
2446
2473
  }
2447
2474
  var LINK_SPLIT = /(\[[^[\]\n]+\]\((?:https?:\/\/|mailto:)[^\s)]+\)|https?:\/\/[^\s]+)/g;
2448
2475
  var WRITTEN_LINK = /^\[([^[\]\n]+)\]\(((?:https?:\/\/|mailto:)[^\s)]+)\)$/;
@@ -2469,15 +2496,15 @@ function textWithLinks(text, renderText) {
2469
2496
  return part ? /* @__PURE__ */ jsx34("span", { children: renderText(part) }, i) : null;
2470
2497
  });
2471
2498
  }
2472
- function Runs({ runs, draw }) {
2499
+ function Runs({ runs, draw: draw2 }) {
2473
2500
  return /* @__PURE__ */ jsx34(Fragment8, { children: (runs ?? []).map((run, i) => {
2474
- if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw.renderReference(run.reference, run) }, i);
2501
+ if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw2.renderReference(run.reference, run) }, i);
2475
2502
  if (run.marks.includes("code")) {
2476
2503
  return /* @__PURE__ */ jsx34("code", { children: run.text }, i);
2477
2504
  }
2478
2505
  let node = run.text.split("\n").map((line, j) => /* @__PURE__ */ jsxs25("span", { children: [
2479
2506
  j > 0 && /* @__PURE__ */ jsx34("br", {}),
2480
- textWithLinks(line, draw.renderText)
2507
+ textWithLinks(line, draw2.renderText)
2481
2508
  ] }, j));
2482
2509
  if (run.marks.includes("underline")) node = /* @__PURE__ */ jsx34("u", { children: node });
2483
2510
  if (run.marks.includes("italic")) node = /* @__PURE__ */ jsx34("em", { children: node });
@@ -2486,7 +2513,7 @@ function Runs({ runs, draw }) {
2486
2513
  }) });
2487
2514
  }
2488
2515
  var named = (block) => block.typeName ?? block.type;
2489
- function Table({ block, draw }) {
2516
+ function Table({ block, draw: draw2 }) {
2490
2517
  const rows = (block.children ?? []).filter((row) => named(row) === "tableRow");
2491
2518
  if (!rows.length) return null;
2492
2519
  const cells = (row) => (row.children ?? []).map((cell, i) => {
@@ -2500,8 +2527,8 @@ function Table({ block, draw }) {
2500
2527
  colSpan: colspan && colspan > 1 ? colspan : void 0,
2501
2528
  rowSpan: rowspan && rowspan > 1 ? rowspan : void 0,
2502
2529
  children: [
2503
- (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw }, j)),
2504
- /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw })
2530
+ (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw: draw2 }, j)),
2531
+ /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw: draw2 })
2505
2532
  ]
2506
2533
  },
2507
2534
  cell.id ?? i
@@ -2514,10 +2541,10 @@ function Table({ block, draw }) {
2514
2541
  /* @__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
2542
  ] });
2516
2543
  }
2517
- function Block({ block, draw }) {
2518
- const own = draw.renderBlock?.(block);
2544
+ function Block({ block, draw: draw2 }) {
2545
+ const own = draw2.renderBlock?.(block);
2519
2546
  if (own !== void 0) return own;
2520
- const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw });
2547
+ const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw: draw2 });
2521
2548
  switch (block.type) {
2522
2549
  case "heading": {
2523
2550
  if (block.level === 1) return /* @__PURE__ */ jsx34("h1", { "data-block-id": block.id, children: runs });
@@ -2528,24 +2555,24 @@ function Block({ block, draw }) {
2528
2555
  return /* @__PURE__ */ jsx34("p", { "data-block-id": block.id, children: runs });
2529
2556
  case "bulletList":
2530
2557
  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));
2558
+ 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
2559
  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
2560
  }
2534
2561
  case "blockquote":
2535
2562
  return /* @__PURE__ */ jsx34("blockquote", { "data-block-id": block.id, children: runs });
2536
2563
  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("") }) });
2564
+ 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
2565
  case "horizontalRule":
2539
2566
  return /* @__PURE__ */ jsx34("hr", { "data-block-id": block.id });
2540
2567
  case "table": {
2541
- const table = /* @__PURE__ */ jsx34(Table, { block, draw });
2568
+ const table = /* @__PURE__ */ jsx34(Table, { block, draw: draw2 });
2542
2569
  if ((block.children ?? []).some((row) => named(row) === "tableRow")) return table;
2543
2570
  break;
2544
2571
  }
2545
2572
  }
2546
2573
  return /* @__PURE__ */ jsxs25("div", { "data-block-id": block.id, "data-block-type": named(block), children: [
2547
2574
  runs,
2548
- (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx34(Block, { block: child, draw }, child.id ?? i))
2575
+ (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx34(Block, { block: child, draw: draw2 }, child.id ?? i))
2549
2576
  ] });
2550
2577
  }
2551
2578
  function RichText({
@@ -2556,8 +2583,8 @@ function RichText({
2556
2583
  renderBlock
2557
2584
  }) {
2558
2585
  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)) });
2586
+ const draw2 = { renderText, renderReference, renderBlock };
2587
+ 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
2588
  }
2562
2589
 
2563
2590
  // src/KindIcon.tsx