nitro-web 0.0.73 → 0.0.74
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/client/app.tsx +6 -12
- package/components/partials/element/dropdown.tsx +55 -8
- package/components/partials/element/github-link.tsx +1 -1
- package/components/partials/form/checkbox.tsx +128 -103
- package/components/partials/form/field.tsx +1 -1
- package/components/partials/styleguide.tsx +8 -5
- package/package.json +1 -1
package/client/app.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createBrowserRouter, createHashRouter, redirect,
|
|
1
|
+
import { createBrowserRouter, createHashRouter, redirect, RouterProvider } from 'react-router-dom'
|
|
2
2
|
import { Fragment, ReactNode } from 'react'
|
|
3
3
|
import ReactDOM from 'react-dom/client'
|
|
4
4
|
import { axios, camelCase, pick, toArray, setTimeoutPromise } from 'nitro-web/util'
|
|
@@ -25,7 +25,7 @@ type Settings = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
type Route = {
|
|
28
|
-
component: React.FC<{ route?: Route;
|
|
28
|
+
component: React.FC<{ route?: Route; config?: Config }>
|
|
29
29
|
middleware: string[]
|
|
30
30
|
name: string
|
|
31
31
|
path: string
|
|
@@ -70,9 +70,7 @@ export function updateJwt(token?: string | null) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function App({ settings, config, storeContainer }: { settings: Settings, config: Config, storeContainer: StoreContainer }): ReactNode {
|
|
73
|
-
|
|
74
|
-
const router = getRouter({ settings, config })
|
|
75
|
-
// const theme = pick(themeNormalised, []) // e.g. 'topPanelHeight'
|
|
73
|
+
const router = useMemo(() => getRouter({ settings, config }), [])
|
|
76
74
|
|
|
77
75
|
useEffect(() => {
|
|
78
76
|
/**
|
|
@@ -97,10 +95,8 @@ function App({ settings, config, storeContainer }: { settings: Settings, config:
|
|
|
97
95
|
|
|
98
96
|
return (
|
|
99
97
|
<storeContainer.Provider>
|
|
100
|
-
{
|
|
101
|
-
{ router && <RouterProvider router={router} /> }
|
|
98
|
+
{ router && <RouterProvider router={router}/> }
|
|
102
99
|
<AfterApp settings={settings} />
|
|
103
|
-
{/* </ThemeProvider> */}
|
|
104
100
|
</storeContainer.Provider>
|
|
105
101
|
)
|
|
106
102
|
}
|
|
@@ -206,7 +202,7 @@ function getRouter({ settings, config }: { settings: Settings, config: Config })
|
|
|
206
202
|
),
|
|
207
203
|
path: route.path,
|
|
208
204
|
loader: async () => { // request
|
|
209
|
-
// wait for container/exposedStoreData to be setup
|
|
205
|
+
// wait for container/exposedStoreData to be setup (note that this causes ReactRouter to re-render, but not the page)
|
|
210
206
|
if (!nonce) {
|
|
211
207
|
nonce = true
|
|
212
208
|
await setTimeoutPromise(() => {}, 0)
|
|
@@ -255,11 +251,9 @@ function RestoreScroll() {
|
|
|
255
251
|
|
|
256
252
|
function RouteComponent({ route, config }: { route: Route, config: Config }) {
|
|
257
253
|
const Component = route.component
|
|
258
|
-
const params = useParams()
|
|
259
|
-
const location = useLocation()
|
|
260
254
|
document.title = route.meta?.title || ''
|
|
261
255
|
return (
|
|
262
|
-
<Component route={route}
|
|
256
|
+
<Component route={route} config={config} />
|
|
263
257
|
)
|
|
264
258
|
}
|
|
265
259
|
|
|
@@ -14,14 +14,14 @@ type DropdownProps = {
|
|
|
14
14
|
options?: { label: string|React.ReactNode, onClick?: Function, isSelected?: boolean, icon?: React.ReactNode, className?: string }[]
|
|
15
15
|
/** Whether the dropdown is hoverable **/
|
|
16
16
|
isHoverable?: boolean
|
|
17
|
-
/** The minimum width of the menu **/
|
|
18
|
-
minWidth?: number | string
|
|
19
17
|
/** The content to render inside the top of the dropdown **/
|
|
20
18
|
menuContent?: React.ReactNode
|
|
21
19
|
menuClassName?: string
|
|
22
20
|
menuOptionClassName?: string
|
|
23
21
|
menuIsOpen?: boolean
|
|
24
22
|
menuToggles?: boolean
|
|
23
|
+
/** The minimum width of the menu **/
|
|
24
|
+
minWidth?: number | string
|
|
25
25
|
toggleCallback?: (isActive: boolean) => void
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -30,15 +30,15 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
30
30
|
animate=true,
|
|
31
31
|
children,
|
|
32
32
|
className,
|
|
33
|
-
dir,
|
|
33
|
+
dir='bottom-left',
|
|
34
34
|
options,
|
|
35
35
|
isHoverable,
|
|
36
|
-
minWidth, // remove in favour of menuClassName
|
|
37
36
|
menuClassName,
|
|
38
37
|
menuOptionClassName,
|
|
39
38
|
menuContent,
|
|
40
39
|
menuIsOpen,
|
|
41
40
|
menuToggles=true,
|
|
41
|
+
minWidth,
|
|
42
42
|
toggleCallback,
|
|
43
43
|
}: DropdownProps, ref) {
|
|
44
44
|
// https://letsbuildui.dev/articles/building-a-dropdown-menu-component-with-react-hooks
|
|
@@ -46,6 +46,8 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
46
46
|
const dropdownRef = useRef<HTMLDivElement|null>(null)
|
|
47
47
|
const [isActive, setIsActive] = useState(!!menuIsOpen)
|
|
48
48
|
const menuStyle = getSelectStyle({ name: 'menu' })
|
|
49
|
+
const [direction, setDirection] = useState<null | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'>(null)
|
|
50
|
+
const [ready, setReady] = useState(false)
|
|
49
51
|
|
|
50
52
|
// Expose the setIsActive function to the parent component
|
|
51
53
|
useImperativeHandle(ref, () => ({ setIsActive }))
|
|
@@ -76,7 +78,50 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
76
78
|
useEffect(() => {
|
|
77
79
|
if (toggleCallback) toggleCallback(isActive)
|
|
78
80
|
}, [isActive])
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
setReady(false)
|
|
84
|
+
if (!isActive || !dropdownRef.current) return
|
|
85
|
+
|
|
86
|
+
const ul = dropdownRef.current.querySelector('ul') as HTMLElement
|
|
87
|
+
if (!ul) return
|
|
88
|
+
|
|
89
|
+
// Temporarily show the ul for measurement
|
|
90
|
+
const originalMaxHeight = ul.style.maxHeight
|
|
91
|
+
const originalVisibility = ul.style.visibility
|
|
92
|
+
const originalOpacity = ul.style.opacity
|
|
93
|
+
const originalPointerEvents = ul.style.pointerEvents
|
|
94
|
+
|
|
95
|
+
ul.style.maxHeight = 'none'
|
|
96
|
+
ul.style.visibility = 'hidden'
|
|
97
|
+
ul.style.opacity = '0'
|
|
98
|
+
ul.style.pointerEvents = 'none'
|
|
79
99
|
|
|
100
|
+
const dropdownHeight = ul.getBoundingClientRect().height
|
|
101
|
+
|
|
102
|
+
// Revert styles
|
|
103
|
+
ul.style.maxHeight = originalMaxHeight
|
|
104
|
+
ul.style.visibility = originalVisibility
|
|
105
|
+
ul.style.opacity = originalOpacity
|
|
106
|
+
ul.style.pointerEvents = originalPointerEvents
|
|
107
|
+
|
|
108
|
+
const rect = dropdownRef.current.getBoundingClientRect()
|
|
109
|
+
const spaceBelow = window.innerHeight - rect.bottom
|
|
110
|
+
const spaceAbove = rect.top
|
|
111
|
+
|
|
112
|
+
const side = dir.endsWith('right') ? 'right' : 'left'
|
|
113
|
+
|
|
114
|
+
const newDirection = dir.startsWith('bottom')
|
|
115
|
+
? `${spaceBelow < dropdownHeight && spaceAbove > dropdownHeight ? 'top' : 'bottom'}-${side}`
|
|
116
|
+
: `${spaceAbove < dropdownHeight && spaceBelow > dropdownHeight ? 'bottom' : 'top'}-${side}`
|
|
117
|
+
|
|
118
|
+
setDirection(newDirection as 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right')
|
|
119
|
+
|
|
120
|
+
requestAnimationFrame(() => {
|
|
121
|
+
setReady(true)
|
|
122
|
+
})
|
|
123
|
+
}, [isActive, dir])
|
|
124
|
+
|
|
80
125
|
function onMouseDown(e: { key: string, preventDefault: Function }) {
|
|
81
126
|
if (e.key && e.key != 'Enter') return
|
|
82
127
|
if (e.key) e.preventDefault() // for button, stops buttons firing twice
|
|
@@ -87,12 +132,13 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
87
132
|
if (option.onClick) option.onClick(e)
|
|
88
133
|
if (!menuIsOpen) setIsActive(!isActive)
|
|
89
134
|
}
|
|
135
|
+
var ready2
|
|
90
136
|
|
|
91
137
|
return (
|
|
92
138
|
<div
|
|
93
139
|
class={
|
|
94
|
-
|
|
95
|
-
(
|
|
140
|
+
`relative is-${direction || dir}` + // until hovered, show the original direction to prevent scrollbars
|
|
141
|
+
(ready2 ? ' is-ready' : '') +
|
|
96
142
|
(isHoverable ? ' is-hoverable' : '') +
|
|
97
143
|
(isActive ? ' is-active' : '') +
|
|
98
144
|
(!animate ? ' no-animation' : '') +
|
|
@@ -113,7 +159,8 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
113
159
|
}
|
|
114
160
|
<ul
|
|
115
161
|
style={{ minWidth }}
|
|
116
|
-
class={
|
|
162
|
+
class={
|
|
163
|
+
twMerge(`${menuStyle} ${ready ? 'is-ready' : ''} absolute invisible opacity-0 select-none min-w-full z-[1] ${menuClassName||''}`)}
|
|
117
164
|
>
|
|
118
165
|
{menuContent}
|
|
119
166
|
{
|
|
@@ -172,7 +219,7 @@ const style = css`
|
|
|
172
219
|
&>ul>li:hover,
|
|
173
220
|
&>ul>li:focus,
|
|
174
221
|
&>ul>li.is-active {
|
|
175
|
-
&>ul {
|
|
222
|
+
&>ul.is-ready {
|
|
176
223
|
opacity: 1;
|
|
177
224
|
visibility: visible;
|
|
178
225
|
transition: transform 0.15s ease, opacity 0.15s ease;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import GithubIcon from 'nitro-web/client/imgs/github.svg'
|
|
2
2
|
|
|
3
3
|
export function GithubLink({ filename }: { filename: string }) {
|
|
4
|
-
const base = 'https://github.com/boycce/nitro-web/blob/master/'
|
|
4
|
+
const base = 'https://github.com/boycce/nitro-web/blob/master/packages/'
|
|
5
5
|
// Filenames are relative to the webpack start directory
|
|
6
6
|
// 1. Remove ../ from filename (i.e. for _example build)
|
|
7
7
|
// 2. Remove node_modules/nitro-web/ from filename (i.e. for packages using nitro-web)
|
|
@@ -1,121 +1,146 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { twMerge, deepFind, getErrorFromState } from 'nitro-web/util'
|
|
3
|
+
import { Errors, type Error } from 'nitro-web/types'
|
|
2
4
|
|
|
3
|
-
type CheckboxProps = {
|
|
5
|
+
type CheckboxProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
6
|
+
/** field name or path on state (used to match errors), e.g. 'date', 'company.email' */
|
|
4
7
|
name: string
|
|
5
|
-
/** name is applied if not provided. Used for radios */
|
|
8
|
+
/** name is applied if id is not provided. Used for radios */
|
|
6
9
|
id?: string
|
|
7
|
-
|
|
10
|
+
/** state object to get the value, and check errors against */
|
|
11
|
+
state?: { errors?: Errors, [key: string]: any }
|
|
12
|
+
size?: number
|
|
8
13
|
subtext?: string|React.ReactNode
|
|
9
14
|
text?: string|React.ReactNode
|
|
10
15
|
type?: 'checkbox' | 'radio' | 'toggle'
|
|
11
|
-
|
|
16
|
+
checkboxClassName?: string
|
|
17
|
+
svgClassName?: string
|
|
18
|
+
labelClassName?: string
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
export function Checkbox({
|
|
21
|
+
export function Checkbox({
|
|
22
|
+
state, size, subtext, text, type='checkbox', className, checkboxClassName, svgClassName, labelClassName, ...props
|
|
23
|
+
}: CheckboxProps) {
|
|
15
24
|
// Checkbox/radio/toggle component
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
id = id || name
|
|
25
|
+
let value!: boolean
|
|
26
|
+
const error = getErrorFromState(state, props.name)
|
|
27
|
+
const id = props.id || props.name
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
md: {
|
|
28
|
-
checkbox: 'size-[16px]',
|
|
29
|
-
toggleWidth: 'w-[40px]', // 4px border + (toggleAfterSize * 2)
|
|
30
|
-
toggleHeight: 'h-[22px]',
|
|
31
|
-
toggleAfterSize: 'after:size-[18px]', // account for 2px border
|
|
32
|
-
},
|
|
29
|
+
if (!props.name) throw new Error('Checkbox requires a `name` prop')
|
|
30
|
+
|
|
31
|
+
// Value: Input is always controlled if state is passed in
|
|
32
|
+
if (typeof props.checked !== 'undefined') value = props.checked
|
|
33
|
+
else if (typeof state == 'object') {
|
|
34
|
+
const v = deepFind(state, props.name) as boolean | undefined
|
|
35
|
+
value = v ?? false
|
|
33
36
|
}
|
|
34
|
-
|
|
37
|
+
|
|
38
|
+
const BORDER = 2
|
|
39
|
+
const checkboxSize = size ?? 14
|
|
40
|
+
const toggleHeight = size ?? 18
|
|
41
|
+
const toggleWidth = toggleHeight * 2 - BORDER * 2
|
|
42
|
+
const toggleAfterSize = toggleHeight - BORDER * 2
|
|
35
43
|
|
|
36
44
|
return (
|
|
37
|
-
<div
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
45
|
+
<div
|
|
46
|
+
className={'mt-2.5 mb-6 ' + twMerge(`mt-input-before mb-input-after text-sm nitro-checkbox ${className}`)}
|
|
47
|
+
>
|
|
48
|
+
<div className="flex gap-3 items-baseline">
|
|
49
|
+
<div className="shrink-0 flex items-center">
|
|
50
|
+
<div className="w-0"> </div>
|
|
51
|
+
<div className="group relative">
|
|
52
|
+
{
|
|
53
|
+
type !== 'toggle'
|
|
54
|
+
? <>
|
|
55
|
+
<input
|
|
56
|
+
{...props}
|
|
57
|
+
type={type}
|
|
58
|
+
style={{ width: checkboxSize, height: checkboxSize }}
|
|
59
|
+
checked={value}
|
|
60
|
+
className={
|
|
61
|
+
twMerge(
|
|
62
|
+
`${type === 'radio' ? 'rounded-full' : 'rounded'} appearance-none border border-gray-300 bg-white forced-colors:appearance-auto disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ` +
|
|
63
|
+
// Variable-selected theme colors (was .*-blue-600)
|
|
64
|
+
'checked:border-variable-selected checked:bg-variable-selected indeterminate:border-variable-selected indeterminate:bg-variable-selected focus-visible:outline-variable-selected ' +
|
|
65
|
+
// Dark mode not used yet... dark:focus-visible:outline-blue-800
|
|
66
|
+
checkboxClassName
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
/>
|
|
70
|
+
<svg
|
|
71
|
+
fill="none"
|
|
72
|
+
viewBox="0 0 14 14"
|
|
73
|
+
style={{ width: checkboxSize, height: checkboxSize }}
|
|
74
|
+
className={twMerge('absolute top-0 left-0 pointer-events-none justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25', svgClassName)}
|
|
75
|
+
>
|
|
76
|
+
{
|
|
77
|
+
type === 'radio'
|
|
78
|
+
? <circle
|
|
79
|
+
// cx={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
|
|
80
|
+
// cy={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
|
|
81
|
+
// r={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 6}
|
|
82
|
+
cx={7}
|
|
83
|
+
cy={7}
|
|
84
|
+
r={2.5}
|
|
85
|
+
className="fill-white opacity-0 group-has-[:checked]:opacity-100"
|
|
86
|
+
/>
|
|
87
|
+
: <>
|
|
88
|
+
<path
|
|
89
|
+
d="M4 8L6 10L10 4.5"
|
|
90
|
+
strokeWidth={2}
|
|
91
|
+
strokeLinecap="round"
|
|
92
|
+
strokeLinejoin="round"
|
|
93
|
+
className="opacity-0 group-has-[:checked]:opacity-100"
|
|
94
|
+
/>
|
|
95
|
+
<path
|
|
96
|
+
d="M4 7H10"
|
|
97
|
+
strokeWidth={2}
|
|
98
|
+
strokeLinecap="round"
|
|
99
|
+
strokeLinejoin="round"
|
|
100
|
+
className="opacity-0 group-has-[:indeterminate]:opacity-100"
|
|
101
|
+
/>
|
|
102
|
+
</>
|
|
103
|
+
}
|
|
104
|
+
</svg>
|
|
105
|
+
</>
|
|
106
|
+
: <>
|
|
107
|
+
<input
|
|
108
|
+
{...props}
|
|
109
|
+
type="checkbox"
|
|
110
|
+
className="sr-only peer"
|
|
111
|
+
checked={value}
|
|
112
|
+
/>
|
|
113
|
+
<label
|
|
114
|
+
for={id}
|
|
115
|
+
style={{ width: toggleWidth, height: toggleHeight }}
|
|
116
|
+
className={
|
|
117
|
+
twMerge(
|
|
118
|
+
'block bg-gray-200 rounded-full transition-colors peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 ' +
|
|
119
|
+
// Variable-selected theme colors (was .*-blue-600)
|
|
120
|
+
'peer-checked:bg-variable-selected peer-focus-visible:outline-variable-selected ' +
|
|
121
|
+
labelClassName
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
>
|
|
125
|
+
<span
|
|
126
|
+
style={{ width: toggleAfterSize, height: toggleAfterSize }}
|
|
127
|
+
className={
|
|
128
|
+
'absolute top-[2px] start-[2px] bg-white border-gray-300 border rounded-full transition-all group-has-[:checked]:border-white group-has-[:checked]:translate-x-full '
|
|
129
|
+
}
|
|
130
|
+
/>
|
|
131
|
+
</label>
|
|
132
|
+
</>
|
|
133
|
+
}
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
{text &&
|
|
137
|
+
<label for={id} className="text-[length:inherit] leading-[inherit] select-none">
|
|
138
|
+
<span className="text-gray-900">{text}</span>
|
|
139
|
+
<span className="ml-2 text-gray-500">{subtext}</span>
|
|
140
|
+
</label>
|
|
111
141
|
}
|
|
112
142
|
</div>
|
|
113
|
-
{
|
|
114
|
-
<label for={id} className="self-center text-sm select-none">
|
|
115
|
-
<span className="text-gray-900">{text}</span>
|
|
116
|
-
<span className="ml-2 text-gray-500">{subtext}</span>
|
|
117
|
-
</label>
|
|
118
|
-
}
|
|
143
|
+
{error && <div class="mt-1.5 text-xs text-danger-foreground nitro-error">{error.detail}</div>}
|
|
119
144
|
</div>
|
|
120
145
|
)
|
|
121
146
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
//
|
|
2
|
+
// fill-current tw class for lucide icons (https://github.com/lucide-icons/lucide/discussions/458)
|
|
3
3
|
import { css } from 'twin.macro'
|
|
4
4
|
import { FieldCurrency, FieldCurrencyProps, FieldColor, FieldColorProps, FieldDate, FieldDateProps } from 'nitro-web'
|
|
5
5
|
import { twMerge, getErrorFromState, deepFind } from 'nitro-web/util'
|
|
@@ -204,18 +204,21 @@ export function Styleguide({ className, elements, children }: StyleguideProps) {
|
|
|
204
204
|
<div class="grid grid-cols-3 gap-x-6 mb-4">
|
|
205
205
|
<div>
|
|
206
206
|
<label for="input2">Label</label>
|
|
207
|
-
<Checkbox name="input2" type="toggle" text="Toggle sm" subtext="some additional text here." class="!mb-0"
|
|
208
|
-
|
|
207
|
+
<Checkbox name="input2" type="toggle" text="Toggle sm" subtext="some additional text here." class="!mb-0"
|
|
208
|
+
state={state} onChange={(e) => onChange(setState, e)} />
|
|
209
|
+
<Checkbox name="input3" type="toggle" text="Toggle 22px" subtext="some additional text here." size={22} />
|
|
209
210
|
</div>
|
|
210
211
|
<div>
|
|
211
212
|
<label for="input1">Label</label>
|
|
212
|
-
<Checkbox name="input1" type="radio" text="Radio
|
|
213
|
+
<Checkbox name="input1" type="radio" text="Radio" subtext="some additional text here 1." id="input1-1" class="!mb-0"
|
|
213
214
|
defaultChecked />
|
|
214
|
-
<Checkbox name="input1" type="radio" text="Radio
|
|
215
|
+
<Checkbox name="input1" type="radio" text="Radio 16px" subtext="some additional text here 2." id="input1-2" size={16} />
|
|
215
216
|
</div>
|
|
216
217
|
<div>
|
|
217
218
|
<label for="input0">Label</label>
|
|
218
|
-
<Checkbox name="input0" type="checkbox" text="Checkbox" subtext="some additional text here." defaultChecked />
|
|
219
|
+
<Checkbox name="input0" type="checkbox" text="Checkbox" subtext="some additional text here." class="!mb-0" defaultChecked />
|
|
220
|
+
<Checkbox name="input0.1" type="checkbox" text="Checkbox 16px" size={16}
|
|
221
|
+
subtext="some additional text here which is a bit longer that will be line-wrap to the next line." />
|
|
219
222
|
</div>
|
|
220
223
|
</div>
|
|
221
224
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.74",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
6
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|