nitro-web 0.0.44 → 0.0.46

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.
package/.eslintrc.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "allowArray": true,
41
41
  "allowObject": true
42
42
  }],
43
- "indent": ["error", 2],
43
+ "indent": ["error", 2, { "SwitchCase": 1, "offsetTernaryExpressions": true }],
44
44
  "max-len": ["error", { "code": 140, "ignorePattern": "^\\s*(<(rect|path|line)\\s|class=|className=|'|`)" }],
45
45
  "no-var": "off",
46
46
  "no-prototype-builtins": "off",
package/client/app.tsx CHANGED
@@ -98,8 +98,8 @@ function App({ settings, config, storeContainer }: { settings: Settings, config:
98
98
  return (
99
99
  <storeContainer.Provider>
100
100
  {/* <ThemeProvider theme={themeNormalised}> */}
101
- { router && <RouterProvider router={router} /> }
102
- <AfterApp settings={settings} />
101
+ { router && <RouterProvider router={router} /> }
102
+ <AfterApp settings={settings} />
103
103
  {/* </ThemeProvider> */}
104
104
  </storeContainer.Provider>
105
105
  )
@@ -24,7 +24,7 @@ export function ResetInstructions() {
24
24
  <form onSubmit={onSubmit}>
25
25
  <div>
26
26
  <label for="email">Email Address</label>
27
- <Field name="email" type="email" state={state} onChange={onChange.bind(setState)} placeholder="Your email address..." />
27
+ <Field name="email" type="email" state={state} onChange={(e) => onChange(setState, e)} placeholder="Your email address..." />
28
28
  </div>
29
29
 
30
30
  <div class="mb-14">
@@ -67,11 +67,11 @@ export function ResetPassword() {
67
67
  <form onSubmit={onSubmit}>
68
68
  <div>
69
69
  <label for="password">Your New Password</label>
70
- <Field name="password" type="password" state={state} onChange={onChange.bind(setState)} />
70
+ <Field name="password" type="password" state={state} onChange={(e) => onChange(setState, e)} />
71
71
  </div>
72
72
  <div>
73
73
  <label for="password2">Repeat Your New Password</label>
74
- <Field name="password2" type="password" state={state} onChange={onChange.bind(setState)} />
74
+ <Field name="password2" type="password" state={state} onChange={(e) => onChange(setState, e)} />
75
75
  </div>
76
76
 
77
77
  <div class="mb-14">
@@ -53,14 +53,15 @@ export function Signin() {
53
53
  <form onSubmit={onSubmit}>
54
54
  <div>
55
55
  <label for="email">Email Address</label>
56
- <Field name="email" type="email" state={state} onChange={onChange.bind(setState)} placeholder="Your email address..." />
56
+ <Field name="email" type="email" state={state} onChange={(e) => onChange(setState, e)}
57
+ placeholder="Your email address..." />
57
58
  </div>
58
59
  <div>
59
60
  <div class="flex justify-between">
60
61
  <label for="password">Password</label>
61
62
  <Link to="/reset" class="label underline2">Forgot?</Link>
62
63
  </div>
63
- <Field name="password" type="password" state={state} onChange={onChange.bind(setState)}/>
64
+ <Field name="password" type="password" state={state} onChange={(e) => onChange(setState, e)}/>
64
65
  </div>
65
66
 
66
67
  <div class="mb-14">
@@ -32,20 +32,20 @@ export function Signup() {
32
32
  <div class="grid grid-cols-2 gap-6">
33
33
  <div>
34
34
  <label for="name">Your Name</label>
35
- <Field name="name" placeholder="E.g. Bruce Wayne" state={state} onChange={onChange.bind(setState)} />
35
+ <Field name="name" placeholder="E.g. Bruce Wayne" state={state} onChange={(e) => onChange(setState, e)} />
36
36
  </div>
37
37
  <div>
38
38
  <label for="businessName">Company Name</label>
39
- <Field name="businessName" placeholder="E.g. Wayne Enterprises" state={state} onChange={onChange.bind(setState)} />
39
+ <Field name="businessName" placeholder="E.g. Wayne Enterprises" state={state} onChange={(e) => onChange(setState, e)} />
40
40
  </div>
41
41
  </div>
42
42
  <div>
43
43
  <label for="email">Email Address</label>
44
- <Field name="email" type="email" state={state} onChange={onChange.bind(setState)} placeholder="Your email address..." />
44
+ <Field name="email" type="email" state={state} onChange={(e) => onChange(setState, e)} placeholder="Your email address..." />
45
45
  </div>
46
46
  <div>
47
47
  <label for="password">Password</label>
48
- <Field name="password" type="password" state={state} onChange={onChange.bind(setState)}/>
48
+ <Field name="password" type="password" state={state} onChange={(e) => onChange(setState, e)}/>
49
49
  </div>
50
50
 
51
51
  <div class="mb-14">
@@ -130,7 +130,7 @@ async function webhookSubUpdated(req, res, event) {
130
130
  // Update the subscription on the company
131
131
  try {
132
132
  const subData = event.data.object
133
- // webhook from deleting a company?
133
+ // webhook from deleting a company?
134
134
  if (subData.cancellation_details.comment == 'company deleted') {
135
135
  return res.json({})
136
136
  }
@@ -31,9 +31,10 @@ export function Avatar({ awsUrl, isRound, user, showPlaceholderImage, className
31
31
 
32
32
  return (
33
33
  user.avatar
34
- ? <img class={classes} src={s3Image(awsUrl, user.avatar, 'small')} />
35
- : showPlaceholderImage ? <img class={classes} src={avatarImg} width="30px" />
36
- : <Initials className={classes} icon={{ initials: getInitials(user), hex: getHex(user) }} isRound={isRound} isMedium={true} />
34
+ ? <img class={classes} src={s3Image(awsUrl, user.avatar, 'small')} />
35
+ : showPlaceholderImage
36
+ ? <img class={classes} src={avatarImg} width="30px" />
37
+ : <Initials className={classes} icon={{ initials: getInitials(user), hex: getHex(user) }} isRound={isRound} isMedium={true} />
37
38
  )
38
39
  }
39
40
 
@@ -76,8 +76,9 @@ export function Modal({ show, setShow, children, maxWidth, minHeight, dismissabl
76
76
  >
77
77
  <div
78
78
  class="absolute top-0 right-0 p-3 m-1 cursor-pointer"
79
- onClick={() => { if (dismissable) { setShow(false) }}}>
80
- <SvgX1 />
79
+ onClick={() => { if (dismissable) { setShow(false) }}}
80
+ >
81
+ <SvgX1 />
81
82
  </div>
82
83
  {children}
83
84
  </div>
@@ -32,8 +32,8 @@ export function Sidebar({ Logo, menu, links }: SidebarProps) {
32
32
  'fixed inset-y-0 z-50 flex flex-col ease-in-out lg:left-0 lg:translate-x-0 lg:!delay-0 lg:!duration-0 ' +
33
33
  (
34
34
  sidebarOpen
35
- ? 'left-0 translate-x-[0px] sidebar-transition '
36
- : 'left-[-100%] translate-x-[-100%] sidebar-transition-delay '
35
+ ? 'left-0 translate-x-[0px] sidebar-transition '
36
+ : 'left-[-100%] translate-x-[-100%] sidebar-transition-delay '
37
37
  ) +
38
38
  sidebarWidth
39
39
  }>
@@ -55,8 +55,8 @@ export function Sidebar({ Logo, menu, links }: SidebarProps) {
55
55
  className={'fixed w-full z-[49] inset-0 bg-gray-900/70 ease-linear lg:hidden ' +
56
56
  (
57
57
  sidebarOpen
58
- ? 'left-0 opacity-100 sidebar-transition '
59
- : 'left-[-100%] opacity-0 sidebar-transition-delay '
58
+ ? 'left-0 opacity-100 sidebar-transition '
59
+ : 'left-[-100%] opacity-0 sidebar-transition-delay '
60
60
  )
61
61
  }
62
62
  />
@@ -14,11 +14,11 @@ export function Tooltip({ text, children, className, classNamePopup, isSmall }:
14
14
  <div class={`${className} relative inline-block align-middle nitro-tooltip`} css={style}>
15
15
  {
16
16
  text
17
- ? <>
18
- <div class="tooltip-trigger ">{children}</div>
19
- <div class={`tooltip-popup ${classNamePopup||''} ${isSmall ? 'is-small' : ''}`}>{text}</div>
20
- </>
21
- : children
17
+ ? <>
18
+ <div class="tooltip-trigger ">{children}</div>
19
+ <div class={`tooltip-popup ${classNamePopup||''} ${isSmall ? 'is-small' : ''}`}>{text}</div>
20
+ </>
21
+ : children
22
22
  }
23
23
  </div>
24
24
  )
@@ -36,76 +36,76 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
36
36
  <div className="flex shrink-0 mt-[2px]">
37
37
  {
38
38
  type !== 'toggle'
39
- ? <div className={`group grid ${_size.checkbox} grid-cols-1`}>
40
- <input
41
- {...props}
42
- id={id}
43
- name={name}
44
- type={type}
45
- className={
46
- `${type === 'radio' ? 'rounded-full' : 'rounded'} col-start-1 row-start-1 appearance-none border border-gray-300 bg-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto ` +
47
- // Default
48
- 'checked:border-blue-600 checked:bg-blue-600 indeterminate:border-blue-600 indeterminate:bg-blue-600 focus-visible:outline-blue-600 ' +
49
- // Variable-selected color defined?
50
- 'checked:!border-variable-selected checked:!bg-variable-selected indeterminate:!border-variable-selected indeterminate:!bg-variable-selected focus-visible:!outline-variable-selected'
51
- }
52
- />
53
- <svg
54
- fill="none"
55
- viewBox="0 0 14 14"
56
- className={`pointer-events-none col-start-1 row-start-1 ${_size.checkbox} self-center justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25`}
57
- >
58
- {
59
- type === 'radio'
60
- ? <circle
61
- // cx={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
62
- // cy={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
63
- // r={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 6}
64
- cx={7}
65
- cy={7}
66
- r={2.5}
67
- className="fill-white opacity-0 group-has-[:checked]:opacity-100"
68
- />
69
- : <>
70
- <path
71
- d="M4 8L6 10L10 4.5"
72
- strokeWidth={2}
73
- strokeLinecap="round"
74
- strokeLinejoin="round"
75
- className="opacity-0 group-has-[:checked]:opacity-100"
76
- />
77
- <path
78
- d="M4 7H10"
79
- strokeWidth={2}
80
- strokeLinecap="round"
81
- strokeLinejoin="round"
82
- className="opacity-0 group-has-[:indeterminate]:opacity-100"
83
- />
84
- </>
85
- }
86
- </svg>
87
- </div>
88
- : <div className="group grid grid-cols-1">
89
- <input
90
- {...props}
91
- id={id}
92
- name={name}
93
- type="checkbox"
94
- class="sr-only peer"
95
- />
96
- <label
97
- for={id}
98
- className={
99
- `col-start-1 row-start-1 relative ${_size.toggleWidth} ${_size.toggleHeight} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${_size.toggleAfterSize} after:transition-all ` +
100
- // Default
101
- 'peer-focus-visible:ring-blue-300 peer-checked:bg-blue-600 ' +
102
- // Variable-selected color defined?
103
- 'peer-focus-visible:!ring-variable-selected peer-checked:!bg-variable-selected '
104
- // Dark mode not used yet...
105
- // 'dark:peer-focus-visible:ring-blue-800 dark:bg-gray-700 dark:border-gray-600 '
106
- }
107
- />
108
- </div>
39
+ ? <div className={`group grid ${_size.checkbox} grid-cols-1`}>
40
+ <input
41
+ {...props}
42
+ id={id}
43
+ name={name}
44
+ type={type}
45
+ className={
46
+ `${type === 'radio' ? 'rounded-full' : 'rounded'} col-start-1 row-start-1 appearance-none border border-gray-300 bg-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto ` +
47
+ // Default
48
+ 'checked:border-blue-600 checked:bg-blue-600 indeterminate:border-blue-600 indeterminate:bg-blue-600 focus-visible:outline-blue-600 ' +
49
+ // Variable-selected color defined?
50
+ 'checked:!border-variable-selected checked:!bg-variable-selected indeterminate:!border-variable-selected indeterminate:!bg-variable-selected focus-visible:!outline-variable-selected'
51
+ }
52
+ />
53
+ <svg
54
+ fill="none"
55
+ viewBox="0 0 14 14"
56
+ className={`pointer-events-none col-start-1 row-start-1 ${_size.checkbox} self-center justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25`}
57
+ >
58
+ {
59
+ type === 'radio'
60
+ ? <circle
61
+ // cx={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
62
+ // cy={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
63
+ // r={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 6}
64
+ cx={7}
65
+ cy={7}
66
+ r={2.5}
67
+ className="fill-white opacity-0 group-has-[:checked]:opacity-100"
68
+ />
69
+ : <>
70
+ <path
71
+ d="M4 8L6 10L10 4.5"
72
+ strokeWidth={2}
73
+ strokeLinecap="round"
74
+ strokeLinejoin="round"
75
+ className="opacity-0 group-has-[:checked]:opacity-100"
76
+ />
77
+ <path
78
+ d="M4 7H10"
79
+ strokeWidth={2}
80
+ strokeLinecap="round"
81
+ strokeLinejoin="round"
82
+ className="opacity-0 group-has-[:indeterminate]:opacity-100"
83
+ />
84
+ </>
85
+ }
86
+ </svg>
87
+ </div>
88
+ : <div className="group grid grid-cols-1">
89
+ <input
90
+ {...props}
91
+ id={id}
92
+ name={name}
93
+ type="checkbox"
94
+ class="sr-only peer"
95
+ />
96
+ <label
97
+ for={id}
98
+ className={
99
+ `col-start-1 row-start-1 relative ${_size.toggleWidth} ${_size.toggleHeight} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${_size.toggleAfterSize} after:transition-all ` +
100
+ // Default
101
+ 'peer-focus-visible:ring-blue-300 peer-checked:bg-blue-600 ' +
102
+ // Variable-selected color defined?
103
+ 'peer-focus-visible:!ring-variable-selected peer-checked:!bg-variable-selected '
104
+ // Dark mode not used yet...
105
+ // 'dark:peer-focus-visible:ring-blue-800 dark:bg-gray-700 dark:border-gray-600 '
106
+ }
107
+ />
108
+ </div>
109
109
  }
110
110
  </div>
111
111
  {text &&
@@ -12,7 +12,7 @@ type DropProps = {
12
12
  /** Field name or path on state (used to match errors), e.g. 'avatar', 'company.avatar' */
13
13
  name: string
14
14
  /** Called when file is selected or dropped */
15
- onChange?: any // (event: { target: { id: string, value: File|FileList } }) => void
15
+ onChange?: (event: { target: { id: string, value: File|FileList } }) => void
16
16
  /** Whether to allow multiple file selection */
17
17
  multiple?: boolean
18
18
  /** State object to get the value and check errors against */
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { format, isValid, parse } from 'date-fns'
2
3
  import { getPrefixWidth } from 'nitro-web/util'
3
4
  import { Calendar, Dropdown } from 'nitro-web'
@@ -6,27 +7,37 @@ type Mode = 'single' | 'multiple' | 'range'
6
7
  type DropdownRef = {
7
8
  setIsActive: (value: boolean) => void
8
9
  }
9
- export type FieldDateProps = React.InputHTMLAttributes<HTMLInputElement> & {
10
+
11
+ type PreFieldDateProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
10
12
  name: string
13
+ mode: Mode
11
14
  id?: string
12
- mode?: Mode
13
15
  showTime?: boolean
14
- // an array is returned for non-single modes
15
- onChange?: (e: { target: { id: string, value: null|number|(null|number)[] } }) => void
16
16
  prefix?: string
17
- value?: null|number|string|(null|number|string)[]
18
17
  numberOfMonths?: number
19
18
  Icon?: React.ReactNode
20
19
  dir?: 'bottom-left'|'bottom-right'|'top-left'|'top-right'
21
20
  }
22
21
 
22
+ // An array is returned for mode = 'multiple' or 'range'
23
+ export type FieldDateProps = (
24
+ | ({ mode: 'single' } & PreFieldDateProps & {
25
+ onChange?: (e: { target: { id: string, value: null|number } }) => void
26
+ value?: null|number|string
27
+ })
28
+ | ({ mode: 'multiple' | 'range' } & PreFieldDateProps & {
29
+ onChange: (e: { target: { id: string, value: (null|number)[] } }) => void
30
+ value?: null|number|string|(null|number|string)[]
31
+ })
32
+ )
33
+
23
34
  type TimePickerProps = {
24
35
  date: Date|null
25
36
  onChange: (mode: Mode, value: number|null) => void
26
37
  }
27
38
 
28
39
  export function FieldDate({
29
- mode='single', onChange, prefix='', value, numberOfMonths, Icon, showTime, dir = 'bottom-left', ...props
40
+ mode, onChange, prefix='', value, numberOfMonths, Icon, showTime, dir = 'bottom-left', ...props
30
41
  }: FieldDateProps) {
31
42
  const localePattern = `d MMM yyyy${showTime && mode == 'single' ? ' hh:mmaa' : ''}`
32
43
  const [prefixWidth, setPrefixWidth] = useState(0)
@@ -51,7 +62,7 @@ export function FieldDate({
51
62
  function onCalendarChange(mode: Mode, value: null|number|(null|number)[]) {
52
63
  if (mode == 'single' && !showTime) dropdownRef.current?.setIsActive(false) // Close the dropdown
53
64
  setInputValue(getInputValue(value))
54
- if (onChange) onChange({ target: { id: id, value: value }})
65
+ if (onChange) onChange({ target: { id: id, value: value as any } })
55
66
  }
56
67
 
57
68
  function getInputValue(dates: Date|number|null|(Date|number|null)[]) {
@@ -82,8 +93,8 @@ export function FieldDate({
82
93
 
83
94
  // Update
84
95
  const value = mode == 'single' ? split[0]?.getTime() ?? null : split.map(d => d?.getTime() ?? null)
85
- if (onChange) onChange({ target: { id, value }})
86
- }
96
+ if (onChange) onChange({ target: { id: id, value: value as any }})
97
+ }
87
98
 
88
99
  return (
89
100
  <Dropdown
@@ -9,7 +9,7 @@ export function Styleguide() {
9
9
  address: '',
10
10
  amount: 100,
11
11
  brandColor: '#F3CA5F',
12
- country: 'us',
12
+ country: 'nz',
13
13
  currency: 'nzd', // can be commented too
14
14
  date: Date.now(),
15
15
  'date-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 33],
@@ -38,12 +38,13 @@ export function Styleguide() {
38
38
  { label: 'Delete' },
39
39
  ]
40
40
 
41
- function onInputChange (e: { target: { id: string, value: unknown } }) {
42
- if ((e.target.id == 'customer' || e.target.id == 'customer2') && e.target.value == '') {
41
+ function onCustomerInputChange (e: { target: { id: string, value: unknown } }) {
42
+ if (e.target.id == 'customer' && e.target.value == '0') {
43
43
  setCustomerSearch('')
44
- e.target.value = null // clear the selected value
44
+ e.target.value = null // clear the select's selected value
45
+ setTimeout(() => alert('Adding new customer...'), 0)
45
46
  }
46
- setState(s => ({ ...s, [e.target.id]: e.target.value }))
47
+ onChange(setState, e)
47
48
  }
48
49
 
49
50
  function onCustomerSearch (search: string) {
@@ -169,7 +170,7 @@ export function Styleguide() {
169
170
  type="country"
170
171
  state={state}
171
172
  options={useMemo(() => getCountryOptions(injectedConfig.countries), [])}
172
- onChange={onInputChange}
173
+ onChange={(e) => onChange(setState, e)}
173
174
  />
174
175
  </div>
175
176
  <div>
@@ -180,16 +181,16 @@ export function Styleguide() {
180
181
  name="customer"
181
182
  type="customer"
182
183
  state={state}
183
- onChange={onInputChange}
184
+ onChange={onCustomerInputChange}
184
185
  onInputChange={onCustomerSearch}
185
186
  options={[
186
187
  {
187
188
  className: 'bb',
188
189
  fixed: true,
189
- value: '',
190
+ value: '0',
190
191
  label: (
191
192
  <>
192
- <b>New Customer</b>
193
+ <b>New Customer</b> (and clear select)
193
194
  {customerSearch ? <> / Add <b>{ucFirst(customerSearch)}</b></> : ''}
194
195
  </>
195
196
  ),
@@ -206,7 +207,7 @@ export function Styleguide() {
206
207
  name="currency"
207
208
  state={state}
208
209
  options={useMemo(() => getCurrencyOptions(injectedConfig.currencies), [])}
209
- onChange={onInputChange}
210
+ onChange={(e) => onChange(setState, e)}
210
211
  />
211
212
  </div>
212
213
  </div>
@@ -215,7 +216,7 @@ export function Styleguide() {
215
216
  <div class="grid grid-cols-3 gap-x-6 mb-4">
216
217
  <div>
217
218
  <label for="firstName">First Name</label>
218
- <Field name="firstName" state={state} onChange={onInputChange} />
219
+ <Field name="firstName" state={state} onChange={(e) => onChange(setState, e)} />
219
220
  </div>
220
221
  <div>
221
222
  <label for="email">Email Address</label>
@@ -238,7 +239,7 @@ export function Styleguide() {
238
239
  </div>
239
240
  <div>
240
241
  <label for="address">Input Error</label>
241
- <Field name="address" placeholder="Address..." state={state} onChange={onInputChange} />
242
+ <Field name="address" placeholder="Address..." state={state} onChange={(e) => onChange(setState, e)} />
242
243
  </div>
243
244
  <div>
244
245
  <label for="description">Description</label>
@@ -246,11 +247,11 @@ export function Styleguide() {
246
247
  </div>
247
248
  <div>
248
249
  <label for="brandColor">Brand Color</label>
249
- <Field name="brandColor" type="color" state={state} iconPos="left" onChange={onInputChange} />
250
+ <Field name="brandColor" type="color" state={state} iconPos="left" onChange={(e) => onChange(setState, e)} />
250
251
  </div>
251
252
  <div>
252
253
  <label for="amount">Amount ({state.amount})</label>
253
- <Field name="amount" type="currency" state={state} currency={state.currency || 'nzd'} onChange={onInputChange}
254
+ <Field name="amount" type="currency" state={state} currency={state.currency || 'nzd'} onChange={(e) => onChange(setState, e)}
254
255
  config={injectedConfig} />
255
256
  </div>
256
257
  </div>
@@ -259,15 +260,15 @@ export function Styleguide() {
259
260
  <div class="grid grid-cols-1 gap-x-6 mb-4 sm:grid-cols-3">
260
261
  <div>
261
262
  <label for="date">Date with time</label>
262
- <Field name="date-time" type="date" showTime={true} state={state} onChange={onInputChange} />
263
+ <Field name="date-time" type="date" mode="single" showTime={true} state={state} onChange={(e) => onChange(setState, e)} />
263
264
  </div>
264
265
  <div>
265
266
  <label for="date-range">Date range with prefix</label>
266
- <Field name="date-range" type="date" mode="range" prefix="Date:" state={state} onChange={onInputChange} />
267
+ <Field name="date-range" type="date" mode="range" prefix="Date:" state={state} onChange={(e) => onChange(setState, e)} />
267
268
  </div>
268
269
  <div>
269
270
  <label for="date">Date (right aligned)</label>
270
- <Field name="date" type="date" state={state} onChange={onInputChange} dir="bottom-right" />
271
+ <Field name="date" type="date" mode="single" state={state} onChange={(e) => onChange(setState, e)} dir="bottom-right" />
271
272
  </div>
272
273
  </div>
273
274
 
@@ -275,13 +276,15 @@ export function Styleguide() {
275
276
  <div class="grid grid-cols-3 gap-x-6 mb-4">
276
277
  <div>
277
278
  <label for="avatar">Avatar</label>
278
- <Drop class="is-small" name="avatar" state={state} onChange={onInputChange} awsUrl={injectedConfig.awsUrl} />
279
+ <Drop class="is-small" name="avatar" state={state} onChange={(e) => onChange(setState, e)} awsUrl={injectedConfig.awsUrl} />
279
280
  </div>
280
281
  <div>
281
282
  <label for="calendar">Calendar</label>
282
- <Calendar mode="range" value={state.calendar} numberOfMonths={1} onChange={(mode, value) => {
283
- onInputChange({ target: { id: 'calendar', value: value } })
284
- }} />
283
+ <Calendar mode="range" value={state.calendar} numberOfMonths={1}
284
+ onChange={(mode, value) => {
285
+ onChange(setState, { target: { id: 'calendar', value: value } })
286
+ }}
287
+ />
285
288
  </div>
286
289
  </div>
287
290
 
@@ -291,7 +294,7 @@ export function Styleguide() {
291
294
  <form class="mb-8 text-left">
292
295
  <div>
293
296
  <label for="firstName2">First Name</label>
294
- <Field name="firstName2" state={state} onChange={onInputChange} />
297
+ <Field name="firstName2" state={state} onChange={(e) => onChange(setState, e)} />
295
298
  </div>
296
299
  <div>
297
300
  <label for="email2">Email Address</label>
@@ -48,16 +48,16 @@ export function SettingsAccount() {
48
48
  <div class="cols cols-6 cols-gap-3">
49
49
  <div class="col">
50
50
  <label for="firstName">First Name(s)</label>
51
- <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={onChange.bind(setState)} />
51
+ <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={(e) => onChange(setState, e)} />
52
52
  </div>
53
53
  <div class="col">
54
54
  <label for="lastName">Last Name</label>
55
- <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={onChange.bind(setState)} />
55
+ <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={(e) => onChange(setState, e)} />
56
56
  </div>
57
57
  <div class="col">
58
58
  <label for="email">Email Address</label>
59
59
  <Field name="email" type="email" placeholder="Your email address..." state={state}
60
- onChange={onChange.bind(setState)} />
60
+ onChange={(e) => onChange(setState, e)} />
61
61
  </div>
62
62
  <div class="col">
63
63
  <Link to="/reset" class="label-right link2 underline2 is-active">Reset Password?</Link>
@@ -65,7 +65,7 @@ export function SettingsBusiness() {
65
65
  type="country"
66
66
  state={state}
67
67
  options={useMemo(() => util.getCountryOptions(injectedConfig.countries), [])}
68
- onChange={onChange.bind(setState)}
68
+ onChange={(e) => onChange(setState, e)}
69
69
  />
70
70
  </div>
71
71
  <div class="col">
@@ -75,37 +75,37 @@ export function SettingsBusiness() {
75
75
  type="country"
76
76
  state={state}
77
77
  options={useMemo(() => util.getCurrencyOptions(injectedConfig.currencies), [])}
78
- onChange={onChange.bind(setState)}
78
+ onChange={(e) => onChange(setState, e)}
79
79
  />
80
80
  </div>
81
81
  <div class="col">
82
82
  <label for="business.name">Trading Name</label>
83
- <Field name="business.name" placeholder="E.g. Wayne Enterprises" state={state} onChange={onChange.bind(setState)} />
83
+ <Field name="business.name" placeholder="E.g. Wayne Enterprises" state={state} onChange={(e) => onChange(setState, e)} />
84
84
  </div>
85
85
  <div class="col">
86
86
  <Link to="#" class="label-right link2 underline2 is-active">Custom Address</Link>
87
87
  <label for="business.address">Address (Start Typing...)</label>
88
- <Field name="business.address.full" placeholder="" state={state} onChange={onChange.bind(setState)} />
88
+ <Field name="business.address.full" placeholder="" state={state} onChange={(e) => onChange(setState, e)} />
89
89
  </div>
90
90
  <div class="col">
91
91
  <label for="business.website">Website</label>
92
- <Field name="business.website" placeholder="https://" state={state} onChange={onChange.bind(setState)} />
92
+ <Field name="business.website" placeholder="https://" state={state} onChange={(e) => onChange(setState, e)} />
93
93
  </div>
94
94
  <div class="col">
95
95
  <label for="business.phone">Mobile Number</label>
96
- <Field name="business.phone" placeholder="" state={state} onChange={onChange.bind(setState)} />
96
+ <Field name="business.phone" placeholder="" state={state} onChange={(e) => onChange(setState, e)} />
97
97
  </div>
98
98
  <div class="col">
99
99
  <Link to="#" class="label-right link2 underline2 is-active">What&apos;s this for?</Link>
100
100
  <label for="tax.number">GST Number</label>
101
101
  <Field class="mb-0" name="tax.number" placeholder="Appears on your documents" state={state}
102
- onChange={onChange.bind(setState)} />
102
+ onChange={(e) => onChange(setState, e)} />
103
103
  </div>
104
104
  <div class="col">
105
105
  <Link to="#" class="label-right link2 underline2 is-active">What&apos;s this for?</Link>
106
106
  <label for="business.number">NZBN</label>
107
107
  <Field class="mb-0" name="business.number" type="text" rows="23" placeholder="Appears on your documents" state={state}
108
- onChange={onChange.bind(setState)} />
108
+ onChange={(e) => onChange(setState, e)} />
109
109
  </div>
110
110
  </div>
111
111
  </form>
@@ -42,7 +42,7 @@ export function SettingsTeamMember ({ showModal, setShowModal }: SettingsTeamMem
42
42
  name="role"
43
43
  isSearchable={false}
44
44
  placeholder="Select a role"
45
- onChange={onChange.bind(setState)}
45
+ onChange={(e) => onChange(setState, e)}
46
46
  state={state}
47
47
  minMenuWidth={460}
48
48
  options={[
@@ -71,16 +71,16 @@ export function SettingsTeamMember ({ showModal, setShowModal }: SettingsTeamMem
71
71
  <label for="email">Email Address</label>
72
72
  <Field
73
73
  name="email" type="email" placeholder="Your email address..." state={state}
74
- onChange={onChange.bind(setState)}
74
+ onChange={(e) => onChange(setState, e)}
75
75
  />
76
76
  </div>
77
77
  <div class="col">
78
78
  <label for="firstName">First Name</label>
79
- <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={onChange.bind(setState)} />
79
+ <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={(e) => onChange(setState, e)} />
80
80
  </div>
81
81
  <div class="col">
82
82
  <label for="lastName">Last Name</label>
83
- <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={onChange.bind(setState)} />
83
+ <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={(e) => onChange(setState, e)} />
84
84
  </div>
85
85
  <div class="col-12">
86
86
  <label for="message">Invitation Message</label>
@@ -88,7 +88,8 @@ export function SettingsTeamMember ({ showModal, setShowModal }: SettingsTeamMem
88
88
  name="message"
89
89
  type="textarea"
90
90
  placeholder={`${user.firstName} is inviting you to collaborate on ${injectedConfig?.name || 'Nitro'}.`}
91
- state={state} onChange={onChange.bind(setState)}
91
+ state={state}
92
+ onChange={(e) => onChange(setState, e)}
92
93
  />
93
94
  </div>
94
95
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
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 🚀",
package/types/util.d.ts CHANGED
@@ -460,21 +460,25 @@ export function omit(obj: {
460
460
  [key: string]: unknown;
461
461
  };
462
462
  /**
463
- * Updates state from an input event, you can also update deep state properties
464
- * @param {ChangeEvent|PathValue} eventOrPathValue
463
+ * Updates state from an input event (deep state properties are supported)
464
+ * E.g. setState(s => ({ ...s, [e.target.id]: e.target.value }))
465
+ *
466
+ * @template T
467
+ * @param {React.Dispatch<React.SetStateAction<T>>} setState
468
+ * @param {{target: {id: string, value: unknown}}|[string, function|unknown]} eventOrPathValue
465
469
  * @param {Function} [beforeSetState] - optional function to run before setting the state
466
- * @returns {Promise<object>}
467
- * @this {function}
470
+ * @returns {Promise<T>}
468
471
  *
469
472
  * @example
470
- * - <input onChange={onChange.bind(setState)} />
471
- * - <input onChange={(e) => onChange.call(setState, e)} />
472
- * - <input onChange={() => onChange.call(setState, ['address.name', 'Joe'])} />
473
- *
474
- * @typedef {import('react').ChangeEvent} ChangeEvent
475
- * @typedef {[string, function|unknown]} PathValue - e.g. ['name.first', (state) => state.myNameHere]
473
+ * - <input onChange={(e) => onChange(setState, e)} />
474
+ * - <input onChange={() => onChange(setState, ['address.name', 'Joe'])} />
476
475
  */
477
- export function onChange(this: Function, eventOrPathValue: ChangeEvent | PathValue, beforeSetState?: Function): Promise<object>;
476
+ export function onChange<T>(setState: React.Dispatch<React.SetStateAction<T>>, eventOrPathValue: {
477
+ target: {
478
+ id: string;
479
+ value: unknown;
480
+ };
481
+ } | [string, Function | unknown], beforeSetState?: Function): Promise<T>;
478
482
  /**
479
483
  * Pads a number
480
484
  * @param {number} [num=0]
@@ -666,14 +670,6 @@ export type Box = {
666
670
  bottomLeft: Point;
667
671
  topRight: Point;
668
672
  };
669
- /**
670
- * Updates state from an input event, you can also update deep state properties
671
- */
672
- export type ChangeEvent = import("react").ChangeEvent;
673
- /**
674
- * - e.g. ['name.first', (state) => state.myNameHere]
675
- */
676
- export type PathValue = [string, Function | unknown];
677
673
  /**
678
674
  * Build image URL from image array or object
679
675
  */
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AAiBA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BC;AAED;;;GAGG;AACH,yBAFa,OAAO,OAAO,EAAE,WAAW,CAevC;AAED;;;;;GAKG;AACH,8BAJW,MAAM,cACN;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,GACrB,MAAM,CAKlB;AAED;;;;;;GAMG;AACH,+BALW,MAAM,oBACN,OAAO,gBACP,OAAO,GACL,MAAM,CAelB;AAED;;;;;GAKG;AACH,sCAJW,MAAM,wBACN,OAAO,GACL,MAAM,CAMlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,iCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;GAMG;AACH,gCALW,MAAM,aACN,MAAM,oBACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;GAIG;AACH,0CAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;;;;GAWG;AACH,2BAVW,MAAM,GAAC,IAAI,WACX,MAAM,aACN,MAAM,GACJ,MAAM,CAsBlB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,gDAbW,MAAM,YACN;IACN,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,CAAA;CACjB,CAuKH;AAED;;;;;GAKG;AACH,yBAJa,CAAC,OACH,CAAC,GACC,CAAC,CAgBb;AAED;;;;;GAKG;AACH,8BAJW,MAAM,GAAC,GAAG,EAAE,QACZ,MAAM,GACJ,OAAO,CAgBnB;AAED;;;;;;;GAOG;AACH,yBANa,CAAC,OACH,CAAC,QACD,MAAM,SACN,OAAO,WAAS,GACd,CAAC,CA8Bb;AAED;;;;;;GAMG;AACH,0BALW;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,GAAC,EAAE,GAAC,IAAI,gCAE5B,MAAM,GACJ,MAAM,GAAC,EAAE,GAAC,IAAI,CAmB1B;AAED;;;;;;;;;GASG;AACH,mCARW,MAAM,GAAC,IAAI,GAAC,IAAI,YAChB,MAAM,SACN,MAAM,QACN,MAAM,GACJ,IAAI,CA+BhB;AAED;;;;;GAKG;AACH,mCAJW,MAAM,iBACN,OAAO,GACL,MAAM,CAMlB;AAED;;;;GAIG;AACH,mCAHW,MAAM,GACJ,MAAM,CAWlB;AAED;;;;;;;;GAQG;AACH,8BAPW,MAAM,QACN;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,qBAC5G,QAAQ,cACR,MAAM,GACJ,QAAQ,CAwEpB;AAED;;;;GAIG;AACH,iCAHW;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GACnC,MAAM,CAIlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,EAAE,CASpB;AAED;;;;GAIG;AACH,6CAHW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAS5D;AAED;;;;GAIG;AACH,+CAHW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAS9C;AAED;;;;;GAKG;AACH,uCAJW,MAAM,iBACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;GAKG;AACH,qCAJW;IAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE,QACvC,MAAM,GACJ,MAAM,CAYlB;AAED;;;;GAIG;AACH,6DAHW,MAAM,GACJ,OAAO,CAAC,OAAO,mBAAmB,EAAE,MAAM,GAAC,IAAI,CAAC,CAI5D;AAED;;;;;;;;;;;GAWG;AACH,wCAHW,aAAa,GACX,UAAU,EAAE,CAiCxB;AAED;;;;;;GAMG;AACH,+BALW,GAAG,EAAE,UACL,OAAO,QACP,MAAM,GACJ,OAAO,CAcnB;AAED;;;;GAIG;AACH,kCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,iCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,oCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,+BAHW,MAAM,GACJ,OAAO,CAMnB;AAED;;;;;GAKG;AACH,8BAJW;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAC,GAAC,IAAI,qBAC7B,OAAO,GACL,OAAO,CASnB;AAED;;;;GAIG;AACH,qCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,+BAHW,OAAO,GACL,OAAO,CAmBnB;AAED;;;;GAIG;AACH,mCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,mCAHW,OAAO,GACL,OAAO,CAKnB;AAED;;;;GAIG;AACH,kCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,mCAHW,OAAO,GACL,OAAO,CAInB;AAED;;;;GAIG;AACH,gCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;GAMG;AACH,kCALW,MAAM,QACN,MAAM,iBACN,OAAO,GACL,MAAM,CAalB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qCAxBW,MAAM,mBACN,KAAK,GAAC,GAAG,aACT,KAAK,GACH,CAAC,KAAK,EAAE,KAAK,CAAC,GAAC,IAAI,CAuC/B;AAED;;;;;;;;;GASG;AACH,qDARW;IACN,IAAI,CAAC,EAAE;QAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC,CAAA;IACjE,QAAQ,CAAC,EAAE;QAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC,CAAA;CAC3C,MACO,MAAM,UACN,MAAM,OA+ChB;AAED;;;;;GAKG;AACH,6CAJW,MAAM,EAAE,UACR,MAAM,EAAE,GACP,MAAM,CAgBjB;AAED;;;;GAIG;AACH,kCAHW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,MACtB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,GAAG;;EAS1C;AAED;;;;;GAKG;AACH,0BAJW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,UAC1B,MAAM,EAAE,GACN;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAStC;AAED;;;;;;;;;;;;;GAaG;AACH,yBAVa,CAAC,YACH,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,oBACvC;IAAC,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,CAAA;CAAC,GAAC,CAAC,MAAM,EAAE,WAAS,OAAO,CAAC,8BAE/D,OAAO,CAAC,CAAC,CAAC,CA2DtB;AAED;;;;;;GAMG;AACH,0BALW,MAAM,YACN,MAAM,eACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;GAIG;AACH,0BAHW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QACtB,MAAM,GAAC,MAAM,GAAC,MAAM,EAAE,GAAC,MAAM,EAAE;;EAiBzC;AAED;;;;;;;GAOG;AACH,0CALW,MAAM,iBACN,OAAO,GACL;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAC,IAAI,CAAA;CAAC,CA+BxC;AAED;;;;GAIG;AACH,kCAHW;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAC,GACtB,MAAM,CAclB;AAED;;;;;;;GAOG;AACH,+BANW,MAAM,SACN;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,UACtB;IAAC,cAAc,CAAC,WAAU;CAAC,cAC3B,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GACjC,OAAO,CAAC,GAAG,CAAC,CAqDxB;AAED;;;;GAIG;AACH,0CAHW,EAAE,GAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,GACrB,EAAE,GAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,CAcnC;AAED;;;;;;;;GAQG;AACH,gCANW,MAAM,gBACN,KAAK,EAAE,GAAC,KAAK,SACb,MAAM,MACN,MAAM,GACJ,MAAM,CAclB;AAED;;;;GAIG;AACH,qCAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;GAOG;AACH,wCANW,MAAM,eACN,MAAM,YACN,MAAM,GACJ,MAAM,CA6ClB;AAED;;;;;GAKG;AACH,uCAJW,MAAM,cACN,OAAO,GACL,MAAM,CAelB;AAED;;;;;GAKG;AACH,gEAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;AAED;;;;GAIG;AACH,oDAFW,aAAa,QAKvB;AAED;;;;;GAKG;AACH,sCAJW;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,EAAE,OACtB,MAAM,GACJ,MAAM,EAAE,CAQpB;AAED;;;;;;;;;;;GAWG;AACH,gDATW,MAAM,YACN;IACL,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACrB,YAoBH;AAED;;;;;GAKG;AACH,wBAJa,CAAC,YACH,CAAC,GAAG,SAAS,GACX,CAAC,CAAC,SAAS,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CASvC;AAED;;;;GAIG;AACH,6BAHW,MAAM,GACJ,MAAM,CAKlB;AAED;;;;GAIG;AACH,gCAHW,MAAM,GACJ,MAAM,CAKlB;;;;yBArzBY;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;;yBACjC;IAAE,MAAM,EAAE,MAAM;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;;;;8BACrC;IAAE,QAAQ,EAAE;QAAE,IAAI,EAAE;YAAE,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE;;;;4BAE7F,KAAK,GAAC,UAAU,EAAE,GAAC,UAAU,GAAC,eAAe,GAAC,MAAM,GAAC,GAAG;;;;oBAqNxD,CAAC,MAAM,EAAE,MAAM,CAAC;;;;kBAChB;IAAC,UAAU,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAA;CAAC;;;;oBAgZpC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC"}
package/util.js CHANGED
@@ -356,10 +356,10 @@ export function debounce(func, wait = 0, options) {
356
356
  return leadingEdge(lastCallTime)
357
357
  }
358
358
  if (maxing) {
359
- // Handle invocations in a tight loop.
360
- clearTimeout(timerId)
361
- timerId = setTimeout(timerExpired, wait)
362
- return invokeFunc(lastCallTime)
359
+ // Handle invocations in a tight loop.
360
+ clearTimeout(timerId)
361
+ timerId = setTimeout(timerExpired, wait)
362
+ return invokeFunc(lastCallTime)
363
363
  }
364
364
  }
365
365
  if (timerId === undefined) {
@@ -1099,24 +1099,20 @@ export function omit (obj, fields) {
1099
1099
  }
1100
1100
 
1101
1101
  /**
1102
- * Updates state from an input event, you can also update deep state properties
1103
- * @param {ChangeEvent|PathValue} eventOrPathValue
1102
+ * Updates state from an input event (deep state properties are supported)
1103
+ * E.g. setState(s => ({ ...s, [e.target.id]: e.target.value }))
1104
+ *
1105
+ * @template T
1106
+ * @param {React.Dispatch<React.SetStateAction<T>>} setState
1107
+ * @param {{target: {id: string, value: unknown}}|[string, function|unknown]} eventOrPathValue
1104
1108
  * @param {Function} [beforeSetState] - optional function to run before setting the state
1105
- * @returns {Promise<object>}
1106
- * @this {function}
1109
+ * @returns {Promise<T>}
1107
1110
  *
1108
1111
  * @example
1109
- * - <input onChange={onChange.bind(setState)} />
1110
- * - <input onChange={(e) => onChange.call(setState, e)} />
1111
- * - <input onChange={() => onChange.call(setState, ['address.name', 'Joe'])} />
1112
- *
1113
- * @typedef {import('react').ChangeEvent} ChangeEvent
1114
- * @typedef {[string, function|unknown]} PathValue - e.g. ['name.first', (state) => state.myNameHere]
1112
+ * - <input onChange={(e) => onChange(setState, e)} />
1113
+ * - <input onChange={() => onChange(setState, ['address.name', 'Joe'])} />
1115
1114
  */
1116
- export function onChange (eventOrPathValue, beforeSetState) {
1117
- if (!isFunction(this)) {
1118
- throw new Error('Missing setState, please either call or bind setState to the function. E.g. onChange.call(setState, e)')
1119
- }
1115
+ export function onChange (setState, eventOrPathValue, beforeSetState) {
1120
1116
  /** @type {unknown|function} */
1121
1117
  let value
1122
1118
  /** @type {string[]} */
@@ -1124,7 +1120,7 @@ export function onChange (eventOrPathValue, beforeSetState) {
1124
1120
  /** @type {boolean} */
1125
1121
  let hasFiles
1126
1122
 
1127
- if (eventOrPathValue instanceof Event && eventOrPathValue.target) {
1123
+ if (typeof eventOrPathValue === 'object' && 'target' in eventOrPathValue) {
1128
1124
  const element = /** @type {HTMLInputElement & {_value?: unknown}} */(eventOrPathValue.target) // we need to assume this is an input
1129
1125
  chunks = (element.id || element.name).split('.')
1130
1126
  hasFiles = !!element.files
@@ -1148,7 +1144,7 @@ export function onChange (eventOrPathValue, beforeSetState) {
1148
1144
 
1149
1145
  // Update state
1150
1146
  return new Promise((resolve) => {
1151
- this((/** @type object */ state) => {
1147
+ setState((state) => {
1152
1148
  /** @type {{[key: string]: any}} */
1153
1149
  const newState = { ...state, ...(hasFiles ? { hasFiles } : {}) }
1154
1150
  let target = newState
@@ -1165,8 +1161,8 @@ export function onChange (eventOrPathValue, beforeSetState) {
1165
1161
  if (beforeSetState) {
1166
1162
  beforeSetState({ newState: newState, fieldName: chunks[i], parent: target })
1167
1163
  }
1168
- resolve(newState)
1169
- return newState
1164
+ resolve(/** @type {T} */(newState))
1165
+ return /** @type {T} */(newState)
1170
1166
  })
1171
1167
  })
1172
1168
  }
@@ -1281,8 +1277,8 @@ export async function request (route, data, event, isLoading) {
1281
1277
  const uri = route.replace(/^(post|put|delete|get) /, '')
1282
1278
  const method =
1283
1279
  /** @type {'post'|'put'|'delete'|'get'} */ (
1284
- (route.match(/^(post|put|delete|get) /)?.[1] || 'post').trim()
1285
- )
1280
+ (route.match(/^(post|put|delete|get) /)?.[1] || 'post').trim()
1281
+ )
1286
1282
 
1287
1283
  // show loading
1288
1284
  if (isLoading) {
@@ -1553,46 +1549,3 @@ export function ucFirst (string) {
1553
1549
  if (!string) return ''
1554
1550
  return string.charAt(0).toUpperCase() + string.slice(1)
1555
1551
  }
1556
-
1557
-
1558
-
1559
-
1560
- //--------------------------------
1561
- /* eslint-disable @typescript-eslint/no-unused-vars */
1562
-
1563
- // const axios2 = axios()
1564
- // const addressSchema2 = addressSchema()
1565
- // const url = buildUrl('https://example.com', { param1: 'value1', param2: 'value2' })
1566
- // const camelCase2 = camelCase('camelCase')
1567
- // const camelCaseToTitle2 = camelCaseToTitle('camelCase')
1568
- // const camelCaseToHypen2 = camelCaseToHypen('camelCase')
1569
- // const capitalise2 = capitalise()
1570
- // const currency2 = currency(1234)
1571
- // const currencyToCents2 = currencyToCents('$12.34')
1572
- // const date2 = date(1234567890)
1573
- // const debounce2 = debounce(() => {}, 1000)
1574
- // const deepCopy2 = deepCopy([])
1575
- // const deepFind2 = deepFind({})
1576
- // const deepSave2 = deepSave({})
1577
- // const each2 = each({})
1578
- // const fileDownload2 = fileDownload('data', 'filename.txt')
1579
- // const formatName2 = formatName('John Smith')
1580
- // const formatSlug2 = formatSlug('John Smith')
1581
- // const formData2 = formData({})
1582
- // const fullName2 = fullName({ firstName: 'John', lastName: 'Smith' })
1583
- // const [firstName, lastName] = fullNameSplit('name')
1584
- // const countries2 = getCountryOptions({ US: { name: 'United States' }, GB: { name: 'United Kingdom' } })
1585
- // const currencies2 = getCurrencyOptions({ USD: { name: 'United States Dollar' }, GBP: { name: 'British Pound' } })
1586
- // const width = getPrefixWidth('£')
1587
- // const directories2 = getDirectories({ join: (...args) => args.join('/') }, 'pwd')
1588
- // const stripeClient = getStripeClientPromise('pk_test')
1589
- // const getResponseErrors2 = getResponseErrors(new Error('test'))
1590
- // const inArray2 = inArray([1, 2, 3], 's')
1591
- // const isArray2 = isArray([1, 2, 3])
1592
-
1593
- // const isObject2 = isObject({})
1594
-
1595
- // const onChange2 = onChange.call(() => {}, { target: {} })
1596
-
1597
- // const queryObject2 = queryObject('?page=1&perPage=10')
1598
- // const queryString2 = queryString({ page: 1, perPage: 10 })