antd-solid 0.0.5 → 0.0.6

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 (50) hide show
  1. package/package.json +3 -2
  2. package/src/Button.tsx +125 -0
  3. package/src/Collapse/index.tsx +86 -0
  4. package/src/ColorPicker.tsx +11 -0
  5. package/src/Compact.tsx +15 -0
  6. package/src/DatePicker.tsx +22 -0
  7. package/src/Empty/PRESENTED_IMAGE_SIMPLE.tsx +15 -0
  8. package/src/Empty/assets/EmptySvg.tsx +43 -0
  9. package/src/Empty/assets/SimpleEmptySvg.tsx +16 -0
  10. package/src/Empty/index.tsx +20 -0
  11. package/src/Image.tsx +29 -0
  12. package/src/Input.tsx +202 -0
  13. package/src/InputNumber.test.tsx +46 -0
  14. package/src/InputNumber.tsx +125 -0
  15. package/src/Modal.tsx +196 -0
  16. package/src/Popconfirm.tsx +75 -0
  17. package/src/Popover.tsx +30 -0
  18. package/src/Progress.tsx +4 -0
  19. package/src/Radio.tsx +132 -0
  20. package/src/Result.tsx +38 -0
  21. package/src/Segmented/index.tsx +95 -0
  22. package/src/Select.tsx +128 -0
  23. package/src/Skeleton.tsx +14 -0
  24. package/src/Spin.tsx +23 -0
  25. package/src/Switch.tsx +34 -0
  26. package/src/Table.tsx +53 -0
  27. package/src/Tabs.tsx +131 -0
  28. package/src/Timeline.tsx +33 -0
  29. package/src/Tooltip.tsx +355 -0
  30. package/src/Tree.tsx +246 -0
  31. package/src/Upload.tsx +10 -0
  32. package/src/form/Form.tsx +94 -0
  33. package/src/form/FormItem.tsx +139 -0
  34. package/src/form/context.ts +16 -0
  35. package/src/form/index.ts +13 -0
  36. package/src/hooks/createControllableValue.ts +68 -0
  37. package/src/hooks/createUpdateEffect.ts +16 -0
  38. package/src/hooks/index.ts +2 -0
  39. package/src/hooks/useClickAway.ts +18 -0
  40. package/src/hooks/useSize.ts +26 -0
  41. package/src/types/index.ts +5 -0
  42. package/src/utils/EventEmitter.ts +15 -0
  43. package/src/utils/ReactToSolid.tsx +38 -0
  44. package/src/utils/SolidToReact.tsx +27 -0
  45. package/src/utils/array.ts +21 -0
  46. package/src/utils/component.tsx +85 -0
  47. package/src/utils/solid.ts +53 -0
  48. package/src/utils/zh_CN.ts +236 -0
  49. package/dist/index.esm.js +0 -2369
  50. package/dist/index.umd.js +0 -1
package/src/Select.tsx ADDED
@@ -0,0 +1,128 @@
1
+ import {
2
+ type JSXElement,
3
+ type Component,
4
+ For,
5
+ createSelector,
6
+ createSignal,
7
+ Show,
8
+ createMemo,
9
+ } from 'solid-js'
10
+ import Tooltip from './Tooltip'
11
+ import { type Key } from './types'
12
+ import createControllableValue from './hooks/createControllableValue'
13
+ import cs from 'classnames'
14
+ import { useClickAway } from './hooks'
15
+ import { isNil } from 'lodash-es'
16
+
17
+ interface SelectOption {
18
+ label: JSXElement
19
+ value: Key
20
+ }
21
+
22
+ interface SelectProps {
23
+ value?: Key
24
+ onChange?: (value: Key) => void
25
+ options: SelectOption[]
26
+ placeholder?: string
27
+ allowClear?: boolean
28
+ class?: string
29
+ }
30
+
31
+ const Select: Component<SelectProps> = props => {
32
+ let select: HTMLDivElement
33
+
34
+ const [value, setValue] = createControllableValue<Key | undefined>(props)
35
+ const selectedValue = createSelector(value)
36
+ const selectedOption = createMemo(() => !isNil(value()) ? props.options.find(option => option.value === value()) : undefined)
37
+
38
+ const [open, setOpen] = createSignal(false)
39
+ useClickAway(
40
+ () => setOpen(false),
41
+ () => select!,
42
+ )
43
+
44
+ const [width, setWidth] = createSignal(0)
45
+ const [hover, setHover] = createSignal(false)
46
+ const showClearBtn = createMemo(() => props.allowClear && hover() && !isNil(value()))
47
+
48
+ return (
49
+ <Tooltip
50
+ mode="light"
51
+ open={open()}
52
+ onOpenChange={setOpen}
53
+ trigger={[]}
54
+ placement="bottomLeft"
55
+ arrow={false}
56
+ contentStyle={{
57
+ padding: 0,
58
+ }}
59
+ content={close => (
60
+ <div class="ant-bg-white ant-w-200px" style={{ width: `${width()}px` }}>
61
+ <For each={props.options}>
62
+ {item => (
63
+ <div
64
+ class={cs(
65
+ 'ant-box-content ant-px-12px ant-py-5px ant-h-22px ant-leading-22px hover:ant-bg-[var(--hover-bg-color)]',
66
+ selectedValue(item.value) ? '!ant-bg-[var(--active-bg-color)]' : '',
67
+ )}
68
+ onClick={() => {
69
+ setValue(item.value)
70
+ close()
71
+ }}
72
+ >
73
+ {item.label}
74
+ </div>
75
+ )}
76
+ </For>
77
+ </div>
78
+ )}
79
+ >
80
+ <div
81
+ ref={select!}
82
+ class={cs('ant-h-32px ant-leading-32px ant-rounded-6px ant-[border:1px_solid_var(--ant-color-border)] ant-px-11px focus:ant-[border-color:var(--primary-color)]', props.class)}
83
+ tabIndex="0"
84
+ onClick={e => {
85
+ setOpen(true)
86
+ setWidth(e.currentTarget.offsetWidth)
87
+ e.currentTarget.focus()
88
+ }}
89
+ onMouseEnter={() => setHover(true)}
90
+ onMouseLeave={() => setHover(false)}
91
+ style={{
92
+ '--ant-arrow-color': 'rgba(146, 146, 146, 1)',
93
+ '--ant-clear-color': 'rgba(146, 146, 146, 1)',
94
+ '--ant-clear-color-hover': 'rgba(194, 194, 194, 1)',
95
+ }}
96
+ >
97
+ <div class="ant-relative ant-h-full">
98
+ <Show
99
+ when={!isNil(value())}
100
+ fallback={
101
+ <input
102
+ class="ant-h-full ant-w-full ant-float-left ant-[outline:none]"
103
+ readOnly
104
+ placeholder={props.placeholder}
105
+ />
106
+ }
107
+ >
108
+ <div>{selectedOption()!.label ?? value()}</div>
109
+ </Show>
110
+
111
+ <div class="ant-absolute ant-top-0 ant-bottom-0 ant-right-0">
112
+ <Show when={showClearBtn()} fallback={<span class="i-ant-design:down-outlined ant-text-[var(--ant-allow-color)]" />}>
113
+ <span
114
+ class="i-ant-design:close-circle-filled ant-cursor-pointer ant-text-[var(--ant-clear-color)] hover:ant-text-[var(--ant-clear-color-hover)]"
115
+ onClick={e => {
116
+ e.stopPropagation()
117
+ setValue(undefined)
118
+ }}
119
+ />
120
+ </Show>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </Tooltip>
125
+ )
126
+ }
127
+
128
+ export default Select
@@ -0,0 +1,14 @@
1
+ import { Skeleton as SkeletonAntd } from 'antd'
2
+ import { reactToSolidComponent, replaceClassName } from './utils/component'
3
+
4
+ const _Skeleton = replaceClassName(reactToSolidComponent(SkeletonAntd))
5
+
6
+ const Image = replaceClassName(reactToSolidComponent(SkeletonAntd.Image))
7
+
8
+ const Skeleton = _Skeleton as typeof _Skeleton & {
9
+ Image: typeof Image
10
+ }
11
+
12
+ Skeleton.Image = Image
13
+
14
+ export default Skeleton
package/src/Spin.tsx ADDED
@@ -0,0 +1,23 @@
1
+ import { Show, type Component, type ParentProps } from 'solid-js'
2
+
3
+ interface SpinProps extends ParentProps {
4
+ /**
5
+ * 是否为加载中状态
6
+ */
7
+ spinning?: boolean
8
+ }
9
+
10
+ const Spin: Component<SpinProps> = props => {
11
+ return (
12
+ <div class="ant-relative ant-min-h-32px">
13
+ {props.children}
14
+ <Show when={props.spinning}>
15
+ <div class="ant-absolute ant-inset-0 ant-flex ant-items-center ant-justify-center ant-bg-[rgba(255,255,255,.5)]">
16
+ <span class="i-ant-design:loading keyframes-spin ant-[animation:spin_1s_linear_infinite] ant-text-32px ant-text-[var(--primary-color)]" />
17
+ </div>
18
+ </Show>
19
+ </div>
20
+ )
21
+ }
22
+
23
+ export default Spin
package/src/Switch.tsx ADDED
@@ -0,0 +1,34 @@
1
+ import { type Component } from 'solid-js'
2
+ import createControllableValue from './hooks/createControllableValue'
3
+ import cs from 'classnames'
4
+
5
+ export interface SwitchProps {
6
+ defaultChecked?: boolean
7
+ checked?: boolean
8
+ onChange?: (checked: boolean) => void
9
+ }
10
+
11
+ const Switch: Component<SwitchProps> = props => {
12
+ const [checked, setChecked] = createControllableValue<boolean>(props, {
13
+ defaultValuePropName: 'defaultChecked',
14
+ valuePropName: 'checked',
15
+ })
16
+ return (
17
+ <button
18
+ class={cs(
19
+ 'ant-w-44px ant-h-22px ant-rounded-100px ant-relative',
20
+ checked() ? 'ant-bg-[var(--primary-color)]' : 'ant-bg-[rgba(0,0,0,0.45)]',
21
+ )}
22
+ onClick={() => setChecked(c => !c)}
23
+ >
24
+ <div
25
+ class={cs(
26
+ 'ant-w-18px ant-h-18px ant-rounded-50% ant-bg-white ant-absolute ant-top-1/2 -ant-translate-y-1/2 ant-transition-left',
27
+ checked() ? 'ant-left-[calc(100%-20px)]' : 'ant-left-2px',
28
+ )}
29
+ />
30
+ </button>
31
+ )
32
+ }
33
+
34
+ export default Switch
package/src/Table.tsx ADDED
@@ -0,0 +1,53 @@
1
+ import Empty from './Empty'
2
+ import { type JSXElement, For, Show } from 'solid-js'
3
+
4
+ export interface TableColumn<R extends {}> {
5
+ title: JSXElement
6
+ render: (row: R) => JSXElement
7
+ }
8
+
9
+ export interface TableProps<R extends {}> {
10
+ columns: Array<TableColumn<R>>
11
+ dataSource: R[]
12
+ }
13
+
14
+ const Table = <R extends {}>(props: TableProps<R>) => {
15
+ return (
16
+ <div>
17
+ <table class="ant-w-full">
18
+ <thead>
19
+ <tr>
20
+ <For each={props.columns}>
21
+ {item => (
22
+ <th class="ant-p-16px ant-bg-[var(--light-bg-color)] ant-font-bold ant-[border-bottom:1px_solid_var(--secondary-border-color)] ant-text-left">
23
+ {item.title}
24
+ </th>
25
+ )}
26
+ </For>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <For each={props.dataSource}>
31
+ {row => (
32
+ <tr class="hover:ant-bg-[var(--light-bg-color)]">
33
+ <For each={props.columns}>
34
+ {item => (
35
+ <td class="ant-p-16px ant-[border-bottom:1px_solid_var(--secondary-border-color)]">
36
+ {item.render(row)}
37
+ </td>
38
+ )}
39
+ </For>
40
+ </tr>
41
+ )}
42
+ </For>
43
+ </tbody>
44
+ </table>
45
+
46
+ <Show when={!props.dataSource.length}>
47
+ <Empty.PRESENTED_IMAGE_SIMPLE />
48
+ </Show>
49
+ </div>
50
+ )
51
+ }
52
+
53
+ export default Table
package/src/Tabs.tsx ADDED
@@ -0,0 +1,131 @@
1
+ import {
2
+ type Component,
3
+ For,
4
+ createSelector,
5
+ createSignal,
6
+ onMount,
7
+ untrack,
8
+ type JSX,
9
+ onCleanup,
10
+ mergeProps,
11
+ Switch,
12
+ Match,
13
+ } from 'solid-js'
14
+ import cs from 'classnames'
15
+ import Segmented from './Segmented'
16
+ import { type StringOrJSXElement } from './types'
17
+ import { unwrapStringOrJSXElement } from './utils/solid'
18
+
19
+ export interface Tab {
20
+ key: string
21
+ label: StringOrJSXElement
22
+ children?: StringOrJSXElement
23
+ }
24
+
25
+ export interface TabsProps {
26
+ type?: 'line' | 'segment'
27
+ class?: string
28
+ navClass?: string
29
+ navItemClass?: string
30
+ contentClass?: string
31
+ items: Tab[]
32
+ }
33
+
34
+ const Tabs: Component<TabsProps> = _props => {
35
+ const props = mergeProps(
36
+ {
37
+ type: 'line',
38
+ } as TabsProps,
39
+ _props,
40
+ )
41
+
42
+ const [selectedItem, setSelectedItem] = createSignal<Tab | undefined>(
43
+ untrack(() => props.items[0]),
44
+ )
45
+ const isSelectedItem = createSelector(() => selectedItem()?.key)
46
+ const [selectedBarStyle, setSelectedBarStyle] = createSignal<JSX.CSSProperties>({
47
+ left: '0px',
48
+ width: '0px',
49
+ })
50
+
51
+ let nav: HTMLDivElement | undefined
52
+ const updateSelectedBarStyle = () => {
53
+ if (!nav) return
54
+
55
+ const el = nav.querySelector<HTMLElement>(':scope > .selected')
56
+ if (!el) return
57
+
58
+ setSelectedBarStyle({
59
+ left: `${el.offsetLeft}px`,
60
+ width: `${el.clientWidth}px`,
61
+ })
62
+ }
63
+ onMount(() => {
64
+ if (!nav) return
65
+
66
+ updateSelectedBarStyle()
67
+
68
+ const resizeObserver = new ResizeObserver(() => {
69
+ updateSelectedBarStyle()
70
+ })
71
+
72
+ resizeObserver.observe(nav)
73
+ onCleanup(() => {
74
+ resizeObserver.disconnect()
75
+ })
76
+ })
77
+
78
+ return (
79
+ <div class={props.class}>
80
+ <Switch>
81
+ <Match when={props.type === 'line'}>
82
+ <div
83
+ ref={nav!}
84
+ class={cs(
85
+ 'ant-mb-16px ant-flex ant-gap-32px ant-[border-bottom:solid_1px_rgba(5,5,5,0.1)] ant-relative',
86
+ props.navClass,
87
+ )}
88
+ >
89
+ <For each={props.items}>
90
+ {item => (
91
+ <div
92
+ class={cs(
93
+ 'ant-py-12px ant-cursor-pointer',
94
+ props.navItemClass,
95
+ isSelectedItem(item.key) && 'ant-text-[var(--primary-color)] selected',
96
+ )}
97
+ onClick={() => {
98
+ setSelectedItem(item)
99
+ updateSelectedBarStyle()
100
+ }}
101
+ >
102
+ {unwrapStringOrJSXElement(item.label)}
103
+ </div>
104
+ )}
105
+ </For>
106
+
107
+ <div
108
+ role={'selected-bar' as any}
109
+ class="ant-absolute ant-bottom-0 ant-bg-[var(--primary-color)] ant-h-2px ant-transition-left"
110
+ style={selectedBarStyle()}
111
+ />
112
+ </div>
113
+ </Match>
114
+ <Match when={props.type === 'segment'}>
115
+ <Segmented
116
+ block
117
+ options={props.items.map(item => ({
118
+ label: item.label,
119
+ value: item.key,
120
+ onClick: () => setSelectedItem(item),
121
+ }))}
122
+ />
123
+ </Match>
124
+ </Switch>
125
+
126
+ <div class={props.contentClass}>{unwrapStringOrJSXElement(selectedItem()?.children)}</div>
127
+ </div>
128
+ )
129
+ }
130
+
131
+ export default Tabs
@@ -0,0 +1,33 @@
1
+ import { type Accessor, type Component, For, type JSXElement } from 'solid-js'
2
+ import { type TimelineItemProps as TimelineItemAntdProps } from 'antd'
3
+
4
+ interface TimelineItemProps extends Omit<TimelineItemAntdProps, 'children' | 'dot' | 'label'> {
5
+ dot?: JSXElement
6
+ label?: JSXElement
7
+ children?: Accessor<JSXElement>
8
+ }
9
+
10
+ interface TimelineProps {
11
+ class?: string
12
+ items: TimelineItemProps[]
13
+ }
14
+
15
+ const Timeline: Component<TimelineProps> = props => {
16
+ return (
17
+ <div class="ant-flex ant-flex-col ant-gap-[16px]">
18
+ <For each={props.items}>
19
+ {(item, i) => (
20
+ <div class="ant-flex ant-relative">
21
+ {i() !== props.items.length - 1 && (
22
+ <div class="ant-absolute ant-top-[8px] ant-bottom-[-24px] ant-left-[4px] ant-w-[2px] ant-bg-[rgba(5,5,5,.06)]" />
23
+ )}
24
+ <div class="ant-w-[10px] ant-h-[10px] ant-border-solid ant-border-width-[3px] ant-border-[var(--primary-color)] ant-bg-white ant-rounded-[50%] ant-mt-[8px]" />
25
+ <div class="ant-ml-[8px]">{item.children?.()}</div>
26
+ </div>
27
+ )}
28
+ </For>
29
+ </div>
30
+ )
31
+ }
32
+
33
+ export default Timeline