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]: unknown
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
- return value && isValid(value) ? new TZDate(value, tz) : undefined
33
- }, [value])
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
- onChange(new Date().getTime())
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, referenceDate?: Date) {
251
- const parsedDate = parse(value.trim(), pattern, referenceDate ?? new Date(), tz ? { in: _tz(tz) } : undefined)
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
- 'date-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 33],
66
- 'date-multiple': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 2],
67
- 'date-time': Date.now(),//////
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
- 'calendar-single': Date.now(),
70
- 'calendar-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 8],
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
- 'date-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 5.2],
85
- 'date-multiple': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 3.2],
86
- 'date-time': Date.now() + 1000 * 60 * 60 * 24 * 2.2,
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
- 'calendar-single': Date.now(),
89
- 'calendar-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 3.2],
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: 'dateRange',
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="date">Date with time</label>
517
- <Field name="date-time" type="date" mode="single" showTime={true} state={state} onChange={(e) => onChange(e, setState)}
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="date-range">Date range (with prefix & disabled days)</label>
526
+ <label for="dateRange">Date range (with prefix & disabled days)</label>
525
527
  <Field
526
- name="date-range"
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="date">Date multi-select (right aligned)</label>
539
- <Field name="date-multiple" type="date" mode="multiple" state={state} onChange={(e) => onChange(e, setState)} dir="bottom-right" />
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['calendar-single'] || '')?.toLocaleString('en-US', { timeZone: 'Pacific/Honolulu' })} */}
574
+ {/* {' ' + new Date(state.calendarSingle || '')?.toLocaleString('en-US', { timeZone: 'Pacific/Honolulu' })} */}
564
575
  </label>
565
- <Calendar mode="range" value={state['calendar-range']} numberOfMonths={1}
566
- onChange={(value) => onChange({ target: { name: 'calendar-range', value: value } }, setState)}
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 value={state.time} className="min-h-[150]"
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.149",
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 🚀",