Add DateRangePicker component with segmented entry and calendar popup
Implements the DateRangePicker design: a DateRangeField that looks like a
single input but splits each date into DD/MM/YYYY part inputs (ordered by
the new common.time.dateformat_hyphenated), and a DateRangeCalendar popup
with a preset column (today, yesterday, last 7/30 days, this/last month,
this year), anchor-style range picking with an outlined/filled/muted range
track, and a Cancel / Clear / Select footer.
Typing fills each part's placeholder from the right (YYYY -> YY19 -> 1987),
auto-advances between parts, and Backspace/Delete reverts the active part.
The committed value lives in hidden ISO {prefix}-min/{prefix}-max inputs --
the same contract as DateRangeFilter, so filter_bar.js needs no changes.
As a tryout, the Purchased filter in PurchaseFilterBar now uses the
DateRangePicker; Refunded keeps the native-date DateRangeFilter, and the
native-path e2e tests were repointed at it.
Includes unit tests for the component family and the filter-bar
integration, plus Playwright e2e tests for segment entry, calendar
picking, presets, and footer actions.
https://claude.ai/code/session_017b75KJAu4kNNpZPu9NAPBM
This commit is contained in:
@@ -918,6 +918,9 @@
|
||||
.ms-2\.5 {
|
||||
margin-inline-start: calc(var(--spacing) * 2.5);
|
||||
}
|
||||
.ms-auto {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
.me-2 {
|
||||
margin-inline-end: calc(var(--spacing) * 2);
|
||||
}
|
||||
@@ -1582,6 +1585,9 @@
|
||||
.w-5\/6 {
|
||||
width: calc(5 / 6 * 100%);
|
||||
}
|
||||
.w-8 {
|
||||
width: calc(var(--spacing) * 8);
|
||||
}
|
||||
.w-10 {
|
||||
width: calc(var(--spacing) * 10);
|
||||
}
|
||||
@@ -1597,6 +1603,12 @@
|
||||
.w-72 {
|
||||
width: calc(var(--spacing) * 72);
|
||||
}
|
||||
.w-\[2\.5ch\] {
|
||||
width: 2.5ch;
|
||||
}
|
||||
.w-\[4\.5ch\] {
|
||||
width: 4.5ch;
|
||||
}
|
||||
.w-\[300px\] {
|
||||
width: 300px;
|
||||
}
|
||||
@@ -1736,6 +1748,9 @@
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.cursor-text {
|
||||
cursor: text;
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
@@ -1787,6 +1802,9 @@
|
||||
.justify-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.gap-0\.5 {
|
||||
gap: calc(var(--spacing) * 0.5);
|
||||
}
|
||||
.gap-1 {
|
||||
gap: calc(var(--spacing) * 1);
|
||||
}
|
||||
@@ -1836,6 +1854,9 @@
|
||||
margin-inline-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
}
|
||||
.gap-y-0\.5 {
|
||||
row-gap: calc(var(--spacing) * 0.5);
|
||||
}
|
||||
.gap-y-4 {
|
||||
row-gap: calc(var(--spacing) * 4);
|
||||
}
|
||||
@@ -1904,6 +1925,9 @@
|
||||
.rounded-xl {
|
||||
border-radius: var(--radius-xl);
|
||||
}
|
||||
.rounded-xs {
|
||||
border-radius: var(--radius-xs);
|
||||
}
|
||||
.rounded-s-base {
|
||||
border-start-start-radius: var(--radius-base);
|
||||
border-end-start-radius: var(--radius-base);
|
||||
@@ -1958,6 +1982,10 @@
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 2px;
|
||||
}
|
||||
.border-y {
|
||||
border-block-style: var(--tw-border-style);
|
||||
border-block-width: 1px;
|
||||
}
|
||||
.border-e {
|
||||
border-inline-end-style: var(--tw-border-style);
|
||||
border-inline-end-width: 1px;
|
||||
@@ -2030,6 +2058,12 @@
|
||||
.border-brand {
|
||||
border-color: var(--color-brand);
|
||||
}
|
||||
.border-brand\/70 {
|
||||
border-color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 70%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
border-color: color-mix(in oklab, var(--color-brand) 70%, transparent);
|
||||
}
|
||||
}
|
||||
.border-default {
|
||||
border-color: var(--color-default);
|
||||
}
|
||||
@@ -2121,12 +2155,24 @@
|
||||
.bg-brand {
|
||||
background-color: var(--color-brand);
|
||||
}
|
||||
.bg-brand\/10 {
|
||||
background-color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 10%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-brand) 10%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-brand\/15 {
|
||||
background-color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 15%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-brand) 15%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-brand\/30 {
|
||||
background-color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 30%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-brand) 30%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-dark-backdrop\/70 {
|
||||
background-color: color-mix(in srgb, oklch(13% 0.028 261.692) 70%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
@@ -2296,6 +2342,9 @@
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
.p-0 {
|
||||
padding: calc(var(--spacing) * 0);
|
||||
}
|
||||
.p-1 {
|
||||
padding: calc(var(--spacing) * 1);
|
||||
}
|
||||
@@ -2320,6 +2369,9 @@
|
||||
.p-6 {
|
||||
padding: calc(var(--spacing) * 6);
|
||||
}
|
||||
.px-0\.5 {
|
||||
padding-inline: calc(var(--spacing) * 0.5);
|
||||
}
|
||||
.px-2 {
|
||||
padding-inline: calc(var(--spacing) * 2);
|
||||
}
|
||||
@@ -2419,6 +2471,9 @@
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
.text-start {
|
||||
text-align: start;
|
||||
}
|
||||
.align-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -2714,9 +2769,15 @@
|
||||
.decoration-dotted {
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
.caret-transparent {
|
||||
caret-color: transparent;
|
||||
}
|
||||
.opacity-0 {
|
||||
opacity: 0%;
|
||||
}
|
||||
.opacity-40 {
|
||||
opacity: 40%;
|
||||
}
|
||||
.opacity-50 {
|
||||
opacity: 50%;
|
||||
}
|
||||
@@ -2752,6 +2813,13 @@
|
||||
--tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.05));
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
}
|
||||
.ring-2 {
|
||||
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
}
|
||||
.ring-brand-strong {
|
||||
--tw-ring-color: var(--color-brand-strong);
|
||||
}
|
||||
.outline {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
@@ -2817,6 +2885,9 @@
|
||||
.\[program\:qcluster\] {
|
||||
program: qcluster;
|
||||
}
|
||||
.ring-inset {
|
||||
--tw-ring-inset: inset;
|
||||
}
|
||||
.group-hover\:absolute {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
@@ -2958,6 +3029,22 @@
|
||||
padding-top: calc(var(--spacing) * 0);
|
||||
}
|
||||
}
|
||||
.focus-within\:border-brand {
|
||||
&:focus-within {
|
||||
border-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
.focus-within\:ring-1 {
|
||||
&:focus-within {
|
||||
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
.focus-within\:ring-brand {
|
||||
&:focus-within {
|
||||
--tw-ring-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
.hover\:scale-110 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
@@ -3223,6 +3310,14 @@
|
||||
border-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
.focus\:bg-brand\/30 {
|
||||
&:focus {
|
||||
background-color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 30%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-brand) 30%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
.focus\:text-blue-700 {
|
||||
&:focus {
|
||||
color: var(--color-blue-700);
|
||||
|
||||
Reference in New Issue
Block a user