nitro-web 0.0.7 → 0.0.9
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/.github/workflows/deploy.yml +36 -0
- package/_example/client/imgs/logo/logo-white.svg +4 -11
- package/_example/client/imgs/logo/logo.svg +4 -11
- package/_example/client/index.html +2 -2
- package/_example/components/index.tsx +13 -22
- package/_example/components/partials/layouts.tsx +5 -1
- package/_example/package.json +6 -3
- package/_example/server/config.js +21 -0
- package/client/app.js +15 -11
- package/client/css/fonts.css +9 -9
- package/client/imgs/avatar.jpg +0 -0
- package/client/imgs/no-image.svg +13 -0
- package/client/index.js +8 -7
- package/components/auth/signin.jsx +2 -10
- package/components/dashboard/dashboard.jsx +31 -0
- package/components/partials/element/avatar.jsx +5 -2
- package/components/partials/element/sidebar.jsx +34 -29
- package/components/partials/form/drop.jsx +2 -1
- package/components/partials/form/select.jsx +3 -33
- package/components/partials/layout/layout1.jsx +9 -3
- package/components/partials/layout/layout2.jsx +2 -2
- package/components/partials/styleguide.jsx +3 -2
- package/package.json +9 -17
- package/readme.md +3 -3
- package/types/client/app.d.ts.map +1 -1
- package/types/client/index.d.ts +3 -2
- package/types/components/auth/signin.d.ts.map +1 -1
- package/types/components/dashboard/dashboard.d.ts +4 -0
- package/types/components/dashboard/dashboard.d.ts.map +1 -0
- package/types/components/partials/element/avatar.d.ts.map +1 -1
- package/types/components/partials/element/sidebar.d.ts +3 -1
- package/types/components/partials/element/sidebar.d.ts.map +1 -1
- package/types/components/partials/form/drop.d.ts.map +1 -1
- package/types/components/partials/layout/layout1.d.ts +11 -2
- package/types/components/partials/layout/layout1.d.ts.map +1 -1
- package/types/components/partials/styleguide.d.ts.map +1 -1
- package/types/util.d.ts +1 -1
- package/types/util.d.ts.map +1 -1
- package/util.js +23 -3
- package/webpack.config.js +39 -4
- package/_example/client/fonts/Roboto-Bold.ttf +0 -0
- package/_example/client/fonts/Roboto-BoldItalic.ttf +0 -0
- package/_example/client/fonts/Roboto-Italic.ttf +0 -0
- package/_example/client/fonts/Roboto-Medium.ttf +0 -0
- package/_example/client/fonts/Roboto-MediumItalic.ttf +0 -0
- package/_example/client/fonts/Roboto-Regular.ttf +0 -0
- package/_example/client/imgs/icons/calendar.svg +0 -3
- package/_example/client/imgs/icons/email.svg +0 -6
- package/_example/client/imgs/icons/eye-open.svg +0 -4
- package/_example/client/imgs/icons/eye.svg +0 -5
- package/_example/client/imgs/icons/filter.svg +0 -7
- package/_example/client/imgs/icons/left-circle.svg +0 -3
- package/_example/client/imgs/icons/left.svg +0 -3
- package/_example/client/imgs/icons/line-options.svg +0 -5
- package/_example/client/imgs/icons/line.svg +0 -3
- package/_example/client/imgs/icons/person.svg +0 -7
- package/_example/client/imgs/icons/plus-circle.svg +0 -5
- package/_example/client/imgs/icons/plus.svg +0 -5
- package/_example/client/imgs/icons/right-circle.svg +0 -3
- package/_example/client/imgs/icons/right.svg +0 -3
- package/_example/client/imgs/icons/search.svg +0 -3
- package/_example/client/imgs/icons/shield.svg +0 -6
- package/_example/client/imgs/icons/tick-circle-solid.svg +0 -8
- package/_example/client/imgs/icons/tick-circle.svg +0 -6
- package/_example/client/imgs/icons/tick.svg +0 -5
- package/_example/client/imgs/icons/up2-small.svg +0 -4
- package/_example/client/imgs/icons/up2.svg +0 -4
- package/_example/client/imgs/icons/updown.svg +0 -6
- package/_example/client/imgs/icons/v-big-dark.svg +0 -3
- package/_example/client/imgs/icons/v-dark.svg +0 -3
- package/_example/client/imgs/icons/v.svg +0 -3
- package/_example/client/imgs/icons/v2-active.svg +0 -6
- package/_example/client/imgs/icons/x1.svg +0 -4
- package/_example/client/imgs/no-image.jpg +0 -0
- package/_example/client/imgs/user.jpg +0 -0
- package/client/imgs/icons/calendar.svg +0 -3
- package/client/imgs/icons/email.svg +0 -6
- package/client/imgs/icons/eye-open.svg +0 -4
- package/client/imgs/icons/eye.svg +0 -5
- package/client/imgs/icons/filter.svg +0 -7
- package/client/imgs/icons/left-circle.svg +0 -3
- package/client/imgs/icons/left.svg +0 -3
- package/client/imgs/icons/line-options.svg +0 -5
- package/client/imgs/icons/line.svg +0 -3
- package/client/imgs/icons/person.svg +0 -7
- package/client/imgs/icons/plus-circle.svg +0 -5
- package/client/imgs/icons/right-circle.svg +0 -3
- package/client/imgs/icons/right.svg +0 -3
- package/client/imgs/icons/search.svg +0 -3
- package/client/imgs/icons/shield.svg +0 -6
- package/client/imgs/icons/tick-circle-solid.svg +0 -8
- package/client/imgs/icons/tick-circle.svg +0 -6
- package/client/imgs/icons/up2-small.svg +0 -4
- package/client/imgs/icons/up2.svg +0 -4
- package/client/imgs/icons/updown.svg +0 -6
- package/client/imgs/icons/v-big-dark.svg +0 -3
- package/client/imgs/icons/v-dark.svg +0 -3
- package/client/imgs/icons/v.svg +0 -3
- package/client/imgs/icons/v2-active.svg +0 -6
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Component: https://tailwindui.com/components/application-ui/application-shells/sidebar#component-a69d85b6237ea2ad506c00ef1cd39a38
|
|
2
2
|
import { Dialog, DialogBackdrop, DialogPanel, TransitionChild } from '@headlessui/react'
|
|
3
|
+
import avatarImg from '../../../client/imgs/avatar.jpg'
|
|
3
4
|
import {
|
|
4
5
|
Bars3Icon,
|
|
5
6
|
HomeIcon,
|
|
@@ -15,7 +16,7 @@ function classNames(...classes) {
|
|
|
15
16
|
return classes.filter(Boolean).join(' ')
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
export function Sidebar({ Logo }) {
|
|
19
|
+
export function Sidebar({ Logo, menu, links }) {
|
|
19
20
|
const [sidebarOpen, setSidebarOpen] = useState(false)
|
|
20
21
|
return (
|
|
21
22
|
<>
|
|
@@ -38,14 +39,14 @@ export function Sidebar({ Logo }) {
|
|
|
38
39
|
</button>
|
|
39
40
|
</div>
|
|
40
41
|
</TransitionChild>
|
|
41
|
-
<SidebarContents Logo={Logo} />
|
|
42
|
+
<SidebarContents Logo={Logo} menu={menu} links={links} />
|
|
42
43
|
</DialogPanel>
|
|
43
44
|
</div>
|
|
44
45
|
</Dialog>
|
|
45
46
|
|
|
46
47
|
{/* Static sidebar for desktop */}
|
|
47
48
|
<div className={`hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:flex-col ${sidebarWidth}`}>
|
|
48
|
-
<SidebarContents Logo={Logo} />
|
|
49
|
+
<SidebarContents Logo={Logo} menu={menu} links={links} />
|
|
49
50
|
</div>
|
|
50
51
|
|
|
51
52
|
{/* mobile sidebar closed */}
|
|
@@ -55,7 +56,7 @@ export function Sidebar({ Logo }) {
|
|
|
55
56
|
</button>
|
|
56
57
|
<div className="flex-1 text-sm/6 font-semibold text-gray-900">Dashboard</div>
|
|
57
58
|
<Link to="#">
|
|
58
|
-
<img alt="" src=
|
|
59
|
+
<img alt="" src={avatarImg} className="size-8 rounded-full bg-gray-50" />
|
|
59
60
|
</Link>
|
|
60
61
|
</div>
|
|
61
62
|
|
|
@@ -64,7 +65,7 @@ export function Sidebar({ Logo }) {
|
|
|
64
65
|
)
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function SidebarContents ({ Logo }) {
|
|
68
|
+
function SidebarContents ({ Logo, menu, links }) {
|
|
68
69
|
const location = useLocation()
|
|
69
70
|
const [{ user }] = sharedStore.useTracked()
|
|
70
71
|
|
|
@@ -74,45 +75,49 @@ function SidebarContents ({ Logo }) {
|
|
|
74
75
|
else return ''
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
const
|
|
78
|
-
{ name: 'Dashboard',
|
|
79
|
-
{ name: '
|
|
80
|
-
{ name: '
|
|
81
|
-
{ name: 'Signout',
|
|
78
|
+
const _menu = menu || [
|
|
79
|
+
{ name: 'Dashboard', to: '/', Icon: HomeIcon },
|
|
80
|
+
{ name: 'Styleguide', to: '/styleguide', Icon: PaintBrushIcon },
|
|
81
|
+
{ name: 'Pricing (example)', to: '/pricing', Icon: UsersIcon },
|
|
82
|
+
{ name: 'Signout', to: '/signout', Icon: ArrowLeftCircleIcon },
|
|
82
83
|
]
|
|
83
84
|
|
|
84
|
-
const
|
|
85
|
-
{
|
|
86
|
-
{
|
|
85
|
+
const _links = links || [
|
|
86
|
+
{ name: 'Team 1', to: '#', initial: 'T' },
|
|
87
|
+
{ name: 'Team 2', to: '#', initial: 'H' },
|
|
87
88
|
]
|
|
88
89
|
|
|
89
90
|
// Sidebar component, swap this element with another sidebar if you like
|
|
90
91
|
return (
|
|
91
92
|
<div className="flex grow flex-col gap-y-8 overflow-y-auto bg-white py-5 px-10 lg:border-r lg:border-gray-200">
|
|
92
93
|
<div className="flex h-16 shrink-0 items-center">
|
|
93
|
-
<
|
|
94
|
+
<Link to="/">
|
|
95
|
+
<Logo alt="Nitro" width="70" height={undefined} />
|
|
96
|
+
</Link>
|
|
94
97
|
</div>
|
|
95
98
|
<nav className="flex flex-1 flex-col">
|
|
96
99
|
<ul role="list" className="flex flex-1 flex-col gap-y-7">
|
|
97
100
|
<li>
|
|
98
101
|
<ul role="list" className="-mx-2 space-y-1">
|
|
99
|
-
{
|
|
102
|
+
{_menu.map((item) => (
|
|
100
103
|
<li key={item.name}>
|
|
101
104
|
<Link
|
|
102
|
-
to={item.
|
|
105
|
+
to={item.to}
|
|
103
106
|
className={classNames(
|
|
104
|
-
isActive(item.
|
|
107
|
+
isActive(item.to)
|
|
105
108
|
? 'bg-gray-50 text-indigo-600'
|
|
106
109
|
: 'text-gray-700 hover:bg-gray-50 hover:text-indigo-600',
|
|
107
110
|
'group flex gap-x-3 items-center rounded-md p-2 text-sm/6 font-semibold'
|
|
108
111
|
)}
|
|
109
112
|
>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
{ item.Icon &&
|
|
114
|
+
<item.Icon
|
|
115
|
+
className={classNames(
|
|
116
|
+
isActive(item.to) ? 'text-indigo-600' : 'text-gray-400 group-hover:text-indigo-600',
|
|
117
|
+
'size-5 shrink-0'
|
|
118
|
+
)}
|
|
119
|
+
/>
|
|
120
|
+
}
|
|
116
121
|
{item.name}
|
|
117
122
|
</Link>
|
|
118
123
|
</li>
|
|
@@ -120,14 +125,14 @@ function SidebarContents ({ Logo }) {
|
|
|
120
125
|
</ul>
|
|
121
126
|
</li>
|
|
122
127
|
<li>
|
|
123
|
-
<div className="text-xs/6 font-semibold text-gray-400">
|
|
128
|
+
<div className="text-xs/6 font-semibold text-gray-400">Other Links</div>
|
|
124
129
|
<ul role="list" className="-mx-2 mt-2 space-y-1">
|
|
125
|
-
{
|
|
130
|
+
{_links.map((team) => (
|
|
126
131
|
<li key={team.name}>
|
|
127
132
|
<Link
|
|
128
|
-
to={team.
|
|
133
|
+
to={team.to}
|
|
129
134
|
className={classNames(
|
|
130
|
-
isActive(team.
|
|
135
|
+
isActive(team.to)
|
|
131
136
|
? 'bg-gray-50 text-indigo-600'
|
|
132
137
|
: 'text-gray-700 hover:bg-gray-50 hover:text-indigo-600',
|
|
133
138
|
'group flex gap-x-3 rounded-md p-2 text-sm/6 font-semibold'
|
|
@@ -135,7 +140,7 @@ function SidebarContents ({ Logo }) {
|
|
|
135
140
|
>
|
|
136
141
|
<span
|
|
137
142
|
className={classNames(
|
|
138
|
-
isActive(team.
|
|
143
|
+
isActive(team.to)
|
|
139
144
|
? 'border-indigo-600 text-indigo-600'
|
|
140
145
|
: 'border-gray-200 text-gray-400 group-hover:border-indigo-600 group-hover:text-indigo-600',
|
|
141
146
|
'flex size-6 shrink-0 items-center justify-center rounded-lg border bg-white text-[0.625rem] font-medium'
|
|
@@ -155,7 +160,7 @@ function SidebarContents ({ Logo }) {
|
|
|
155
160
|
to="#"
|
|
156
161
|
className="flex items-center gap-x-4 px-6 py-3 text-sm/6 font-semibold text-gray-900 hover:bg-gray-50"
|
|
157
162
|
>
|
|
158
|
-
<img alt="" src=
|
|
163
|
+
<img alt="" src={avatarImg} className="size-8 rounded-full bg-gray-50" />
|
|
159
164
|
<span aria-hidden="true" class="truncate1">{user?.name || 'Guest'}</span>
|
|
160
165
|
</Link>
|
|
161
166
|
</li>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isRegex, deepFind, s3Image } from '../../../util.js'
|
|
2
2
|
import { DropHandler } from './drop-handler.jsx'
|
|
3
|
+
import noImage from '../../../client/imgs/no-image.svg'
|
|
3
4
|
|
|
4
5
|
export function Drop({ awsUrl, className, id, name, onChange, multiple, state, ...props }) {
|
|
5
6
|
/**
|
|
@@ -108,7 +109,7 @@ export function Drop({ awsUrl, className, id, name, onChange, multiple, state, .
|
|
|
108
109
|
{
|
|
109
110
|
urls.map((url, i) => (
|
|
110
111
|
<div key={i} class="flex align-items-center gap-1">
|
|
111
|
-
<img src={url} width="100%" />
|
|
112
|
+
<img src={url || noImage} width="100%" />
|
|
112
113
|
</div>
|
|
113
114
|
))
|
|
114
115
|
}
|
|
@@ -261,9 +261,7 @@ function Option(props) {
|
|
|
261
261
|
const DropdownIndicator = (props) => {
|
|
262
262
|
return (
|
|
263
263
|
<components.DropdownIndicator {...props}>
|
|
264
|
-
{/* <img src="/assets/imgs/icons/v.svg" /> */}
|
|
265
264
|
<ChevronDownIcon className="size-6 -my-0.5 -mx-1" />
|
|
266
|
-
{/* <ChevronDownIcon /> */}
|
|
267
265
|
</components.DropdownIndicator>
|
|
268
266
|
)
|
|
269
267
|
}
|
|
@@ -287,8 +285,10 @@ const MultiValueRemove = (props) => {
|
|
|
287
285
|
|
|
288
286
|
function Flag({ flag }) {
|
|
289
287
|
if (!flag) return null
|
|
288
|
+
// todo: public needs to come from webpack
|
|
289
|
+
const publicPath = '/'
|
|
290
290
|
return (
|
|
291
|
-
<span class="flag" style={{ backgroundImage: `url(
|
|
291
|
+
<span class="flag" style={{ backgroundImage: `url(${publicPath}assets/imgs/flags/${flag}.svg)` }} />
|
|
292
292
|
)
|
|
293
293
|
}
|
|
294
294
|
|
|
@@ -324,36 +324,6 @@ const style = () => css`
|
|
|
324
324
|
} */
|
|
325
325
|
|
|
326
326
|
/*
|
|
327
|
-
todo: not yet accounted for (maybe remove)
|
|
328
|
-
|
|
329
|
-
.bb:not(:last-child) {
|
|
330
|
-
// option border
|
|
331
|
-
position: relative;
|
|
332
|
-
margin-bottom: 6px;
|
|
333
|
-
&:after {
|
|
334
|
-
content: "";
|
|
335
|
-
position: absolute;
|
|
336
|
-
bottom: -4px;
|
|
337
|
-
left: 0;
|
|
338
|
-
height: 2px;
|
|
339
|
-
width: 100%;
|
|
340
|
-
background-color: $border-color;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
.bt:not(:first-child) {
|
|
344
|
-
// option border
|
|
345
|
-
position: relative;
|
|
346
|
-
margin-top: 6px;
|
|
347
|
-
&:after {
|
|
348
|
-
content: "";
|
|
349
|
-
position: absolute;
|
|
350
|
-
top: -4px;
|
|
351
|
-
left: 0;
|
|
352
|
-
height: 2px;
|
|
353
|
-
width: 100%;
|
|
354
|
-
background-color: $border-color;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
327
|
.flag {
|
|
358
328
|
// https://github.com/lipis/flag-icons
|
|
359
329
|
flex-shrink: 0;
|
|
@@ -3,8 +3,14 @@ import { Outlet } from 'react-router-dom'
|
|
|
3
3
|
import { Message } from '../element/message.jsx'
|
|
4
4
|
import { Sidebar } from '../element/sidebar.jsx'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Dashboard, app screens (only the <Outlet/> receives `params` and `location`)
|
|
8
|
+
* @param {object} props
|
|
9
|
+
* @param {JSX.Element} props.Logo
|
|
10
|
+
* @param {array} [props.menu] - [{name, to, Icon}]
|
|
11
|
+
* @param {array} [props.links] - [{name, to, initial}]
|
|
12
|
+
*/
|
|
13
|
+
export function Layout1({ Logo, menu, links }) {
|
|
8
14
|
const [store] = sharedStore.useTracked()
|
|
9
15
|
|
|
10
16
|
return (
|
|
@@ -12,7 +18,7 @@ export function Layout1({ Logo }) {
|
|
|
12
18
|
<Message />
|
|
13
19
|
<div class="flex-1">
|
|
14
20
|
<div class="wrapper lg:flex min-h-[100%] w-[100%] bg-[#FDFDFD] shadow-[0_0_40px_0_rgb(237_237_237)]">
|
|
15
|
-
<Sidebar Logo={Logo} />
|
|
21
|
+
<Sidebar Logo={Logo} menu={menu} links={links} />
|
|
16
22
|
<div class="py-10 px-14 flex-1" key={store?.company?._id}>
|
|
17
23
|
<Outlet />
|
|
18
24
|
</div>
|
|
@@ -20,8 +20,8 @@ export function Layout2({ Logo }) {
|
|
|
20
20
|
<div class="wrapper-2 w-full px-5 pb-4 flex items-center text-sm text-[#1F1F1F]">
|
|
21
21
|
<ul class="flex-1 flex gap-4 list-style-none">
|
|
22
22
|
<li><Link class="underline1" to="/">Home</Link></li>
|
|
23
|
-
<li><Link class="underline1" to="/
|
|
24
|
-
<li><Link class="underline1" to="/
|
|
23
|
+
<li><Link class="underline1" to="/about">About</Link></li>
|
|
24
|
+
<li><Link class="underline1" to="/support">Support</Link></li>
|
|
25
25
|
</ul>
|
|
26
26
|
<div>
|
|
27
27
|
2025 © Nitro
|
|
@@ -142,8 +142,9 @@ export function Styleguide({ config }) {
|
|
|
142
142
|
name="multi"
|
|
143
143
|
isMulti={true}
|
|
144
144
|
options={[
|
|
145
|
-
{ value: '
|
|
146
|
-
{ value: '
|
|
145
|
+
{ value: 'blue', label: 'Blue' },
|
|
146
|
+
{ value: 'green', label: 'Green' },
|
|
147
|
+
{ value: 'yellow', label: 'Yellow' },
|
|
147
148
|
]}
|
|
148
149
|
/>
|
|
149
150
|
</div>
|
package/package.json
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"name": "nitro-web",
|
|
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.9",
|
|
6
7
|
"main": "./client/index.js",
|
|
7
8
|
"types": "./types/client/index.d.ts",
|
|
8
9
|
"type": "module",
|
|
@@ -40,11 +41,13 @@
|
|
|
40
41
|
"scripts": {
|
|
41
42
|
"dev": "npm run dev -w example",
|
|
42
43
|
"dev:client": "npm run dev:client -w example",
|
|
44
|
+
"dev:client-only": "isDemo=true npm run dev:client -w example",
|
|
43
45
|
"dev:server": "npm run dev:server -w example",
|
|
44
|
-
"build": "npm run build -w example",
|
|
46
|
+
"build": "isDemo=true npm run build -w example",
|
|
45
47
|
"major": "standard-version --release-as major && npm publish",
|
|
46
48
|
"minor": "standard-version --release-as minor && npm publish",
|
|
47
49
|
"patch": "standard-version --release-as patch && npm publish",
|
|
50
|
+
"start": "npm run start -w example",
|
|
48
51
|
"types": "tsc client/*.js components/**/*.jsx --declaration --declarationMap --allowJs --emitDeclarationOnly --jsx react-jsx --esModuleInterop --outDir types"
|
|
49
52
|
},
|
|
50
53
|
"dependencies": {
|
|
@@ -85,26 +88,18 @@
|
|
|
85
88
|
"monastery": "^3.5.2",
|
|
86
89
|
"react": "^18.3.1",
|
|
87
90
|
"react-dom": "^18.3.1",
|
|
88
|
-
"stripe": "^9.16.0"
|
|
91
|
+
"stripe": "^9.16.0",
|
|
92
|
+
"tailwindcss": "^3.4.17",
|
|
93
|
+
"twin.macro": "^3.4.1"
|
|
89
94
|
},
|
|
90
95
|
"devDependencies": {
|
|
91
96
|
"@emotion/eslint-plugin": "^11.11.0",
|
|
92
|
-
"@emotion/react": "^11.11.4",
|
|
93
|
-
"@emotion/styled": "^11.11.4",
|
|
94
|
-
"@types/react": "^19.0.2",
|
|
95
|
-
"@types/react-dom": "^19.0.2",
|
|
96
|
-
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
97
|
-
"@typescript-eslint/parser": "^8.18.1",
|
|
98
97
|
"babel-eslint": "^10.0.3",
|
|
99
98
|
"eslint": "^8.57.1",
|
|
100
99
|
"eslint-plugin-import": "^2.26.0",
|
|
101
100
|
"eslint-plugin-react": "^7.19.0",
|
|
102
101
|
"eslint-plugin-react-hooks": "^4.0.0",
|
|
103
|
-
"
|
|
104
|
-
"standard-version": "^9.3.2",
|
|
105
|
-
"tailwindcss": "^3.4.17",
|
|
106
|
-
"twin.macro": "^3.4.1",
|
|
107
|
-
"typescript": "^5.7.3"
|
|
102
|
+
"standard-version": "^9.3.2"
|
|
108
103
|
},
|
|
109
104
|
"engines": {
|
|
110
105
|
"node": "^18"
|
|
@@ -125,9 +120,6 @@
|
|
|
125
120
|
}
|
|
126
121
|
]
|
|
127
122
|
},
|
|
128
|
-
"jest": {
|
|
129
|
-
"transform": {}
|
|
130
|
-
},
|
|
131
123
|
"author": "",
|
|
132
124
|
"license": "ISC"
|
|
133
125
|
}
|
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": "
|
|
14
|
+
2. In package.json, replace `"nitro-web": "file:.."` with `"nitro-web": "~0.0.9"`
|
|
15
15
|
3. In package.json, replace `"../.eslintrc.json"` with `"./node_modules/nitro-web/.eslintrc.json"`
|
|
16
16
|
4. Run `npm i`
|
|
17
17
|
|
|
@@ -66,5 +66,5 @@ npm run start
|
|
|
66
66
|
|
|
67
67
|
### Package notes
|
|
68
68
|
|
|
69
|
-
- Added twin.macro is required as a
|
|
70
|
-
- Added tailwindcss^3 as a
|
|
69
|
+
- Added twin.macro is required as a peer dependency to ./.
|
|
70
|
+
- Added tailwindcss^3 as a peer dependency to ./ to stop tailwind^4.0.0 from being installed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../client/app.js"],"names":[],"mappings":"AAKA,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../client/app.js"],"names":[],"mappings":"AAKA,mEAeC"}
|
package/types/client/index.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export * from "../util.js";
|
|
|
3
3
|
export * as util from "../util.js";
|
|
4
4
|
export { Signin } from "../components/auth/signin.jsx";
|
|
5
5
|
export { Signup } from "../components/auth/signup.jsx";
|
|
6
|
+
export { Dashboard } from "../components/dashboard/dashboard.jsx";
|
|
7
|
+
export { NotFound } from "../components/partials/not-found.jsx";
|
|
8
|
+
export { Styleguide } from "../components/partials/styleguide.jsx";
|
|
6
9
|
export { Accordion } from "../components/partials/element/accordion.jsx";
|
|
7
10
|
export { Avatar } from "../components/partials/element/avatar.jsx";
|
|
8
11
|
export { Button } from "../components/partials/element/button.jsx";
|
|
@@ -22,7 +25,5 @@ export { Toggle } from "../components/partials/form/toggle.jsx";
|
|
|
22
25
|
export { Layout1 } from "../components/partials/layout/layout1.jsx";
|
|
23
26
|
export { Layout2 } from "../components/partials/layout/layout2.jsx";
|
|
24
27
|
export { IsFirstRender } from "../components/partials/is-first-render.js";
|
|
25
|
-
export { NotFound } from "../components/partials/not-found.jsx";
|
|
26
|
-
export { Styleguide } from "../components/partials/styleguide.jsx";
|
|
27
28
|
export { ResetInstructions, ResetPassword } from "../components/auth/reset.jsx";
|
|
28
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signin.d.ts","sourceRoot":"","sources":["../../../components/auth/signin.jsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"signin.d.ts","sourceRoot":"","sources":["../../../components/auth/signin.jsx"],"names":[],"mappings":"AAMA;;4CAmEC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../components/dashboard/dashboard.jsx"],"names":[],"mappings":"AAEA;;4CAsBC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/avatar.jsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/avatar.jsx"],"names":[],"mappings":"AAKA;;;;;;4CAwBC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/sidebar.jsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/sidebar.jsx"],"names":[],"mappings":"AAkBA;;;;4CA+CC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../components/partials/form/drop.jsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../components/partials/form/drop.jsx"],"names":[],"mappings":"AAIA;;;;;;;;;4CAyHC"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard, app screens (only the <Outlet/> receives `params` and `location`)
|
|
3
|
+
* @param {object} props
|
|
4
|
+
* @param {JSX.Element} props.Logo
|
|
5
|
+
* @param {array} [props.menu] - [{name, to, Icon}]
|
|
6
|
+
* @param {array} [props.links] - [{name, to, initial}]
|
|
7
|
+
*/
|
|
8
|
+
export function Layout1({ Logo, menu, links }: {
|
|
9
|
+
Logo: JSX.Element;
|
|
10
|
+
menu?: any[];
|
|
11
|
+
links?: any[];
|
|
3
12
|
}): import("react/jsx-runtime").JSX.Element;
|
|
4
13
|
//# sourceMappingURL=layout1.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout1.d.ts","sourceRoot":"","sources":["../../../../components/partials/layout/layout1.jsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"layout1.d.ts","sourceRoot":"","sources":["../../../../components/partials/layout/layout1.jsx"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,+CAJG;IAA2B,IAAI,EAAvB,GAAG,CAAC,OAAO;IACG,IAAI;IACJ,KAAK;CAC7B,2CAiBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleguide.d.ts","sourceRoot":"","sources":["../../../components/partials/styleguide.jsx"],"names":[],"mappings":"AASA;;
|
|
1
|
+
{"version":3,"file":"styleguide.d.ts","sourceRoot":"","sources":["../../../components/partials/styleguide.jsx"],"names":[],"mappings":"AASA;;4CAkPC"}
|
package/types/util.d.ts
CHANGED
|
@@ -84,11 +84,11 @@ export function getDirectories(path: any, pwd: any): {
|
|
|
84
84
|
componentsDir: any;
|
|
85
85
|
distDir: any;
|
|
86
86
|
emailTemplateDir: any;
|
|
87
|
-
fontsDir: any;
|
|
88
87
|
imgsDir: any;
|
|
89
88
|
tmpDir: any;
|
|
90
89
|
};
|
|
91
90
|
export function getLink(obj: any, query: any): string;
|
|
91
|
+
export function getPublicPath(env: any, homepage: any, publicPath: any): string;
|
|
92
92
|
export function getStripeClientPromise(stripePublishableKey: any): any;
|
|
93
93
|
export function getResponseErrors(errs: any): any;
|
|
94
94
|
export function inArray(array: any, key: any, value: any): any;
|
package/types/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,mFAUC;AAED
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,mFAUC;AAED;;;;;;;EAUC;AAED,sDAYC;AAED,gFAmBC;AAED,uEAEC;AAED,kDAsBC;AAED,+DAaC;AAED,0DAEC;AAED,+CAEC;AAED,kDAEC;AAED,6CAIC;AAED,kEAOC;AAED,mDAEC;AAED,6CAiBC;AAED,iDAEC;AAED,iDAGC;AAED,gDAEC;AAED,iDAEC;AAED,0CAEC;AAED,yEAWC;AAED,mFAwCC;AAED;;;;;;;;;;;;;;;;;;;;;;;;EA0CC;AAED,uEAmBC;AAED,oDAKC;AAED,iDAOC;AAED,8EAqDC;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;AArpCD,6BAAoC"}
|
package/util.js
CHANGED
|
@@ -497,7 +497,6 @@ export function getDirectories (path, pwd) {
|
|
|
497
497
|
componentsDir: path.join(_pwd, process.env.componentsDir || 'components', '/'),
|
|
498
498
|
distDir: path.join(_pwd, process.env.distDir || ((process.env.clientDir || 'client') + '/dist'), '/'),
|
|
499
499
|
emailTemplateDir: path.join(_pwd, process.env.emailTemplateDir || 'server/email', '/'),
|
|
500
|
-
fontsDir: path.join(_pwd, (process.env.clientDir || 'client'), 'fonts', '/'),
|
|
501
500
|
imgsDir: path.join(_pwd, (process.env.clientDir || 'client'), 'imgs', '/'),
|
|
502
501
|
tmpDir: path.join(_pwd, process.env.tmpDir || 'tmp', '/'),
|
|
503
502
|
}
|
|
@@ -517,6 +516,27 @@ export function getLink (obj, query) {
|
|
|
517
516
|
return queryString(newQueryObj) || '?'
|
|
518
517
|
}
|
|
519
518
|
|
|
519
|
+
export function getPublicPath(env, homepage, publicPath) {
|
|
520
|
+
/**
|
|
521
|
+
* Returns public path used for webapck (we can't use relative paths)
|
|
522
|
+
* @param {string} env - 'development', 'staging', 'production'
|
|
523
|
+
* @param {string} publicPath - proces.env.publicPath
|
|
524
|
+
* @param {string} homepage - package.json homepage
|
|
525
|
+
*/
|
|
526
|
+
if (publicPath) {
|
|
527
|
+
const publicPathObj = new URL(publicPath, 'https://domain.com')
|
|
528
|
+
return publicPathObj.pathname
|
|
529
|
+
|
|
530
|
+
} else if (homepage) {
|
|
531
|
+
const homepageObj = new URL(homepage, 'https://domain.com')
|
|
532
|
+
if (env === 'development') return '/'
|
|
533
|
+
else return homepageObj.pathname
|
|
534
|
+
|
|
535
|
+
} else {
|
|
536
|
+
return '/'
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
520
540
|
export function getStripeClientPromise (stripePublishableKey) {
|
|
521
541
|
return global.stripeClientPromise || (global.stripeClientPromise = loadStripe(stripePublishableKey))
|
|
522
542
|
}
|
|
@@ -977,7 +997,7 @@ export function s3Image (awsUrl, image, size='full', i) {
|
|
|
977
997
|
let usingMilliseconds = true
|
|
978
998
|
|
|
979
999
|
if (!isObject(image)) image = (image && image[i]) ? image[i] : null
|
|
980
|
-
if (!image) return '
|
|
1000
|
+
if (!image) return ''
|
|
981
1001
|
// Alway use preview if available
|
|
982
1002
|
if (image.base64) return image.base64
|
|
983
1003
|
// Wait a moment before the different sizes are generated by lambda
|
|
@@ -1155,4 +1175,4 @@ export function trim (string) {
|
|
|
1155
1175
|
export function ucFirst (string) {
|
|
1156
1176
|
if (!string) return ''
|
|
1157
1177
|
return string.charAt(0).toUpperCase() + string.slice(1)
|
|
1158
|
-
}
|
|
1178
|
+
}
|
package/webpack.config.js
CHANGED
|
@@ -2,6 +2,7 @@ import axios from '@hokify/axios'
|
|
|
2
2
|
import axiosRetry from 'axios-retry'
|
|
3
3
|
import autoprefixer from 'autoprefixer'
|
|
4
4
|
import CleanTerminalPlugin from 'clean-terminal-webpack-plugin'
|
|
5
|
+
import { CleanWebpackPlugin } from 'clean-webpack-plugin'
|
|
5
6
|
import CopyWebpackPlugin from 'copy-webpack-plugin'
|
|
6
7
|
import HtmlWebpackPlugin from 'html-webpack-plugin'
|
|
7
8
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
|
@@ -15,7 +16,7 @@ import postcssImport from 'postcss-import'
|
|
|
15
16
|
import postcssNested from 'postcss-nested'
|
|
16
17
|
import postcssFor from 'postcss-for'
|
|
17
18
|
import { createRequire } from 'module'
|
|
18
|
-
import { getDirectories } from './util.js'
|
|
19
|
+
import { getDirectories, getPublicPath } from './util.js'
|
|
19
20
|
|
|
20
21
|
const _require = createRequire(import.meta.url)
|
|
21
22
|
const pick = (object, list) => list.reduce((o, e) => ((o[e] = object[e]), o), {})
|
|
@@ -29,7 +30,8 @@ axiosRetry(axios, {
|
|
|
29
30
|
|
|
30
31
|
// process.traceDeprecation = true
|
|
31
32
|
export const getConfig = (config) => {
|
|
32
|
-
const { clientDir, componentsDir, distDir, imgsDir
|
|
33
|
+
const { clientDir, componentsDir, distDir, imgsDir } = getDirectories(path, config.pwd)
|
|
34
|
+
const publicPath = getPublicPath(config.env, config.homepage, config.publicPath)
|
|
33
35
|
|
|
34
36
|
return (env, argv) => [{
|
|
35
37
|
devtool: isBuild ? false : 'source-map',
|
|
@@ -177,6 +179,13 @@ export const getConfig = (config) => {
|
|
|
177
179
|
},
|
|
178
180
|
],
|
|
179
181
|
},
|
|
182
|
+
{
|
|
183
|
+
test: /\.(png|jpe?g|gif|woff|woff2|ttf|eot)$/i,
|
|
184
|
+
type: 'asset/resource',
|
|
185
|
+
generator: {
|
|
186
|
+
filename: 'assets/images/[name].[ext][query]',//[hash][ext][query]
|
|
187
|
+
},
|
|
188
|
+
},
|
|
180
189
|
{
|
|
181
190
|
test: /\.svg$/,
|
|
182
191
|
use: [
|
|
@@ -196,6 +205,7 @@ export const getConfig = (config) => {
|
|
|
196
205
|
},
|
|
197
206
|
},
|
|
198
207
|
},
|
|
208
|
+
// 'removeDimensions', (dont need this, just use width/height={undefined} if required)
|
|
199
209
|
// {
|
|
200
210
|
// name: 'addClassesToSVGElement',
|
|
201
211
|
// params: {
|
|
@@ -237,7 +247,7 @@ export const getConfig = (config) => {
|
|
|
237
247
|
// Because of this we manually need to prefix all output filenames with `assets/`.
|
|
238
248
|
filename: `assets/bundle.[name]${isBuild ? '.[contenthash]' : ''}.js`,
|
|
239
249
|
path: distDir,
|
|
240
|
-
publicPath:
|
|
250
|
+
publicPath: publicPath,
|
|
241
251
|
},
|
|
242
252
|
performance: {
|
|
243
253
|
hints: false,
|
|
@@ -257,16 +267,17 @@ export const getConfig = (config) => {
|
|
|
257
267
|
},
|
|
258
268
|
plugins: [
|
|
259
269
|
// new (require('webpack-bundle-analyzer').BundleAnalyzerPlugin)(),
|
|
270
|
+
new CleanWebpackPlugin(),
|
|
260
271
|
new CopyWebpackPlugin({
|
|
261
272
|
patterns: [
|
|
262
273
|
{ from: imgsDir + 'favicon.png', to: './favicon.png' },
|
|
263
274
|
{ from: imgsDir, to: './assets/imgs' },
|
|
264
|
-
{ from: fontsDir, to: './assets/fonts' },
|
|
265
275
|
],
|
|
266
276
|
}),
|
|
267
277
|
new webpack.DefinePlugin({
|
|
268
278
|
CONFIG: JSON.stringify({
|
|
269
279
|
...pick(config, config.inject ? config.inject.split(' ') : []),
|
|
280
|
+
isDemo: process.env.isDemo,
|
|
270
281
|
version: config.version,
|
|
271
282
|
}),
|
|
272
283
|
}),
|
|
@@ -276,6 +287,7 @@ export const getConfig = (config) => {
|
|
|
276
287
|
}),
|
|
277
288
|
new MiniCssExtractPlugin({ filename: `assets/bundle.[name]${isBuild ? '.[contenthash]' : ''}.css` }),
|
|
278
289
|
new HtmlWebpackPlugin({ template: clientDir + 'index.html', filename: distDir + 'index.html' }),
|
|
290
|
+
new InterpolateHtmlPlugin(HtmlWebpackPlugin, { PUBLIC_PATH: publicPath }),
|
|
279
291
|
new CleanTerminalPlugin({ skipFirstRun: true }),
|
|
280
292
|
// !isBuild && new ReactRefreshWebpackPlugin({ overlay: false }),
|
|
281
293
|
].filter(Boolean),
|
|
@@ -301,3 +313,26 @@ export const getConfig = (config) => {
|
|
|
301
313
|
},
|
|
302
314
|
}]
|
|
303
315
|
}
|
|
316
|
+
|
|
317
|
+
class InterpolateHtmlPlugin {
|
|
318
|
+
constructor(htmlWebpackPlugin, replacements) {
|
|
319
|
+
this.htmlWebpackPlugin = htmlWebpackPlugin
|
|
320
|
+
this.replacements = replacements
|
|
321
|
+
}
|
|
322
|
+
apply(compiler) {
|
|
323
|
+
compiler.hooks.compilation.tap('InterpolateHtmlPlugin', compilation => {
|
|
324
|
+
this.htmlWebpackPlugin
|
|
325
|
+
.getHooks(compilation)
|
|
326
|
+
.afterTemplateExecution.tap('InterpolateHtmlPlugin', data => {
|
|
327
|
+
// Run HTML through a series of user-specified string replacements.
|
|
328
|
+
for (const key in this.replacements) {
|
|
329
|
+
const value = this.replacements[key]
|
|
330
|
+
data.html = data.html.replace(
|
|
331
|
+
new RegExp('{' + key + '}', 'g'),
|
|
332
|
+
value
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
})
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|