@sakura-ui/sakura-ui 0.2.0 → 0.4.1

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 (212) hide show
  1. package/README.md +77 -6
  2. package/package.json +28 -21
  3. package/packages/core/package.json +30 -17
  4. package/packages/core/src/components/Button.tsx +33 -32
  5. package/packages/core/src/components/Card.tsx +37 -20
  6. package/packages/core/src/components/Code.tsx +6 -4
  7. package/packages/core/src/components/Faq.tsx +13 -7
  8. package/packages/core/src/components/Heading.tsx +42 -32
  9. package/packages/core/src/components/Icon.tsx +43 -13
  10. package/packages/core/src/components/IconButton.tsx +54 -43
  11. package/packages/core/src/components/LangSelector.tsx +135 -0
  12. package/packages/core/src/components/Link.tsx +37 -66
  13. package/packages/core/src/components/LinkCard.tsx +126 -0
  14. package/packages/core/src/components/List.tsx +14 -12
  15. package/packages/core/src/components/MenuButton.tsx +112 -0
  16. package/packages/core/src/components/NavigationItem.tsx +41 -0
  17. package/packages/core/src/components/NotificationBanner.tsx +20 -0
  18. package/packages/core/src/components/OverflowContainer.tsx +24 -0
  19. package/packages/core/src/components/PopoverMenu.tsx +82 -0
  20. package/packages/core/src/components/Pre.tsx +6 -4
  21. package/packages/core/src/components/Table.tsx +31 -25
  22. package/packages/core/src/components/buttonStyle.ts +43 -32
  23. package/packages/core/src/components/index.ts +13 -25
  24. package/packages/core/src/icons/Close.tsx +21 -0
  25. package/packages/core/src/icons/CloseMobile.tsx +43 -0
  26. package/packages/core/src/icons/KeyboardArrowDown.tsx +24 -0
  27. package/packages/core/src/icons/Language.tsx +25 -0
  28. package/packages/core/src/icons/LanguageMobile.tsx +40 -0
  29. package/packages/core/src/icons/Menu.tsx +24 -0
  30. package/packages/core/src/icons/MenuMobile.tsx +40 -0
  31. package/packages/core/src/icons/index.ts +8 -0
  32. package/packages/core/src/icons/props.ts +5 -0
  33. package/packages/core/src/index.ts +10 -28
  34. package/packages/core/src/type.d.ts +1 -0
  35. package/packages/core/tests/Button.test.tsx +20 -10
  36. package/packages/core/tests/Card.test.tsx +16 -11
  37. package/packages/core/tests/IconButton.test.tsx +57 -0
  38. package/packages/core/tests/Link.test.tsx +60 -0
  39. package/packages/core/tests/vitest.setup.ts +1 -0
  40. package/packages/core/tsconfig.node.json +3 -2
  41. package/packages/core/vite.config.ts +2 -1
  42. package/packages/forms/.turbo/turbo-build.log +12 -0
  43. package/packages/forms/dist/index.cjs.js +183 -131
  44. package/packages/forms/dist/index.es.js +750 -1062
  45. package/packages/forms/dist/types/components/Checkbox.d.ts +9 -4
  46. package/packages/forms/dist/types/components/Checkbox.d.ts.map +1 -1
  47. package/packages/forms/dist/types/components/FieldsetControl.d.ts +14 -9
  48. package/packages/forms/dist/types/components/FieldsetControl.d.ts.map +1 -1
  49. package/packages/forms/dist/types/components/FileInput.d.ts +10 -3
  50. package/packages/forms/dist/types/components/FileInput.d.ts.map +1 -1
  51. package/packages/forms/dist/types/components/Input.d.ts +9 -4
  52. package/packages/forms/dist/types/components/Input.d.ts.map +1 -1
  53. package/packages/forms/dist/types/components/LabelControl.d.ts +13 -8
  54. package/packages/forms/dist/types/components/LabelControl.d.ts.map +1 -1
  55. package/packages/forms/dist/types/components/Radio.d.ts +9 -4
  56. package/packages/forms/dist/types/components/Radio.d.ts.map +1 -1
  57. package/packages/forms/dist/types/components/Select.d.ts +9 -4
  58. package/packages/forms/dist/types/components/Select.d.ts.map +1 -1
  59. package/packages/forms/dist/types/components/Textarea.d.ts +8 -3
  60. package/packages/forms/dist/types/components/Textarea.d.ts.map +1 -1
  61. package/packages/forms/dist/types/components/controlled/CheckboxGroup.d.ts +16 -11
  62. package/packages/forms/dist/types/components/controlled/CheckboxGroup.d.ts.map +1 -1
  63. package/packages/forms/dist/types/components/controlled/RadioGroup.d.ts +17 -12
  64. package/packages/forms/dist/types/components/controlled/RadioGroup.d.ts.map +1 -1
  65. package/packages/forms/dist/types/components/index.d.ts +8 -8
  66. package/packages/forms/dist/types/components/index.d.ts.map +1 -1
  67. package/packages/forms/dist/types/components/inputStyle.d.ts +1 -1
  68. package/packages/forms/dist/types/components/inputStyle.d.ts.map +1 -1
  69. package/packages/forms/dist/types/index.d.ts +0 -1
  70. package/packages/forms/dist/types/index.d.ts.map +1 -1
  71. package/packages/forms/node_modules/.bin/autoprefixer +44 -6
  72. package/packages/forms/package.json +21 -16
  73. package/packages/forms/src/components/Checkbox.tsx +76 -80
  74. package/packages/forms/src/components/FieldsetControl.tsx +21 -28
  75. package/packages/forms/src/components/FileInput.tsx +92 -63
  76. package/packages/forms/src/components/Input.tsx +29 -31
  77. package/packages/forms/src/components/LabelControl.tsx +19 -25
  78. package/packages/forms/src/components/Radio.tsx +68 -69
  79. package/packages/forms/src/components/Select.tsx +65 -65
  80. package/packages/forms/src/components/Textarea.tsx +49 -54
  81. package/packages/forms/src/components/controlled/CheckboxGroup.tsx +15 -17
  82. package/packages/forms/src/components/controlled/RadioGroup.tsx +16 -18
  83. package/packages/forms/src/components/index.ts +8 -8
  84. package/packages/forms/src/components/inputStyle.ts +7 -8
  85. package/packages/forms/src/index.ts +0 -11
  86. package/packages/forms/tests/Checkbox.test.tsx +44 -0
  87. package/packages/forms/tests/FieldsetControl.test.tsx +68 -11
  88. package/packages/forms/tests/FileInput.test.tsx +25 -0
  89. package/packages/forms/tests/Input.test.tsx +12 -83
  90. package/packages/forms/tests/LabelControl.test.tsx +88 -20
  91. package/packages/forms/tests/Radio.test.tsx +23 -78
  92. package/packages/forms/tests/Select.test.tsx +30 -0
  93. package/packages/forms/tests/Textarea.test.tsx +25 -0
  94. package/packages/forms/tests/vitest.setup.ts +1 -0
  95. package/packages/forms/tsconfig.node.json +3 -2
  96. package/packages/forms/vite.config.ts +2 -1
  97. package/packages/helper/.turbo/turbo-build.log +12 -0
  98. package/packages/helper/dist/index.cjs.js +76 -0
  99. package/packages/helper/dist/index.es.js +119 -0
  100. package/packages/helper/dist/types/calc.d.ts +2 -0
  101. package/packages/helper/dist/types/calc.d.ts.map +1 -0
  102. package/packages/{forms/dist/types/utils/class.d.ts → helper/dist/types/cx.d.ts} +1 -1
  103. package/packages/helper/dist/types/cx.d.ts.map +1 -0
  104. package/packages/helper/dist/types/index.d.ts +6 -0
  105. package/packages/helper/dist/types/index.d.ts.map +1 -0
  106. package/packages/helper/dist/types/querySelector.d.ts +2 -0
  107. package/packages/helper/dist/types/querySelector.d.ts.map +1 -0
  108. package/packages/helper/dist/types/styles.d.ts +22 -0
  109. package/packages/helper/dist/types/styles.d.ts.map +1 -0
  110. package/packages/helper/dist/types/treefy.d.ts +8 -0
  111. package/packages/helper/dist/types/treefy.d.ts.map +1 -0
  112. package/packages/helper/node_modules/.bin/vitest +55 -0
  113. package/packages/helper/package.json +50 -0
  114. package/packages/helper/src/calc.ts +1 -0
  115. package/packages/helper/src/cx.ts +2 -0
  116. package/packages/helper/src/index.ts +5 -0
  117. package/packages/helper/src/querySelector.ts +20 -0
  118. package/packages/helper/src/styles.ts +114 -0
  119. package/packages/helper/src/treefy.ts +24 -0
  120. package/packages/helper/tests/calc.test.ts +22 -0
  121. package/packages/helper/tests/cx.test.ts +30 -0
  122. package/packages/helper/tests/querySelector.test.ts +24 -0
  123. package/packages/helper/tests/treefy.test.ts +111 -0
  124. package/packages/helper/tests/vitest.setup.ts +2 -0
  125. package/packages/helper/tsconfig.json +13 -0
  126. package/packages/helper/tsconfig.node.json +6 -0
  127. package/packages/helper/vite.config.ts +26 -0
  128. package/packages/markdown/.turbo/turbo-build.log +12 -0
  129. package/packages/markdown/README.md +129 -0
  130. package/packages/markdown/dist/index.cjs.js +149 -0
  131. package/packages/markdown/dist/index.es.js +16960 -0
  132. package/packages/markdown/dist/types/components/Markdown.d.ts +15 -0
  133. package/packages/markdown/dist/types/components/Markdown.d.ts.map +1 -0
  134. package/packages/markdown/dist/types/components/index.d.ts +2 -0
  135. package/packages/markdown/dist/types/components/index.d.ts.map +1 -0
  136. package/packages/markdown/dist/types/index.d.ts +2 -0
  137. package/packages/markdown/dist/types/index.d.ts.map +1 -0
  138. package/packages/markdown/dist/types/plugins/attr.d.ts +3 -0
  139. package/packages/markdown/dist/types/plugins/attr.d.ts.map +1 -0
  140. package/packages/markdown/dist/types/plugins/card.d.ts +3 -0
  141. package/packages/markdown/dist/types/plugins/card.d.ts.map +1 -0
  142. package/packages/markdown/dist/types/plugins/cell.d.ts +3 -0
  143. package/packages/markdown/dist/types/plugins/cell.d.ts.map +1 -0
  144. package/packages/markdown/dist/types/plugins/faq.d.ts +3 -0
  145. package/packages/markdown/dist/types/plugins/faq.d.ts.map +1 -0
  146. package/packages/markdown/dist/types/plugins/grid.d.ts +3 -0
  147. package/packages/markdown/dist/types/plugins/grid.d.ts.map +1 -0
  148. package/packages/markdown/dist/types/plugins/headings.d.ts +11 -0
  149. package/packages/markdown/dist/types/plugins/headings.d.ts.map +1 -0
  150. package/packages/markdown/dist/types/plugins/helper.d.ts +9 -0
  151. package/packages/markdown/dist/types/plugins/helper.d.ts.map +1 -0
  152. package/packages/markdown/dist/types/plugins/index.d.ts +9 -0
  153. package/packages/markdown/dist/types/plugins/index.d.ts.map +1 -0
  154. package/packages/markdown/dist/types/plugins/linkButton.d.ts +3 -0
  155. package/packages/markdown/dist/types/plugins/linkButton.d.ts.map +1 -0
  156. package/packages/markdown/dist/types/plugins/youtube.d.ts +3 -0
  157. package/packages/markdown/dist/types/plugins/youtube.d.ts.map +1 -0
  158. package/packages/markdown/node_modules/.bin/autoprefixer +55 -0
  159. package/packages/markdown/package.json +84 -0
  160. package/packages/markdown/src/components/Markdown.tsx +365 -0
  161. package/packages/markdown/src/components/index.ts +1 -0
  162. package/packages/markdown/src/global.d.ts +9 -0
  163. package/packages/markdown/src/index.ts +1 -0
  164. package/packages/markdown/src/plugins/attr.ts +19 -0
  165. package/packages/markdown/src/plugins/card.ts +57 -0
  166. package/packages/markdown/src/plugins/cell.ts +47 -0
  167. package/packages/markdown/src/plugins/faq.ts +40 -0
  168. package/packages/markdown/src/plugins/grid.ts +54 -0
  169. package/packages/markdown/src/plugins/headings.ts +38 -0
  170. package/packages/markdown/src/plugins/helper.ts +27 -0
  171. package/packages/markdown/src/plugins/index.ts +8 -0
  172. package/packages/markdown/src/plugins/linkButton.ts +26 -0
  173. package/packages/markdown/src/plugins/youtube.ts +49 -0
  174. package/packages/markdown/tsconfig.json +13 -0
  175. package/packages/markdown/tsconfig.node.json +7 -0
  176. package/packages/markdown/vite.config.ts +30 -0
  177. package/packages/tailwind-theme-plugin/#package.json# +51 -0
  178. package/packages/tailwind-theme-plugin/.turbo/turbo-build.log +12 -0
  179. package/packages/tailwind-theme-plugin/dist/index.cjs.js +1 -1
  180. package/packages/tailwind-theme-plugin/dist/index.es.js +4970 -6093
  181. package/packages/tailwind-theme-plugin/dist/types/index.d.ts +1 -4
  182. package/packages/tailwind-theme-plugin/dist/types/index.d.ts.map +1 -1
  183. package/packages/tailwind-theme-plugin/node_modules/.bin/autoprefixer +44 -6
  184. package/packages/tailwind-theme-plugin/package.json +11 -9
  185. package/packages/tailwind-theme-plugin/src/index.ts +241 -349
  186. package/packages/tailwind-theme-plugin/vite.config.ts +2 -0
  187. package/packages/core/src/libs/cx.ts +0 -2
  188. package/packages/core/src/libs/forward-ref.ts +0 -44
  189. package/packages/core/src/types/component.ts +0 -83
  190. package/packages/forms/dist/types/utils/class.d.ts.map +0 -1
  191. package/packages/forms/node_modules/.bin/acorn +0 -17
  192. package/packages/forms/node_modules/.bin/browserslist +0 -17
  193. package/packages/forms/node_modules/.bin/eslint +0 -17
  194. package/packages/forms/node_modules/.bin/tailwind +0 -17
  195. package/packages/forms/node_modules/.bin/tailwindcss +0 -17
  196. package/packages/forms/node_modules/.bin/ts-node +0 -17
  197. package/packages/forms/node_modules/.bin/ts-node-cwd +0 -17
  198. package/packages/forms/node_modules/.bin/ts-node-esm +0 -17
  199. package/packages/forms/node_modules/.bin/ts-node-script +0 -17
  200. package/packages/forms/node_modules/.bin/ts-node-transpile-only +0 -17
  201. package/packages/forms/node_modules/.bin/ts-script +0 -17
  202. package/packages/forms/node_modules/.bin/vitest +0 -17
  203. package/packages/forms/src/utils/class.ts +0 -2
  204. package/packages/tailwind-theme-plugin/node_modules/.bin/browserslist +0 -17
  205. package/packages/tailwind-theme-plugin/node_modules/.bin/tailwind +0 -17
  206. package/packages/tailwind-theme-plugin/node_modules/.bin/tailwindcss +0 -17
  207. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node +0 -17
  208. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-cwd +0 -17
  209. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-esm +0 -17
  210. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-script +0 -17
  211. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-transpile-only +0 -17
  212. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-script +0 -17
@@ -1,5 +1,5 @@
1
- import React from 'react'
2
- import { cx } from '../utils/class'
1
+ import React, { type ComponentPropsWithRef } from 'react'
2
+ import { cx, Style } from '@sakura-ui/helper'
3
3
  import { ControllerContext } from './context'
4
4
  import {
5
5
  type InputSize,
@@ -8,90 +8,86 @@ import {
8
8
  iconStyles
9
9
  } from './inputStyle'
10
10
 
11
- export interface CheckboxProps
12
- extends Omit<React.ComponentPropsWithRef<'input'>, 'size'> {
13
- size?: InputSize
11
+ export namespace Checkbox {
12
+ export interface Props extends Omit<ComponentPropsWithRef<'input'>, 'size'> {
13
+ size?: InputSize
14
+ }
14
15
  }
15
16
 
16
- export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
17
- (props, ref) => {
18
- const { id, className, size = 'lg', children, ...restProps } = props
19
- const checkboxId = id || React.useId()
20
- const ctx = React.useContext(ControllerContext)
21
- if (ctx.isRequired) {
22
- restProps.required = true
23
- }
24
- if (ctx.groupName) {
25
- restProps.name = ctx.groupName
26
- }
17
+ export const Checkbox = (props: Checkbox.Props) => {
18
+ const { id, className, size = 'lg', children, ...restProps } = props
19
+ const genId = React.useId()
20
+ const checkboxId = id || genId
21
+ const ctx = React.useContext(ControllerContext)
22
+ if (ctx.isRequired) {
23
+ restProps.required = true
24
+ }
25
+ if (ctx.groupName) {
26
+ restProps.name = ctx.groupName
27
+ }
27
28
 
28
- const scales: { [key in InputSize]: number } = {
29
- lg: 22 / 24,
30
- md: 18 / 24,
31
- sm: 18 / 24
32
- }
29
+ const scales: { [key in InputSize]: number } = {
30
+ lg: 22 / 24,
31
+ md: 18 / 24,
32
+ sm: 18 / 24
33
+ }
33
34
 
34
- const styleInput = `
35
- peer
36
- sr-only
37
- `
35
+ const styleInput = `
36
+ peer
37
+ sr-only
38
+ `
38
39
 
39
- const styleCheck = `
40
- bg-clip-content
41
- rounded
42
- border
43
- border-solid
44
- border-sumi-900
45
- fill-transparent
46
- peer-checked:fill-white
47
- peer-checked:bg-sea-600
48
- peer-checked:border-none
49
- peer-disabled:border-sumi-500
50
- peer-focus-visible:ring-2
51
- peer-focus-visible:ring-offset-2
52
- peer-focus-visible:ring-wood-500
53
- `
40
+ const styleCheck = `
41
+ bg-clip-content
42
+ rounded-sm
43
+ border
44
+ border-solid
45
+ border-solid-gray-900
46
+ fill-transparent
47
+ peer-checked:fill-white
48
+ peer-checked:bg-blue-600
49
+ peer-checked:border-none
50
+ peer-disabled:border-solid-gray-500
51
+ ${Style.Peer.focusRect}
52
+ `
54
53
 
55
- return (
56
- <label
57
- htmlFor={checkboxId}
58
- className={cx(
59
- borderlessInputBaseStyles,
60
- borderlessInputSizeStyles[size],
61
- className
62
- )}
63
- >
64
- <span className="flex items-center">
65
- <input
66
- id={checkboxId}
67
- className={styleInput}
68
- type="checkbox"
69
- aria-describedby={ctx.helperTextId}
70
- aria-errormessage={ctx.errorMessageId}
71
- aria-invalid={ctx.isInvalid ?? false}
72
- aria-required={ctx.isRequired ?? false}
73
- {...restProps}
74
- ref={ref}
75
- />
76
- <span className={cx(styleCheck, iconStyles[size])}>
77
- <svg
78
- xmlns="http://www.w3.org/2000/svg"
79
- aria-hidden={true}
80
- width="24"
81
- height="24"
82
- viewBox="0 0 24 24"
83
- >
84
- <title>check</title>
85
- <g transform={`scale(${scales[size]} ${scales[size]})`}>
86
- <path d="m9.55 17.65-5.325-5.325 1.05-1.075 4.275 4.275 9.175-9.175 1.05 1.075Z" />
87
- </g>
88
- </svg>
89
- </span>
90
- <span className="peer-disabled:text-sumi-500">{children}</span>
54
+ return (
55
+ <label
56
+ htmlFor={checkboxId}
57
+ className={cx(
58
+ borderlessInputBaseStyles,
59
+ borderlessInputSizeStyles[size],
60
+ className
61
+ )}
62
+ >
63
+ <span className="flex items-center">
64
+ <input
65
+ id={checkboxId}
66
+ className={styleInput}
67
+ type="checkbox"
68
+ aria-describedby={ctx.helperTextId}
69
+ aria-errormessage={ctx.errorMessageId}
70
+ aria-invalid={ctx.isInvalid ?? false}
71
+ aria-required={ctx.isRequired ?? false}
72
+ {...restProps}
73
+ />
74
+ <span className={cx(styleCheck, iconStyles[size])}>
75
+ <svg
76
+ xmlns="http://www.w3.org/2000/svg"
77
+ aria-hidden={true}
78
+ width="24"
79
+ height="24"
80
+ viewBox="0 0 24 24"
81
+ >
82
+ <g transform={`scale(${scales[size]} ${scales[size]})`}>
83
+ <path d="m9.55 17.65-5.325-5.325 1.05-1.075 4.275 4.275 9.175-9.175 1.05 1.075Z" />
84
+ </g>
85
+ </svg>
91
86
  </span>
92
- </label>
93
- )
94
- }
95
- )
87
+ <span className="peer-disabled:text-solid-gray-500">{children}</span>
88
+ </span>
89
+ </label>
90
+ )
91
+ }
96
92
 
97
93
  Checkbox.displayName = 'Checkbox'
@@ -1,21 +1,19 @@
1
- import React from 'react'
2
- import { cx } from '../utils/class'
1
+ import React, { type ComponentPropsWithRef } from 'react'
2
+ import { cx } from '@sakura-ui/helper'
3
3
  import { ControllerContext } from './context'
4
4
 
5
- export interface FieldsetControlProps
6
- extends React.ComponentPropsWithRef<'fieldset'> {
7
- labelText: string
8
- helperText?: string
9
- errorMessage?: string
10
- isInvalid?: boolean
11
- isRequired?: boolean
12
- direction?: 'flex-col' | 'flex-row'
5
+ export namespace FieldsetControl {
6
+ export interface Props extends ComponentPropsWithRef<'fieldset'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ direction?: 'flex-col' | 'flex-row'
13
+ }
13
14
  }
14
15
 
15
- export const FieldsetControl = React.forwardRef<
16
- HTMLFieldSetElement,
17
- FieldsetControlProps
18
- >((props, ref) => {
16
+ export const FieldsetControl = (props: FieldsetControl.Props) => {
19
17
  const id = React.useId()
20
18
  const {
21
19
  labelText,
@@ -43,35 +41,30 @@ export const FieldsetControl = React.forwardRef<
43
41
 
44
42
  return (
45
43
  <ControllerContext.Provider value={context}>
46
- <fieldset className={cx('mb-4', className)} ref={ref} {...restProps}>
44
+ <fieldset
45
+ className={cx('flex flex-col items-start gap-2', className)}
46
+ {...restProps}
47
+ >
47
48
  <legend>
48
- <p
49
- className={cx('block mb-2 text-label', isInvalid && 'text-sun-800')}
50
- >
49
+ <p className={cx('block text-label', isInvalid && 'text-red-800')}>
51
50
  {labelText}
52
- {isRequired && <span className="text-sun-800">&nbsp;*</span>}
51
+ {isRequired && <span className="text-red-800">&nbsp;*</span>}
53
52
  </p>
54
53
  </legend>
55
54
  <div className={cx('inline-flex', styleDirection)}>{children}</div>
56
55
  {helperText && (
57
- <p id={context.helperTextId} className="text-sup text-sumi-700 mt-2">
56
+ <p id={context.helperTextId} className="text-sup text-solid-gray-700">
58
57
  {helperText}
59
58
  </p>
60
59
  )}
61
60
  {isInvalid && (
62
- <p
63
- id={context.errorMessageId}
64
- className={cx(
65
- 'text-label text-sun-800',
66
- helperText ? 'mt-1' : 'mt-2'
67
- )}
68
- >
61
+ <p id={context.errorMessageId} className="text-label text-red-800">
69
62
  {errorMessage}
70
63
  </p>
71
64
  )}
72
65
  </fieldset>
73
66
  </ControllerContext.Provider>
74
67
  )
75
- })
68
+ }
76
69
 
77
70
  FieldsetControl.displayName = 'FieldsetControl'
@@ -1,76 +1,105 @@
1
- import React from 'react'
2
- import { cx } from '../utils/class'
1
+ import React, { type ComponentPropsWithRef } from 'react'
2
+ import { cx, Style } from '@sakura-ui/helper'
3
3
  import { ControllerContext } from './context'
4
+ import type { InputSize } from './inputStyle'
4
5
 
5
- export interface FileInputProps extends React.ComponentPropsWithRef<'input'> {}
6
+ export namespace FileInput {
7
+ export interface Props extends Omit<ComponentPropsWithRef<'input'>, 'size'> {
8
+ size?: InputSize
9
+ }
10
+ }
6
11
 
7
- export const FileInput = React.forwardRef<HTMLInputElement, FileInputProps>(
8
- (props, ref) => {
9
- const { id, className, ...restProps } = props
10
- const ctx = React.useContext(ControllerContext)
11
- if (ctx.isRequired) {
12
- restProps.required = true
13
- }
12
+ export const FileInput = (props: FileInput.Props) => {
13
+ const { id, className, size = 'lg', ...restProps } = props
14
+ const ctx = React.useContext(ControllerContext)
15
+ if (ctx.isRequired) {
16
+ restProps.required = true
17
+ }
14
18
 
15
- const base = `
16
- file:mr-2
17
- file:inline-block
18
- file:text-button
19
- file:text-center
20
- file:cursor-pointer
21
- file:select-none
22
- file:touch-manipulation
23
- file:whitespace-nowrap
24
- file:border
25
- file:border-solid
26
- file:border-sea-800
27
- file:active:border-sea-1200
28
- file:hover:border-sea-900
29
- file:disabled:border-sumi-500
30
- file:disabled:cursor-not-allowed
31
- `
19
+ const base = `
20
+ file:mr-2
21
+ file:inline-block
22
+ file:text-button
23
+ file:text-center
24
+ file:cursor-pointer
25
+ file:select-none
26
+ file:touch-manipulation
27
+ file:whitespace-nowrap
28
+ file:border
29
+ file:border-solid
30
+ file:border-blue-900
31
+ file:hover:border-blue-1000
32
+ file:active:border-blue-1200
33
+ file:disabled:border-solid-gray-500
34
+ file:disabled:cursor-not-allowed
35
+ `
32
36
 
33
- const secondary = `
34
- file:text-sea-800
35
- file:bg-transparent
36
- file:active:bg-sea-200
37
- file:hover:bg-sea-100
38
- file:active:text-sea-1200
39
- file:hover:text-sea-900
40
- file:disabled:text-sumi-500
41
- file:disabled:bg-transparent
42
- `
43
- const styleLg = `
37
+ const outline = `
38
+ file:text-blue-900
39
+ file:hover:text-blue-1000
40
+ file:active:text-blue-1200
41
+ file:bg-transparent
42
+ file:hover:bg-blue-200
43
+ file:active:bg-blue-300
44
+ file:disabled:text-solid-gray-500
45
+ file:disabled:bg-transparent
46
+ `
47
+
48
+ const styleInput = `
49
+ text-label
50
+ text-solid-gray-900
51
+ rounded-lg
52
+ outline-offset-2
53
+ aria-invalid:text-red-800
54
+ ${Style.hoverUnderline}
55
+ ${Style.focusRounded}
56
+ `
57
+
58
+ const sizeStyles: { [key in InputSize]: string } = {
59
+ // 16(p-4) * 2 + 22(text-button * leading-snug) + boader * 2 = 56px
60
+ lg: `
44
61
  file:p-4
45
62
  file:text-button
46
63
  file:rounded-lg
47
64
  file:leading-snug
65
+ `,
66
+ // 12(py-3) * 2 + 22(text-button * leading-snug) + boader * 2 = 48px
67
+ md: `
68
+ file:px-4
69
+ file:py-3
70
+ file:text-button
71
+ file:rounded-lg
72
+ file:leading-snug
73
+ `,
74
+ // 8(py-2) * 2 + 22(text-button * leading-snug) + boader * 2 = 40px
75
+ sm: `
76
+ file:px-3
77
+ file:py-2
78
+ file:text-button
79
+ file:rounded-md
80
+ file:leading-snug
48
81
  `
49
- const styleInput = `
50
- text-label
51
- text-sumi-900
52
- rounded-lg
53
- outline-offset-2
54
- focus:outline
55
- focus:outline-2
56
- focus:outline-wood-600
57
- aria-invalid:text-sun-800
58
- `
59
-
60
- return (
61
- <input
62
- type="file"
63
- id={id || ctx.id}
64
- className={cx(base, secondary, styleLg, styleInput, className)}
65
- aria-describedby={ctx.helperTextId}
66
- aria-errormessage={ctx.errorMessageId}
67
- aria-invalid={ctx.isInvalid ?? false}
68
- aria-required={ctx.isRequired ?? false}
69
- ref={ref}
70
- {...restProps}
71
- />
72
- )
73
82
  }
74
- )
83
+
84
+ // TODO: aria-required is not valid on input[type=file] and role="button" does not
85
+ // describe a file picker. Both need to be reworked (the required attribute changes
86
+ // form submission behaviour), so they are tracked separately from this change.
87
+ return (
88
+ // biome-ignore lint/a11y/useAriaPropsSupportedByRole: see the TODO above
89
+ // biome-ignore lint/a11y/useSemanticElements: see the TODO above
90
+ <input
91
+ type="file"
92
+ id={id || ctx.id}
93
+ className={cx(base, outline, sizeStyles[size], styleInput, className)}
94
+ aria-describedby={ctx.helperTextId}
95
+ aria-errormessage={ctx.errorMessageId}
96
+ aria-invalid={ctx.isInvalid ?? false}
97
+ aria-required={ctx.isRequired ?? false}
98
+ role="button"
99
+ aria-label="File Upload"
100
+ {...restProps}
101
+ />
102
+ )
103
+ }
75
104
 
76
105
  FileInput.displayName = 'FileInput'
@@ -1,5 +1,5 @@
1
- import React from 'react'
2
- import { cx } from '../utils/class'
1
+ import React, { type ComponentPropsWithRef } from 'react'
2
+ import { cx } from '@sakura-ui/helper'
3
3
  import { ControllerContext } from './context'
4
4
  import {
5
5
  type InputSize,
@@ -7,37 +7,35 @@ import {
7
7
  borderedInputSizeStyles
8
8
  } from './inputStyle'
9
9
 
10
- export interface InputProps
11
- extends Omit<React.ComponentPropsWithRef<'input'>, 'size'> {
12
- size?: InputSize
10
+ export namespace Input {
11
+ export interface Props extends Omit<ComponentPropsWithRef<'input'>, 'size'> {
12
+ size?: InputSize
13
+ }
13
14
  }
14
15
 
15
- export const Input = React.forwardRef<HTMLInputElement, InputProps>(
16
- (props, ref) => {
17
- const { id, className, size = 'lg', ...restProps } = props
18
- const ctx = React.useContext(ControllerContext)
19
- if (ctx.isRequired) {
20
- restProps.required = true
21
- }
22
-
23
- return (
24
- <input
25
- type="text"
26
- id={id || ctx.id}
27
- className={cx(
28
- borderedInputBaseStyles,
29
- borderedInputSizeStyles[size],
30
- className
31
- )}
32
- aria-describedby={ctx.helperTextId}
33
- aria-errormessage={ctx.errorMessageId}
34
- aria-invalid={ctx.isInvalid ?? false}
35
- aria-required={ctx.isRequired ?? false}
36
- ref={ref}
37
- {...restProps}
38
- />
39
- )
16
+ export const Input = (props: Input.Props) => {
17
+ const { id, className, size = 'lg', ...restProps } = props
18
+ const ctx = React.useContext(ControllerContext)
19
+ if (ctx.isRequired) {
20
+ restProps.required = true
40
21
  }
41
- )
22
+
23
+ return (
24
+ <input
25
+ type="text"
26
+ id={id || ctx.id}
27
+ className={cx(
28
+ borderedInputBaseStyles,
29
+ borderedInputSizeStyles[size],
30
+ className
31
+ )}
32
+ aria-describedby={ctx.helperTextId}
33
+ aria-errormessage={ctx.errorMessageId}
34
+ aria-invalid={ctx.isInvalid ?? false}
35
+ aria-required={ctx.isRequired ?? false}
36
+ {...restProps}
37
+ />
38
+ )
39
+ }
42
40
 
43
41
  Input.displayName = 'Input'
@@ -1,20 +1,18 @@
1
- import React from 'react'
2
- import { cx } from '../utils/class'
1
+ import React, { type ComponentPropsWithRef } from 'react'
2
+ import { cx } from '@sakura-ui/helper'
3
3
  import { ControllerContext } from './context'
4
4
 
5
- export interface LabelControlProps
6
- extends React.ComponentPropsWithRef<'label'> {
7
- labelText: string
8
- helperText?: string
9
- errorMessage?: string
10
- isInvalid?: boolean
11
- isRequired?: boolean
5
+ export namespace LabelControl {
6
+ export interface Props extends ComponentPropsWithRef<'label'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ }
12
13
  }
13
14
 
14
- export const LabelControl = React.forwardRef<
15
- HTMLLabelElement,
16
- LabelControlProps
17
- >((props, ref) => {
15
+ export const LabelControl = (props: LabelControl.Props) => {
18
16
  const id = React.useId()
19
17
  const {
20
18
  labelText,
@@ -36,44 +34,40 @@ export const LabelControl = React.forwardRef<
36
34
  }
37
35
 
38
36
  const styleHelp = `
39
- text-label text-sumi-700
37
+ text-label text-solid-gray-700
40
38
  `
41
39
 
42
40
  const styleError = `
43
- text-label text-sun-800
41
+ text-label text-red-800
44
42
  `
45
43
 
46
44
  return (
47
45
  <ControllerContext.Provider value={context}>
48
- <div className={cx('mb-4', className)}>
46
+ <div className={cx('flex flex-col items-start gap-2', className)}>
49
47
  <label
50
- className={cx('block mb-2 text-label', isInvalid && 'text-sun-800')}
48
+ className={cx('block text-label', isInvalid && 'text-red-800')}
51
49
  htmlFor={context.id}
52
- ref={ref}
53
50
  {...restProps}
54
51
  >
55
52
  {labelText}
56
53
  {isRequired && (
57
- <span className="text-label text-sun-800">&nbsp;*</span>
54
+ <span className="text-label text-red-800">&nbsp;*</span>
58
55
  )}
59
56
  </label>
60
57
  {helperText && (
61
- <p id={context.helperTextId} className={cx(styleHelp, 'mb-2')}>
58
+ <p id={context.helperTextId} className={styleHelp}>
62
59
  {helperText}
63
60
  </p>
64
61
  )}
65
62
  {children}
66
63
  {isInvalid && (
67
- <p
68
- id={context.errorMessageId}
69
- className={cx(styleError, helperText ? 'mt-1' : 'mt-2')}
70
- >
64
+ <p id={context.errorMessageId} className={styleError}>
71
65
  {errorMessage}
72
66
  </p>
73
67
  )}
74
68
  </div>
75
69
  </ControllerContext.Provider>
76
70
  )
77
- })
71
+ }
78
72
 
79
73
  LabelControl.displayName = 'LabelControl'