nitro-web 0.0.13 → 0.0.14

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.
@@ -1,3 +1,4 @@
1
+ import { twMerge } from 'tailwind-merge'
1
2
  import { ChevronDownIcon } from '@heroicons/react/20/solid'
2
3
 
3
4
  type Props = {
@@ -32,10 +33,10 @@ export function Button({ color='primary', size='md', className, isLoading, IconL
32
33
 
33
34
  // Icon position
34
35
  const contentLayouts = {
35
- left: 'w-full inline-flex items-center',
36
- right: 'w-full inline-flex items-center',
37
- right2: 'w-full inline-flex items-center justify-between',
38
- none: 'w-full ',
36
+ left: 'w-full inline-flex items-center gap-x-1.5',
37
+ right: 'w-full inline-flex items-center gap-x-1.5',
38
+ right2: 'w-full inline-flex items-center justify-between gap-x-1.5',
39
+ none: 'w-full gap-x-1.5',
39
40
  }
40
41
 
41
42
  let colorAndSize = ''
@@ -43,25 +44,23 @@ export function Button({ color='primary', size='md', className, isLoading, IconL
43
44
  else if (color.match(/secondary/)) colorAndSize = `${secondary} ${sizes[size]}`
44
45
  else if (color.match(/white/)) colorAndSize = `${white} ${sizes[size]}`
45
46
 
46
- let contentLayout = `${contentLayouts[iconPosition]}`
47
- if (!(className||'').match(/gap-/)) contentLayout += ' gap-x-1.5'
47
+ const contentLayout = `${contentLayouts[iconPosition]}`
48
+ const loading = isLoading ? '[&>*]:opacity-0 text-opacity-0' : ''
48
49
 
49
- function getIcon(Icon: React.ReactNode|'v', className: string) {
50
- if (Icon == 'v') return <ChevronDownIcon className={className} />
50
+ function getIcon(Icon: React.ReactNode | 'v') {
51
+ if (Icon == 'v') return <ChevronDownIcon className="size-6 -my-6 -mx-1" />
51
52
  else return Icon
52
53
  }
53
54
 
54
55
  return (
55
- <button class={`${base} ${colorAndSize} ${className||''}`} {...props}>
56
- <span class={`${contentLayout} ${isLoading ? 'opacity-0' : ''}`}>
57
- {IconLeft && getIcon(IconLeft, 'size-6 -my-6 -mx-1')}
58
- {children}
59
- {IconRight && getIcon(IconRight, 'size-6 -my-6 -mx-1')}
60
- {IconRight2 && getIcon(IconRight2, 'size-6 -my-6 -mx-1')}
61
- </span>
56
+ <button class={twMerge(`${base} ${colorAndSize} ${contentLayout} ${loading} ${className||''}`)} {...props}>
57
+ {IconLeft && getIcon(IconLeft)}
58
+ {children}
59
+ {IconRight && getIcon(IconRight)}
60
+ {IconRight2 && getIcon(IconRight2)}
62
61
  {
63
62
  isLoading &&
64
- <span class="absolute inset-0 flex items-center justify-center">
63
+ <span class="!opacity-100 absolute inset-0 flex items-center justify-center">
65
64
  <span className="w-4 h-4 rounded-full animate-spin border-2 border-t-transparent border-white" />
66
65
  </span>
67
66
  }
@@ -14,38 +14,69 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
14
14
  // https://tailwindui.com/components/application-ui/forms/checkboxes#component-744ed4fa65ba36b925701eb4da5c6e31
15
15
  if (!name) throw new Error('Checkbox requires a `name` prop')
16
16
  id = id || name
17
+
18
+ const sizeMap = {
19
+ sm: {
20
+ checkbox: 'size-[14px]',
21
+ toggleWidth: 'w-[32px]', // 4px border + (toggleAfterSize * 2)
22
+ toggleHeight: 'h-[18px]',
23
+ toggleAfterSize: 'after:size-[14px]', // account for 2px border
24
+ },
25
+ md: {
26
+ checkbox: 'size-[16px]',
27
+ toggleWidth: 'w-[40px]', // 4px border + (toggleAfterSize * 2)
28
+ toggleHeight: 'h-[22px]',
29
+ toggleAfterSize: 'after:size-[18px]', // account for 2px border
30
+ },
31
+ }
32
+ const _size = sizeMap[size]
33
+
17
34
  return (
18
35
  <div className={`mt-input-before mb-input-after flex gap-3 ${props.className || ''}`}>
19
- <div className="flex h-6 shrink-0 items-center">
36
+ <div className="flex shrink-0 mt-[2px]">
20
37
  {
21
38
  type !== 'toggle'
22
- ? <div className="group grid size-4 grid-cols-1">
39
+ ? <div className={`group grid ${_size.checkbox} grid-cols-1`}>
23
40
  <input
24
41
  {...props}
25
42
  id={id}
26
43
  name={name}
27
44
  type={type}
28
- className="col-start-1 row-start-1 appearance-none rounded border border-gray-300 bg-white checked:border-primary checked:bg-primary indeterminate:border-primary indeterminate:bg-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto"
45
+ className={`${type === 'radio' ? 'rounded-full' : 'rounded'} col-start-1 row-start-1 appearance-none border border-gray-300 bg-white checked:border-primary checked:bg-primary indeterminate:border-primary indeterminate:bg-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto`}
29
46
  />
30
47
  <svg
31
48
  fill="none"
32
49
  viewBox="0 0 14 14"
33
- className="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25"
50
+ className={`pointer-events-none col-start-1 row-start-1 ${_size.checkbox} self-center justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25`}
34
51
  >
35
- <path
36
- d="M3 8L6 11L11 3.5"
37
- strokeWidth={2}
38
- strokeLinecap="round"
39
- strokeLinejoin="round"
40
- className="opacity-0 group-has-[:checked]:opacity-100"
41
- />
42
- <path
43
- d="M3 7H11"
44
- strokeWidth={2}
45
- strokeLinecap="round"
46
- strokeLinejoin="round"
47
- className="opacity-0 group-has-[:indeterminate]:opacity-100"
48
- />
52
+ {
53
+ type === 'radio'
54
+ ? <circle
55
+ // cx={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
56
+ // cy={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 2}
57
+ // r={(_size.checkbox.match(/\d+/)?.[0] as unknown as number) / 6}
58
+ cx={7}
59
+ cy={7}
60
+ r={2.5}
61
+ className="fill-white opacity-0 group-has-[:checked]:opacity-100"
62
+ />
63
+ : <>
64
+ <path
65
+ d="M4 8L6 10L10 4.5"
66
+ strokeWidth={2}
67
+ strokeLinecap="round"
68
+ strokeLinejoin="round"
69
+ className="opacity-0 group-has-[:checked]:opacity-100"
70
+ />
71
+ <path
72
+ d="M4 7H10"
73
+ strokeWidth={2}
74
+ strokeLinecap="round"
75
+ strokeLinejoin="round"
76
+ className="opacity-0 group-has-[:indeterminate]:opacity-100"
77
+ />
78
+ </>
79
+ }
49
80
  </svg>
50
81
  </div>
51
82
  : <div className="group grid grid-cols-1">
@@ -58,17 +89,17 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
58
89
  />
59
90
  <label
60
91
  for={id}
61
- className={`col-start-1 row-start-1 relative ${size == 'sm' ? 'w-9' : 'w-11'} ${size == 'sm' ? 'h-5' : 'h-6'} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 peer-focus-visible:ring-blue-300 dark:peer-focus-visible:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${size == 'sm' ? 'after:w-4' : 'after:w-5'} ${size == 'sm' ? 'after:h-4' : 'after:h-5'} after:transition-all dark:border-gray-600 peer-checked:bg-blue-600`}
92
+ className={`col-start-1 row-start-1 relative ${_size.toggleWidth} ${_size.toggleHeight} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 peer-focus-visible:ring-blue-300 dark:peer-focus-visible:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${_size.toggleAfterSize} after:transition-all dark:border-gray-600 peer-checked:bg-blue-600`}
62
93
  />
63
94
  </div>
64
95
  }
65
96
  </div>
66
- {text && <div className="text-sm/6">
67
- <label for={id} className="select-none">
68
- <span className="font-medium text-gray-900">{text}</span>
97
+ {text &&
98
+ <label for={id} className="self-center text-sm-label select-none">
99
+ <span className="text-gray-900">{text}</span>
69
100
  <span className="ml-2 text-gray-500">{subtext}</span>
70
101
  </label>
71
- </div>}
102
+ }
72
103
  </div>
73
104
  )
74
105
  }
@@ -1,9 +1,7 @@
1
- import { css } from 'twin.macro'
2
1
  import { hsvaToHex, hexToHsva, validHex, HsvaColor } from '@uiw/color-convert'
3
2
  import Saturation from '@uiw/react-color-saturation'
4
3
  import Hue from '@uiw/react-color-hue'
5
4
  import { Dropdown, util } from 'nitro-web'
6
- import React from 'react'
7
5
 
8
6
  type InputColorProps = {
9
7
  className?: string
@@ -32,7 +30,7 @@ export function InputColor({ className, defaultColor='#333', iconEl, id, onChang
32
30
  <ColorPicker key={lastChanged} defaultColor={defaultColor} id={id} value={value} onChange={onChange} />
33
31
  }
34
32
  >
35
- <div className="grid grid-cols-1" css={style}>
33
+ <div className="grid grid-cols-1">
36
34
  {iconEl}
37
35
  <input
38
36
  {...props}
@@ -59,7 +57,7 @@ function ColorPicker({ id='', onChange, value='', defaultColor='' }: InputColorP
59
57
  return (
60
58
  <>
61
59
  <Saturation
62
- css={style}
60
+ className="!w-[100%] !h-[150px]"
63
61
  hsva={hsva}
64
62
  onChange={(newHsva) => {
65
63
  setHsva(newHsva)
@@ -67,7 +65,6 @@ function ColorPicker({ id='', onChange, value='', defaultColor='' }: InputColorP
67
65
  }}
68
66
  />
69
67
  <Hue
70
- css={style}
71
68
  hue={hsva.h}
72
69
  onChange={(newHue) => {
73
70
  setHsva({ ...hsva, ...newHue })
@@ -78,12 +75,5 @@ function ColorPicker({ id='', onChange, value='', defaultColor='' }: InputColorP
78
75
  )
79
76
  }
80
77
 
81
- const style = css`
82
- /////////////////////
83
- .w-color-interactive {
84
- width: 100% !important;
85
- height: 150px !important;
86
- }
87
- `
88
78
 
89
79
 
@@ -52,7 +52,11 @@ export function Styleguide({ config }: { config: Config }) {
52
52
  <div class="mb-10 text-left max-w-[1100px]">
53
53
  <GithubLink filename={__filename} />
54
54
  <div class="mb-7">
55
- <h1 class="h1 m-0">Styleguide</h1>
55
+ <h1 class="h1">Styleguide</h1>
56
+ <p>
57
+ Components are styled using&nbsp;
58
+ <a href="https://v3.tailwindcss.com/docs/configuration" class="underline" target="_blank" rel="noreferrer">TailwindCSS</a>.
59
+ </p>
56
60
  </div>
57
61
 
58
62
  <h2 class="h3">Links</h2>
@@ -76,7 +80,8 @@ export function Styleguide({ config }: { config: Config }) {
76
80
  </div>
77
81
  <div>
78
82
  <label for="input2">Label</label>
79
- <Checkbox name="input2" type="toggle" text="Toggle" subtext="some additional text here." defaultChecked />
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." />
80
85
  </div>
81
86
  </div>
82
87
 
@@ -84,7 +89,7 @@ export function Styleguide({ config }: { config: Config }) {
84
89
  <div class="flex flex-wrap gap-x-6 gap-y-4 mb-8">
85
90
  <div>
86
91
  <Dropdown options={options} minWidth="250px">
87
- <Button IconRight2="v" class="gap-x-3">Dropdown</Button>
92
+ <Button IconRight="v" class="gap-x-3">Dropdown</Button>
88
93
  </Dropdown>
89
94
  </div>
90
95
  <div>
@@ -116,7 +121,7 @@ export function Styleguide({ config }: { config: Config }) {
116
121
  <div><Button IconLeft={<CheckIcon class="size-5 -my-5 -mx-0.5" />}>IconLeft=Element</Button></div>
117
122
  <div><Button IconRight="v">IconRight=&quot;v&quot;</Button></div>
118
123
  <div><Button IconRight2="v" className="w-[200px]">IconRight2=&quot;v&quot;</Button></div>
119
- <div><Button color="primary" isLoading>primary isLoading</Button></div>
124
+ <div><Button color="primary" IconRight="v" isLoading>primary isLoading</Button></div>
120
125
  </div>
121
126
 
122
127
  <h2 class="h3">Selects</h2>
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.13",
6
+ "version": "0.0.14",
7
7
  "main": "./client/index.ts",
8
8
  "type": "module",
9
9
  "keywords": [
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.13"`
14
+ 2. In package.json, replace `"nitro-web": "file:.."` with `"nitro-web": "~0.0.14"`
15
15
  3. In package.json, replace `"../.eslintrc.json"` with `"./node_modules/nitro-web/.eslintrc.json"`
16
16
  4. Run `npm i`
17
17