@fluid-topics/ftds-period-picker 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
1
+ import { PropertyValues } from "lit";
2
+ import { FtdsBase } from "@fluid-topics/ft-wc-utils";
3
+ import { FtdsPeriodPickerDateInputsVisibility, FtdsPeriodPickerProperties, FtPeriod, FtPeriodPickerConfigOption, FtPeriodPickerOption, FtPeriodSelection } from "./ftds-period-picker.properties";
4
+ import { FtdsRadio, FtdsRadioGroup } from "@fluid-topics/ftds-radio";
5
+ import { FtdsTextInput } from "@fluid-topics/ftds-text-input";
6
+ import { FtdsIcon } from "@fluid-topics/ftds-icon";
7
+ import { FtdsFloatingMenu } from "@fluid-topics/ftds-floating-menu";
8
+ import { FtdsButton } from "@fluid-topics/ftds-button";
9
+ export declare class FtPeriodChangeEvent extends CustomEvent<FtPeriodSelection> {
10
+ constructor(detail: FtPeriodSelection);
11
+ }
12
+ declare const FtdsPeriodPicker_base: typeof FtdsBase & import("@fluid-topics/ft-wc-utils").Constructor<import("@fluid-topics/ft-wc-utils").FtInputInterface<FtPeriod>> & import("@fluid-topics/ft-wc-utils").Constructor<import("@fluid-topics/ft-i18n").FtLitElementWithI18nInterface>;
13
+ export declare class FtdsPeriodPicker extends FtdsPeriodPicker_base implements FtdsPeriodPickerProperties {
14
+ static elementDefinitions: {
15
+ "ftds-radio-group": typeof FtdsRadioGroup;
16
+ "ftds-radio": typeof FtdsRadio;
17
+ "ftds-text-input": typeof FtdsTextInput;
18
+ "ftds-icon": typeof FtdsIcon;
19
+ "ftds-floating-menu": typeof FtdsFloatingMenu;
20
+ "ftds-button": typeof FtdsButton;
21
+ };
22
+ static styles: import("lit").CSSResult[];
23
+ dateInputsVisibility: FtdsPeriodPickerDateInputsVisibility;
24
+ customPeriodLabel: string;
25
+ periods: FtPeriodPickerConfigOption[];
26
+ minDate?: Date;
27
+ maxDate?: Date;
28
+ defaultPeriod?: FtPeriodSelection;
29
+ locale: string;
30
+ currentSelection?: FtPeriodPickerOption;
31
+ periodOptions: FtPeriodPickerOption[];
32
+ mainPanel?: HTMLElement;
33
+ customPeriodFromDateInput: FtdsTextInput;
34
+ customPeriodToDateInput: FtdsTextInput;
35
+ ftdsRadioGroup: FtdsRadioGroup;
36
+ constructor();
37
+ protected willUpdate(props: PropertyValues): void;
38
+ protected firstUpdated(props: PropertyValues): void;
39
+ protected render(): import("lit-html").TemplateResult<1>;
40
+ protected renderRadioOptions(): import("lit-html").TemplateResult<1>;
41
+ protected renderDateInputs(): import("lit-html").TemplateResult<1>;
42
+ dateLimitRule(date: Date | undefined, limitDate: Date | undefined, shouldBeLater: boolean): string | true;
43
+ dateCompareRule(fromDate: Date | undefined, toDate: Date | undefined): string | true;
44
+ private onOptionChange;
45
+ private getInput;
46
+ private updatePeriodInputs;
47
+ private updateDateInputsValue;
48
+ private onCustomPeriodDateChange;
49
+ private triggerDateInputsValidation;
50
+ private dispatchPeriodChange;
51
+ }
52
+ export {};
@@ -0,0 +1,283 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, } from "lit";
8
+ import { property, query, state, } from "lit/decorators.js";
9
+ import { when } from "lit/directives/when.js";
10
+ import { repeat } from "lit/directives/repeat.js";
11
+ import { DateFormatter, dateProperty, FtdsBase, toFtInput, } from "@fluid-topics/ft-wc-utils";
12
+ import { i18n, withI18n, } from "@fluid-topics/ft-i18n";
13
+ import { FtdsPeriodPickerDateInputsVisibility, } from "./ftds-period-picker.properties";
14
+ import { styles } from "./ftds-period-picker.styles";
15
+ import { ftPeriodI18nContext, periodPickerDefaultMessages, } from "./FtdsPeriodPickerMessages";
16
+ import { FtdsRadio, FtdsRadioGroup, } from "@fluid-topics/ftds-radio";
17
+ import { datesLastInstant, FtPeriodsBuiltin, } from "./FtPeriodsBuiltin";
18
+ import { FtdsTextInput } from "@fluid-topics/ftds-text-input";
19
+ import { FtdsIcon } from "@fluid-topics/ftds-icon";
20
+ import { FtdsFloatingMenu } from "@fluid-topics/ftds-floating-menu";
21
+ import { FtdsButton } from "@fluid-topics/ftds-button";
22
+ export class FtPeriodChangeEvent extends CustomEvent {
23
+ constructor(detail) {
24
+ super("change", { detail });
25
+ }
26
+ }
27
+ export class FtdsPeriodPicker extends withI18n(toFtInput(FtdsBase)) {
28
+ constructor() {
29
+ super();
30
+ this.dateInputsVisibility = FtdsPeriodPickerDateInputsVisibility.dateInputsAlwaysVisible;
31
+ this.customPeriodLabel = "";
32
+ this.periods = [FtPeriodsBuiltin.anyTime()];
33
+ this.locale = "en-US";
34
+ this.periodOptions = [];
35
+ this.addI18nContext(ftPeriodI18nContext, periodPickerDefaultMessages);
36
+ this.errorRules = [
37
+ (v) => this.dateLimitRule(v === null || v === void 0 ? void 0 : v.from, this.minDate, true),
38
+ (v) => this.dateLimitRule(v === null || v === void 0 ? void 0 : v.to, this.minDate, true),
39
+ (v) => this.dateLimitRule(v === null || v === void 0 ? void 0 : v.from, this.maxDate, false),
40
+ (v) => this.dateLimitRule(v === null || v === void 0 ? void 0 : v.to, this.maxDate, false),
41
+ () => { var _a, _b; return this.dateCompareRule((_a = this.value) === null || _a === void 0 ? void 0 : _a.from, (_b = this.value) === null || _b === void 0 ? void 0 : _b.to); },
42
+ ];
43
+ }
44
+ willUpdate(props) {
45
+ super.willUpdate(props);
46
+ if (props.has("periods")) {
47
+ this.periodOptions = this.periods.map(({ key, label, selector }) => ({
48
+ key,
49
+ label: typeof label === "string" ? label : label(),
50
+ selector,
51
+ }));
52
+ }
53
+ if (this.defaultPeriod && !this.currentSelection) {
54
+ if (this.defaultPeriod.key == "custom") {
55
+ this.value = { from: this.defaultPeriod.from, to: this.defaultPeriod.to };
56
+ this.currentSelection = {
57
+ key: "custom",
58
+ label: this.customPeriodLabel,
59
+ selector: () => { var _a; return (_a = this.value) !== null && _a !== void 0 ? _a : {}; },
60
+ };
61
+ }
62
+ else {
63
+ const period = this.periodOptions.find((p) => { var _a; return p.key === ((_a = this.defaultPeriod) === null || _a === void 0 ? void 0 : _a.key); });
64
+ if (period) {
65
+ this.value = period.selector();
66
+ this.currentSelection = period;
67
+ }
68
+ }
69
+ }
70
+ }
71
+ firstUpdated(props) {
72
+ super.firstUpdated(props);
73
+ if (this.currentSelection) {
74
+ this.updatePeriodInputs();
75
+ }
76
+ }
77
+ render() {
78
+ var _a;
79
+ return html `
80
+ <div class="period-picker">
81
+ ${this.renderRadioOptions()}
82
+ ${when(((_a = this.currentSelection) === null || _a === void 0 ? void 0 : _a.key) == "custom" || this.dateInputsVisibility == FtdsPeriodPickerDateInputsVisibility.dateInputsAlwaysVisible, this.renderDateInputs.bind(this))}
83
+ </div>
84
+ `;
85
+ }
86
+ renderRadioOptions() {
87
+ var _a;
88
+ return html `
89
+ <ftds-radio-group @change=${(e) => this.onOptionChange(e)}
90
+ @input=${(e) => e.stopPropagation()}
91
+ @input-validated=${(e) => e.stopPropagation()}
92
+ aria-label="${ftPeriodI18nContext.messages.pickAPeriod()}">
93
+ ${repeat(this.periodOptions, (option) => option.key, (option) => {
94
+ var _a;
95
+ return html `
96
+ <ftds-radio value="${option.key}"
97
+ ?checked=${((_a = this.currentSelection) === null || _a === void 0 ? void 0 : _a.key) === option.key}>
98
+ ${option.label}
99
+ </ftds-radio>
100
+ `;
101
+ })}
102
+ <ftds-radio value="custom"
103
+ ?checked=${((_a = this.currentSelection) === null || _a === void 0 ? void 0 : _a.key) === "custom"}>
104
+ ${this.customPeriodLabel}
105
+ </ftds-radio>
106
+ </ftds-radio-group>
107
+ `;
108
+ }
109
+ renderDateInputs() {
110
+ return html `
111
+ <ftds-text-input id="custom-period-from-date"
112
+ type="date"
113
+ label="${ftPeriodI18nContext.messages.from()}"
114
+ .errorRules=${[
115
+ (v) => this.dateLimitRule(new Date(Date.parse(v)), this.minDate, true),
116
+ (v) => this.dateLimitRule(new Date(Date.parse(v)), this.maxDate, false),
117
+ ]}
118
+ @input=${(e) => this.onCustomPeriodDateChange("from", e)}
119
+ @input-validated=${(e) => e.stopPropagation()}></ftds-text-input>
120
+ <ftds-text-input id="custom-period-to-date"
121
+ type="date"
122
+ label="${ftPeriodI18nContext.messages.to()}"
123
+ .errorRules=${[
124
+ (v) => this.dateLimitRule(new Date(Date.parse(v)), this.minDate, true),
125
+ (v) => this.dateLimitRule(new Date(Date.parse(v)), this.maxDate, false),
126
+ () => { var _a, _b; return this.dateCompareRule((_a = this.value) === null || _a === void 0 ? void 0 : _a.from, (_b = this.value) === null || _b === void 0 ? void 0 : _b.to); },
127
+ ]}
128
+ @input=${(e) => this.onCustomPeriodDateChange("to", e)}
129
+ @input-validated=${(e) => e.stopPropagation()}></ftds-text-input>
130
+ `;
131
+ }
132
+ dateLimitRule(date, limitDate, shouldBeLater) {
133
+ if (!date || isNaN(date.valueOf()) || !limitDate) {
134
+ return true;
135
+ }
136
+ if ((shouldBeLater && date >= limitDate) || (!shouldBeLater && date <= limitDate)) {
137
+ return true;
138
+ }
139
+ const limitDateStr = DateFormatter.format(limitDate, this.locale, false, false, false);
140
+ return shouldBeLater
141
+ ? ftPeriodI18nContext.messages.mustNotBeEarlierThan(limitDateStr)
142
+ : ftPeriodI18nContext.messages.mustNotBeLaterThan(limitDateStr);
143
+ }
144
+ dateCompareRule(fromDate, toDate) {
145
+ if (!fromDate || !toDate || fromDate <= toDate) {
146
+ return true;
147
+ }
148
+ return ftPeriodI18nContext.messages.fromDateMustBeBeforeToDate();
149
+ }
150
+ onOptionChange(e) {
151
+ e.stopPropagation();
152
+ if (e.detail === "custom") {
153
+ this.currentSelection = {
154
+ key: "custom",
155
+ label: this.customPeriodLabel,
156
+ selector: () => { var _a; return (_a = this.value) !== null && _a !== void 0 ? _a : {}; },
157
+ };
158
+ }
159
+ else {
160
+ this.currentSelection = this.periodOptions.find((option) => option.key === e.detail);
161
+ this.value = this.currentSelection.selector();
162
+ this.triggerValidation();
163
+ if (this.dateInputsVisibility == FtdsPeriodPickerDateInputsVisibility.dateInputsAlwaysVisible) {
164
+ this.updatePeriodInputs();
165
+ }
166
+ this.triggerDateInputsValidation();
167
+ }
168
+ this.dispatchPeriodChange();
169
+ }
170
+ getInput(fromOrTo) {
171
+ return fromOrTo === "from"
172
+ ? this.renderRoot.querySelector("#custom-period-from-date")
173
+ : this.renderRoot.querySelector("#custom-period-to-date");
174
+ }
175
+ updatePeriodInputs() {
176
+ var _a, _b;
177
+ this.updateDateInputsValue((_a = this.value) === null || _a === void 0 ? void 0 : _a.from, this.getInput("from"));
178
+ this.updateDateInputsValue((_b = this.value) === null || _b === void 0 ? void 0 : _b.to, this.getInput("to"));
179
+ }
180
+ updateDateInputsValue(date, dateInput) {
181
+ if (!dateInput) {
182
+ return;
183
+ }
184
+ if (date) {
185
+ // the value provided to an HTML input of 'date' type must be in YYYY-MM-DD format
186
+ dateInput.value = date.toISOString().split("T")[0];
187
+ }
188
+ else {
189
+ dateInput.value = "";
190
+ }
191
+ }
192
+ onCustomPeriodDateChange(whichDate, e) {
193
+ var _a;
194
+ e.stopPropagation();
195
+ if (((_a = this.currentSelection) === null || _a === void 0 ? void 0 : _a.key) != "custom") {
196
+ this.currentSelection = {
197
+ key: "custom",
198
+ label: this.customPeriodLabel,
199
+ selector: () => { var _a; return (_a = this.value) !== null && _a !== void 0 ? _a : {}; },
200
+ };
201
+ }
202
+ const value = e.currentTarget.value;
203
+ let date;
204
+ if (value) {
205
+ const dateValue = Date.parse(value);
206
+ if (isNaN(dateValue)) {
207
+ return;
208
+ }
209
+ date = new Date(dateValue);
210
+ }
211
+ this.value = {
212
+ ...this.value,
213
+ [whichDate]: date,
214
+ };
215
+ this.dispatchPeriodChange();
216
+ this.triggerValidation();
217
+ this.triggerDateInputsValidation();
218
+ }
219
+ triggerDateInputsValidation() {
220
+ var _a, _b;
221
+ (_a = this.getInput("from")) === null || _a === void 0 ? void 0 : _a.triggerValidation();
222
+ (_b = this.getInput("to")) === null || _b === void 0 ? void 0 : _b.triggerValidation();
223
+ }
224
+ dispatchPeriodChange() {
225
+ var _a, _b, _c;
226
+ this.dispatchEvent(new FtPeriodChangeEvent({
227
+ key: this.currentSelection.key,
228
+ from: (_a = this.value) === null || _a === void 0 ? void 0 : _a.from,
229
+ to: ((_b = this.value) === null || _b === void 0 ? void 0 : _b.to) ? datesLastInstant((_c = this.value) === null || _c === void 0 ? void 0 : _c.to) : undefined,
230
+ }));
231
+ }
232
+ }
233
+ FtdsPeriodPicker.elementDefinitions = {
234
+ "ftds-radio-group": FtdsRadioGroup,
235
+ "ftds-radio": FtdsRadio,
236
+ "ftds-text-input": FtdsTextInput,
237
+ "ftds-icon": FtdsIcon,
238
+ "ftds-floating-menu": FtdsFloatingMenu,
239
+ "ftds-button": FtdsButton,
240
+ };
241
+ // language=CSS
242
+ FtdsPeriodPicker.styles = [
243
+ styles,
244
+ ];
245
+ __decorate([
246
+ property()
247
+ ], FtdsPeriodPicker.prototype, "dateInputsVisibility", void 0);
248
+ __decorate([
249
+ i18n(ftPeriodI18nContext.properties.custom())
250
+ ], FtdsPeriodPicker.prototype, "customPeriodLabel", void 0);
251
+ __decorate([
252
+ property({ attribute: false })
253
+ ], FtdsPeriodPicker.prototype, "periods", void 0);
254
+ __decorate([
255
+ dateProperty()
256
+ ], FtdsPeriodPicker.prototype, "minDate", void 0);
257
+ __decorate([
258
+ dateProperty()
259
+ ], FtdsPeriodPicker.prototype, "maxDate", void 0);
260
+ __decorate([
261
+ property({ attribute: false })
262
+ ], FtdsPeriodPicker.prototype, "defaultPeriod", void 0);
263
+ __decorate([
264
+ property()
265
+ ], FtdsPeriodPicker.prototype, "locale", void 0);
266
+ __decorate([
267
+ state()
268
+ ], FtdsPeriodPicker.prototype, "currentSelection", void 0);
269
+ __decorate([
270
+ state()
271
+ ], FtdsPeriodPicker.prototype, "periodOptions", void 0);
272
+ __decorate([
273
+ query(".period-picker--main-panel")
274
+ ], FtdsPeriodPicker.prototype, "mainPanel", void 0);
275
+ __decorate([
276
+ query("#custom-period-from-date")
277
+ ], FtdsPeriodPicker.prototype, "customPeriodFromDateInput", void 0);
278
+ __decorate([
279
+ query("#custom-period-to-date")
280
+ ], FtdsPeriodPicker.prototype, "customPeriodToDateInput", void 0);
281
+ __decorate([
282
+ query("ftds-radio-group")
283
+ ], FtdsPeriodPicker.prototype, "ftdsRadioGroup", void 0);