nitro-web 0.0.149 → 0.0.151
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.
|
@@ -15,7 +15,7 @@ export type FilterType = (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
type FilterState = {
|
|
18
|
-
[key: string]:
|
|
18
|
+
[key: string]: any
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
type FiltersProps = {
|
|
@@ -37,10 +37,6 @@ type FiltersProps = {
|
|
|
37
37
|
dropdownFiltersClassName?: string
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
export type FiltersHandleType = {
|
|
41
|
-
submit: (includePagination?: boolean) => void
|
|
42
|
-
}
|
|
43
|
-
|
|
44
40
|
const debounceTime = 250
|
|
45
41
|
|
|
46
42
|
export function Filters({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useRef, useMemo, useEffect } from 'react'
|
|
1
2
|
import { isValid, format } from 'date-fns'
|
|
2
3
|
import { TZDate } from '@date-fns/tz'
|
|
3
4
|
import { twMerge } from 'nitro-web'
|
|
@@ -9,9 +10,12 @@ export type TimePickerProps = {
|
|
|
9
10
|
onChange?: (value: Timestamp) => void
|
|
10
11
|
tz?: string
|
|
11
12
|
value?: Timestamp
|
|
13
|
+
/** "Reactive" reference timestamp to use for the time picker's date. Precedence order: `referenceTimestamp`, `value`, or today */
|
|
14
|
+
referenceTimestamp?: Timestamp
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
export function TimePicker({ value, onChange, className, tz }: TimePickerProps) {
|
|
17
|
+
export function TimePicker({ value, onChange, className, tz, referenceTimestamp }: TimePickerProps) {
|
|
18
|
+
const [internallyChanged, setInternallyChanged] = useState<Timestamp>()
|
|
15
19
|
const refs = {
|
|
16
20
|
hour: useRef<HTMLDivElement>(null),
|
|
17
21
|
minute: useRef<HTMLDivElement>(null),
|
|
@@ -29,8 +33,32 @@ export function TimePicker({ value, onChange, className, tz }: TimePickerProps)
|
|
|
29
33
|
|
|
30
34
|
// Convert the value to an valid* date
|
|
31
35
|
const internalValue = useMemo(() => {
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
if (!value || !isValid(value)) return undefined
|
|
37
|
+
const date = new TZDate(value, tz)
|
|
38
|
+
|
|
39
|
+
// Carry over the date from the referenceTimestamp, if provided
|
|
40
|
+
if (referenceTimestamp && isValid(referenceTimestamp)) {
|
|
41
|
+
const referenceDate = new TZDate(referenceTimestamp, tz)
|
|
42
|
+
const originalTime = date.getTime()
|
|
43
|
+
date.setDate(referenceDate.getDate())
|
|
44
|
+
date.setMonth(referenceDate.getMonth())
|
|
45
|
+
date.setFullYear(referenceDate.getFullYear())
|
|
46
|
+
// If the time has changed, update the value
|
|
47
|
+
if (originalTime !== date.getTime()) {
|
|
48
|
+
setInternallyChanged(date.getTime())
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return date
|
|
53
|
+
}, [value, tz, referenceTimestamp])
|
|
54
|
+
|
|
55
|
+
// Update the value when the changedValue changes
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (internallyChanged && isValid(internallyChanged)) {
|
|
58
|
+
onChange?.(internallyChanged)
|
|
59
|
+
setInternallyChanged(undefined)
|
|
60
|
+
}
|
|
61
|
+
}, [internallyChanged])
|
|
34
62
|
|
|
35
63
|
// Get current values from date or use defaults
|
|
36
64
|
const hour = useMemo(() => internalValue ? parseInt(format(internalValue, 'h')) : undefined, [internalValue])
|
|
@@ -34,6 +34,8 @@ type PreFieldDateProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onCh
|
|
|
34
34
|
DropdownProps?: DropdownProps
|
|
35
35
|
/** timezone to use for the date picker */
|
|
36
36
|
tz?: string
|
|
37
|
+
/** Reference timestamp to use for the time picker's date. Precedence order: `referenceTimestamp`, `value`, or today */
|
|
38
|
+
referenceTimestamp?: Timestamp
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
// Discriminated union types based on mode
|
|
@@ -64,6 +66,7 @@ export function FieldDate({
|
|
|
64
66
|
DayPickerProps,
|
|
65
67
|
DropdownProps,
|
|
66
68
|
tz,
|
|
69
|
+
referenceTimestamp,
|
|
67
70
|
...props
|
|
68
71
|
}: FieldDateProps) {
|
|
69
72
|
const [month, setMonth] = useState<number|undefined>()
|
|
@@ -141,7 +144,7 @@ export function FieldDate({
|
|
|
141
144
|
|
|
142
145
|
// Parse the datestring into timestamps
|
|
143
146
|
let timestamps = e.target.value.split(/-|,/).map(o => {
|
|
144
|
-
return parseDateString(o.trim(), pattern, tz)
|
|
147
|
+
return parseDateString(o.trim(), pattern, tz, referenceTimestamp)
|
|
145
148
|
})
|
|
146
149
|
|
|
147
150
|
// For range mode we need limit the array to 2
|
|
@@ -168,7 +171,10 @@ export function FieldDate({
|
|
|
168
171
|
}
|
|
169
172
|
|
|
170
173
|
function onNowClick() {
|
|
171
|
-
|
|
174
|
+
// Use the browser's local time and parse it into the timezone
|
|
175
|
+
const [hours, minutes, seconds] = [new Date().getHours(), new Date().getMinutes(), new Date().getSeconds()]
|
|
176
|
+
const nowInTz = parseDateString(`${hours}:${minutes}:${seconds}`, 'hh:mm:ss', tz, referenceTimestamp)
|
|
177
|
+
onChange(nowInTz)
|
|
172
178
|
}
|
|
173
179
|
|
|
174
180
|
// Common props for the Calendar component
|
|
@@ -198,7 +204,8 @@ export function FieldDate({
|
|
|
198
204
|
{
|
|
199
205
|
(props.mode == 'time' || (!!showTime && props.mode == 'single')) &&
|
|
200
206
|
<TimePicker value={internalValue?.[0]} onChange={onChange<Timestamp>}
|
|
201
|
-
className={`border-l border-gray-100 ${props.mode == 'single' ? 'min-h-[0]' : ''}`}
|
|
207
|
+
className={`border-l border-gray-100 ${props.mode == 'single' ? 'min-h-[0]' : ''}`}
|
|
208
|
+
referenceTimestamp={referenceTimestamp}
|
|
202
209
|
/>
|
|
203
210
|
}
|
|
204
211
|
</div>
|
|
@@ -247,8 +254,8 @@ export function FieldDate({
|
|
|
247
254
|
* @param [referenceDate] - required if value doesn't contain a date, e.g. for time only
|
|
248
255
|
* @param [tz] - timezone
|
|
249
256
|
*/
|
|
250
|
-
function parseDateString(value: string, pattern: string, tz?: string,
|
|
251
|
-
const parsedDate = parse(value.trim(), pattern,
|
|
257
|
+
function parseDateString(value: string, pattern: string, tz?: string, referenceTimestamp?: Timestamp) {
|
|
258
|
+
const parsedDate = parse(value.trim(), pattern, referenceTimestamp ?? new Date(), tz ? { in: _tz(tz) } : undefined)
|
|
252
259
|
if (!isValid(parsedDate)) return null
|
|
253
260
|
else return parsedDate.getTime()
|
|
254
261
|
}
|
|
@@ -62,12 +62,13 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
62
62
|
country: 'nz',
|
|
63
63
|
currency: 'nzd',
|
|
64
64
|
date: Date.now(),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
dateRange: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 33],
|
|
66
|
+
dateMultiple: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 2],
|
|
67
|
+
dateTime: Date.now(),
|
|
68
68
|
time: Date.now(),
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
timeReference: Date.now(),
|
|
70
|
+
calendarSingle: Date.now(),
|
|
71
|
+
calendarRange: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 8],
|
|
71
72
|
firstName: 'Bruce',
|
|
72
73
|
tableFilter: '',
|
|
73
74
|
errors: [
|
|
@@ -81,12 +82,13 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
81
82
|
country: 'au',
|
|
82
83
|
currency: 'btc',
|
|
83
84
|
date: Date.now() + 1000 * 60 * 60 * 24 * 1.2,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
dateRange: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 5.2],
|
|
86
|
+
dateMultiple: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 3.2],
|
|
87
|
+
dateTime: Date.now() + 1000 * 60 * 60 * 24 * 2.2,
|
|
87
88
|
time: Date.now() + 1000 * 60 * 60 * 1.2,
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
timeReference: Date.now() + 1000 * 60 * 60 * 1.2,
|
|
90
|
+
calendarSingle: Date.now(),
|
|
91
|
+
calendarRange: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 3.2],
|
|
90
92
|
firstName: 'John',
|
|
91
93
|
tableFilter: '',
|
|
92
94
|
errors: [
|
|
@@ -110,7 +112,7 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
110
112
|
const filters: FilterType[] = [
|
|
111
113
|
{
|
|
112
114
|
type: 'date',
|
|
113
|
-
name: '
|
|
115
|
+
name: 'dateRange2',
|
|
114
116
|
mode: 'range',
|
|
115
117
|
placeholder: 'Select a range...',
|
|
116
118
|
},
|
|
@@ -513,17 +515,17 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
513
515
|
<h2 class="h3">Date Inputs</h2>
|
|
514
516
|
<div class="grid grid-cols-1 gap-x-6 sm:grid-cols-3">
|
|
515
517
|
<div>
|
|
516
|
-
<label for="
|
|
517
|
-
<Field name="
|
|
518
|
+
<label for="dateTime">Date with time</label>
|
|
519
|
+
<Field name="dateTime" type="date" mode="single" showTime={true} state={state} onChange={(e) => onChange(e, setState)}
|
|
518
520
|
// Testing timezone support:
|
|
519
521
|
// tz="Pacific/Honolulu"
|
|
520
522
|
// DropdownProps={{ menuIsOpen: true }}
|
|
521
523
|
/>
|
|
522
524
|
</div>
|
|
523
525
|
<div>
|
|
524
|
-
<label for="
|
|
526
|
+
<label for="dateRange">Date range (with prefix & disabled days)</label>
|
|
525
527
|
<Field
|
|
526
|
-
name="
|
|
528
|
+
name="dateRange"
|
|
527
529
|
type="date"
|
|
528
530
|
mode="range"
|
|
529
531
|
prefix="Date:"
|
|
@@ -535,16 +537,25 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
535
537
|
/>
|
|
536
538
|
</div>
|
|
537
539
|
<div>
|
|
538
|
-
<label for="
|
|
539
|
-
<Field name="
|
|
540
|
+
<label for="dateMultiple">Date multi-select (right aligned)</label>
|
|
541
|
+
<Field name="dateMultiple" type="date" mode="multiple" state={state} onChange={(e) => onChange(e, setState)} dir="bottom-right" />
|
|
540
542
|
</div>
|
|
541
543
|
<div>
|
|
542
|
-
<label for="time">Time</label>
|
|
544
|
+
<label for="time">Time: {date(state.time, 'dd MMM hh:mmaa')}</label>
|
|
543
545
|
<Field name="time" type="date" mode="time" state={state} onChange={(e) => onChange(e, setState)}
|
|
544
546
|
// Testing timezone support:
|
|
545
547
|
// tz="Pacific/Honolulu"
|
|
546
548
|
/>
|
|
547
549
|
</div>
|
|
550
|
+
<div>
|
|
551
|
+
<label for="timeReference">Time: {date(state.timeReference, 'dd MMM hh:mmaa')} (with date reference)</label>
|
|
552
|
+
<Field name="timeReference" type="date" mode="time" state={state} onChange={(e) => onChange(e, setState)}
|
|
553
|
+
// Testing timezone support:
|
|
554
|
+
// tz="Pacific/Honolulu"
|
|
555
|
+
// referenceTimestamp={useMemo(() => new Date().getTime() + 1000 * 60 * 60 * 24 * 5, [])}
|
|
556
|
+
referenceTimestamp={state.dateTime}
|
|
557
|
+
/>
|
|
558
|
+
</div>
|
|
548
559
|
</div>
|
|
549
560
|
</div>
|
|
550
561
|
)}
|
|
@@ -560,10 +571,10 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
560
571
|
<div>
|
|
561
572
|
<label for="calendar">
|
|
562
573
|
Calendar
|
|
563
|
-
{/* {' ' + new Date(state
|
|
574
|
+
{/* {' ' + new Date(state.calendarSingle || '')?.toLocaleString('en-US', { timeZone: 'Pacific/Honolulu' })} */}
|
|
564
575
|
</label>
|
|
565
|
-
<Calendar mode="range" value={state
|
|
566
|
-
onChange={(value) => onChange({ target: { name: '
|
|
576
|
+
<Calendar mode="range" value={state.calendarRange} numberOfMonths={1}
|
|
577
|
+
onChange={(value) => onChange({ target: { name: 'calendarRange', value: value } }, setState)}
|
|
567
578
|
// Testing timezone support:
|
|
568
579
|
// tz="Pacific/Honolulu"
|
|
569
580
|
// preserveTime={true}
|
|
@@ -571,13 +582,16 @@ export function Styleguide({ className, elements, children, currencies }: Styleg
|
|
|
571
582
|
</div>
|
|
572
583
|
<div>
|
|
573
584
|
<label for="time">TimePicker</label>
|
|
574
|
-
<div className="mt-2.5 mb-6 mt-input-before mb-input-after pt-2">
|
|
575
|
-
<TimePicker
|
|
585
|
+
{/* <div className="mt-2.5 mb-6 mt-input-before mb-input-after pt-2"> */}
|
|
586
|
+
<TimePicker
|
|
587
|
+
value={state.time}
|
|
588
|
+
className="min-h-[150] mt-2.5 mb-6 mt-input-before mb-input-after pt-2"
|
|
576
589
|
onChange={(value) => onChange({ target: { name: 'time', value: value }}, setState)}
|
|
577
590
|
// Testing timezone support:
|
|
578
591
|
// tz="Pacific/Honolulu"
|
|
592
|
+
// referenceTimestamp={new Date().getTime() + 1000 * 60 * 60 * 24 * 5}
|
|
579
593
|
/>
|
|
580
|
-
</div>
|
|
594
|
+
{/* </div> */}
|
|
581
595
|
</div>
|
|
582
596
|
</div>
|
|
583
597
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.151",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
6
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|