@estiva-app/ui 0.60.2 → 0.62.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.
@@ -21,13 +21,16 @@ export interface MembersDialogProps {
21
21
  /** The number in the title's chip. Defaults to how many rows there are. */
22
22
  count?: number;
23
23
  /**
24
- * The viewer's own row on top: "Join" when they are not in, "Leave" when
25
- * they are. Absent while it is not known, or where they cannot change it —
26
- * no row is better than a wrong one.
24
+ * What the viewer can do: "Leave" on their own row when they are in, which
25
+ * is drawn first; a "Join" row on top when they are not. Absent while it is
26
+ * not known, or where they cannot change it — no button is better than a
27
+ * wrong one.
27
28
  */
28
29
  self?: {
29
30
  action: MembersDialogSelfAction;
30
31
  onToggle: () => void | Promise<unknown>;
32
+ /** The viewer's id: the row in `members` that carries Leave and comes first. */
33
+ id: string;
31
34
  };
32
35
  /** Who "Add members" may offer. Members are left out by id. */
33
36
  candidates?: MembersDialogCandidate[];
@@ -49,8 +52,10 @@ export interface MembersDialogProps {
49
52
  *
50
53
  * Moved from Peek's `MembersDialog` (2026-10-06; Katerina's design of 22 July,
51
54
  * with the row and inset rulings of 15 September). Two layers in one dialog:
52
- * the roster, with the viewer's Join or Leave and "Add members" on top, and the
53
- * add layer, whose back arrow returns to the roster. Adding returns to the
55
+ * the roster, with "Add members" (and Join, for a non-member) on top, and the
56
+ * add layer, whose back arrow returns to the roster. Leave is a small red
57
+ * button on the viewer's own row, which always comes first (Katerina, 8
58
+ * October: a Leave row on top looked like an invite, the same as Add members). Adding returns to the
54
59
  * roster so the new people are visible at once.
55
60
  */
56
61
  export declare function MembersDialog({ members, count, self, candidates, onAdd, note, initialView, onClose }: MembersDialogProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"MembersDialog.d.ts","sourceRoot":"","sources":["../src/MembersDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKvD,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAO7D,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,oFAAoF;AACpF,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAA;AAEtD,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,uBAAuB,CAAA;QAC/B,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KACxC,CAAA;IACD,+DAA+D;IAC/D,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,KAAK,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAA;IACtF,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAID;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAe,EAAE,KAAK,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,EAAE,kBAAkB,+BAgHtI"}
1
+ {"version":3,"file":"MembersDialog.d.ts","sourceRoot":"","sources":["../src/MembersDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKvD,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAO7D,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,oFAAoF;AACpF,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAA;AAEtD,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,uBAAuB,CAAA;QAC/B,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;QACvC,gFAAgF;QAChF,EAAE,EAAE,MAAM,CAAA;KACX,CAAA;IACD,+DAA+D;IAC/D,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,KAAK,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAA;IACtF,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAe,EAAE,KAAK,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,EAAE,kBAAkB,+BA0HtI"}
@@ -14,6 +14,10 @@ import { type ReactNode } from 'react';
14
14
  *
15
15
  * Focus arriving inside the cut content opens it: a field or a link there,
16
16
  * reached by Tab or a click, is never worked on out of sight.
17
+ *
18
+ * `action` is one more small button on the toggle's row, at its right
19
+ * (Katerina, 8 October: Peek's block card puts "Open in Estiva Ship" level with
20
+ * Show more). The row is drawn for it whether or not the content is cut.
17
21
  */
18
22
  export interface ShowMoreProps {
19
23
  children: ReactNode;
@@ -21,7 +25,9 @@ export interface ShowMoreProps {
21
25
  maxHeight?: number;
22
26
  /** What the content sits on, for the fade to end in: a panel's `surface` (default), or an inset card's `inset`. */
23
27
  surface?: 'surface' | 'inset';
28
+ /** A small muted `Button` with a leading icon, at the right of the toggle's row: the way out to where the content lives. Its words end where the content does. */
29
+ action?: ReactNode;
24
30
  className?: string;
25
31
  }
26
- export declare function ShowMore({ children, maxHeight, surface, className }: ShowMoreProps): import("react").JSX.Element;
32
+ export declare function ShowMore({ children, maxHeight, surface, action, className }: ShowMoreProps): import("react").JSX.Element;
27
33
  //# sourceMappingURL=ShowMore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShowMore.d.ts","sourceRoot":"","sources":["../src/ShowMore.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,SAAS,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mHAAmH;IACnH,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAc,EAAE,OAAmB,EAAE,SAAS,EAAE,EAAE,aAAa,+BA+BnG"}
1
+ {"version":3,"file":"ShowMore.d.ts","sourceRoot":"","sources":["../src/ShowMore.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,SAAS,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mHAAmH;IACnH,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B,kKAAkK;IAClK,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAc,EAAE,OAAmB,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,aAAa,+BAkC3G"}
package/dist/index.js CHANGED
@@ -1731,6 +1731,9 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1731
1731
  setChosen([]);
1732
1732
  setView("list");
1733
1733
  };
1734
+ const ownRow = self?.action === "leave" ? members.find((m) => m.id === self.id) : void 0;
1735
+ const roster = ownRow ? [ownRow, ...members.filter((m) => m !== ownRow)] : members;
1736
+ const selfOnTop = self && !ownRow;
1734
1737
  if (view === "add" && onAdd) {
1735
1738
  return /* @__PURE__ */ jsx26(
1736
1739
  DialogShell,
@@ -1774,8 +1777,8 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1774
1777
  bodyMaxHeight: "max-h-[400px]",
1775
1778
  bodyClassName: "p-0 py-2",
1776
1779
  children: [
1777
- (self || onAdd) && /* @__PURE__ */ jsxs17("div", { className: "flex flex-col px-2", children: [
1778
- self && /* @__PURE__ */ jsx26(
1780
+ (selfOnTop || onAdd) && /* @__PURE__ */ jsxs17("div", { className: "flex flex-col px-2", children: [
1781
+ selfOnTop && /* @__PURE__ */ jsx26(
1779
1782
  MenuItem,
1780
1783
  {
1781
1784
  size: "tall",
@@ -1797,12 +1800,13 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1797
1800
  }
1798
1801
  )
1799
1802
  ] }),
1800
- members.map((member) => /* @__PURE__ */ jsxs17("div", { className: "flex h-12 items-center gap-3 px-5", children: [
1803
+ roster.map((member) => /* @__PURE__ */ jsxs17("div", { className: "flex h-12 items-center gap-3 px-5", children: [
1801
1804
  /* @__PURE__ */ jsx26(Avatar, { size: 32, name: member.name, src: member.picture }),
1802
1805
  /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-[2px]", children: [
1803
1806
  /* @__PURE__ */ jsx26("div", { className: "truncate text-body-2 text-text-primary", children: member.name }),
1804
1807
  member.caption && /* @__PURE__ */ jsx26("div", { className: "truncate text-caption text-text-secondary", children: member.caption })
1805
- ] })
1808
+ ] }),
1809
+ member === ownRow && /* @__PURE__ */ jsx26(Button, { variant: "destructive", size: "small", disabled: toggling, onClick: () => void toggle(), children: "Leave" })
1806
1810
  ] }, member.id)),
1807
1811
  note && /* @__PURE__ */ jsx26("div", { className: "px-5 pb-2 pt-3 text-caption text-text-secondary", children: note })
1808
1812
  ]
@@ -3705,9 +3709,10 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
3705
3709
 
3706
3710
  // src/ShowMore.tsx
3707
3711
  import { useLayoutEffect as useLayoutEffect5, useRef as useRef13, useState as useState12 } from "react";
3712
+ import { IconChevronDown as IconChevronDown4, IconChevronUp } from "@tabler/icons-react";
3708
3713
  import { jsx as jsx54, jsxs as jsxs38 } from "react/jsx-runtime";
3709
3714
  var FADE_CLASSES = { surface: "from-bg-surface", inset: "from-bg-inset" };
3710
- function ShowMore({ children, maxHeight = 96, surface = "surface", className }) {
3715
+ function ShowMore({ children, maxHeight = 96, surface = "surface", action, className }) {
3711
3716
  const box = useRef13(null);
3712
3717
  const [open, setOpen] = useState12(false);
3713
3718
  const [overflows, setOverflows] = useState12(false);
@@ -3727,10 +3732,27 @@ function ShowMore({ children, maxHeight = 96, surface = "surface", className })
3727
3732
  children,
3728
3733
  cut && /* @__PURE__ */ jsx54("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-x-0 bottom-0 h-10 bg-gradient-to-t to-transparent", FADE_CLASSES[surface]) })
3729
3734
  ] }),
3730
- overflows && // `-ml-1.5`: the small button's own 6px inset, so its words start where the content's do.
3731
- /* @__PURE__ */ jsx54(Button, { variant: "muted", size: "small", className: "-ml-1.5 mt-1", "aria-expanded": open, onClick: () => setOpen((o) => !o), children: open ? "Show less" : "Show more" })
3735
+ action ? /* @__PURE__ */ jsxs38("div", { className: cn("mt-1 flex w-full items-center gap-2", overflows ? "justify-between" : "justify-end"), children: [
3736
+ overflows && /* @__PURE__ */ jsx54(Toggle, { open, onToggle: () => setOpen((o) => !o) }),
3737
+ /* @__PURE__ */ jsx54("div", { className: "-mr-2 flex shrink-0", children: action })
3738
+ ] }) : overflows && /* @__PURE__ */ jsx54(Toggle, { open, onToggle: () => setOpen((o) => !o), className: "mt-1" })
3732
3739
  ] });
3733
3740
  }
3741
+ function Toggle({ open, onToggle, className }) {
3742
+ const Icon = open ? IconChevronUp : IconChevronDown4;
3743
+ return /* @__PURE__ */ jsx54(
3744
+ Button,
3745
+ {
3746
+ variant: "outlined",
3747
+ size: "small",
3748
+ leadingIcon: /* @__PURE__ */ jsx54(Icon, { stroke: 1.5, className: "size-3.5" }),
3749
+ className,
3750
+ "aria-expanded": open,
3751
+ onClick: onToggle,
3752
+ children: open ? "Show less" : "Show more"
3753
+ }
3754
+ );
3755
+ }
3734
3756
 
3735
3757
  // src/Toolbar.tsx
3736
3758
  import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
@@ -3908,13 +3930,13 @@ function Property({ label, layout = "row", children, className }) {
3908
3930
  }
3909
3931
 
3910
3932
  // src/Reaction.tsx
3911
- import { Toggle } from "@base-ui/react/toggle";
3933
+ import { Toggle as Toggle2 } from "@base-ui/react/toggle";
3912
3934
  import { jsx as jsx61, jsxs as jsxs42 } from "react/jsx-runtime";
3913
3935
  function Reaction({ emoji, count, pressed = false, className, ...props }) {
3914
3936
  return (
3915
3937
  // @estiva-escape(no-copied-look): W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
3916
3938
  /* @__PURE__ */ jsxs42(
3917
- Toggle,
3939
+ Toggle2,
3918
3940
  {
3919
3941
  pressed,
3920
3942
  className: cn(