diff --git a/components/filter/demo/filter.html b/components/filter/demo/filter.html
index 8ab259eedac..0a08371af56 100644
--- a/components/filter/demo/filter.html
+++ b/components/filter/demo/filter.html
@@ -11,9 +11,13 @@
import '../../filter/filter-dimension-set-empty-state.js';
import '../../filter/filter-dimension-set-value.js';
import '../../filter/filter-dimension-set-date-text-value.js';
+ import '../../filter/filter-dimension-set-date-time-range-value.js';
import './filter-search-demo.js';
import './filter-load-more-demo.js';
+
@@ -162,11 +166,12 @@
Date Filter
-
-
+
+
-
+
+
diff --git a/components/filter/filter-dimension-set-date-time-range-value.js b/components/filter/filter-dimension-set-date-time-range-value.js
new file mode 100644
index 00000000000..3e41933240d
--- /dev/null
+++ b/components/filter/filter-dimension-set-date-time-range-value.js
@@ -0,0 +1,134 @@
+import '../inputs/input-date-time-range.js';
+import { html, LitElement } from 'lit';
+import { ifDefined } from 'lit/directives/if-defined.js';
+import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
+
+/**
+ * A component to represent a possible custom date range or date-time range value that can be selected for a dimension set (the main filter dimension type).
+ * The start-value and end-value will be included in the d2l-filter-change event and formatted as an ISO string in UTC time.
+ * This component does not render anything, but instead gathers data needed for the d2l-filter.
+ */
+class FilterDimensionSetDateTimeRangeValue extends LocalizeCoreElement(LitElement) {
+
+ static get properties() {
+ return {
+ /**
+ * Whether this value in the filter is disabled or not
+ * @type {boolean}
+ */
+ disabled: { type: Boolean, reflect: true },
+ /**
+ * @ignore
+ */
+ endValue: { type: String, attribute: 'end-value' },
+ /**
+ * REQUIRED: Unique key to represent this value in the dimension
+ * @type {string}
+ */
+ key: { type: String },
+ /**
+ * Whether this value in the filter is selected or not
+ * @type {boolean}
+ */
+ selected: { type: Boolean, reflect: true },
+ /**
+ * @ignore
+ */
+ startValue: { type: String, attribute: 'start-value' },
+ /**
+ * Defaults to "Custom Date Range" (localized). Can be overridden if desired.
+ * @type {string}
+ */
+ text: { type: String, reflect: true }
+ };
+ }
+
+ constructor() {
+ super();
+ this.disabled = false;
+ this.selected = false;
+ this._dispatchFilterChangeEvent = false;
+ this._enforceSingleSelection = true;
+ this._filterSetValue = true;
+ this._minWidth = 375;
+ this._noSearchSupport = true;
+
+ this._handleDateChange = this._handleDateChange.bind(this);
+ }
+
+ firstUpdated(changedProperties) {
+ super.firstUpdated(changedProperties);
+
+ this.text = this.text || this.localize('components.filter-dimension-set-date-time-range-value.text');
+ }
+
+ updated(changedProperties) {
+ super.updated(changedProperties);
+
+ const changes = new Map();
+ let shouldDispatchChangeEvent = false;
+ changedProperties.forEach((oldValue, prop) => {
+ if (oldValue === undefined && (prop === 'selected' || prop === 'disabled')) return;
+ if (this._dispatchFilterChangeEvent && (prop === 'startValue' || prop === 'endValue')) shouldDispatchChangeEvent = true;
+
+ if (prop === 'disabled' || prop === 'selected' || prop === 'startValue' || prop === 'endValue' || prop === 'text') {
+ changes.set(prop, this[prop]);
+ }
+ });
+ if (changes.size > 0) {
+ /** @ignore */
+ this.dispatchEvent(new CustomEvent('d2l-filter-dimension-set-value-data-change', {
+ detail: { valueKey: this.key, changes: changes, dispatchChangeEvent: shouldDispatchChangeEvent },
+ bubbles: true,
+ composed: false
+ }));
+ this._dispatchFilterChangeEvent = false;
+ }
+ }
+
+ getValueDetails() {
+ return {
+ disabled: this.disabled,
+ key: this.key,
+ selected: this.selected,
+ text: this.text,
+ additionalContent: this._getAdditionalContent.bind(this),
+ getAdditionalEventDetails: this._getAdditionalEventDetails.bind(this),
+ clearProperties: this._clearProperties.bind(this)
+ };
+ }
+
+ _clearProperties() {
+ this.startValue = undefined;
+ this.endValue = undefined;
+ }
+
+ _getAdditionalContent() {
+ return html`
+
+ `;
+ }
+
+ _getAdditionalEventDetails(selected) {
+ if (!selected) return {};
+ return { startValue: this.startValue, endValue: this.endValue };
+ }
+
+ async _handleDateChange(e) {
+ this.startValue = e.target.startValue;
+ this.endValue = e.target.endValue;
+
+ this._dispatchFilterChangeEvent = true;
+ }
+}
+
+customElements.define('d2l-filter-dimension-set-date-time-range-value', FilterDimensionSetDateTimeRangeValue);
diff --git a/components/filter/filter-dimension-set.js b/components/filter/filter-dimension-set.js
index 8e4de968745..af9c56219ca 100644
--- a/components/filter/filter-dimension-set.js
+++ b/components/filter/filter-dimension-set.js
@@ -36,6 +36,10 @@ class FilterDimensionSet extends LitElement {
* @type {boolean}
*/
loading: { type: Boolean },
+ /**
+ * @ignore
+ */
+ minWidth: { type: Number },
/**
* Whether to hide the search input, perform a simple text search, or fire an event on search
* @type {'none'|'automatic'|'manual'}
@@ -138,14 +142,17 @@ class FilterDimensionSet extends LitElement {
const valueNodes = this._getSlottedNodes();
let noSearchSupport = false;
let enforceSingleSelection = false;
+ let minWidth = undefined;
const values = valueNodes.map(value => {
if (value._noSearchSupport) noSearchSupport = true;
if (value._enforceSingleSelection) enforceSingleSelection = true;
+ if (value._minWidth) minWidth = value._minWidth;
return value.getValueDetails();
});
if (noSearchSupport) this.searchType = 'none';
if (enforceSingleSelection) this.selectionSingle = true;
+ if (minWidth) this.minWidth = minWidth;
return values;
}
@@ -182,7 +189,7 @@ class FilterDimensionSet extends LitElement {
_handleDimensionSetValueDataChange(e) {
e.stopPropagation();
- this._dispatchDataChangeEvent({ dimensionKey: this.key, valueKey: e.detail.valueKey, changes: e.detail.changes });
+ this._dispatchDataChangeEvent({ dimensionKey: this.key, valueKey: e.detail.valueKey, changes: e.detail.changes, dispatchChangeEvent: e.detail.dispatchChangeEvent });
}
_handleSearchEmptyStateSlotChange(e) {
diff --git a/components/filter/filter.js b/components/filter/filter.js
index 734ad6df720..5e01e2b6a2c 100644
--- a/components/filter/filter.js
+++ b/components/filter/filter.js
@@ -34,6 +34,7 @@ import { SubscriberRegistryController } from '../../controllers/subscriber/subsc
const ARROWLEFT_KEY_CODE = 37;
const ESCAPE_KEY_CODE = 27;
+const FILTER_CONTENT_CLASS = 'd2l-filter-dropdown-content';
const SET_DIMENSION_ID_PREFIX = 'list-';
/**
@@ -67,6 +68,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
text: { type: String },
_activeDimensionKey: { type: String, attribute: false },
_dimensions: { type: Array, attribute: false },
+ _minWidth: { type: Number, attribute: false },
_totalAppliedCount: { type: Number, attribute: false }
};
}
@@ -144,8 +146,8 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
flex-shrink: 0;
}
d2l-expand-collapse-content[expanded] {
+ margin-inline-start: -2rem;
padding-block: 0.5rem;
- padding-inline: 0.2rem;
}
.d2l-filter-dimension-set-value-text {
@@ -206,6 +208,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
this.opened = false;
this._changeEventsToDispatch = new Map();
this._dimensions = [];
+ this._minWidth = 285;
this._openedDimensions = [];
this._totalAppliedCount = 0;
@@ -244,27 +247,29 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
const dropdownContent = singleDimension ? html`
${header}
${dimensions}
`
: html`
${header}
@@ -289,7 +294,8 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
@d2l-dropdown-open="${this._handleDropdownOpen}"
@d2l-dropdown-position="${this._stopPropagation}"
class="vdiff-target"
- ?disabled="${this.disabled}">
+ ?disabled="${this.disabled}"
+ prefer-fixed-positioning>
`;
+const singleSetDimensionDateTimeRangeFixture = html`
+
+
+
+
+
+ `;
const singleSetDimensionSingleSelectionFixture = html`
@@ -539,6 +547,77 @@ describe('d2l-filter', () => {
clock.restore();
});
+ it('single set date-time range dimension fires change events', async() => {
+ const elem = await fixture(singleSetDimensionDateTimeRangeFixture);
+ const selectedElem = elem.querySelector('d2l-filter-dimension-set-date-time-range-value[selected]');
+ expect(selectedElem.startValue).to.equal(undefined);
+ expect(selectedElem.endValue).to.equal(undefined);
+ expect(elem._dimensions[0].values[0].selected).to.be.true;
+ expect(elem._dimensions[0].values[1].selected).to.be.false;
+
+ // set startValue and wait for event
+ const dateTimeRange = elem.shadowRoot.querySelector('d2l-input-date-time-range');
+ dateTimeRange.startValue = '2019-02-12T20:00:00.000Z';
+ dateTimeRange.dispatchEvent(new CustomEvent(
+ 'change', {
+ bubbles: true,
+ composed: false
+ }
+ ));
+
+ let e = await oneEvent(elem, 'd2l-filter-change');
+ let dimensions = e.detail.dimensions;
+ expect(dimensions.length).to.equal(1);
+ expect(dimensions[0].dimensionKey).to.equal('dim');
+ expect(dimensions[0].cleared).to.be.false;
+ let changes = dimensions[0].changes;
+ expect(changes.length).to.equal(1);
+ expect(changes[0].valueKey).to.equal('1');
+ expect(changes[0].selected).to.be.true;
+ expect(changes[0].startValue).to.equal('2019-02-12T20:00:00.000Z');
+
+ // select other item
+ const secondElem = elem.shadowRoot.querySelector('d2l-list-item[key="2"]');
+ setTimeout(() => secondElem.setSelected(true));
+ e = await oneEvent(elem, 'd2l-filter-change');
+ expect(e.detail.allCleared).to.be.false;
+ dimensions = e.detail.dimensions;
+ expect(dimensions.length).to.equal(1);
+ expect(dimensions[0].dimensionKey).to.equal('dim');
+ expect(dimensions[0].cleared).to.be.false;
+ changes = dimensions[0].changes;
+ expect(changes.length).to.equal(2);
+ expect(changes[0].valueKey).to.equal('2');
+ expect(changes[0].selected).to.be.true;
+ expect(elem._dimensions[0].values[1].selected).to.be.true;
+ expect(changes[1].valueKey).to.equal('1');
+ expect(changes[1].selected).to.be.false;
+ expect(changes[1].startValue).to.be.undefined;
+ expect(changes[1].endValue).to.be.undefined;
+ expect(elem._dimensions[0].values[0].selected).to.be.false;
+
+ // re-select first item, make sure start-value is maintained
+ const firstElem = elem.shadowRoot.querySelector('d2l-list-item[key="1"]');
+ setTimeout(() => firstElem.setSelected(true));
+ e = await oneEvent(elem, 'd2l-filter-change');
+ expect(e.detail.allCleared).to.be.false;
+ dimensions = e.detail.dimensions;
+ expect(dimensions.length).to.equal(1);
+ expect(dimensions[0].dimensionKey).to.equal('dim');
+ expect(dimensions[0].cleared).to.be.false;
+ changes = dimensions[0].changes;
+ expect(changes.length).to.equal(2);
+ expect(changes[0].valueKey).to.equal('1');
+ expect(changes[0].selected).to.be.true;
+ expect(changes[0].startValue).to.equal('2019-02-12T20:00:00.000Z');
+ expect(elem._dimensions[0].values[0].selected).to.be.true;
+ expect(changes[1].valueKey).to.equal('2');
+ expect(changes[1].selected).to.be.false;
+ expect(changes[1].startValue).to.be.undefined;
+ expect(changes[1].endValue).to.be.undefined;
+ expect(elem._dimensions[0].values[1].selected).to.be.false;
+ });
+
it('single set dimension with selection-single on fires change events', async() => {
const elem = await fixture(singleSetDimensionSingleSelectionFixture);
const value = elem.shadowRoot.querySelector('d2l-list-item[key="2"]');
diff --git a/components/filter/test/filter.vdiff.js b/components/filter/test/filter.vdiff.js
index 98f9bd8b1d2..73f1c5368e2 100644
--- a/components/filter/test/filter.vdiff.js
+++ b/components/filter/test/filter.vdiff.js
@@ -2,6 +2,7 @@ import '../filter.js';
import '../filter-dimension-set.js';
import '../filter-dimension-set-empty-state.js';
import '../filter-dimension-set-date-text-value.js';
+import '../filter-dimension-set-date-time-range-value.js';
import '../filter-dimension-set-value.js';
import { clickElem, expect, fixture, hoverAt, html, nextFrame, oneEvent, sendKeysElem, waitUntil } from '@brightspace-ui/testing';
import { ifDefined } from 'lit/directives/if-defined.js';
@@ -87,6 +88,23 @@ function createSingleDimDate() {
`;
}
+function createSingleDimDateCustom(opts) {
+ const { long, customSelected, longCustomSelected, opened, startValue } = { long: false, customSelected: false, longCustomSelected: false, opened: false, ...opts };
+ return html`
+
+
+
+
+
+
+
+
+
+ ${ long ? html`` : nothing }
+
+
+ `;
+}
function createEmptyMultipleDims(opts) {
const { long, text } = { long: false, ...opts };
@@ -138,6 +156,10 @@ describe('filter', () => {
{ name: 'multi-selection-all-selected', template: createSingleDim({ selected: true, selectAll: true }) },
{ name: 'multi-selection-clamping', template: createSingleDim({ selected: true, selectAll: true, clampingValues: true }) },
{ name: 'dates', template: createSingleDimDate() },
+ { name: 'dates-long', template: createSingleDimDateCustom({ long: true }) },
+ { name: 'dates-custom-selected', template: createSingleDimDateCustom({ customSelected: true }) },
+ { name: 'dates-custom-selected-start-value', template: createSingleDimDateCustom({ customSelected: true, startValue: '2018-02-12T05:00:00.000Z' }) },
+ { name: 'dates-long-custom-selected', template: createSingleDimDateCustom({ long: true, longCustomSelected: true }) },
].forEach(({ name, template }) => {
it(`${rtl ? 'rtl-' : ''}${name}`, async() => {
const elem = await fixture(template, { rtl, viewport: { height: 1500 } });
@@ -208,22 +230,46 @@ describe('filter', () => {
});
});
- it('press-clear-dates', async() => {
- const elem = await fixture(html`
-
-
-
-
-
-
-
-
-
- `);
+ describe('dates', () => {
+ it('press-clear-dates', async() => {
+ const elem = await fixture(html`
+
+
+
+
+
+
+
+
+
+ `);
- await clickElem(elem.shadowRoot.querySelector('d2l-button-subtle'));
- await hoverAt(0, 0);
- await expect(elem).to.be.golden();
+ await clickElem(elem.shadowRoot.querySelector('[text="Clear"]'));
+ await hoverAt(0, 0);
+ await expect(elem).to.be.golden();
+ });
+
+ it('press-clear-dates-custom-date-selected', async() => {
+ const elem = await fixture(createSingleDimDateCustom({ customSelected: true, startValue: '2018-02-12T05:00:00.000Z', opened: true }));
+
+ await clickElem(elem.shadowRoot.querySelector('[text="Clear"]'));
+ await hoverAt(0, 0);
+ await expect(elem).to.be.golden();
+ });
+
+ it('select-other-option-then-custom-again', async() => {
+ const elem = await fixture(createSingleDimDateCustom({ customSelected: true, startValue: '2018-02-12T05:00:00.000Z', opened: true }));
+ await clickElem(elem.shadowRoot.querySelector('d2l-list-item'));
+ await clickElem(elem.shadowRoot.querySelector('d2l-list-item[label="Custom date range"]'));
+ await hoverAt(0, 0);
+ await expect(elem).to.be.golden();
+ });
+
+ it('open custom date input', async() => {
+ const elem = await fixture(createSingleDimDateCustom({ customSelected: true, startValue: '2018-02-12T05:00:00.000Z', opened: true }));
+ elem.shadowRoot.querySelector('d2l-list-item[label="Custom date range"]').querySelector('d2l-input-date-time-range').setAttribute('start-opened', 'start-opened');
+ await expect(elem).to.be.golden();
+ });
});
});
@@ -278,8 +324,15 @@ describe('filter', () => {
-
-
+
+
+
+
+
+
+
+
+
`;
@@ -289,6 +342,7 @@ describe('filter', () => {
{ name: 'empty', template: createEmptyMultipleDims({ long: true }) },
{ name: 'dates', template: multipleDimsDate },
{ name: 'nested-dates', template: multipleDimsDate, dim: 2 },
+ { name: 'nested-dates-custom', template: multipleDimsDate, dim: 3 },
{ name: 'selected', template: multipleDims },
...[{ dim: 1, height: 439 }, { dim: 2, height: 151 }, { dim: 3, height: 79 }].map(({ dim, height }) =>
({ name: `nested-dim-${dim}`, dim, height, template: multipleDims })
diff --git a/components/filter/test/golden/filter/chromium/multiple-dates.png b/components/filter/test/golden/filter/chromium/multiple-dates.png
index 2a9e5d80dc3..691cbc46692 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-dates.png and b/components/filter/test/golden/filter/chromium/multiple-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-mobile-dates.png b/components/filter/test/golden/filter/chromium/multiple-mobile-dates.png
index 1dc59b0ee33..8a30856957a 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-mobile-dates.png and b/components/filter/test/golden/filter/chromium/multiple-mobile-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates-custom.png b/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates-custom.png
new file mode 100644
index 00000000000..6c8143dc2ac
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates-custom.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates.png b/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates.png
index 28e27fa2195..0870a2cb3c5 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates.png and b/components/filter/test/golden/filter/chromium/multiple-mobile-nested-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-nested-dates-custom.png b/components/filter/test/golden/filter/chromium/multiple-nested-dates-custom.png
new file mode 100644
index 00000000000..ec33c46241b
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/multiple-nested-dates-custom.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-nested-dates.png b/components/filter/test/golden/filter/chromium/multiple-nested-dates.png
index f0192628bee..cb918cc1f76 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-nested-dates.png and b/components/filter/test/golden/filter/chromium/multiple-nested-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-rtl-dates.png b/components/filter/test/golden/filter/chromium/multiple-rtl-dates.png
index 569e01412f2..065e3266a12 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-rtl-dates.png and b/components/filter/test/golden/filter/chromium/multiple-rtl-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-dates.png b/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-dates.png
index 110c86093e2..0fd1aff94d1 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-dates.png and b/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-nested-dates-custom.png b/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-nested-dates-custom.png
new file mode 100644
index 00000000000..3b08d8c23f1
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/multiple-rtl-mobile-nested-dates-custom.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates-custom.png b/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates-custom.png
new file mode 100644
index 00000000000..a3de735e053
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates-custom.png differ
diff --git a/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates.png b/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates.png
index 34361d3433a..fa55cfd197e 100644
Binary files a/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates.png and b/components/filter/test/golden/filter/chromium/multiple-rtl-nested-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected-start-value.png b/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected-start-value.png
new file mode 100644
index 00000000000..8ec9bb36ce0
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected-start-value.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected.png
new file mode 100644
index 00000000000..dd973155d4a
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-long-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-dates-long-custom-selected.png
new file mode 100644
index 00000000000..69c9c4ffcb1
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-long-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-long.png b/components/filter/test/golden/filter/chromium/single-set-dates-long.png
new file mode 100644
index 00000000000..4b9fcab35af
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-long.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-open-custom-date-input.png b/components/filter/test/golden/filter/chromium/single-set-dates-open-custom-date-input.png
new file mode 100644
index 00000000000..7e9ac0f16bd
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-open-custom-date-input.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates-custom-date-selected.png b/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates-custom-date-selected.png
new file mode 100644
index 00000000000..e8337579c79
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates-custom-date-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates.png b/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates.png
new file mode 100644
index 00000000000..36b9763fc35
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-press-clear-dates.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-select-other-option-then-custom-again.png b/components/filter/test/golden/filter/chromium/single-set-dates-select-other-option-then-custom-again.png
new file mode 100644
index 00000000000..b78518ed578
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-select-other-option-then-custom-again.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected-start-value.png b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected-start-value.png
new file mode 100644
index 00000000000..44a6c8d55f5
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected-start-value.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected.png
new file mode 100644
index 00000000000..c1ef5902b5a
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long-custom-selected.png
new file mode 100644
index 00000000000..5b6abbcb3c1
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long.png b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long.png
new file mode 100644
index 00000000000..811d0b651b5
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-mobile-dates-long.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-press-clear-dates.png b/components/filter/test/golden/filter/chromium/single-set-press-clear-dates.png
deleted file mode 100644
index fb39f229423..00000000000
Binary files a/components/filter/test/golden/filter/chromium/single-set-press-clear-dates.png and /dev/null differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected-start-value.png b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected-start-value.png
new file mode 100644
index 00000000000..b7d779422a6
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected-start-value.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected.png
new file mode 100644
index 00000000000..6a6d78cf104
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long-custom-selected.png
new file mode 100644
index 00000000000..504eec3c535
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long.png b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long.png
new file mode 100644
index 00000000000..b99622314df
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-dates-long.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected-start-value.png b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected-start-value.png
new file mode 100644
index 00000000000..fea6db4a723
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected-start-value.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected.png
new file mode 100644
index 00000000000..ef3af2cbf57
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long-custom-selected.png b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long-custom-selected.png
new file mode 100644
index 00000000000..509286e382a
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long-custom-selected.png differ
diff --git a/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long.png b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long.png
new file mode 100644
index 00000000000..482ab7f1985
Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-rtl-mobile-dates-long.png differ
diff --git a/lang/ar.js b/lang/ar.js
index 6ec2b9ee551..1756671deb0 100644
--- a/lang/ar.js
+++ b/lang/ar.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} غير صالحة.",
"components.form-element.defaultFieldLabel": "الحقل",
"components.form-element.input.email.typeMismatch": "البريد الإلكتروني غير صالح",
diff --git a/lang/cy.js b/lang/cy.js
index bfd5c1ebd26..ba324c1901c 100644
--- a/lang/cy.js
+++ b/lang/cy.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "Mae {label} yn annilys.",
"components.form-element.defaultFieldLabel": "Maes",
"components.form-element.input.email.typeMismatch": "Nid yw'r e-bost yn ddilys",
diff --git a/lang/da.js b/lang/da.js
index 9983ff5181b..86ca1c71206 100644
--- a/lang/da.js
+++ b/lang/da.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} er ugyldigt.",
"components.form-element.defaultFieldLabel": "Felt",
"components.form-element.input.email.typeMismatch": "E-mail er ikke gyldig",
diff --git a/lang/de.js b/lang/de.js
index 14aedf638e1..3798e187cc1 100644
--- a/lang/de.js
+++ b/lang/de.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} ist ungültig.",
"components.form-element.defaultFieldLabel": "Feld",
"components.form-element.input.email.typeMismatch": "Die E-Mail-Adresse ist ungültig",
diff --git a/lang/en-gb.js b/lang/en-gb.js
index 093a0243b29..ef77620d498 100644
--- a/lang/en-gb.js
+++ b/lang/en-gb.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} is invalid.",
"components.form-element.defaultFieldLabel": "Field",
"components.form-element.input.email.typeMismatch": "Email is not valid",
diff --git a/lang/en.js b/lang/en.js
index 8eebd9dffd1..80dfad2a0e7 100644
--- a/lang/en.js
+++ b/lang/en.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} is invalid.",
"components.form-element.defaultFieldLabel": "Field",
"components.form-element.input.email.typeMismatch": "Email is not valid",
diff --git a/lang/es-es.js b/lang/es-es.js
index 6187d6e70cc..ded5bbc82f4 100644
--- a/lang/es-es.js
+++ b/lang/es-es.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} no es válido.",
"components.form-element.defaultFieldLabel": "Campo",
"components.form-element.input.email.typeMismatch": "El correo electrónico no es válido",
diff --git a/lang/es.js b/lang/es.js
index 99c4641feaf..d68b4adaf87 100644
--- a/lang/es.js
+++ b/lang/es.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} no es válida.",
"components.form-element.defaultFieldLabel": "Campo",
"components.form-element.input.email.typeMismatch": "El correo electrónico no es válido",
diff --git a/lang/fr-fr.js b/lang/fr-fr.js
index 26a8e81fab0..0802cf5b0e5 100644
--- a/lang/fr-fr.js
+++ b/lang/fr-fr.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} n'est pas valide.",
"components.form-element.defaultFieldLabel": "Champ",
"components.form-element.input.email.typeMismatch": "L'adresse e-mail n'est pas valide.",
diff --git a/lang/fr.js b/lang/fr.js
index d015f739791..19771b2cc78 100644
--- a/lang/fr.js
+++ b/lang/fr.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} n'est pas valide.",
"components.form-element.defaultFieldLabel": "Champ",
"components.form-element.input.email.typeMismatch": "L'adresse courriel n'est pas valide",
diff --git a/lang/hi.js b/lang/hi.js
index 746d57d8700..093d3bcfea9 100644
--- a/lang/hi.js
+++ b/lang/hi.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} अमान्य है।",
"components.form-element.defaultFieldLabel": "फ़ील्ड",
"components.form-element.input.email.typeMismatch": "ईमेल मान्य नहीं है",
diff --git a/lang/ja.js b/lang/ja.js
index 99b1afbd27f..9b629099e73 100644
--- a/lang/ja.js
+++ b/lang/ja.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} は無効です。",
"components.form-element.defaultFieldLabel": "フィールド",
"components.form-element.input.email.typeMismatch": "電子メールが無効です",
diff --git a/lang/ko.js b/lang/ko.js
index c94f5fef5d5..9629b18ea0d 100644
--- a/lang/ko.js
+++ b/lang/ko.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label}이(가) 잘못되었습니다.",
"components.form-element.defaultFieldLabel": "필드",
"components.form-element.input.email.typeMismatch": "이메일이 유효하지 않습니다.",
diff --git a/lang/nl.js b/lang/nl.js
index ee92df87bc2..69a273f7772 100644
--- a/lang/nl.js
+++ b/lang/nl.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} is ongeldig.",
"components.form-element.defaultFieldLabel": "Veld",
"components.form-element.input.email.typeMismatch": "E-mailadres is ongeldig",
diff --git a/lang/pt.js b/lang/pt.js
index 06ba8bd6737..1aae0305b50 100644
--- a/lang/pt.js
+++ b/lang/pt.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} é inválido.",
"components.form-element.defaultFieldLabel": "Campo",
"components.form-element.input.email.typeMismatch": "E-mail inválido",
diff --git a/lang/sv.js b/lang/sv.js
index 8e01325e3c6..c625f68d917 100644
--- a/lang/sv.js
+++ b/lang/sv.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} är ogiltig.",
"components.form-element.defaultFieldLabel": "Fält",
"components.form-element.input.email.typeMismatch": "E-postadressen är ogiltig",
diff --git a/lang/tr.js b/lang/tr.js
index 1fe64a0a1d1..438bcf05317 100644
--- a/lang/tr.js
+++ b/lang/tr.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, one {Last hour} other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} one {Last {num} days} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} geçersiz.",
"components.form-element.defaultFieldLabel": "Alan",
"components.form-element.input.email.typeMismatch": "E-posta geçerli değil",
diff --git a/lang/zh-cn.js b/lang/zh-cn.js
index 95a62252bfc..00e93046a35 100644
--- a/lang/zh-cn.js
+++ b/lang/zh-cn.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} 无效。",
"components.form-element.defaultFieldLabel": "字段",
"components.form-element.input.email.typeMismatch": "电子邮件无效",
diff --git a/lang/zh-tw.js b/lang/zh-tw.js
index d7ac7e000f9..1e01a4014c9 100644
--- a/lang/zh-tw.js
+++ b/lang/zh-tw.js
@@ -28,6 +28,7 @@ export default {
"components.filter-dimension-set-date-text-value.textHours": "{num, plural, other {Last {num} hours}}",
"components.filter-dimension-set-date-text-value.textDays": "{num, plural, =0 {Today} other {Last {num} days}}",
"components.filter-dimension-set-date-text-value.textMonths": "Last {num} months",
+ "components.filter-dimension-set-date-time-range-value.text": "Custom date range",
"components.form-element.defaultError": "{label} 無效。",
"components.form-element.defaultFieldLabel": "欄位",
"components.form-element.input.email.typeMismatch": "電子郵件無效",