@plexui/ui 0.20.7 → 0.20.9
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/es/components/DateRangePicker/Calendar.js +18 -19
- package/dist/es/components/DateRangePicker/Calendar.js.map +1 -1
- package/dist/es/components/DateRangePicker/DateRangePicker.js +3 -1
- package/dist/es/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/es/components/DateRangePicker/context.js.map +1 -1
- package/dist/es/components/DateRangePicker/index.js.map +1 -1
- package/dist/es/components/DateRangePicker/types.js.map +1 -1
- package/dist/es/components/Dialog/Dialog.js +8 -2
- package/dist/es/components/Dialog/Dialog.js.map +1 -1
- package/dist/es/components/Field/Field.js +6 -3
- package/dist/es/components/Field/Field.js.map +1 -1
- package/dist/es/components/InputGroup/InputGroup.js +1 -1
- package/dist/es/components/InputGroup/InputGroup.js.map +1 -1
- package/dist/es/components/Menu/Menu.js +8 -3
- package/dist/es/components/Menu/Menu.js.map +1 -1
- package/dist/es/components/Popover/Popover.js +16 -8
- package/dist/es/components/Popover/Popover.js.map +1 -1
- package/dist/es/components/Select/Select.js +18 -10
- package/dist/es/components/Select/Select.js.map +1 -1
- package/dist/es/components/SelectControl/SelectControl.js +6 -5
- package/dist/es/components/SelectControl/SelectControl.js.map +1 -1
- package/dist/es/components/Transition/TransitionGroup.js +7 -6
- package/dist/es/components/Transition/TransitionGroup.js.map +1 -1
- package/dist/es/components/Transition/shared.js +30 -0
- package/dist/es/components/Transition/shared.js.map +1 -1
- package/dist/es/lib/dateUtils.js +5 -0
- package/dist/es/lib/dateUtils.js.map +1 -1
- package/dist/es/lib/helpers.js +30 -0
- package/dist/es/lib/helpers.js.map +1 -1
- package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +6 -1
- package/dist/types/components/DateRangePicker/context.d.ts +2 -1
- package/dist/types/components/DateRangePicker/index.d.ts +1 -1
- package/dist/types/components/DateRangePicker/types.d.ts +2 -0
- package/dist/types/components/Field/Field.d.ts +4 -2
- package/dist/types/components/Popover/Popover.d.ts +2 -0
- package/dist/types/components/Select/Select.d.ts +5 -0
- package/dist/types/components/SelectControl/SelectControl.d.ts +7 -1
- package/dist/types/components/Transition/TransitionGroup.d.ts +5 -0
- package/dist/types/components/Transition/shared.d.ts +23 -0
- package/dist/types/lib/dateUtils.d.ts +5 -0
- package/dist/types/lib/helpers.d.ts +14 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { DateTime, Interval } from "luxon";
|
|
|
4
4
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { useBreakpoint } from "../../hooks/useBreakpoints.js";
|
|
6
6
|
import { useStableCallback } from "../../hooks/useStableCallback.js";
|
|
7
|
-
import { chunkIntoWeeks, getDaysOfMonth, isAfter, isBefore, isSameDay, isToday, } from "../../lib/dateUtils.js";
|
|
7
|
+
import { chunkIntoWeeks, getDaysOfMonth, isAfter, isBefore, isSameDay, isToday, weekPosition, } from "../../lib/dateUtils.js";
|
|
8
8
|
import { waitForAnimationFrame } from "../../lib/helpers.js";
|
|
9
9
|
import { Button } from "../Button/index.js";
|
|
10
10
|
import { Check, ChevronLeft, ChevronRight } from "../Icon/index.js";
|
|
@@ -12,12 +12,9 @@ import { TransitionGroup } from "../Transition/index.js";
|
|
|
12
12
|
import s from "@plexui/styles/components/DateRangePicker/Calendar.module.css";
|
|
13
13
|
import { useDateRangeContext } from "./context.js";
|
|
14
14
|
import {} from "./types.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
// The day a grid key moves to: a day, a week, the Sunday or Saturday of the
|
|
19
|
-
// week (rows start on Sunday), or a month (Luxon clamps Jan 31 to Feb 28/29)
|
|
20
|
-
const getKeyTarget = (key, day) => {
|
|
15
|
+
// The day a grid key moves to: a day, a week, the first or last day of the
|
|
16
|
+
// week row, or a month (Luxon clamps Jan 31 to Feb 28/29)
|
|
17
|
+
const getKeyTarget = (key, day, weekStartsOn) => {
|
|
21
18
|
switch (key) {
|
|
22
19
|
case "ArrowLeft":
|
|
23
20
|
return day.minus({ days: 1 });
|
|
@@ -28,9 +25,9 @@ const getKeyTarget = (key, day) => {
|
|
|
28
25
|
case "ArrowDown":
|
|
29
26
|
return day.plus({ days: 7 });
|
|
30
27
|
case "Home":
|
|
31
|
-
return day.minus({ days: day
|
|
28
|
+
return day.minus({ days: weekPosition(day, weekStartsOn) });
|
|
32
29
|
case "End":
|
|
33
|
-
return day.plus({ days: 6 - (day
|
|
30
|
+
return day.plus({ days: 6 - weekPosition(day, weekStartsOn) });
|
|
34
31
|
case "PageUp":
|
|
35
32
|
return day.minus({ months: 1 });
|
|
36
33
|
case "PageDown":
|
|
@@ -41,7 +38,7 @@ const getKeyTarget = (key, day) => {
|
|
|
41
38
|
};
|
|
42
39
|
const monthIndex = (date) => date.year * 12 + date.month;
|
|
43
40
|
export const DateRangeCalendar = () => {
|
|
44
|
-
const { value, min, max, maxRangeDays, onChangeRef } = useDateRangeContext();
|
|
41
|
+
const { value, min, max, maxRangeDays, weekStartsOn, onChangeRef } = useDateRangeContext();
|
|
45
42
|
const isSmallUp = useBreakpoint("sm");
|
|
46
43
|
const calendarContainerRef = useRef(null);
|
|
47
44
|
// The day to focus once a key has moved the view to its month
|
|
@@ -129,7 +126,7 @@ export const DateRangeCalendar = () => {
|
|
|
129
126
|
}
|
|
130
127
|
// While a move waits for its month to render, the next key starts from
|
|
131
128
|
// the day it is moving to (key repeat), not the day that still has focus
|
|
132
|
-
const target = getKeyTarget(event.key, pendingFocusRef.current ?? day);
|
|
129
|
+
const target = getKeyTarget(event.key, pendingFocusRef.current ?? day, weekStartsOn);
|
|
133
130
|
if (!target) {
|
|
134
131
|
return;
|
|
135
132
|
}
|
|
@@ -235,7 +232,7 @@ export const DateRangeCalendar = () => {
|
|
|
235
232
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-run this hook when the months change
|
|
236
233
|
}, [leftCalendarDate]);
|
|
237
234
|
return (_jsx("div", { className: s.CalendarWrapper, children: _jsxs("div", { ref: calendarContainerRef, className: s.CalendarContainer, onMouseLeave: handleCalendarMouseLeave, children: [_jsx("div", { className: s.Previous, children: _jsx(Button, { variant: "ghost", color: "secondary", size: "sm", pill: false, gutterSize: "2xs", iconSize: "sm", onClick: handlePrevious, disabled: !canGoBack, "aria-label": "Previous month", children: _jsx(ChevronLeft, {}) }) }), _jsx("div", { className: s.Next, children: _jsx(Button, { variant: "ghost", color: "secondary", size: "sm", pill: false, gutterSize: "2xs", iconSize: "sm", onClick: handleNext, disabled: !canGoForward, "aria-label": "Next month", children: _jsx(ChevronRight, {}) }) }), _jsx("div", { className: s.CalendarRange, style: {
|
|
238
|
-
transform: `translate(${calendarSteps * -1 *
|
|
235
|
+
transform: `translate(calc(${calendarSteps * -1} * var(--calendar-step)), 0)`,
|
|
239
236
|
}, children: _jsxs(TransitionGroup, { enterDuration: 400, exitDuration: 400, children: [_jsx(CalendarView, { stepPosition: calendarSteps, date: leftCalendarDate, selectedDates: selectedDisplayValue, min: min, max: max, selectionStart: selectionRange?.[0], maxRangeDays: maxRangeDays, isSelecting: !!selectionRange, onDateSelect: handleDateSelect, onDateMouseEnter: handleDateMouseEnter, onDayKeyDown: handleDayKeyDown }, leftCalendarDate.toLocaleString({
|
|
240
237
|
month: "long",
|
|
241
238
|
year: "numeric",
|
|
@@ -246,12 +243,13 @@ export const DateRangeCalendar = () => {
|
|
|
246
243
|
};
|
|
247
244
|
const daysOfTheWeekLabels = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
248
245
|
const CalendarView = ({ date, selectedDates, min, max, selectionStart, maxRangeDays, isSelecting, onDateSelect, onDateMouseEnter, onDayKeyDown, stepPosition, }) => {
|
|
246
|
+
const { weekStartsOn } = useDateRangeContext();
|
|
249
247
|
// Lock position on mount and don't respond to changes
|
|
250
248
|
const [position] = useState(stepPosition);
|
|
251
249
|
const { startOfMonth, weeks, enabledInterval } = useMemo(() => {
|
|
252
250
|
const monthStart = date.startOf("month");
|
|
253
251
|
const endOfMonth = date.endOf("month");
|
|
254
|
-
const daysBeforeMonthStart = monthStart
|
|
252
|
+
const daysBeforeMonthStart = weekPosition(monthStart, weekStartsOn);
|
|
255
253
|
const blankDays = new Array(daysBeforeMonthStart).fill(null);
|
|
256
254
|
const daysInMonth = getDaysOfMonth(monthStart);
|
|
257
255
|
const calendarCells = [...blankDays, ...daysInMonth];
|
|
@@ -264,7 +262,8 @@ const CalendarView = ({ date, selectedDates, min, max, selectionStart, maxRangeD
|
|
|
264
262
|
weeks: chunkIntoWeeks(calendarCells, 7),
|
|
265
263
|
enabledInterval: enabledDateInterval,
|
|
266
264
|
};
|
|
267
|
-
}, [date, min, max]);
|
|
265
|
+
}, [date, min, max, weekStartsOn]);
|
|
266
|
+
const dayLabels = [...daysOfTheWeekLabels.slice(weekStartsOn), ...daysOfTheWeekLabels.slice(0, weekStartsOn)];
|
|
268
267
|
const [selectedStart, selectedEnd] = selectedDates || [];
|
|
269
268
|
const rangeEndLimit = selectionStart && maxRangeDays != null
|
|
270
269
|
? selectionStart.plus({ days: maxRangeDays - 1 })
|
|
@@ -275,7 +274,7 @@ const CalendarView = ({ date, selectedDates, min, max, selectionStart, maxRangeD
|
|
|
275
274
|
}
|
|
276
275
|
return Interval.fromDateTimes(selectedStart.startOf("day"), selectedEnd.endOf("day"));
|
|
277
276
|
}, [selectedStart, selectedEnd]);
|
|
278
|
-
return (_jsxs("div", { className: s.Calendar, style: { left: position *
|
|
277
|
+
return (_jsxs("div", { className: s.Calendar, style: { left: `calc(${position} * var(--calendar-step))` }, "data-calendar": true, children: [_jsxs("p", { className: s.MonthLabel, children: [startOfMonth.monthLong, " ", startOfMonth.year] }), _jsx("div", { className: s.Week, children: dayLabels.map((day) => (_jsx("div", { className: s.DayLabel, children: day }, day))) }), weeks.map((week, weekIndex) => (_jsx("div", { className: s.Week, children: week.map((d, dayIndex) => {
|
|
279
278
|
if (!d) {
|
|
280
279
|
return _jsx("div", { className: s.Day }, `${weekIndex}-${dayIndex}`);
|
|
281
280
|
}
|
|
@@ -288,13 +287,13 @@ const CalendarView = ({ date, selectedDates, min, max, selectionStart, maxRangeD
|
|
|
288
287
|
const isInRange = hasRange && selectedInterval?.contains(d);
|
|
289
288
|
const dayIsToday = isToday(d);
|
|
290
289
|
const isFirstRangeTrail = d.day === 1 &&
|
|
291
|
-
// Trail doesn't make sense to display at the start of the week
|
|
292
|
-
d
|
|
290
|
+
// Trail doesn't make sense to display at the start of the week
|
|
291
|
+
weekPosition(d, weekStartsOn) !== 0 &&
|
|
293
292
|
isInRange &&
|
|
294
293
|
!isStart;
|
|
295
294
|
const isLastRangeTrail = d.day === d.daysInMonth &&
|
|
296
|
-
// Trail doesn't make sense to display at the end of the week
|
|
297
|
-
d
|
|
295
|
+
// Trail doesn't make sense to display at the end of the week
|
|
296
|
+
weekPosition(d, weekStartsOn) !== 6 &&
|
|
298
297
|
isInRange &&
|
|
299
298
|
!isEnd;
|
|
300
299
|
return (_jsx("div", { className: s.Day, "data-is-start": isStart ? "" : undefined, "data-is-end": isEnd ? "" : undefined, "data-is-in-range": isInRange ? "" : undefined, "data-is-first-range-trail": isFirstRangeTrail ? "" : undefined, "data-is-last-range-trail": isLastRangeTrail ? "" : undefined, children: _jsxs("button", { className: s.InteractiveDay, disabled: !enabled, "aria-label": d.toLocaleString(DateTime.DATE_HUGE), "aria-pressed": !!(isStart || isEnd || isInRange), "aria-current": dayIsToday ? "date" : undefined, onClick: () => d && onDateSelect?.(d), onMouseEnter: () => d && onDateMouseEnter?.(d), onKeyDown: (event) => d && onDayKeyDown?.(event, d), children: [d.day, dayIsToday && _jsx("span", { className: s.TodayDot })] }) }, dayIndex));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Calendar.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/Calendar.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport { DateTime, Interval } from \"luxon\"\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent } from \"react\"\nimport { useBreakpoint } from \"../../hooks/useBreakpoints\"\nimport { useStableCallback } from \"../../hooks/useStableCallback\"\nimport {\n chunkIntoWeeks,\n getDaysOfMonth,\n isAfter,\n isBefore,\n isSameDay,\n isToday,\n} from \"../../lib/dateUtils\"\nimport { waitForAnimationFrame } from \"../../lib/helpers\"\nimport { Button } from \"../Button\"\nimport { Check, ChevronLeft, ChevronRight } from \"../Icon\"\nimport { TransitionGroup } from \"../Transition\"\nimport s from \"@plexui/styles/components/DateRangePicker/Calendar.module.css\"\nimport { useDateRangeContext } from \"./context\"\nimport { type DateRange, type DateRangeShortcut } from \"./types\"\n\nconst CALENDAR_WIDTH_PX = 210\nconst CALENDAR_GAP_PX = 32\nconst STEP_DISTANCE_PX = CALENDAR_WIDTH_PX + CALENDAR_GAP_PX\n\n// The day a grid key moves to: a day, a week, the Sunday or Saturday of the\n// week (rows start on Sunday), or a month (Luxon clamps Jan 31 to Feb 28/29)\nconst getKeyTarget = (key: string, day: DateTime): DateTime | null => {\n switch (key) {\n case \"ArrowLeft\":\n return day.minus({ days: 1 })\n case \"ArrowRight\":\n return day.plus({ days: 1 })\n case \"ArrowUp\":\n return day.minus({ days: 7 })\n case \"ArrowDown\":\n return day.plus({ days: 7 })\n case \"Home\":\n return day.minus({ days: day.weekday % 7 })\n case \"End\":\n return day.plus({ days: 6 - (day.weekday % 7) })\n case \"PageUp\":\n return day.minus({ months: 1 })\n case \"PageDown\":\n return day.plus({ months: 1 })\n default:\n return null\n }\n}\n\nconst monthIndex = (date: DateTime) => date.year * 12 + date.month\n\nexport const DateRangeCalendar = () => {\n const { value, min, max, maxRangeDays, onChangeRef } = useDateRangeContext()\n const isSmallUp = useBreakpoint(\"sm\")\n const calendarContainerRef = useRef<HTMLDivElement | null>(null)\n // The day to focus once a key has moved the view to its month\n const pendingFocusRef = useRef<DateTime | null>(null)\n const [selectionRange, setSelectionRange] = useState<DateRange | null>(null)\n const [calendarSteps, setCalendarSteps] = useState<number>(0)\n const [forceRenderIncrement, setForceRenderIncrement] = useState<number>(0)\n const [leftCalendarDate, setLeftCalendarDate] = useState<DateTime>(() =>\n isSmallUp\n ? getLeftCalendarDate(value?.[0] ?? DateTime.now(), max)\n : value?.[0] ?? DateTime.now(),\n )\n\n const rightCalendarDate = isSmallUp\n ? leftCalendarDate.plus({ months: 1 }).startOf(\"month\")\n : leftCalendarDate.startOf(\"month\")\n\n const canGoBack = !min || isBefore(min, leftCalendarDate.startOf(\"month\"))\n const canGoForward = !max || isBefore(rightCalendarDate.endOf(\"month\"), max)\n\n const handleNext = () => {\n setCalendarSteps((c) => c + 1)\n setLeftCalendarDate((dt) => dt.plus({ months: 1 }))\n }\n\n const handlePrevious = () => {\n setCalendarSteps((c) => c - 1)\n setLeftCalendarDate((dt) => dt.minus({ months: 1 }))\n }\n\n const handleDateSelect = (selectedDate: DateTime) => {\n if (!selectionRange) {\n setSelectionRange([selectedDate, selectedDate])\n return\n }\n\n const [currentSelectionStartDate] = selectionRange\n\n // Selecting a date before the current selected start date moves the start date\n // but does not resolve the selection\n if (isBefore(selectedDate, currentSelectionStartDate)) {\n setSelectionRange([selectedDate, selectedDate])\n return\n }\n\n // Resolve the selection by emitting the value and clearing selection\n onChangeRef.current([currentSelectionStartDate, selectedDate])\n setSelectionRange(null)\n }\n\n const handleDateMouseEnter = (hoveredDate: DateTime) => {\n // If we're not actively selecting, no-op\n if (!selectionRange) {\n return\n }\n\n setSelectionRange((currentSelectionRange) => {\n // impossible due to the check above\n if (!currentSelectionRange) {\n return currentSelectionRange\n }\n\n const [currentStartDate] = currentSelectionRange\n\n // When hovering a date before the current date, don't change the selection range\n if (isBefore(hoveredDate, currentStartDate)) {\n return [currentStartDate, currentStartDate]\n }\n\n return [currentStartDate, hoveredDate]\n })\n }\n\n const handleCalendarMouseLeave = () => {\n // If we're not actively selecting, no-op\n if (!selectionRange) {\n return\n }\n\n setSelectionRange((currentSelectionRange) => {\n if (!currentSelectionRange) {\n return currentSelectionRange\n }\n\n // Reset the end selection\n const [currentStartDate] = currentSelectionRange\n return [currentStartDate, currentStartDate]\n })\n }\n\n // Days are named by their full date; skip calendars that are leaving\n const focusDay = (day: DateTime) => {\n const label = day.toLocaleString(DateTime.DATE_HUGE)\n const buttons = calendarContainerRef.current?.querySelectorAll<HTMLButtonElement>(\n `button[aria-label=\"${label}\"]`,\n )\n Array.from(buttons ?? [])\n .find((button) => !button.closest(\"[data-exiting]\"))\n ?.focus()\n }\n\n // A calendar that is leaving keeps the props it last rendered with, so its\n // days reach the current state through a stable callback\n const handleDayKeyDown = useStableCallback((event: KeyboardEvent, day: DateTime) => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return\n }\n\n // While a move waits for its month to render, the next key starts from\n // the day it is moving to (key repeat), not the day that still has focus\n const target = getKeyTarget(event.key, pendingFocusRef.current ?? day)\n if (!target) {\n return\n }\n\n event.preventDefault()\n\n // A disabled day (outside min/max, or past maxRangeDays while selecting)\n // keeps focus where it is\n const rangeEndLimit =\n selectionRange && maxRangeDays != null\n ? selectionRange[0].plus({ days: maxRangeDays - 1 })\n : undefined\n if (\n (min && isBefore(target, min.startOf(\"day\"))) ||\n (max && isAfter(target, max.endOf(\"day\"))) ||\n (rangeEndLimit && isAfter(target, rangeEndLimit))\n ) {\n return\n }\n\n const monthsBefore = monthIndex(leftCalendarDate) - monthIndex(target)\n const monthsAfter = monthIndex(target) - monthIndex(rightCalendarDate)\n if (monthsBefore <= 0 && monthsAfter <= 0) {\n pendingFocusRef.current = null\n focusDay(target)\n return\n }\n\n // Step the view like the month buttons; a day within min/max keeps every step in bounds\n if (monthsAfter > 0 ? !canGoForward : !canGoBack) {\n return\n }\n\n pendingFocusRef.current = target\n for (let step = 0; step < Math.max(monthsBefore, monthsAfter); step++) {\n if (monthsAfter > 0) {\n handleNext()\n } else {\n handlePrevious()\n }\n }\n })\n\n const selectedDisplayValue = selectionRange || value\n\n // Force re-renders when `value` changes out of brand from direct user-selection\n useEffect(() => {\n // When a new value is received, it could be out of band from the control of this calendar.\n // For example, a shortcut could be selected, or clear could be pressed. In either case, selection\n // should be reset so that the new `value` can be displayed fully.\n setSelectionRange(null)\n\n // Nothing else to do when value is empty\n if (!value) {\n return\n }\n\n // Check if `value` is still within view of our calendar\n const viewInterval = Interval.fromDateTimes(\n leftCalendarDate.startOf(\"month\"),\n rightCalendarDate.endOf(\"month\"),\n )\n const isValueInRangeOfCalendar =\n viewInterval.contains(value[0]) || viewInterval.contains(value[1])\n if (!isValueInRangeOfCalendar) {\n // Reset state the calendar view entirely\n setSelectionRange(null)\n setCalendarSteps(0)\n setLeftCalendarDate(isSmallUp ? getLeftCalendarDate(value[0], max) : value[0])\n setForceRenderIncrement((c) => c + 1)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-run this hook when value changes\n }, [value])\n\n // Detect height changes when new calendars are rendered\n useEffect(() => {\n waitForAnimationFrame(() => {\n const container = calendarContainerRef.current\n\n if (!container) {\n return\n }\n\n let maxHeight = -Infinity\n\n // Find the tallest calendar\n container.querySelectorAll(\"[data-calendar]\")?.forEach((element) => {\n // NOTE: clientHeight does not respect the scale() that popover uses to animate in, which is what we want\n // We want to know the full height of the element, without any transform applied.\n const height = element.clientHeight\n\n // Ignore calendars that are exiting\n if (element.closest(\"[data-exiting]\")) {\n return\n }\n\n if (height > maxHeight) {\n maxHeight = height\n }\n })\n\n container.style.height = `${maxHeight}px`\n\n // Don't animate the initial height.\n // This is relevant when the calendar opens to a larger size than the default.\n if (!container.style.transition) {\n waitForAnimationFrame(() => {\n container.style.transition = `height 0.25s var(--cubic-move)`\n })\n }\n })\n }, [leftCalendarDate])\n\n // Focus a pending day once its month has rendered. New calendars mount\n // after this render (TransitionGroup), so wait a frame like the height does\n useEffect(() => {\n if (!pendingFocusRef.current) {\n return\n }\n\n return waitForAnimationFrame(() => {\n const target = pendingFocusRef.current\n pendingFocusRef.current = null\n if (target) {\n focusDay(target)\n }\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-run this hook when the months change\n }, [leftCalendarDate])\n\n return (\n <div className={s.CalendarWrapper} key={`stable-view-${forceRenderIncrement}`}>\n <div\n ref={calendarContainerRef}\n className={s.CalendarContainer}\n onMouseLeave={handleCalendarMouseLeave}\n >\n <div className={s.Previous}>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n size=\"sm\"\n pill={false}\n gutterSize=\"2xs\"\n iconSize=\"sm\"\n onClick={handlePrevious}\n disabled={!canGoBack}\n aria-label=\"Previous month\"\n >\n <ChevronLeft />\n </Button>\n </div>\n <div className={s.Next}>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n size=\"sm\"\n pill={false}\n gutterSize=\"2xs\"\n iconSize=\"sm\"\n onClick={handleNext}\n disabled={!canGoForward}\n aria-label=\"Next month\"\n >\n <ChevronRight />\n </Button>\n </div>\n <div\n className={s.CalendarRange}\n style={{\n transform: `translate(${calendarSteps * -1 * STEP_DISTANCE_PX}px, 0)`,\n }}\n >\n <TransitionGroup enterDuration={400} exitDuration={400}>\n <CalendarView\n key={leftCalendarDate.toLocaleString({\n month: \"long\",\n year: \"numeric\",\n })}\n stepPosition={calendarSteps}\n date={leftCalendarDate}\n selectedDates={selectedDisplayValue}\n min={min}\n max={max}\n selectionStart={selectionRange?.[0]}\n maxRangeDays={maxRangeDays}\n isSelecting={!!selectionRange}\n onDateSelect={handleDateSelect}\n onDateMouseEnter={handleDateMouseEnter}\n onDayKeyDown={handleDayKeyDown}\n />\n {isSmallUp && (\n <CalendarView\n key={rightCalendarDate.toLocaleString({\n month: \"long\",\n year: \"numeric\",\n })}\n stepPosition={calendarSteps + 1}\n date={rightCalendarDate}\n selectedDates={selectedDisplayValue}\n min={min}\n max={max}\n selectionStart={selectionRange?.[0]}\n maxRangeDays={maxRangeDays}\n isSelecting={!!selectionRange}\n onDateSelect={handleDateSelect}\n onDateMouseEnter={handleDateMouseEnter}\n onDayKeyDown={handleDayKeyDown}\n />\n )}\n </TransitionGroup>\n </div>\n </div>\n </div>\n )\n}\n\ntype CalendarViewProps = {\n // Can be any day within the given month that the calendar should render for\n date: DateTime\n selectedDates?: DateRange | null\n onDateSelect?: (dt: DateTime) => void\n onDateMouseEnter?: (dt: DateTime) => void\n onDayKeyDown?: (event: KeyboardEvent<HTMLButtonElement>, dt: DateTime) => void\n min?: DateTime\n max?: DateTime\n selectionStart?: DateTime | null\n maxRangeDays?: number\n isSelecting?: boolean\n stepPosition: number\n}\n\nconst daysOfTheWeekLabels = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\n\nconst CalendarView = ({\n date,\n selectedDates,\n min,\n max,\n selectionStart,\n maxRangeDays,\n isSelecting,\n onDateSelect,\n onDateMouseEnter,\n onDayKeyDown,\n stepPosition,\n}: CalendarViewProps) => {\n // Lock position on mount and don't respond to changes\n const [position] = useState(stepPosition)\n const { startOfMonth, weeks, enabledInterval } = useMemo(() => {\n const monthStart = date.startOf(\"month\")\n const endOfMonth = date.endOf(\"month\")\n\n const daysBeforeMonthStart = monthStart.weekday % 7\n const blankDays = new Array(daysBeforeMonthStart).fill(null)\n const daysInMonth = getDaysOfMonth(monthStart)\n const calendarCells = [...blankDays, ...daysInMonth]\n\n // Cells are start-of-day values and Interval excludes its end, so widen the\n // bounds to whole days: min/max days themselves stay selectable.\n const enabledDateInterval = Interval.fromDateTimes(\n (min || monthStart).startOf(\"day\"),\n (max || endOfMonth).endOf(\"day\"),\n )\n\n return {\n startOfMonth: monthStart,\n endOfMonth,\n weeks: chunkIntoWeeks(calendarCells, 7),\n enabledInterval: enabledDateInterval,\n }\n }, [date, min, max])\n\n const [selectedStart, selectedEnd] = selectedDates || []\n const rangeEndLimit =\n selectionStart && maxRangeDays != null\n ? selectionStart.plus({ days: maxRangeDays - 1 })\n : undefined\n\n const selectedInterval = useMemo<Interval | null>(() => {\n if (!selectedStart || !selectedEnd) {\n return null\n }\n\n return Interval.fromDateTimes(selectedStart.startOf(\"day\"), selectedEnd.endOf(\"day\"))\n }, [selectedStart, selectedEnd])\n\n return (\n <div className={s.Calendar} style={{ left: position * STEP_DISTANCE_PX }} data-calendar>\n <p className={s.MonthLabel}>\n {startOfMonth.monthLong} {startOfMonth.year}\n </p>\n <div className={s.Week}>\n {daysOfTheWeekLabels.map((day) => (\n <div key={day} className={s.DayLabel}>\n {day}\n </div>\n ))}\n </div>\n {weeks.map((week, weekIndex) => (\n <div className={s.Week} key={weekIndex}>\n {week.map((d, dayIndex) => {\n if (!d) {\n return <div className={s.Day} key={`${weekIndex}-${dayIndex}`} />\n }\n\n // Check if 'day' is within selected range\n const enabled =\n enabledInterval.contains(d) &&\n !(isSelecting && rangeEndLimit && isAfter(d, rangeEndLimit))\n const isStart = enabled && selectedStart && isSameDay(d, selectedStart)\n const isEnd = enabled && selectedEnd && isSameDay(d, selectedEnd)\n const hasRange = selectedStart && selectedEnd && !isSameDay(selectedStart, selectedEnd)\n const isInRange = hasRange && selectedInterval?.contains(d)\n const dayIsToday = isToday(d)\n const isFirstRangeTrail =\n d.day === 1 &&\n // Trail doesn't make sense to display at the start of the week (Monday)\n d.weekday !== 7 &&\n isInRange &&\n !isStart\n const isLastRangeTrail =\n d.day === d.daysInMonth &&\n // Trail doesn't make sense to display at the end of the week (Saturday)\n d.weekday !== 6 &&\n isInRange &&\n !isEnd\n\n return (\n <div\n className={s.Day}\n key={dayIndex}\n data-is-start={isStart ? \"\" : undefined}\n data-is-end={isEnd ? \"\" : undefined}\n data-is-in-range={isInRange ? \"\" : undefined}\n data-is-first-range-trail={isFirstRangeTrail ? \"\" : undefined}\n data-is-last-range-trail={isLastRangeTrail ? \"\" : undefined}\n >\n {/* The full date names the day, which \"15\" alone does not across months */}\n <button\n className={s.InteractiveDay}\n disabled={!enabled}\n aria-label={d.toLocaleString(DateTime.DATE_HUGE)}\n aria-pressed={!!(isStart || isEnd || isInRange)}\n aria-current={dayIsToday ? \"date\" : undefined}\n onClick={() => d && onDateSelect?.(d)}\n onMouseEnter={() => d && onDateMouseEnter?.(d)}\n onKeyDown={(event) => d && onDayKeyDown?.(event, d)}\n >\n {d.day}\n {dayIsToday && <span className={s.TodayDot} />}\n </button>\n </div>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n\nexport const DateRangeShortcuts = ({ shortcuts }: { shortcuts?: DateRangeShortcut[] }) => {\n const isMediumUp = useBreakpoint(\"md\")\n const { value, min, max, maxRangeDays, onChangeRef } = useDateRangeContext()\n\n if (!isMediumUp || !shortcuts?.length) {\n return null\n }\n\n return (\n <div className={s.Shortcuts}>\n {shortcuts.map((shortcut) => {\n const { label, getDateRange } = shortcut\n const range = getDateRange()\n const [start, end] = range\n const isActive = !!value && isSameDay(value[0], start) && isSameDay(value[1], end)\n\n return (\n <Button\n key={label}\n className=\"mb-1\"\n variant=\"ghost\"\n color=\"primary\"\n pill={false}\n size=\"md\"\n iconSize=\"sm\"\n block\n selected={isActive}\n disabled={!isRangeWithinLimits(range, min, max, maxRangeDays)}\n onClick={() => onChangeRef.current(range, shortcut)}\n >\n <span className={s.ButtonText}>{label}</span>\n {isActive && <Check />}\n </Button>\n )\n })}\n </div>\n )\n}\n\n// A shortcut follows the calendar's limits: whole days from min to max, and\n// no more than maxRangeDays days\nconst isRangeWithinLimits = (\n [start, end]: DateRange,\n min?: DateTime,\n max?: DateTime,\n maxRangeDays?: number,\n) =>\n !(min && isBefore(start, min.startOf(\"day\"))) &&\n !(max && isAfter(end, max.endOf(\"day\"))) &&\n !(\n maxRangeDays != null &&\n isAfter(end.startOf(\"day\"), start.startOf(\"day\").plus({ days: maxRangeDays - 1 }))\n )\n\nconst getLeftCalendarDate = (targetDate: DateTime, maxDate?: DateTime) => {\n if (!maxDate) {\n return targetDate\n }\n\n return isBefore(targetDate.endOf(\"month\"), maxDate) ? targetDate : targetDate.minus({ months: 1 })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Calendar.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/Calendar.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport { DateTime, Interval } from \"luxon\"\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent } from \"react\"\nimport { useBreakpoint } from \"../../hooks/useBreakpoints\"\nimport { useStableCallback } from \"../../hooks/useStableCallback\"\nimport {\n chunkIntoWeeks,\n getDaysOfMonth,\n isAfter,\n isBefore,\n isSameDay,\n isToday,\n weekPosition,\n} from \"../../lib/dateUtils\"\nimport { waitForAnimationFrame } from \"../../lib/helpers\"\nimport { Button } from \"../Button\"\nimport { Check, ChevronLeft, ChevronRight } from \"../Icon\"\nimport { TransitionGroup } from \"../Transition\"\nimport s from \"@plexui/styles/components/DateRangePicker/Calendar.module.css\"\nimport { useDateRangeContext } from \"./context\"\nimport { type DateRange, type DateRangeShortcut } from \"./types\"\n\n// The day a grid key moves to: a day, a week, the first or last day of the\n// week row, or a month (Luxon clamps Jan 31 to Feb 28/29)\nconst getKeyTarget = (key: string, day: DateTime, weekStartsOn: number): DateTime | null => {\n switch (key) {\n case \"ArrowLeft\":\n return day.minus({ days: 1 })\n case \"ArrowRight\":\n return day.plus({ days: 1 })\n case \"ArrowUp\":\n return day.minus({ days: 7 })\n case \"ArrowDown\":\n return day.plus({ days: 7 })\n case \"Home\":\n return day.minus({ days: weekPosition(day, weekStartsOn) })\n case \"End\":\n return day.plus({ days: 6 - weekPosition(day, weekStartsOn) })\n case \"PageUp\":\n return day.minus({ months: 1 })\n case \"PageDown\":\n return day.plus({ months: 1 })\n default:\n return null\n }\n}\n\nconst monthIndex = (date: DateTime) => date.year * 12 + date.month\n\nexport const DateRangeCalendar = () => {\n const { value, min, max, maxRangeDays, weekStartsOn, onChangeRef } = useDateRangeContext()\n const isSmallUp = useBreakpoint(\"sm\")\n const calendarContainerRef = useRef<HTMLDivElement | null>(null)\n // The day to focus once a key has moved the view to its month\n const pendingFocusRef = useRef<DateTime | null>(null)\n const [selectionRange, setSelectionRange] = useState<DateRange | null>(null)\n const [calendarSteps, setCalendarSteps] = useState<number>(0)\n const [forceRenderIncrement, setForceRenderIncrement] = useState<number>(0)\n const [leftCalendarDate, setLeftCalendarDate] = useState<DateTime>(() =>\n isSmallUp\n ? getLeftCalendarDate(value?.[0] ?? DateTime.now(), max)\n : value?.[0] ?? DateTime.now(),\n )\n\n const rightCalendarDate = isSmallUp\n ? leftCalendarDate.plus({ months: 1 }).startOf(\"month\")\n : leftCalendarDate.startOf(\"month\")\n\n const canGoBack = !min || isBefore(min, leftCalendarDate.startOf(\"month\"))\n const canGoForward = !max || isBefore(rightCalendarDate.endOf(\"month\"), max)\n\n const handleNext = () => {\n setCalendarSteps((c) => c + 1)\n setLeftCalendarDate((dt) => dt.plus({ months: 1 }))\n }\n\n const handlePrevious = () => {\n setCalendarSteps((c) => c - 1)\n setLeftCalendarDate((dt) => dt.minus({ months: 1 }))\n }\n\n const handleDateSelect = (selectedDate: DateTime) => {\n if (!selectionRange) {\n setSelectionRange([selectedDate, selectedDate])\n return\n }\n\n const [currentSelectionStartDate] = selectionRange\n\n // Selecting a date before the current selected start date moves the start date\n // but does not resolve the selection\n if (isBefore(selectedDate, currentSelectionStartDate)) {\n setSelectionRange([selectedDate, selectedDate])\n return\n }\n\n // Resolve the selection by emitting the value and clearing selection\n onChangeRef.current([currentSelectionStartDate, selectedDate])\n setSelectionRange(null)\n }\n\n const handleDateMouseEnter = (hoveredDate: DateTime) => {\n // If we're not actively selecting, no-op\n if (!selectionRange) {\n return\n }\n\n setSelectionRange((currentSelectionRange) => {\n // impossible due to the check above\n if (!currentSelectionRange) {\n return currentSelectionRange\n }\n\n const [currentStartDate] = currentSelectionRange\n\n // When hovering a date before the current date, don't change the selection range\n if (isBefore(hoveredDate, currentStartDate)) {\n return [currentStartDate, currentStartDate]\n }\n\n return [currentStartDate, hoveredDate]\n })\n }\n\n const handleCalendarMouseLeave = () => {\n // If we're not actively selecting, no-op\n if (!selectionRange) {\n return\n }\n\n setSelectionRange((currentSelectionRange) => {\n if (!currentSelectionRange) {\n return currentSelectionRange\n }\n\n // Reset the end selection\n const [currentStartDate] = currentSelectionRange\n return [currentStartDate, currentStartDate]\n })\n }\n\n // Days are named by their full date; skip calendars that are leaving\n const focusDay = (day: DateTime) => {\n const label = day.toLocaleString(DateTime.DATE_HUGE)\n const buttons = calendarContainerRef.current?.querySelectorAll<HTMLButtonElement>(\n `button[aria-label=\"${label}\"]`,\n )\n Array.from(buttons ?? [])\n .find((button) => !button.closest(\"[data-exiting]\"))\n ?.focus()\n }\n\n // A calendar that is leaving keeps the props it last rendered with, so its\n // days reach the current state through a stable callback\n const handleDayKeyDown = useStableCallback((event: KeyboardEvent, day: DateTime) => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return\n }\n\n // While a move waits for its month to render, the next key starts from\n // the day it is moving to (key repeat), not the day that still has focus\n const target = getKeyTarget(event.key, pendingFocusRef.current ?? day, weekStartsOn)\n if (!target) {\n return\n }\n\n event.preventDefault()\n\n // A disabled day (outside min/max, or past maxRangeDays while selecting)\n // keeps focus where it is\n const rangeEndLimit =\n selectionRange && maxRangeDays != null\n ? selectionRange[0].plus({ days: maxRangeDays - 1 })\n : undefined\n if (\n (min && isBefore(target, min.startOf(\"day\"))) ||\n (max && isAfter(target, max.endOf(\"day\"))) ||\n (rangeEndLimit && isAfter(target, rangeEndLimit))\n ) {\n return\n }\n\n const monthsBefore = monthIndex(leftCalendarDate) - monthIndex(target)\n const monthsAfter = monthIndex(target) - monthIndex(rightCalendarDate)\n if (monthsBefore <= 0 && monthsAfter <= 0) {\n pendingFocusRef.current = null\n focusDay(target)\n return\n }\n\n // Step the view like the month buttons; a day within min/max keeps every step in bounds\n if (monthsAfter > 0 ? !canGoForward : !canGoBack) {\n return\n }\n\n pendingFocusRef.current = target\n for (let step = 0; step < Math.max(monthsBefore, monthsAfter); step++) {\n if (monthsAfter > 0) {\n handleNext()\n } else {\n handlePrevious()\n }\n }\n })\n\n const selectedDisplayValue = selectionRange || value\n\n // Force re-renders when `value` changes out of brand from direct user-selection\n useEffect(() => {\n // When a new value is received, it could be out of band from the control of this calendar.\n // For example, a shortcut could be selected, or clear could be pressed. In either case, selection\n // should be reset so that the new `value` can be displayed fully.\n setSelectionRange(null)\n\n // Nothing else to do when value is empty\n if (!value) {\n return\n }\n\n // Check if `value` is still within view of our calendar\n const viewInterval = Interval.fromDateTimes(\n leftCalendarDate.startOf(\"month\"),\n rightCalendarDate.endOf(\"month\"),\n )\n const isValueInRangeOfCalendar =\n viewInterval.contains(value[0]) || viewInterval.contains(value[1])\n if (!isValueInRangeOfCalendar) {\n // Reset state the calendar view entirely\n setSelectionRange(null)\n setCalendarSteps(0)\n setLeftCalendarDate(isSmallUp ? getLeftCalendarDate(value[0], max) : value[0])\n setForceRenderIncrement((c) => c + 1)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-run this hook when value changes\n }, [value])\n\n // Detect height changes when new calendars are rendered\n useEffect(() => {\n waitForAnimationFrame(() => {\n const container = calendarContainerRef.current\n\n if (!container) {\n return\n }\n\n let maxHeight = -Infinity\n\n // Find the tallest calendar\n container.querySelectorAll(\"[data-calendar]\")?.forEach((element) => {\n // NOTE: clientHeight does not respect the scale() that popover uses to animate in, which is what we want\n // We want to know the full height of the element, without any transform applied.\n const height = element.clientHeight\n\n // Ignore calendars that are exiting\n if (element.closest(\"[data-exiting]\")) {\n return\n }\n\n if (height > maxHeight) {\n maxHeight = height\n }\n })\n\n container.style.height = `${maxHeight}px`\n\n // Don't animate the initial height.\n // This is relevant when the calendar opens to a larger size than the default.\n if (!container.style.transition) {\n waitForAnimationFrame(() => {\n container.style.transition = `height 0.25s var(--cubic-move)`\n })\n }\n })\n }, [leftCalendarDate])\n\n // Focus a pending day once its month has rendered. New calendars mount\n // after this render (TransitionGroup), so wait a frame like the height does\n useEffect(() => {\n if (!pendingFocusRef.current) {\n return\n }\n\n return waitForAnimationFrame(() => {\n const target = pendingFocusRef.current\n pendingFocusRef.current = null\n if (target) {\n focusDay(target)\n }\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-run this hook when the months change\n }, [leftCalendarDate])\n\n return (\n <div className={s.CalendarWrapper} key={`stable-view-${forceRenderIncrement}`}>\n <div\n ref={calendarContainerRef}\n className={s.CalendarContainer}\n onMouseLeave={handleCalendarMouseLeave}\n >\n <div className={s.Previous}>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n size=\"sm\"\n pill={false}\n gutterSize=\"2xs\"\n iconSize=\"sm\"\n onClick={handlePrevious}\n disabled={!canGoBack}\n aria-label=\"Previous month\"\n >\n <ChevronLeft />\n </Button>\n </div>\n <div className={s.Next}>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n size=\"sm\"\n pill={false}\n gutterSize=\"2xs\"\n iconSize=\"sm\"\n onClick={handleNext}\n disabled={!canGoForward}\n aria-label=\"Next month\"\n >\n <ChevronRight />\n </Button>\n </div>\n <div\n className={s.CalendarRange}\n style={{\n transform: `translate(calc(${calendarSteps * -1} * var(--calendar-step)), 0)`,\n }}\n >\n <TransitionGroup enterDuration={400} exitDuration={400}>\n <CalendarView\n key={leftCalendarDate.toLocaleString({\n month: \"long\",\n year: \"numeric\",\n })}\n stepPosition={calendarSteps}\n date={leftCalendarDate}\n selectedDates={selectedDisplayValue}\n min={min}\n max={max}\n selectionStart={selectionRange?.[0]}\n maxRangeDays={maxRangeDays}\n isSelecting={!!selectionRange}\n onDateSelect={handleDateSelect}\n onDateMouseEnter={handleDateMouseEnter}\n onDayKeyDown={handleDayKeyDown}\n />\n {isSmallUp && (\n <CalendarView\n key={rightCalendarDate.toLocaleString({\n month: \"long\",\n year: \"numeric\",\n })}\n stepPosition={calendarSteps + 1}\n date={rightCalendarDate}\n selectedDates={selectedDisplayValue}\n min={min}\n max={max}\n selectionStart={selectionRange?.[0]}\n maxRangeDays={maxRangeDays}\n isSelecting={!!selectionRange}\n onDateSelect={handleDateSelect}\n onDateMouseEnter={handleDateMouseEnter}\n onDayKeyDown={handleDayKeyDown}\n />\n )}\n </TransitionGroup>\n </div>\n </div>\n </div>\n )\n}\n\ntype CalendarViewProps = {\n // Can be any day within the given month that the calendar should render for\n date: DateTime\n selectedDates?: DateRange | null\n onDateSelect?: (dt: DateTime) => void\n onDateMouseEnter?: (dt: DateTime) => void\n onDayKeyDown?: (event: KeyboardEvent<HTMLButtonElement>, dt: DateTime) => void\n min?: DateTime\n max?: DateTime\n selectionStart?: DateTime | null\n maxRangeDays?: number\n isSelecting?: boolean\n stepPosition: number\n}\n\nconst daysOfTheWeekLabels = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\n\nconst CalendarView = ({\n date,\n selectedDates,\n min,\n max,\n selectionStart,\n maxRangeDays,\n isSelecting,\n onDateSelect,\n onDateMouseEnter,\n onDayKeyDown,\n stepPosition,\n}: CalendarViewProps) => {\n const { weekStartsOn } = useDateRangeContext()\n // Lock position on mount and don't respond to changes\n const [position] = useState(stepPosition)\n const { startOfMonth, weeks, enabledInterval } = useMemo(() => {\n const monthStart = date.startOf(\"month\")\n const endOfMonth = date.endOf(\"month\")\n\n const daysBeforeMonthStart = weekPosition(monthStart, weekStartsOn)\n const blankDays = new Array(daysBeforeMonthStart).fill(null)\n const daysInMonth = getDaysOfMonth(monthStart)\n const calendarCells = [...blankDays, ...daysInMonth]\n\n // Cells are start-of-day values and Interval excludes its end, so widen the\n // bounds to whole days: min/max days themselves stay selectable.\n const enabledDateInterval = Interval.fromDateTimes(\n (min || monthStart).startOf(\"day\"),\n (max || endOfMonth).endOf(\"day\"),\n )\n\n return {\n startOfMonth: monthStart,\n endOfMonth,\n weeks: chunkIntoWeeks(calendarCells, 7),\n enabledInterval: enabledDateInterval,\n }\n }, [date, min, max, weekStartsOn])\n const dayLabels = [...daysOfTheWeekLabels.slice(weekStartsOn), ...daysOfTheWeekLabels.slice(0, weekStartsOn)]\n\n const [selectedStart, selectedEnd] = selectedDates || []\n const rangeEndLimit =\n selectionStart && maxRangeDays != null\n ? selectionStart.plus({ days: maxRangeDays - 1 })\n : undefined\n\n const selectedInterval = useMemo<Interval | null>(() => {\n if (!selectedStart || !selectedEnd) {\n return null\n }\n\n return Interval.fromDateTimes(selectedStart.startOf(\"day\"), selectedEnd.endOf(\"day\"))\n }, [selectedStart, selectedEnd])\n\n return (\n <div className={s.Calendar} style={{ left: `calc(${position} * var(--calendar-step))` }} data-calendar>\n <p className={s.MonthLabel}>\n {startOfMonth.monthLong} {startOfMonth.year}\n </p>\n <div className={s.Week}>\n {dayLabels.map((day) => (\n <div key={day} className={s.DayLabel}>\n {day}\n </div>\n ))}\n </div>\n {weeks.map((week, weekIndex) => (\n <div className={s.Week} key={weekIndex}>\n {week.map((d, dayIndex) => {\n if (!d) {\n return <div className={s.Day} key={`${weekIndex}-${dayIndex}`} />\n }\n\n // Check if 'day' is within selected range\n const enabled =\n enabledInterval.contains(d) &&\n !(isSelecting && rangeEndLimit && isAfter(d, rangeEndLimit))\n const isStart = enabled && selectedStart && isSameDay(d, selectedStart)\n const isEnd = enabled && selectedEnd && isSameDay(d, selectedEnd)\n const hasRange = selectedStart && selectedEnd && !isSameDay(selectedStart, selectedEnd)\n const isInRange = hasRange && selectedInterval?.contains(d)\n const dayIsToday = isToday(d)\n const isFirstRangeTrail =\n d.day === 1 &&\n // Trail doesn't make sense to display at the start of the week\n weekPosition(d, weekStartsOn) !== 0 &&\n isInRange &&\n !isStart\n const isLastRangeTrail =\n d.day === d.daysInMonth &&\n // Trail doesn't make sense to display at the end of the week\n weekPosition(d, weekStartsOn) !== 6 &&\n isInRange &&\n !isEnd\n\n return (\n <div\n className={s.Day}\n key={dayIndex}\n data-is-start={isStart ? \"\" : undefined}\n data-is-end={isEnd ? \"\" : undefined}\n data-is-in-range={isInRange ? \"\" : undefined}\n data-is-first-range-trail={isFirstRangeTrail ? \"\" : undefined}\n data-is-last-range-trail={isLastRangeTrail ? \"\" : undefined}\n >\n {/* The full date names the day, which \"15\" alone does not across months */}\n <button\n className={s.InteractiveDay}\n disabled={!enabled}\n aria-label={d.toLocaleString(DateTime.DATE_HUGE)}\n aria-pressed={!!(isStart || isEnd || isInRange)}\n aria-current={dayIsToday ? \"date\" : undefined}\n onClick={() => d && onDateSelect?.(d)}\n onMouseEnter={() => d && onDateMouseEnter?.(d)}\n onKeyDown={(event) => d && onDayKeyDown?.(event, d)}\n >\n {d.day}\n {dayIsToday && <span className={s.TodayDot} />}\n </button>\n </div>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n\nexport const DateRangeShortcuts = ({ shortcuts }: { shortcuts?: DateRangeShortcut[] }) => {\n const isMediumUp = useBreakpoint(\"md\")\n const { value, min, max, maxRangeDays, onChangeRef } = useDateRangeContext()\n\n if (!isMediumUp || !shortcuts?.length) {\n return null\n }\n\n return (\n <div className={s.Shortcuts}>\n {shortcuts.map((shortcut) => {\n const { label, getDateRange } = shortcut\n const range = getDateRange()\n const [start, end] = range\n const isActive = !!value && isSameDay(value[0], start) && isSameDay(value[1], end)\n\n return (\n <Button\n key={label}\n className=\"mb-1\"\n variant=\"ghost\"\n color=\"primary\"\n pill={false}\n size=\"md\"\n iconSize=\"sm\"\n block\n selected={isActive}\n disabled={!isRangeWithinLimits(range, min, max, maxRangeDays)}\n onClick={() => onChangeRef.current(range, shortcut)}\n >\n <span className={s.ButtonText}>{label}</span>\n {isActive && <Check />}\n </Button>\n )\n })}\n </div>\n )\n}\n\n// A shortcut follows the calendar's limits: whole days from min to max, and\n// no more than maxRangeDays days\nconst isRangeWithinLimits = (\n [start, end]: DateRange,\n min?: DateTime,\n max?: DateTime,\n maxRangeDays?: number,\n) =>\n !(min && isBefore(start, min.startOf(\"day\"))) &&\n !(max && isAfter(end, max.endOf(\"day\"))) &&\n !(\n maxRangeDays != null &&\n isAfter(end.startOf(\"day\"), start.startOf(\"day\").plus({ days: maxRangeDays - 1 }))\n )\n\nconst getLeftCalendarDate = (targetDate: DateTime, maxDate?: DateTime) => {\n if (!maxDate) {\n return targetDate\n }\n\n return isBefore(targetDate.endOf(\"month\"), maxDate) ? targetDate : targetDate.minus({ months: 1 })\n}\n"]}
|
|
@@ -10,7 +10,7 @@ import { DateRangeContext } from "./context.js";
|
|
|
10
10
|
import { DateRangeTrigger } from "./Trigger.js";
|
|
11
11
|
import {} from "./types.js";
|
|
12
12
|
export const DateRangePicker = (props) => {
|
|
13
|
-
const { value, onChange, min, max, maxRangeDays, shortcuts, side = "bottom", sideOffset = 8, align = "center", alignOffset, variant = "outline", size = "md", clearable = false, disabled = false, dropdownIconType, placeholder = "Select date range...", pill = true, block = false, triggerStepperUnit, triggerClassName, triggerShowIcon = true, triggerDateFormat = "MM/dd/yy", } = props;
|
|
13
|
+
const { value, onChange, min, max, maxRangeDays, weekStartsOn = 0, shortcuts, side = "bottom", sideOffset = 8, align = "center", alignOffset, variant = "outline", size = "md", clearable = false, disabled = false, dropdownIconType, placeholder = "Select date range...", pill = true, block = false, triggerStepperUnit, triggerClassName, triggerShowIcon = true, triggerDateFormat = "MM/dd/yy", } = props;
|
|
14
14
|
// min and max are inclusive, so equal bounds allow one date
|
|
15
15
|
if (min && max && isAfter(min, max)) {
|
|
16
16
|
throw new Error("DateRangePicker error: `min` date must not be after the `max` date");
|
|
@@ -22,6 +22,7 @@ export const DateRangePicker = (props) => {
|
|
|
22
22
|
min,
|
|
23
23
|
max,
|
|
24
24
|
maxRangeDays,
|
|
25
|
+
weekStartsOn,
|
|
25
26
|
variant,
|
|
26
27
|
size,
|
|
27
28
|
dropdownIconType,
|
|
@@ -41,6 +42,7 @@ export const DateRangePicker = (props) => {
|
|
|
41
42
|
min,
|
|
42
43
|
max,
|
|
43
44
|
maxRangeDays,
|
|
45
|
+
weekStartsOn,
|
|
44
46
|
variant,
|
|
45
47
|
size,
|
|
46
48
|
dropdownIconType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRangePicker.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/DateRangePicker.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAA4B,MAAM,YAAY,CAAA;AAE9D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAA8B,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"DateRangePicker.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/DateRangePicker.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport { DateTime } from \"luxon\"\nimport { useMemo } from \"react\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { isAfter } from \"../../lib/dateUtils\"\nimport { Popover, type PopoverContentProps } from \"../Popover\"\nimport type { SelectControlProps } from \"../SelectControl\"\nimport { DateRangeCalendar, DateRangeShortcuts } from \"./Calendar\"\nimport { DateRangeContext, type DateRangeContextValue } from \"./context\"\nimport { DateRangeTrigger } from \"./Trigger\"\nimport { type DateRange, type DateRangeShortcut, type WeekStart } from \"./types\"\n\nexport type DateRangePickerProps = {\n /**\n * The selected date range value.\n */\n value: DateRange | null\n /**\n * Handler that is triggered when the date range changes.\n */\n onChange: (nextValue: DateRange | null, shortcut?: DateRangeShortcut) => void\n /**\n * Defines the earliest selectable date (inclusive).\n */\n min?: DateTime\n /**\n * Defines the latest selectable date (inclusive).\n */\n max?: DateTime\n /**\n * Maximum length of the selectable range in days (inclusive).\n * When set, the end date cannot be more than this many days after the start date.\n */\n maxRangeDays?: number\n /**\n * The day each week starts on, from 0 (Sunday) to 6 (Saturday).\n * @default 0\n */\n weekStartsOn?: WeekStart\n /**\n * List of date range shortcuts displayed for quick selection, shown to the left of the calendar.\n */\n shortcuts?: DateRangeShortcut[]\n /**\n * The preferred side of the trigger to render against when open. Will be reversed when collisions occur.\n * @default bottom\n */\n side?: PopoverContentProps[\"side\"]\n /**\n * The distance in pixels from the trigger.\n * @default 8\n */\n sideOffset?: PopoverContentProps[\"sideOffset\"]\n /**\n * The preferred alignment against the trigger. May change when collisions occur.\n * @default center\n */\n align?: PopoverContentProps[\"align\"]\n /**\n * An offset in pixels from the \"start\" or \"end\" alignment options.\n * @default 0\n */\n alignOffset?: PopoverContentProps[\"alignOffset\"]\n\n /**\n * Disables the select visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Placeholder text for the select\n * @default Select date range...\n */\n placeholder?: string\n /**\n * Style variant for the select trigger\n * @default outline\n */\n variant?: SelectControlProps[\"variant\"]\n /**\n * Determines if the select trigger should be a fully rounded pill shape\n * @default true\n */\n pill?: boolean\n /**\n * Determines size of the size and spacing of the control.\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n * @default md\n */\n size?: SelectControlProps[\"size\"]\n /**\n * Icon displayed in the far right of the select trigger\n * @default dropdown\n */\n dropdownIconType?: SelectControlProps[\"dropdownIconType\"]\n /**\n * Custom class applied to the select trigger\n */\n triggerClassName?: string\n /**\n * Display calendar icon at the start of the trigger\n * @default true\n */\n triggerShowIcon?: boolean\n /**\n * Allows the trigger to display as a stepper when the selected date matches the unit.\n * Currently 'month' is the only supported unit.\n */\n triggerStepperUnit?: \"month\"\n /**\n * Format of dates displayed in the trigger\n * @default \"MM/dd/yy\"\n */\n triggerDateFormat?: string\n /**\n * Display a clear action that allows the select to be unset.\n * @default false\n */\n clearable?: boolean\n /**\n * Extends select to 100% of available width.\n * @default false\n */\n block?: boolean\n}\n\nexport const DateRangePicker = (props: DateRangePickerProps) => {\n const {\n value,\n onChange,\n min,\n max,\n maxRangeDays,\n weekStartsOn = 0,\n shortcuts,\n side = \"bottom\",\n sideOffset = 8,\n align = \"center\",\n alignOffset,\n variant = \"outline\",\n size = \"md\",\n clearable = false,\n disabled = false,\n dropdownIconType,\n placeholder = \"Select date range...\",\n pill = true,\n block = false,\n triggerStepperUnit,\n triggerClassName,\n triggerShowIcon = true,\n triggerDateFormat = \"MM/dd/yy\",\n } = props\n\n // min and max are inclusive, so equal bounds allow one date\n if (min && max && isAfter(min, max)) {\n throw new Error(\"DateRangePicker error: `min` date must not be after the `max` date\")\n }\n\n // Create stable, mutable references to avoid memoization requirements from consumers\n const onChangeRef = useLatestValue(onChange)\n\n const store = useMemo<DateRangeContextValue>(\n () => ({\n value,\n min,\n max,\n maxRangeDays,\n weekStartsOn,\n variant,\n size,\n dropdownIconType,\n clearable,\n disabled,\n placeholder,\n block,\n pill,\n shortcuts,\n triggerStepperUnit,\n triggerClassName,\n triggerShowIcon,\n triggerDateFormat,\n onChangeRef,\n }),\n [\n value,\n min,\n max,\n maxRangeDays,\n weekStartsOn,\n variant,\n size,\n dropdownIconType,\n clearable,\n disabled,\n placeholder,\n block,\n pill,\n shortcuts,\n triggerStepperUnit,\n triggerClassName,\n triggerShowIcon,\n triggerDateFormat,\n onChangeRef,\n ],\n )\n\n return (\n <DateRangeContext value={store}>\n <Popover>\n <Popover.Trigger>\n <DateRangeTrigger />\n </Popover.Trigger>\n <Popover.Content\n minWidth={230}\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset ?? (align === \"center\" ? 0 : -5)}\n >\n <div className=\"flex\">\n <DateRangeShortcuts shortcuts={shortcuts} />\n <DateRangeCalendar />\n </div>\n </Popover.Content>\n </Popover>\n </DateRangeContext>\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/context.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/context.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AA6B1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAA;AAEjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAErC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAChF,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA","sourcesContent":["\"use client\"\n\nimport { DateTime } from \"luxon\"\nimport { createContext, use } from \"react\"\nimport type { SelectControlProps } from \"../SelectControl\"\nimport type { DateRange, DateRangeShortcut, WeekStart } from \"./types\"\n\nexport type DateRangeContextValue = {\n value: DateRange | null\n min?: DateTime\n max?: DateTime\n maxRangeDays?: number\n weekStartsOn: WeekStart\n triggerStepperUnit?: \"month\"\n triggerClassName?: string\n triggerShowIcon?: boolean\n triggerDateFormat: string\n disabled: boolean\n variant?: SelectControlProps[\"variant\"]\n pill: boolean\n block: boolean\n size?: SelectControlProps[\"size\"]\n dropdownIconType?: SelectControlProps[\"dropdownIconType\"]\n clearable: boolean\n placeholder: string\n shortcuts?: DateRangeShortcut[]\n // References\n onChangeRef: React.MutableRefObject<\n (nextValue: DateRange | null, shortcut?: DateRangeShortcut) => void\n >\n}\n\nexport const DateRangeContext = createContext<DateRangeContextValue | null>(null)\n\nexport const useDateRangeContext = () => {\n const context = use(DateRangeContext)\n\n if (!context) {\n throw new Error(\"DateRange components must be wrapped in <DateRangePicker />\")\n }\n\n return context\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA6B,MAAM,mBAAmB,CAAA;AAE9E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA6B,MAAM,mBAAmB,CAAA;AAE9E,OAAO,EAA0D,MAAM,SAAS,CAAA","sourcesContent":["export { DateRangePicker, type DateRangePickerProps } from \"./DateRangePicker\"\n\nexport { type DateRange, type DateRangeShortcut, type WeekStart } from \"./types\"\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,OAAO,CAAA","sourcesContent":["import { type DateTime } from \"luxon\"\n\nexport type DateRange = [DateTime, DateTime]\nexport type DateRangeShortcut = {\n label: string\n getDateRange: () => DateRange\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,OAAO,CAAA","sourcesContent":["import { type DateTime } from \"luxon\"\n\nexport type DateRange = [DateTime, DateTime]\n/** The day a week starts on: 0 is Sunday, 6 is Saturday. */\nexport type WeekStart = 0 | 1 | 2 | 3 | 4 | 5 | 6\nexport type DateRangeShortcut = {\n label: string\n getDateRange: () => DateRange\n}\n"]}
|
|
@@ -4,8 +4,9 @@ import clsx from "clsx";
|
|
|
4
4
|
import { Dialog as RadixDialog } from "radix-ui";
|
|
5
5
|
import { createContext, useCallback, useContext, useMemo, useState, } from "react";
|
|
6
6
|
import { useEscCloseStack } from "../../hooks/useEscCloseStack.js";
|
|
7
|
-
import { preventDefaultHandler, toCssVariables } from "../../lib/helpers.js";
|
|
7
|
+
import { keepMovedFocus, preventDefaultHandler, toCssVariables } from "../../lib/helpers.js";
|
|
8
8
|
import { TransitionGroup } from "../Transition/index.js";
|
|
9
|
+
import { createExitGuard, overlayTiming, overlayTimingLarge } from "../Transition/shared.js";
|
|
9
10
|
import s from "@plexui/styles/components/Dialog/Dialog.module.css";
|
|
10
11
|
const DialogContext = createContext(null);
|
|
11
12
|
const useDialogContext = () => {
|
|
@@ -33,10 +34,15 @@ const Trigger = ({ children }) => {
|
|
|
33
34
|
};
|
|
34
35
|
const Content = ({ children, width = 480, showClose = true, pill = false, className, placement = "center", mobilePlacement, onOpenAutoFocus, onCloseAutoFocus, }) => {
|
|
35
36
|
const { open, setOpen } = useDialogContext();
|
|
37
|
+
const [exitGuard] = useState(createExitGuard);
|
|
38
|
+
const crossesScreen = placement === "bottom" || placement === "start" || placement === "end" || mobilePlacement === "bottom";
|
|
36
39
|
useEscCloseStack(open, () => {
|
|
37
40
|
setOpen(false);
|
|
38
41
|
});
|
|
39
|
-
return (_jsx(RadixDialog.Portal, { forceMount: true, children: _jsx(TransitionGroup, {
|
|
42
|
+
return (_jsx(RadixDialog.Portal, { forceMount: true, children: _jsx(TransitionGroup, { ...(crossesScreen ? overlayTimingLarge : overlayTiming), ...exitGuard.transition, className: s.Transition, overlay: true, preventInitialTransition: false, children: open && (_jsxs("div", { children: [_jsx(RadixDialog.Overlay, { className: s.Overlay }), _jsx(RadixDialog.Content, { forceMount: true, className: s.Content, style: toCssVariables({ "dialog-width": width }), "data-placement": placement === "center" ? undefined : placement, "data-mobile-placement": mobilePlacement, "data-pill": pill ? "" : undefined, onEscapeKeyDown: preventDefaultHandler, onInteractOutside: exitGuard.onInteractOutside, onOpenAutoFocus: onOpenAutoFocus, onCloseAutoFocus: (event) => {
|
|
43
|
+
onCloseAutoFocus?.(event);
|
|
44
|
+
keepMovedFocus(event);
|
|
45
|
+
}, children: _jsxs("div", { className: clsx(s.Panel, className), children: [showClose && (_jsx(RadixDialog.Close, { asChild: true, children: _jsx("button", { type: "button", className: s.CloseButton, "aria-label": "Close dialog", children: _jsx("svg", { className: s.CloseIcon, viewBox: "0 0 20 20", width: "20", height: "20", "aria-hidden": "true", children: _jsx("path", { fill: "currentColor", d: "M5.22 5.22a.75.75 0 0 1 1.06 0L10 8.94l3.72-3.72a.75.75 0 1 1 1.06 1.06L11.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06L10 11.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06L8.94 10 5.22 6.28a.75.75 0 0 1 0-1.06" }) }) }) })), children] }) })] }, "dialog")) }) }));
|
|
40
46
|
};
|
|
41
47
|
const Header = ({ children, className }) => {
|
|
42
48
|
return _jsx("div", { className: clsx(s.Header, className), children: children });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.js","sourceRoot":"","sources":["../../../../src/components/Dialog/Dialog.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { Dialog as RadixDialog } from \"radix-ui\"\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\"\nimport { useEscCloseStack } from \"../../hooks/useEscCloseStack\"\nimport { preventDefaultHandler, toCssVariables } from \"../../lib/helpers\"\nimport { TransitionGroup } from \"../Transition\"\nimport s from \"@plexui/styles/components/Dialog/Dialog.module.css\"\n\ntype DialogContextValue = {\n open: boolean\n setOpen: (nextState: boolean) => void\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null)\n\nconst useDialogContext = () => {\n const context = useContext(DialogContext)\n\n if (!context) {\n throw new Error(\"Dialog compound components must be used inside <Dialog>\")\n }\n\n return context\n}\n\nexport type DialogProps = {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: ReactNode\n}\n\nexport const Dialog = ({\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n children,\n}: DialogProps) => {\n const [open, setOpen] = useState<boolean>(false)\n const isOpen = controlledOpen ?? open\n\n const handleOpenChange = useCallback(\n (nextState: boolean) => {\n controlledOnOpenChange?.(nextState)\n setOpen(nextState)\n },\n [controlledOnOpenChange],\n )\n\n const store = useMemo<DialogContextValue>(\n () => ({\n open: isOpen,\n setOpen: handleOpenChange,\n }),\n [isOpen, handleOpenChange],\n )\n\n return (\n <DialogContext value={store}>\n <RadixDialog.Root open={isOpen} onOpenChange={handleOpenChange}>\n {children}\n </RadixDialog.Root>\n </DialogContext>\n )\n}\n\nconst Trigger = ({ children }: { children: ReactNode }) => {\n return <RadixDialog.Trigger asChild>{children}</RadixDialog.Trigger>\n}\n\nexport type DialogPlacement = \"center\" | \"top\" | \"bottom\" | \"start\" | \"end\" | \"fullscreen\"\n\nexport type DialogContentProps = {\n children: ReactNode\n width?: number | string\n showClose?: boolean\n /**\n * Rounder panel and a round close button, for dialogs that sit beside pill controls.\n * @default false\n */\n pill?: boolean\n className?: string\n /**\n * Where the panel sits: centered, near the top (search, command lists),\n * a sheet along the bottom, a full-height panel on the start or end side,\n * or the whole screen.\n * @default center\n */\n placement?: DialogPlacement\n /** Placement at 640px and below, such as a bottom sheet on phones. @default placement */\n mobilePlacement?: Extract<DialogPlacement, \"center\" | \"bottom\" | \"fullscreen\">\n /**\n * Called when focus moves into the dialog on open. Call\n * `event.preventDefault()` to focus something else yourself.\n */\n onOpenAutoFocus?: (event: Event) => void\n /** Called when focus returns on close. Call `event.preventDefault()` to keep it elsewhere. */\n onCloseAutoFocus?: (event: Event) => void\n}\n\nconst Content = ({\n children,\n width = 480,\n showClose = true,\n pill = false,\n className,\n placement = \"center\",\n mobilePlacement,\n onOpenAutoFocus,\n onCloseAutoFocus,\n}: DialogContentProps) => {\n const { open, setOpen } = useDialogContext()\n\n useEscCloseStack(open, () => {\n setOpen(false)\n })\n\n return (\n <RadixDialog.Portal forceMount>\n <TransitionGroup\n enterDuration={250}\n exitDuration={150}\n className={s.Transition}\n disableAnimations\n >\n {open && (\n <div key=\"dialog\">\n <RadixDialog.Overlay className={s.Overlay} />\n <RadixDialog.Content\n forceMount\n className={s.Content}\n style={toCssVariables({ \"dialog-width\": width })}\n data-placement={placement === \"center\" ? undefined : placement}\n data-mobile-placement={mobilePlacement}\n data-pill={pill ? \"\" : undefined}\n onEscapeKeyDown={preventDefaultHandler}\n onOpenAutoFocus={onOpenAutoFocus}\n onCloseAutoFocus={onCloseAutoFocus}\n >\n <div className={clsx(s.Panel, className)}>\n {showClose && (\n <RadixDialog.Close asChild>\n <button type=\"button\" className={s.CloseButton} aria-label=\"Close dialog\">\n <svg\n className={s.CloseIcon}\n viewBox=\"0 0 20 20\"\n width=\"20\"\n height=\"20\"\n aria-hidden=\"true\"\n >\n <path\n fill=\"currentColor\"\n d=\"M5.22 5.22a.75.75 0 0 1 1.06 0L10 8.94l3.72-3.72a.75.75 0 1 1 1.06 1.06L11.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06L10 11.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06L8.94 10 5.22 6.28a.75.75 0 0 1 0-1.06\"\n />\n </svg>\n </button>\n </RadixDialog.Close>\n )}\n {children}\n </div>\n </RadixDialog.Content>\n </div>\n )}\n </TransitionGroup>\n </RadixDialog.Portal>\n )\n}\n\ntype DialogSlotProps = {\n children: ReactNode\n className?: string\n}\n\nconst Header = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Header, className)}>{children}</div>\n}\n\n/** The scrolling part between Header and Footer: with it, only the body scrolls */\nconst Body = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Body, className)}>{children}</div>\n}\n\nconst Footer = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Footer, className)}>{children}</div>\n}\n\nconst Title = ({ children, className }: DialogSlotProps) => {\n return <RadixDialog.Title className={clsx(s.Title, className)}>{children}</RadixDialog.Title>\n}\n\nconst Description = ({ children, className }: DialogSlotProps) => {\n return (\n <RadixDialog.Description className={clsx(s.Description, className)}>\n {children}\n </RadixDialog.Description>\n )\n}\n\nconst Close = ({ children }: { children: ReactNode }) => {\n return <RadixDialog.Close asChild>{children}</RadixDialog.Close>\n}\n\nDialog.Trigger = Trigger\nDialog.Content = Content\nDialog.Header = Header\nDialog.Body = Body\nDialog.Footer = Footer\nDialog.Title = Title\nDialog.Description = Description\nDialog.Close = Close\n"]}
|
|
1
|
+
{"version":3,"file":"Dialog.js","sourceRoot":"","sources":["../../../../src/components/Dialog/Dialog.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { Dialog as RadixDialog } from \"radix-ui\"\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\"\nimport { useEscCloseStack } from \"../../hooks/useEscCloseStack\"\nimport { keepMovedFocus, preventDefaultHandler, toCssVariables } from \"../../lib/helpers\"\nimport { TransitionGroup } from \"../Transition\"\nimport { createExitGuard, overlayTiming, overlayTimingLarge } from \"../Transition/shared\"\nimport s from \"@plexui/styles/components/Dialog/Dialog.module.css\"\n\ntype DialogContextValue = {\n open: boolean\n setOpen: (nextState: boolean) => void\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null)\n\nconst useDialogContext = () => {\n const context = useContext(DialogContext)\n\n if (!context) {\n throw new Error(\"Dialog compound components must be used inside <Dialog>\")\n }\n\n return context\n}\n\nexport type DialogProps = {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: ReactNode\n}\n\nexport const Dialog = ({\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n children,\n}: DialogProps) => {\n const [open, setOpen] = useState<boolean>(false)\n const isOpen = controlledOpen ?? open\n\n const handleOpenChange = useCallback(\n (nextState: boolean) => {\n controlledOnOpenChange?.(nextState)\n setOpen(nextState)\n },\n [controlledOnOpenChange],\n )\n\n const store = useMemo<DialogContextValue>(\n () => ({\n open: isOpen,\n setOpen: handleOpenChange,\n }),\n [isOpen, handleOpenChange],\n )\n\n return (\n <DialogContext value={store}>\n <RadixDialog.Root open={isOpen} onOpenChange={handleOpenChange}>\n {children}\n </RadixDialog.Root>\n </DialogContext>\n )\n}\n\nconst Trigger = ({ children }: { children: ReactNode }) => {\n return <RadixDialog.Trigger asChild>{children}</RadixDialog.Trigger>\n}\n\nexport type DialogPlacement = \"center\" | \"top\" | \"bottom\" | \"start\" | \"end\" | \"fullscreen\"\n\nexport type DialogContentProps = {\n children: ReactNode\n width?: number | string\n showClose?: boolean\n /**\n * Rounder panel and a round close button, for dialogs that sit beside pill controls.\n * @default false\n */\n pill?: boolean\n className?: string\n /**\n * Where the panel sits: centered, near the top (search, command lists),\n * a sheet along the bottom, a full-height panel on the start or end side,\n * or the whole screen.\n * @default center\n */\n placement?: DialogPlacement\n /** Placement at 640px and below, such as a bottom sheet on phones. @default placement */\n mobilePlacement?: Extract<DialogPlacement, \"center\" | \"bottom\" | \"fullscreen\">\n /**\n * Called when focus moves into the dialog on open. Call\n * `event.preventDefault()` to focus something else yourself.\n */\n onOpenAutoFocus?: (event: Event) => void\n /** Called when focus returns on close. Call `event.preventDefault()` to keep it elsewhere. */\n onCloseAutoFocus?: (event: Event) => void\n}\n\nconst Content = ({\n children,\n width = 480,\n showClose = true,\n pill = false,\n className,\n placement = \"center\",\n mobilePlacement,\n onOpenAutoFocus,\n onCloseAutoFocus,\n}: DialogContentProps) => {\n const { open, setOpen } = useDialogContext()\n const [exitGuard] = useState(createExitGuard)\n const crossesScreen =\n placement === \"bottom\" || placement === \"start\" || placement === \"end\" || mobilePlacement === \"bottom\"\n\n useEscCloseStack(open, () => {\n setOpen(false)\n })\n\n return (\n <RadixDialog.Portal forceMount>\n {/* A dialog mounted open enters too, as `open` set with the mount does */}\n <TransitionGroup\n {...(crossesScreen ? overlayTimingLarge : overlayTiming)}\n {...exitGuard.transition}\n className={s.Transition}\n overlay\n preventInitialTransition={false}\n >\n {open && (\n <div key=\"dialog\">\n <RadixDialog.Overlay className={s.Overlay} />\n <RadixDialog.Content\n forceMount\n className={s.Content}\n style={toCssVariables({ \"dialog-width\": width })}\n data-placement={placement === \"center\" ? undefined : placement}\n data-mobile-placement={mobilePlacement}\n data-pill={pill ? \"\" : undefined}\n onEscapeKeyDown={preventDefaultHandler}\n onInteractOutside={exitGuard.onInteractOutside}\n onOpenAutoFocus={onOpenAutoFocus}\n onCloseAutoFocus={(event) => {\n onCloseAutoFocus?.(event)\n keepMovedFocus(event)\n }}\n >\n <div className={clsx(s.Panel, className)}>\n {showClose && (\n <RadixDialog.Close asChild>\n <button type=\"button\" className={s.CloseButton} aria-label=\"Close dialog\">\n <svg\n className={s.CloseIcon}\n viewBox=\"0 0 20 20\"\n width=\"20\"\n height=\"20\"\n aria-hidden=\"true\"\n >\n <path\n fill=\"currentColor\"\n d=\"M5.22 5.22a.75.75 0 0 1 1.06 0L10 8.94l3.72-3.72a.75.75 0 1 1 1.06 1.06L11.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06L10 11.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06L8.94 10 5.22 6.28a.75.75 0 0 1 0-1.06\"\n />\n </svg>\n </button>\n </RadixDialog.Close>\n )}\n {children}\n </div>\n </RadixDialog.Content>\n </div>\n )}\n </TransitionGroup>\n </RadixDialog.Portal>\n )\n}\n\ntype DialogSlotProps = {\n children: ReactNode\n className?: string\n}\n\nconst Header = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Header, className)}>{children}</div>\n}\n\n/** The scrolling part between Header and Footer: with it, only the body scrolls */\nconst Body = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Body, className)}>{children}</div>\n}\n\nconst Footer = ({ children, className }: DialogSlotProps) => {\n return <div className={clsx(s.Footer, className)}>{children}</div>\n}\n\nconst Title = ({ children, className }: DialogSlotProps) => {\n return <RadixDialog.Title className={clsx(s.Title, className)}>{children}</RadixDialog.Title>\n}\n\nconst Description = ({ children, className }: DialogSlotProps) => {\n return (\n <RadixDialog.Description className={clsx(s.Description, className)}>\n {children}\n </RadixDialog.Description>\n )\n}\n\nconst Close = ({ children }: { children: ReactNode }) => {\n return <RadixDialog.Close asChild>{children}</RadixDialog.Close>\n}\n\nDialog.Trigger = Trigger\nDialog.Content = Content\nDialog.Header = Header\nDialog.Body = Body\nDialog.Footer = Footer\nDialog.Title = Title\nDialog.Description = Description\nDialog.Close = Close\n"]}
|
|
@@ -9,8 +9,11 @@ export function Field({ label, description, errorMessage, labelAction, size: siz
|
|
|
9
9
|
const generatedId = useId();
|
|
10
10
|
const fieldId = idProp || `field-${generatedId}`;
|
|
11
11
|
const labelId = `${fieldId}-label`;
|
|
12
|
-
const
|
|
12
|
+
const childProps = isValidElement(children) ? children.props : undefined;
|
|
13
|
+
const childSize = childProps?.size;
|
|
13
14
|
const size = sizeProp ?? (CONTROL_SIZES.has(childSize) ? childSize : "md");
|
|
15
|
+
// The control's id, which the label's `htmlFor` has to match
|
|
16
|
+
const controlId = childProps?.id || fieldId;
|
|
14
17
|
const descriptionId = description ? `${fieldId}-description` : undefined;
|
|
15
18
|
const errorId = errorMessage ? `${fieldId}-error` : undefined;
|
|
16
19
|
// Build aria-describedby from description + error IDs
|
|
@@ -19,7 +22,7 @@ export function Field({ label, description, errorMessage, labelAction, size: siz
|
|
|
19
22
|
// Props to inject into the child control (`aria-labelledby` is added below:
|
|
20
23
|
// to a render prop's props, and to a cloned child without a name of its own)
|
|
21
24
|
const fieldChildProps = {
|
|
22
|
-
id:
|
|
25
|
+
id: controlId,
|
|
23
26
|
"aria-describedby": ariaDescribedBy,
|
|
24
27
|
"aria-invalid": invalid || undefined,
|
|
25
28
|
...(opticallyAlign && { opticallyAlign }),
|
|
@@ -44,7 +47,7 @@ export function Field({ label, description, errorMessage, labelAction, size: siz
|
|
|
44
47
|
else {
|
|
45
48
|
resolvedChildren = children;
|
|
46
49
|
}
|
|
47
|
-
const labelElement = (_jsxs("label", { className: s.Label, id: labelId, htmlFor:
|
|
50
|
+
const labelElement = (_jsxs("label", { className: s.Label, id: labelId, htmlFor: controlId, children: [label, required && (_jsx("span", { className: s.RequiredIndicator, "aria-hidden": "true", children: "*" }))] }));
|
|
48
51
|
return (_jsxs("div", { className: clsx(s.Field, className), "data-size": size, "data-orientation": orientation, "data-optically-align": opticallyAlign, children: [_jsxs("div", { className: s.LabelGroup, children: [labelAction ? (_jsxs("div", { className: s.LabelRow, children: [labelElement, _jsx("div", { className: s.LabelAction, children: labelAction })] })) : (labelElement), description && (_jsx("div", { className: s.Description, id: descriptionId, children: description }))] }), _jsxs("div", { className: s.Content, children: [_jsx("div", { className: s.Control, children: resolvedChildren }), errorMessage && (_jsx(FieldError, { id: errorId, children: errorMessage }))] })] }));
|
|
49
52
|
}
|
|
50
53
|
//# sourceMappingURL=Field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../../src/components/Field/Field.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { cloneElement, isValidElement, useId } from \"react\"\n\nimport type { ControlSize } from \"../../types\"\nimport { FieldError } from \"../FieldError\"\n\nimport s from \"@plexui/styles/components/Field/Field.module.css\"\n\nexport type FieldChildProps = {\n id: string\n /** The label's id. Spread onto a control that the label's `for` cannot name, such as a Select trigger. */\n \"aria-labelledby\"?: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n opticallyAlign?: \"start\" | \"end\"\n}\n\nconst CONTROL_SIZES: ReadonlySet<unknown> = new Set([\"3xs\", \"2xs\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\"])\n\nexport type FieldProps = {\n /**\n * Label text for the field\n */\n label: React.ReactNode\n /**\n * Helper/description text displayed below the label.\n * Automatically linked via aria-describedby.\n */\n description?: React.ReactNode\n /**\n * Error message displayed below the control.\n * When provided, the child control receives aria-invalid=\"true\".\n * Uses the existing FieldError component internally.\n */\n errorMessage?: React.ReactNode\n /**\n * Content placed at the end of the label row, such as a link that acts on\n * the field (\"Forgot password?\", \"Replace\").\n */\n labelAction?: React.ReactNode\n /**\n * Controls the font size of the label to visually match the child control's size.\n * Matches the ControlSize scale used by Input, Select, etc.\n * @default the child control's `size`, else \"md\"\n */\n size?: ControlSize\n /**\n * Display a required indicator (asterisk) after the label.\n * This is purely visual — it does not add the `required` HTML attribute.\n * @default false\n */\n required?: boolean\n /**\n * Layout direction of label and control.\n * - \"vertical\": label stacked above control (default)\n * - \"horizontal\": label beside control\n * @default \"vertical\"\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * Allows overriding the auto-generated `id`. When provided, this becomes\n * the id set on the child control and the `htmlFor` on the label.\n */\n id?: string\n /**\n * Applies a negative margin on the child control using its gutter to\n * optically align the control's text with surrounding content.\n * Passed through to the child control via cloneElement / render prop.\n */\n opticallyAlign?: \"start\" | \"end\"\n /**\n * CSS class applied to the root wrapper\n */\n className?: string\n /**\n * The form control(s) to render.\n * - If a single ReactElement, Field clones it with { id, aria-describedby, aria-invalid }.\n * A child without its own `aria-label`, `aria-labelledby` or `label` also gets\n * `aria-labelledby` pointing at the label, which names controls the label's\n * `for` cannot reach, such as the Select and DatePicker triggers.\n * - If a function (render prop), it is called with { id, \"aria-labelledby\", \"aria-describedby\", \"aria-invalid\" }.\n */\n children: React.ReactElement | ((fieldProps: FieldChildProps) => React.ReactNode)\n}\n\nexport function Field({\n label,\n description,\n errorMessage,\n labelAction,\n size: sizeProp,\n required = false,\n orientation = \"vertical\",\n opticallyAlign,\n id: idProp,\n className,\n children,\n}: FieldProps) {\n const generatedId = useId()\n const fieldId = idProp || `field-${generatedId}`\n const labelId = `${fieldId}-label`\n const childSize = isValidElement<{ size?: unknown }>(children) ? children.props.size : undefined\n const size = sizeProp ?? (CONTROL_SIZES.has(childSize) ? (childSize as ControlSize) : \"md\")\n const descriptionId = description ? `${fieldId}-description` : undefined\n const errorId = errorMessage ? `${fieldId}-error` : undefined\n\n // Build aria-describedby from description + error IDs\n const ariaDescribedBy =\n [descriptionId, errorId].filter(Boolean).join(\" \") || undefined\n\n const invalid = !!errorMessage\n\n // Props to inject into the child control (`aria-labelledby` is added below:\n // to a render prop's props, and to a cloned child without a name of its own)\n const fieldChildProps: FieldChildProps = {\n id: fieldId,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": invalid || undefined,\n ...(opticallyAlign && { opticallyAlign }),\n }\n\n // Resolve the children\n let resolvedChildren: React.ReactNode\n if (typeof children === \"function\") {\n resolvedChildren = children({ ...fieldChildProps, \"aria-labelledby\": labelId })\n } else if (isValidElement(children)) {\n const child = children as React.ReactElement<Record<string, unknown>>\n // Merge with the child's own associations instead of overwriting them\n const childDescribedBy = child.props[\"aria-describedby\"] as string | undefined\n const childNamed =\n child.props[\"aria-label\"] != null || child.props[\"aria-labelledby\"] != null || child.props.label != null\n resolvedChildren = cloneElement(child, {\n ...fieldChildProps,\n \"aria-describedby\":\n [childDescribedBy, ariaDescribedBy].filter(Boolean).join(\" \") || undefined,\n \"aria-invalid\": child.props[\"aria-invalid\"] ?? fieldChildProps[\"aria-invalid\"],\n ...(!childNamed && { \"aria-labelledby\": labelId }),\n })\n } else {\n resolvedChildren = children\n }\n\n const labelElement = (\n <label className={s.Label} id={labelId} htmlFor={fieldId}>\n {label}\n {required && (\n <span className={s.RequiredIndicator} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )\n\n return (\n <div\n className={clsx(s.Field, className)}\n data-size={size}\n data-orientation={orientation}\n data-optically-align={opticallyAlign}\n >\n <div className={s.LabelGroup}>\n {labelAction ? (\n <div className={s.LabelRow}>\n {labelElement}\n <div className={s.LabelAction}>{labelAction}</div>\n </div>\n ) : (\n labelElement\n )}\n {description && (\n <div className={s.Description} id={descriptionId}>\n {description}\n </div>\n )}\n </div>\n <div className={s.Content}>\n <div className={s.Control}>{resolvedChildren}</div>\n {errorMessage && (\n <FieldError id={errorId}>{errorMessage}</FieldError>\n )}\n </div>\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../../src/components/Field/Field.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { cloneElement, isValidElement, useId } from \"react\"\n\nimport type { ControlSize } from \"../../types\"\nimport { FieldError } from \"../FieldError\"\n\nimport s from \"@plexui/styles/components/Field/Field.module.css\"\n\nexport type FieldChildProps = {\n id: string\n /** The label's id. Spread onto a control that the label's `for` cannot name, such as a Select trigger. */\n \"aria-labelledby\"?: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n opticallyAlign?: \"start\" | \"end\"\n}\n\nconst CONTROL_SIZES: ReadonlySet<unknown> = new Set([\"3xs\", \"2xs\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\"])\n\nexport type FieldProps = {\n /**\n * Label text for the field\n */\n label: React.ReactNode\n /**\n * Helper/description text displayed below the label.\n * Automatically linked via aria-describedby.\n */\n description?: React.ReactNode\n /**\n * Error message displayed below the control.\n * When provided, the child control receives aria-invalid=\"true\".\n * Uses the existing FieldError component internally.\n */\n errorMessage?: React.ReactNode\n /**\n * Content placed at the end of the label row, such as a link that acts on\n * the field (\"Forgot password?\", \"Replace\").\n */\n labelAction?: React.ReactNode\n /**\n * Controls the font size of the label to visually match the child control's size.\n * Matches the ControlSize scale used by Input, Select, etc.\n * @default the child control's `size`, else \"md\"\n */\n size?: ControlSize\n /**\n * Display a required indicator (asterisk) after the label.\n * This is purely visual — it does not add the `required` HTML attribute.\n * @default false\n */\n required?: boolean\n /**\n * Layout direction of label and control.\n * - \"vertical\": label stacked above control (default)\n * - \"horizontal\": label beside control\n * @default \"vertical\"\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * Allows overriding the auto-generated `id`. When provided, this becomes\n * the id set on the child control and the `htmlFor` on the label. A child's\n * own `id` wins over both: it stays, and the label's `htmlFor` follows it.\n */\n id?: string\n /**\n * Applies a negative margin on the child control using its gutter to\n * optically align the control's text with surrounding content.\n * Passed through to the child control via cloneElement / render prop.\n */\n opticallyAlign?: \"start\" | \"end\"\n /**\n * CSS class applied to the root wrapper\n */\n className?: string\n /**\n * The form control(s) to render.\n * - If a single ReactElement, Field clones it with { id, aria-describedby, aria-invalid },\n * keeping an `id` the child already has.\n * A child without its own `aria-label`, `aria-labelledby` or `label` also gets\n * `aria-labelledby` pointing at the label, which names controls the label's\n * `for` cannot reach, such as the Select and DatePicker triggers.\n * - If a function (render prop), it is called with { id, \"aria-labelledby\", \"aria-describedby\", \"aria-invalid\" }.\n */\n children: React.ReactElement | ((fieldProps: FieldChildProps) => React.ReactNode)\n}\n\nexport function Field({\n label,\n description,\n errorMessage,\n labelAction,\n size: sizeProp,\n required = false,\n orientation = \"vertical\",\n opticallyAlign,\n id: idProp,\n className,\n children,\n}: FieldProps) {\n const generatedId = useId()\n const fieldId = idProp || `field-${generatedId}`\n const labelId = `${fieldId}-label`\n const childProps = isValidElement<{ size?: unknown; id?: string }>(children) ? children.props : undefined\n const childSize = childProps?.size\n const size = sizeProp ?? (CONTROL_SIZES.has(childSize) ? (childSize as ControlSize) : \"md\")\n // The control's id, which the label's `htmlFor` has to match\n const controlId = childProps?.id || fieldId\n const descriptionId = description ? `${fieldId}-description` : undefined\n const errorId = errorMessage ? `${fieldId}-error` : undefined\n\n // Build aria-describedby from description + error IDs\n const ariaDescribedBy =\n [descriptionId, errorId].filter(Boolean).join(\" \") || undefined\n\n const invalid = !!errorMessage\n\n // Props to inject into the child control (`aria-labelledby` is added below:\n // to a render prop's props, and to a cloned child without a name of its own)\n const fieldChildProps: FieldChildProps = {\n id: controlId,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": invalid || undefined,\n ...(opticallyAlign && { opticallyAlign }),\n }\n\n // Resolve the children\n let resolvedChildren: React.ReactNode\n if (typeof children === \"function\") {\n resolvedChildren = children({ ...fieldChildProps, \"aria-labelledby\": labelId })\n } else if (isValidElement(children)) {\n const child = children as React.ReactElement<Record<string, unknown>>\n // Merge with the child's own associations instead of overwriting them\n const childDescribedBy = child.props[\"aria-describedby\"] as string | undefined\n const childNamed =\n child.props[\"aria-label\"] != null || child.props[\"aria-labelledby\"] != null || child.props.label != null\n resolvedChildren = cloneElement(child, {\n ...fieldChildProps,\n \"aria-describedby\":\n [childDescribedBy, ariaDescribedBy].filter(Boolean).join(\" \") || undefined,\n \"aria-invalid\": child.props[\"aria-invalid\"] ?? fieldChildProps[\"aria-invalid\"],\n ...(!childNamed && { \"aria-labelledby\": labelId }),\n })\n } else {\n resolvedChildren = children\n }\n\n const labelElement = (\n <label className={s.Label} id={labelId} htmlFor={controlId}>\n {label}\n {required && (\n <span className={s.RequiredIndicator} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )\n\n return (\n <div\n className={clsx(s.Field, className)}\n data-size={size}\n data-orientation={orientation}\n data-optically-align={opticallyAlign}\n >\n <div className={s.LabelGroup}>\n {labelAction ? (\n <div className={s.LabelRow}>\n {labelElement}\n <div className={s.LabelAction}>{labelAction}</div>\n </div>\n ) : (\n labelElement\n )}\n {description && (\n <div className={s.Description} id={descriptionId}>\n {description}\n </div>\n )}\n </div>\n <div className={s.Content}>\n <div className={s.Control}>{resolvedChildren}</div>\n {errorMessage && (\n <FieldError id={errorId}>{errorMessage}</FieldError>\n )}\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -35,7 +35,7 @@ const InputGroupRoot = ({ variant = "outline", size = "md", pill = false, disabl
|
|
|
35
35
|
evt.preventDefault();
|
|
36
36
|
control.focus();
|
|
37
37
|
};
|
|
38
|
-
return (_jsx(InputGroupContext.Provider, { value: { size, pill, disabled, invalid }, children: _jsx("div", { ref: ref,
|
|
38
|
+
return (_jsx(InputGroupContext.Provider, { value: { size, pill, disabled, invalid }, children: _jsx("div", { ref: ref, "data-slot": "input-group", "data-variant": variant, "data-size": size, "data-pill": pill ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-invalid": invalid ? "" : undefined, className: clsx(s.InputGroup, className), onMouseDown: handleMouseDown, ...restProps }) }));
|
|
39
39
|
};
|
|
40
40
|
const InputGroupInput = ({ type = "text", disabled, className, ref, ...restProps }) => {
|
|
41
41
|
const group = useContext(InputGroupContext);
|