@estiva-app/ui 0.67.0 → 0.68.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 (41) hide show
  1. package/dist/BlockNodes.d.ts +12 -1
  2. package/dist/BlockNodes.d.ts.map +1 -1
  3. package/dist/LinkChips.d.ts +82 -0
  4. package/dist/LinkChips.d.ts.map +1 -0
  5. package/dist/ReferenceCards.d.ts +77 -0
  6. package/dist/ReferenceCards.d.ts.map +1 -0
  7. package/dist/ReferenceMenu.d.ts +18 -0
  8. package/dist/ReferenceMenu.d.ts.map +1 -0
  9. package/dist/RichText.d.ts +9 -2
  10. package/dist/RichText.d.ts.map +1 -1
  11. package/dist/SelectionToolbar.d.ts +9 -1
  12. package/dist/SelectionToolbar.d.ts.map +1 -1
  13. package/dist/editor.d.ts +3 -0
  14. package/dist/editor.d.ts.map +1 -1
  15. package/dist/editor.js +589 -20
  16. package/dist/editor.js.map +4 -4
  17. package/dist/index.js +39 -19
  18. package/dist/index.js.map +4 -4
  19. package/package.json +1 -1
  20. package/registry.json +290 -3
  21. package/src/BlockNodes.test.tsx +2 -1
  22. package/src/BlockNodes.tsx +51 -9
  23. package/src/LinkChips.mdx +57 -0
  24. package/src/LinkChips.stories.tsx +67 -0
  25. package/src/LinkChips.test.tsx +178 -0
  26. package/src/LinkChips.ts +243 -0
  27. package/src/ReferenceCards.mdx +79 -0
  28. package/src/ReferenceCards.stories.tsx +64 -0
  29. package/src/ReferenceCards.test.tsx +143 -0
  30. package/src/ReferenceCards.ts +225 -0
  31. package/src/ReferenceMenu.mdx +75 -0
  32. package/src/ReferenceMenu.stories.tsx +59 -0
  33. package/src/ReferenceMenu.test.tsx +289 -0
  34. package/src/ReferenceMenu.tsx +346 -0
  35. package/src/RichText.test.tsx +17 -0
  36. package/src/RichText.tsx +34 -3
  37. package/src/SelectionToolbar.tsx +10 -2
  38. package/src/editor.ts +13 -0
  39. package/src/pages.test.ts +3 -0
  40. package/src/registry/registry.test.ts +6 -6
  41. package/stories/Choosing.mdx +3 -0
package/dist/index.js CHANGED
@@ -2421,6 +2421,9 @@ 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/RichText.tsx
2425
+ import { Fragment as Fragment8 } from "react";
2426
+
2424
2427
  // src/codeColours.ts
2425
2428
  import { createElement } from "react";
2426
2429
  import { common, createLowlight } from "lowlight";
@@ -2438,7 +2441,7 @@ function codeColours(text, language) {
2438
2441
  }
2439
2442
 
2440
2443
  // src/RichText.tsx
2441
- import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2444
+ import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2442
2445
  var RICH_TEXT_CLASSES = {
2443
2446
  /* Blocks 8px apart (Katerina, 9 October; 4 before). A list's own items stay together. */
2444
2447
  base: "flex flex-col gap-2 break-words text-text-secondary",
@@ -2510,7 +2513,7 @@ function calloutLook(tone) {
2510
2513
  return CALLOUT_TONES.has(named2) ? named2 : "note";
2511
2514
  }
2512
2515
  function Runs({ runs, draw: draw2 }) {
2513
- return /* @__PURE__ */ jsx34(Fragment8, { children: (runs ?? []).map((run, i) => {
2516
+ return /* @__PURE__ */ jsx34(Fragment9, { children: (runs ?? []).map((run, i) => {
2514
2517
  if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw2.renderReference(run.reference, run) }, i);
2515
2518
  if (run.marks.includes("code")) {
2516
2519
  return /* @__PURE__ */ jsx34("code", { children: run.text }, i);
@@ -2540,8 +2543,12 @@ function Table({ block, draw: draw2 }) {
2540
2543
  colSpan: colspan && colspan > 1 ? colspan : void 0,
2541
2544
  rowSpan: rowspan && rowspan > 1 ? rowspan : void 0,
2542
2545
  children: [
2543
- (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw: draw2 }, j)),
2544
- /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw: draw2 })
2546
+ (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsxs25(Fragment8, { children: [
2547
+ /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw: draw2 }),
2548
+ draw2.renderAfter?.(child)
2549
+ ] }, j)),
2550
+ /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw: draw2 }),
2551
+ draw2.renderAfter?.(cell)
2545
2552
  ]
2546
2553
  },
2547
2554
  cell.id ?? i
@@ -2559,6 +2566,7 @@ function ListItem({ item, draw: draw2, below }) {
2559
2566
  if (typeof item.checked !== "boolean") {
2560
2567
  return /* @__PURE__ */ jsxs25("li", { "data-block-id": item.id, children: [
2561
2568
  /* @__PURE__ */ jsx34(Runs, { runs: item.inline, draw: draw2 }),
2569
+ draw2.renderAfter?.(item),
2562
2570
  below
2563
2571
  ] });
2564
2572
  }
@@ -2570,6 +2578,7 @@ function ListItem({ item, draw: draw2, below }) {
2570
2578
  /* @__PURE__ */ jsx34("span", { "data-checklist-box": "", ...control ? {} : { role: "checkbox", "aria-checked": item.checked, "aria-readonly": true, "aria-label": name }, children: /* @__PURE__ */ jsx34(Checkbox, { checked: item.checked, onChange: control, "aria-label": name }) }),
2571
2579
  /* @__PURE__ */ jsxs25("div", { children: [
2572
2580
  /* @__PURE__ */ jsx34("p", { children: /* @__PURE__ */ jsx34(Runs, { runs: item.inline, draw: draw2 }) }),
2581
+ draw2.renderAfter?.(item),
2573
2582
  below
2574
2583
  ] })
2575
2584
  ] });
@@ -2591,6 +2600,16 @@ function nestItems(items) {
2591
2600
  function Block({ block, draw: draw2 }) {
2592
2601
  const own = draw2.renderBlock?.(block);
2593
2602
  if (own !== void 0) return own;
2603
+ const drawn = Drawn({ block, draw: draw2 });
2604
+ const lineOfWords = block.type === "paragraph" || block.type === "heading" || block.type === "blockquote";
2605
+ const after = lineOfWords ? draw2.renderAfter?.(block) : void 0;
2606
+ if (after === void 0 || after === null || after === false) return drawn;
2607
+ return /* @__PURE__ */ jsxs25(Fragment9, { children: [
2608
+ drawn,
2609
+ after
2610
+ ] });
2611
+ }
2612
+ function Drawn({ block, draw: draw2 }) {
2594
2613
  const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw: draw2 });
2595
2614
  switch (block.type) {
2596
2615
  case "heading": {
@@ -2638,10 +2657,11 @@ function RichText({
2638
2657
  renderText = (text) => text,
2639
2658
  renderReference = (_reference, run) => run.text,
2640
2659
  renderBlock,
2660
+ renderAfter,
2641
2661
  onTick
2642
2662
  }) {
2643
2663
  if (blocks.length === 0) return null;
2644
- const draw2 = { renderText, renderReference, renderBlock, onTick };
2664
+ const draw2 = { renderText, renderReference, renderBlock, renderAfter, onTick };
2645
2665
  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)) });
2646
2666
  }
2647
2667
 
@@ -2738,7 +2758,7 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
2738
2758
  }
2739
2759
 
2740
2760
  // src/IdentityMenu.tsx
2741
- import { Fragment as Fragment9, jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
2761
+ import { Fragment as Fragment10, jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
2742
2762
  function IdentityPanel({ className, onClose = () => {
2743
2763
  }, ...rest }) {
2744
2764
  return /* @__PURE__ */ jsx38(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx38(IdentityRows, { ...rest, onClose }) });
@@ -2749,7 +2769,7 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
2749
2769
  action();
2750
2770
  };
2751
2771
  const appRows = typeof children === "function" ? children(onClose) : children;
2752
- return /* @__PURE__ */ jsxs28(Fragment9, { children: [
2772
+ return /* @__PURE__ */ jsxs28(Fragment10, { children: [
2753
2773
  /* @__PURE__ */ jsxs28(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
2754
2774
  /* @__PURE__ */ jsx38(MenuRow, { children: /* @__PURE__ */ jsx38("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx38(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
2755
2775
  /* @__PURE__ */ jsx38(Note, { children: signedIn ? "Your Estiva ID. The same person you are in every Estiva app." : "A key held by this browser only. Nobody else knows who you are." }),
@@ -2758,14 +2778,14 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
2758
2778
  " \xB7 known to Estiva, never published to the relay"
2759
2779
  ] })
2760
2780
  ] }),
2761
- relayUrl && /* @__PURE__ */ jsxs28(Fragment9, { children: [
2781
+ relayUrl && /* @__PURE__ */ jsxs28(Fragment10, { children: [
2762
2782
  /* @__PURE__ */ jsx38(Divider, { className: "mx-0 my-2" }),
2763
2783
  /* @__PURE__ */ jsxs28(MenuSection, { label: "Workspace", children: [
2764
2784
  /* @__PURE__ */ jsx38(MenuRow, { children: /* @__PURE__ */ jsx38("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
2765
2785
  /* @__PURE__ */ jsx38(Note, { children: "Everyone on this relay shares this workspace, in every app." })
2766
2786
  ] })
2767
2787
  ] }),
2768
- appRows && /* @__PURE__ */ jsxs28(Fragment9, { children: [
2788
+ appRows && /* @__PURE__ */ jsxs28(Fragment10, { children: [
2769
2789
  /* @__PURE__ */ jsx38(Divider, { className: "mx-0 my-2" }),
2770
2790
  appRows
2771
2791
  ] }),
@@ -3020,7 +3040,7 @@ var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
3020
3040
 
3021
3041
  // src/ConfirmDialog.tsx
3022
3042
  import { useState as useState6 } from "react";
3023
- import { Fragment as Fragment10, jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
3043
+ import { Fragment as Fragment11, jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
3024
3044
  function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
3025
3045
  const [busy, setBusy] = useState6(false);
3026
3046
  const confirm = async () => {
@@ -3038,7 +3058,7 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
3038
3058
  alert: true,
3039
3059
  title,
3040
3060
  onClose,
3041
- footer: /* @__PURE__ */ jsxs30(Fragment10, { children: [
3061
+ footer: /* @__PURE__ */ jsxs30(Fragment11, { children: [
3042
3062
  /* @__PURE__ */ jsx43(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
3043
3063
  /* @__PURE__ */ jsx43(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
3044
3064
  ] }),
@@ -3210,7 +3230,7 @@ function ProgressBar({ value, max, label, variant = "default", className }) {
3210
3230
  }
3211
3231
 
3212
3232
  // src/Breadcrumb.tsx
3213
- import { Fragment as Fragment11, useCallback as useCallback3, useLayoutEffect as useLayoutEffect4, useRef as useRef10, useState as useState8 } from "react";
3233
+ import { Fragment as Fragment12, useCallback as useCallback3, useLayoutEffect as useLayoutEffect4, useRef as useRef10, useState as useState8 } from "react";
3214
3234
  import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
3215
3235
  function Breadcrumb({ items, className }) {
3216
3236
  const navRef = useRef10(null);
@@ -3254,7 +3274,7 @@ function Breadcrumb({ items, className }) {
3254
3274
  // truncates and is measured.
3255
3275
  /* @__PURE__ */ jsx47("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx47(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
3256
3276
  ) : /* @__PURE__ */ jsx47("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
3257
- return /* @__PURE__ */ jsxs31(Fragment11, { children: [
3277
+ return /* @__PURE__ */ jsxs31(Fragment12, { children: [
3258
3278
  index > 0 && /* @__PURE__ */ jsx47("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
3259
3279
  item.icon && /* @__PURE__ */ jsx47("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
3260
3280
  truncated.has(index) ? (
@@ -3447,7 +3467,7 @@ import { Collapsible as Collapsible2 } from "@base-ui/react/collapsible";
3447
3467
  // src/SectionHeader.tsx
3448
3468
  import { IconChevronRight as IconChevronRight3, IconDotsVertical as IconDotsVertical2 } from "@tabler/icons-react";
3449
3469
  import { useRender } from "@base-ui/react/use-render";
3450
- import { Fragment as Fragment12, jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
3470
+ import { Fragment as Fragment13, jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
3451
3471
  function SectionHeader({ title, chevron = false, icon, isExpanded = true, onToggle, trailing, count, actions, menu, menuLabel, showActions = "hover", hover = "fill", look = "heading", render, className }) {
3452
3472
  const row = look === "row";
3453
3473
  const acts = actions && actions.length > 0 || menu != null;
@@ -3461,7 +3481,7 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3461
3481
  // row itself carried the click.
3462
3482
  // An icon is a row's: NavItem's 8px after it.
3463
3483
  className: cn("flex h-full min-w-0 flex-1 items-center text-left", row || chevron || icon != null ? "gap-2" : "gap-1"),
3464
- children: /* @__PURE__ */ jsxs33(Fragment12, { children: [
3484
+ children: /* @__PURE__ */ jsxs33(Fragment13, { children: [
3465
3485
  icon != null ? /* @__PURE__ */ jsxs33("span", { className: "relative flex size-4 shrink-0 items-center justify-center text-text-secondary", children: [
3466
3486
  /* @__PURE__ */ jsx50("span", { className: cn("flex", chevron && "transition-opacity group-hover:opacity-0 group-has-[:focus-visible]:opacity-0"), children: icon }),
3467
3487
  chevron && /* @__PURE__ */ jsx50(
@@ -3575,7 +3595,7 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
3575
3595
  }
3576
3596
 
3577
3597
  // src/NavTree.tsx
3578
- import { Fragment as Fragment13, jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
3598
+ import { Fragment as Fragment14, jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
3579
3599
  var NAV_TREE_INTENT_MS = 150;
3580
3600
  function holds(nodes, id) {
3581
3601
  return !!nodes && id !== void 0 && nodes.some((node) => node.id === id || holds(node.children ?? null, id));
@@ -3665,7 +3685,7 @@ function NavTreeSection({ id, title, message, loading = false, pending, trailing
3665
3685
  );
3666
3686
  }
3667
3687
  function NavTree({ title, titleActions, groups, children, selected, onSelect, emptyMessage = "", storageKey }) {
3668
- return /* @__PURE__ */ jsxs35(Fragment13, { children: [
3688
+ return /* @__PURE__ */ jsxs35(Fragment14, { children: [
3669
3689
  title && /* @__PURE__ */ jsx52(SectionHeader, { title, look: "quiet", showActions: "always", actions: titleActions, className: "mt-4 shrink-0" }),
3670
3690
  groups === void 0 ? children : groups === null ? /* @__PURE__ */ jsx52(SkeletonList, { rows: 5 }) : groups.length === 0 ? (
3671
3691
  // No words, no line: an app that says nothing when it has no groups.
@@ -4185,7 +4205,7 @@ function ListColumn(props) {
4185
4205
 
4186
4206
  // src/Tabs.tsx
4187
4207
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
4188
- import { Fragment as Fragment14, jsx as jsx66, jsxs as jsxs46 } from "react/jsx-runtime";
4208
+ import { Fragment as Fragment15, jsx as jsx66, jsxs as jsxs46 } from "react/jsx-runtime";
4189
4209
  function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
4190
4210
  return /* @__PURE__ */ jsx66(
4191
4211
  BaseTabs.Root,
@@ -4219,7 +4239,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
4219
4239
  tab.label,
4220
4240
  tab.count !== void 0 ? /* @__PURE__ */ jsx66("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
4221
4241
  ] }),
4222
- tab.unread ? /* @__PURE__ */ jsxs46(Fragment14, { children: [
4242
+ tab.unread ? /* @__PURE__ */ jsxs46(Fragment15, { children: [
4223
4243
  /* @__PURE__ */ jsx66(UnreadDot, { className: "h-auto w-auto" }),
4224
4244
  /* @__PURE__ */ jsx66("span", { className: "sr-only", children: "new" })
4225
4245
  ] }) : null