@wallarm-org/design-system 1.31.0 → 1.32.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/Stepper/Stepper.d.ts +22 -0
- package/dist/components/Stepper/Stepper.figma.d.ts +1 -0
- package/dist/components/Stepper/Stepper.figma.js +59 -0
- package/dist/components/Stepper/Stepper.js +34 -0
- package/dist/components/Stepper/StepperContent.d.ts +16 -0
- package/dist/components/Stepper/StepperContent.js +28 -0
- package/dist/components/Stepper/StepperContext.d.ts +58 -0
- package/dist/components/Stepper/StepperContext.js +37 -0
- package/dist/components/Stepper/StepperDescription.d.ts +8 -0
- package/dist/components/Stepper/StepperDescription.js +30 -0
- package/dist/components/Stepper/StepperIndicator.d.ts +9 -0
- package/dist/components/Stepper/StepperIndicator.js +34 -0
- package/dist/components/Stepper/StepperItem.d.ts +19 -0
- package/dist/components/Stepper/StepperItem.js +48 -0
- package/dist/components/Stepper/StepperList.d.ts +12 -0
- package/dist/components/Stepper/StepperList.js +28 -0
- package/dist/components/Stepper/StepperNextTrigger.d.ts +14 -0
- package/dist/components/Stepper/StepperNextTrigger.js +28 -0
- package/dist/components/Stepper/StepperPrevTrigger.d.ts +13 -0
- package/dist/components/Stepper/StepperPrevTrigger.js +31 -0
- package/dist/components/Stepper/StepperRootProvider.d.ts +18 -0
- package/dist/components/Stepper/StepperRootProvider.js +25 -0
- package/dist/components/Stepper/StepperSeparator.d.ts +7 -0
- package/dist/components/Stepper/StepperSeparator.js +28 -0
- package/dist/components/Stepper/StepperTitle.d.ts +8 -0
- package/dist/components/Stepper/StepperTitle.js +32 -0
- package/dist/components/Stepper/StepperTrigger.d.ts +16 -0
- package/dist/components/Stepper/StepperTrigger.js +32 -0
- package/dist/components/Stepper/classes.d.ts +14 -0
- package/dist/components/Stepper/classes.js +37 -0
- package/dist/components/Stepper/constants.d.ts +22 -0
- package/dist/components/Stepper/constants.js +23 -0
- package/dist/components/Stepper/index.d.ts +15 -0
- package/dist/components/Stepper/index.js +14 -0
- package/dist/components/Stepper/takeAsChildDisabled.d.ts +11 -0
- package/dist/components/Stepper/takeAsChildDisabled.js +17 -0
- package/dist/components/Stepper/types.d.ts +11 -0
- package/dist/components/Stepper/types.js +0 -0
- package/dist/components/Stepper/useStepper.d.ts +38 -0
- package/dist/components/Stepper/useStepper.js +58 -0
- package/dist/components/Table/TableBody/TableBodyVirtualizedCore.js +1 -1
- package/dist/components/Table/TableBody/TableBodyVirtualizedWindow.js +30 -8
- package/dist/components/Table/TableInner/TableInnerWindow.js +7 -2
- package/dist/components/Table/hooks/index.d.ts +1 -0
- package/dist/components/Table/hooks/index.js +1 -0
- package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.d.ts +4 -2
- package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.js +6 -2
- package/dist/components/Table/hooks/infiniteScroll/useInitialAnchor.d.ts +7 -1
- package/dist/components/Table/hooks/infiniteScroll/useInitialAnchor.js +4 -3
- package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.d.ts +4 -1
- package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.js +13 -11
- package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.d.ts +4 -1
- package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.js +7 -18
- package/dist/components/Table/hooks/useWindowScrollRoot.d.ts +26 -0
- package/dist/components/Table/hooks/useWindowScrollRoot.js +62 -0
- package/dist/components/Table/lib/index.d.ts +1 -0
- package/dist/components/Table/lib/index.js +1 -0
- package/dist/components/Table/lib/scrollRoot.d.ts +24 -0
- package/dist/components/Table/lib/scrollRoot.js +22 -0
- package/dist/components/Table/types.d.ts +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/metadata/components.json +4097 -426
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { useTestId } from "../../utils/testId.js";
|
|
4
|
+
import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from "../OverflowTooltip/index.js";
|
|
5
|
+
import { stepperTitleVariants } from "./classes.js";
|
|
6
|
+
import { useStepperItemContext } from "./StepperContext.js";
|
|
7
|
+
const StepperTitle = ({ children, className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
8
|
+
const { status } = useStepperItemContext();
|
|
9
|
+
const testId = useTestId('title', testIdProp);
|
|
10
|
+
return /*#__PURE__*/ jsxs(OverflowTooltip, {
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ jsx(OverflowTooltipTrigger, {
|
|
13
|
+
ref: ref,
|
|
14
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
15
|
+
...rest,
|
|
16
|
+
"data-slot": "stepper-title",
|
|
17
|
+
"data-status": status,
|
|
18
|
+
"data-testid": testId,
|
|
19
|
+
className: cn(stepperTitleVariants({
|
|
20
|
+
status
|
|
21
|
+
}), className),
|
|
22
|
+
children: children
|
|
23
|
+
})
|
|
24
|
+
}),
|
|
25
|
+
/*#__PURE__*/ jsx(OverflowTooltipContent, {
|
|
26
|
+
children: children
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
StepperTitle.displayName = 'StepperTitle';
|
|
32
|
+
export { StepperTitle };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, FC, ReactNode, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
export interface StepperTriggerProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'>, TestableProps {
|
|
4
|
+
/** `StepperIndicator`, `StepperTitle` and an optional `StepperDescription`. */
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
ref?: Ref<HTMLButtonElement>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The step's button: a click makes the step current. Carries `aria-current="step"` while
|
|
10
|
+
* current, a screen-reader-only status suffix (", Completed" / ", Has errors") and every
|
|
11
|
+
* consumer attribute, so analytics land on the real `<button>`.
|
|
12
|
+
*
|
|
13
|
+
* Set its `id` with the root `ids.triggerId` prop: `StepperContent` is named by the root's trigger
|
|
14
|
+
* id, so an `id` passed here leaves the body's `aria-labelledby` pointing at nothing.
|
|
15
|
+
*/
|
|
16
|
+
export declare const StepperTrigger: FC<StepperTriggerProps>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Steps } from "@ark-ui/react/steps";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { stepperTriggerVariants } from "./classes.js";
|
|
6
|
+
import { ARK_TAB_ARIA_RESET } from "./constants.js";
|
|
7
|
+
import { useStepperItemContext } from "./StepperContext.js";
|
|
8
|
+
const StepperTrigger = ({ children, className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
9
|
+
const { current, status, statusLabel } = useStepperItemContext();
|
|
10
|
+
const testId = useTestId('trigger', testIdProp);
|
|
11
|
+
if ('production' !== process.env.NODE_ENV && void 0 !== rest.id) console.warn(`[Stepper] id="${rest.id}" on StepperTrigger: set trigger ids with the root \`ids.triggerId\` prop, or StepperContent's aria-labelledby points at nothing.`);
|
|
12
|
+
return /*#__PURE__*/ jsxs(Steps.Trigger, {
|
|
13
|
+
...ARK_TAB_ARIA_RESET,
|
|
14
|
+
"aria-current": current ? 'step' : void 0,
|
|
15
|
+
...rest,
|
|
16
|
+
ref: ref,
|
|
17
|
+
type: "button",
|
|
18
|
+
"data-slot": "stepper-trigger",
|
|
19
|
+
"data-status": status,
|
|
20
|
+
"data-testid": testId,
|
|
21
|
+
className: cn(stepperTriggerVariants(), className),
|
|
22
|
+
children: [
|
|
23
|
+
children,
|
|
24
|
+
statusLabel && /*#__PURE__*/ jsx("span", {
|
|
25
|
+
className: "sr-only",
|
|
26
|
+
children: `, ${statusLabel}`
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
StepperTrigger.displayName = 'StepperTrigger';
|
|
32
|
+
export { StepperTrigger };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const stepperVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
2
|
+
export declare const stepperListVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
3
|
+
export declare const stepperItemVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
4
|
+
export declare const stepperTriggerVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
5
|
+
export declare const stepperIndicatorVariants: (props?: ({
|
|
6
|
+
status?: "active" | "completed" | "danger" | "upcoming" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
export declare const stepperTitleVariants: (props?: ({
|
|
9
|
+
status?: "active" | "completed" | "danger" | "upcoming" | null | undefined;
|
|
10
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
|
+
export declare const stepperDescriptionVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
12
|
+
export declare const stepperSeparatorVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
13
|
+
export declare const stepperSeparatorLineClassNames = "block h-px w-full bg-border-primary";
|
|
14
|
+
export declare const stepperContentVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
const stepperVariants = cva('min-w-0');
|
|
4
|
+
const stepperListVariants = cva('m-0 flex min-w-0 list-none items-start border-b-1 border-border-primary-light px-24 py-8');
|
|
5
|
+
const stepperItemVariants = cva('flex min-w-0 items-start');
|
|
6
|
+
const stepperTriggerVariants = cva(cn('grid min-w-0 cursor-pointer grid-cols-[auto_minmax(0,1fr)] grid-rows-[20px] items-start gap-x-4 bg-transparent p-0 text-left', 'rounded-6 focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-focus-primary'));
|
|
7
|
+
const stepperIndicatorVariants = cva("col-start-1 row-span-2 row-start-1 inline-flex h-20 min-w-16 shrink-0 items-center justify-center rounded-full font-mono font-medium text-xs [font-feature-settings:'liga'_0]", {
|
|
8
|
+
variants: {
|
|
9
|
+
status: {
|
|
10
|
+
active: 'bg-states-brand-active px-4 py-2 text-text-brand',
|
|
11
|
+
danger: 'bg-states-danger-active px-4 py-2 text-text-danger',
|
|
12
|
+
completed: 'bg-states-primary-active px-2 py-2 text-icon-primary',
|
|
13
|
+
upcoming: 'border-1 border-border-primary bg-component-outline-button-bg px-3 py-1 text-text-primary'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
status: 'upcoming'
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const stepperTitleVariants = cva('col-start-2 row-start-1 block min-w-0 max-w-320 truncate font-sans font-normal text-sm', {
|
|
21
|
+
variants: {
|
|
22
|
+
status: {
|
|
23
|
+
active: 'text-text-brand',
|
|
24
|
+
danger: 'text-text-danger',
|
|
25
|
+
completed: 'text-text-primary',
|
|
26
|
+
upcoming: 'text-text-primary'
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
status: 'upcoming'
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const stepperDescriptionVariants = cva('col-start-2 row-start-2 -mt-2 block min-w-0 max-w-320 truncate font-sans text-text-secondary text-xs');
|
|
34
|
+
const stepperSeparatorVariants = cva('flex h-20 w-32 shrink-0 items-center px-8');
|
|
35
|
+
const stepperSeparatorLineClassNames = 'block h-px w-full bg-border-primary';
|
|
36
|
+
const stepperContentVariants = cva('min-w-0');
|
|
37
|
+
export { stepperContentVariants, stepperDescriptionVariants, stepperIndicatorVariants, stepperItemVariants, stepperListVariants, stepperSeparatorLineClassNames, stepperSeparatorVariants, stepperTitleVariants, stepperTriggerVariants, stepperVariants };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const ARK_LIST_ARIA_RESET: {
|
|
2
|
+
readonly role: undefined;
|
|
3
|
+
readonly 'aria-owns': undefined;
|
|
4
|
+
readonly 'aria-orientation': undefined;
|
|
5
|
+
};
|
|
6
|
+
export declare const ARK_ITEM_ARIA_RESET: {
|
|
7
|
+
readonly 'aria-current': undefined;
|
|
8
|
+
};
|
|
9
|
+
export declare const ARK_TAB_ARIA_RESET: {
|
|
10
|
+
readonly role: undefined;
|
|
11
|
+
readonly 'aria-selected': undefined;
|
|
12
|
+
readonly 'aria-controls': undefined;
|
|
13
|
+
};
|
|
14
|
+
export declare const ARK_CONTENT_ARIA_RESET: {
|
|
15
|
+
readonly tabIndex: undefined;
|
|
16
|
+
};
|
|
17
|
+
/** The design supports up to six steps; more logs a dev warning. */
|
|
18
|
+
export declare const STEPPER_MAX_STEPS = 6;
|
|
19
|
+
export declare const DEFAULT_STEPPER_STATUS_LABELS: {
|
|
20
|
+
readonly completed: 'Completed';
|
|
21
|
+
readonly danger: 'Has errors';
|
|
22
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const REMOVE = null;
|
|
2
|
+
const ARK_LIST_ARIA_RESET = {
|
|
3
|
+
role: REMOVE,
|
|
4
|
+
'aria-owns': REMOVE,
|
|
5
|
+
'aria-orientation': REMOVE
|
|
6
|
+
};
|
|
7
|
+
const ARK_ITEM_ARIA_RESET = {
|
|
8
|
+
'aria-current': REMOVE
|
|
9
|
+
};
|
|
10
|
+
const ARK_TAB_ARIA_RESET = {
|
|
11
|
+
role: REMOVE,
|
|
12
|
+
'aria-selected': REMOVE,
|
|
13
|
+
'aria-controls': REMOVE
|
|
14
|
+
};
|
|
15
|
+
const ARK_CONTENT_ARIA_RESET = {
|
|
16
|
+
tabIndex: REMOVE
|
|
17
|
+
};
|
|
18
|
+
const STEPPER_MAX_STEPS = 6;
|
|
19
|
+
const DEFAULT_STEPPER_STATUS_LABELS = {
|
|
20
|
+
completed: 'Completed',
|
|
21
|
+
danger: 'Has errors'
|
|
22
|
+
};
|
|
23
|
+
export { ARK_CONTENT_ARIA_RESET, ARK_ITEM_ARIA_RESET, ARK_LIST_ARIA_RESET, ARK_TAB_ARIA_RESET, DEFAULT_STEPPER_STATUS_LABELS, STEPPER_MAX_STEPS };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Stepper, type StepperProps } from './Stepper';
|
|
2
|
+
export { StepperContent, type StepperContentProps } from './StepperContent';
|
|
3
|
+
export { type StepperItemContextValue, type UseStepperContextReturn, useStepperContext, useStepperItemContext, } from './StepperContext';
|
|
4
|
+
export { StepperDescription, type StepperDescriptionProps } from './StepperDescription';
|
|
5
|
+
export { StepperIndicator, type StepperIndicatorProps } from './StepperIndicator';
|
|
6
|
+
export { StepperItem, type StepperItemProps } from './StepperItem';
|
|
7
|
+
export { StepperList, type StepperListProps } from './StepperList';
|
|
8
|
+
export { StepperNextTrigger, type StepperNextTriggerProps } from './StepperNextTrigger';
|
|
9
|
+
export { StepperPrevTrigger, type StepperPrevTriggerProps } from './StepperPrevTrigger';
|
|
10
|
+
export { StepperRootProvider, type StepperRootProviderProps } from './StepperRootProvider';
|
|
11
|
+
export { StepperSeparator, type StepperSeparatorProps } from './StepperSeparator';
|
|
12
|
+
export { StepperTitle, type StepperTitleProps } from './StepperTitle';
|
|
13
|
+
export { StepperTrigger, type StepperTriggerProps } from './StepperTrigger';
|
|
14
|
+
export type { StepperItemStatus, StepperStatusLabels, StepperVisualStatus } from './types';
|
|
15
|
+
export { type UseStepperProps, type UseStepperReturn, useStepper } from './useStepper';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { Stepper } from "./Stepper.js";
|
|
2
|
+
export { StepperContent } from "./StepperContent.js";
|
|
3
|
+
export { useStepperContext, useStepperItemContext } from "./StepperContext.js";
|
|
4
|
+
export { StepperDescription } from "./StepperDescription.js";
|
|
5
|
+
export { StepperIndicator } from "./StepperIndicator.js";
|
|
6
|
+
export { StepperItem } from "./StepperItem.js";
|
|
7
|
+
export { StepperList } from "./StepperList.js";
|
|
8
|
+
export { StepperNextTrigger } from "./StepperNextTrigger.js";
|
|
9
|
+
export { StepperPrevTrigger } from "./StepperPrevTrigger.js";
|
|
10
|
+
export { StepperRootProvider } from "./StepperRootProvider.js";
|
|
11
|
+
export { StepperSeparator } from "./StepperSeparator.js";
|
|
12
|
+
export { StepperTitle } from "./StepperTitle.js";
|
|
13
|
+
export { StepperTrigger } from "./StepperTrigger.js";
|
|
14
|
+
export { useStepper } from "./useStepper.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* With `asChild`, Ark merges the child's props over the trigger's, so a child `disabled={false}`
|
|
4
|
+
* (e.g. `<Button disabled={isSaving}>`) would re-enable Next on the last step or Prev on the first.
|
|
5
|
+
* This takes the child's `disabled` out, for the trigger to fold into its own, so the trigger's
|
|
6
|
+
* computed value always wins.
|
|
7
|
+
*/
|
|
8
|
+
export declare const takeAsChildDisabled: (asChild: boolean | undefined, children: ReactNode) => {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
childDisabled?: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { cloneElement, isValidElement } from "react";
|
|
2
|
+
const takeAsChildDisabled = (asChild, children)=>{
|
|
3
|
+
if (!asChild || !isValidElement(children)) return {
|
|
4
|
+
children
|
|
5
|
+
};
|
|
6
|
+
const { disabled } = children.props;
|
|
7
|
+
if (void 0 === disabled) return {
|
|
8
|
+
children
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
children: cloneElement(children, {
|
|
12
|
+
disabled: void 0
|
|
13
|
+
}),
|
|
14
|
+
childDisabled: disabled
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export { takeAsChildDisabled };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Status set by the page. `'active'` is never passed: it is derived from the current step. */
|
|
2
|
+
export type StepperItemStatus = 'upcoming' | 'completed' | 'danger';
|
|
3
|
+
/** Rendered state, exposed as `data-status`. */
|
|
4
|
+
export type StepperVisualStatus = 'active' | StepperItemStatus;
|
|
5
|
+
/** Screen-reader-only status suffixes (i18n). */
|
|
6
|
+
export interface StepperStatusLabels {
|
|
7
|
+
/** Default `'Completed'`. */
|
|
8
|
+
completed?: string;
|
|
9
|
+
/** Default `'Has errors'`. */
|
|
10
|
+
danger?: string;
|
|
11
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type UseStepsProps, type UseStepsReturn } from '@ark-ui/react/steps';
|
|
2
|
+
/** Ark props the Stepper does not support: it never blocks a step and is horizontal only. */
|
|
3
|
+
export type StepperOmittedArkProps = 'linear' | 'isStepValid' | 'isStepSkippable' | 'onStepInvalid' | 'onStepComplete' | 'orientation';
|
|
4
|
+
export interface StepperGuardProps {
|
|
5
|
+
/** Number of steps, 1–6. Required: each `StepperItem` and `StepperContent` takes its `index`. */
|
|
6
|
+
count: number;
|
|
7
|
+
/** Controlled current step, 0-based. Clamped to `[0, count - 1]`. */
|
|
8
|
+
step?: number;
|
|
9
|
+
/** Uncontrolled initial step. Default `0`. Clamped to `[0, count - 1]`. */
|
|
10
|
+
defaultStep?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Fires when a click changes the step, back or forward: `({ step }) => void`. A click on the
|
|
13
|
+
* current step does not fire it; use the trigger's `onClick` to observe that.
|
|
14
|
+
*/
|
|
15
|
+
onStepChange?: UseStepsProps['onStepChange'];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The root guards shared by `Stepper` and `useStepper`: clamps `step` / `defaultStep`, warns in
|
|
19
|
+
* development, and never reports a step past the last one (Ark's "completed" state).
|
|
20
|
+
*/
|
|
21
|
+
export declare const useStepperGuards: ({ count, step, defaultStep, onStepChange }: StepperGuardProps) => {
|
|
22
|
+
count: number;
|
|
23
|
+
step?: number | undefined;
|
|
24
|
+
defaultStep?: number | undefined;
|
|
25
|
+
onStepChange: ((details: {
|
|
26
|
+
step: number;
|
|
27
|
+
}) => void) | undefined;
|
|
28
|
+
};
|
|
29
|
+
export interface UseStepperProps extends Omit<UseStepsProps, StepperOmittedArkProps | keyof StepperGuardProps>, StepperGuardProps {
|
|
30
|
+
}
|
|
31
|
+
export type UseStepperReturn = UseStepsReturn;
|
|
32
|
+
/**
|
|
33
|
+
* Creates the Stepper machine outside the component, for `StepperRootProvider`. Wraps Ark's
|
|
34
|
+
* `useSteps` with the same guards as `Stepper` and `useStepperContext`: the step is clamped to
|
|
35
|
+
* `[0, count - 1]`, `setStep` clamps too, and Next / Back move from the shown step, so the machine
|
|
36
|
+
* never reaches Ark's "completed" state (`isCompleted` is always `false`).
|
|
37
|
+
*/
|
|
38
|
+
export declare const useStepper: ({ count, step, defaultStep, onStepChange, ...rest }: UseStepperProps) => UseStepperReturn;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useSteps } from "@ark-ui/react/steps";
|
|
2
|
+
import { STEPPER_MAX_STEPS } from "./constants.js";
|
|
3
|
+
import { clampStep } from "./StepperContext.js";
|
|
4
|
+
const warn = (message)=>console.warn(`[Stepper] ${message}`);
|
|
5
|
+
const useStepperGuards = ({ count, step, defaultStep, onStepChange })=>{
|
|
6
|
+
const clamp = (value)=>void 0 === value ? void 0 : clampStep(value, count);
|
|
7
|
+
const clampedStep = clamp(step);
|
|
8
|
+
const clampedDefaultStep = clamp(defaultStep);
|
|
9
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
10
|
+
if (count > STEPPER_MAX_STEPS) warn(`${count} steps; the design supports up to ${STEPPER_MAX_STEPS}.`);
|
|
11
|
+
if (count < 1) warn(`count=${count}; a Stepper needs at least one step.`);
|
|
12
|
+
if (void 0 !== step && step !== clampedStep) warn(`step=${step} is out of range [0, ${count - 1}]; clamped.`);
|
|
13
|
+
if (void 0 !== defaultStep && defaultStep !== clampedDefaultStep) warn(`defaultStep=${defaultStep} is out of range [0, ${count - 1}]; clamped.`);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
count,
|
|
17
|
+
...void 0 !== clampedStep && {
|
|
18
|
+
step: clampedStep
|
|
19
|
+
},
|
|
20
|
+
...void 0 !== clampedDefaultStep && {
|
|
21
|
+
defaultStep: clampedDefaultStep
|
|
22
|
+
},
|
|
23
|
+
onStepChange: onStepChange ? (details)=>{
|
|
24
|
+
if (details.step <= count - 1) onStepChange(details);
|
|
25
|
+
} : void 0
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const useStepper = ({ count, step, defaultStep, onStepChange, ...rest })=>{
|
|
29
|
+
const guarded = useStepperGuards({
|
|
30
|
+
count,
|
|
31
|
+
step,
|
|
32
|
+
defaultStep,
|
|
33
|
+
onStepChange
|
|
34
|
+
});
|
|
35
|
+
const api = useSteps({
|
|
36
|
+
...rest,
|
|
37
|
+
...guarded
|
|
38
|
+
});
|
|
39
|
+
const value = clampStep(api.value, api.count);
|
|
40
|
+
const hasNextStep = value < api.count - 1;
|
|
41
|
+
const hasPrevStep = value > 0;
|
|
42
|
+
return {
|
|
43
|
+
...api,
|
|
44
|
+
value,
|
|
45
|
+
percent: api.count > 0 ? value / api.count * 100 : 0,
|
|
46
|
+
isCompleted: false,
|
|
47
|
+
hasNextStep,
|
|
48
|
+
hasPrevStep,
|
|
49
|
+
goToNextStep: ()=>{
|
|
50
|
+
if (hasNextStep) api.setStep(value + 1);
|
|
51
|
+
},
|
|
52
|
+
goToPrevStep: ()=>{
|
|
53
|
+
if (hasPrevStep) api.setStep(value - 1);
|
|
54
|
+
},
|
|
55
|
+
setStep: (next)=>api.setStep(clampStep(next, api.count))
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export { useStepper, useStepperGuards };
|
|
@@ -47,7 +47,7 @@ const TableBodyVirtualizedCore = ({ tbodyRef, virtualizer })=>{
|
|
|
47
47
|
virtualRows.length > 0 && /*#__PURE__*/ jsx(Tr, {
|
|
48
48
|
children: /*#__PURE__*/ jsx(Td, {
|
|
49
49
|
style: {
|
|
50
|
-
height: `${totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0)}px`,
|
|
50
|
+
height: `${totalSize + scrollMargin - (virtualRows[virtualRows.length - 1]?.end ?? 0)}px`,
|
|
51
51
|
padding: 0,
|
|
52
52
|
border: 'none'
|
|
53
53
|
},
|
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useCallback, useContext, useEffect, useLayoutEffect, useRef } from "react";
|
|
3
|
+
import { elementScroll, observeElementOffset, observeElementRect, observeWindowOffset, observeWindowRect, useVirtualizer } from "@tanstack/react-virtual";
|
|
4
|
+
import { WindowScrollRootContext } from "../hooks/useWindowScrollRoot.js";
|
|
5
|
+
import { TABLE_VIRTUALIZATION_OVERSCAN, getOffsetTopInScrollRoot, getRowKey, getScrollMetrics, isWindowScrollRoot } from "../lib/index.js";
|
|
5
6
|
import { useTableContext } from "../TableContext/index.js";
|
|
6
|
-
import { getDocumentOffsetTop } from "./lib/getDocumentOffsetTop.js";
|
|
7
7
|
import { measureRowElement } from "./lib/measureRowElement.js";
|
|
8
8
|
import { TableBodyVirtualizedCore } from "./TableBodyVirtualizedCore.js";
|
|
9
9
|
import { useResetVirtualizerOnDataChange } from "./useResetVirtualizerOnDataChange.js";
|
|
10
10
|
import { useSmoothScrollOnSort } from "./useSmoothScrollOnSort.js";
|
|
11
|
+
const isWindowRoot = (instance)=>instance.scrollElement === window;
|
|
12
|
+
const observeRootRect = (instance, cb)=>isWindowRoot(instance) ? observeWindowRect(instance, cb) : observeElementRect(instance, cb);
|
|
13
|
+
const observeRootOffset = (instance, cb)=>isWindowRoot(instance) ? observeWindowOffset(instance, cb) : observeElementOffset(instance, cb);
|
|
11
14
|
const TableBodyVirtualizedWindow = ()=>{
|
|
12
15
|
const { table, estimateRowHeight, overscan, tbodyRef, virtualizerRef } = useTableContext();
|
|
13
|
-
const
|
|
16
|
+
const scrollRoot = useContext(WindowScrollRootContext);
|
|
17
|
+
const scrollRootRef = useRef(scrollRoot);
|
|
18
|
+
scrollRootRef.current = scrollRoot;
|
|
19
|
+
const getScrollElement = useCallback(()=>scrollRootRef.current, []);
|
|
20
|
+
useLayoutEffect(()=>{
|
|
21
|
+
const instance = virtualizerRef.current;
|
|
22
|
+
if (instance && instance.scrollElement !== scrollRoot) instance.scrollOffset = null;
|
|
23
|
+
});
|
|
24
|
+
const virtualizer = useVirtualizer({
|
|
14
25
|
count: table.getRowModel().rows.length,
|
|
26
|
+
getScrollElement: getScrollElement,
|
|
27
|
+
observeElementRect: observeRootRect,
|
|
28
|
+
observeElementOffset: observeRootOffset,
|
|
29
|
+
scrollToFn: elementScroll,
|
|
30
|
+
initialRect: scrollRoot && isWindowScrollRoot(scrollRoot) ? {
|
|
31
|
+
width: scrollRoot.innerWidth,
|
|
32
|
+
height: scrollRoot.innerHeight
|
|
33
|
+
} : void 0,
|
|
34
|
+
initialOffset: ()=>{
|
|
35
|
+
const root = getScrollElement() ?? ("u" < typeof window ? null : window);
|
|
36
|
+
return root ? getScrollMetrics(root).scrollTop : 0;
|
|
37
|
+
},
|
|
15
38
|
estimateSize: estimateRowHeight ?? (()=>40),
|
|
16
39
|
overscan: overscan ?? TABLE_VIRTUALIZATION_OVERSCAN,
|
|
17
|
-
scrollMargin: tbodyRef.current ?
|
|
40
|
+
scrollMargin: tbodyRef.current && scrollRoot ? getOffsetTopInScrollRoot(tbodyRef.current, scrollRoot) : 0,
|
|
18
41
|
getItemKey: useCallback((index)=>getRowKey(table.getRowModel().rows, index), [
|
|
19
42
|
table
|
|
20
43
|
]),
|
|
@@ -27,8 +50,7 @@ const TableBodyVirtualizedWindow = ()=>{
|
|
|
27
50
|
virtualizerRef
|
|
28
51
|
]);
|
|
29
52
|
useResetVirtualizerOnDataChange(table, virtualizer);
|
|
30
|
-
|
|
31
|
-
useSmoothScrollOnSort(table, getScrollTarget);
|
|
53
|
+
useSmoothScrollOnSort(table, getScrollElement);
|
|
32
54
|
return /*#__PURE__*/ jsx(TableBodyVirtualizedCore, {
|
|
33
55
|
tbodyRef: tbodyRef,
|
|
34
56
|
virtualizer: virtualizer
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
3
|
import { useTestId } from "../../../utils/testId.js";
|
|
4
4
|
import { ScrollArea, ScrollAreaScrollbar, ScrollAreaViewport } from "../../ScrollArea/index.js";
|
|
5
|
-
import { useInfiniteScroll, useWheelHorizontalScroll } from "../hooks/index.js";
|
|
5
|
+
import { WindowScrollRootContext, useInfiniteScroll, useWheelHorizontalScroll, useWindowScrollRoot } from "../hooks/index.js";
|
|
6
6
|
import { useContainerWidth } from "../lib/index.js";
|
|
7
7
|
import { StickyGroupParent } from "../StickyGroupParent.js";
|
|
8
8
|
import { TableBody } from "../TableBody/index.js";
|
|
@@ -15,8 +15,10 @@ const TableInnerWindow = ({ isEmpty, showSettings, hasConsumerSettingsMenu, aria
|
|
|
15
15
|
const testId = useTestId('window');
|
|
16
16
|
const rootRef = useRef(null);
|
|
17
17
|
const containerWidth = useContainerWidth(rootRef);
|
|
18
|
+
const { scrollRoot, isSettled } = useWindowScrollRoot(containerRef, !isEmpty && table.getRowModel().rows.length > 0);
|
|
18
19
|
useInfiniteScroll({
|
|
19
20
|
mode: 'window',
|
|
21
|
+
scrollRoot: isSettled ? scrollRoot : null,
|
|
20
22
|
table,
|
|
21
23
|
virtualizerRef,
|
|
22
24
|
tbodyRef,
|
|
@@ -102,7 +104,10 @@ const TableInnerWindow = ({ isEmpty, showSettings, hasConsumerSettingsMenu, aria
|
|
|
102
104
|
/*#__PURE__*/ jsx(TableColGroup, {
|
|
103
105
|
tableWidth: tableWidth
|
|
104
106
|
}),
|
|
105
|
-
!isEmpty && /*#__PURE__*/ jsx(
|
|
107
|
+
!isEmpty && /*#__PURE__*/ jsx(WindowScrollRootContext, {
|
|
108
|
+
value: scrollRoot,
|
|
109
|
+
children: /*#__PURE__*/ jsx(TableBody, {})
|
|
110
|
+
})
|
|
106
111
|
]
|
|
107
112
|
}),
|
|
108
113
|
children
|
|
@@ -4,3 +4,4 @@ export { useMasterCell } from './useMasterCell';
|
|
|
4
4
|
export { useStickyGroupParent } from './useStickyGroupParent';
|
|
5
5
|
export { useTableState } from './useTableState';
|
|
6
6
|
export { useWheelHorizontalScroll } from './useWheelHorizontalScroll';
|
|
7
|
+
export { useWindowScrollRoot, WindowScrollRootContext } from './useWindowScrollRoot';
|
|
@@ -4,3 +4,4 @@ export { useMasterCell } from "./useMasterCell.js";
|
|
|
4
4
|
export { useStickyGroupParent } from "./useStickyGroupParent.js";
|
|
5
5
|
export { useTableState } from "./useTableState.js";
|
|
6
6
|
export { useWheelHorizontalScroll } from "./useWheelHorizontalScroll.js";
|
|
7
|
+
export { WindowScrollRootContext, useWindowScrollRoot } from "./useWindowScrollRoot.js";
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
2
|
import type { RowData, Table } from '@tanstack/react-table';
|
|
3
|
-
import { type DSTableFeatures } from '../../lib';
|
|
3
|
+
import { type DSTableFeatures, type ScrollRoot } from '../../lib';
|
|
4
4
|
import type { TableVirtualizerInstance } from '../../TableContext/types';
|
|
5
5
|
interface UseInfiniteScrollOptions<T extends RowData> {
|
|
6
6
|
mode: 'container' | 'window';
|
|
7
7
|
/** Scroll element ref — required for `container` mode */
|
|
8
8
|
scrollRef?: RefObject<HTMLElement | null>;
|
|
9
|
+
/** `window` mode: the resolved scroll root (see `useWindowScrollRoot`) */
|
|
10
|
+
scrollRoot?: ScrollRoot | null;
|
|
9
11
|
table: Table<DSTableFeatures, T>;
|
|
10
12
|
virtualizerRef: RefObject<TableVirtualizerInstance | null>;
|
|
11
13
|
tbodyRef?: RefObject<HTMLTableSectionElement | null>;
|
|
@@ -18,5 +20,5 @@ interface UseInfiniteScrollOptions<T extends RowData> {
|
|
|
18
20
|
isLoadingPrevious?: boolean;
|
|
19
21
|
}
|
|
20
22
|
/** Single entry point for bidirectional infinite scroll behavior. */
|
|
21
|
-
export declare const useInfiniteScroll: <T extends RowData>({ mode, scrollRef, table, virtualizerRef, tbodyRef, onStartReached, onStartReachedThreshold, onEndReached, onEndReachedThreshold, initialScrollToRowId, isLoadingPrevious, }: UseInfiniteScrollOptions<T>) => void;
|
|
23
|
+
export declare const useInfiniteScroll: <T extends RowData>({ mode, scrollRef, scrollRoot, table, virtualizerRef, tbodyRef, onStartReached, onStartReachedThreshold, onEndReached, onEndReachedThreshold, initialScrollToRowId, isLoadingPrevious, }: UseInfiniteScrollOptions<T>) => void;
|
|
22
24
|
export {};
|
|
@@ -2,16 +2,18 @@ import { TABLE_END_REACHED_THRESHOLD, TABLE_START_REACHED_THRESHOLD } from "../.
|
|
|
2
2
|
import { useInitialAnchor } from "./useInitialAnchor.js";
|
|
3
3
|
import { usePrependScrollAnchor } from "./usePrependScrollAnchor.js";
|
|
4
4
|
import { useScrollEdge } from "./useScrollEdge.js";
|
|
5
|
-
const useInfiniteScroll = ({ mode, scrollRef, table, virtualizerRef, tbodyRef, onStartReached, onStartReachedThreshold, onEndReached, onEndReachedThreshold, initialScrollToRowId, isLoadingPrevious })=>{
|
|
5
|
+
const useInfiniteScroll = ({ mode, scrollRef, scrollRoot, table, virtualizerRef, tbodyRef, onStartReached, onStartReachedThreshold, onEndReached, onEndReachedThreshold, initialScrollToRowId, isLoadingPrevious })=>{
|
|
6
6
|
const rows = table.getRowModel().rows;
|
|
7
7
|
const ready = useInitialAnchor({
|
|
8
8
|
initialScrollToRowId,
|
|
9
9
|
rows,
|
|
10
|
-
virtualizerRef
|
|
10
|
+
virtualizerRef,
|
|
11
|
+
enabled: 'window' !== mode || null != scrollRoot
|
|
11
12
|
});
|
|
12
13
|
usePrependScrollAnchor({
|
|
13
14
|
mode,
|
|
14
15
|
scrollRef,
|
|
16
|
+
scrollRoot,
|
|
15
17
|
rows,
|
|
16
18
|
virtualizerRef,
|
|
17
19
|
tbodyRef,
|
|
@@ -21,6 +23,7 @@ const useInfiniteScroll = ({ mode, scrollRef, table, virtualizerRef, tbodyRef, o
|
|
|
21
23
|
edge: 'start',
|
|
22
24
|
mode,
|
|
23
25
|
scrollRef,
|
|
26
|
+
scrollRoot,
|
|
24
27
|
onReached: onStartReached,
|
|
25
28
|
threshold: onStartReachedThreshold ?? TABLE_START_REACHED_THRESHOLD,
|
|
26
29
|
enabled: ready
|
|
@@ -29,6 +32,7 @@ const useInfiniteScroll = ({ mode, scrollRef, table, virtualizerRef, tbodyRef, o
|
|
|
29
32
|
edge: 'end',
|
|
30
33
|
mode,
|
|
31
34
|
scrollRef,
|
|
35
|
+
scrollRoot,
|
|
32
36
|
onReached: onEndReached,
|
|
33
37
|
threshold: onEndReachedThreshold ?? TABLE_END_REACHED_THRESHOLD,
|
|
34
38
|
enabled: ready
|
|
@@ -6,11 +6,17 @@ interface UseInitialAnchorOptions {
|
|
|
6
6
|
id: string;
|
|
7
7
|
}[];
|
|
8
8
|
virtualizerRef: RefObject<TableVirtualizerInstance | null>;
|
|
9
|
+
/**
|
|
10
|
+
* When false, holds the scroll. `window` mode waits for its scroll root to
|
|
11
|
+
* settle: in a pane host the root is still the window at mount, and an
|
|
12
|
+
* anchor scrolled there never reaches the pane.
|
|
13
|
+
*/
|
|
14
|
+
enabled?: boolean;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Scrolls to the anchor row once on mount and returns `ready`, which gates the
|
|
12
18
|
* edge detectors until the initial scroll has settled. Without this, a table
|
|
13
19
|
* mounted at scrollTop 0 would fire `onStartReached` immediately.
|
|
14
20
|
*/
|
|
15
|
-
export declare const useInitialAnchor: ({ initialScrollToRowId, rows, virtualizerRef, }: UseInitialAnchorOptions) => boolean;
|
|
21
|
+
export declare const useInitialAnchor: ({ initialScrollToRowId, rows, virtualizerRef, enabled, }: UseInitialAnchorOptions) => boolean;
|
|
16
22
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
const useInitialAnchor = ({ initialScrollToRowId, rows, virtualizerRef })=>{
|
|
2
|
+
const useInitialAnchor = ({ initialScrollToRowId, rows, virtualizerRef, enabled = true })=>{
|
|
3
3
|
const [ready, setReady] = useState(!initialScrollToRowId);
|
|
4
4
|
const doneRef = useRef(false);
|
|
5
5
|
useEffect(()=>{
|
|
6
|
-
if (doneRef.current || !initialScrollToRowId) return;
|
|
6
|
+
if (doneRef.current || !initialScrollToRowId || !enabled) return;
|
|
7
7
|
const virtualizer = virtualizerRef.current;
|
|
8
8
|
if (!virtualizer) {
|
|
9
9
|
doneRef.current = true;
|
|
@@ -21,7 +21,8 @@ const useInitialAnchor = ({ initialScrollToRowId, rows, virtualizerRef })=>{
|
|
|
21
21
|
}, [
|
|
22
22
|
initialScrollToRowId,
|
|
23
23
|
rows,
|
|
24
|
-
virtualizerRef
|
|
24
|
+
virtualizerRef,
|
|
25
|
+
enabled
|
|
25
26
|
]);
|
|
26
27
|
return ready;
|
|
27
28
|
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { type RefObject } from 'react';
|
|
2
|
+
import { type ScrollRoot } from '../../lib';
|
|
2
3
|
import type { TableVirtualizerInstance } from '../../TableContext/types';
|
|
3
4
|
interface UsePrependScrollAnchorOptions {
|
|
4
5
|
mode: 'container' | 'window';
|
|
5
6
|
scrollRef?: RefObject<HTMLElement | null>;
|
|
7
|
+
/** `window` mode: the resolved scroll root (see `useWindowScrollRoot`) */
|
|
8
|
+
scrollRoot?: ScrollRoot | null;
|
|
6
9
|
rows: {
|
|
7
10
|
id: string;
|
|
8
11
|
}[];
|
|
@@ -31,5 +34,5 @@ interface UsePrependScrollAnchorOptions {
|
|
|
31
34
|
* commit (hence no dep array) and its collapse joins the delta when the prepend
|
|
32
35
|
* lands in the same commit.
|
|
33
36
|
*/
|
|
34
|
-
export declare const usePrependScrollAnchor: ({ mode, scrollRef, rows, virtualizerRef, tbodyRef, isLoadingPrevious, }: UsePrependScrollAnchorOptions) => void;
|
|
37
|
+
export declare const usePrependScrollAnchor: ({ mode, scrollRef, scrollRoot, rows, virtualizerRef, tbodyRef, isLoadingPrevious, }: UsePrependScrollAnchorOptions) => void;
|
|
35
38
|
export {};
|