@tensor_1/react 2.26.2 → 2.27.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 (68) hide show
  1. package/README.md +51 -0
  2. package/dist/calendar-model.d.ts +4 -2
  3. package/dist/components/AppShell.d.ts +1 -1
  4. package/dist/components/AppShell.js +6 -2
  5. package/dist/components/Button.d.ts +28 -4
  6. package/dist/components/Button.js +19 -9
  7. package/dist/components/Card.d.ts +7 -1
  8. package/dist/components/Card.js +3 -3
  9. package/dist/components/Chip.d.ts +43 -0
  10. package/dist/components/Chip.js +73 -0
  11. package/dist/components/CollapsibleSection.d.ts +19 -1
  12. package/dist/components/CollapsibleSection.js +5 -2
  13. package/dist/components/CollapsibleSectionState.d.ts +11 -0
  14. package/dist/components/CollapsibleSectionState.js +67 -0
  15. package/dist/components/CommandPalette.d.ts +1 -1
  16. package/dist/components/CommandPalette.js +4 -1
  17. package/dist/components/DateRangePicker.js +3 -1
  18. package/dist/components/Dialogs.d.ts +54 -3
  19. package/dist/components/Dialogs.js +167 -6
  20. package/dist/components/Drawer.d.ts +6 -1
  21. package/dist/components/Drawer.js +5 -2
  22. package/dist/components/EmojiPicker.d.ts +3 -0
  23. package/dist/components/EmojiPicker.js +109 -54
  24. package/dist/components/Kbd.d.ts +27 -0
  25. package/dist/components/Kbd.js +45 -0
  26. package/dist/components/Menu.d.ts +51 -0
  27. package/dist/components/Menu.js +177 -0
  28. package/dist/components/Modal.d.ts +1 -1
  29. package/dist/components/Modal.js +4 -1
  30. package/dist/components/Pagination.d.ts +36 -5
  31. package/dist/components/Pagination.js +59 -37
  32. package/dist/components/Peek.d.ts +1 -1
  33. package/dist/components/Peek.js +6 -1
  34. package/dist/components/Popover.d.ts +15 -5
  35. package/dist/components/Popover.js +66 -6
  36. package/dist/components/SchedulingCalendar.d.ts +47 -2
  37. package/dist/components/SchedulingCalendar.js +69 -22
  38. package/dist/components/SearchSuggest.d.ts +1 -1
  39. package/dist/components/SearchSuggest.js +4 -1
  40. package/dist/components/Sidebar.d.ts +7 -2
  41. package/dist/components/Sidebar.js +15 -4
  42. package/dist/components/Stat.d.ts +16 -0
  43. package/dist/components/Stat.js +12 -5
  44. package/dist/components/Steps.d.ts +48 -0
  45. package/dist/components/Steps.js +42 -0
  46. package/dist/components/Toast.d.ts +2 -2
  47. package/dist/components/Toast.js +7 -2
  48. package/dist/components/Tooltip.d.ts +10 -4
  49. package/dist/components/Tooltip.js +2 -2
  50. package/dist/{emoji-image-WQLh8ZQP.d.cts → emoji-image-6mPZ15Zy.d.cts} +4 -1
  51. package/dist/emoji.cjs +326 -76
  52. package/dist/emoji.d.cts +3 -3
  53. package/dist/hooks/useAnchoredPosition.d.ts +13 -5
  54. package/dist/hooks/useAnchoredPosition.js +146 -15
  55. package/dist/index.cjs +2278 -1372
  56. package/dist/index.d.cts +622 -176
  57. package/dist/index.d.ts +10 -4
  58. package/dist/index.js +24 -2
  59. package/dist/labels-context.d.ts +72 -0
  60. package/dist/labels-context.js +23 -0
  61. package/dist/link.d.ts +20 -0
  62. package/dist/link.js +9 -0
  63. package/dist/{overlay-position-CEGSz6Z2.d.cts → overlay-position-Cjv5E7mn.d.cts} +7 -0
  64. package/dist/overlay-position.d.ts +7 -0
  65. package/dist/overlay-position.js +7 -2
  66. package/dist/rich-text.cjs +324 -74
  67. package/dist/rich-text.d.cts +3 -3
  68. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@ export { UseTableOptions, UseTableResult, useTable } from './hooks/useTable.js';
4
4
  export { UseVirtualRowsOptions, UseVirtualRowsResult, useVirtualRows } from './hooks/useVirtualRows.js';
5
5
  export { UseAnchoredPositionOptions, useAnchoredPosition } from './hooks/useAnchoredPosition.js';
6
6
  export { Align, Placement, PositionOptions, PositionResult, Rect, Side, Size, computePosition } from './overlay-position.js';
7
- export { Button, ButtonGroup, ButtonGroupProps, ButtonProps } from './components/Button.js';
7
+ export { Button, ButtonGroup, ButtonGroupProps, ButtonLink, ButtonLinkProps, ButtonProps, ButtonSize, ButtonVariant } from './components/Button.js';
8
+ export { UixLabels, UixLabelsProvider, UixLabelsProviderProps, useUixLabels } from './labels-context.js';
9
+ export { UixLinkProps, UixRenderLink, renderPlainLink } from './link.js';
8
10
  export { Input, InputGroup, InputGroupProps, InputProps } from './components/Input.js';
9
11
  export { Combobox, ComboboxProps } from './components/Combobox.js';
10
12
  export { ComboboxOption, filterComboboxOptions } from './combobox-model.js';
@@ -17,7 +19,7 @@ export { Radio, RadioGroup, RadioGroupProps, RadioProps } from './components/Rad
17
19
  export { Switch, SwitchProps } from './components/Switch.js';
18
20
  export { Field, FieldProps } from './components/Field.js';
19
21
  export { Modal, ModalProps } from './components/Modal.js';
20
- export { ConfirmDialog, ConfirmDialogProps, PromptDialog, PromptDialogProps } from './components/Dialogs.js';
22
+ export { ConfirmDialog, ConfirmDialogProps, Popconfirm, PopconfirmProps, PromptDialog, PromptDialogProps } from './components/Dialogs.js';
21
23
  export { Drawer, DrawerProps } from './components/Drawer.js';
22
24
  export { Peek, PeekProps } from './components/Peek.js';
23
25
  export { Card, CardLink, CardLinkProps, CardProps } from './components/Card.js';
@@ -46,6 +48,9 @@ export { PillTone, PillTreatment, StatusPill, StatusPillProps } from './componen
46
48
  export { Progress, ProgressProps } from './components/Progress.js';
47
49
  export { Meter, MeterProps, MeterTone } from './components/Meter.js';
48
50
  export { Stat, StatProps, StatTrend } from './components/Stat.js';
51
+ export { Chip, ChipGroup, ChipGroupProps, ChipProps } from './components/Chip.js';
52
+ export { Kbd, KbdCombo, KbdComboProps, KbdPlatform, KbdProps } from './components/Kbd.js';
53
+ export { DEFAULT_STEP_STATE_LABELS, Step, StepProps, StepState, StepStateLabels, Steps, StepsProps } from './components/Steps.js';
49
54
  export { Tooltip, TooltipProps } from './components/Tooltip.js';
50
55
  export { InfoTip, InfoTipProps } from './components/InfoTip.js';
51
56
  export { AccessStateProps, EmptyState, EmptyStateProps, ErrorState, ErrorStateProps, FilteredEmptyState, ForbiddenState, LoadingState, LoadingStateProps, NotFoundState, Skeleton, SkeletonProps, StateVariant } from './components/States.js';
@@ -64,6 +69,7 @@ export { Pipeline, PipelineProps, PipelineStage, PipelineStageProps, PipelineSta
64
69
  export { Flow, FlowNode, FlowNodeProps, FlowNodeState, FlowProps, FlowVariant } from './components/Flow.js';
65
70
  export { Note, NoteProps, NoteTone, Prose, ProseProps } from './components/Prose.js';
66
71
  export { Popover, PopoverProps } from './components/Popover.js';
72
+ export { Menu, MenuGroup, MenuGroupProps, MenuItem, MenuItemProps, MenuProps, MenuSeparator } from './components/Menu.js';
67
73
  export { CommandGroup, CommandGroupProps, CommandItem, CommandItemProps, CommandPalette, CommandPaletteProps } from './components/CommandPalette.js';
68
74
  export { Inbox, InboxDetail, InboxDetailProps, InboxItem, InboxItemProps, InboxList, InboxListProps, InboxProps } from './components/Inbox.js';
69
75
  export { Kanban, KanbanCard, KanbanCardProps, KanbanColumn, KanbanColumnProps, KanbanMoveDirection, KanbanProps } from './components/Kanban.js';
@@ -74,9 +80,9 @@ export { JsonPrimitive, JsonValue } from './json-value.js';
74
80
  export { DEFAULT_RULE_BUILDER_LABELS, RuleActionDefinition, RuleBuilder, RuleBuilderLabels, RuleBuilderProps, RuleFieldDefinition, RuleOperatorDefinition, RuleValueEditorProps } from './components/RuleBuilder.js';
75
81
  export { RuleAction, RuleCondition, RuleDefinition, RuleGroup, RuleValidationIssue, appendRuleNode, findRuleNodeDepth, isRuleGroup, mapRuleGroup, moveRuleNode, removeRuleNode, ruleDepth, summarizeRule, validateRuleDefinition } from './rule-builder-model.js';
76
82
  export { BuilderCanvas, BuilderCanvasItem, BuilderCanvasLabels, BuilderCanvasProps, BuilderPaletteItem, DEFAULT_BUILDER_CANVAS_LABELS } from './components/BuilderCanvas.js';
77
- export { DEFAULT_SCHEDULING_CALENDAR_LABELS, SchedulingCalendar, SchedulingCalendarEntry, SchedulingCalendarLabels, SchedulingCalendarOverlay, SchedulingCalendarProps, SchedulingCalendarView, SchedulingEntryState, SchedulingOverlayKind } from './components/SchedulingCalendar.js';
83
+ export { DEFAULT_SCHEDULING_CALENDAR_LABELS, SchedulingCalendar, SchedulingCalendarEntry, SchedulingCalendarLabels, SchedulingCalendarOverlay, SchedulingCalendarProps, SchedulingCalendarView, SchedulingDatePart, SchedulingEntryState, SchedulingOverlayKind } from './components/SchedulingCalendar.js';
78
84
  export { DEFAULT_DATE_RANGE_PICKER_LABELS, DateRangePicker, DateRangePickerLabels, DateRangePickerProps } from './components/DateRangePicker.js';
79
- export { CalendarDay, DateRangeValue, ZonedDateSpan, addCalendarDays, addCalendarMonths, buildMonthGrid, enumerateDateSpan, isDateInRange, isDateUnavailable, selectRangeDate, startOfMonth, toDateKey, zonedDateKey, zonedDateSpan } from './calendar-model.js';
85
+ export { CalendarDay, CalendarWeekday, DateRangeValue, ZonedDateSpan, addCalendarDays, addCalendarMonths, buildMonthGrid, enumerateDateSpan, isDateInRange, isDateUnavailable, selectRangeDate, startOfMonth, toDateKey, zonedDateKey, zonedDateSpan } from './calendar-model.js';
80
86
  export { DEFAULT_RELATIONSHIP_GRAPH_LABELS, RelationshipGraph, RelationshipGraphLabels, RelationshipGraphLegendItem, RelationshipGraphProps } from './components/RelationshipGraph.js';
81
87
  export { BoundedRelationshipGraph, LayeredColumn, LayeredEdgeClassification, LayeredEdgeKind, LayeredItem, LayeredLayout, LayeredLayoutOptions, LayeredNavigationKey, PositionedRelationshipNode, RelationshipGraphArrow, RelationshipGraphCluster, RelationshipGraphEdge, RelationshipGraphNode, RoutedEdge, boundRelationshipGraph, classifyLayeredEdges, clusterIdFor, layeredNeighbor, layoutLayeredGraph, layoutRelationshipGraph, relationshipNeighbors, traverseRelationshipNode, wrapEdgeLabel } from './relationship-graph-model.js';
82
88
  export { DEFAULT_MATCH_REVIEW_LABELS, MatchBulkResult, MatchReview, MatchReviewAction, MatchReviewCandidate, MatchReviewField, MatchReviewLabels, MatchReviewProps } from './components/MatchReview.js';
package/dist/index.js CHANGED
@@ -4,7 +4,9 @@ import { useTable } from "./hooks/useTable.js";
4
4
  import { useVirtualRows } from "./hooks/useVirtualRows.js";
5
5
  import { useAnchoredPosition } from "./hooks/useAnchoredPosition.js";
6
6
  import { computePosition } from "./overlay-position.js";
7
- import { Button, ButtonGroup } from "./components/Button.js";
7
+ import { Button, ButtonGroup, ButtonLink } from "./components/Button.js";
8
+ import { UixLabelsProvider, useUixLabels } from "./labels-context.js";
9
+ import { renderPlainLink } from "./link.js";
8
10
  import { Input, InputGroup } from "./components/Input.js";
9
11
  import { Combobox } from "./components/Combobox.js";
10
12
  import { filterComboboxOptions } from "./combobox-model.js";
@@ -17,7 +19,7 @@ import { Radio, RadioGroup } from "./components/Radio.js";
17
19
  import { Switch } from "./components/Switch.js";
18
20
  import { Field } from "./components/Field.js";
19
21
  import { Modal } from "./components/Modal.js";
20
- import { ConfirmDialog, PromptDialog } from "./components/Dialogs.js";
22
+ import { ConfirmDialog, Popconfirm, PromptDialog } from "./components/Dialogs.js";
21
23
  import { Drawer } from "./components/Drawer.js";
22
24
  import { Peek } from "./components/Peek.js";
23
25
  import { Card, CardLink } from "./components/Card.js";
@@ -60,6 +62,9 @@ import { StatusPill } from "./components/StatusPill.js";
60
62
  import { Progress } from "./components/Progress.js";
61
63
  import { Meter } from "./components/Meter.js";
62
64
  import { Stat } from "./components/Stat.js";
65
+ import { Chip, ChipGroup } from "./components/Chip.js";
66
+ import { Kbd, KbdCombo } from "./components/Kbd.js";
67
+ import { Steps, Step, DEFAULT_STEP_STATE_LABELS } from "./components/Steps.js";
63
68
  import { Tooltip } from "./components/Tooltip.js";
64
69
  import { InfoTip } from "./components/InfoTip.js";
65
70
  import { EmptyState, ErrorState, ForbiddenState, NotFoundState, FilteredEmptyState, Skeleton, LoadingState } from "./components/States.js";
@@ -78,6 +83,7 @@ import { Pipeline, PipelineStage } from "./components/Pipeline.js";
78
83
  import { Flow, FlowNode } from "./components/Flow.js";
79
84
  import { Prose, Note } from "./components/Prose.js";
80
85
  import { Popover } from "./components/Popover.js";
86
+ import { Menu, MenuItem, MenuGroup, MenuSeparator } from "./components/Menu.js";
81
87
  import { CommandPalette, CommandGroup, CommandItem } from "./components/CommandPalette.js";
82
88
  import { Inbox, InboxList, InboxItem, InboxDetail } from "./components/Inbox.js";
83
89
  import { Kanban, KanbanColumn, KanbanCard } from "./components/Kanban.js";
@@ -150,11 +156,14 @@ export {
150
156
  BulkBar,
151
157
  Button,
152
158
  ButtonGroup,
159
+ ButtonLink,
153
160
  Card,
154
161
  CardLink,
155
162
  CellStrong,
156
163
  CellSub,
157
164
  Checkbox,
165
+ Chip,
166
+ ChipGroup,
158
167
  CollapsibleSection,
159
168
  ColorPicker,
160
169
  Combobox,
@@ -180,6 +189,7 @@ export {
180
189
  DEFAULT_RULE_BUILDER_LABELS,
181
190
  DEFAULT_SAVE_STATUS_LABELS,
182
191
  DEFAULT_SCHEDULING_CALENDAR_LABELS,
192
+ DEFAULT_STEP_STATE_LABELS,
183
193
  DateRangePicker,
184
194
  DescriptionItem,
185
195
  DescriptionList,
@@ -211,6 +221,8 @@ export {
211
221
  Kanban,
212
222
  KanbanCard,
213
223
  KanbanColumn,
224
+ Kbd,
225
+ KbdCombo,
214
226
  Label,
215
227
  LicensePositionBar,
216
228
  List,
@@ -218,6 +230,10 @@ export {
218
230
  LoadingState,
219
231
  Mark,
220
232
  MatchReview,
233
+ Menu,
234
+ MenuGroup,
235
+ MenuItem,
236
+ MenuSeparator,
221
237
  Meter,
222
238
  MetricInput,
223
239
  Modal,
@@ -234,6 +250,7 @@ export {
234
250
  Peek,
235
251
  Pipeline,
236
252
  PipelineStage,
253
+ Popconfirm,
237
254
  Popover,
238
255
  Progress,
239
256
  PromptDialog,
@@ -264,6 +281,8 @@ export {
264
281
  StatLine,
265
282
  StatusPill,
266
283
  StatusRow,
284
+ Step,
285
+ Steps,
267
286
  SubNavItem,
268
287
  Switch,
269
288
  Tab,
@@ -282,6 +301,7 @@ export {
282
301
  Tooltip,
283
302
  Tr,
284
303
  Tree,
304
+ UixLabelsProvider,
285
305
  UserChip,
286
306
  ViewMenu,
287
307
  addCalendarDays,
@@ -320,6 +340,7 @@ export {
320
340
  relationshipNeighbors,
321
341
  relativeTimeValue,
322
342
  removeRuleNode,
343
+ renderPlainLink,
323
344
  restoreBrandProfile,
324
345
  rgbToHex,
325
346
  rgbToHsv,
@@ -336,6 +357,7 @@ export {
336
357
  useAnchoredPosition,
337
358
  useDialog,
338
359
  useTable,
360
+ useUixLabels,
339
361
  useVirtualRows,
340
362
  validateRuleDefinition,
341
363
  wrapEdgeLabel,
@@ -0,0 +1,72 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { PaginationLabels } from './components/Pagination.js';
4
+ import { SchedulingCalendarLabels } from './components/SchedulingCalendar.js';
5
+ import { DateRangePickerLabels } from './components/DateRangePicker.js';
6
+ import './link.js';
7
+ import './calendar-model.js';
8
+
9
+ /**
10
+ * Kit chrome strings by component (HAR-1358; TENSOR C20, MOTUS executive summary #3).
11
+ * Each entry overrides that component's English defaults for every instance below the
12
+ * provider; an explicit prop on one instance still wins.
13
+ *
14
+ * Client components read the provider. Server-renderable ones (`Pagination`, `BulkBar`)
15
+ * cannot read context: pass `labels` from `useUixLabels()` in a client parent, or translate
16
+ * on the server.
17
+ */
18
+ interface UixLabels {
19
+ modal?: {
20
+ close?: string;
21
+ };
22
+ drawer?: {
23
+ close?: string;
24
+ };
25
+ peek?: {
26
+ previous?: string;
27
+ next?: string;
28
+ close?: string;
29
+ };
30
+ toast?: {
31
+ dismiss?: string;
32
+ };
33
+ toaster?: {
34
+ region?: string;
35
+ };
36
+ appShell?: {
37
+ skipToContent?: string;
38
+ exitFocus?: string;
39
+ };
40
+ sidebar?: {
41
+ expand?: string;
42
+ collapse?: string;
43
+ };
44
+ searchSuggest?: {
45
+ clear?: string;
46
+ };
47
+ commandPalette?: {
48
+ input?: string;
49
+ };
50
+ confirmDialog?: {
51
+ typeToConfirm?: string;
52
+ compensation?: string;
53
+ };
54
+ schedulingCalendar?: Partial<SchedulingCalendarLabels>;
55
+ dateRangePicker?: Partial<DateRangePickerLabels>;
56
+ /** Read by `useUixLabels()` callers; `Pagination` itself is server-safe and takes `labels`. */
57
+ pagination?: Partial<PaginationLabels>;
58
+ /** Read by `useUixLabels()` callers; `BulkBar` itself is server-safe and takes `label`. */
59
+ bulkBar?: {
60
+ region?: string;
61
+ };
62
+ }
63
+ interface UixLabelsProviderProps {
64
+ labels: UixLabels;
65
+ children?: ReactNode;
66
+ }
67
+ /** Translates kit chrome once for a subtree. Nested providers merge per component. */
68
+ declare function UixLabelsProvider({ labels, children }: UixLabelsProviderProps): react.JSX.Element;
69
+ /** The chrome strings in effect here (empty outside a provider). */
70
+ declare function useUixLabels(): UixLabels;
71
+
72
+ export { type UixLabels, UixLabelsProvider, type UixLabelsProviderProps, useUixLabels };
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext, useMemo } from "react";
4
+ const UixLabelsContext = createContext({});
5
+ function UixLabelsProvider({ labels, children }) {
6
+ const parent = useContext(UixLabelsContext);
7
+ const value = useMemo(() => {
8
+ const merged = { ...parent };
9
+ for (const [key, entry] of Object.entries(labels)) {
10
+ const inherited = parent[key];
11
+ merged[key] = inherited && entry ? { ...inherited, ...entry } : entry ?? inherited;
12
+ }
13
+ return merged;
14
+ }, [parent, labels]);
15
+ return /* @__PURE__ */ jsx(UixLabelsContext.Provider, { value, children });
16
+ }
17
+ function useUixLabels() {
18
+ return useContext(UixLabelsContext);
19
+ }
20
+ export {
21
+ UixLabelsProvider,
22
+ useUixLabels
23
+ };
package/dist/link.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { AnchorHTMLAttributes, ReactNode } from 'react';
2
+
3
+ /**
4
+ * What a `renderLink` callback receives (HAR-1348). Spread it onto your router's link
5
+ * so it keeps client navigation and prefetch: `renderLink={(p) => <NextLink {...p} />}`.
6
+ * Every UIx component that can render a link (`ButtonLink`, `Stat href`, `Pagination
7
+ * hrefFor`, `DetailPage`) takes the same callback, so one adapter serves them all.
8
+ */
9
+ interface UixLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
10
+ href: string;
11
+ className?: string;
12
+ children?: ReactNode;
13
+ }
14
+ /** Renders a link with the consumer's router. Default: a plain `<a>`. */
15
+ type UixRenderLink = (props: UixLinkProps) => ReactNode;
16
+ declare const renderPlainLink: UixRenderLink;
17
+ /** Calls the consumer's `renderLink`, falling back to a plain `<a>` when it returns nothing. */
18
+ declare function renderUixLink(renderLink: UixRenderLink | undefined, props: UixLinkProps): ReactNode;
19
+
20
+ export { type UixLinkProps, type UixRenderLink, renderPlainLink, renderUixLink };
package/dist/link.js ADDED
@@ -0,0 +1,9 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ const renderPlainLink = (props) => /* @__PURE__ */ jsx("a", { ...props });
3
+ function renderUixLink(renderLink, props) {
4
+ return renderLink?.(props) ?? renderPlainLink(props);
5
+ }
6
+ export {
7
+ renderPlainLink,
8
+ renderUixLink
9
+ };
@@ -39,6 +39,13 @@ interface PositionOptions {
39
39
  flip?: boolean;
40
40
  /** Slide along the cross axis to stay on-screen. Default true. */
41
41
  shift?: boolean;
42
+ /**
43
+ * The side the element is already on, while it stays open. It is kept unless it no longer
44
+ * fits AND the opposite side does, so a size change or a small scroll never flips an open
45
+ * overlay back and forth. Ignored when it is not on `placement`'s axis. Unset = decide from
46
+ * `placement` alone (an overlay that is opening).
47
+ */
48
+ stickySide?: Side;
42
49
  }
43
50
  interface PositionResult {
44
51
  /** Viewport-space left, for `position: fixed`. */
@@ -39,6 +39,13 @@ interface PositionOptions {
39
39
  flip?: boolean;
40
40
  /** Slide along the cross axis to stay on-screen. Default true. */
41
41
  shift?: boolean;
42
+ /**
43
+ * The side the element is already on, while it stays open. It is kept unless it no longer
44
+ * fits AND the opposite side does, so a size change or a small scroll never flips an open
45
+ * overlay back and forth. Ignored when it is not on `placement`'s axis. Unset = decide from
46
+ * `placement` alone (an overlay that is opening).
47
+ */
48
+ stickySide?: Side;
42
49
  }
43
50
  interface PositionResult {
44
51
  /** Viewport-space left, for `position: fixed`. */
@@ -21,10 +21,15 @@ function fitsOn(side, a, f, vp, offset, padding) {
21
21
  return spaceOn(side, a, vp, offset) >= need + padding;
22
22
  }
23
23
  function computePosition(anchor, floating, viewport, options = {}) {
24
- const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true } = options;
24
+ const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true, stickySide } = options;
25
25
  const { side: preferred, align } = parsePlacement(placement);
26
26
  let side = preferred;
27
- if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
27
+ const sticky = stickySide === preferred || stickySide === OPPOSITE[preferred] ? stickySide : void 0;
28
+ if (flip && sticky) {
29
+ side = sticky;
30
+ const opp = OPPOSITE[side];
31
+ if (!fitsOn(side, anchor, floating, viewport, offset, padding) && fitsOn(opp, anchor, floating, viewport, offset, padding)) side = opp;
32
+ } else if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
28
33
  const opp = OPPOSITE[side];
29
34
  if (fitsOn(opp, anchor, floating, viewport, offset, padding) || spaceOn(opp, anchor, viewport, offset) > spaceOn(side, anchor, viewport, offset)) {
30
35
  side = opp;