@rebasepro/ui 0.22.0 → 0.24.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.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Whether a key event has already been handled by something above you — the
3
+ * one question every global key handler (a `keydown` listener on `window` or
4
+ * `document`) must ask before acting.
5
+ *
6
+ * The rule: **a handler that acts on a key calls `event.preventDefault()`;
7
+ * a global handler that finds the event already handled does nothing.** Every
8
+ * kit overlay follows it for free — `Dialog`, `Sheet`, `Popover`, `Menu`,
9
+ * `Select`, `MultiSelect`, `Tooltip` are Radix layers, and a Radix layer calls
10
+ * `preventDefault()` on the Escape it consumes to close itself. So Escape
11
+ * pressed in an open dropdown closes the dropdown, and the record panel's
12
+ * Escape handler underneath sees it handled and leaves the record open.
13
+ *
14
+ * Two conditions make it hold:
15
+ *
16
+ * - **Listen in the bubble phase.** A Radix layer listens on `document` in
17
+ * the capture phase, so it has run before any bubble listener — on the
18
+ * target, on `document` or on `window` — whatever order they were added in.
19
+ * A capture listener added before the layer opened runs *before* it and
20
+ * cannot see its claim. Only a layer of your own, one that sits above
21
+ * everything else while it is open, belongs in the capture phase, and it
22
+ * must call `preventDefault()` when it acts.
23
+ * - **Do not ask the DOM instead.** `document.querySelector('[role="dialog"]')`
24
+ * misses every layer that is not a dialog (a menu is `role="menu"`, a select
25
+ * list `role="listbox"`), and the list of roles is never finished.
26
+ *
27
+ * An IME composition counts as handled too: Escape while composing Japanese or
28
+ * Chinese text cancels the composition, and must not close a panel.
29
+ */
30
+ export declare function isKeyHandled(event: KeyboardEvent): boolean;
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { CollectionSize } from "./ListView.js";
3
+ import { type ViewScrollEvent } from "./useScrollParentRestoration.js";
3
4
  export type CardViewProps<T> = {
4
5
  data: T[];
5
6
  dataLoading?: boolean;
@@ -14,11 +15,7 @@ export type CardViewProps<T> = {
14
15
  highlightedIds?: Set<string | number>;
15
16
  selectionEnabled?: boolean;
16
17
  onSelectionChange?: (item: T, selected: boolean) => void;
17
- onScroll?: (props: {
18
- scrollDirection: "forward" | "backward";
19
- scrollOffset: number;
20
- scrollUpdateWasRequested: boolean;
21
- }) => void;
18
+ onScroll?: (props: ViewScrollEvent) => void;
22
19
  initialScroll?: number;
23
20
  size?: CollectionSize;
24
21
  renderCard: (item: T, extra: {
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { type ViewScrollEvent } from "./useScrollParentRestoration.js";
2
3
  export type CollectionSize = "xs" | "s" | "m" | "l" | "xl";
3
4
  export type ListViewColumnDef<T> = {
4
5
  key: string;
@@ -23,6 +24,13 @@ export type ListViewProps<T> = {
23
24
  selectionEnabled?: boolean;
24
25
  onSelectionChange?: (item: T, selected: boolean) => void;
25
26
  emptyComponent?: React.ReactNode;
27
+ /**
28
+ * Called with the scroll parent's offset as it scrolls, and restored from
29
+ * `initialScroll` on mount — the list does not scroll itself, the page
30
+ * around it does.
31
+ */
32
+ onScroll?: (props: ViewScrollEvent) => void;
33
+ initialScroll?: number;
26
34
  size?: CollectionSize;
27
35
  selectedEntityId?: string | number;
28
36
  /**
@@ -43,4 +51,4 @@ export type ListViewProps<T> = {
43
51
  onSelectionChange: (selected: boolean) => void;
44
52
  }) => React.ReactNode;
45
53
  };
46
- export declare function ListView<T>({ data, dataLoading, noMoreToLoad, dataLoadingError, itemCount, setItemCount, pageSize, paginationEnabled, onItemClick, selectedIds, highlightedIds, selectionEnabled, onSelectionChange, emptyComponent, size, selectedEntityId, header, renderRow }: ListViewProps<T>): React.JSX.Element;
54
+ export declare function ListView<T>({ data, dataLoading, noMoreToLoad, dataLoadingError, itemCount, setItemCount, pageSize, paginationEnabled, onItemClick, selectedIds, highlightedIds, selectionEnabled, onSelectionChange, emptyComponent, onScroll, initialScroll, size, selectedEntityId, header, renderRow }: ListViewProps<T>): React.JSX.Element;
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ export type ViewScrollEvent = {
3
+ scrollDirection: "forward" | "backward";
4
+ scrollOffset: number;
5
+ scrollUpdateWasRequested: boolean;
6
+ };
7
+ /**
8
+ * The nearest ancestor that scrolls vertically. The list and card views do not
9
+ * scroll themselves: the page around them does, so that is the element whose
10
+ * offset is worth keeping.
11
+ */
12
+ export declare function getScrollParent(element: HTMLElement | null): HTMLElement | null;
13
+ /**
14
+ * Report the scroll parent's offset through `onScroll`, and put it back at
15
+ * `initialScroll` once there are rows to scroll over.
16
+ *
17
+ * Opening a record full screen unmounts the collection view, so coming back
18
+ * mounts a fresh one. The caller keeps the offset (and the rows it was over)
19
+ * outside the component; this is what hands it over and applies it again.
20
+ */
21
+ export declare function useScrollParentRestoration({ containerRef, initialScroll, onScroll, dataLength }: {
22
+ containerRef: React.RefObject<HTMLElement | null>;
23
+ initialScroll?: number;
24
+ onScroll?: (props: ViewScrollEvent) => void;
25
+ dataLength: number;
26
+ }): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/ui",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Rebase design system — React components and design tokens built on Radix UI, Tailwind CSS and lucide-react",
5
5
  "keywords": [
6
6
  "rebase",