cx 26.4.3 → 26.5.1

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.
Files changed (74) hide show
  1. package/build/charts/axis/Axis.d.ts +8 -0
  2. package/build/charts/axis/Axis.d.ts.map +1 -1
  3. package/build/charts/axis/Axis.js +18 -1
  4. package/build/charts/axis/TimeAxis.js +1 -0
  5. package/build/data/AugmentedViewBase.d.ts.map +1 -1
  6. package/build/data/AugmentedViewBase.js +5 -4
  7. package/build/data/View.d.ts +0 -1
  8. package/build/data/View.d.ts.map +1 -1
  9. package/build/data/View.js +1 -3
  10. package/build/ui/Format.d.ts.map +1 -1
  11. package/build/ui/Format.js +26 -2
  12. package/build/util/Format.d.ts.map +1 -1
  13. package/build/util/Format.js +6 -0
  14. package/build/util/date/dateQuarter.d.ts +7 -0
  15. package/build/util/date/dateQuarter.d.ts.map +1 -0
  16. package/build/util/date/dateQuarter.js +8 -0
  17. package/build/util/date/dayBefore.d.ts +12 -0
  18. package/build/util/date/dayBefore.d.ts.map +1 -0
  19. package/build/util/date/dayBefore.js +15 -0
  20. package/build/util/date/index.d.ts +2 -0
  21. package/build/util/date/index.d.ts.map +1 -1
  22. package/build/util/date/index.js +2 -0
  23. package/build/widgets/form/DateTimePicker.d.ts.map +1 -1
  24. package/build/widgets/form/DateTimePicker.js +53 -31
  25. package/build/widgets/form/Field.d.ts.map +1 -1
  26. package/build/widgets/form/Field.js +2 -1
  27. package/build/widgets/form/LookupField.js +2 -1
  28. package/build/widgets/form/Wheel.d.ts +8 -0
  29. package/build/widgets/form/Wheel.d.ts.map +1 -1
  30. package/build/widgets/form/Wheel.js +30 -7
  31. package/build/widgets/grid/Grid.d.ts +1 -1
  32. package/build/widgets/grid/Grid.d.ts.map +1 -1
  33. package/dist/charts.css +6 -0
  34. package/dist/charts.js +18 -1
  35. package/dist/data.js +5 -4
  36. package/dist/manifest.js +772 -763
  37. package/dist/ui.js +33 -1
  38. package/dist/util.js +32 -0
  39. package/dist/widgets.css +9 -3
  40. package/dist/widgets.js +230 -174
  41. package/package.json +1 -1
  42. package/src/charts/RangeMarker.scss +3 -0
  43. package/src/charts/axis/Axis.tsx +31 -1
  44. package/src/charts/axis/TimeAxis.tsx +1 -0
  45. package/src/charts/index.scss +1 -0
  46. package/src/data/AugmentedViewBase.ts +5 -4
  47. package/src/data/View.ts +16 -61
  48. package/src/ui/DataProxy.ts +55 -55
  49. package/src/ui/Format.spec.ts +32 -0
  50. package/src/ui/Format.ts +27 -2
  51. package/src/ui/Rescope.ts +50 -50
  52. package/src/ui/adapter/ArrayAdapter.ts +229 -229
  53. package/src/ui/exprHelpers.ts +96 -96
  54. package/src/util/Format.spec.ts +11 -0
  55. package/src/util/Format.ts +7 -0
  56. package/src/util/date/dateQuarter.ts +8 -0
  57. package/src/util/date/dayBefore.ts +15 -0
  58. package/src/util/date/index.ts +2 -0
  59. package/src/widgets/Sandbox.ts +104 -104
  60. package/src/widgets/form/ColorField.scss +112 -112
  61. package/src/widgets/form/DateTimeField.scss +111 -111
  62. package/src/widgets/form/DateTimePicker.tsx +453 -392
  63. package/src/widgets/form/Field.tsx +2 -1
  64. package/src/widgets/form/LookupField.maps.scss +26 -26
  65. package/src/widgets/form/LookupField.scss +10 -3
  66. package/src/widgets/form/LookupField.tsx +4 -1
  67. package/src/widgets/form/MonthField.scss +113 -113
  68. package/src/widgets/form/NumberField.scss +72 -72
  69. package/src/widgets/form/Select.scss +104 -104
  70. package/src/widgets/form/TextField.scss +66 -66
  71. package/src/widgets/form/ValidationGroup.spec.tsx +30 -1
  72. package/src/widgets/form/Wheel.tsx +36 -7
  73. package/src/widgets/grid/Grid.tsx +1 -1
  74. package/src/widgets/nav/MenuItem.tsx +525 -525
@@ -12,32 +12,38 @@ import { WheelComponent } from "./Wheel";
12
12
  enableCultureSensitiveFormatting();
13
13
 
14
14
  export class DateTimePicker extends Widget {
15
- declare public size: number;
16
- declare public segment: string;
17
- declare public autoFocus?: boolean;
18
- declare public showSeconds?: boolean;
19
- declare public encoding?: (date: Date) => string;
20
- declare public onFocusOut?: string | ((instance: Instance) => void);
21
- declare public onSelect?: string | ((e: React.KeyboardEvent, instance: Instance, date: Date) => void);
22
- declare baseClass: string;
23
-
24
- declareData(...args: Record<string, unknown>[]): void {
25
- return super.declareData(...args, {
26
- value: undefined,
27
- });
28
- }
29
-
30
- render(context: RenderingContext, instance: Instance, key: string): React.ReactNode {
31
- return (
32
- <DateTimePickerComponent
33
- key={key}
34
- instance={instance}
35
- data={instance.data}
36
- size={this.size}
37
- segment={this.segment}
38
- />
39
- );
40
- }
15
+ declare public size: number;
16
+ declare public segment: string;
17
+ declare public autoFocus?: boolean;
18
+ declare public showSeconds?: boolean;
19
+ declare public encoding?: (date: Date) => string;
20
+ declare public onFocusOut?: string | ((instance: Instance) => void);
21
+ declare public onSelect?:
22
+ | string
23
+ | ((e: React.KeyboardEvent, instance: Instance, date: Date) => void);
24
+ declare baseClass: string;
25
+
26
+ declareData(...args: Record<string, unknown>[]): void {
27
+ return super.declareData(...args, {
28
+ value: undefined,
29
+ });
30
+ }
31
+
32
+ render(
33
+ context: RenderingContext,
34
+ instance: Instance,
35
+ key: string,
36
+ ): React.ReactNode {
37
+ return (
38
+ <DateTimePickerComponent
39
+ key={key}
40
+ instance={instance}
41
+ data={instance.data}
42
+ size={this.size}
43
+ segment={this.segment}
44
+ />
45
+ );
46
+ }
41
47
  }
42
48
 
43
49
  DateTimePicker.prototype.baseClass = "datetimepicker";
@@ -47,383 +53,438 @@ DateTimePicker.prototype.autoFocus = false;
47
53
  DateTimePicker.prototype.segment = "datetime";
48
54
  DateTimePicker.prototype.showSeconds = false;
49
55
 
56
+ // Builds the option spans for a numeric wheel — one zero-padded span per value.
57
+ // Pass the result to a WheelComponent with `cycle` set to make it scroll
58
+ // endlessly; centre the current value by passing `index = value + range`.
59
+ function buildNumberWheel(range: number, startAt: number): React.ReactNode[] {
60
+ return Array.from({ length: range }, (_, j) => (
61
+ <span key={j}>{String(j + startAt).padStart(2, "0")}</span>
62
+ ));
63
+ }
64
+
50
65
  interface DateTimePickerComponentProps {
51
- instance: Instance;
52
- data: Record<string, unknown>;
53
- size: number;
54
- segment: string;
66
+ instance: Instance;
67
+ data: Record<string, unknown>;
68
+ size: number;
69
+ segment: string;
55
70
  }
56
71
 
57
72
  interface DateTimePickerComponentState {
58
- date: Date;
59
- activeWheel: string | null;
73
+ date: Date;
74
+ activeWheel: string | null;
60
75
  }
61
76
 
62
- class DateTimePickerComponent extends VDOM.Component<DateTimePickerComponentProps, DateTimePickerComponentState> {
63
- el!: HTMLDivElement;
64
- declare wheels: Record<string, boolean>;
65
- keyDownPipes: Record<string, (e: React.KeyboardEvent) => void>;
66
-
67
- constructor(props: DateTimePickerComponentProps) {
68
- super(props);
69
- let date = props.data.value ? parseDateInvariant(props.data.value as string | number | Date) : new Date();
70
- if (isNaN(date.getTime())) date = new Date();
71
- this.state = {
72
- date: date,
73
- activeWheel: null,
74
- };
75
-
76
- let { widget } = props.instance;
77
- let pickerWidget = widget as DateTimePicker;
78
-
79
- this.handleChange = this.handleChange.bind(this);
80
- this.onFocus = this.onFocus.bind(this);
81
- this.onBlur = this.onBlur.bind(this);
82
- this.onKeyDown = this.onKeyDown.bind(this);
83
-
84
- let showDate = props.segment.indexOf("date") !== -1;
85
- let showTime = props.segment.indexOf("time") !== -1;
86
-
87
- this.wheels = {
88
- year: showDate,
89
- month: showDate,
90
- date: showDate,
91
- hours: showTime,
92
- minutes: showTime,
93
- seconds: showTime && !!pickerWidget.showSeconds,
94
- };
95
-
96
- this.keyDownPipes = {};
97
- }
98
-
99
- UNSAFE_componentWillReceiveProps(props: DateTimePickerComponentProps): void {
100
- let date = props.data.value ? parseDateInvariant(props.data.value as string | number | Date) : new Date();
101
- if (isNaN(date.getTime())) date = new Date();
102
- this.setState({ date });
103
- }
104
-
105
- setDateComponent(date: Date, component: string, value: number): Date {
106
- let v = new Date(date);
107
- switch (component) {
108
- case "year":
109
- v.setFullYear(value);
110
- break;
111
-
112
- case "month":
113
- v.setMonth(value);
114
- break;
115
-
116
- case "date":
117
- v.setDate(value);
118
- break;
119
-
120
- case "hours":
121
- v.setHours(value);
122
- break;
123
-
124
- case "minutes":
125
- v.setMinutes(value);
126
- break;
127
-
128
- case "seconds":
129
- v.setSeconds(value);
130
- break;
131
- }
132
- return v;
133
- }
134
-
135
- handleChange(): void {
136
- let { widget } = this.props.instance;
137
- let pickerWidget = widget as DateTimePicker;
138
- let encode = pickerWidget.encoding || Culture.getDefaultDateEncoding();
139
- this.props.instance.set("value", encode!(this.state.date));
140
- }
141
-
142
- render(): React.ReactNode {
143
- let { instance, data, size } = this.props;
144
- let { widget } = instance;
145
- let { CSS, baseClass } = widget;
146
- let pickerWidget = widget as DateTimePicker;
147
- let date = this.state.date;
148
-
149
- let culture = Culture.getDateTimeCulture();
150
- let monthNames = culture.getMonthNames("short");
151
-
152
- let years = [];
153
- for (let y = 1970; y <= 2050; y++) years.push(<span key={y}>{y}</span>);
154
-
155
- let days = [];
156
- let start = new Date(date.getFullYear(), date.getMonth(), 1);
157
- while (start.getMonth() === date.getMonth()) {
158
- let day = start.getDate();
159
- days.push(<span key={day}>{day < 10 ? "0" + day : day}</span>);
160
- start.setDate(start.getDate() + 1);
161
- }
162
-
163
- let hours = [];
164
- for (let h = 0; h < 24; h++) {
165
- hours.push(<span key={h}>{h < 10 ? "0" + h : h}</span>);
166
- }
167
-
168
- let minutes = [];
169
- for (let m = 0; m < 60; m++) {
170
- minutes.push(<span key={m}>{m < 10 ? "0" + m : m}</span>);
171
- }
172
-
173
- return (
174
- <div
175
- tabIndex={0}
176
- ref={(el) => {
177
- this.el = el!;
77
+ class DateTimePickerComponent extends VDOM.Component<
78
+ DateTimePickerComponentProps,
79
+ DateTimePickerComponentState
80
+ > {
81
+ el!: HTMLDivElement;
82
+ declare wheels: Record<string, boolean>;
83
+ keyDownPipes: Record<string, (e: React.KeyboardEvent) => void>;
84
+ declare years: any[];
85
+ declare days: any[];
86
+ declare hours: any[];
87
+ declare minutes: any[];
88
+ declare century: number;
89
+ declare firstYear: number;
90
+ declare numberOfDaysInMonth: number;
91
+
92
+ constructor(props: DateTimePickerComponentProps) {
93
+ super(props);
94
+ let date = props.data.value
95
+ ? parseDateInvariant(props.data.value as string | number | Date)
96
+ : new Date();
97
+ if (isNaN(date.getTime())) date = new Date();
98
+ this.state = {
99
+ date: date,
100
+ activeWheel: null,
101
+ };
102
+ this.century = (date.getFullYear() / 100) | 0;
103
+
104
+ let { widget } = props.instance;
105
+ let pickerWidget = widget as DateTimePicker;
106
+
107
+ this.handleChange = this.handleChange.bind(this);
108
+ this.onFocus = this.onFocus.bind(this);
109
+ this.onBlur = this.onBlur.bind(this);
110
+ this.onKeyDown = this.onKeyDown.bind(this);
111
+
112
+ let showDate = props.segment.indexOf("date") !== -1;
113
+ let showTime = props.segment.indexOf("time") !== -1;
114
+
115
+ this.wheels = {
116
+ year: showDate,
117
+ month: showDate,
118
+ date: showDate,
119
+ hours: showTime,
120
+ minutes: showTime,
121
+ seconds: showTime && !!pickerWidget.showSeconds,
122
+ };
123
+
124
+ this.keyDownPipes = {};
125
+ }
126
+
127
+ UNSAFE_componentWillReceiveProps(props: DateTimePickerComponentProps): void {
128
+ let date = props.data.value
129
+ ? parseDateInvariant(props.data.value as string | number | Date)
130
+ : new Date();
131
+ if (isNaN(date.getTime())) date = new Date();
132
+ this.setState({ date });
133
+ }
134
+
135
+ setDateComponent(date: Date, component: string, value: number): Date {
136
+ let v = new Date(date);
137
+ switch (component) {
138
+ case "year":
139
+ v.setFullYear(value);
140
+ break;
141
+
142
+ case "month":
143
+ v.setMonth(value);
144
+ break;
145
+
146
+ case "date":
147
+ v.setDate(value);
148
+ break;
149
+
150
+ case "hours":
151
+ v.setHours(value);
152
+ break;
153
+
154
+ case "minutes":
155
+ v.setMinutes(value);
156
+ break;
157
+
158
+ case "seconds":
159
+ v.setSeconds(value);
160
+ break;
161
+ }
162
+ return v;
163
+ }
164
+
165
+ handleChange(): void {
166
+ let { widget } = this.props.instance;
167
+ let pickerWidget = widget as DateTimePicker;
168
+ let encode = pickerWidget.encoding || Culture.getDefaultDateEncoding();
169
+ this.props.instance.set("value", encode!(this.state.date));
170
+ }
171
+
172
+ render(): React.ReactNode {
173
+ let { instance, data, size } = this.props;
174
+ let { widget } = instance;
175
+ let { CSS, baseClass } = widget;
176
+ let pickerWidget = widget as DateTimePicker;
177
+ let date = this.state.date;
178
+
179
+ let culture = Culture.getDateTimeCulture();
180
+ let monthNames = culture.getMonthNames("short");
181
+
182
+ // Years: a window spanning the current century, rebuilt when it changes.
183
+ let currentCentury = (date.getFullYear() / 100) | 0;
184
+ if (!this.years || this.century !== currentCentury) {
185
+ this.century = currentCentury;
186
+ this.firstYear = currentCentury * 100 - 3;
187
+ let lastYear = (currentCentury + 1) * 100 + 5;
188
+ this.years = [];
189
+ for (let y = this.firstYear; y <= lastYear; y++)
190
+ this.years.push(<span key={y}>{y}</span>);
191
+ }
192
+ let years = this.years;
193
+
194
+ // Day/hour/minute wheels use a 3x buffer (see buildNumberWheel). The day
195
+ // buffer depends on the month length, so it is rebuilt when that changes.
196
+ const numberOfDaysInMonth = new Date(
197
+ date.getFullYear(),
198
+ date.getMonth() + 1,
199
+ 0,
200
+ ).getDate();
201
+ if (!this.days || this.numberOfDaysInMonth !== numberOfDaysInMonth) {
202
+ this.numberOfDaysInMonth = numberOfDaysInMonth;
203
+ this.days = buildNumberWheel(numberOfDaysInMonth, 1);
204
+ }
205
+ let days = this.days;
206
+
207
+ if (!this.hours) this.hours = buildNumberWheel(24, 0);
208
+ let hours = this.hours;
209
+
210
+ if (!this.minutes) this.minutes = buildNumberWheel(60, 0);
211
+ let minutes = this.minutes;
212
+
213
+ return (
214
+ <div
215
+ tabIndex={0}
216
+ ref={(el) => {
217
+ this.el = el!;
218
+ }}
219
+ className={data.classNames as string}
220
+ onFocus={this.onFocus}
221
+ onBlur={this.onBlur}
222
+ onKeyDown={this.onKeyDown}
223
+ >
224
+ {this.wheels.year && (
225
+ <WheelComponent
226
+ key={`years-${this.century}`}
227
+ size={size}
228
+ CSS={CSS}
229
+ active={this.state.activeWheel === "year"}
230
+ baseClass={baseClass + "-wheel"}
231
+ index={date.getFullYear() - this.firstYear}
232
+ onChange={(newIndex) => {
233
+ this.setState(
234
+ (state) => ({
235
+ date: this.setDateComponent(
236
+ state.date,
237
+ "year",
238
+ newIndex + this.firstYear,
239
+ ),
240
+ }),
241
+ this.handleChange,
242
+ );
178
243
  }}
179
- className={data.classNames as string}
180
- onFocus={this.onFocus}
181
- onBlur={this.onBlur}
182
- onKeyDown={this.onKeyDown}
183
- >
184
- {this.wheels.year && (
185
- <WheelComponent
186
- size={size}
187
- CSS={CSS}
188
- active={this.state.activeWheel === "year"}
189
- baseClass={baseClass + "-wheel"}
190
- index={date.getFullYear() - 1970}
191
- onChange={(newIndex) => {
192
- this.setState(
193
- (state) => ({
194
- date: this.setDateComponent(this.state.date, "year", newIndex + 1970),
195
- }),
196
- this.handleChange,
197
- );
198
- }}
199
- onPipeKeyDown={(kd) => {
200
- this.keyDownPipes["year"] = kd;
201
- }}
202
- onMouseDown={() => {
203
- this.setState({ activeWheel: "year" });
204
- }}
205
- >
206
- {years}
207
- </WheelComponent>
208
- )}
209
- {this.wheels.year && this.wheels.month && <span>-</span>}
210
- {this.wheels.month && (
211
- <WheelComponent
212
- size={size}
213
- CSS={CSS}
214
- active={this.state.activeWheel === "month"}
215
- baseClass={baseClass + "-wheel"}
216
- index={date.getMonth()}
217
- onChange={(newIndex) => {
218
- this.setState(
219
- (state) => ({
220
- date: this.setDateComponent(this.state.date, "month", newIndex),
221
- }),
222
- this.handleChange,
223
- );
224
- }}
225
- onPipeKeyDown={(kd) => {
226
- this.keyDownPipes["month"] = kd;
227
- }}
228
- onMouseDown={() => {
229
- this.setState({ activeWheel: "month" });
230
- }}
231
- >
232
- {monthNames.map((m: string, i: number) => (
233
- <span key={i}>{m}</span>
234
- ))}
235
- </WheelComponent>
236
- )}
237
- {this.wheels.month && this.wheels.date && <span>-</span>}
238
- {this.wheels.date && (
239
- <WheelComponent
240
- size={size}
241
- CSS={CSS}
242
- active={this.state.activeWheel === "date"}
243
- baseClass={baseClass + "-wheel"}
244
- index={date.getDate() - 1}
245
- onChange={(newIndex) => {
246
- this.setState(
247
- (state) => ({
248
- date: this.setDateComponent(this.state.date, "date", newIndex + 1),
249
- }),
250
- this.handleChange,
251
- );
252
- }}
253
- onPipeKeyDown={(kd) => {
254
- this.keyDownPipes["date"] = kd;
255
- }}
256
- onMouseDown={() => {
257
- this.setState({ activeWheel: "date" });
258
- }}
259
- >
260
- {days}
261
- </WheelComponent>
262
- )}
263
- {this.wheels.hours && this.wheels.year && <span className={CSS.element(baseClass!, "spacer")} />}
264
- {this.wheels.hours && (
265
- <WheelComponent
266
- size={size}
267
- CSS={CSS}
268
- active={this.state.activeWheel === "hours"}
269
- baseClass={baseClass + "-wheel"}
270
- index={date.getHours()}
271
- onChange={(newIndex) => {
272
- this.setState(
273
- (state) => ({
274
- date: this.setDateComponent(this.state.date, "hours", newIndex),
275
- }),
276
- this.handleChange,
277
- );
278
- }}
279
- onPipeKeyDown={(kd) => {
280
- this.keyDownPipes["hours"] = kd;
281
- }}
282
- onMouseDown={() => {
283
- this.setState({ activeWheel: "hours" });
284
- }}
285
- >
286
- {hours}
287
- </WheelComponent>
288
- )}
289
- {this.wheels.hours && this.wheels.minutes && <span>:</span>}
290
- {this.wheels.minutes && (
291
- <WheelComponent
292
- size={size}
293
- CSS={CSS}
294
- baseClass={baseClass + "-wheel"}
295
- active={this.state.activeWheel === "minutes"}
296
- index={date.getMinutes()}
297
- onChange={(newIndex) => {
298
- this.setState(
299
- (state) => ({
300
- date: this.setDateComponent(this.state.date, "minutes", newIndex),
301
- }),
302
- this.handleChange,
303
- );
304
- }}
305
- onPipeKeyDown={(kd) => {
306
- this.keyDownPipes["minutes"] = kd;
307
- }}
308
- onMouseDown={() => {
309
- this.setState({ activeWheel: "minutes" });
310
- }}
311
- >
312
- {minutes}
313
- </WheelComponent>
314
- )}
315
- {this.wheels.minutes && this.wheels.seconds && <span>:</span>}
316
- {this.wheels.seconds && (
317
- <WheelComponent
318
- size={size}
319
- CSS={CSS}
320
- baseClass={baseClass + "-wheel"}
321
- active={this.state.activeWheel === "seconds"}
322
- index={date.getSeconds()}
323
- onChange={(newIndex) => {
324
- this.setState(
325
- (state) => ({
326
- date: this.setDateComponent(this.state.date, "seconds", newIndex),
327
- }),
328
- this.handleChange,
329
- );
330
- }}
331
- onPipeKeyDown={(kd) => {
332
- this.keyDownPipes["seconds"] = kd;
333
- }}
334
- onMouseDown={() => {
335
- this.setState({ activeWheel: "seconds" });
336
- }}
337
- >
338
- {minutes}
339
- </WheelComponent>
340
- )}
341
- </div>
342
- );
343
- }
344
-
345
- componentDidMount(): void {
346
- let { widget } = this.props.instance;
347
- let pickerWidget = widget as DateTimePicker;
348
- if (pickerWidget.autoFocus) this.el.focus();
349
- }
350
-
351
- componentWillUnmount(): void {
352
- offFocusOut(this);
353
- }
354
-
355
- onFocus(): void {
356
- oneFocusOut(this, this.el, this.onFocusOut.bind(this));
357
-
358
- if (!this.state.activeWheel) {
359
- let firstWheel: string | null = null;
360
- for (let wheel in this.wheels) {
361
- if (this.wheels[wheel]) {
362
- firstWheel = wheel;
363
- break;
364
- }
365
- }
366
-
367
- this.setState({
368
- activeWheel: firstWheel,
369
- });
244
+ onPipeKeyDown={(kd) => {
245
+ this.keyDownPipes["year"] = kd;
246
+ }}
247
+ onMouseDown={() => {
248
+ this.setState({ activeWheel: "year" });
249
+ }}
250
+ >
251
+ {years}
252
+ </WheelComponent>
253
+ )}
254
+ {this.wheels.year && this.wheels.month && <span>-</span>}
255
+ {this.wheels.month && (
256
+ <WheelComponent
257
+ size={size}
258
+ CSS={CSS}
259
+ active={this.state.activeWheel === "month"}
260
+ baseClass={baseClass + "-wheel"}
261
+ index={date.getMonth()}
262
+ onChange={(newIndex) => {
263
+ this.setState(
264
+ (state) => ({
265
+ date: this.setDateComponent(state.date, "month", newIndex),
266
+ }),
267
+ this.handleChange,
268
+ );
269
+ }}
270
+ onPipeKeyDown={(kd) => {
271
+ this.keyDownPipes["month"] = kd;
272
+ }}
273
+ onMouseDown={() => {
274
+ this.setState({ activeWheel: "month" });
275
+ }}
276
+ >
277
+ {monthNames.map((m: string, i: number) => (
278
+ <span key={i}>{m}</span>
279
+ ))}
280
+ </WheelComponent>
281
+ )}
282
+ {this.wheels.month && this.wheels.date && <span>-</span>}
283
+ {this.wheels.date && (
284
+ <WheelComponent
285
+ key="date"
286
+ size={size}
287
+ CSS={CSS}
288
+ cycle
289
+ active={this.state.activeWheel === "date"}
290
+ baseClass={baseClass + "-wheel"}
291
+ index={date.getDate() - 1 + this.numberOfDaysInMonth}
292
+ onChange={(rawIndex) => {
293
+ let day = rawIndex % this.numberOfDaysInMonth;
294
+ this.setState(
295
+ (state) => ({
296
+ date: this.setDateComponent(state.date, "date", day + 1),
297
+ }),
298
+ this.handleChange,
299
+ );
300
+ }}
301
+ onPipeKeyDown={(kd) => {
302
+ this.keyDownPipes["date"] = kd;
303
+ }}
304
+ onMouseDown={() => {
305
+ this.setState({ activeWheel: "date" });
306
+ }}
307
+ >
308
+ {days}
309
+ </WheelComponent>
310
+ )}
311
+ {this.wheels.hours && this.wheels.year && (
312
+ <span className={CSS.element(baseClass!, "spacer")} />
313
+ )}
314
+ {this.wheels.hours && (
315
+ <WheelComponent
316
+ key="hours"
317
+ size={size}
318
+ CSS={CSS}
319
+ cycle
320
+ active={this.state.activeWheel === "hours"}
321
+ baseClass={baseClass + "-wheel"}
322
+ index={date.getHours() + 24}
323
+ onChange={(rawIndex) => {
324
+ let hour = rawIndex % 24;
325
+ this.setState(
326
+ (state) => ({
327
+ date: this.setDateComponent(state.date, "hours", hour),
328
+ }),
329
+ this.handleChange,
330
+ );
331
+ }}
332
+ onPipeKeyDown={(kd) => {
333
+ this.keyDownPipes["hours"] = kd;
334
+ }}
335
+ onMouseDown={() => {
336
+ this.setState({ activeWheel: "hours" });
337
+ }}
338
+ >
339
+ {hours}
340
+ </WheelComponent>
341
+ )}
342
+ {this.wheels.hours && this.wheels.minutes && <span>:</span>}
343
+ {this.wheels.minutes && (
344
+ <WheelComponent
345
+ key="minutes"
346
+ size={size}
347
+ CSS={CSS}
348
+ cycle
349
+ baseClass={baseClass + "-wheel"}
350
+ active={this.state.activeWheel === "minutes"}
351
+ index={date.getMinutes() + 60}
352
+ onChange={(rawIndex) => {
353
+ let minute = rawIndex % 60;
354
+ this.setState(
355
+ (state) => ({
356
+ date: this.setDateComponent(state.date, "minutes", minute),
357
+ }),
358
+ this.handleChange,
359
+ );
360
+ }}
361
+ onPipeKeyDown={(kd) => {
362
+ this.keyDownPipes["minutes"] = kd;
363
+ }}
364
+ onMouseDown={() => {
365
+ this.setState({ activeWheel: "minutes" });
366
+ }}
367
+ >
368
+ {minutes}
369
+ </WheelComponent>
370
+ )}
371
+ {this.wheels.minutes && this.wheels.seconds && <span>:</span>}
372
+ {this.wheels.seconds && (
373
+ <WheelComponent
374
+ key="seconds"
375
+ size={size}
376
+ CSS={CSS}
377
+ cycle
378
+ baseClass={baseClass + "-wheel"}
379
+ active={this.state.activeWheel === "seconds"}
380
+ index={date.getSeconds() + 60}
381
+ onChange={(rawIndex) => {
382
+ let second = rawIndex % 60;
383
+ this.setState(
384
+ (state) => ({
385
+ date: this.setDateComponent(state.date, "seconds", second),
386
+ }),
387
+ this.handleChange,
388
+ );
389
+ }}
390
+ onPipeKeyDown={(kd) => {
391
+ this.keyDownPipes["seconds"] = kd;
392
+ }}
393
+ onMouseDown={() => {
394
+ this.setState({ activeWheel: "seconds" });
395
+ }}
396
+ >
397
+ {minutes}
398
+ </WheelComponent>
399
+ )}
400
+ </div>
401
+ );
402
+ }
403
+
404
+ componentDidMount(): void {
405
+ let { widget } = this.props.instance;
406
+ let pickerWidget = widget as DateTimePicker;
407
+ if (pickerWidget.autoFocus) this.el.focus();
408
+ }
409
+
410
+ componentWillUnmount(): void {
411
+ offFocusOut(this);
412
+ }
413
+
414
+ onFocus(): void {
415
+ oneFocusOut(this, this.el, this.onFocusOut.bind(this));
416
+
417
+ if (!this.state.activeWheel) {
418
+ let firstWheel: string | null = null;
419
+ for (let wheel in this.wheels) {
420
+ if (this.wheels[wheel]) {
421
+ firstWheel = wheel;
422
+ break;
423
+ }
370
424
  }
371
- }
372
425
 
373
- onFocusOut(): void {
374
- let { instance } = this.props;
375
- let { widget } = instance;
376
- let pickerWidget = widget as DateTimePicker;
377
- if (pickerWidget.onFocusOut) instance.invoke("onFocusOut", null, instance);
378
- }
379
-
380
- onBlur(): void {
381
426
  this.setState({
382
- activeWheel: null,
427
+ activeWheel: firstWheel,
383
428
  });
384
- }
385
-
386
- onKeyDown(e: React.KeyboardEvent): void {
387
- let tmp: string | null = null;
388
- let { instance } = this.props;
389
- let { widget } = instance;
390
- let pickerWidget = widget as DateTimePicker;
391
-
392
- switch (e.keyCode) {
393
- case KeyCode.right:
394
- e.preventDefault();
395
- for (let wheel in this.wheels) {
396
- if (this.wheels[wheel]) {
397
- if (tmp === this.state.activeWheel) {
398
- this.setState({ activeWheel: wheel });
399
- break;
400
- }
401
- tmp = wheel;
402
- }
429
+ }
430
+ }
431
+
432
+ onFocusOut(): void {
433
+ let { instance } = this.props;
434
+ let { widget } = instance;
435
+ let pickerWidget = widget as DateTimePicker;
436
+ if (pickerWidget.onFocusOut) instance.invoke("onFocusOut", null, instance);
437
+ }
438
+
439
+ onBlur(): void {
440
+ this.setState({
441
+ activeWheel: null,
442
+ });
443
+ }
444
+
445
+ onKeyDown(e: React.KeyboardEvent): void {
446
+ let tmp: string | null = null;
447
+ let { instance } = this.props;
448
+ let { widget } = instance;
449
+ let pickerWidget = widget as DateTimePicker;
450
+
451
+ switch (e.keyCode) {
452
+ case KeyCode.right:
453
+ e.preventDefault();
454
+ for (let wheel in this.wheels) {
455
+ if (this.wheels[wheel]) {
456
+ if (tmp === this.state.activeWheel) {
457
+ this.setState({ activeWheel: wheel });
458
+ break;
403
459
  }
404
- break;
405
-
406
- case KeyCode.left:
407
- e.preventDefault();
408
- for (let wheel in this.wheels) {
409
- if (this.wheels[wheel]) {
410
- if (wheel === this.state.activeWheel && tmp) {
411
- this.setState({ activeWheel: tmp });
412
- break;
413
- }
414
- tmp = wheel;
415
- }
460
+ tmp = wheel;
461
+ }
462
+ }
463
+ break;
464
+
465
+ case KeyCode.left:
466
+ e.preventDefault();
467
+ for (let wheel in this.wheels) {
468
+ if (this.wheels[wheel]) {
469
+ if (wheel === this.state.activeWheel && tmp) {
470
+ this.setState({ activeWheel: tmp });
471
+ break;
416
472
  }
417
- break;
418
-
419
- case KeyCode.enter:
420
- e.preventDefault();
421
- if (pickerWidget.onSelect) instance.invoke("onSelect", e, instance, this.state.date);
422
- break;
423
-
424
- default: let kdp = this.keyDownPipes[this.state.activeWheel!];
425
- if (kdp) kdp(e);
426
- break;
427
- }
428
- }
473
+ tmp = wheel;
474
+ }
475
+ }
476
+ break;
477
+
478
+ case KeyCode.enter:
479
+ e.preventDefault();
480
+ if (pickerWidget.onSelect)
481
+ instance.invoke("onSelect", e, instance, this.state.date);
482
+ break;
483
+
484
+ default:
485
+ let kdp = this.keyDownPipes[this.state.activeWheel!];
486
+ if (kdp) kdp(e);
487
+ break;
488
+ }
489
+ }
429
490
  }