@tensor_1/react 2.6.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EditorialHome.d.ts +183 -0
- package/dist/components/EditorialHome.js +183 -0
- package/dist/components/Field.js +10 -4
- package/dist/components/Popover.d.ts +18 -4
- package/dist/components/Popover.js +31 -2
- package/dist/components/Toast.js +5 -4
- package/dist/components/Tooltip.d.ts +9 -5
- package/dist/components/Tooltip.js +61 -3
- package/dist/components/Tree.d.ts +15 -1
- package/dist/components/Tree.js +247 -35
- package/dist/hooks/useAnchoredPosition.d.ts +22 -0
- package/dist/hooks/useAnchoredPosition.js +44 -0
- package/dist/hooks/useDialog.js +36 -5
- package/dist/index.cjs +852 -100
- package/dist/index.d.cts +343 -11
- package/dist/index.d.ts +4 -0
- package/dist/index.js +35 -0
- package/dist/overlay-position.d.ts +59 -0
- package/dist/overlay-position.js +62 -0
- package/dist/table-engine.js +72 -6
- package/dist/tree-model.d.ts +48 -0
- package/dist/tree-model.js +49 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes, CSSProperties, HTMLAttributes, AnchorHTMLAttributes, TdHTMLAttributes, TableHTMLAttributes, ThHTMLAttributes } from 'react';
|
|
2
|
+
import { RefObject, ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes, CSSProperties, HTMLAttributes, AnchorHTMLAttributes, TdHTMLAttributes, TableHTMLAttributes, ThHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
declare function cx(...args: (string | false | null | undefined | 0)[]): string;
|
|
5
5
|
|
|
@@ -140,6 +140,82 @@ interface UseTableResult<T> {
|
|
|
140
140
|
*/
|
|
141
141
|
declare function useTable<T extends Row>(data: readonly T[], options?: UseTableOptions): UseTableResult<T>;
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* uix overlay positioning — framework-agnostic, dependency-free anchored placement.
|
|
145
|
+
*
|
|
146
|
+
* Pure geometry (no DOM): given the anchor's rect, the floating element's size, and
|
|
147
|
+
* the viewport, compute where to put the floating element with two behaviours:
|
|
148
|
+
* • flip — if the preferred side doesn't fit, use the opposite side (or whichever
|
|
149
|
+
* side has more room);
|
|
150
|
+
* • shift — slide along the cross axis so the element stays within the viewport.
|
|
151
|
+
*
|
|
152
|
+
* The React hook (useAnchoredPosition) and the vanilla styleguide both feed this
|
|
153
|
+
* getBoundingClientRect() values, so anchored overlays land in the same place in every
|
|
154
|
+
* browser — instead of relying on CSS anchor() positioning, which is Chromium-only and
|
|
155
|
+
* silently detaches the overlay from its trigger everywhere else (UIX-FIX-02).
|
|
156
|
+
*
|
|
157
|
+
* Everything here is deterministic and unit-tested (see overlay-position.test.mjs).
|
|
158
|
+
*/
|
|
159
|
+
type Side = 'top' | 'bottom' | 'left' | 'right';
|
|
160
|
+
type Align = 'start' | 'center' | 'end';
|
|
161
|
+
type Placement = Side | `${Side}-${Align}`;
|
|
162
|
+
/** A viewport-space rectangle, as returned by getBoundingClientRect(). */
|
|
163
|
+
interface Rect {
|
|
164
|
+
x: number;
|
|
165
|
+
y: number;
|
|
166
|
+
width: number;
|
|
167
|
+
height: number;
|
|
168
|
+
}
|
|
169
|
+
interface Size {
|
|
170
|
+
width: number;
|
|
171
|
+
height: number;
|
|
172
|
+
}
|
|
173
|
+
interface PositionOptions {
|
|
174
|
+
/** Preferred placement. Default `'bottom-start'`; a bare side (e.g. `'top'`) centers on the cross axis. */
|
|
175
|
+
placement?: Placement;
|
|
176
|
+
/** Gap between the anchor and the floating element, in px. Default 6. */
|
|
177
|
+
offset?: number;
|
|
178
|
+
/** Minimum gap kept from each viewport edge when shifting, in px. Default 8. */
|
|
179
|
+
padding?: number;
|
|
180
|
+
/** Flip to the opposite side when the preferred one doesn't fit. Default true. */
|
|
181
|
+
flip?: boolean;
|
|
182
|
+
/** Slide along the cross axis to stay on-screen. Default true. */
|
|
183
|
+
shift?: boolean;
|
|
184
|
+
}
|
|
185
|
+
interface PositionResult {
|
|
186
|
+
/** Viewport-space left, for `position: fixed`. */
|
|
187
|
+
x: number;
|
|
188
|
+
/** Viewport-space top, for `position: fixed`. */
|
|
189
|
+
y: number;
|
|
190
|
+
/** The placement actually used (after any flip). */
|
|
191
|
+
placement: Placement;
|
|
192
|
+
side: Side;
|
|
193
|
+
align: Align;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Compute the floating element's viewport-space position anchored to `anchor`.
|
|
197
|
+
* Coordinates are for `position: fixed` (same space as getBoundingClientRect).
|
|
198
|
+
*/
|
|
199
|
+
declare function computePosition(anchor: Rect, floating: Size, viewport: Size, options?: PositionOptions): PositionResult;
|
|
200
|
+
|
|
201
|
+
interface UseAnchoredPositionOptions {
|
|
202
|
+
/** Reposition while true, and (re)attach scroll/resize listeners. */
|
|
203
|
+
open: boolean;
|
|
204
|
+
placement?: Placement;
|
|
205
|
+
offset?: number;
|
|
206
|
+
padding?: number;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Position a floating element (a native-popover overlay) against an anchor with
|
|
210
|
+
* cross-browser flip/shift — the DOM half of the overlay-position engine (UIX-FIX-02).
|
|
211
|
+
*
|
|
212
|
+
* Measures both elements with getBoundingClientRect, applies `position: fixed` + left/top
|
|
213
|
+
* (overriding the popover's default centered `inset:0; margin:auto`), and keeps the overlay
|
|
214
|
+
* glued to its anchor on scroll/resize while `open`. Returns a `reposition` fn for callers
|
|
215
|
+
* that want to nudge it manually (e.g. right when a native popover's `toggle` fires).
|
|
216
|
+
*/
|
|
217
|
+
declare function useAnchoredPosition(anchor: RefObject<HTMLElement | null> | HTMLElement | null | undefined, floatingRef: RefObject<HTMLElement | null>, { open, placement, offset, padding }: UseAnchoredPositionOptions): () => void;
|
|
218
|
+
|
|
143
219
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
144
220
|
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger' | 'link';
|
|
145
221
|
size?: 'sm' | 'md' | 'lg';
|
|
@@ -654,16 +730,19 @@ interface StatProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
654
730
|
declare function Stat({ label, value, icon, meta, trend, className, ...props }: StatProps): react.JSX.Element;
|
|
655
731
|
|
|
656
732
|
interface TooltipProps extends HTMLAttributes<HTMLSpanElement> {
|
|
657
|
-
/** Tooltip text.
|
|
733
|
+
/** Tooltip text. */
|
|
658
734
|
label: string;
|
|
735
|
+
/** Preferred placement. Default `'top'`. */
|
|
736
|
+
placement?: Placement;
|
|
659
737
|
children?: ReactNode;
|
|
660
738
|
}
|
|
661
739
|
/**
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
740
|
+
* Tooltip whose bubble renders in the top layer via the native Popover API, so it
|
|
741
|
+
* escapes any `overflow: hidden/scroll` ancestor that would clip the old CSS-only
|
|
742
|
+
* `[data-uix-tip]` tooltip (UIX-FIX-02). Positioned by the shared overlay engine
|
|
743
|
+
* (flip/shift), shown on hover and keyboard focus, dismissed on blur or Escape.
|
|
665
744
|
*/
|
|
666
|
-
declare function Tooltip({ label, children, ...props }: TooltipProps): react.JSX.Element;
|
|
745
|
+
declare function Tooltip({ label, placement, className, children, ...props }: TooltipProps): react.JSX.Element;
|
|
667
746
|
|
|
668
747
|
interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
669
748
|
icon?: ReactNode;
|
|
@@ -832,13 +911,26 @@ interface PopoverProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
832
911
|
* wires to it via `popoverTarget={id}`. Pass `"manual"` to control open state yourself.
|
|
833
912
|
*/
|
|
834
913
|
popover?: 'auto' | 'manual';
|
|
914
|
+
/**
|
|
915
|
+
* Element (or ref) to anchor against. When set, the popover is placed with
|
|
916
|
+
* cross-browser JS positioning — flip when it won't fit, shift to stay on-screen —
|
|
917
|
+
* instead of relying on CSS `anchor()`, which is Chromium-only and detaches the
|
|
918
|
+
* popover from its trigger everywhere else. The native Popover API still provides
|
|
919
|
+
* the top layer (so it escapes `overflow` clipping) and light-dismiss.
|
|
920
|
+
*/
|
|
921
|
+
anchor?: RefObject<HTMLElement | null> | HTMLElement | null;
|
|
922
|
+
/** Preferred placement when `anchor` is set. Default `'bottom-start'`. */
|
|
923
|
+
placement?: Placement;
|
|
924
|
+
/** Gap between the trigger and the popover, in px. Default 6. */
|
|
925
|
+
offset?: number;
|
|
835
926
|
children?: ReactNode;
|
|
836
927
|
}
|
|
837
928
|
/**
|
|
838
|
-
* Anchored surface over `.uix-popover`, using the native Popover API.
|
|
839
|
-
*
|
|
929
|
+
* Anchored surface over `.uix-popover`, using the native Popover API. Compose ITSM
|
|
930
|
+
* things like a filter popover, menu, or rich select by putting controls inside.
|
|
931
|
+
* Pass `anchor` to get collision-aware, cross-browser placement (UIX-FIX-02).
|
|
840
932
|
*/
|
|
841
|
-
declare function Popover({ popover,
|
|
933
|
+
declare function Popover({ popover, anchor, placement, offset, className, children, ...props }: PopoverProps): react.JSX.Element;
|
|
842
934
|
|
|
843
935
|
interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
844
936
|
/** Props for the search input (value/onChange/placeholder wired by the consumer). */
|
|
@@ -924,8 +1016,11 @@ interface TreeNodeProps {
|
|
|
924
1016
|
node: TreeNodeData;
|
|
925
1017
|
expanded: Set<string>;
|
|
926
1018
|
selected?: string;
|
|
1019
|
+
selectable: boolean;
|
|
1020
|
+
tabbableId?: string;
|
|
927
1021
|
onToggle: (id: string) => void;
|
|
928
1022
|
onSelect?: (id: string) => void;
|
|
1023
|
+
onFocusNode: (id: string) => void;
|
|
929
1024
|
level?: number;
|
|
930
1025
|
}
|
|
931
1026
|
interface TreeProps extends Omit<HTMLAttributes<HTMLUListElement>, 'onSelect' | 'onChange'> {
|
|
@@ -935,7 +1030,244 @@ interface TreeProps extends Omit<HTMLAttributes<HTMLUListElement>, 'onSelect' |
|
|
|
935
1030
|
selected?: string;
|
|
936
1031
|
onToggle?: (id: string) => void;
|
|
937
1032
|
onSelect?: (id: string) => void;
|
|
1033
|
+
/**
|
|
1034
|
+
* Virtualize a large tree — render only the rows in view (UIX-FIX-05). Defaults to auto
|
|
1035
|
+
* (on past the engine's `shouldVirtualize` threshold of visible rows). When on, the tree is
|
|
1036
|
+
* flattened to a scrollable list of `maxHeight` with fixed-height rows; a11y is preserved via
|
|
1037
|
+
* `aria-level` / `aria-setsize` / `aria-posinset` instead of nested `role="group"`s.
|
|
1038
|
+
*/
|
|
1039
|
+
virtualize?: boolean;
|
|
1040
|
+
/** Fixed row height (px) used for virtualization. Default 32. */
|
|
1041
|
+
rowHeight?: number;
|
|
1042
|
+
/** Scroll-viewport height (px) when virtualizing. Default 384. */
|
|
1043
|
+
maxHeight?: number;
|
|
1044
|
+
}
|
|
1045
|
+
declare function Tree({ nodes, expanded: controlledExpanded, defaultExpanded, selected, onToggle, onSelect, virtualize, rowHeight, maxHeight, className, ...props }: TreeProps): react.JSX.Element;
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* uix tree model — framework-agnostic, dependency-free tree flattening + keyboard nav.
|
|
1049
|
+
*
|
|
1050
|
+
* Pure functions (no DOM, no React): flatten a nested tree into the linear list of *visible*
|
|
1051
|
+
* rows (respecting expansion) so it can be virtualized with the table engine's virtualWindow,
|
|
1052
|
+
* and resolve a keyboard key into a navigation decision. Both the plain and the virtualized
|
|
1053
|
+
* <Tree> render paths use these, so the two behave identically and keyboard nav works even for
|
|
1054
|
+
* rows that are scrolled out of the virtual window (UIX-FIX-05). Unit-tested (tree-model.test.mjs).
|
|
1055
|
+
*/
|
|
1056
|
+
/** Minimal shape a node must have; the concrete node (label, icon, …) rides along as `T`. */
|
|
1057
|
+
interface TreeLike<T> {
|
|
1058
|
+
id: string;
|
|
1059
|
+
children?: T[];
|
|
1060
|
+
}
|
|
1061
|
+
interface FlatNode<T> {
|
|
1062
|
+
node: T;
|
|
1063
|
+
/** 1-based depth, for aria-level. */
|
|
1064
|
+
level: number;
|
|
1065
|
+
/** number of siblings at this level (this node's parent's child count), for aria-setsize. */
|
|
1066
|
+
setsize: number;
|
|
1067
|
+
/** 1-based index among those siblings, for aria-posinset. */
|
|
1068
|
+
posinset: number;
|
|
1069
|
+
hasChildren: boolean;
|
|
1070
|
+
isExpanded: boolean;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Flatten a nested tree into the visible rows, in DOM/reading order. A node's children follow
|
|
1074
|
+
* it immediately and are included only when the node is in `expanded`.
|
|
1075
|
+
*/
|
|
1076
|
+
declare function flattenTree<T extends TreeLike<T>>(nodes: readonly T[], expanded: ReadonlySet<string>, level?: number): FlatNode<T>[];
|
|
1077
|
+
/** A decision produced by a key press — any subset may be set. */
|
|
1078
|
+
interface TreeNavAction {
|
|
1079
|
+
/** move focus (roving tabindex) to this node id. */
|
|
1080
|
+
focusId?: string;
|
|
1081
|
+
/** toggle this node's expansion. */
|
|
1082
|
+
toggleId?: string;
|
|
1083
|
+
/** select this node id. */
|
|
1084
|
+
selectId?: string;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Resolve a key press against the flattened, visible node list — the single source of truth for
|
|
1088
|
+
* both render paths. Mirrors the WAI-ARIA tree pattern: Up/Down move by row, Right expands then
|
|
1089
|
+
* descends, Left collapses then ascends to the parent, Home/End jump, Enter/Space select (and
|
|
1090
|
+
* toggle a parent). Returns an empty action for unhandled keys or an unknown current id.
|
|
1091
|
+
*/
|
|
1092
|
+
declare function treeNav<T extends TreeLike<T>>(flat: readonly FlatNode<T>[], currentId: string | undefined, key: string): TreeNavAction;
|
|
1093
|
+
|
|
1094
|
+
interface PageIntroProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
1095
|
+
/** Small line above the title (e.g. today's date). */
|
|
1096
|
+
kicker?: ReactNode;
|
|
1097
|
+
title: ReactNode;
|
|
1098
|
+
/** Supporting copy under the title. */
|
|
1099
|
+
lede?: ReactNode;
|
|
1100
|
+
/** Label shown above the search well. */
|
|
1101
|
+
searchLabel?: ReactNode;
|
|
1102
|
+
/** The search well itself (form + `.uix-searchbar` markup, or `SearchBar`-style composition). */
|
|
1103
|
+
search?: ReactNode;
|
|
1104
|
+
/** Shortcut buttons; rendered inside the `.uix-shortcut-grid` full-width row. */
|
|
1105
|
+
shortcuts?: ReactNode;
|
|
1106
|
+
/** Accessible label for the shortcuts group. */
|
|
1107
|
+
shortcutsLabel?: string;
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Editorial page intro — kicker / title / lede beside a search well, with an
|
|
1111
|
+
* optional full-width shortcut grid underneath (`.uix-page-intro`).
|
|
1112
|
+
*/
|
|
1113
|
+
declare function PageIntro({ kicker, title, lede, searchLabel, search, shortcuts, shortcutsLabel, className, children, ...props }: PageIntroProps): react.JSX.Element;
|
|
1114
|
+
interface SectionHeadProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
1115
|
+
title: ReactNode;
|
|
1116
|
+
/** id for the `<h2>`, for `aria-labelledby` wiring on the enclosing section. */
|
|
1117
|
+
titleId?: string;
|
|
1118
|
+
/** Right-aligned slot — a `.uix-section-link` anchor, a button, a pill. */
|
|
1119
|
+
action?: ReactNode;
|
|
1120
|
+
}
|
|
1121
|
+
/** Section head — title row with an optional trailing action (`.uix-section-head`). */
|
|
1122
|
+
declare function SectionHead({ title, titleId, action, className, ...props }: SectionHeadProps): react.JSX.Element;
|
|
1123
|
+
interface NoticeQueueProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
1124
|
+
/** Leading icon slot. */
|
|
1125
|
+
icon?: ReactNode;
|
|
1126
|
+
/** Bolded lead-in of the notice copy. */
|
|
1127
|
+
title?: ReactNode;
|
|
1128
|
+
/** Rest of the notice copy, after the title. */
|
|
1129
|
+
summary?: ReactNode;
|
|
1130
|
+
/** Meta line under the copy (e.g. "Needs action · Required by Friday"). */
|
|
1131
|
+
meta?: ReactNode;
|
|
1132
|
+
/** Queue position (e.g. "1 of 4 important updates"). */
|
|
1133
|
+
position?: ReactNode;
|
|
1134
|
+
/**
|
|
1135
|
+
* Trailing controls — previous/next arrows (put `uix-notice__arrow--previous`
|
|
1136
|
+
* on the previous button to flip its icon), read/view-all buttons.
|
|
1137
|
+
*/
|
|
1138
|
+
actions?: ReactNode;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Notice queue — the rotating "important updates" banner (`.uix-notice`). The
|
|
1142
|
+
* copy region is `aria-live="polite"` so queue rotation is announced.
|
|
1143
|
+
*/
|
|
1144
|
+
declare function NoticeQueue({ icon, title, summary, meta, position, actions, className, ...props }: NoticeQueueProps): react.JSX.Element;
|
|
1145
|
+
interface FeaturedStageProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
1146
|
+
/** Decorative visual (story signal + diagram). Hidden from AT unless `visualLabel` is set. */
|
|
1147
|
+
visual?: ReactNode;
|
|
1148
|
+
/** Accessible description of the visual; when set the visual gets `role="img"`. */
|
|
1149
|
+
visualLabel?: string;
|
|
1150
|
+
/**
|
|
1151
|
+
* Ordinal of the story on stage (e.g. "01"), rendered as the filled
|
|
1152
|
+
* `.uix-featured__now` chip in the eyebrow. Pair it with the matching
|
|
1153
|
+
* `FeaturedRundownItem`'s `number` — the selected item's number renders as
|
|
1154
|
+
* the same chip, and that pairing is what links rundown to stage on every
|
|
1155
|
+
* breakpoint (the divider caret only exists while the zones sit side by side).
|
|
1156
|
+
*/
|
|
1157
|
+
ordinal?: ReactNode;
|
|
1158
|
+
eyebrow?: ReactNode;
|
|
1159
|
+
title: ReactNode;
|
|
1160
|
+
/** id for the `<h2>` title, for `aria-labelledby` wiring. */
|
|
1161
|
+
titleId?: string;
|
|
1162
|
+
description?: ReactNode;
|
|
1163
|
+
meta?: ReactNode;
|
|
1164
|
+
/** Call-to-action slot under the meta line. */
|
|
1165
|
+
action?: ReactNode;
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Featured stage — the hero story zone of the featured briefing
|
|
1169
|
+
* (`.uix-featured__stage`). The briefing is ONE `.uix-featured` card: put this
|
|
1170
|
+
* and `FeaturedRundown` directly inside it and the internal hairline, the
|
|
1171
|
+
* selected item's caret, and the ordinal chips connect the two zones. Content
|
|
1172
|
+
* is `aria-live="polite"` so swapping the featured story (from the rundown)
|
|
1173
|
+
* is announced.
|
|
1174
|
+
*/
|
|
1175
|
+
declare function FeaturedStage({ visual, visualLabel, ordinal, eyebrow, title, titleId, description, meta, action, className, ...props }: FeaturedStageProps): react.JSX.Element;
|
|
1176
|
+
interface FeaturedRundownProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
1177
|
+
/** Uppercase line above the title (e.g. "Editorial briefing"). */
|
|
1178
|
+
eyebrow?: ReactNode;
|
|
1179
|
+
title: ReactNode;
|
|
1180
|
+
/** id for the `<h2>` title, for `aria-labelledby` wiring. */
|
|
1181
|
+
titleId?: string;
|
|
1182
|
+
/** Trailing head slot (e.g. a count pill). */
|
|
1183
|
+
meta?: ReactNode;
|
|
1184
|
+
/** `FeaturedRundownItem`s. */
|
|
1185
|
+
children?: ReactNode;
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Featured rundown — the story-list zone of the featured briefing
|
|
1189
|
+
* (`.uix-rundown`), sitting inside the single `.uix-featured` card beside (or,
|
|
1190
|
+
* stacked, below) the `FeaturedStage`.
|
|
1191
|
+
*/
|
|
1192
|
+
declare function FeaturedRundown({ eyebrow, title, titleId, meta, children, className, ...props }: FeaturedRundownProps): react.JSX.Element;
|
|
1193
|
+
interface FeaturedRundownItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'> {
|
|
1194
|
+
/** Ordinal label (e.g. "01"). */
|
|
1195
|
+
number?: ReactNode;
|
|
1196
|
+
/** Topic/duration line above the item title (e.g. "Company · 5 min"). */
|
|
1197
|
+
topic?: ReactNode;
|
|
1198
|
+
/** The story title. */
|
|
1199
|
+
title: ReactNode;
|
|
1200
|
+
/** Whether this story is on the stage — sets `aria-pressed` + `data-selected`. */
|
|
1201
|
+
selected?: boolean;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* One rundown story — a toggle button (`.uix-rundown__item`) whose selection
|
|
1205
|
+
* is conveyed with `aria-pressed` and styled through `[data-selected]`.
|
|
1206
|
+
*/
|
|
1207
|
+
declare function FeaturedRundownItem({ number, topic, title, selected, className, ...props }: FeaturedRundownItemProps): react.JSX.Element;
|
|
1208
|
+
interface NewsLeadProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
1209
|
+
/** Meta line above the title (pill + date). */
|
|
1210
|
+
meta?: ReactNode;
|
|
1211
|
+
title: ReactNode;
|
|
1212
|
+
summary?: ReactNode;
|
|
1213
|
+
}
|
|
1214
|
+
/** News lead — the top story of a news column (`.uix-news-lead`). */
|
|
1215
|
+
declare function NewsLead({ meta, title, summary, className, ...props }: NewsLeadProps): react.JSX.Element;
|
|
1216
|
+
interface ContentListProps extends HTMLAttributes<HTMLUListElement> {
|
|
1217
|
+
/** `ContentListItem`s. */
|
|
1218
|
+
children?: ReactNode;
|
|
1219
|
+
}
|
|
1220
|
+
/** Content list — hairline-divided rows of titled items (`.uix-content-list`). */
|
|
1221
|
+
declare function ContentList({ children, className, ...props }: ContentListProps): react.JSX.Element;
|
|
1222
|
+
interface ContentListItemProps extends Omit<HTMLAttributes<HTMLLIElement>, 'title'> {
|
|
1223
|
+
title: ReactNode;
|
|
1224
|
+
meta?: ReactNode;
|
|
1225
|
+
/** Trailing slot — an arrow glyph, a pill. */
|
|
1226
|
+
trailing?: ReactNode;
|
|
1227
|
+
}
|
|
1228
|
+
/** One content-list row — title + meta with an optional trailing slot. */
|
|
1229
|
+
declare function ContentListItem({ title, meta, trailing, className, ...props }: ContentListItemProps): react.JSX.Element;
|
|
1230
|
+
interface ResourceGridProps extends HTMLAttributes<HTMLDivElement> {
|
|
1231
|
+
/** Resource buttons/links (typically `.uix-btn--outline`). */
|
|
1232
|
+
children?: ReactNode;
|
|
1233
|
+
}
|
|
1234
|
+
/** Resource grid — a three-up grid of resource shortcuts (`.uix-resource-grid`). */
|
|
1235
|
+
declare function ResourceGrid({ children, className, ...props }: ResourceGridProps): react.JSX.Element;
|
|
1236
|
+
interface StatLineItem {
|
|
1237
|
+
/** Stable identity for the item; falls back to the index when omitted. */
|
|
1238
|
+
id?: string;
|
|
1239
|
+
value: ReactNode;
|
|
1240
|
+
label: ReactNode;
|
|
1241
|
+
}
|
|
1242
|
+
interface StatLineProps extends HTMLAttributes<HTMLDivElement> {
|
|
1243
|
+
items?: StatLineItem[];
|
|
1244
|
+
children?: ReactNode;
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1247
|
+
* Stat line — a compact value/label summary strip over a hairline
|
|
1248
|
+
* (`.uix-stat-line`). Use `items` for data-driven stats or hand-author
|
|
1249
|
+
* `.uix-stat-line__item` children.
|
|
1250
|
+
*/
|
|
1251
|
+
declare function StatLine({ items, children, className, ...props }: StatLineProps): react.JSX.Element;
|
|
1252
|
+
interface EventRowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
1253
|
+
/** Calendar-block month (e.g. "Jul"). */
|
|
1254
|
+
month: ReactNode;
|
|
1255
|
+
/** Calendar-block day (e.g. "30"). */
|
|
1256
|
+
day: ReactNode;
|
|
1257
|
+
title: ReactNode;
|
|
1258
|
+
meta?: ReactNode;
|
|
1259
|
+
}
|
|
1260
|
+
/** Event row — date block + title/meta (`.uix-event-row`). */
|
|
1261
|
+
declare function EventRow({ month, day, title, meta, className, ...props }: EventRowProps): react.JSX.Element;
|
|
1262
|
+
interface StatusRowProps extends HTMLAttributes<HTMLDivElement> {
|
|
1263
|
+
/** Leading indicator slot (e.g. a `.uix-dot`). */
|
|
1264
|
+
indicator?: ReactNode;
|
|
1265
|
+
/** Service name — takes the flexible middle (`.uix-status-row__name`). */
|
|
1266
|
+
name: ReactNode;
|
|
1267
|
+
/** Trailing meta (e.g. "Healthy"), rendered as `.uix-list-meta`. */
|
|
1268
|
+
meta?: ReactNode;
|
|
938
1269
|
}
|
|
939
|
-
|
|
1270
|
+
/** Status row — indicator + name + trailing meta (`.uix-status-row`). */
|
|
1271
|
+
declare function StatusRow({ indicator, name, meta, className, ...props }: StatusRowProps): react.JSX.Element;
|
|
940
1272
|
|
|
941
|
-
export { Alert, type AlertProps, type AlertTone, AppShell, type AppShellProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BulkBar, type BulkBarProps, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, Card, type CardProps, CellStrong, CellSub, Checkbox, type CheckboxProps, type ColumnFilter, CommandGroup, type CommandGroupProps, CommandItem, type CommandItemProps, CommandPalette, type CommandPaletteProps, Comment, type CommentProps, Comments, type CommentsProps, Composer, ComposerBar, type ComposerBarProps, type ComposerProps, DescriptionItem, type DescriptionItemProps, DescriptionList, type DescriptionListItem, type DescriptionListProps, DetailLayout, type DetailLayoutProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, ExpandToggle, type ExpandToggleProps, Field, type FieldProps, type FilterKind, type FilterOp, Highlighted, type HighlightedProps, Inbox, InboxDetail, type InboxDetailProps, InboxItem, type InboxItemProps, InboxList, type InboxListProps, type InboxProps, Input, InputGroup, type InputGroupProps, type InputProps, Kanban, KanbanCard, type KanbanCardProps, KanbanColumn, type KanbanColumnProps, type KanbanProps, Label, type LabelProps, List, ListItem, type ListItemProps, type ListProps, LoadingState, type LoadingStateProps, Mark, type MarkProps, Meter, type MeterProps, type MeterTone, Modal, type ModalProps, type NavFavouriteItem, NavFavourites, type NavFavouritesLabels, type NavFavouritesProps, NavGroup, type NavGroupProps, NavItem, type NavItemProps, Note, type NoteProps, type NoteTone, PageHeader, type PageHeaderProps, Pagination, type PaginationProps, Peek, type PeekProps, type PillTone, type PillTreatment, Popover, type PopoverProps, type Primitive, Progress, type ProgressProps, Prose, type ProseProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type Row, RowAction, type RowActionProps, RowActions, type RowActionsProps, type Segment, Segmented, SegmentedOption, type SegmentedOptionProps, type SegmentedProps, Select, type SelectAllState, type SelectProps, type ShellNav, Sidebar, type SidebarProps, SidebarSection, type SidebarSectionProps, Skeleton, type SkeletonProps, type SortDir, type SortDirection, type SortKey, Spinner, type SpinnerProps, StarButton, type StarButtonProps, Stat, type StatProps, type StatTrend, StatusPill, type StatusPillProps, SubNavItem, type SubNavItemProps, Switch, type SwitchProps, Tab, type TabProps, Table, type TableDensity, type TableProps, TableWrap, type TableWrapProps, Tabs, type TabsProps, Td, type TdProps, Textarea, type TextareaProps, Th, type ThProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineProps, Toast, type ToastProps, type ToastTone, Toaster, type ToasterProps, Tooltip, type TooltipProps, Tr, type TrProps, Tree, type TreeNodeData, type TreeNodeProps, type TreeProps, type UseTableOptions, type UseTableResult, UserChip, type UserChipProps, type ViewState, type VirtualWindow, applyFilters, clampWidth, cx, highlightSegments, matchFilter, mergePinned, multiSort, nextSortDir, parseView, reorder, searchRows, selectAllState, serializeView, shouldVirtualize, toggleId, togglePage, toggleSort, useDialog, useTable, virtualWindow };
|
|
1273
|
+
export { Alert, type AlertProps, type AlertTone, type Align, AppShell, type AppShellProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BulkBar, type BulkBarProps, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, Card, type CardProps, CellStrong, CellSub, Checkbox, type CheckboxProps, type ColumnFilter, CommandGroup, type CommandGroupProps, CommandItem, type CommandItemProps, CommandPalette, type CommandPaletteProps, Comment, type CommentProps, Comments, type CommentsProps, Composer, ComposerBar, type ComposerBarProps, type ComposerProps, ContentList, ContentListItem, type ContentListItemProps, type ContentListProps, DescriptionItem, type DescriptionItemProps, DescriptionList, type DescriptionListItem, type DescriptionListProps, DetailLayout, type DetailLayoutProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, EventRow, type EventRowProps, ExpandToggle, type ExpandToggleProps, FeaturedRundown, FeaturedRundownItem, type FeaturedRundownItemProps, type FeaturedRundownProps, FeaturedStage, type FeaturedStageProps, Field, type FieldProps, type FilterKind, type FilterOp, type FlatNode, Highlighted, type HighlightedProps, Inbox, InboxDetail, type InboxDetailProps, InboxItem, type InboxItemProps, InboxList, type InboxListProps, type InboxProps, Input, InputGroup, type InputGroupProps, type InputProps, Kanban, KanbanCard, type KanbanCardProps, KanbanColumn, type KanbanColumnProps, type KanbanProps, Label, type LabelProps, List, ListItem, type ListItemProps, type ListProps, LoadingState, type LoadingStateProps, Mark, type MarkProps, Meter, type MeterProps, type MeterTone, Modal, type ModalProps, type NavFavouriteItem, NavFavourites, type NavFavouritesLabels, type NavFavouritesProps, NavGroup, type NavGroupProps, NavItem, type NavItemProps, NewsLead, type NewsLeadProps, Note, type NoteProps, type NoteTone, NoticeQueue, type NoticeQueueProps, PageHeader, type PageHeaderProps, PageIntro, type PageIntroProps, Pagination, type PaginationProps, Peek, type PeekProps, type PillTone, type PillTreatment, type Placement, Popover, type PopoverProps, type PositionOptions, type PositionResult, type Primitive, Progress, type ProgressProps, Prose, type ProseProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type Rect, ResourceGrid, type ResourceGridProps, type Row, RowAction, type RowActionProps, RowActions, type RowActionsProps, SectionHead, type SectionHeadProps, type Segment, Segmented, SegmentedOption, type SegmentedOptionProps, type SegmentedProps, Select, type SelectAllState, type SelectProps, type ShellNav, type Side, Sidebar, type SidebarProps, SidebarSection, type SidebarSectionProps, type Size, Skeleton, type SkeletonProps, type SortDir, type SortDirection, type SortKey, Spinner, type SpinnerProps, StarButton, type StarButtonProps, Stat, StatLine, type StatLineItem, type StatLineProps, type StatProps, type StatTrend, StatusPill, type StatusPillProps, StatusRow, type StatusRowProps, SubNavItem, type SubNavItemProps, Switch, type SwitchProps, Tab, type TabProps, Table, type TableDensity, type TableProps, TableWrap, type TableWrapProps, Tabs, type TabsProps, Td, type TdProps, Textarea, type TextareaProps, Th, type ThProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineProps, Toast, type ToastProps, type ToastTone, Toaster, type ToasterProps, Tooltip, type TooltipProps, Tr, type TrProps, Tree, type TreeLike, type TreeNavAction, type TreeNodeData, type TreeNodeProps, type TreeProps, type UseAnchoredPositionOptions, type UseTableOptions, type UseTableResult, UserChip, type UserChipProps, type ViewState, type VirtualWindow, applyFilters, clampWidth, computePosition, cx, flattenTree, highlightSegments, matchFilter, mergePinned, multiSort, nextSortDir, parseView, reorder, searchRows, selectAllState, serializeView, shouldVirtualize, toggleId, togglePage, toggleSort, treeNav, useAnchoredPosition, useDialog, useTable, virtualWindow };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { cx } from './cx.js';
|
|
2
2
|
export { useDialog } from './hooks/useDialog.js';
|
|
3
3
|
export { UseTableOptions, UseTableResult, useTable } from './hooks/useTable.js';
|
|
4
|
+
export { UseAnchoredPositionOptions, useAnchoredPosition } from './hooks/useAnchoredPosition.js';
|
|
5
|
+
export { Align, Placement, PositionOptions, PositionResult, Rect, Side, Size, computePosition } from './overlay-position.js';
|
|
4
6
|
export { Button, ButtonGroup, ButtonGroupProps, ButtonProps } from './components/Button.js';
|
|
5
7
|
export { Input, InputGroup, InputGroupProps, InputProps } from './components/Input.js';
|
|
6
8
|
export { Textarea, TextareaProps } from './components/Textarea.js';
|
|
@@ -46,4 +48,6 @@ export { CommandGroup, CommandGroupProps, CommandItem, CommandItemProps, Command
|
|
|
46
48
|
export { Inbox, InboxDetail, InboxDetailProps, InboxItem, InboxItemProps, InboxList, InboxListProps, InboxProps } from './components/Inbox.js';
|
|
47
49
|
export { Kanban, KanbanCard, KanbanCardProps, KanbanColumn, KanbanColumnProps, KanbanProps } from './components/Kanban.js';
|
|
48
50
|
export { Tree, TreeNodeData, TreeNodeProps, TreeProps } from './components/Tree.js';
|
|
51
|
+
export { FlatNode, TreeLike, TreeNavAction, flattenTree, treeNav } from './tree-model.js';
|
|
52
|
+
export { ContentList, ContentListItem, ContentListItemProps, ContentListProps, EventRow, EventRowProps, FeaturedRundown, FeaturedRundownItem, FeaturedRundownItemProps, FeaturedRundownProps, FeaturedStage, FeaturedStageProps, NewsLead, NewsLeadProps, NoticeQueue, NoticeQueueProps, PageIntro, PageIntroProps, ResourceGrid, ResourceGridProps, SectionHead, SectionHeadProps, StatLine, StatLineItem, StatLineProps, StatusRow, StatusRowProps } from './components/EditorialHome.js';
|
|
49
53
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { cx } from "./cx.js";
|
|
2
2
|
import { useDialog } from "./hooks/useDialog.js";
|
|
3
3
|
import { useTable } from "./hooks/useTable.js";
|
|
4
|
+
import { useAnchoredPosition } from "./hooks/useAnchoredPosition.js";
|
|
5
|
+
import { computePosition } from "./overlay-position.js";
|
|
4
6
|
import { Button, ButtonGroup } from "./components/Button.js";
|
|
5
7
|
import { Input, InputGroup } from "./components/Input.js";
|
|
6
8
|
import { Textarea } from "./components/Textarea.js";
|
|
@@ -60,6 +62,22 @@ import { CommandPalette, CommandGroup, CommandItem } from "./components/CommandP
|
|
|
60
62
|
import { Inbox, InboxList, InboxItem, InboxDetail } from "./components/Inbox.js";
|
|
61
63
|
import { Kanban, KanbanColumn, KanbanCard } from "./components/Kanban.js";
|
|
62
64
|
import { Tree } from "./components/Tree.js";
|
|
65
|
+
import { flattenTree, treeNav } from "./tree-model.js";
|
|
66
|
+
import {
|
|
67
|
+
PageIntro,
|
|
68
|
+
SectionHead,
|
|
69
|
+
NoticeQueue,
|
|
70
|
+
FeaturedStage,
|
|
71
|
+
FeaturedRundown,
|
|
72
|
+
FeaturedRundownItem,
|
|
73
|
+
NewsLead,
|
|
74
|
+
ContentList,
|
|
75
|
+
ContentListItem,
|
|
76
|
+
ResourceGrid,
|
|
77
|
+
StatLine,
|
|
78
|
+
EventRow,
|
|
79
|
+
StatusRow
|
|
80
|
+
} from "./components/EditorialHome.js";
|
|
63
81
|
export {
|
|
64
82
|
Alert,
|
|
65
83
|
AppShell,
|
|
@@ -79,13 +97,19 @@ export {
|
|
|
79
97
|
Comments,
|
|
80
98
|
Composer,
|
|
81
99
|
ComposerBar,
|
|
100
|
+
ContentList,
|
|
101
|
+
ContentListItem,
|
|
82
102
|
DescriptionItem,
|
|
83
103
|
DescriptionList,
|
|
84
104
|
DetailLayout,
|
|
85
105
|
Drawer,
|
|
86
106
|
EmptyState,
|
|
87
107
|
ErrorState,
|
|
108
|
+
EventRow,
|
|
88
109
|
ExpandToggle,
|
|
110
|
+
FeaturedRundown,
|
|
111
|
+
FeaturedRundownItem,
|
|
112
|
+
FeaturedStage,
|
|
89
113
|
Field,
|
|
90
114
|
Highlighted,
|
|
91
115
|
Inbox,
|
|
@@ -107,8 +131,11 @@ export {
|
|
|
107
131
|
NavFavourites,
|
|
108
132
|
NavGroup,
|
|
109
133
|
NavItem,
|
|
134
|
+
NewsLead,
|
|
110
135
|
Note,
|
|
136
|
+
NoticeQueue,
|
|
111
137
|
PageHeader,
|
|
138
|
+
PageIntro,
|
|
112
139
|
Pagination,
|
|
113
140
|
Peek,
|
|
114
141
|
Popover,
|
|
@@ -116,8 +143,10 @@ export {
|
|
|
116
143
|
Prose,
|
|
117
144
|
Radio,
|
|
118
145
|
RadioGroup,
|
|
146
|
+
ResourceGrid,
|
|
119
147
|
RowAction,
|
|
120
148
|
RowActions,
|
|
149
|
+
SectionHead,
|
|
121
150
|
Segmented,
|
|
122
151
|
SegmentedOption,
|
|
123
152
|
Select,
|
|
@@ -127,7 +156,9 @@ export {
|
|
|
127
156
|
Spinner,
|
|
128
157
|
StarButton,
|
|
129
158
|
Stat,
|
|
159
|
+
StatLine,
|
|
130
160
|
StatusPill,
|
|
161
|
+
StatusRow,
|
|
131
162
|
SubNavItem,
|
|
132
163
|
Switch,
|
|
133
164
|
Tab,
|
|
@@ -145,7 +176,11 @@ export {
|
|
|
145
176
|
Tr,
|
|
146
177
|
Tree,
|
|
147
178
|
UserChip,
|
|
179
|
+
computePosition,
|
|
148
180
|
cx,
|
|
181
|
+
flattenTree,
|
|
182
|
+
treeNav,
|
|
183
|
+
useAnchoredPosition,
|
|
149
184
|
useDialog,
|
|
150
185
|
useTable
|
|
151
186
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uix overlay positioning — framework-agnostic, dependency-free anchored placement.
|
|
3
|
+
*
|
|
4
|
+
* Pure geometry (no DOM): given the anchor's rect, the floating element's size, and
|
|
5
|
+
* the viewport, compute where to put the floating element with two behaviours:
|
|
6
|
+
* • flip — if the preferred side doesn't fit, use the opposite side (or whichever
|
|
7
|
+
* side has more room);
|
|
8
|
+
* • shift — slide along the cross axis so the element stays within the viewport.
|
|
9
|
+
*
|
|
10
|
+
* The React hook (useAnchoredPosition) and the vanilla styleguide both feed this
|
|
11
|
+
* getBoundingClientRect() values, so anchored overlays land in the same place in every
|
|
12
|
+
* browser — instead of relying on CSS anchor() positioning, which is Chromium-only and
|
|
13
|
+
* silently detaches the overlay from its trigger everywhere else (UIX-FIX-02).
|
|
14
|
+
*
|
|
15
|
+
* Everything here is deterministic and unit-tested (see overlay-position.test.mjs).
|
|
16
|
+
*/
|
|
17
|
+
type Side = 'top' | 'bottom' | 'left' | 'right';
|
|
18
|
+
type Align = 'start' | 'center' | 'end';
|
|
19
|
+
type Placement = Side | `${Side}-${Align}`;
|
|
20
|
+
/** A viewport-space rectangle, as returned by getBoundingClientRect(). */
|
|
21
|
+
interface Rect {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
}
|
|
27
|
+
interface Size {
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}
|
|
31
|
+
interface PositionOptions {
|
|
32
|
+
/** Preferred placement. Default `'bottom-start'`; a bare side (e.g. `'top'`) centers on the cross axis. */
|
|
33
|
+
placement?: Placement;
|
|
34
|
+
/** Gap between the anchor and the floating element, in px. Default 6. */
|
|
35
|
+
offset?: number;
|
|
36
|
+
/** Minimum gap kept from each viewport edge when shifting, in px. Default 8. */
|
|
37
|
+
padding?: number;
|
|
38
|
+
/** Flip to the opposite side when the preferred one doesn't fit. Default true. */
|
|
39
|
+
flip?: boolean;
|
|
40
|
+
/** Slide along the cross axis to stay on-screen. Default true. */
|
|
41
|
+
shift?: boolean;
|
|
42
|
+
}
|
|
43
|
+
interface PositionResult {
|
|
44
|
+
/** Viewport-space left, for `position: fixed`. */
|
|
45
|
+
x: number;
|
|
46
|
+
/** Viewport-space top, for `position: fixed`. */
|
|
47
|
+
y: number;
|
|
48
|
+
/** The placement actually used (after any flip). */
|
|
49
|
+
placement: Placement;
|
|
50
|
+
side: Side;
|
|
51
|
+
align: Align;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Compute the floating element's viewport-space position anchored to `anchor`.
|
|
55
|
+
* Coordinates are for `position: fixed` (same space as getBoundingClientRect).
|
|
56
|
+
*/
|
|
57
|
+
declare function computePosition(anchor: Rect, floating: Size, viewport: Size, options?: PositionOptions): PositionResult;
|
|
58
|
+
|
|
59
|
+
export { type Align, type Placement, type PositionOptions, type PositionResult, type Rect, type Side, type Size, computePosition };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" };
|
|
2
|
+
function parsePlacement(p) {
|
|
3
|
+
const [side, align] = p.split("-");
|
|
4
|
+
return { side, align: align ?? "center" };
|
|
5
|
+
}
|
|
6
|
+
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
7
|
+
function spaceOn(side, a, vp, offset) {
|
|
8
|
+
switch (side) {
|
|
9
|
+
case "top":
|
|
10
|
+
return a.y - offset;
|
|
11
|
+
case "bottom":
|
|
12
|
+
return vp.height - (a.y + a.height) - offset;
|
|
13
|
+
case "left":
|
|
14
|
+
return a.x - offset;
|
|
15
|
+
case "right":
|
|
16
|
+
return vp.width - (a.x + a.width) - offset;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function fitsOn(side, a, f, vp, offset, padding) {
|
|
20
|
+
const need = side === "top" || side === "bottom" ? f.height : f.width;
|
|
21
|
+
return spaceOn(side, a, vp, offset) >= need + padding;
|
|
22
|
+
}
|
|
23
|
+
function computePosition(anchor, floating, viewport, options = {}) {
|
|
24
|
+
const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true } = options;
|
|
25
|
+
const { side: preferred, align } = parsePlacement(placement);
|
|
26
|
+
let side = preferred;
|
|
27
|
+
if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
|
|
28
|
+
const opp = OPPOSITE[side];
|
|
29
|
+
if (fitsOn(opp, anchor, floating, viewport, offset, padding) || spaceOn(opp, anchor, viewport, offset) > spaceOn(side, anchor, viewport, offset)) {
|
|
30
|
+
side = opp;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
let x, y;
|
|
34
|
+
const horizontal = side === "top" || side === "bottom";
|
|
35
|
+
if (side === "top") y = anchor.y - floating.height - offset;
|
|
36
|
+
else if (side === "bottom") y = anchor.y + anchor.height + offset;
|
|
37
|
+
else if (side === "left") x = anchor.x - floating.width - offset;
|
|
38
|
+
else x = anchor.x + anchor.width + offset;
|
|
39
|
+
if (horizontal) {
|
|
40
|
+
const start = anchor.x;
|
|
41
|
+
const end = anchor.x + anchor.width - floating.width;
|
|
42
|
+
const center = anchor.x + (anchor.width - floating.width) / 2;
|
|
43
|
+
x = align === "start" ? start : align === "end" ? end : center;
|
|
44
|
+
if (shift) x = clamp(x, padding, Math.max(padding, viewport.width - floating.width - padding));
|
|
45
|
+
} else {
|
|
46
|
+
const start = anchor.y;
|
|
47
|
+
const end = anchor.y + anchor.height - floating.height;
|
|
48
|
+
const center = anchor.y + (anchor.height - floating.height) / 2;
|
|
49
|
+
y = align === "start" ? start : align === "end" ? end : center;
|
|
50
|
+
if (shift) y = clamp(y, padding, Math.max(padding, viewport.height - floating.height - padding));
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
x,
|
|
54
|
+
y,
|
|
55
|
+
placement: align === "center" ? side : `${side}-${align}`,
|
|
56
|
+
side,
|
|
57
|
+
align
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
computePosition
|
|
62
|
+
};
|