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.
Files changed (99) hide show
  1. package/.github/workflows/deploy.yml +36 -0
  2. package/_example/client/imgs/logo/logo-white.svg +4 -11
  3. package/_example/client/imgs/logo/logo.svg +4 -11
  4. package/_example/client/index.html +2 -2
  5. package/_example/components/index.tsx +13 -22
  6. package/_example/components/partials/layouts.tsx +5 -1
  7. package/_example/package.json +6 -3
  8. package/_example/server/config.js +21 -0
  9. package/client/app.js +15 -11
  10. package/client/css/fonts.css +9 -9
  11. package/client/imgs/avatar.jpg +0 -0
  12. package/client/imgs/no-image.svg +13 -0
  13. package/client/index.js +8 -7
  14. package/components/auth/signin.jsx +2 -10
  15. package/components/dashboard/dashboard.jsx +31 -0
  16. package/components/partials/element/avatar.jsx +5 -2
  17. package/components/partials/element/sidebar.jsx +34 -29
  18. package/components/partials/form/drop.jsx +2 -1
  19. package/components/partials/form/select.jsx +3 -33
  20. package/components/partials/layout/layout1.jsx +9 -3
  21. package/components/partials/layout/layout2.jsx +2 -2
  22. package/components/partials/styleguide.jsx +3 -2
  23. package/package.json +9 -17
  24. package/readme.md +3 -3
  25. package/types/client/app.d.ts.map +1 -1
  26. package/types/client/index.d.ts +3 -2
  27. package/types/components/auth/signin.d.ts.map +1 -1
  28. package/types/components/dashboard/dashboard.d.ts +4 -0
  29. package/types/components/dashboard/dashboard.d.ts.map +1 -0
  30. package/types/components/partials/element/avatar.d.ts.map +1 -1
  31. package/types/components/partials/element/sidebar.d.ts +3 -1
  32. package/types/components/partials/element/sidebar.d.ts.map +1 -1
  33. package/types/components/partials/form/drop.d.ts.map +1 -1
  34. package/types/components/partials/layout/layout1.d.ts +11 -2
  35. package/types/components/partials/layout/layout1.d.ts.map +1 -1
  36. package/types/components/partials/styleguide.d.ts.map +1 -1
  37. package/types/util.d.ts +1 -1
  38. package/types/util.d.ts.map +1 -1
  39. package/util.js +23 -3
  40. package/webpack.config.js +39 -4
  41. package/_example/client/fonts/Roboto-Bold.ttf +0 -0
  42. package/_example/client/fonts/Roboto-BoldItalic.ttf +0 -0
  43. package/_example/client/fonts/Roboto-Italic.ttf +0 -0
  44. package/_example/client/fonts/Roboto-Medium.ttf +0 -0
  45. package/_example/client/fonts/Roboto-MediumItalic.ttf +0 -0
  46. package/_example/client/fonts/Roboto-Regular.ttf +0 -0
  47. package/_example/client/imgs/icons/calendar.svg +0 -3
  48. package/_example/client/imgs/icons/email.svg +0 -6
  49. package/_example/client/imgs/icons/eye-open.svg +0 -4
  50. package/_example/client/imgs/icons/eye.svg +0 -5
  51. package/_example/client/imgs/icons/filter.svg +0 -7
  52. package/_example/client/imgs/icons/left-circle.svg +0 -3
  53. package/_example/client/imgs/icons/left.svg +0 -3
  54. package/_example/client/imgs/icons/line-options.svg +0 -5
  55. package/_example/client/imgs/icons/line.svg +0 -3
  56. package/_example/client/imgs/icons/person.svg +0 -7
  57. package/_example/client/imgs/icons/plus-circle.svg +0 -5
  58. package/_example/client/imgs/icons/plus.svg +0 -5
  59. package/_example/client/imgs/icons/right-circle.svg +0 -3
  60. package/_example/client/imgs/icons/right.svg +0 -3
  61. package/_example/client/imgs/icons/search.svg +0 -3
  62. package/_example/client/imgs/icons/shield.svg +0 -6
  63. package/_example/client/imgs/icons/tick-circle-solid.svg +0 -8
  64. package/_example/client/imgs/icons/tick-circle.svg +0 -6
  65. package/_example/client/imgs/icons/tick.svg +0 -5
  66. package/_example/client/imgs/icons/up2-small.svg +0 -4
  67. package/_example/client/imgs/icons/up2.svg +0 -4
  68. package/_example/client/imgs/icons/updown.svg +0 -6
  69. package/_example/client/imgs/icons/v-big-dark.svg +0 -3
  70. package/_example/client/imgs/icons/v-dark.svg +0 -3
  71. package/_example/client/imgs/icons/v.svg +0 -3
  72. package/_example/client/imgs/icons/v2-active.svg +0 -6
  73. package/_example/client/imgs/icons/x1.svg +0 -4
  74. package/_example/client/imgs/no-image.jpg +0 -0
  75. package/_example/client/imgs/user.jpg +0 -0
  76. package/client/imgs/icons/calendar.svg +0 -3
  77. package/client/imgs/icons/email.svg +0 -6
  78. package/client/imgs/icons/eye-open.svg +0 -4
  79. package/client/imgs/icons/eye.svg +0 -5
  80. package/client/imgs/icons/filter.svg +0 -7
  81. package/client/imgs/icons/left-circle.svg +0 -3
  82. package/client/imgs/icons/left.svg +0 -3
  83. package/client/imgs/icons/line-options.svg +0 -5
  84. package/client/imgs/icons/line.svg +0 -3
  85. package/client/imgs/icons/person.svg +0 -7
  86. package/client/imgs/icons/plus-circle.svg +0 -5
  87. package/client/imgs/icons/right-circle.svg +0 -3
  88. package/client/imgs/icons/right.svg +0 -3
  89. package/client/imgs/icons/search.svg +0 -3
  90. package/client/imgs/icons/shield.svg +0 -6
  91. package/client/imgs/icons/tick-circle-solid.svg +0 -8
  92. package/client/imgs/icons/tick-circle.svg +0 -6
  93. package/client/imgs/icons/up2-small.svg +0 -4
  94. package/client/imgs/icons/up2.svg +0 -4
  95. package/client/imgs/icons/updown.svg +0 -6
  96. package/client/imgs/icons/v-big-dark.svg +0 -3
  97. package/client/imgs/icons/v-dark.svg +0 -3
  98. package/client/imgs/icons/v.svg +0 -3
  99. 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="/assets/imgs/user.jpg" className="size-8 rounded-full bg-gray-50" />
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 navigation = [
78
- { name: 'Dashboard', href: '/', icon: HomeIcon },
79
- { name: 'Pricing (example)', href: '/pricing', icon: UsersIcon },
80
- { name: 'Styleguide', href: '/styleguide', icon: PaintBrushIcon },
81
- { name: 'Signout', href: '/signout', icon: ArrowLeftCircleIcon },
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 teams = [
85
- { id: 1, name: 'Team 1', href: '#', initial: 'T' },
86
- { id: 2, name: 'Team 2', href: '#', initial: 'H' },
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
- <Logo alt="Nitro" width="70" />
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
- {navigation.map((item) => (
102
+ {_menu.map((item) => (
100
103
  <li key={item.name}>
101
104
  <Link
102
- to={item.href}
105
+ to={item.to}
103
106
  className={classNames(
104
- isActive(item.href)
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
- <item.icon
111
- className={classNames(
112
- isActive(item.href) ? 'text-indigo-600' : 'text-gray-400 group-hover:text-indigo-600',
113
- 'size-5 shrink-0'
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">Your teams</div>
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
- {teams.map((team) => (
130
+ {_links.map((team) => (
126
131
  <li key={team.name}>
127
132
  <Link
128
- to={team.href}
133
+ to={team.to}
129
134
  className={classNames(
130
- isActive(team.href)
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.href)
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="/assets/imgs/user.jpg" className="size-8 rounded-full bg-gray-50" />
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(/assets/imgs/flags/${flag}.svg)` }} />
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
- // Dashboard, app screens (only the <Outlet/> receives `params` and `location`)
7
- export function Layout1({ Logo }) {
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="/signin">About</Link></li>
24
- <li><Link class="underline1" to="/signin">Support</Link></li>
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: 'edit', label: 'Edit' },
146
- { value: 'delete', label: 'Delete' },
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
- "version": "0.0.7",
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
- "eslint-webpack-plugin": "^2.7.0",
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": "^0.0.7"`
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 dev dependency to ./. Note that this may cause errors when npm linking nitro-web, since dev deps are not installed.
70
- - Added tailwindcss^3 as a dev dependency to ./ to stop tailwind^4.0.0 from being installed
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,mEAcC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../client/app.js"],"names":[],"mappings":"AAKA,mEAeC"}
@@ -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":"AAOA;;4CAoEC"}
1
+ {"version":3,"file":"signin.d.ts","sourceRoot":"","sources":["../../../components/auth/signin.jsx"],"names":[],"mappings":"AAMA;;4CAmEC"}
@@ -0,0 +1,4 @@
1
+ export function Dashboard({ config }: {
2
+ config: any;
3
+ }): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -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":"AAGA;;;;;;4CAwBC"}
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/avatar.jsx"],"names":[],"mappings":"AAKA;;;;;;4CAwBC"}
@@ -1,4 +1,6 @@
1
- export function Sidebar({ Logo }: {
1
+ export function Sidebar({ Logo, menu, links }: {
2
2
  Logo: any;
3
+ menu: any;
4
+ links: any;
3
5
  }): import("react/jsx-runtime").JSX.Element;
4
6
  //# sourceMappingURL=sidebar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../components/partials/element/sidebar.jsx"],"names":[],"mappings":"AAiBA;;4CA+CC"}
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":"AAGA;;;;;;;;;4CAyHC"}
1
+ {"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../components/partials/form/drop.jsx"],"names":[],"mappings":"AAIA;;;;;;;;;4CAyHC"}
@@ -1,4 +1,13 @@
1
- export function Layout1({ Logo }: {
2
- Logo: any;
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":"AAMA;;4CAgBC"}
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;;4CAiPC"}
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;
@@ -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;;;;;;;;EAWC;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,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;AAjoCD,6BAAoC"}
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 '/assets/imgs/no-image.jpg'
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, fontsDir } = getDirectories(path, config.pwd)
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
+ }