nitro-web 0.0.203 → 0.0.205

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.
@@ -6,10 +6,10 @@ import { type FieldCurrencyProps, FieldCurrency } from './field-currency'
6
6
  import { type FieldDateProps, FieldDate } from './field-date'
7
7
  import { twMerge, getErrorFromState, deepFind } from 'nitro-web/util'
8
8
  import { Errors, type Error } from 'nitro-web/types'
9
- import { MailIcon, CalendarIcon, FunnelIcon, SearchIcon, EyeIcon, EyeOffIcon, ClockIcon } from 'lucide-react'
10
- import { memo } from 'react'
9
+ import { MailIcon, CalendarIcon, FunnelIcon, SearchIcon, EyeIcon, EyeOffIcon, ClockIcon, PaperclipIcon } from 'lucide-react'
10
+ import { memo, useState } from 'react'
11
11
 
12
- type FieldType = 'text' | 'number' | 'password' | 'email' | 'filter' | 'search' | 'textarea' | 'currency' | 'date' | 'color'
12
+ type FieldType = 'text' | 'number' | 'password' | 'email' | 'filter' | 'search' | 'textarea' | 'currency' | 'date' | 'color' | 'file'
13
13
  type InputProps = React.InputHTMLAttributes<HTMLInputElement>
14
14
  type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>
15
15
  type FieldExtraProps = {
@@ -44,6 +44,7 @@ export type FieldProps = (
44
44
  | ({ type: 'currency' } & FieldCurrencyProps & FieldExtraProps)
45
45
  | ({ type: 'color' } & FieldColorProps & FieldExtraProps)
46
46
  | ({ type: 'date' } & FieldDateProps & FieldExtraProps)
47
+ | ({ type: 'file' } & InputProps & FieldExtraProps)
47
48
  )
48
49
  type IsFieldCachedProps = {
49
50
  name: string
@@ -74,11 +75,13 @@ function FieldBase({ state, icon, iconPos: ip, errorTitle, inputClassName, ...pr
74
75
  return type == 'password' ? 'password' : (type == 'textarea' ? 'textarea' : (type == 'number' ? 'number' : 'text'))
75
76
  })
76
77
 
77
- // Value: Input is always controlled if state is passed in
78
- if (typeof props.value !== 'undefined') value = props.value
79
- else if (typeof state == 'object') {
80
- const v = deepFind(state, props.name) ?? ''
81
- value = v
78
+ // Value: Input is always controlled if state is passed in (file inputs stay uncontrolled)
79
+ if (type !== 'file') {
80
+ if (typeof props.value !== 'undefined') value = props.value
81
+ else if (typeof state == 'object') {
82
+ const v = deepFind(state, props.name) ?? ''
83
+ value = v
84
+ }
82
85
  }
83
86
 
84
87
  // Icon
@@ -101,6 +104,8 @@ function FieldBase({ state, icon, iconPos: ip, errorTitle, inputClassName, ...pr
101
104
  Icon = <IconWrapper iconPos={iconPos} icon={icon || <ClockIcon />} className="size-[14px] size-input-icon" />
102
105
  } else if (type == 'date') {
103
106
  Icon = <IconWrapper iconPos={iconPos} icon={icon || <CalendarIcon />} className="size-[14px] size-input-icon" />
107
+ } else if (type == 'file') {
108
+ Icon = <IconWrapper iconPos={iconPos} icon={icon || <PaperclipIcon />} className="size-[14px] size-input-icon" />
104
109
  } else if (icon) {
105
110
  Icon = <IconWrapper iconPos={iconPos} icon={icon} className="size-[14px] size-input-icon" />
106
111
  }
@@ -141,6 +146,13 @@ function FieldBase({ state, icon, iconPos: ip, errorTitle, inputClassName, ...pr
141
146
  <FieldDate {...props} {...commonProps} Icon={Icon} />
142
147
  </FieldContainer>
143
148
  )
149
+ } else if (type == 'file') {
150
+ // const { className, ...rest } = props as Extract<FieldProps, { type: 'file' }>
151
+ return (
152
+ <FieldContainer error={error} className={props.className}>
153
+ {Icon}<input {...props} {...commonProps} type="file" />
154
+ </FieldContainer>
155
+ )
144
156
  }
145
157
  }
146
158
 
@@ -162,7 +174,7 @@ function getInputClasses({ error, Icon, iconPos, type }: { error?: Error, Icon?:
162
174
  const px = 'px-[12px]'
163
175
  const py = 'py-[9px] py-input-y'
164
176
  return (
165
- 'block col-start-1 row-start-1 w-full rounded-md bg-white disabled:bg-input-disabled-bg text-input-base outline outline-1 -outline-offset-1 ' +
177
+ 'block col-start-1 row-start-1 w-full rounded-md bg-white disabled:cursor-not-allowed disabled:bg-input-disabled-bg text-input-base outline outline-1 -outline-offset-1 ' +
166
178
  'placeholder:text-input-placeholder focus:outline focus:outline-2 focus:-outline-offset-2 (' +
167
179
  `${py} ${px} ` +
168
180
  (iconPos == 'right' && Icon ? 'pr-[32px] pr-input-x-icon pl-input-x ' : '') +
@@ -173,6 +185,12 @@ function getInputClasses({ error, Icon, iconPos, type }: { error?: Error, Icon?:
173
185
  ? 'text-danger-foreground outline-danger focus:outline-danger '
174
186
  : 'text-input outline-input-border focus:outline-input-border-focus disabled:text-input-disabled ') +
175
187
  (iconPos == 'right' ? 'justify-self-start ' : 'justify-self-end ') +
188
+ (type == 'file'
189
+ ? 'file:inline-flex file:shrink-0 file:cursor-pointer file:items-center file:justify-center ' +
190
+ 'file:rounded file:border-0 file:bg-transparent file:py-[0.1em] file:my-[-0.1em] file:px-[0.4em] file:ml-[-0.4em] file:mr-[0.7em] file:text-input-base file:font-medium file:text-input ' +
191
+ 'file:outline-none file:bg-gray-100 hover:file:bg-gray-200 '
192
+ : ''
193
+ ) +
176
194
  'nitro-input'
177
195
  )
178
196
  }
@@ -228,7 +246,7 @@ export function isFieldCached(prev: IsFieldCachedProps, next: IsFieldCachedProps
228
246
  }
229
247
 
230
248
  const style = css`
231
- input {
249
+ input:not([type='file']) {
232
250
  appearance: textfield;
233
251
  -moz-appearance: textfield;
234
252
  }
@@ -591,6 +591,10 @@ export function Styleguide({ className, elements, children, currencies, groups }
591
591
  <label for="firstName">First Name (disabled)</label>
592
592
  <Field name="firstName" state={state} onChange={(e) => onChange(e, setState)} disabled />
593
593
  </div>
594
+ <div>
595
+ <label for="file">File Input</label>
596
+ <Field name="file" type="file" state={state} onChange={(e) => onChange(e, setState)} />
597
+ </div>
594
598
  </div>
595
599
  </div>
596
600
  )}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.203",
3
+ "version": "0.0.205",
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 🚀",
@@ -62,7 +62,7 @@
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@stripe/stripe-js": "^1.34.0",
65
- "monastery": "^3.5.9",
65
+ "monastery": "^3.5.12",
66
66
  "stripe": "^9.16.0"
67
67
  },
68
68
  "_peers-are-packages-that-will-be-used-in-the-host-repo-too": "",
@@ -188,6 +188,7 @@ async function sendWithMailgun(settings, html) {
188
188
  // Supports batch sending via recipientVariables, limit 1000 emails
189
189
  // https://documentation.mailgun.com/en/latest/user_manual.html?highlight=batch%20sending#batch-sending
190
190
  let processedhtml = await processTemplate(settings, html)
191
+ // console.log(settings)
191
192
  if (settings.test) return processedhtml
192
193
 
193
194
  return new Promise((resolve, reject) => {
@@ -1,5 +1,5 @@
1
1
  // @ts-nocheck
2
- import { addressSchema, fullName } from 'nitro-web/util'
2
+ import { addressSchema, fullName, _toArray } from 'nitro-web/util'
3
3
 
4
4
  export default {
5
5
 
@@ -12,6 +12,7 @@ export default {
12
12
  number: { type: 'string' },
13
13
  phone: { type: 'string' },
14
14
  website: { type: 'string', isURL: true },
15
+ schema: { required: true },
15
16
  },
16
17
  status: { type: 'string', default: 'active', enum: ['active', 'unpaid', 'deleted'], required: true },
17
18
  users: [{
@@ -29,6 +30,15 @@ export default {
29
30
  findBL: ['invites.token'],
30
31
  updateBL: ['status', 'users'],
31
32
 
33
+ // beforeValidate: [
34
+ // async function (data) {
35
+ // const rows = toArray(data)
36
+ // for (const data of rows) {
37
+ // // if (data.name) data.name = data.name.trim()
38
+ // }
39
+ // },
40
+ // ],
41
+
32
42
  afterFind: [
33
43
  async function (data) {
34
44
  if (!data) return
@@ -79,6 +79,10 @@ declare namespace _default {
79
79
  export { type_5 as type };
80
80
  export let isURL: boolean;
81
81
  }
82
+ namespace schema {
83
+ let required_3: boolean;
84
+ export { required_3 as required };
85
+ }
82
86
  }
83
87
  namespace status {
84
88
  let type_6: string;
@@ -87,8 +91,8 @@ declare namespace _default {
87
91
  export { _default_2 as default };
88
92
  let _enum: string[];
89
93
  export { _enum as enum };
90
- let required_3: boolean;
91
- export { required_3 as required };
94
+ let required_4: boolean;
95
+ export { required_4 as required };
92
96
  }
93
97
  let users: {
94
98
  _id: {
@@ -1 +1 @@
1
- {"version":3,"file":"company.d.ts","sourceRoot":"","sources":["../../../server/models/company.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+CgB,sCAEX;QACc;;;;;;;;;;;;;;;;;;;;;;;YAyBd"}
1
+ {"version":3,"file":"company.d.ts","sourceRoot":"","sources":["../../../server/models/company.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyDgB,sCAEX;QACc;;;;;;;;;;;;;;;;;;;;;;;YAyBd"}