@estiva-app/ui 0.8.0 → 0.10.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 (153) hide show
  1. package/dist/Avatar.d.ts +13 -1
  2. package/dist/Avatar.d.ts.map +1 -1
  3. package/dist/AvatarGroup.d.ts.map +1 -1
  4. package/dist/Banner.d.ts +16 -1
  5. package/dist/Banner.d.ts.map +1 -1
  6. package/dist/Breadcrumb.d.ts +9 -0
  7. package/dist/Breadcrumb.d.ts.map +1 -1
  8. package/dist/Button.d.ts +12 -2
  9. package/dist/Button.d.ts.map +1 -1
  10. package/dist/Checkbox.d.ts +2 -0
  11. package/dist/Checkbox.d.ts.map +1 -1
  12. package/dist/Chip.d.ts +3 -2
  13. package/dist/Chip.d.ts.map +1 -1
  14. package/dist/ChipInput.d.ts +3 -1
  15. package/dist/ChipInput.d.ts.map +1 -1
  16. package/dist/ConfirmDialog.d.ts +5 -0
  17. package/dist/ConfirmDialog.d.ts.map +1 -1
  18. package/dist/DialogShell.d.ts +27 -3
  19. package/dist/DialogShell.d.ts.map +1 -1
  20. package/dist/EditableText.d.ts +6 -0
  21. package/dist/EditableText.d.ts.map +1 -1
  22. package/dist/Field.d.ts +42 -25
  23. package/dist/Field.d.ts.map +1 -1
  24. package/dist/IconButton.d.ts +3 -2
  25. package/dist/IconButton.d.ts.map +1 -1
  26. package/dist/IdentityMenu.d.ts +25 -13
  27. package/dist/IdentityMenu.d.ts.map +1 -1
  28. package/dist/Menu.d.ts +65 -82
  29. package/dist/Menu.d.ts.map +1 -1
  30. package/dist/PersonTrigger.d.ts.map +1 -1
  31. package/dist/Popover.d.ts +86 -0
  32. package/dist/Popover.d.ts.map +1 -0
  33. package/dist/PreviewCard.d.ts +39 -0
  34. package/dist/PreviewCard.d.ts.map +1 -0
  35. package/dist/Reaction.d.ts.map +1 -1
  36. package/dist/ReactionPicker.d.ts +55 -0
  37. package/dist/ReactionPicker.d.ts.map +1 -0
  38. package/dist/SearchInput.d.ts +5 -0
  39. package/dist/SearchInput.d.ts.map +1 -1
  40. package/dist/Select.d.ts +26 -16
  41. package/dist/Select.d.ts.map +1 -1
  42. package/dist/Tabs.d.ts +11 -1
  43. package/dist/Tabs.d.ts.map +1 -1
  44. package/dist/TextInput.d.ts +7 -1
  45. package/dist/TextInput.d.ts.map +1 -1
  46. package/dist/Textarea.d.ts +8 -1
  47. package/dist/Textarea.d.ts.map +1 -1
  48. package/dist/Toolbar.d.ts +95 -0
  49. package/dist/Toolbar.d.ts.map +1 -0
  50. package/dist/Tooltip.d.ts +36 -10
  51. package/dist/Tooltip.d.ts.map +1 -1
  52. package/dist/cn.d.ts.map +1 -1
  53. package/dist/fit.d.ts +7 -72
  54. package/dist/fit.d.ts.map +1 -1
  55. package/dist/index.d.ts +6 -3
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +882 -763
  58. package/dist/index.js.map +4 -4
  59. package/package.json +1 -1
  60. package/src/Avatar.mdx +17 -0
  61. package/src/Avatar.name.test.tsx +99 -0
  62. package/src/Avatar.tsx +25 -3
  63. package/src/AvatarGroup.tsx +4 -1
  64. package/src/Banner.mdx +10 -2
  65. package/src/Banner.stories.tsx +29 -0
  66. package/src/Banner.test.tsx +60 -0
  67. package/src/Banner.tsx +35 -3
  68. package/src/Breadcrumb.mdx +5 -2
  69. package/src/Breadcrumb.test.tsx +44 -0
  70. package/src/Breadcrumb.tsx +10 -2
  71. package/src/Button.compose.test.tsx +119 -0
  72. package/src/Button.mdx +7 -5
  73. package/src/Button.test.tsx +2 -1
  74. package/src/Button.tsx +21 -5
  75. package/src/Checkbox.tsx +3 -0
  76. package/src/Chip.tsx +3 -2
  77. package/src/ChipInput.tsx +4 -0
  78. package/src/ConfirmDialog.mdx +20 -1
  79. package/src/ConfirmDialog.test.tsx +109 -0
  80. package/src/ConfirmDialog.tsx +6 -0
  81. package/src/DialogShell.mdx +18 -4
  82. package/src/DialogShell.stories.tsx +56 -6
  83. package/src/DialogShell.test.tsx +184 -0
  84. package/src/DialogShell.tsx +108 -39
  85. package/src/EditableText.mdx +6 -1
  86. package/src/EditableText.test.tsx +156 -0
  87. package/src/EditableText.tsx +23 -5
  88. package/src/Field.mdx +23 -3
  89. package/src/Field.stories.tsx +35 -0
  90. package/src/Field.test.tsx +117 -27
  91. package/src/Field.tsx +86 -58
  92. package/src/IconButton.mdx +6 -2
  93. package/src/IconButton.test.tsx +5 -2
  94. package/src/IconButton.tsx +12 -6
  95. package/src/IdentityMenu.mdx +29 -6
  96. package/src/IdentityMenu.stories.tsx +41 -6
  97. package/src/IdentityMenu.tsx +74 -47
  98. package/src/Kbd.stories.tsx +3 -3
  99. package/src/Menu.mdx +88 -75
  100. package/src/Menu.stories.tsx +120 -52
  101. package/src/Menu.test.tsx +315 -0
  102. package/src/Menu.tsx +341 -251
  103. package/src/MenuItem.stories.tsx +135 -98
  104. package/src/NavItem.mdx +1 -1
  105. package/src/PersonTrigger.mdx +20 -14
  106. package/src/PersonTrigger.tsx +23 -1
  107. package/src/Popover.mdx +130 -0
  108. package/src/Popover.stories.tsx +222 -0
  109. package/src/Popover.test.tsx +188 -0
  110. package/src/Popover.tsx +153 -0
  111. package/src/PreviewCard.mdx +98 -0
  112. package/src/PreviewCard.stories.tsx +168 -0
  113. package/src/PreviewCard.test.tsx +83 -0
  114. package/src/PreviewCard.tsx +91 -0
  115. package/src/Rail.mdx +63 -0
  116. package/src/Rail.stories.tsx +81 -0
  117. package/src/Reaction.mdx +4 -2
  118. package/src/Reaction.tsx +4 -2
  119. package/src/ReactionPicker.mdx +85 -0
  120. package/src/ReactionPicker.stories.tsx +120 -0
  121. package/src/ReactionPicker.test.tsx +118 -0
  122. package/src/ReactionPicker.tsx +88 -0
  123. package/src/SearchInput.mdx +6 -2
  124. package/src/SearchInput.tsx +7 -1
  125. package/src/Select.mdx +16 -5
  126. package/src/Select.test.tsx +157 -0
  127. package/src/Select.tsx +89 -214
  128. package/src/Sidebar.mdx +6 -2
  129. package/src/Tabs.mdx +5 -0
  130. package/src/Tabs.test.tsx +15 -0
  131. package/src/Tabs.tsx +17 -2
  132. package/src/TextInput.mdx +8 -2
  133. package/src/TextInput.tsx +10 -7
  134. package/src/Textarea.mdx +6 -2
  135. package/src/Textarea.tsx +14 -9
  136. package/src/Toolbar.mdx +104 -0
  137. package/src/Toolbar.stories.tsx +142 -0
  138. package/src/Toolbar.test.tsx +198 -0
  139. package/src/Toolbar.tsx +158 -0
  140. package/src/Tooltip.mdx +43 -5
  141. package/src/Tooltip.stories.tsx +26 -0
  142. package/src/Tooltip.test.tsx +195 -0
  143. package/src/Tooltip.tsx +150 -48
  144. package/src/cn.ts +1 -1
  145. package/src/fit.test.ts +101 -0
  146. package/src/fit.ts +19 -63
  147. package/src/index.ts +6 -3
  148. package/stories/Choosing.mdx +8 -3
  149. package/stories/TokensPage.tsx +6 -2
  150. package/tailwind-preset.js +12 -0
  151. package/tokens.css +8 -0
  152. package/src/Menu.fit.test.ts +0 -90
  153. package/src/Select.fit.test.ts +0 -101
package/dist/Menu.d.ts CHANGED
@@ -1,79 +1,14 @@
1
- import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
- /**
3
- * THE menu shell (2026-09-01) — extracted once, for every menu in every app.
4
- *
5
- * Peek has no single Menu file; its topic menu, conversation menus, files
6
- * menu and the top bar's account menu each hand-roll the same thing, and
7
- * they disagree: some close on Escape, most do not, and row heights and
8
- * minimum widths drift copy by copy. Ship extracted the shape so it would
9
- * not become the next copy; the package exists so nobody becomes the one
10
- * after that.
11
- *
12
- * What every menu shares, kept exactly: an elevated container with a
13
- * hairline border, 8px radius, 8px padding and the large shadow; items that
14
- * are 8px-radius rows, `px-2 py-1.5`, hover fill, 14px text, destructive
15
- * ones in the error colour; section headings as a SectionLabel in a 32px
16
- * row; and the two exits every menu has — Escape and a click outside —
17
- * owned by the menu, never copied into a caller.
18
- *
19
- * Where it goes is owned here too (2026-09-03), because the two ways a menu
20
- * goes wrong are both placement: it opens inside a stacking context or a
21
- * scroll container and something covers or clips it, or it opens near an
22
- * edge and runs off the screen. Both shipped — the identity menu vanished
23
- * under a z-indexed panel header, a submenu was cut by the right edge — so
24
- * the shell now portals to the body (nothing in an app can cover the body's
25
- * last child at z-50) and fits itself to the viewport (fit.ts, the same
26
- * measured geometry Select uses). A caller hands over a trigger, not
27
- * coordinates.
28
- *
29
- * Three anchorings, in order of preference:
30
- * - `anchor` (an element, usually the trigger): portalled, measured, and
31
- * placed by `fitMenu` — under the anchor, flipped above when the room
32
- * below is worse, clamped inside the viewport, height-capped with its own
33
- * scrollbar. `align="right"` hangs the menu's right edge from the
34
- * anchor's. Closes on resize and on any page scroll, because both move
35
- * the anchor out from under it.
36
- * - `position` (viewport coordinates the caller computed): portalled and
37
- * clamped (`clampBox`) — the caller's corner survives, but can no longer
38
- * land off screen.
39
- * - neither: in-flow under a `relative` wrapper, right-aligned. For stories
40
- * and static surfaces only — inside an app this mode inherits every
41
- * ancestor's stacking context and clip, which is how the identity menu
42
- * got covered.
43
- */
44
- export interface MenuProps {
45
- onClose: () => void;
46
- /** The trigger — an element, or the rect a click handler already measured.
47
- * The menu portals to the body and places itself against it. */
48
- anchor?: HTMLElement | DOMRect | null;
49
- /** With `anchor`: which of the menu's edges hangs from the anchor's. Default left. */
50
- align?: 'left' | 'right';
51
- /** Viewport coordinates; the menu is portalled, hung from `top`, aligned to whichever edge is given, and clamped on screen. */
52
- position?: {
53
- top: number;
54
- right: number;
55
- } | {
56
- top: number;
57
- left: number;
58
- };
59
- /** Close 150ms after the pointer leaves the menu — the hover-flow menus
60
- * (quick-menu cards) dismiss this way. The grace period is shared with any
61
- * open MenuSub panel, so crossing into a portalled submenu never counts as
62
- * leaving. */
63
- closeOnLeave?: boolean;
64
- children: ReactNode;
65
- className?: string;
66
- }
1
+ import { type ComponentPropsWithRef, type ReactElement, type ReactNode, type RefObject } from 'react';
67
2
  /**
68
3
  * The menu's surface, with none of its behaviour — an elevated box with a
69
4
  * hairline border, 8px radius, 8px padding and the large shadow.
70
5
  *
71
- * Split out of `Menu` on 2026-09-05. `Menu` owns Escape, outside-click and
72
- * placement, and that is right for a menu opened from a trigger — but a
73
- * type-ahead popup inside a text editor cannot have them: the editor's
74
- * suggestion plugin already owns the keyboard and positions the popup, and a
75
- * second Escape handler fights it. So Peek's `@`, `/` and `[` menus each drew
76
- * this box by hand, and the three had already drifted apart.
6
+ * Split out of `Menu` on 2026-09-05. `Menu` owns Escape, outside-click,
7
+ * placement and now the keyboard, and that is right for a menu opened from a
8
+ * trigger — but a type-ahead popup inside a text editor cannot have them: the
9
+ * editor's suggestion plugin already owns the keyboard and positions the
10
+ * popup, and a second Escape handler fights it. So Peek's `@`, `/` and `[`
11
+ * menus each drew this box by hand, and the three had already drifted apart.
77
12
  *
78
13
  * `Menu` renders this, so there is still exactly one definition of the
79
14
  * surface — change it here and every menu in every app follows.
@@ -82,20 +17,60 @@ export interface MenuProps {
82
17
  * people is not the width of one that lists verbs.
83
18
  */
84
19
  export interface MenuPanelProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
85
- children: ReactNode;
20
+ /** Optional only because Base UI fills it in when this is a `render`
21
+ * target: `Menu.Popup` supplies the children. Every other caller passes
22
+ * them. */
23
+ children?: ReactNode;
86
24
  }
87
25
  export declare function MenuPanel({ children, className, ...props }: MenuPanelProps): import("react").JSX.Element;
88
- export declare function Menu({ onClose, anchor, align, position, closeOnLeave, children, className }: MenuProps): import("react").JSX.Element;
26
+ export interface MenuProps {
27
+ /**
28
+ * The control that opens the menu. Any element that forwards its ref and
29
+ * spreads its props — this package's `Button`, `IconButton` and
30
+ * `PersonTrigger` all do.
31
+ *
32
+ * The menu owns it, and that is the point: Base UI can only do the toggle,
33
+ * the placement, the focus return, the first-item highlight and the whole
34
+ * hover choreography if it knows which element opened it.
35
+ */
36
+ trigger: ReactElement;
37
+ /** Which of the menu's edges hangs from the trigger's. Default left. */
38
+ align?: 'left' | 'right';
39
+ /**
40
+ * Open on hover, and close shortly after the pointer leaves — for a control
41
+ * that only appears while the pointer is on a card.
42
+ *
43
+ * Base UI owns the whole choreography, including the diagonal from a row
44
+ * out to a submenu panel. The shell used to hand-write this and got it
45
+ * wrong in two directions.
46
+ */
47
+ openOnHover?: boolean;
48
+ /** Controlled, for a caller that must know or must force it. Leave both
49
+ * off and the menu keeps its own state. */
50
+ open?: boolean;
51
+ onOpenChange?: (open: boolean) => void;
52
+ /** Base UI's imperative handle. `actions.current?.close()` shuts the menu —
53
+ * for a row that must close it before opening what it opens. A `MenuItem`
54
+ * closes the menu by itself, so this is only for content that is not one. */
55
+ actionsRef?: RefObject<{
56
+ close: () => void;
57
+ unmount: () => void;
58
+ } | null>;
59
+ children: ReactNode;
60
+ /** On the menu's surface — its width, its internal rhythm. */
61
+ className?: string;
62
+ }
63
+ export declare function Menu({ trigger, align, openOnHover, open, onOpenChange, actionsRef, children, className }: MenuProps): import("react").JSX.Element;
89
64
  /**
90
65
  * A row that opens another menu beside it — the submenu two Peek menus
91
66
  * hand-rolled before this, one of which dropped the ref its edge-flip
92
67
  * measured and shipped a submenu cut off by the screen (2026-09-03).
93
68
  *
94
- * Hover-timed like those were: opens at once, closes 150ms after the
95
- * pointer leaves row and panel both, so the diagonal from row to panel
96
- * survives. The panel portals to the body and is placed by `fitSubmenu`
97
- * right of the row when it fits, left when it does not, never past an edge
98
- * so it also escapes whatever container its menu happens to be in.
69
+ * Hover-timed as those were, and as ours was: it opens at once and closes
70
+ * 150ms after the pointer leaves, so the diagonal from row to panel survives.
71
+ * Those two numbers are all that is left of the old implementation the
72
+ * placement, the flip at a screen edge, and now the arrow keys (→ opens it,
73
+ * closes it) are Base UI's.
99
74
  */
100
75
  export interface MenuSubProps {
101
76
  /** The trigger row's label. */
@@ -170,9 +145,17 @@ export declare function MenuItem({ label, children, size, description, leading,
170
145
  export declare function EnterHint({ target }: {
171
146
  target?: string;
172
147
  }): import("react").JSX.Element;
173
- /** A section heading inside a menu: the 32px row with a SectionLabel, read
174
- * secondary a heading inside a menu labels the rows, it is not one of
175
- * them (Katerina, 2026-09-01). */
148
+ /**
149
+ * A section heading inside a menu: the 32px row with a SectionLabel, read
150
+ * secondary — a heading inside a menu labels the rows, it is not one of
151
+ * them (Katerina, 2026-09-01).
152
+ *
153
+ * Inside a `Menu` it is Base UI's `Menu.Group` with the heading as its
154
+ * `GroupLabel`, so the rows under it are announced as a named group rather
155
+ * than as a run of items with a stray line above them. Outside one — the
156
+ * editor pickers, which draw the surface but not the menu — it is the two
157
+ * plain elements it has always been.
158
+ */
176
159
  export declare function MenuSection({ label, children, className }: {
177
160
  label: string;
178
161
  children: ReactNode; /** On the heading row — a surface whose rows are px-3 aligns its heading with px-3. */
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PersonTrigger.d.ts","sourceRoot":"","sources":["../src/PersonTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAKlD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AAEnD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACnD,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,+FAA+F;IAC/F,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAY,EAAE,OAAe,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,+BA8BtI"}
1
+ {"version":3,"file":"PersonTrigger.d.ts","sourceRoot":"","sources":["../src/PersonTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAKlD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AAEnD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACnD,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,+FAA+F;IAC/F,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAY,EAAE,OAAe,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,+BAoDtI"}
@@ -0,0 +1,86 @@
1
+ import { type ReactElement, type ReactNode, type RefObject } from 'react';
2
+ /**
3
+ * A floating panel from a trigger — the same elevated surface a `Menu` uses,
4
+ * with none of a menu's semantics. New at stage 4 (2026-09-07).
5
+ *
6
+ * **It exists because `Menu` was being used for this.** Peek's selection
7
+ * toolbar puts a text field inside one, and its debug panel fills one with
8
+ * toggle rows; neither is a list of actions, and since the menus moved onto
9
+ * Base UI a `Menu` gives its contents roving focus and typeahead, which is
10
+ * wrong for both and fights a text field outright. Beyond those two, Peek
11
+ * hand-writes overlay behaviour in thirteen files — six `createPortal`, five
12
+ * outside-click listeners, seven position calculations against
13
+ * `window.innerWidth` (`COMPONENTS-PEEK.md` F5). This is what they become.
14
+ *
15
+ * **The API is `Menu`'s**: it takes the `trigger` and owns everything after —
16
+ * the toggle, the placement, the dismissal and the focus return. What differs
17
+ * is inside: a `Popover` announces itself as a dialog, its contents are
18
+ * ordinary content, and Tab walks them in order.
19
+ *
20
+ * The one thing a `Menu` has no use for is the second mode below: a panel with
21
+ * no trigger element at all, hung from a rect the caller measured — a toolbar
22
+ * over a text selection. That mode is controlled, because there is nothing for
23
+ * Base UI to watch.
24
+ */
25
+ export interface PopoverProps {
26
+ /**
27
+ * The control that opens the panel. Any element that forwards its ref and
28
+ * spreads its props — this package's `Button`, `IconButton` and
29
+ * `PersonTrigger` all do.
30
+ *
31
+ * Base UI can only do the toggle, the placement, the dismissal and the focus
32
+ * return if it knows which element opened the panel. Give it the trigger
33
+ * unless there is genuinely no element to give — see `anchor`.
34
+ */
35
+ trigger?: ReactElement;
36
+ /**
37
+ * For a panel with **no trigger element**: an element, or a rect the caller
38
+ * measured — a text selection's. Pair it with `open`, since there is nothing
39
+ * for Base UI to watch.
40
+ *
41
+ * An anchored panel **does not take focus**, because the person is still in
42
+ * whatever produced it. That also means it cannot be reached by keyboard, so
43
+ * everything in one must be reachable another way.
44
+ *
45
+ * Render it always and toggle `open`; do not mount it only while it is open.
46
+ */
47
+ anchor?: HTMLElement | DOMRect | null;
48
+ /** Which of the panel's edges hangs from the trigger's. Default left. */
49
+ align?: 'left' | 'right';
50
+ /**
51
+ * Which side of the trigger, or of the anchor, the panel prefers. Default
52
+ * `bottom`.
53
+ *
54
+ * **A toolbar over a text selection wants `top`** (Katerina, 2026-09-08):
55
+ * below, it covers the line you are about to read next, and it is the line
56
+ * *after* the selection that tells you what you have selected. It is a
57
+ * preference, not a promise — Base UI flips it when that side has no room.
58
+ */
59
+ side?: 'top' | 'bottom';
60
+ /** Controlled, for a caller that must know or must force it. Required with
61
+ * `anchor`; with a `trigger`, leave both off and the panel keeps its own. */
62
+ open?: boolean;
63
+ onOpenChange?: (open: boolean) => void;
64
+ /**
65
+ * Where focus goes when the panel closes. With a `trigger` it goes back to
66
+ * the trigger and this is not needed. An anchored panel never took focus, so
67
+ * this only matters when something inside it did — a field the person tabbed
68
+ * or clicked into: point it at what they came from, or focus is left on the
69
+ * document body.
70
+ */
71
+ finalFocus?: RefObject<HTMLElement | null>;
72
+ /** Base UI's imperative handle. `actions.current?.close()` shuts the panel —
73
+ * for the Cancel and Save buttons a form panel ends with. */
74
+ actionsRef?: RefObject<{
75
+ close: () => void;
76
+ unmount: () => void;
77
+ } | null>;
78
+ /** Names the panel for assistive tech. A panel with a visible heading can
79
+ * point at it instead, with `aria-labelledby`. */
80
+ ariaLabel?: string;
81
+ children: ReactNode;
82
+ /** On the panel's surface — its width, its internal rhythm. */
83
+ className?: string;
84
+ }
85
+ export declare function Popover({ trigger, anchor, align, side, open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className }: PopoverProps): import("react").JSX.Element;
86
+ //# sourceMappingURL=Popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../src/Popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKlF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAAA;IACrC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;IACvB;kFAC8E;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC1C;kEAC8D;IAC9D,UAAU,CAAC,EAAE,SAAS,CAAC;QAAE,KAAK,EAAE,MAAM,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACzE;uDACmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;IACnB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAOD,wBAAgB,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAc,EAAE,IAAe,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,YAAY,+BA6DrK"}
@@ -0,0 +1,39 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * More of a thing, on hover — a card beside a row that is only a snippet.
4
+ * New at stage 4 (2026-09-07).
5
+ *
6
+ * **It exists because Peek's Screener preview is this, hand-written**: its own
7
+ * `createPortal`, its own "prefer the right, flip left if it would run off
8
+ * screen" arithmetic against `window.innerWidth`, and its own clamp against
9
+ * the bottom edge (`ScreenerPreviewCard.tsx`). Floating UI does all three.
10
+ *
11
+ * **Not a Tooltip.** A tooltip is a word for a control, is
12
+ * `pointer-events: none`, and may hold nothing you can reach. A preview card
13
+ * holds *content* — faces, text, a link — and you can move the pointer into
14
+ * it, which is what a preview is for. If what you have is a label, use
15
+ * `WithTooltip`.
16
+ *
17
+ * The surface is the package's elevated panel, the same one a `Menu` draws, so
18
+ * there is one definition of that box. Width, height and internal rhythm are
19
+ * the caller's: a preview of a conversation is not the size of a preview of a
20
+ * person.
21
+ */
22
+ export interface PreviewCardProps {
23
+ /** What the card holds. Rendered only while it is open. */
24
+ content: ReactNode;
25
+ /** The row, name or avatar the card previews. */
26
+ children: ReactNode;
27
+ /** Which side of the trigger to prefer. It flips when that side has no room. Default right. */
28
+ side?: 'top' | 'bottom' | 'left' | 'right';
29
+ /** Before it opens, in ms. Long enough that crossing a list does not flash a card at every row. */
30
+ delay?: number;
31
+ /** After the pointer leaves, in ms — the grace that lets you cross the gap into the card. */
32
+ closeDelay?: number;
33
+ /** On the card's surface: its width, its padding, a max height. */
34
+ className?: string;
35
+ /** Extra classes on the trigger wrapper — e.g. `block w-full` for a row. */
36
+ wrapperClassName?: string;
37
+ }
38
+ export declare function PreviewCard({ content, children, side, delay, closeDelay, className, wrapperClassName }: PreviewCardProps): import("react").JSX.Element;
39
+ //# sourceMappingURL=PreviewCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewCard.d.ts","sourceRoot":"","sources":["../src/PreviewCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,OAAO,EAAE,SAAS,CAAA;IAClB,iDAAiD;IACjD,QAAQ,EAAE,SAAS,CAAA;IACnB,+FAA+F;IAC/F,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC1C,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAmBD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAc,EAAE,KAAkB,EAAE,UAAwB,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,gBAAgB,+BA+B7J"}
@@ -1 +1 @@
1
- {"version":3,"file":"Reaction.d.ts","sourceRoot":"","sources":["../src/Reaction.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC9F,0EAA0E;IAC1E,KAAK,EAAE,SAAS,CAAA;IAChB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAe,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,+BA8BnG"}
1
+ {"version":3,"file":"Reaction.d.ts","sourceRoot":"","sources":["../src/Reaction.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC9F,0EAA0E;IAC1E,KAAK,EAAE,SAAS,CAAA;IAChB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAe,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,+BAgCnG"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The reactions on offer, to choose one from — Peek's `ReactionPicker`
3
+ * (2026-09-03), moved in at Katerina's request (2026-09-08).
4
+ *
5
+ * **`Reaction` is the answer; this is the question.** A `Reaction` is a pill
6
+ * that says an emoji, a count and whether it is yours. This is the row you
7
+ * pick from before any of that exists, and both apps need it: Peek draws one
8
+ * from a card's action strip (`ConversationQuickMenu`), and Ship draws the
9
+ * same row in `Reactions.tsx` from its own vocabulary.
10
+ *
11
+ * **It is a `Toolbar`** — icon buttons holding emoji, on the strip's own
12
+ * elevated box — so the whole row is one Tab stop and the arrow keys walk it.
13
+ * Peek's was five separate stops.
14
+ *
15
+ * ## What stays with the app
16
+ *
17
+ * **Which emoji, and what each one means.** Peek offers five and names them
18
+ * ("Makes sense", "Agree", "Thank you", "Let's go!", "Congrats"); Ship will
19
+ * offer its own. A vocabulary is product knowledge, so it arrives as
20
+ * `options` — and the name is not optional, because the emoji is decorative
21
+ * here for the same reason it is on `Reaction`: a glyph read aloud is noise,
22
+ * and its spoken name differs per screen reader.
23
+ *
24
+ * ## Picking, and nothing else
25
+ *
26
+ * **It does not show which reactions are yours.** That is `Reaction`'s job —
27
+ * the pill with the count and the accent fill — and the two live in different
28
+ * places: the reactions *made* sit in a row on the card, and this row is what
29
+ * opens over it when you go to add one. A picker that also reported state
30
+ * would be two components wearing one name (Katerina, 2026-09-08).
31
+ */
32
+ export interface ReactionOption {
33
+ /** The emoji itself. Drawn decoratively — `label` names the control. */
34
+ emoji: string;
35
+ /** What this reaction *means*: "Makes sense", "Congrats". Required, and it
36
+ * is what a screen reader and the tooltip both say. */
37
+ label: string;
38
+ }
39
+ export interface ReactionPickerProps {
40
+ /** What is on offer, in the order it is drawn. The app's vocabulary. */
41
+ options: ReactionOption[];
42
+ onSelect: (emoji: string) => void;
43
+ /** Names the row. Default "Reactions". */
44
+ 'aria-label'?: string;
45
+ /**
46
+ * The elevated box around the row, from `Toolbar`. **On by default**, which
47
+ * is how a picker floats over a card. Off inside a `Popover`, which draws
48
+ * that box already.
49
+ */
50
+ surface?: boolean;
51
+ /** The row's layout — its gap, its padding. */
52
+ className?: string;
53
+ }
54
+ export declare function ReactionPicker({ options, onSelect, 'aria-label': ariaLabel, surface, className }: ReactionPickerProps): import("react").JSX.Element;
55
+ //# sourceMappingURL=ReactionPicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReactionPicker.d.ts","sourceRoot":"","sources":["../src/ReactionPicker.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb;4DACwD;IACxD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAuB,EAAE,OAAc,EAAE,SAAS,EAAE,EAAE,mBAAmB,+BA6B1I"}
@@ -11,6 +11,11 @@ import { type InputHTMLAttributes } from 'react';
11
11
  * In Peek's top bar this is a launcher affordance rather than a live field:
12
12
  * the input is `pointer-events-none` and clicking the surround opens the
13
13
  * command launcher. The component is the same either way.
14
+ *
15
+ * On Base UI's `Input` since stage 3 of the migration (2026-09-07), so a
16
+ * search field inside a `Field` is labelled by it without the caller wiring
17
+ * an id. The surround stays ours: the border, the focus-within rule and the
18
+ * `Kbd` hint are this component's, not the input's.
14
19
  */
15
20
  export interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className'> {
16
21
  /** A keyboard hint drawn at the right edge, e.g. "Ctrl+K". */
@@ -1 +1 @@
1
- {"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../src/SearchInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAIhD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAChG,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAuB,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,+BAkBvG"}
1
+ {"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../src/SearchInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAKhD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAChG,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAuB,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,+BAkBvG"}
package/dist/Select.d.ts CHANGED
@@ -1,20 +1,30 @@
1
- import { type ReactNode } from 'react';
1
+ import type { ReactNode } from 'react';
2
2
  /**
3
3
  * Peek's Select (2026-08-28), verbatim, plus what Ship added: an option may
4
4
  * carry a `leading` node — an avatar beside a person's name — shown in the
5
- * trigger and in the list.
5
+ * trigger and in the list. On Base UI's `Select` since stage 4 of the
6
+ * migration (2026-09-07).
6
7
  *
7
- * A button that opens a portalled listbox under itself: arrows move (and keep
8
- * the active option scrolled into view), Home and End jump, Enter and Space
9
- * pick, Escape closes and returns focus to the trigger, Tab closes, a click
10
- * outside closes, a PAGE scroll or resize closes (the list is fixed to where
11
- * the trigger was) — a scroll *inside* the list is the list's own business
12
- * and must not dismiss it. The menu keeps itself on screen: clamped to the
13
- * viewport's sides, height capped to the space it actually has, opening
14
- * upward when the room below is worse than the room above (Katerina,
15
- * 2026-09-01 the files-panel picker was cut right and bottom, and its own
16
- * scroll closed it). Two sizes; `disabled` explains nothing by itself wrap
17
- * it in a tooltip that does.
8
+ * A button that shows the choice and opens a listbox under it. **Under it:
9
+ * Base UI would rather lay the list over the trigger so the chosen option's
10
+ * text covers the trigger's, the way macOS does `alignItemWithTrigger` is
11
+ * off, because every Select in both apps opens below one today (Katerina,
12
+ * D24).**
13
+ *
14
+ * What the port deleted: `createPortal`, the whole `onKeyDown` switch, the
15
+ * outside-click, resize and scroll listeners, the `aria-activedescendant`
16
+ * bookkeeping, the `scrollIntoView` that kept the highlight visible, and
17
+ * `fit.ts` the pure geometry this component grew and then shared with the
18
+ * Menu shell. Floating UI does the fitting; `--available-height` is where the
19
+ * old 288px cap now meets the room the screen actually has.
20
+ *
21
+ * What it gained, and none of it was written here: **typeahead** — type the
22
+ * first letters of an option and the list jumps to it — a listbox whose
23
+ * highlight is managed rather than counted, and a value that can be part of a
24
+ * form.
25
+ *
26
+ * Two sizes; `disabled` explains nothing by itself — wrap it in a tooltip
27
+ * that does.
18
28
  */
19
29
  export interface SelectOption {
20
30
  value: string;
@@ -28,11 +38,11 @@ export interface SelectProps {
28
38
  options: SelectOption[];
29
39
  size?: 'default' | 'small';
30
40
  ariaLabel?: string;
41
+ /** Set by a `Field` with `required`; a caller inside one owes nothing. */
42
+ 'aria-required'?: boolean | 'true' | 'false';
31
43
  placeholder?: string;
32
44
  disabled?: boolean;
33
45
  className?: string;
34
46
  }
35
- import { fitMenu } from './fit';
36
- export { fitMenu };
37
- export declare function Select({ value, onChange, options, size, ariaLabel, placeholder, disabled, className }: SelectProps): import("react").JSX.Element;
47
+ export declare function Select({ value, onChange, options, size, ariaLabel, placeholder, disabled, className, ...aria }: SelectProps): import("react").JSX.Element;
38
48
  //# sourceMappingURL=Select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiG,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrI;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAKD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,CAAA;AAElB,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAgB,EAAE,SAAS,EAAE,WAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,WAAW,+BAwO1I"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAOD,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAgB,EAAE,SAAS,EAAE,WAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,WAAW,+BAgGnJ"}
package/dist/Tabs.d.ts CHANGED
@@ -30,8 +30,18 @@ export interface TabsProps<T extends string> {
30
30
  onChange: (id: T) => void;
31
31
  /** `default` 14px; `small` 12px, the denser geometry. */
32
32
  size?: 'default' | 'small';
33
+ /**
34
+ * Names the row for assistive tech — "Views", "Filters".
35
+ *
36
+ * A `tablist` with no name is announced as a bare "tab list", which says
37
+ * nothing and says the same nothing twice on a page with two of them
38
+ * (measured 2026-09-08: no name, and no way to give one). Where a visible
39
+ * heading already names it, point at that with `aria-labelledby` instead.
40
+ */
41
+ 'aria-label'?: string;
42
+ 'aria-labelledby'?: string;
33
43
  /** Lands on the outer box, around the row. */
34
44
  className?: string;
35
45
  }
36
- export declare function Tabs<T extends string>({ tabs, active, onChange, size, className }: TabsProps<T>): import("react").JSX.Element;
46
+ export declare function Tabs<T extends string>({ tabs, active, onChange, size, className, ...aria }: TabsProps<T>): import("react").JSX.Element;
37
47
  //# sourceMappingURL=Tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../src/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM;IACtC,EAAE,EAAE,CAAC,CAAA;IACL,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;IACzC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IACjB,MAAM,EAAE,CAAC,CAAA;IACT,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAA;IACzB,yDAAyD;IACzD,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAgB,EAAE,SAAS,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,+BA2C3G"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../src/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM;IACtC,EAAE,EAAE,CAAC,CAAA;IACL,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;IACzC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IACjB,MAAM,EAAE,CAAC,CAAA;IACT,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAA;IACzB,yDAAyD;IACzD,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAgB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,+BAgDpH"}
@@ -4,7 +4,13 @@ import { type InputHTMLAttributes } from 'react';
4
4
  * text, the focus border in every theme (Katerina, 2026-08-28: Ship's inputs
5
5
  * focus like Signal's) — and Signal's glow on top.
6
6
  * Plus a disabled look (Ship's addition): the disabled surface and text,
7
- * no pointer.
7
+ * no pointer. On Base UI's `Input` since stage 3 of the migration
8
+ * (2026-09-07).
9
+ *
10
+ * Base UI's `Input` is a native `<input>` that finds a surrounding `Field` on
11
+ * its own, so the id plumbing this used to do — `useFieldControlId`, and the
12
+ * context behind it — is gone. Outside a `Field` it behaves as before: the
13
+ * field context has a default, so nothing has to be wrapped.
8
14
  */
9
15
  export type TextInputProps = InputHTMLAttributes<HTMLInputElement>;
10
16
  export declare const TextInput: import("react").ForwardRefExoticComponent<TextInputProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAI5D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;AAElE,eAAO,MAAM,SAAS,6GAmBpB,CAAA"}
1
+ {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAI5D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;AAElE,eAAO,MAAM,SAAS,6GAgBpB,CAAA"}
@@ -1,7 +1,14 @@
1
1
  import { type TextareaHTMLAttributes } from 'react';
2
2
  /**
3
3
  * Peek's Textarea (2026-08-28), verbatim: TextInput's look on a textarea
4
- * that does not resize. Plus a disabled look (Ship's addition).
4
+ * that does not resize. Plus a disabled look (Ship's addition). On Base UI's
5
+ * `Field.Control` since stage 3 of the migration (2026-09-07).
6
+ *
7
+ * Base UI has an `Input` part but no textarea, so this is `Field.Control`
8
+ * rendering a `<textarea>` — the same part `Input` is built on, told which
9
+ * element to be. It finds a surrounding `Field` on its own, which is what
10
+ * retired `useFieldControlId`; outside one it renders a plain textarea, as
11
+ * before.
5
12
  */
6
13
  export type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement>;
7
14
  export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaProps & import("react").RefAttributes<HTMLTextAreaElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../src/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,sBAAsB,EAAE,MAAM,OAAO,CAAA;AAI/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAEvE,eAAO,MAAM,QAAQ,+GAkBnB,CAAA"}
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../src/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,sBAAsB,EAAE,MAAM,OAAO,CAAA;AAI/D;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAEvE,eAAO,MAAM,QAAQ,+GAgBnB,CAAA"}