Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions package/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"name": "@klinking/colander",
"version": "0.0.0",
"homepage": "https://github.com/klink-ing/colander#readme",
"bugs": "https://github.com/klink-ing/colander/issues",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/klink-ing/colander.git",
"directory": "package"
},
"files": [
"dist",
"src"
Expand Down
17 changes: 17 additions & 0 deletions package/src/calendar-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
type SelectionResult,
} from "./root-selection";
import type {
BaseRootState,
DateRange,
DateValueObject,
RangeMode,
Expand Down Expand Up @@ -582,6 +583,20 @@ function CalendarProvider<F extends ValueFormat = "PlainDate">(
],
);

const baseRootState = useMemo<BaseRootState>(
() => ({
hasSelection: nonNullDates.length > 0,
selected: nonNullDates[0],
selectedDates: nonNullDates,
rangeStart,
rangeEnd,
timeZone,
locale,
readOnly,
}),
[nonNullDates, rangeStart, rangeEnd, timeZone, locale, readOnly],
);

const stateCtx = useMemo<CalendarStateContextValue>(
() => ({
selected,
Expand All @@ -591,6 +606,7 @@ function CalendarProvider<F extends ValueFormat = "PlainDate">(
hoveredDate,
previewStart,
previewEnd,
baseRootState,
}),
[
selected,
Expand All @@ -600,6 +616,7 @@ function CalendarProvider<F extends ValueFormat = "PlainDate">(
hoveredDate,
previewStart,
previewEnd,
baseRootState,
],
);

Expand Down
7 changes: 7 additions & 0 deletions package/src/calendar-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Temporal } from "@js-temporal/polyfill";
import type {
BaseRootState,
DateRange,
DateValueObject,
RangeMode,
Expand Down Expand Up @@ -219,4 +220,10 @@ export interface CalendarStateContextValue {
previewStart: Temporal.PlainDate | undefined;
/** End of the computed preview range. */
previewEnd: Temporal.PlainDate | undefined;
/**
* View-independent part of the render-prop `RootState` (selection + resolved
* config), built once here so MonthView and WeeksView expose identical state.
* Each view adds its own `focused`/`viewing`.
*/
baseRootState: BaseRootState;
}
35 changes: 13 additions & 22 deletions package/src/day-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { MonthViewStableContext } from "./month-view-context";
import { useMonthViewState } from "./month-view-context";
import type { StateAttributesMapping } from "./types";
import type {
ValueFormat,
DayCellTemplateProps,
DayButtonProps,
DayCellTemplateState,
Expand Down Expand Up @@ -244,22 +243,20 @@ export const dayStateAttributesMapping = {
} as const satisfies StateAttributesMapping<DayCellTemplateState>;

/** Props for the memoized DayCellInstance. */
interface DayCellInstanceProps<F extends ValueFormat = ValueFormat> {
render?: DayCellTemplateProps<F>["render"];
interface DayCellInstanceProps {
render?: DayCellTemplateProps["render"];
date: TemporalPoly.PlainDate;
columnIndex?: number | undefined;
children?: React.ReactNode;
_derivedState: DayCellTemplateState & { isTabTarget: boolean };
[key: string]: unknown;
}

function DayCellInstanceFn<F extends ValueFormat = ValueFormat>(
props: DayCellInstanceProps<F>,
) {
function DayCellInstanceFn(props: DayCellInstanceProps) {
const { render, date, columnIndex, children, _derivedState, ...otherProps } =
props;

const state = _derivedState as unknown as DayCellTemplateState<F>;
const state = _derivedState as unknown as DayCellTemplateState;

const defaultProps: Record<string, unknown> = state.hidden
? {
Expand Down Expand Up @@ -348,9 +345,7 @@ const DayCellInstance = memo(
* When used inside a {@link WeekTemplate}, iterates over that week's days.
* An explicit `date` prop renders a single cell.
*/
export function DayCellTemplate<F extends ValueFormat = ValueFormat>(
props: DayCellTemplateProps<F>,
) {
export function DayCellTemplate(props: DayCellTemplateProps) {
const { date: dateProp, ...restProps } = props;
const weekData = useContext(WeekDataContext);

Expand Down Expand Up @@ -457,8 +452,8 @@ export function DayCellTemplate<F extends ValueFormat = ValueFormat>(
}

/** Props for the memoized DayButtonInstance. */
interface DayButtonInnerProps<F extends ValueFormat = ValueFormat> {
render?: DayButtonProps<F>["render"];
interface DayButtonInnerProps {
render?: DayButtonProps["render"];
date: TemporalPoly.PlainDate;
_derivedState?: DayCellTemplateState & { isTabTarget: boolean };
[key: string]: unknown;
Expand Down Expand Up @@ -570,8 +565,8 @@ function dayButtonInnerPropsAreEqual(
const DayButtonInner = memo(
forwardRef(DayButtonInnerFn as any) as any,
dayButtonInnerPropsAreEqual as any,
) as unknown as <F extends ValueFormat = ValueFormat>(
props: DayButtonInnerProps<F> & React.RefAttributes<HTMLButtonElement>,
) as unknown as (
props: DayButtonInnerProps & React.RefAttributes<HTMLButtonElement>,
) => React.ReactElement | null;

/**
Expand Down Expand Up @@ -612,10 +607,8 @@ function DayButtonFn(
);
}

export const DayButton = forwardRef(DayButtonFn) as <
F extends ValueFormat = ValueFormat,
>(
props: DayButtonProps<F> & {
export const DayButton = forwardRef(DayButtonFn) as (
props: DayButtonProps & {
_derivedState?: DayCellTemplateState & { isTabTarget: boolean };
} & React.RefAttributes<HTMLButtonElement>,
) => React.ReactElement | null;
Expand Down Expand Up @@ -681,10 +674,8 @@ function DayButtonFallbackFn(
);
}

const DayButtonFallback = forwardRef(DayButtonFallbackFn) as <
F extends ValueFormat = ValueFormat,
>(
props: Omit<DayButtonProps<F>, "date"> & {
const DayButtonFallback = forwardRef(DayButtonFallbackFn) as (
props: Omit<DayButtonProps, "date"> & {
date: TemporalPoly.PlainDate;
} & React.RefAttributes<HTMLButtonElement>,
) => React.ReactElement | null;
25 changes: 9 additions & 16 deletions package/src/drag-handle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { DayCellDataContext, GridContext } from "./context";
import { useMonthViewState } from "./month-view-context";
import type { StateAttributesMapping } from "./types";
import type {
ValueFormat,
DragHandleState,
RangeStartDragHandleProps,
RangeEndDragHandleProps,
Expand All @@ -21,7 +20,7 @@ const dragHandleStateAttributesMapping = {
orientation: (v) => ({ "data-orientation": v }),
} as const satisfies StateAttributesMapping<DragHandleState>;

function useDragHandle<F extends ValueFormat = ValueFormat>(
function useDragHandle(
edge: "start" | "end",
{ dragging: draggingProp }: { dragging?: boolean | undefined },
) {
Expand All @@ -48,9 +47,9 @@ function useDragHandle<F extends ValueFormat = ValueFormat>(
const isDragging = !!draggingProp && isActive;
const handleRef = useRef<HTMLSpanElement>(null);

const state = useMemo<DragHandleState<F>>(
const state = useMemo<DragHandleState>(
() => ({
root: rootState as any,
root: rootState,
active: isActive,
dragging: isDragging,
edge,
Expand Down Expand Up @@ -108,10 +107,8 @@ function RangeDragHandleFn(
* Drag handle (`<span>`) rendered at a range boundary. Exposes
* `data-active`, `data-dragging`, and `data-edge` attributes.
*/
export const RangeDragHandle = forwardRef(RangeDragHandleFn) as <
F extends ValueFormat = ValueFormat,
>(
props: RangeDragHandleProps<F> & React.RefAttributes<HTMLSpanElement>,
export const RangeDragHandle = forwardRef(RangeDragHandleFn) as (
props: RangeDragHandleProps & React.RefAttributes<HTMLSpanElement>,
) => React.ReactElement | null;

function RangeStartDragHandleFn(
Expand All @@ -122,10 +119,8 @@ function RangeStartDragHandleFn(
}

/** Convenience wrapper for {@link RangeDragHandle} with `edge="start"`. */
export const RangeStartDragHandle = forwardRef(RangeStartDragHandleFn) as <
F extends ValueFormat = ValueFormat,
>(
props: RangeStartDragHandleProps<F> & React.RefAttributes<HTMLSpanElement>,
export const RangeStartDragHandle = forwardRef(RangeStartDragHandleFn) as (
props: RangeStartDragHandleProps & React.RefAttributes<HTMLSpanElement>,
) => React.ReactElement | null;

function RangeEndDragHandleFn(
Expand All @@ -136,8 +131,6 @@ function RangeEndDragHandleFn(
}

/** Convenience wrapper for {@link RangeDragHandle} with `edge="end"`. */
export const RangeEndDragHandle = forwardRef(RangeEndDragHandleFn) as <
F extends ValueFormat = ValueFormat,
>(
props: RangeEndDragHandleProps<F> & React.RefAttributes<HTMLSpanElement>,
export const RangeEndDragHandle = forwardRef(RangeEndDragHandleFn) as (
props: RangeEndDragHandleProps & React.RefAttributes<HTMLSpanElement>,
) => React.ReactElement | null;
Loading
Loading