nitro-web 0.0.15 → 0.0.17
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/_example/client/css/index.css +1 -1
- package/_example/client/index.ts +1 -3
- package/_example/components/index.tsx +10 -4
- package/_example/tailwind.config.js +17 -17
- package/client/index.ts +9 -5
- package/components/auth/reset.tsx +4 -4
- package/components/auth/signin.tsx +3 -3
- package/components/auth/signup.tsx +5 -5
- package/components/dashboard/dashboard.tsx +3 -3
- package/components/partials/element/button.tsx +4 -3
- package/components/partials/element/calendar.tsx +108 -0
- package/components/partials/element/modal.tsx +54 -196
- package/components/partials/element/sidebar.tsx +5 -4
- package/components/partials/form/checkbox.tsx +1 -1
- package/components/partials/form/input-color.tsx +21 -20
- package/components/partials/form/input-currency.tsx +51 -35
- package/components/partials/form/input-date.tsx +55 -167
- package/components/partials/form/input.tsx +123 -92
- package/components/partials/form/select.tsx +4 -4
- package/components/partials/styleguide.tsx +85 -43
- package/components/settings/settings-account.tsx +6 -6
- package/components/settings/settings-business.tsx +12 -12
- package/components/settings/settings-team--member.tsx +8 -8
- package/package.json +10 -6
- package/readme.md +11 -7
- package/types/required-globals.d.ts +1 -0
- package/types/util.d.ts +19 -10
- package/types/util.d.ts.map +1 -1
- package/types.ts +5 -3
- package/util.js +22 -14
- package/webpack.config.js +1 -5
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { Drop, Dropdown,
|
|
1
|
+
import { Drop, Dropdown, Field, Select, Button, Checkbox, GithubLink, isDemo, Modal, Calendar } from 'nitro-web'
|
|
2
2
|
import { getCountryOptions, getCurrencyOptions, ucFirst } from 'nitro-web/util'
|
|
3
3
|
import { CheckIcon } from '@heroicons/react/20/solid'
|
|
4
4
|
import { Config } from 'types'
|
|
5
5
|
|
|
6
6
|
export function Styleguide({ config }: { config: Config }) {
|
|
7
7
|
const [customerSearch, setCustomerSearch] = useState('')
|
|
8
|
+
const [showModal1, setShowModal1] = useState(false)
|
|
8
9
|
const [state, setState] = useState({
|
|
9
10
|
address: '',
|
|
10
|
-
country: 'us',
|
|
11
|
-
currency: 'nzd', // can be commented too
|
|
12
11
|
amount: 100,
|
|
13
12
|
brandColor: '#F3CA5F',
|
|
14
|
-
|
|
13
|
+
country: 'us',
|
|
14
|
+
currency: 'nzd', // can be commented too
|
|
15
15
|
date: Date.now(),
|
|
16
|
+
'date-range': [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 33],
|
|
17
|
+
calendar: [Date.now(), Date.now() + 1000 * 60 * 60 * 24 * 8],
|
|
18
|
+
firstName: 'Bruce',
|
|
16
19
|
errors: [
|
|
17
20
|
{ title: 'address', detail: 'Address is required' },
|
|
18
|
-
{ title: 'currency', detail: 'Currency is required' },
|
|
19
21
|
],
|
|
20
22
|
})
|
|
21
23
|
|
|
@@ -52,7 +54,7 @@ export function Styleguide({ config }: { config: Config }) {
|
|
|
52
54
|
<div class="mb-10 text-left max-w-[1100px]">
|
|
53
55
|
<GithubLink filename={__filename} />
|
|
54
56
|
<div class="mb-7">
|
|
55
|
-
<h1 class="h1">
|
|
57
|
+
<h1 class="h1">{isDemo ? 'Design System' : 'Style Guide'}</h1>
|
|
56
58
|
<p>
|
|
57
59
|
Components are styled using
|
|
58
60
|
<a href="https://v3.tailwindcss.com/docs/configuration" class="underline" target="_blank" rel="noreferrer">TailwindCSS</a>.
|
|
@@ -60,33 +62,19 @@ export function Styleguide({ config }: { config: Config }) {
|
|
|
60
62
|
</div>
|
|
61
63
|
|
|
62
64
|
<h2 class="h3">Links</h2>
|
|
63
|
-
<div class="mb-
|
|
65
|
+
<div class="mb-10">
|
|
64
66
|
<a class="mr-2" href="#">Default</a>
|
|
65
67
|
<a class="underline1 is-active mr-2" href="#">Underline1</a>
|
|
66
68
|
<a class="underline2 is-active mr-2" href="#">Underline2</a>
|
|
67
69
|
</div>
|
|
68
70
|
|
|
69
|
-
<h2 class="h3">
|
|
70
|
-
<div class="
|
|
71
|
-
<div>
|
|
72
|
-
<label for="input0">Label</label>
|
|
73
|
-
<Checkbox name="input0" type="checkbox" text="Checkbox" subtext="some additional text here." defaultChecked />
|
|
74
|
-
</div>
|
|
75
|
-
<div>
|
|
76
|
-
<label for="input1">Label</label>
|
|
77
|
-
<Checkbox name="input1" type="radio" text="Radio 1" subtext="some additional text here 1." id="input1-1" class="!mb-0"
|
|
78
|
-
defaultChecked />
|
|
79
|
-
<Checkbox name="input1" type="radio" text="Radio 2" subtext="some additional text here 2." id="input1-2" class="!mt-0" />
|
|
80
|
-
</div>
|
|
81
|
-
<div>
|
|
82
|
-
<label for="input2">Label</label>
|
|
83
|
-
<Checkbox name="input2" type="toggle" text="Toggle sm" subtext="some additional text here." class="!mb-0" defaultChecked />
|
|
84
|
-
<Checkbox name="input3" type="toggle" text="Toggle md" size="md" subtext="some additional text here." />
|
|
85
|
-
</div>
|
|
71
|
+
<h2 class="h3">Modals</h2>
|
|
72
|
+
<div class="flex flex-wrap gap-x-6 gap-y-4 mb-10">
|
|
73
|
+
<div><Button color="primary" onClick={() => setShowModal1(true)}>Modal (default)</Button></div>
|
|
86
74
|
</div>
|
|
87
75
|
|
|
88
76
|
<h2 class="h3">Dropdowns</h2>
|
|
89
|
-
<div class="flex flex-wrap gap-x-6 gap-y-4 mb-
|
|
77
|
+
<div class="flex flex-wrap gap-x-6 gap-y-4 mb-10">
|
|
90
78
|
<div>
|
|
91
79
|
<Dropdown options={options} minWidth="250px">
|
|
92
80
|
<Button IconRight="v" class="gap-x-3">Dropdown</Button>
|
|
@@ -110,7 +98,7 @@ export function Styleguide({ config }: { config: Config }) {
|
|
|
110
98
|
</div>
|
|
111
99
|
|
|
112
100
|
<h2 class="h3">Buttons</h2>
|
|
113
|
-
<div class="flex flex-wrap gap-x-6 gap-y-4 mb-
|
|
101
|
+
<div class="flex flex-wrap gap-x-6 gap-y-4 mb-10">
|
|
114
102
|
<div><Button color="primary">primary (default)</Button></div>
|
|
115
103
|
<div><Button color="secondary">secondary button</Button></div>
|
|
116
104
|
<div><Button color="white">white button</Button></div>
|
|
@@ -124,8 +112,27 @@ export function Styleguide({ config }: { config: Config }) {
|
|
|
124
112
|
<div><Button color="primary" IconRight="v" isLoading>primary isLoading</Button></div>
|
|
125
113
|
</div>
|
|
126
114
|
|
|
115
|
+
<h2 class="h3">Checkboxes</h2>
|
|
116
|
+
<div class="grid grid-cols-3 gap-x-6 mb-4">
|
|
117
|
+
<div>
|
|
118
|
+
<label for="input2">Label</label>
|
|
119
|
+
<Checkbox name="input2" type="toggle" text="Toggle sm" subtext="some additional text here." class="!mb-0" defaultChecked />
|
|
120
|
+
<Checkbox name="input3" type="toggle" text="Toggle md" size="md" subtext="some additional text here." />
|
|
121
|
+
</div>
|
|
122
|
+
<div>
|
|
123
|
+
<label for="input1">Label</label>
|
|
124
|
+
<Checkbox name="input1" type="radio" text="Radio 1" subtext="some additional text here 1." id="input1-1" class="!mb-0"
|
|
125
|
+
defaultChecked />
|
|
126
|
+
<Checkbox name="input1" type="radio" text="Radio 2" subtext="some additional text here 2." id="input1-2" class="!mt-0" />
|
|
127
|
+
</div>
|
|
128
|
+
<div>
|
|
129
|
+
<label for="input0">Label</label>
|
|
130
|
+
<Checkbox name="input0" type="checkbox" text="Checkbox" subtext="some additional text here." defaultChecked />
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
127
134
|
<h2 class="h3">Selects</h2>
|
|
128
|
-
<div class="grid grid-cols-3 lg:grid-cols-3 gap-x-6">
|
|
135
|
+
<div class="grid grid-cols-3 lg:grid-cols-3 gap-x-6 mb-4">
|
|
129
136
|
<div>
|
|
130
137
|
<label for="action">Default</label>
|
|
131
138
|
<Select
|
|
@@ -204,53 +211,88 @@ export function Styleguide({ config }: { config: Config }) {
|
|
|
204
211
|
<div class="grid grid-cols-3 gap-x-6 mb-4">
|
|
205
212
|
<div>
|
|
206
213
|
<label for="firstName">First Name</label>
|
|
207
|
-
<
|
|
214
|
+
<Field name="firstName" state={state} onChange={onInputChange} />
|
|
208
215
|
</div>
|
|
209
216
|
<div>
|
|
210
217
|
<label for="email">Email Address</label>
|
|
211
|
-
<
|
|
218
|
+
<Field name="email" type="email" placeholder="Your email address..."/>
|
|
212
219
|
</div>
|
|
213
220
|
<div>
|
|
214
221
|
<div class="flex justify-between">
|
|
215
222
|
<label for="password">Password</label>
|
|
216
223
|
<a href="#" class="label">Forgot?</a>
|
|
217
224
|
</div>
|
|
218
|
-
<
|
|
225
|
+
<Field name="password" type="password"/>
|
|
219
226
|
</div>
|
|
220
227
|
<div>
|
|
221
228
|
<label for="search">Search</label>
|
|
222
|
-
<
|
|
229
|
+
<Field name="search" type="search" placeholder="Search..." />
|
|
223
230
|
</div>
|
|
224
231
|
<div>
|
|
225
|
-
<label for="filter">Filter</label>
|
|
226
|
-
<
|
|
232
|
+
<label for="filter">Filter by Code</label>
|
|
233
|
+
<Field name="filter" type="filter" iconPos="left" />
|
|
227
234
|
</div>
|
|
228
235
|
<div>
|
|
229
236
|
<label for="address">Input Error</label>
|
|
230
|
-
<
|
|
237
|
+
<Field name="address" placeholder="Address..." state={state} onChange={onInputChange} />
|
|
231
238
|
</div>
|
|
232
|
-
{/* <div>
|
|
233
|
-
<label for="date">Date</label>
|
|
234
|
-
<Input name="date" type="date" prefix="Date:" state={state} onChange={onInputChange} />
|
|
235
|
-
</div> */}
|
|
236
239
|
<div>
|
|
237
|
-
<label for="
|
|
238
|
-
<
|
|
240
|
+
<label for="description">Description</label>
|
|
241
|
+
<Field name="description" type="textarea" rows={2} />
|
|
239
242
|
</div>
|
|
240
243
|
<div>
|
|
241
|
-
<label for="
|
|
242
|
-
<
|
|
244
|
+
<label for="brandColor">Brand Color</label>
|
|
245
|
+
<Field name="brandColor" type="color" state={state} iconPos="left" onChange={onInputChange} />
|
|
243
246
|
</div>
|
|
244
247
|
<div>
|
|
245
248
|
<label for="amount">Amount ({state.amount})</label>
|
|
246
|
-
<
|
|
249
|
+
<Field name="amount" type="currency" state={state} currency={state.currency || 'nzd'} onChange={onInputChange} config={config} />
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<h2 class="h3">Date Inputs</h2>
|
|
254
|
+
<div class="grid grid-cols-3 gap-x-6 mb-4">
|
|
255
|
+
<div>
|
|
256
|
+
<label for="date">Date</label>
|
|
257
|
+
<Field name="date" type="date" state={state} onChange={onInputChange} />
|
|
247
258
|
</div>
|
|
259
|
+
<div>
|
|
260
|
+
<label for="date-range">Date range with prefix</label>
|
|
261
|
+
<Field name="date-range" type="date" mode="range" prefix="Date:" state={state} onChange={onInputChange} />
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<h2 class="h3">File Inputs & Calendar</h2>
|
|
266
|
+
<div class="grid grid-cols-3 gap-x-6 mb-4">
|
|
248
267
|
<div>
|
|
249
268
|
<label for="avatar">Avatar</label>
|
|
250
269
|
<Drop class="is-small" name="avatar" state={state} onChange={onInputChange} awsUrl={config.awsUrl} />
|
|
251
270
|
</div>
|
|
271
|
+
<div>
|
|
272
|
+
<label for="calendar">Calendar</label>
|
|
273
|
+
<Calendar mode="range" value={state.calendar} numberOfMonths={1} onChange={(mode, value) => {
|
|
274
|
+
onInputChange({ target: { id: 'calendar', value: value } })
|
|
275
|
+
}} />
|
|
276
|
+
</div>
|
|
252
277
|
</div>
|
|
253
278
|
|
|
279
|
+
<Modal show={showModal1} setShow={setShowModal1} class="p-9">
|
|
280
|
+
<h3 class="h3">Edit Profile</h3>
|
|
281
|
+
<p class="mb-5">An example modal containing a basic form for editing profiles.</p>
|
|
282
|
+
<form class="mb-8 text-left">
|
|
283
|
+
<div>
|
|
284
|
+
<label for="firstName2">First Name</label>
|
|
285
|
+
<Field name="firstName2" state={state} onChange={onInputChange} />
|
|
286
|
+
</div>
|
|
287
|
+
<div>
|
|
288
|
+
<label for="email2">Email Address</label>
|
|
289
|
+
<Field name="email2" type="email" placeholder="Your email address..."/>
|
|
290
|
+
</div>
|
|
291
|
+
</form>
|
|
292
|
+
<div class="flex justify-end">
|
|
293
|
+
<Button color="primary" onClick={() => setShowModal1(false)}>Save</Button>
|
|
294
|
+
</div>
|
|
295
|
+
</Modal>
|
|
254
296
|
</div>
|
|
255
297
|
)
|
|
256
298
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// todo: finish tailwind conversion
|
|
3
3
|
import * as util from 'nitro-web/util'
|
|
4
4
|
import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
|
|
5
|
-
import { Button, FormError,
|
|
5
|
+
import { Button, FormError, Field, Modal, Topbar, Tabbar } from 'nitro-web'
|
|
6
6
|
|
|
7
7
|
export function SettingsAccount() {
|
|
8
8
|
const isLoading = useState('')
|
|
@@ -48,21 +48,21 @@ 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
|
-
<
|
|
51
|
+
<Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={onChange.bind(setState)} />
|
|
52
52
|
</div>
|
|
53
53
|
<div class="col">
|
|
54
54
|
<label for="lastName">Last Name</label>
|
|
55
|
-
<
|
|
55
|
+
<Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={onChange.bind(setState)} />
|
|
56
56
|
</div>
|
|
57
57
|
<div class="col">
|
|
58
58
|
<label for="email">Email Address</label>
|
|
59
|
-
<
|
|
60
|
-
onChange={onChange(setState)} />
|
|
59
|
+
<Field name="email" type="email" placeholder="Your email address..." state={state}
|
|
60
|
+
onChange={onChange.bind(setState)} />
|
|
61
61
|
</div>
|
|
62
62
|
<div class="col">
|
|
63
63
|
<Link to="/reset" class="label-right link2 underline2 is-active">Reset Password?</Link>
|
|
64
64
|
<label for="password">Password</label>
|
|
65
|
-
<
|
|
65
|
+
<Field name="password" placeholder="•••••••••••" disabled={true} />
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
68
68
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
//@ts-nocheck
|
|
2
2
|
// todo: finish tailwind conversio
|
|
3
3
|
|
|
4
4
|
////// look at the select type error below
|
|
5
5
|
import * as util from 'nitro-web/util'
|
|
6
6
|
import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
|
|
7
|
-
import { Button,
|
|
7
|
+
import { Button, Field, Select, Topbar, Tabbar } from 'nitro-web'
|
|
8
8
|
|
|
9
9
|
export function SettingsBusiness({ config }) {
|
|
10
10
|
const isLoading = useState('')
|
|
@@ -65,7 +65,7 @@ export function SettingsBusiness({ config }) {
|
|
|
65
65
|
type="country"
|
|
66
66
|
state={state}
|
|
67
67
|
options={useMemo(() => util.getCountryOptions(config.countries), [])}
|
|
68
|
-
onChange={onChange(setState)}
|
|
68
|
+
onChange={onChange.bind(setState)}
|
|
69
69
|
/>
|
|
70
70
|
</div>
|
|
71
71
|
<div class="col">
|
|
@@ -75,37 +75,37 @@ export function SettingsBusiness({ config }) {
|
|
|
75
75
|
type="country"
|
|
76
76
|
state={state}
|
|
77
77
|
options={useMemo(() => util.getCurrencyOptions(config.currencies), [])}
|
|
78
|
-
onChange={onChange(setState)}
|
|
78
|
+
onChange={onChange.bind(setState)}
|
|
79
79
|
/>
|
|
80
80
|
</div>
|
|
81
81
|
<div class="col">
|
|
82
82
|
<label for="business.name">Trading Name</label>
|
|
83
|
-
<
|
|
83
|
+
<Field name="business.name" placeholder="E.g. Wayne Enterprises" state={state} onChange={onChange.bind(setState)} />
|
|
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
|
-
<
|
|
88
|
+
<Field name="business.address.full" placeholder="" state={state} onChange={onChange.bind(setState)} />
|
|
89
89
|
</div>
|
|
90
90
|
<div class="col">
|
|
91
91
|
<label for="business.website">Website</label>
|
|
92
|
-
<
|
|
92
|
+
<Field name="business.website" placeholder="https://" state={state} onChange={onChange.bind(setState)} />
|
|
93
93
|
</div>
|
|
94
94
|
<div class="col">
|
|
95
95
|
<label for="business.phone">Mobile Number</label>
|
|
96
|
-
<
|
|
96
|
+
<Field name="business.phone" placeholder="" state={state} onChange={onChange.bind(setState)} />
|
|
97
97
|
</div>
|
|
98
98
|
<div class="col">
|
|
99
99
|
<Link to="#" class="label-right link2 underline2 is-active">What's this for?</Link>
|
|
100
100
|
<label for="tax.number">GST Number</label>
|
|
101
|
-
<
|
|
102
|
-
onChange={onChange(setState)} />
|
|
101
|
+
<Field class="mb-0" name="tax.number" placeholder="Appears on your documents" state={state}
|
|
102
|
+
onChange={onChange.bind(setState)} />
|
|
103
103
|
</div>
|
|
104
104
|
<div class="col">
|
|
105
105
|
<Link to="#" class="label-right link2 underline2 is-active">What's this for?</Link>
|
|
106
106
|
<label for="business.number">NZBN</label>
|
|
107
|
-
<
|
|
108
|
-
onChange={onChange(setState)} />
|
|
107
|
+
<Field class="mb-0" name="business.number" type="text" rows="23" placeholder="Appears on your documents" state={state}
|
|
108
|
+
onChange={onChange.bind(setState)} />
|
|
109
109
|
</div>
|
|
110
110
|
</div>
|
|
111
111
|
</form>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// todo: finish tailwind conversion
|
|
3
|
-
import { Button, FormError,
|
|
3
|
+
import { Button, FormError, Field, Modal, Select } from 'nitro-web'
|
|
4
4
|
import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
|
|
5
5
|
|
|
6
6
|
export function SettingsTeamMember ({ showModal, setShowModal }) {
|
|
@@ -38,7 +38,7 @@ export function SettingsTeamMember ({ showModal, setShowModal }) {
|
|
|
38
38
|
name="role"
|
|
39
39
|
isSearchable={false}
|
|
40
40
|
placeholder="Select a role"
|
|
41
|
-
onChange={onChange(setState)}
|
|
41
|
+
onChange={onChange.bind(setState)}
|
|
42
42
|
state={state}
|
|
43
43
|
minMenuWidth={460}
|
|
44
44
|
options={[
|
|
@@ -65,26 +65,26 @@ export function SettingsTeamMember ({ showModal, setShowModal }) {
|
|
|
65
65
|
</div>
|
|
66
66
|
<div class="col">
|
|
67
67
|
<label for="email">Email Address</label>
|
|
68
|
-
<
|
|
68
|
+
<Field
|
|
69
69
|
name="email" type="email" placeholder="Your email address..." state={state}
|
|
70
|
-
onChange={onChange(setState)}
|
|
70
|
+
onChange={onChange.bind(setState)}
|
|
71
71
|
/>
|
|
72
72
|
</div>
|
|
73
73
|
<div class="col">
|
|
74
74
|
<label for="firstName">First Name</label>
|
|
75
|
-
<
|
|
75
|
+
<Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={onChange.bind(setState)} />
|
|
76
76
|
</div>
|
|
77
77
|
<div class="col">
|
|
78
78
|
<label for="lastName">Last Name</label>
|
|
79
|
-
<
|
|
79
|
+
<Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={onChange.bind(setState)} />
|
|
80
80
|
</div>
|
|
81
81
|
<div class="col-12">
|
|
82
82
|
<label for="message">Invitation Message</label>
|
|
83
|
-
<
|
|
83
|
+
<Field
|
|
84
84
|
name="message"
|
|
85
85
|
type="textarea"
|
|
86
86
|
placeholder={`${user.firstName} is inviting you to collaborate on Nitro.`}
|
|
87
|
-
state={state} onChange={onChange(setState)}
|
|
87
|
+
state={state} onChange={onChange.bind(setState)}
|
|
88
88
|
/>
|
|
89
89
|
</div>
|
|
90
90
|
</div>
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
|
-
"version": "0.0.
|
|
6
|
+
"version": "0.0.17",
|
|
7
7
|
"main": "./client/index.ts",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"keywords": [
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"dev": "npm run dev -w example",
|
|
38
|
-
"dev:client": "npm run dev:client -w example",
|
|
39
|
-
"dev:client-only": "isStatic=true npm run dev:client -w example",
|
|
38
|
+
"dev:client": "isDemo=true npm run dev:client -w example",
|
|
39
|
+
"dev:client-only": "isDemo=true isStatic=true npm run dev:client -w example",
|
|
40
40
|
"dev:server": "npm run dev:server -w example",
|
|
41
|
-
"build": "isStatic=true npm run build -w example",
|
|
41
|
+
"build": "isDemo=true isStatic=true npm run build -w example",
|
|
42
42
|
"major": "npm run types && standard-version --release-as major && npm publish",
|
|
43
43
|
"minor": "npm run types && standard-version --release-as minor && npm publish",
|
|
44
44
|
"patch": "npm run types && standard-version --release-as patch && npm publish",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"passport": "^0.4.1",
|
|
68
68
|
"passport-local": "^1.0.0",
|
|
69
69
|
"react-currency-input-field": "^3.8.0",
|
|
70
|
-
"react-day-picker": "^
|
|
70
|
+
"react-day-picker": "^9.6.4",
|
|
71
71
|
"react-number-format": "^5.4.0",
|
|
72
72
|
"react-router-dom": "6.24.1",
|
|
73
73
|
"react-select": "^5.9.0",
|
|
@@ -107,5 +107,9 @@
|
|
|
107
107
|
]
|
|
108
108
|
},
|
|
109
109
|
"author": "",
|
|
110
|
-
"license": "ISC"
|
|
110
|
+
"license": "ISC",
|
|
111
|
+
"devDependencies": {
|
|
112
|
+
"@types/lodash": "^4.17.15",
|
|
113
|
+
"lodash": "^4.17.21"
|
|
114
|
+
}
|
|
111
115
|
}
|
package/readme.md
CHANGED
|
@@ -11,7 +11,7 @@ npm i nitro-web
|
|
|
11
11
|
### Install
|
|
12
12
|
|
|
13
13
|
1. Copy ./_example into your project
|
|
14
|
-
2. In package.json, replace `"nitro-web": "file:.."` with `"nitro-web": "~0.0.
|
|
14
|
+
2. In package.json, replace `"nitro-web": "file:.."` with `"nitro-web": "~0.0.17"`
|
|
15
15
|
3. In package.json, replace `"../.eslintrc.json"` with `"./node_modules/nitro-web/.eslintrc.json"`
|
|
16
16
|
4. Run `npm i`
|
|
17
17
|
|
|
@@ -31,21 +31,25 @@ const server = await setupRouter(config)
|
|
|
31
31
|
server.listen(3001, '0.0.0.0')
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### Run
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
+
# Running in development (watching for changes)
|
|
37
38
|
npm run dev:server # run and watch the nodemon server
|
|
38
39
|
npm run dev:client # run and watch the webpack dev server
|
|
39
|
-
npm run dev # or
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Building for production
|
|
40
|
+
npm run dev # or run and watch both the server and client
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
# Building for production
|
|
45
43
|
npm run build
|
|
46
44
|
npm run start
|
|
47
45
|
```
|
|
48
46
|
|
|
47
|
+
### Nitro Development
|
|
48
|
+
|
|
49
|
+
The same run commands can be used in ./ which are actually executed in ./example/ via npm workspaces (`-w` flag).
|
|
50
|
+
|
|
51
|
+
If util.js is updated, you must run `npm run types` to update the types file.
|
|
52
|
+
|
|
49
53
|
### Versions
|
|
50
54
|
|
|
51
55
|
- Express `^4.17`
|
|
@@ -7,6 +7,7 @@ import { CSSInterpolation } from '@emotion/serialize'
|
|
|
7
7
|
declare global {
|
|
8
8
|
/** Webpack injected config variables */
|
|
9
9
|
const INJECTED: Record<string, string|boolean|object>
|
|
10
|
+
const ISDEMO: boolean
|
|
10
11
|
/** Webpack svg loader */
|
|
11
12
|
module '*.svg' {
|
|
12
13
|
const content: React.FC<React.SVGProps<SVGElement>>
|
package/types/util.d.ts
CHANGED
|
@@ -78,7 +78,13 @@ export function getCurrencyOptions(currencies: any): {
|
|
|
78
78
|
value: string;
|
|
79
79
|
label: any;
|
|
80
80
|
}[];
|
|
81
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Get the width of a prefix
|
|
83
|
+
* @param {string} prefix
|
|
84
|
+
* @param {number} paddingRight
|
|
85
|
+
* @returns {number}
|
|
86
|
+
*/
|
|
87
|
+
export function getPrefixWidth(prefix: string, paddingRight?: number): number;
|
|
82
88
|
export function getDirectories(path: any, pwd: any): {
|
|
83
89
|
clientDir: any;
|
|
84
90
|
componentsDir: any;
|
|
@@ -99,7 +105,12 @@ export function isEmpty(obj: any, truthyValuesOnly: any): boolean;
|
|
|
99
105
|
export function isFunction(variable: any): boolean;
|
|
100
106
|
export function isHex24(value: any): boolean;
|
|
101
107
|
export function isNumber(variable: any): boolean;
|
|
102
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Checks if a variable is an object
|
|
110
|
+
* @param {unknown} variable
|
|
111
|
+
* @returns {boolean}
|
|
112
|
+
*/
|
|
113
|
+
export function isObject(variable: unknown): boolean;
|
|
103
114
|
export function isRegex(variable: any): boolean;
|
|
104
115
|
export function isString(variable: any): boolean;
|
|
105
116
|
export function lcFirst(string: any): any;
|
|
@@ -135,16 +146,14 @@ export function objectMap(object: any, fn: any): {};
|
|
|
135
146
|
export function omit(obj: any, fields: any): any;
|
|
136
147
|
/**
|
|
137
148
|
* Updates state from an input event, you can also update deep state properties
|
|
138
|
-
* @param {
|
|
139
|
-
*
|
|
140
|
-
* {
|
|
141
|
-
* {Event} - pass the event object, e.g. <input onChange={_onChange}>
|
|
142
|
-
* {Array} - pass an array with [path, value], e.g. <input onChange={() => _onChange(['name', 'Joe'])}>
|
|
149
|
+
* @param {Event|Array[{string},{string|number|fn}]}
|
|
150
|
+
* {Event} - pass the event object e.g. <input onChange={(e) => onChange.call(setState, e)}>
|
|
151
|
+
* {Array} - pass an array with [path, value] e.g. <input onChange={(e) => onChange.call(setState, e, ['name', 'Joe'])}>
|
|
143
152
|
* @param {Function} [beforeSetState] - optional function to run before setting the state
|
|
144
|
-
*
|
|
145
|
-
* @return {
|
|
153
|
+
* @this {Function} setState
|
|
154
|
+
* @return {Promise({state, chunks, target})}
|
|
146
155
|
*/
|
|
147
|
-
export function onChange(
|
|
156
|
+
export function onChange(this: Function, event: any, beforeSetState?: Function): Promise<any>;
|
|
148
157
|
export function pad(num: any, padLeft: any, fixedRight: any): any;
|
|
149
158
|
export function pick(obj: any, keys: any): {};
|
|
150
159
|
export function queryObject(search: any, assignTrue: any): any;
|
package/types/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BC;AAED,6DAaC;AAED,4DAQC;AAED,iFAaC;AAED,0EAIC;AAED,gDAEC;AAED,0CAEC;AAED,qFAQC;AAED,uDAIC;AAED,iEAoBC;AAED;;;;EAgIC;AAED,wCASC;AAED,mDAYC;AAED,+DAyBC;AAED,iEAeC;AAED,kFA2BC;AAED,gEAIC;AAED,6CASC;AAED,qEAsEC;AAED,8CAGC;AAED,kDAQC;AAED;;;;IAOC;AAED;;;IAOC;AAED,
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BC;AAED,6DAaC;AAED,4DAQC;AAED,iFAaC;AAED,0EAIC;AAED,gDAEC;AAED,0CAEC;AAED,qFAQC;AAED,uDAIC;AAED,iEAoBC;AAED;;;;EAgIC;AAED,wCASC;AAED,mDAYC;AAED,+DAyBC;AAED,iEAeC;AAED,kFA2BC;AAED,gEAIC;AAED,6CASC;AAED,qEAsEC;AAED,8CAGC;AAED,kDAQC;AAED;;;;IAOC;AAED;;;IAOC;AAED;;;;;GAKG;AACH,uCAJW,MAAM,iBACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;EAUC;AAED,sDAYC;AAED,uEAEC;AAED,kDAsBC;AAED,+DAaC;AAED,0DAEC;AAED,+CAEC;AAED,kDAEC;AAED,6CAIC;AAED,kEAOC;AAED,mDAEC;AAED,6CAiBC;AAED,iDAEC;AAED;;;;GAIG;AACH,mCAHW,OAAO,GACL,OAAO,CAKnB;AAED,gDAEC;AAED,iDAEC;AAED,0CAEC;AAED,yEAWC;AAED,mFAwCC;AAED;;;;;;;;;;;;;;;;;;;;;;;;EA0CC;AAED,uEAmBC;AAED,oDAKC;AAED,iDAOC;AAED;;;;;;;;GAQG;AACH,8FAyCC;AAED,kEAQC;AAED,8CAeC;AAED,+DAiCC;AAED,8CAcC;AAED,yFAiDC;AAED,oDAYC;AAED,4EAmBC;AAED,kDAUC;AAED,mFAiDC;AAED,oEAaC;AAED,8EAIC;AAED,0DAQC;AAED,uDAMC;AAED,mFAwBC;AAED;;;;EAyBC;AAED,8CAIC;AAED,uCAGC;AAED,0CAGC;AAxoCD,6BAAoC"}
|
package/types.ts
CHANGED
|
@@ -3,8 +3,9 @@ export type Config = {
|
|
|
3
3
|
clientUrl: string
|
|
4
4
|
env: string
|
|
5
5
|
awsUrl?: string
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// needed for input-currency.tsx
|
|
7
|
+
currencies: { [key: string]: { symbol: string, digits: number } }
|
|
8
|
+
countries: { [key: string]: { numberFormats: { currency: string } } }
|
|
8
9
|
googleMapsApiKey?: string
|
|
9
10
|
isStatic?: boolean
|
|
10
11
|
placeholderEmail?: string
|
|
@@ -22,7 +23,8 @@ export type User = {
|
|
|
22
23
|
avatar?: MonasteryImage
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export type
|
|
26
|
+
export type Error = { title: string, detail: string }
|
|
27
|
+
export type Errors = Array<Error> | null
|
|
26
28
|
|
|
27
29
|
export type MonasteryImage = {
|
|
28
30
|
url: string
|
package/util.js
CHANGED
|
@@ -479,8 +479,14 @@ export function getCurrencyOptions (currencies) {
|
|
|
479
479
|
return output
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
|
|
483
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Get the width of a prefix
|
|
484
|
+
* @param {string} prefix
|
|
485
|
+
* @param {number} paddingRight
|
|
486
|
+
* @returns {number}
|
|
487
|
+
*/
|
|
488
|
+
export function getPrefixWidth (prefix, paddingRight=0) {
|
|
489
|
+
if (!prefix) return 0
|
|
484
490
|
const span = document.createElement('span')
|
|
485
491
|
span.classList.add('input-prefix')
|
|
486
492
|
span.style.visibility = 'hidden'
|
|
@@ -614,6 +620,11 @@ export function isNumber (variable) {
|
|
|
614
620
|
return !isNaN(parseFloat(variable)) && isFinite(variable)
|
|
615
621
|
}
|
|
616
622
|
|
|
623
|
+
/**
|
|
624
|
+
* Checks if a variable is an object
|
|
625
|
+
* @param {unknown} variable
|
|
626
|
+
* @returns {boolean}
|
|
627
|
+
*/
|
|
617
628
|
export function isObject (variable) {
|
|
618
629
|
// Excludes null and array's
|
|
619
630
|
return variable !== null && typeof variable === 'object' && !(variable instanceof Array) ? true : false
|
|
@@ -769,19 +780,16 @@ export function omit (obj, fields) {
|
|
|
769
780
|
|
|
770
781
|
/**
|
|
771
782
|
* Updates state from an input event, you can also update deep state properties
|
|
772
|
-
* @param {
|
|
773
|
-
*
|
|
774
|
-
* {
|
|
775
|
-
* {Event} - pass the event object, e.g. <input onChange={_onChange}>
|
|
776
|
-
* {Array} - pass an array with [path, value], e.g. <input onChange={() => _onChange(['name', 'Joe'])}>
|
|
783
|
+
* @param {Event|Array[{string},{string|number|fn}]}
|
|
784
|
+
* {Event} - pass the event object e.g. <input onChange={(e) => onChange.call(setState, e)}>
|
|
785
|
+
* {Array} - pass an array with [path, value] e.g. <input onChange={(e) => onChange.call(setState, e, ['name', 'Joe'])}>
|
|
777
786
|
* @param {Function} [beforeSetState] - optional function to run before setting the state
|
|
778
|
-
*
|
|
779
|
-
* @return {
|
|
787
|
+
* @this {Function} setState
|
|
788
|
+
* @return {Promise({state, chunks, target})}
|
|
780
789
|
*/
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
return onChange.bind(this, setState)
|
|
790
|
+
export function onChange (event, beforeSetState) {
|
|
791
|
+
if (!isFunction(this)) {
|
|
792
|
+
throw new Error('Missing setState, please either call or bind setState to the function. E.g. onChange.call(setState, e)')
|
|
785
793
|
}
|
|
786
794
|
let elem = event.target ? event.target : { id: event[0], value: event[1] }
|
|
787
795
|
let chunks = (elem.id || elem.name).split('.')
|
|
@@ -800,7 +808,7 @@ export function onChange (setState, event, beforeSetState) {
|
|
|
800
808
|
|
|
801
809
|
// Update state
|
|
802
810
|
return new Promise((resolve) => {
|
|
803
|
-
|
|
811
|
+
this((state) => {
|
|
804
812
|
const newState = { ...state, ...(elem.files ? { hasFiles: true } : {}) }
|
|
805
813
|
let target = newState
|
|
806
814
|
for (var i = 0, l = chunks.length; i < l; i++) {
|
package/webpack.config.js
CHANGED
|
@@ -161,11 +161,6 @@ export const getConfig = (config) => {
|
|
|
161
161
|
replace: 'if (false && unsafePseudoClasses',
|
|
162
162
|
},
|
|
163
163
|
},
|
|
164
|
-
{
|
|
165
|
-
test: /styleguide\.html$/i,
|
|
166
|
-
exclude: [/\/server\/email/],
|
|
167
|
-
loader: 'html-loader',
|
|
168
|
-
},
|
|
169
164
|
{
|
|
170
165
|
test: /\.csv$/,
|
|
171
166
|
use: [
|
|
@@ -278,6 +273,7 @@ export const getConfig = (config) => {
|
|
|
278
273
|
],
|
|
279
274
|
}),
|
|
280
275
|
new webpack.DefinePlugin({
|
|
276
|
+
ISDEMO: !!process.env.isDemo,
|
|
281
277
|
INJECTED: JSON.stringify({
|
|
282
278
|
...pick(config, config.inject ? config.inject.split(' ') : []),
|
|
283
279
|
}),
|