antd-solid 0.0.2 → 0.0.3

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 (105) hide show
  1. package/.eslintignore +2 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.vscode/settings.json +1 -1
  4. package/docs/.vitepress/components/Code.vue +127 -11
  5. package/docs/.vitepress/config.ts +39 -1
  6. package/docs/.vitepress/theme/index.css +4 -0
  7. package/docs/.vitepress/theme/index.ts +0 -1
  8. package/docs/components/{Button.tsx → button/Base.tsx} +1 -0
  9. package/docs/components/button/Danger.tsx +21 -0
  10. package/docs/components/button.md +19 -7
  11. package/docs/components/collapse/Base.tsx +25 -0
  12. package/docs/components/collapse.md +26 -0
  13. package/docs/components/color-picker/Base.tsx +14 -0
  14. package/docs/components/color-picker.md +26 -0
  15. package/docs/components/compact/Base.tsx +27 -0
  16. package/docs/components/compact.md +26 -0
  17. package/docs/components/date-picker/Base.tsx +15 -0
  18. package/docs/components/date-picker.md +26 -0
  19. package/docs/components/empty/Base.tsx +8 -0
  20. package/docs/components/empty/PRESENTED_IMAGE_SIMPLE.tsx +8 -0
  21. package/docs/components/empty.md +32 -0
  22. package/docs/components/form/Base.tsx +63 -0
  23. package/docs/components/form.md +27 -0
  24. package/docs/components/image/Base.tsx +13 -0
  25. package/docs/components/image.md +26 -0
  26. package/docs/components/input/AddonBeforeAndAfter.tsx +14 -0
  27. package/docs/components/input/Base.tsx +15 -0
  28. package/docs/components/input/Disabled.tsx +19 -0
  29. package/docs/components/input/PrefixAndSuffix.tsx +14 -0
  30. package/docs/components/input/Status.tsx +25 -0
  31. package/docs/components/input/TextArea.tsx +14 -0
  32. package/docs/components/input-number/Base.tsx +15 -0
  33. package/docs/components/input-number/MinMax.tsx +17 -0
  34. package/docs/components/input-number.md +34 -0
  35. package/docs/components/input.md +57 -0
  36. package/docs/components/modal/Base.tsx +35 -0
  37. package/docs/components/modal.md +26 -0
  38. package/docs/components/popconfirm/Base.tsx +25 -0
  39. package/docs/components/popconfirm.md +26 -0
  40. package/docs/components/popover/Base.tsx +19 -0
  41. package/docs/components/popover.md +26 -0
  42. package/docs/components/progress/Base.tsx +16 -0
  43. package/docs/components/progress.md +26 -0
  44. package/docs/components/radio/Base.tsx +10 -0
  45. package/docs/components/radio.md +26 -0
  46. package/docs/components/segmented/Base.tsx +10 -0
  47. package/docs/components/segmented/Block.tsx +10 -0
  48. package/docs/components/segmented/Disabled.tsx +28 -0
  49. package/docs/components/segmented.md +38 -0
  50. package/docs/components/select/AllowClear.tsx +18 -0
  51. package/docs/components/select/Base.tsx +17 -0
  52. package/docs/components/select.md +35 -0
  53. package/docs/components/switch/Base.tsx +14 -0
  54. package/docs/components/switch.md +26 -0
  55. package/docs/components/{Table.tsx → table/Base.tsx} +2 -2
  56. package/docs/components/table.md +12 -6
  57. package/docs/components/tabs/Base.tsx +25 -0
  58. package/docs/components/tabs/Segment.tsx +25 -0
  59. package/docs/components/tabs.md +33 -0
  60. package/docs/components/tooltip/Base.tsx +12 -0
  61. package/docs/components/tooltip/Placement.tsx +90 -0
  62. package/docs/components/tooltip.md +32 -0
  63. package/docs/components/tree/Base.tsx +45 -0
  64. package/docs/components/tree.md +26 -0
  65. package/global.d.ts +9 -0
  66. package/package.json +29 -14
  67. package/patches/vitepress@1.0.0-rc.4.patch +60 -0
  68. package/rollup.config.js +60 -20
  69. package/scripts/annotationNonProductionCode.js +30 -0
  70. package/scripts/cancelAnnotationNonProductionCode.js +30 -0
  71. package/src/Button.tsx +51 -12
  72. package/src/Collapse/index.tsx +86 -0
  73. package/src/ColorPicker.tsx +6 -61
  74. package/src/Compact.tsx +15 -0
  75. package/src/Empty/PRESENTED_IMAGE_SIMPLE.tsx +15 -0
  76. package/src/Empty/assets/EmptySvg.tsx +43 -0
  77. package/src/Empty/assets/SimpleEmptySvg.tsx +16 -0
  78. package/src/Empty/index.tsx +20 -0
  79. package/src/Input.tsx +154 -62
  80. package/src/InputNumber.tsx +68 -62
  81. package/src/Modal.tsx +90 -62
  82. package/src/Popconfirm.tsx +5 -3
  83. package/src/Segmented/index.tsx +95 -0
  84. package/src/Select.tsx +125 -3
  85. package/src/Switch.tsx +1 -1
  86. package/src/Table.tsx +36 -29
  87. package/src/Tabs.tsx +88 -45
  88. package/src/Tooltip.tsx +233 -87
  89. package/src/Tree.tsx +4 -4
  90. package/src/form/Form.tsx +94 -0
  91. package/src/form/FormItem.tsx +139 -0
  92. package/src/form/context.ts +16 -0
  93. package/src/form/index.ts +13 -0
  94. package/src/hooks/createControllableValue.ts +9 -6
  95. package/src/index.ts +12 -5
  96. package/src/types/index.ts +5 -0
  97. package/src/utils/EventEmitter.ts +15 -0
  98. package/src/utils/component.tsx +1 -1
  99. package/src/utils/solid.ts +8 -3
  100. package/src/utils/zh_CN.ts +236 -0
  101. package/tsconfig.json +6 -4
  102. package/unocss.config.ts +90 -6
  103. package/src/Button.css +0 -14
  104. package/src/Form.tsx +0 -98
  105. package/src/index.css +0 -21
package/src/Button.tsx CHANGED
@@ -8,10 +8,9 @@ import {
8
8
  createMemo,
9
9
  } from 'solid-js'
10
10
  import cs from 'classnames'
11
- import './Button.css'
12
11
 
13
12
  interface ButtonProps extends ParentProps, JSX.CustomAttributes<HTMLButtonElement> {
14
- type?: 'default' | 'primary' | 'text' | 'link'
13
+ type?: 'default' | 'primary' | 'dashed' | 'text' | 'link'
15
14
  onClick?: ((e: MouseEvent) => void) | ((e: MouseEvent) => Promise<unknown>)
16
15
  /**
17
16
  * 默认: middle
@@ -21,6 +20,10 @@ interface ButtonProps extends ParentProps, JSX.CustomAttributes<HTMLButtonElemen
21
20
  class?: string
22
21
  style?: JSX.CSSProperties
23
22
  loading?: boolean
23
+ /**
24
+ * 设置危险按钮
25
+ */
26
+ danger?: boolean
24
27
  }
25
28
 
26
29
  const sizeClassMap = {
@@ -31,12 +34,41 @@ const sizeClassMap = {
31
34
  } as const
32
35
 
33
36
  const typeClassMap = {
34
- default:
35
- 'ant-[border:1px_solid_rgb(217,217,217)] ant-bg-white ant-text-[var(--dark-color)] hover:ant-[border-color:var(--light-primary-color)] hover:ant-text-[var(--light-primary-color)]',
36
- primary:
37
- 'ant-border-none ant-bg-[var(--primary-color)] hover:ant-bg-[var(--light-primary-color)] ant-text-white',
38
- text: 'ant-border-none ant-bg-transparent ant-text-[var(--dark-color)] hover:ant-bg-[rgba(0,0,0,0.06)] active:ant-bg-[rgba(0,0,0,.15)]',
39
- link: 'ant-border-none ant-bg-transparent ant-text-[var(--primary-color)] hover:ant-text-[var(--light-primary-color)] active:ant-text-[var(--dark-primary-color)]',
37
+ default: (danger: boolean) =>
38
+ cs(
39
+ 'ant-bg-white',
40
+ danger
41
+ ? 'ant-[border:1px_solid_var(--ant-color-error)] ant-text-[var(--ant-color-error)] hover:ant-[border-color:var(--light-error-color)] hover:ant-text-[var(--light-error-color)] active:ant-[border-color:var(--dark-error-color)] active:ant-text-[var(--dark-error-color)]'
42
+ : 'ant-[border:1px_solid_var(--ant-color-border)] ant-text-[var(--dark-color)] hover:ant-[border-color:var(--light-primary-color)] hover:ant-text-[var(--light-primary-color)] active:ant-[border-color:var(--dark-primary-color)] active:ant-text-[var(--dark-primary-color)]',
43
+ ),
44
+ primary: (danger: boolean) =>
45
+ cs(
46
+ 'ant-border-none ant-text-white',
47
+ danger
48
+ ? 'ant-bg-[var(--ant-color-error)] hover:ant-bg-[var(--light-error-color)] active:ant-bg-[var(--dark-error-color)]'
49
+ : 'ant-bg-[var(--primary-color)] hover:ant-bg-[var(--light-primary-color)] active:ant-bg-[var(--dark-primary-color)]',
50
+ ),
51
+ dashed: (danger: boolean) =>
52
+ cs(
53
+ ' ant-bg-white',
54
+ danger
55
+ ? 'ant-[border:1px_dashed_var(--ant-color-error)] ant-text-[var(--ant-color-error)] hover:ant-[border-color:var(--light-error-color)] hover:ant-text-[var(--light-error-color)] active:ant-[border-color:var(--dark-error-color)] active:ant-text-[var(--dark-error-color)]'
56
+ : 'ant-[border:1px_dashed_var(--ant-color-border)] ant-text-[var(--dark-color)] hover:ant-[border-color:var(--light-primary-color)] hover:ant-text-[var(--light-primary-color)] active:ant-[border-color:var(--dark-primary-color)] active:ant-text-[var(--dark-primary-color)]',
57
+ ),
58
+ text: (danger: boolean) =>
59
+ cs(
60
+ 'ant-border-none ant-bg-transparent',
61
+ danger
62
+ ? 'ant-text-[var(--ant-color-error)] hover:ant-bg-[var(--error-bg-color)] active:ant-bg-[var(--error-bg-color)]'
63
+ : 'ant-text-[var(--dark-color)] hover:ant-bg-[rgba(0,0,0,0.06)] active:ant-bg-[rgba(0,0,0,.15)]',
64
+ ),
65
+ link: (danger: boolean) =>
66
+ cs(
67
+ 'ant-border-none ant-bg-transparent',
68
+ danger
69
+ ? 'ant-text-[var(--ant-color-error)] hover:ant-text-[var(--light-error-color)] active:ant-text-[var(--dark-error-color)]'
70
+ : 'ant-text-[var(--primary-color)] hover:ant-text-[var(--light-primary-color)] active:ant-text-[var(--dark-primary-color)]',
71
+ ),
40
72
  } as const
41
73
 
42
74
  const Button: Component<ButtonProps> = props => {
@@ -51,8 +83,9 @@ const Button: Component<ButtonProps> = props => {
51
83
  'ant-relative ant-cursor-pointer',
52
84
  mergedProps.class,
53
85
  sizeClassMap[mergedProps.size!],
54
- typeClassMap[mergedProps.type!],
86
+ typeClassMap[mergedProps.type!](props.danger ?? false),
55
87
  loading() && 'ant-opacity-65',
88
+ 'ant-[--color:--light-primary-color]'
56
89
  )}
57
90
  style={mergedProps.style}
58
91
  onClick={e => {
@@ -62,10 +95,16 @@ const Button: Component<ButtonProps> = props => {
62
95
  res.finally(() => setLoading(false))
63
96
  }
64
97
 
65
- if (mergedProps.type === 'default' || mergedProps.type === 'primary') {
98
+ if (
99
+ mergedProps.type === 'default' ||
100
+ mergedProps.type === 'primary' ||
101
+ mergedProps.type === 'dashed'
102
+ ) {
66
103
  const div = document.createElement('div')
67
- div.className =
68
- 'ant-absolute ant-inset-0 ant-rounded-inherit ant-[border:1px_solid_var(--light-primary-color)] ant-[animation:button-border_linear_1s]'
104
+ div.className = cs(
105
+ props.danger ? 'ant-[--color:var(--light-error-color)]' : 'ant-[--color:var(--light-primary-color)]',
106
+ 'ant-absolute ant-inset-0 ant-rounded-inherit ant-[background:radial-gradient(var(--color),rgba(0,0,0,0))] ant-z--1 ant-keyframes-button-border[inset:0px][inset:-6px] ant-[animation:button-border_ease-out_0.3s]',
107
+ )
69
108
  const onAnimationEnd = () => {
70
109
  div.remove()
71
110
  div.removeEventListener('animationend', onAnimationEnd)
@@ -0,0 +1,86 @@
1
+ import { type JSX, type JSXElement, type Component, For, Show } from 'solid-js'
2
+ import cs from 'classnames'
3
+ import { Transition } from 'solid-transition-group'
4
+ import { type Key } from '../types'
5
+ import createControllableValue from '../hooks/createControllableValue'
6
+
7
+ export interface CollapseItem {
8
+ key: Key
9
+ label: JSXElement
10
+ children: JSXElement
11
+ }
12
+
13
+ export interface CollapseProps {
14
+ class?: string
15
+ defaultActiveKey?: Key[]
16
+ activeKey?: Key[]
17
+ items: CollapseItem[]
18
+ style?: JSX.CSSProperties
19
+ }
20
+
21
+ const Collapse: Component<CollapseProps> = props => {
22
+ const [activeKey, setActiveKey] = createControllableValue<Key[]>(props, {
23
+ defaultValuePropName: 'defaultActiveKey',
24
+ valuePropName: 'activeKey',
25
+ defaultValue: [],
26
+ })
27
+
28
+ return (
29
+ <div
30
+ class={cs(
31
+ 'ant-rounded-[var(--ant-border-radius-lg)] ant-[border:1px_solid_var(--ant-color-border)] ant-border-b-0',
32
+ props.class,
33
+ )}
34
+ style={props.style}
35
+ >
36
+ <For each={props.items}>
37
+ {item => (
38
+ <div class="ant-[border-bottom:1px_solid_var(--ant-color-border)] first:ant-rounded-t-[var(--ant-border-radius-lg)] last:ant-rounded-b-[var(--ant-border-radius-lg)] ant-cursor-pointer">
39
+ <div
40
+ class="ant-bg-[var(--ant-collapse-header-bg)] ant-text-[var(--ant-color-text-heading)] ant-p-[var(--ant-collapse-header-padding)]"
41
+ onClick={() => {
42
+ setActiveKey(keys => {
43
+ if (keys.includes(item.key)) {
44
+ return keys.filter(key => key !== item.key)
45
+ }
46
+ return [...keys, item.key]
47
+ })
48
+ }}
49
+ >
50
+ <span
51
+ class={cs(
52
+ 'i-ant-design:right-outlined',
53
+ 'ant-mr-[var(--ant-margin-sm)] ant-duration-.3s',
54
+ activeKey().includes(item.key) && 'ant-rotate-[90deg]',
55
+ )}
56
+ />
57
+ {item.label}
58
+ </div>
59
+ <Transition
60
+ onEnter={(el, done) => {
61
+ el.animate([{ height: '0px' }, { height: `${el.scrollHeight}px` }], {
62
+ duration: 300,
63
+ }).finished.finally(done)
64
+ }}
65
+ onExit={(el, done) => {
66
+ el.animate([{ height: `${el.scrollHeight}px` }, { height: '0px' }], {
67
+ duration: 300,
68
+ }).finished.finally(done)
69
+ }}
70
+ >
71
+ <Show when={activeKey().includes(item.key)}>
72
+ <div class="ant-overflow-hidden">
73
+ <div class="ant-p-[var(--ant-padding-sm)] ant-[border-top:1px_solid_var(--ant-color-border)]">
74
+ {item.children}
75
+ </div>
76
+ </div>
77
+ </Show>
78
+ </Transition>
79
+ </div>
80
+ )}
81
+ </For>
82
+ </div>
83
+ )
84
+ }
85
+
86
+ export default Collapse
@@ -1,66 +1,11 @@
1
- import { type Component, createSignal, mergeProps, untrack } from 'solid-js'
2
- import { type ColorResult, SketchPicker, type Color, type RGBColor, type HSLColor } from 'react-color'
1
+ import { ColorPicker } from 'antd'
2
+ import { type Color } from 'antd/es/color-picker'
3
3
  import { reactToSolidComponent } from './utils/component'
4
- import Button from './Button'
5
- import Popover from './Popover'
6
- import { get, isNil } from 'lodash-es'
7
-
8
- const _SketchPicker = reactToSolidComponent(SketchPicker)
9
4
 
10
5
  export interface ColorPickerProps {
11
- /**
12
- * 默认: rgba
13
- */
14
- type?: 'rgba' | 'hsla'
15
- defaultColor?: string
16
- onChange?: (colorString: string, color: ColorResult) => void
17
- }
18
-
19
- function isRGBColor(color: Color): color is RGBColor {
20
- return ['r', 'g', 'b'].every(k => !isNil(get(color, k)))
21
- }
22
-
23
- function isHSLColor(color: Color): color is HSLColor {
24
- return ['r', 'g', 'b'].every(k => !isNil(get(color, k)))
25
- }
26
-
27
- function colorStringify(color: Color | undefined) {
28
- if (!color) return
29
-
30
- if (isRGBColor(color)) return `rgba(${color.r},${color.g},${color.b},${color.a ?? 1})`
31
-
32
- if (isHSLColor(color)) return `hsla(${color.h},${color.s},${color.l},${color.a ?? 1})`
33
-
34
- return color
35
- }
36
-
37
- const ColorPicker: Component<ColorPickerProps> = _props => {
38
- const props = mergeProps({ type: 'rgba' } as ColorPickerProps, _props)
39
- const [color, setColor] = createSignal(props.defaultColor ?? 'black')
40
-
41
- return (
42
- <Popover
43
- content={
44
- <_SketchPicker
45
- color={color()}
46
- onChange={colorResult =>
47
- { untrack(() => {
48
- const colorString = colorStringify(
49
- props.type === 'rgba' ? colorResult.rgb : colorResult.hsl,
50
- )!
51
- setColor(colorString)
52
-
53
- props.onChange?.(colorString, colorResult)
54
- }); }
55
- }
56
- />
57
- }
58
- trigger="click"
59
- placement="bottomLeft"
60
- >
61
- <Button style={{ background: color() }} />
62
- </Popover>
63
- )
6
+ defaultValue?: string | Color
7
+ value?: string | Color
8
+ onChange?: (value: Color, hex: string) => void
64
9
  }
65
10
 
66
- export default ColorPicker
11
+ export default reactToSolidComponent(ColorPicker)
@@ -0,0 +1,15 @@
1
+ import { type ParentProps } from 'solid-js'
2
+
3
+ interface CompactProps extends ParentProps {}
4
+
5
+ function Compact(props: CompactProps) {
6
+ return <div class="ant-compact ant-flex">{props.children}</div>
7
+ }
8
+
9
+ Compact.compactItemClass = 'p[.ant-compact]:ant-ml--1px'
10
+ Compact.compactItemRounded0Class = 'p[.ant-compact>*]:ant-rounded-0'
11
+ Compact.compactItemRoundedLeftClass = 'p[.ant-compact>:first-child]:ant-rounded-l-6px'
12
+ Compact.compactItemRoundedRightClass = 'p[.ant-compact>:last-child]:ant-rounded-r-6px'
13
+ Compact.compactItemZIndexClass = 'p[.ant-compact>*]:focus:ant-z-10 p[.ant-compact>*]:focus-within:ant-z-10'
14
+
15
+ export default Compact
@@ -0,0 +1,15 @@
1
+ import { type Component } from 'solid-js'
2
+ import SimpleEmptySvg from './assets/SimpleEmptySvg'
3
+
4
+ const PRESENTED_IMAGE_SIMPLE: Component = () => {
5
+ return (
6
+ <div class='ant-my-[var(--ant-margin-xl)] ant-mx-[var(--ant-margin-xs)]'>
7
+ <div class="ant-mb-[var(--ant-margin-xs)] ant-flex ant-justify-center">
8
+ <SimpleEmptySvg />
9
+ </div>
10
+ <div class="ant-text-[var(--ant-color-text-disabled)] ant-text-center">暂无数据</div>
11
+ </div>
12
+ )
13
+ }
14
+
15
+ export default PRESENTED_IMAGE_SIMPLE
@@ -0,0 +1,43 @@
1
+ const EmptySvg = () => (
2
+ <svg width="184" height="100" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg">
3
+ <g fill="none" fill-rule="evenodd">
4
+ <g transform="translate(24 31.67)">
5
+ <ellipse
6
+ fill-opacity=".8"
7
+ fill="#F5F5F7"
8
+ cx="67.797"
9
+ cy="106.89"
10
+ rx="67.797"
11
+ ry="12.668"
12
+ />
13
+ <path
14
+ d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
15
+ fill="#AEB8C2"
16
+ />
17
+ <path
18
+ d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
19
+ fill="url(#linearGradient-1)"
20
+ transform="translate(13.56)"
21
+ />
22
+ <path
23
+ d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
24
+ fill="#F5F5F7"
25
+ />
26
+ <path
27
+ d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
28
+ fill="#DCE0E6"
29
+ />
30
+ </g>
31
+ <path
32
+ d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
33
+ fill="#DCE0E6"
34
+ />
35
+ <g transform="translate(149.65 15.383)" fill="#FFF">
36
+ <ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815" />
37
+ <path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z" />
38
+ </g>
39
+ </g>
40
+ </svg>
41
+ )
42
+
43
+ export default EmptySvg
@@ -0,0 +1,16 @@
1
+ const EmptySvg = () => (
2
+ <svg width="64" height="41" viewBox="0 0 64 41" xmlns="http://www.w3.org/2000/svg">
3
+ <g transform="translate(0 1)" fill="none" fill-rule="evenodd">
4
+ <ellipse fill="#f5f5f5" cx="32" cy="33" rx="32" ry="7" />
5
+ <g fill-rule="nonzero" stroke="#d9d9d9">
6
+ <path d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z" />
7
+ <path
8
+ d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
9
+ fill="#fafafa"
10
+ />
11
+ </g>
12
+ </g>
13
+ </svg>
14
+ )
15
+
16
+ export default EmptySvg
@@ -0,0 +1,20 @@
1
+ import { type Component } from 'solid-js'
2
+ import PRESENTED_IMAGE_SIMPLE from './PRESENTED_IMAGE_SIMPLE'
3
+ import EmptySvg from './assets/EmptySvg'
4
+
5
+ const Empty: Component & {
6
+ PRESENTED_IMAGE_SIMPLE: Component
7
+ } = () => {
8
+ return (
9
+ <div>
10
+ <div class='ant-mb-[var(--ant-margin-xs)] ant-flex ant-justify-center'>
11
+ <EmptySvg />
12
+ </div>
13
+ <div class='ant-text-[var(--ant-color-text)] ant-text-center'>暂无数据</div>
14
+ </div>
15
+ )
16
+ }
17
+
18
+ Empty.PRESENTED_IMAGE_SIMPLE = PRESENTED_IMAGE_SIMPLE
19
+
20
+ export default Empty
package/src/Input.tsx CHANGED
@@ -1,89 +1,173 @@
1
- import { omit } from 'lodash-es'
2
- import { Show, splitProps } from 'solid-js'
1
+ import { isNil, omit } from 'lodash-es'
2
+ import { Show, createMemo, splitProps } from 'solid-js'
3
3
  import type { JSX, JSXElement, Component } from 'solid-js'
4
4
  import cs from 'classnames'
5
5
  import createControllableValue from './hooks/createControllableValue'
6
6
  import { Dynamic } from 'solid-js/web'
7
+ import Compact from './Compact'
7
8
 
8
- type CommonInputProps<T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement> = JSX.CustomAttributes<T> & {
9
- textarea?: boolean
10
- defaultValue?: string | undefined
11
- value?: string | undefined
12
- addonBefore?: JSXElement
13
- addonAfter?: JSXElement
14
- /**
15
- * 仅供 InputNumber 使用
16
- */
17
- inputAfter?: JSXElement
18
- placeholder?: string
19
- onChange?: JSX.InputEventHandler<T, InputEvent>
20
- onPressEnter?: JSX.EventHandler<T, KeyboardEvent>
21
- onKeyDown?: JSX.EventHandler<T, KeyboardEvent>
9
+ type CommonInputProps<T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement> =
10
+ JSX.CustomAttributes<T> & {
11
+ textarea?: boolean
12
+ defaultValue?: string | undefined
13
+ value?: string | undefined
14
+ addonBefore?: JSXElement
15
+ addonAfter?: JSXElement
16
+ prefix?: JSXElement
17
+ suffix?: JSXElement
18
+ placeholder?: string
19
+ /**
20
+ * 仅供 InputNumber 使用
21
+ */
22
+ actions?: JSXElement
23
+ /**
24
+ * 设置校验状态
25
+ */
26
+ status?: 'error' | 'warning'
27
+ onChange?: JSX.InputEventHandler<T, InputEvent>
28
+ onPressEnter?: JSX.EventHandler<T, KeyboardEvent>
29
+ onKeyDown?: JSX.EventHandler<T, KeyboardEvent>
30
+ }
31
+
32
+ const statusClassDict = {
33
+ default: (disabled: boolean) =>
34
+ cs(
35
+ 'ant-[border:1px_solid_var(--ant-color-border)]',
36
+ !disabled &&
37
+ 'hover:ant-border-[var(--primary-color)] focus-within:ant-border-[var(--primary-color)] focus-within:ant-[box-shadow:0_0_0_2px_rgba(5,145,255,0.1)]',
38
+ ),
39
+ error: (disabled: boolean) =>
40
+ cs(
41
+ 'ant-[border:1px_solid_var(--ant-color-error)]',
42
+ !disabled &&
43
+ 'hover:ant-border-[var(--light-error-color)] focus-within:ant-[box-shadow:0_0_0_2px_rgba(255,38,5,.06)]',
44
+ ),
45
+ warning: (disabled: boolean) =>
46
+ cs(
47
+ 'ant-[border:1px_solid_var(--warning-color)]',
48
+ !disabled &&
49
+ 'hover:ant-border-[var(--color-warning-border-hover)] focus-within:ant-[box-shadow:0_0_0_2px_rgba(255,215,5,.1)]',
50
+ ),
22
51
  }
23
52
 
24
- export function CommonInput<T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement>(props: CommonInputProps<T> &
25
- Omit<JSX.InputHTMLAttributes<T>, 'onChange' | 'onInput' | 'onKeyDown'>) {
26
- const [{ onChange, onPressEnter, onKeyDown }, inputProps] = splitProps(props, [
53
+ export function CommonInput<T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement>(
54
+ props: CommonInputProps<T> &
55
+ Omit<JSX.InputHTMLAttributes<T>, 'onChange' | 'onInput' | 'onKeyDown'>,
56
+ ) {
57
+ const [{ style, onChange, onPressEnter, onKeyDown }, inputProps] = splitProps(props, [
27
58
  'defaultValue',
28
59
  'value',
29
60
  'class',
30
61
  'addonBefore',
31
62
  'addonAfter',
32
- 'inputAfter',
63
+ 'suffix',
33
64
  'onChange',
34
65
  'onPressEnter',
35
66
  'onKeyDown',
67
+ 'actions',
68
+ 'style',
36
69
  ])
37
70
 
38
71
  const [_, controllableProps] = splitProps(props, ['onChange'])
39
72
  const [value, setValue] = createControllableValue(controllableProps)
40
73
 
74
+ const inputWrapClass = createMemo(() =>
75
+ cs(
76
+ 'ant-px-11px ant-py-4px ant-rounded-6px',
77
+ !props.textarea && 'ant-h-32px',
78
+ props.addonBefore ? 'ant-rounded-l-0' : Compact.compactItemRoundedLeftClass,
79
+ props.addonAfter ? 'ant-rounded-r-0' : Compact.compactItemRoundedRightClass,
80
+ statusClassDict[props.status ?? 'default'](!!inputProps.disabled),
81
+ Compact.compactItemRounded0Class,
82
+ Compact.compactItemZIndexClass,
83
+ ),
84
+ )
85
+ const hasPrefixOrSuffix = createMemo(
86
+ () => !isNil(props.prefix) || !isNil(props.suffix) || !isNil(props.actions),
87
+ )
88
+ const inputJSX = (
89
+ <Dynamic<Component<JSX.InputHTMLAttributes<HTMLInputElement>>>
90
+ component={
91
+ (props.textarea ? 'textarea' : 'input') as unknown as Component<
92
+ JSX.InputHTMLAttributes<HTMLInputElement>
93
+ >
94
+ }
95
+ {...(inputProps as JSX.InputHTMLAttributes<HTMLInputElement>)}
96
+ class={cs(
97
+ 'ant-w-full ant-[outline:none] ant-text-14px',
98
+ !hasPrefixOrSuffix() && inputWrapClass(),
99
+ inputProps.disabled &&
100
+ 'ant-bg-[var(--ant-color-bg-container-disabled)] ant-cursor-not-allowed',
101
+ )}
102
+ value={value() ?? ''}
103
+ onInput={e => {
104
+ setValue(e.target.value)
105
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
106
+ onChange?.(e as any)
107
+
108
+ if (Object.keys(props).includes('value')) {
109
+ e.target.value = value()
110
+ }
111
+ }}
112
+ onKeyDown={e => {
113
+ if (e.key === 'Enter') {
114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
115
+ onPressEnter?.(e as any)
116
+ }
117
+
118
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
119
+ onKeyDown?.(e as any)
120
+ }}
121
+ />
122
+ )
123
+
41
124
  return (
42
- <div class="ant-flex ant-w-full">
125
+ <div class={cs('ant-flex ant-w-full', Compact.compactItemClass)} style={style}>
43
126
  <Show when={props.addonBefore}>
44
- <div class="ant-shrink-0 ant-flex ant-justify-center ant-items-center ant-px-11px ant-bg-[rgba(0,0,0,.02)] ant-[border:1px_solid_#d9d9d9] ant-border-r-0 ant-rounded-l-6px ant-text-14px">
127
+ <div
128
+ class={cs(
129
+ 'ant-shrink-0 ant-flex ant-justify-center ant-items-center ant-px-11px ant-bg-[rgba(0,0,0,.02)] ant-[border:1px_solid_var(--ant-color-border)] ant-border-r-0 ant-rounded-l-6px ant-text-14px',
130
+ Compact.compactItemRounded0Class,
131
+ Compact.compactItemRoundedLeftClass,
132
+ )}
133
+ >
45
134
  {props.addonBefore}
46
135
  </div>
47
136
  </Show>
48
137
 
49
- <div class="ant-w-full ant-relative ant-[--input-after-display:none] hover:ant-[--input-after-display:block] p-hover-child[input]:ant-border-[var(--primary-color)]">
50
- <Dynamic<Component<JSX.InputHTMLAttributes<HTMLInputElement>>>
51
- component={
52
- (props.textarea ? 'textarea' : 'input') as unknown as Component<
53
- JSX.InputHTMLAttributes<HTMLInputElement>
54
- >
55
- }
56
- {...inputProps as JSX.InputHTMLAttributes<HTMLInputElement>}
138
+ <Show when={hasPrefixOrSuffix()} fallback={inputJSX}>
139
+ <div
57
140
  class={cs(
58
- 'ant-w-full ant-py-0 ant-px-11px ant-[outline:none] ant-text-14px ant-rounded-6px ant-[border:1px_solid_#d9d9d9] focus:ant-border-[var(--primary-color)] focus:ant-[box-shadow:0_0_0_2px_rgba(5,145,255,0.1)] ant-py-8px',
59
- !props.textarea && 'ant-h-32px',
60
- props.class,
61
- props.addonBefore && 'ant-rounded-l-0',
62
- props.addonAfter && 'ant-rounded-r-0',
141
+ 'ant-flex ant-items-center ant-w-full ant-relative ant-[--input-after-display:none] hover:ant-[--input-after-display:block] p:hover-child[input]:ant-border-[var(--primary-color)]',
142
+ inputWrapClass(),
63
143
  )}
64
- value={value() ?? ''}
65
- onInput={e => {
66
- setValue(e.target.value)
67
- onChange?.(e as any)
68
- }}
69
- onKeyDown={e => {
70
- if (e.key === 'Enter') {
71
- onPressEnter?.(e as any)
72
- }
73
-
74
- onKeyDown?.(e as any)
75
- }}
76
- />
77
-
78
- <Show when={props.inputAfter}>
79
- <div class="ant-[display:var(--input-after-display)] ant-absolute ant-top-0 ant-bottom-0 ant-right-0 ant-h-[calc(100%-2px)] ant-translate-y-1px -ant-translate-x-1px">
80
- {props.inputAfter}
81
- </div>
82
- </Show>
83
- </div>
144
+ >
145
+ <Show when={props.prefix}>
146
+ <div class="ant-mr-4px">{props.prefix}</div>
147
+ </Show>
148
+
149
+ {inputJSX}
150
+
151
+ <Show when={props.suffix}>
152
+ <div class="ant-ml-4px">{props.suffix}</div>
153
+ </Show>
154
+
155
+ <Show when={props.actions}>
156
+ <div class="ant-[display:var(--input-after-display)] ant-absolute ant-top-0 ant-bottom-0 ant-right-0 ant-h-[calc(100%-2px)] ant-translate-y-1px -ant-translate-x-1px">
157
+ {props.actions}
158
+ </div>
159
+ </Show>
160
+ </div>
161
+ </Show>
84
162
 
85
163
  <Show when={props.addonAfter}>
86
- <div class="ant-shrink-0 ant-flex ant-justify-center ant-items-center ant-px-11px ant-bg-[rgba(0,0,0,.02)] ant-[border:1px_solid_#d9d9d9] ant-border-l-0 ant-rounded-r-6px ant-text-14px">
164
+ <div
165
+ class={cs(
166
+ 'ant-shrink-0 ant-flex ant-justify-center ant-items-center ant-px-11px ant-bg-[rgba(0,0,0,.02)] ant-[border:1px_solid_var(--ant-color-border)] ant-border-l-0 ant-rounded-r-6px ant-text-14px',
167
+ Compact.compactItemRounded0Class,
168
+ Compact.compactItemRoundedRightClass,
169
+ )}
170
+ >
87
171
  {props.addonAfter}
88
172
  </div>
89
173
  </Show>
@@ -91,20 +175,28 @@ export function CommonInput<T extends HTMLInputElement | HTMLTextAreaElement = H
91
175
  )
92
176
  }
93
177
 
94
- export type InputProps = Omit<CommonInputProps, 'inputAfter' | 'textarea'> &
95
- Omit<JSX.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'onKeyDown'>
178
+ export type InputProps = Omit<CommonInputProps, 'actions' | 'textarea'> &
179
+ Omit<JSX.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'onKeyDown'>
96
180
 
97
- export type TextAreaProps = Omit<CommonInputProps<HTMLTextAreaElement>, 'inputAfter' | 'textarea'> &
98
- Omit<JSX.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange' | 'onInput' | 'onKeyDown'>
181
+ export type TextAreaProps = Omit<
182
+ CommonInputProps<HTMLTextAreaElement>,
183
+ 'prefix' | 'suffix' | 'textarea'
184
+ > &
185
+ Omit<
186
+ JSX.TextareaHTMLAttributes<HTMLTextAreaElement>,
187
+ 'actions' | 'onChange' | 'onInput' | 'onKeyDown'
188
+ >
99
189
 
100
190
  const Input: Component<InputProps> & {
101
191
  TextArea: Component<TextAreaProps>
102
192
  } = props => {
103
- return <CommonInput {...omit(props, ['inputAfter'])} />
193
+ return <CommonInput {...omit(props, ['actions'])} />
104
194
  }
105
195
 
106
196
  Input.TextArea = props => {
107
- return <CommonInput<HTMLTextAreaElement> textarea {...omit(props, ['inputAfter'])} />
197
+ return (
198
+ <CommonInput<HTMLTextAreaElement> textarea {...omit(props, ['prefix', 'suffix', 'actions'])} />
199
+ )
108
200
  }
109
201
 
110
202
  export default Input