@giddaa-housing/ui 2.0.0 → 2.1.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/css/generated/shared.css +1 -1
- package/dist/card.d.ts +4 -2
- package/dist/card.js +7 -7
- package/dist/combobox.d.ts +48 -1
- package/dist/combobox.js +77 -4
- package/dist/data-table.js +1 -1
- package/dist/date-picker.d.ts +5 -2
- package/dist/date-picker.js +11 -6
- package/dist/infinite-scroll.d.ts +40 -0
- package/dist/infinite-scroll.js +125 -0
- package/dist/picker-xSTzeYhc.js +50 -0
- package/dist/popover.d.ts +2 -2
- package/dist/popover.js +2 -1
- package/dist/styles.css +31 -6
- package/dist/table.js +2 -2
- package/dist/tabs.js +2 -2
- package/dist/time-picker.d.ts +4 -1
- package/dist/time-picker.js +8 -5
- package/package.json +6 -1
- package/dist/picker-lzgmsNfG.js +0 -32
package/dist/combobox.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as ComponentSize } from "./size-context-D4mYvcg8.js";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Combobox as Combobox$1 } from "@base-ui/react";
|
|
4
|
+
import { Virtualizer } from "@tanstack/react-virtual";
|
|
4
5
|
//#region src/combobox.d.ts
|
|
5
6
|
type ComboboxSize = ComponentSize;
|
|
6
7
|
declare function Combobox<Value, Multiple extends boolean | undefined = false>({ multiple, children, size, ...props }: Combobox$1.Root.Props<Value, Multiple> & {
|
|
@@ -26,5 +27,51 @@ declare function ComboboxChip({ className, children, showRemove, ...props }: Com
|
|
|
26
27
|
}): React.JSX.Element;
|
|
27
28
|
declare function ComboboxChipsInput({ className, ...props }: Combobox$1.Input.Props): React.JSX.Element;
|
|
28
29
|
declare function useComboboxAnchor(): React.RefObject<HTMLDivElement | null>;
|
|
30
|
+
type ComboboxVirtualizer = Virtualizer<HTMLDivElement, Element>;
|
|
31
|
+
type ComboboxHighlightDetails = {
|
|
32
|
+
reason: "keyboard" | "pointer" | "none";
|
|
33
|
+
index: number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Wires up an external virtualizer for a large `Combobox`. Spread the returned
|
|
37
|
+
* `onItemHighlighted` onto `<Combobox virtualized items={...}>` and pass
|
|
38
|
+
* `virtualizerRef` to `<ComboboxVirtualizedList>`. Keeps keyboard navigation in
|
|
39
|
+
* sync by scrolling the highlighted (off-screen) item into view.
|
|
40
|
+
*/
|
|
41
|
+
declare function useComboboxVirtualizer(): {
|
|
42
|
+
virtualizerRef: React.RefObject<ComboboxVirtualizer | null>;
|
|
43
|
+
onItemHighlighted: (item: unknown, { reason, index }: ComboboxHighlightDetails) => void;
|
|
44
|
+
};
|
|
45
|
+
type ComboboxVirtualItemProps = {
|
|
46
|
+
index: number;
|
|
47
|
+
"data-index": number;
|
|
48
|
+
"aria-setsize": number;
|
|
49
|
+
"aria-posinset": number;
|
|
50
|
+
style: React.CSSProperties;
|
|
51
|
+
};
|
|
52
|
+
declare function ComboboxVirtualizedList<Item>({ virtualizerRef, estimateSize, overscan, paddingStart, paddingEnd, maxHeight, className, children }: {
|
|
53
|
+
/** Ref returned by {@link useComboboxVirtualizer}. */
|
|
54
|
+
virtualizerRef: React.RefObject<ComboboxVirtualizer | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Fixed row height in px (or a per-index function). Rows render at this
|
|
57
|
+
* exact height, so match it to the item size variant (roughly sm: 32,
|
|
58
|
+
* md: 40, lg: 44). Defaults to 40.
|
|
59
|
+
*/
|
|
60
|
+
estimateSize?: number | ((index: number) => number);
|
|
61
|
+
overscan?: number;
|
|
62
|
+
paddingStart?: number;
|
|
63
|
+
paddingEnd?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Fixed max height of the scroll viewport (px number or CSS length).
|
|
66
|
+
* Must be a stable value — do NOT wire this to `--available-height` or any
|
|
67
|
+
* value the popup positioner writes, or react-virtual's resize observer and
|
|
68
|
+
* the positioner will feed back into each other and freeze the page on open.
|
|
69
|
+
* Defaults to `"22rem"`.
|
|
70
|
+
*/
|
|
71
|
+
maxHeight?: number | string;
|
|
72
|
+
className?: string;
|
|
73
|
+
/** Render a `ComboboxItem`, spreading the provided props onto it. */
|
|
74
|
+
children: (item: Item, props: ComboboxVirtualItemProps) => React.ReactNode;
|
|
75
|
+
}): React.JSX.Element | null;
|
|
29
76
|
//#endregion
|
|
30
|
-
export { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, type ComboboxSize, ComboboxTrigger, ComboboxValue, useComboboxAnchor };
|
|
77
|
+
export { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, type ComboboxSize, ComboboxTrigger, ComboboxValue, type ComboboxVirtualItemProps, ComboboxVirtualizedList, type ComboboxVirtualizer, useComboboxAnchor, useComboboxVirtualizer };
|
package/dist/combobox.js
CHANGED
|
@@ -8,6 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
import { cva } from "class-variance-authority";
|
|
9
9
|
import * as React from "react";
|
|
10
10
|
import { Combobox as Combobox$1 } from "@base-ui/react";
|
|
11
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
11
12
|
//#region src/combobox.tsx
|
|
12
13
|
const ComboboxSelectionContext = React.createContext({ multiple: false });
|
|
13
14
|
function Combobox({ multiple, children, size, ...props }) {
|
|
@@ -115,7 +116,7 @@ function ComboboxInput({ className, children, disabled = false, showTrigger = tr
|
|
|
115
116
|
variant: "ghost",
|
|
116
117
|
render: /* @__PURE__ */ jsx(ComboboxTrigger, {}),
|
|
117
118
|
"data-slot": "input-group-button",
|
|
118
|
-
className: "
|
|
119
|
+
className: "border-0 bg-transparent p-0 shadow-none inset-ring-0 group-has-data-[slot=combobox-clear]/input-group:hidden hover:border-transparent focus-visible:border-transparent focus-visible:inset-ring-0 data-popup-open:border-transparent data-popup-open:bg-transparent data-popup-open:inset-ring-0 data-pressed:bg-transparent",
|
|
119
120
|
disabled
|
|
120
121
|
}), showClear && /* @__PURE__ */ jsx(ComboboxClear, { disabled })]
|
|
121
122
|
}),
|
|
@@ -135,7 +136,7 @@ function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "
|
|
|
135
136
|
children: /* @__PURE__ */ jsx(Combobox$1.Popup, {
|
|
136
137
|
"data-slot": "combobox-content",
|
|
137
138
|
"data-chips": !!anchor,
|
|
138
|
-
className: cn("group/combobox-content", comboboxContentVariants({ size: resolvedSize }), className),
|
|
139
|
+
className: cn("group/combobox-content", comboboxContentVariants({ size: resolvedSize }), "has-data-[slot=combobox-virtualized]:max-h-none", className),
|
|
139
140
|
...props
|
|
140
141
|
})
|
|
141
142
|
}) });
|
|
@@ -143,7 +144,7 @@ function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "
|
|
|
143
144
|
function ComboboxList({ className, ...props }) {
|
|
144
145
|
return /* @__PURE__ */ jsx(Combobox$1.List, {
|
|
145
146
|
"data-slot": "combobox-list",
|
|
146
|
-
className: cn("no-scrollbar max-h-(--available-height) space-y-0.5 scroll-py-1 overflow-y-auto overscroll-contain data-empty:p-0", className),
|
|
147
|
+
className: cn("no-scrollbar max-h-(--available-height) space-y-0.5 scroll-py-1 overflow-y-auto overscroll-contain data-empty:p-0 has-data-[slot=combobox-virtualized]:max-h-none has-data-[slot=combobox-virtualized]:space-y-0 has-data-[slot=combobox-virtualized]:overflow-hidden", className),
|
|
147
148
|
...props
|
|
148
149
|
});
|
|
149
150
|
}
|
|
@@ -233,5 +234,77 @@ function ComboboxChipsInput({ className, ...props }) {
|
|
|
233
234
|
function useComboboxAnchor() {
|
|
234
235
|
return React.useRef(null);
|
|
235
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Wires up an external virtualizer for a large `Combobox`. Spread the returned
|
|
239
|
+
* `onItemHighlighted` onto `<Combobox virtualized items={...}>` and pass
|
|
240
|
+
* `virtualizerRef` to `<ComboboxVirtualizedList>`. Keeps keyboard navigation in
|
|
241
|
+
* sync by scrolling the highlighted (off-screen) item into view.
|
|
242
|
+
*/
|
|
243
|
+
function useComboboxVirtualizer() {
|
|
244
|
+
const virtualizerRef = React.useRef(null);
|
|
245
|
+
return {
|
|
246
|
+
virtualizerRef,
|
|
247
|
+
onItemHighlighted: React.useCallback((item, { reason, index }) => {
|
|
248
|
+
const virtualizer = virtualizerRef.current;
|
|
249
|
+
if (item == null || !virtualizer || index < 0) return;
|
|
250
|
+
const isStart = index === 0;
|
|
251
|
+
const isEnd = index === virtualizer.options.count - 1;
|
|
252
|
+
if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) queueMicrotask(() => {
|
|
253
|
+
virtualizer.scrollToIndex(index, { align: isEnd ? "start" : "end" });
|
|
254
|
+
});
|
|
255
|
+
}, [])
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function ComboboxVirtualizedList({ virtualizerRef, estimateSize = 40, overscan = 20, paddingStart = 4, paddingEnd = 4, maxHeight = "22rem", className, children }) {
|
|
259
|
+
const filteredItems = Combobox$1.useFilteredItems();
|
|
260
|
+
const scrollElementRef = React.useRef(null);
|
|
261
|
+
const virtualizer = useVirtualizer({
|
|
262
|
+
count: filteredItems.length,
|
|
263
|
+
getScrollElement: () => scrollElementRef.current,
|
|
264
|
+
estimateSize: typeof estimateSize === "function" ? estimateSize : () => estimateSize,
|
|
265
|
+
overscan,
|
|
266
|
+
paddingStart,
|
|
267
|
+
paddingEnd,
|
|
268
|
+
scrollPaddingStart: paddingStart,
|
|
269
|
+
scrollPaddingEnd: paddingEnd
|
|
270
|
+
});
|
|
271
|
+
React.useImperativeHandle(virtualizerRef, () => virtualizer, [virtualizer]);
|
|
272
|
+
const handleScrollElementRef = React.useCallback((element) => {
|
|
273
|
+
scrollElementRef.current = element;
|
|
274
|
+
if (element) virtualizer.measure();
|
|
275
|
+
}, [virtualizer]);
|
|
276
|
+
const totalSize = virtualizer.getTotalSize();
|
|
277
|
+
if (!filteredItems.length) return null;
|
|
278
|
+
return /* @__PURE__ */ jsx("div", {
|
|
279
|
+
role: "presentation",
|
|
280
|
+
ref: handleScrollElementRef,
|
|
281
|
+
"data-slot": "combobox-virtualized",
|
|
282
|
+
style: { maxHeight },
|
|
283
|
+
className: cn("no-scrollbar overflow-y-auto overscroll-contain", className),
|
|
284
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
285
|
+
role: "presentation",
|
|
286
|
+
className: "relative w-full",
|
|
287
|
+
style: { height: totalSize },
|
|
288
|
+
children: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
289
|
+
const item = filteredItems[virtualItem.index];
|
|
290
|
+
if (item == null) return null;
|
|
291
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: children(item, {
|
|
292
|
+
index: virtualItem.index,
|
|
293
|
+
"data-index": virtualItem.index,
|
|
294
|
+
"aria-setsize": filteredItems.length,
|
|
295
|
+
"aria-posinset": virtualItem.index + 1,
|
|
296
|
+
style: {
|
|
297
|
+
position: "absolute",
|
|
298
|
+
top: 0,
|
|
299
|
+
left: 0,
|
|
300
|
+
width: "100%",
|
|
301
|
+
height: virtualItem.size,
|
|
302
|
+
transform: `translateY(${virtualItem.start}px)`
|
|
303
|
+
}
|
|
304
|
+
}) }, virtualItem.key);
|
|
305
|
+
})
|
|
306
|
+
})
|
|
307
|
+
});
|
|
308
|
+
}
|
|
236
309
|
//#endregion
|
|
237
|
-
export { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, useComboboxAnchor };
|
|
310
|
+
export { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, ComboboxVirtualizedList, useComboboxAnchor, useComboboxVirtualizer };
|
package/dist/data-table.js
CHANGED
|
@@ -243,7 +243,7 @@ function DataTable({ className, containerClassName, emptyState, interactiveColum
|
|
|
243
243
|
pinnedSide,
|
|
244
244
|
style: getCommonPinningStyles(header.column),
|
|
245
245
|
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs("div", {
|
|
246
|
-
className: "flex items-center gap-2",
|
|
246
|
+
className: "flex min-w-0 items-center gap-2",
|
|
247
247
|
children: [
|
|
248
248
|
flexRender(header.column.columnDef.header, header.getContext()),
|
|
249
249
|
header.column.getCanSort() ? /* @__PURE__ */ jsx("button", {
|
package/dist/date-picker.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { n as InputSize } from "./input-CfoEJ8A6.js";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
import { DateRange, Matcher } from "react-day-picker";
|
|
3
4
|
//#region src/date-picker.d.ts
|
|
4
5
|
type CaptionLayout = "label" | "dropdown" | "dropdown-months" | "dropdown-years";
|
|
5
6
|
interface DatePickerBaseProps {
|
|
6
7
|
disabled?: boolean;
|
|
8
|
+
/** Controls the trigger size. The calendar panel is not resized. */
|
|
9
|
+
size?: InputSize;
|
|
7
10
|
placeholder?: string;
|
|
8
11
|
className?: string;
|
|
9
12
|
/** Caption style. Defaults to month + year dropdowns for quick navigation. */
|
|
@@ -19,11 +22,11 @@ interface DatePickerProps extends DatePickerBaseProps {
|
|
|
19
22
|
value?: Date;
|
|
20
23
|
onChange?: (date: Date | undefined) => void;
|
|
21
24
|
}
|
|
22
|
-
declare function DatePicker({ value, onChange, disabled, placeholder, className, captionLayout, startMonth, endMonth, disabledDates }: DatePickerProps): React.JSX.Element;
|
|
25
|
+
declare function DatePicker({ value, onChange, disabled, size, placeholder, className, captionLayout, startMonth, endMonth, disabledDates }: DatePickerProps): React.JSX.Element;
|
|
23
26
|
interface DateRangePickerProps extends DatePickerBaseProps {
|
|
24
27
|
value?: DateRange;
|
|
25
28
|
onChange?: (range: DateRange | undefined) => void;
|
|
26
29
|
}
|
|
27
|
-
declare function DateRangePicker({ value, onChange, disabled, placeholder, className, captionLayout, startMonth, endMonth, disabledDates }: DateRangePickerProps): React.JSX.Element;
|
|
30
|
+
declare function DateRangePicker({ value, onChange, disabled, size, placeholder, className, captionLayout, startMonth, endMonth, disabledDates }: DateRangePickerProps): React.JSX.Element;
|
|
28
31
|
//#endregion
|
|
29
32
|
export { DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps };
|
package/dist/date-picker.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { t as cn } from "./cn-BI_4DMBf.js";
|
|
3
3
|
import { Calendar } from "./calendar.js";
|
|
4
4
|
import { Popover, PopoverContent } from "./popover.js";
|
|
5
|
-
import { n as PickerTrigger, t as
|
|
5
|
+
import { n as PickerFooter, r as PickerTrigger, t as PICKER_COLLISION_AVOIDANCE } from "./picker-xSTzeYhc.js";
|
|
6
6
|
import { CalendarIcon } from "lucide-react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import * as React from "react";
|
|
@@ -14,14 +14,14 @@ function formatDate(date) {
|
|
|
14
14
|
year: "numeric"
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
|
-
const PANEL_CLASSES = "flex min-w-(--anchor-width) flex-col items-center gap-0 overflow-hidden rounded-2xl p-0";
|
|
17
|
+
const PANEL_CLASSES = "flex min-w-(--anchor-width) flex-col items-center gap-0 overflow-hidden rounded-2xl p-0 border border-line-subtle";
|
|
18
18
|
function defaultStartMonth() {
|
|
19
19
|
return new Date((/* @__PURE__ */ new Date()).getFullYear() - 100, 0);
|
|
20
20
|
}
|
|
21
21
|
function defaultEndMonth() {
|
|
22
22
|
return new Date((/* @__PURE__ */ new Date()).getFullYear() + 10, 11);
|
|
23
23
|
}
|
|
24
|
-
function DatePicker({ value, onChange, disabled = false, placeholder = "Select date", className, captionLayout = "dropdown", startMonth, endMonth, disabledDates }) {
|
|
24
|
+
function DatePicker({ value, onChange, disabled = false, size, placeholder = "Select date", className, captionLayout = "dropdown", startMonth, endMonth, disabledDates }) {
|
|
25
25
|
const [open, setOpen] = React.useState(false);
|
|
26
26
|
const [pending, setPending] = React.useState(value);
|
|
27
27
|
const [month, setMonth] = React.useState(() => value ?? /* @__PURE__ */ new Date());
|
|
@@ -41,11 +41,13 @@ function DatePicker({ value, onChange, disabled = false, placeholder = "Select d
|
|
|
41
41
|
placeholder,
|
|
42
42
|
disabled,
|
|
43
43
|
open,
|
|
44
|
+
size,
|
|
44
45
|
className
|
|
45
46
|
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
46
47
|
showArrow: false,
|
|
47
|
-
align: "
|
|
48
|
+
align: "center",
|
|
48
49
|
side: "bottom",
|
|
50
|
+
collisionAvoidance: PICKER_COLLISION_AVOIDANCE,
|
|
49
51
|
className: PANEL_CLASSES,
|
|
50
52
|
children: [/* @__PURE__ */ jsx(Calendar, {
|
|
51
53
|
mode: "single",
|
|
@@ -72,7 +74,7 @@ function DatePicker({ value, onChange, disabled = false, placeholder = "Select d
|
|
|
72
74
|
})]
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
|
-
function DateRangePicker({ value, onChange, disabled = false, placeholder = "Select date range", className, captionLayout = "dropdown", startMonth, endMonth, disabledDates }) {
|
|
77
|
+
function DateRangePicker({ value, onChange, disabled = false, size, placeholder = "Select date range", className, captionLayout = "dropdown", startMonth, endMonth, disabledDates }) {
|
|
76
78
|
const [open, setOpen] = React.useState(false);
|
|
77
79
|
const [pending, setPending] = React.useState(value);
|
|
78
80
|
const [month, setMonth] = React.useState(() => value?.from ?? /* @__PURE__ */ new Date());
|
|
@@ -96,10 +98,13 @@ function DateRangePicker({ value, onChange, disabled = false, placeholder = "Sel
|
|
|
96
98
|
placeholder,
|
|
97
99
|
disabled,
|
|
98
100
|
open,
|
|
101
|
+
size,
|
|
99
102
|
className
|
|
100
103
|
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
101
104
|
showArrow: false,
|
|
102
|
-
align: "
|
|
105
|
+
align: "center",
|
|
106
|
+
side: "bottom",
|
|
107
|
+
collisionAvoidance: PICKER_COLLISION_AVOIDANCE,
|
|
103
108
|
className: cn(PANEL_CLASSES, "w-auto"),
|
|
104
109
|
children: [/* @__PURE__ */ jsx(Calendar, {
|
|
105
110
|
mode: "range",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/infinite-scroll.d.ts
|
|
3
|
+
interface InfiniteScrollState {
|
|
4
|
+
/** Initial page load state, usually from useInfiniteQuery. */
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
/** Whether the flattened list has no items. */
|
|
7
|
+
isEmpty: boolean;
|
|
8
|
+
error?: Error | null;
|
|
9
|
+
hasNextPage: boolean | undefined;
|
|
10
|
+
isFetchingNextPage: boolean;
|
|
11
|
+
fetchNextPage: () => unknown;
|
|
12
|
+
}
|
|
13
|
+
declare function useInfiniteScrollSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, rootMargin }: Pick<InfiniteScrollState, "hasNextPage" | "isFetchingNextPage" | "fetchNextPage"> & {
|
|
14
|
+
rootMargin?: string;
|
|
15
|
+
}): import("react").RefCallback<HTMLDivElement | null>;
|
|
16
|
+
declare function InfiniteScroll({ children, isLoading, isEmpty, error, hasNextPage, isFetchingNextPage, fetchNextPage }: InfiniteScrollState & {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
declare function InfiniteScrollLoading({ children }: {
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
}): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
|
|
22
|
+
declare function InfiniteScrollContent({ children }: {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}): ReactNode;
|
|
25
|
+
declare function InfiniteScrollEmpty({ children }: {
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}): ReactNode;
|
|
28
|
+
declare function InfiniteScrollError({ children }: {
|
|
29
|
+
children?: ReactNode;
|
|
30
|
+
}): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
|
|
31
|
+
declare function InfiniteScrollEnd({ children }: {
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}): ReactNode;
|
|
34
|
+
declare function InfiniteScrollSentinel({ rootMargin, className }: {
|
|
35
|
+
/** Distance from the viewport at which the next fetch triggers. */
|
|
36
|
+
rootMargin?: string;
|
|
37
|
+
className?: string;
|
|
38
|
+
}): import("react").JSX.Element | null;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { InfiniteScroll, InfiniteScrollContent, InfiniteScrollEmpty, InfiniteScrollEnd, InfiniteScrollError, InfiniteScrollLoading, InfiniteScrollSentinel, type InfiniteScrollState, useInfiniteScrollSentinel };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as cn } from "./cn-BI_4DMBf.js";
|
|
3
|
+
import { Loader2 } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
//#region src/lib/use-intersection.ts
|
|
7
|
+
function useIntersection(options) {
|
|
8
|
+
const [entry, setEntry] = useState(null);
|
|
9
|
+
const observer = useRef(null);
|
|
10
|
+
return {
|
|
11
|
+
ref: useCallback((element) => {
|
|
12
|
+
if (observer.current) {
|
|
13
|
+
observer.current.disconnect();
|
|
14
|
+
observer.current = null;
|
|
15
|
+
}
|
|
16
|
+
if (element === null) {
|
|
17
|
+
setEntry(null);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
21
|
+
setEntry(null);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
observer.current = new IntersectionObserver(([_entry]) => {
|
|
25
|
+
setEntry(_entry ?? null);
|
|
26
|
+
}, options);
|
|
27
|
+
observer.current.observe(element);
|
|
28
|
+
}, [options]),
|
|
29
|
+
entry
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/infinite-scroll.tsx
|
|
34
|
+
const InfiniteScrollContext = createContext(null);
|
|
35
|
+
function useInfiniteScrollContext(consumer) {
|
|
36
|
+
const context = useContext(InfiniteScrollContext);
|
|
37
|
+
if (!context) throw new Error(`${consumer} must be used within <InfiniteScroll>`);
|
|
38
|
+
return context;
|
|
39
|
+
}
|
|
40
|
+
function useInfiniteScrollSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, rootMargin = "200px" }) {
|
|
41
|
+
const { ref, entry } = useIntersection(useMemo(() => ({ rootMargin }), [rootMargin]));
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (entry?.isIntersecting && hasNextPage && !isFetchingNextPage) fetchNextPage();
|
|
44
|
+
}, [
|
|
45
|
+
entry?.isIntersecting,
|
|
46
|
+
hasNextPage,
|
|
47
|
+
isFetchingNextPage,
|
|
48
|
+
fetchNextPage
|
|
49
|
+
]);
|
|
50
|
+
return ref;
|
|
51
|
+
}
|
|
52
|
+
function InfiniteScroll({ children, isLoading, isEmpty, error, hasNextPage, isFetchingNextPage, fetchNextPage }) {
|
|
53
|
+
const value = useMemo(() => ({
|
|
54
|
+
isLoading,
|
|
55
|
+
isEmpty,
|
|
56
|
+
error,
|
|
57
|
+
hasNextPage,
|
|
58
|
+
isFetchingNextPage,
|
|
59
|
+
fetchNextPage
|
|
60
|
+
}), [
|
|
61
|
+
isLoading,
|
|
62
|
+
isEmpty,
|
|
63
|
+
error,
|
|
64
|
+
hasNextPage,
|
|
65
|
+
isFetchingNextPage,
|
|
66
|
+
fetchNextPage
|
|
67
|
+
]);
|
|
68
|
+
return /* @__PURE__ */ jsx(InfiniteScrollContext.Provider, {
|
|
69
|
+
value,
|
|
70
|
+
children
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function DefaultLoader({ label }) {
|
|
74
|
+
return /* @__PURE__ */ jsxs("output", {
|
|
75
|
+
"aria-live": "polite",
|
|
76
|
+
className: "flex items-center justify-center gap-2 px-4 py-6 text-fg-secondary text-gdt-sm",
|
|
77
|
+
children: [/* @__PURE__ */ jsx(Loader2, { className: "animate-spin" }), /* @__PURE__ */ jsx("span", { children: label })]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function InfiniteScrollLoading({ children }) {
|
|
81
|
+
const { isLoading, isFetchingNextPage } = useInfiniteScrollContext("InfiniteScrollLoading");
|
|
82
|
+
if (!isLoading && !isFetchingNextPage) return null;
|
|
83
|
+
return children ?? /* @__PURE__ */ jsx(DefaultLoader, { label: isFetchingNextPage ? "Loading more..." : "Loading..." });
|
|
84
|
+
}
|
|
85
|
+
function InfiniteScrollContent({ children }) {
|
|
86
|
+
const { isLoading, isEmpty } = useInfiniteScrollContext("InfiniteScrollContent");
|
|
87
|
+
if (isLoading || isEmpty) return null;
|
|
88
|
+
return children;
|
|
89
|
+
}
|
|
90
|
+
function InfiniteScrollEmpty({ children }) {
|
|
91
|
+
const { isLoading, isEmpty, error } = useInfiniteScrollContext("InfiniteScrollEmpty");
|
|
92
|
+
if (isLoading || error || !isEmpty) return null;
|
|
93
|
+
return children;
|
|
94
|
+
}
|
|
95
|
+
function InfiniteScrollError({ children }) {
|
|
96
|
+
const { error } = useInfiniteScrollContext("InfiniteScrollError");
|
|
97
|
+
if (!error) return null;
|
|
98
|
+
return children ?? /* @__PURE__ */ jsx("div", {
|
|
99
|
+
role: "alert",
|
|
100
|
+
className: "px-4 py-4 text-center text-fg-danger text-gdt-sm",
|
|
101
|
+
children: error.message || "Something went wrong while loading more items."
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function InfiniteScrollEnd({ children }) {
|
|
105
|
+
const { isLoading, isEmpty, hasNextPage, error } = useInfiniteScrollContext("InfiniteScrollEnd");
|
|
106
|
+
if (isLoading || isEmpty || hasNextPage || error) return null;
|
|
107
|
+
return children;
|
|
108
|
+
}
|
|
109
|
+
function InfiniteScrollSentinel({ rootMargin, className }) {
|
|
110
|
+
const { hasNextPage, isFetchingNextPage, fetchNextPage } = useInfiniteScrollContext("InfiniteScrollSentinel");
|
|
111
|
+
const ref = useInfiniteScrollSentinel({
|
|
112
|
+
hasNextPage,
|
|
113
|
+
isFetchingNextPage,
|
|
114
|
+
fetchNextPage,
|
|
115
|
+
rootMargin
|
|
116
|
+
});
|
|
117
|
+
if (!hasNextPage) return null;
|
|
118
|
+
return /* @__PURE__ */ jsx("div", {
|
|
119
|
+
ref,
|
|
120
|
+
"aria-hidden": "true",
|
|
121
|
+
className: cn("h-px", className)
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
export { InfiniteScroll, InfiniteScrollContent, InfiniteScrollEmpty, InfiniteScrollEnd, InfiniteScrollError, InfiniteScrollLoading, InfiniteScrollSentinel, useInfiniteScrollSentinel };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { t as cn } from "./cn-BI_4DMBf.js";
|
|
2
|
+
import { Button } from "./button.js";
|
|
3
|
+
import { useInputComponentSize } from "./input-size-context.js";
|
|
4
|
+
import { PopoverTrigger } from "./popover.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
//#region src/lib/picker.tsx
|
|
8
|
+
const PICKER_COLLISION_AVOIDANCE = {
|
|
9
|
+
side: "flip",
|
|
10
|
+
align: "shift",
|
|
11
|
+
fallbackAxisSide: "none"
|
|
12
|
+
};
|
|
13
|
+
const pickerTriggerVariants = cva("flex w-full items-center justify-between rounded-full border transition-[border-color,box-shadow] outline-none", {
|
|
14
|
+
variants: { size: {
|
|
15
|
+
sm: "h-8 px-3 text-gdt-xs [&_svg]:size-3.5",
|
|
16
|
+
md: "h-10 px-3.5 text-gdt-sm [&_svg]:size-4",
|
|
17
|
+
lg: "h-12 px-4 text-gdt-md [&_svg]:size-4.5",
|
|
18
|
+
xl: "h-14 px-4.5 text-gdt-lg [&_svg]:size-5"
|
|
19
|
+
} },
|
|
20
|
+
defaultVariants: { size: "md" }
|
|
21
|
+
});
|
|
22
|
+
function PickerTrigger({ icon: Icon, displayValue, placeholder, disabled, open, size, className }) {
|
|
23
|
+
const resolvedSize = useInputComponentSize(size);
|
|
24
|
+
return /* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
25
|
+
disabled,
|
|
26
|
+
"data-size": resolvedSize,
|
|
27
|
+
className: cn(pickerTriggerVariants({ size: resolvedSize }), disabled ? "cursor-not-allowed border-line-subtle bg-surface text-fg-caption-placeholder" : open ? "border-line-focus bg-canvas text-fg-primary inset-ring-1 inset-ring-line-focus" : "border-line bg-canvas text-fg-primary hover:border-line-strong", className),
|
|
28
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
29
|
+
className: cn("min-w-0 truncate", !displayValue && "text-fg-caption-placeholder"),
|
|
30
|
+
children: displayValue || placeholder
|
|
31
|
+
}), /* @__PURE__ */ jsx(Icon, { className: cn("ml-2 shrink-0", disabled ? "text-fg-caption-placeholder" : "text-fg-secondary") })]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function PickerFooter({ secondaryLabel, onSecondary, onApply }) {
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
36
|
+
className: "flex w-full items-center justify-between border-t border-line-subtle px-4 py-3",
|
|
37
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
38
|
+
variant: "tertiary-outline",
|
|
39
|
+
size: "sm",
|
|
40
|
+
onClick: onSecondary,
|
|
41
|
+
children: secondaryLabel
|
|
42
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
43
|
+
size: "sm",
|
|
44
|
+
onClick: onApply,
|
|
45
|
+
children: "Apply"
|
|
46
|
+
})]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { PickerFooter as n, PickerTrigger as r, PICKER_COLLISION_AVOIDANCE as t };
|
package/dist/popover.d.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { Popover as Popover$1 } from "@base-ui/react/popover";
|
|
|
4
4
|
//#region src/popover.d.ts
|
|
5
5
|
declare function Popover({ ...props }: Popover$1.Root.Props): React.JSX.Element;
|
|
6
6
|
declare function PopoverTrigger({ ...props }: Popover$1.Trigger.Props): React.JSX.Element;
|
|
7
|
-
type PopoverContentProps = Popover$1.Popup.Props & Pick<Popover$1.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset"> & {
|
|
7
|
+
type PopoverContentProps = Popover$1.Popup.Props & Pick<Popover$1.Positioner.Props, "align" | "alignOffset" | "collisionAvoidance" | "side" | "sideOffset"> & {
|
|
8
8
|
showArrow?: boolean;
|
|
9
9
|
size?: ComponentSize;
|
|
10
10
|
};
|
|
11
|
-
declare function PopoverContent({ className, align, alignOffset, side, sideOffset, showArrow, size, children, ...props }: PopoverContentProps): React.JSX.Element;
|
|
11
|
+
declare function PopoverContent({ className, align, alignOffset, collisionAvoidance, side, sideOffset, showArrow, size, children, ...props }: PopoverContentProps): React.JSX.Element;
|
|
12
12
|
declare function PopoverHeader({ className, border, ...props }: React.ComponentProps<"div"> & {
|
|
13
13
|
border?: boolean;
|
|
14
14
|
}): React.JSX.Element;
|
package/dist/popover.js
CHANGED
|
@@ -16,10 +16,11 @@ function PopoverTrigger({ ...props }) {
|
|
|
16
16
|
...props
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
function PopoverContent({ className, align = "center", alignOffset = 0, side = "bottom", sideOffset = 6, showArrow = true, size = "md", children, ...props }) {
|
|
19
|
+
function PopoverContent({ className, align = "center", alignOffset = 0, collisionAvoidance, side = "bottom", sideOffset = 6, showArrow = true, size = "md", children, ...props }) {
|
|
20
20
|
return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, {
|
|
21
21
|
align,
|
|
22
22
|
alignOffset,
|
|
23
|
+
collisionAvoidance,
|
|
23
24
|
side,
|
|
24
25
|
sideOffset,
|
|
25
26
|
className: "isolate z-50",
|
package/dist/styles.css
CHANGED
|
@@ -1449,9 +1449,6 @@
|
|
|
1449
1449
|
.scroll-py-1 {
|
|
1450
1450
|
scroll-padding-block: var(--spacing);
|
|
1451
1451
|
}
|
|
1452
|
-
.\[scrollbar-width\:none\] {
|
|
1453
|
-
scrollbar-width: none;
|
|
1454
|
-
}
|
|
1455
1452
|
.scrollbar-none {
|
|
1456
1453
|
scrollbar-width: none;
|
|
1457
1454
|
}
|
|
@@ -2165,6 +2162,9 @@
|
|
|
2165
2162
|
.p-gdt-xl {
|
|
2166
2163
|
padding: var(--spacing-gdt-xl);
|
|
2167
2164
|
}
|
|
2165
|
+
.px-\(--card-padding\) {
|
|
2166
|
+
padding-inline: var(--card-padding);
|
|
2167
|
+
}
|
|
2168
2168
|
.px-\(--cell-width\) {
|
|
2169
2169
|
padding-inline: var(--cell-width);
|
|
2170
2170
|
}
|
|
@@ -2240,6 +2240,9 @@
|
|
|
2240
2240
|
.px-gdt-xl {
|
|
2241
2241
|
padding-inline: var(--spacing-gdt-xl);
|
|
2242
2242
|
}
|
|
2243
|
+
.py-\(--card-padding\) {
|
|
2244
|
+
padding-block: var(--card-padding);
|
|
2245
|
+
}
|
|
2243
2246
|
.py-0 {
|
|
2244
2247
|
padding-block: 0;
|
|
2245
2248
|
}
|
|
@@ -2303,9 +2306,6 @@
|
|
|
2303
2306
|
.py-gdt-sm {
|
|
2304
2307
|
padding-block: var(--spacing-gdt-sm);
|
|
2305
2308
|
}
|
|
2306
|
-
.py-gdt-xl {
|
|
2307
|
-
padding-block: var(--spacing-gdt-xl);
|
|
2308
|
-
}
|
|
2309
2309
|
.pt-\(--sheet-padding-top\) {
|
|
2310
2310
|
padding-top: var(--sheet-padding-top);
|
|
2311
2311
|
}
|
|
@@ -2593,6 +2593,9 @@
|
|
|
2593
2593
|
.text-pretty {
|
|
2594
2594
|
text-wrap: pretty;
|
|
2595
2595
|
}
|
|
2596
|
+
.break-words {
|
|
2597
|
+
overflow-wrap: break-word;
|
|
2598
|
+
}
|
|
2596
2599
|
.wrap-break-word {
|
|
2597
2600
|
overflow-wrap: break-word;
|
|
2598
2601
|
}
|
|
@@ -3130,6 +3133,9 @@
|
|
|
3130
3133
|
.\[--anchor-y\:0px\] {
|
|
3131
3134
|
--anchor-y: 0px;
|
|
3132
3135
|
}
|
|
3136
|
+
.\[--card-padding\:1\.5rem\] {
|
|
3137
|
+
--card-padding: 1.5rem;
|
|
3138
|
+
}
|
|
3133
3139
|
.\[--cell-height\:36px\] {
|
|
3134
3140
|
--cell-height: 36px;
|
|
3135
3141
|
}
|
|
@@ -6181,6 +6187,25 @@
|
|
|
6181
6187
|
padding-right: 0;
|
|
6182
6188
|
}
|
|
6183
6189
|
}
|
|
6190
|
+
.has-data-\[slot\=combobox-virtualized\]\:max-h-none {
|
|
6191
|
+
&:has(*[data-slot="combobox-virtualized"]) {
|
|
6192
|
+
max-height: none;
|
|
6193
|
+
}
|
|
6194
|
+
}
|
|
6195
|
+
.has-data-\[slot\=combobox-virtualized\]\:space-y-0 {
|
|
6196
|
+
&:has(*[data-slot="combobox-virtualized"]) {
|
|
6197
|
+
:where(& > :not(:last-child)) {
|
|
6198
|
+
--tw-space-y-reverse: 0;
|
|
6199
|
+
margin-block-start: 0;
|
|
6200
|
+
margin-block-end: 0;
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6204
|
+
.has-data-\[slot\=combobox-virtualized\]\:overflow-hidden {
|
|
6205
|
+
&:has(*[data-slot="combobox-virtualized"]) {
|
|
6206
|
+
overflow: hidden;
|
|
6207
|
+
}
|
|
6208
|
+
}
|
|
6184
6209
|
.has-data-\[slot\=kbd\]\:pr-1\.5 {
|
|
6185
6210
|
&:has(*[data-slot="kbd"]) {
|
|
6186
6211
|
padding-right: calc(var(--spacing) * 1.5);
|
package/dist/table.js
CHANGED
|
@@ -79,7 +79,7 @@ function TableRow({ className, ...props }) {
|
|
|
79
79
|
function TableHead({ className, pinnedSide, ...props }) {
|
|
80
80
|
return /* @__PURE__ */ jsx("th", {
|
|
81
81
|
"data-slot": "table-head",
|
|
82
|
-
className: cn("relative h-14 px-6 py-4 text-left align-middle bg-surface-raised", "text-gdt-sm font-semibold text-fg-secondary", "
|
|
82
|
+
className: cn("relative h-14 px-6 py-4 text-left align-middle bg-surface-raised", "text-gdt-sm font-semibold text-fg-secondary", "break-words has-[[role=checkbox]]:pr-0", getPinnedDividerClassName(pinnedSide), className),
|
|
83
83
|
...props
|
|
84
84
|
});
|
|
85
85
|
}
|
|
@@ -95,7 +95,7 @@ function TableHead({ className, pinnedSide, ...props }) {
|
|
|
95
95
|
function TableCell({ className, pinned = false, pinnedSide, ...props }) {
|
|
96
96
|
return /* @__PURE__ */ jsx("td", {
|
|
97
97
|
"data-slot": "table-cell",
|
|
98
|
-
className: cn("relative h-14 px-6 py-4 align-middle text-gdt-sm text-fg-primary", "
|
|
98
|
+
className: cn("relative h-14 px-6 py-4 align-middle text-gdt-sm text-fg-primary", "break-words", pinned && "bg-canvas transition-[background-color,filter] group-hover:bg-surface group-active:bg-surface-raised group-data-[state=selected]:bg-surface-brand-subtle group-data-[state=selected]:group-hover:bg-surface-brand-subtle group-data-[state=selected]:group-hover:brightness-95 group-data-[state=selected]:group-active:brightness-90", getPinnedDividerClassName(pinnedSide), className),
|
|
99
99
|
...props
|
|
100
100
|
});
|
|
101
101
|
}
|
package/dist/tabs.js
CHANGED
|
@@ -24,9 +24,9 @@ function Tabs({ className, orientation = "horizontal", size, ...props }) {
|
|
|
24
24
|
children: root
|
|
25
25
|
}) : root;
|
|
26
26
|
}
|
|
27
|
-
const tabsListVariants = cva(cn("group/tabs-list relative inline-flex w-fit shrink-0 items-center gap-1 text-fg-secondary", "group-data-[orientation=
|
|
27
|
+
const tabsListVariants = cva(cn("group/tabs-list relative inline-flex w-fit shrink-0 items-center gap-1 text-fg-secondary", "group-data-[orientation=vertical]/tabs:flex-col"), {
|
|
28
28
|
variants: { variant: {
|
|
29
|
-
underline: "rounded-none bg-transparent p-0",
|
|
29
|
+
underline: cn("rounded-none bg-transparent p-0", "group-data-[orientation=horizontal]/tabs:border-b group-data-[orientation=horizontal]/tabs:border-line-subtle", "group-data-[orientation=vertical]/tabs:border-l group-data-[orientation=vertical]/tabs:border-line-subtle"),
|
|
30
30
|
secondary: "rounded-4xl bg-transparent p-0"
|
|
31
31
|
} },
|
|
32
32
|
defaultVariants: { variant: "underline" }
|
package/dist/time-picker.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as InputSize } from "./input-CfoEJ8A6.js";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
//#region src/time-picker.d.ts
|
|
3
4
|
interface TimePickerProps {
|
|
@@ -5,9 +6,11 @@ interface TimePickerProps {
|
|
|
5
6
|
onChange?: (time: string | undefined) => void;
|
|
6
7
|
format?: "12h" | "24h";
|
|
7
8
|
disabled?: boolean;
|
|
9
|
+
/** Controls the trigger size. The time selection panel is not resized. */
|
|
10
|
+
size?: InputSize;
|
|
8
11
|
placeholder?: string;
|
|
9
12
|
className?: string;
|
|
10
13
|
}
|
|
11
|
-
declare function TimePicker({ value, onChange, format, disabled, placeholder, className }: TimePickerProps): React.JSX.Element;
|
|
14
|
+
declare function TimePicker({ value, onChange, format, disabled, size, placeholder, className }: TimePickerProps): React.JSX.Element;
|
|
12
15
|
//#endregion
|
|
13
16
|
export { TimePicker, type TimePickerProps };
|