elementdrawing 1.0.0
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/LICENSE +21 -0
- package/dist/elementdrawing.min.js +3 -0
- package/dist/elementdrawing.min.js.LICENSE.txt +8 -0
- package/dist/elementdrawing.min.js.map +1 -0
- package/dist/index.html +1 -0
- package/package.json +127 -0
- package/src/core/bridge.h +855 -0
- package/src/core/diff.c +900 -0
- package/src/core/element.c +1078 -0
- package/src/core/event.c +813 -0
- package/src/core/fiber.c +1027 -0
- package/src/core/hooks.c +919 -0
- package/src/core/renderer.c +963 -0
- package/src/core/scheduler.c +702 -0
- package/src/core/state.c +803 -0
- package/src/css/animations.css +779 -0
- package/src/css/base.css +615 -0
- package/src/css/components.css +1311 -0
- package/src/css/tailwind.css +370 -0
- package/src/css/themes.css +517 -0
- package/src/css/utilities.css +475 -0
- package/src/index.js +746 -0
- package/src/js/animation.js +655 -0
- package/src/js/dom.js +665 -0
- package/src/js/events.js +585 -0
- package/src/js/http.js +446 -0
- package/src/js/index.js +26 -0
- package/src/js/router.js +483 -0
- package/src/js/store.js +539 -0
- package/src/js/utils.js +593 -0
- package/src/js/validator.js +529 -0
- package/src/jsx/components/Accordion.jsx +210 -0
- package/src/jsx/components/Alert.jsx +169 -0
- package/src/jsx/components/Avatar.jsx +214 -0
- package/src/jsx/components/Badge.jsx +136 -0
- package/src/jsx/components/Breadcrumb.jsx +200 -0
- package/src/jsx/components/Button.jsx +188 -0
- package/src/jsx/components/Card.jsx +192 -0
- package/src/jsx/components/Carousel.jsx +278 -0
- package/src/jsx/components/Checkbox.jsx +215 -0
- package/src/jsx/components/Dialog.jsx +242 -0
- package/src/jsx/components/Drawer.jsx +190 -0
- package/src/jsx/components/Dropdown.jsx +268 -0
- package/src/jsx/components/Form.jsx +274 -0
- package/src/jsx/components/Input.jsx +285 -0
- package/src/jsx/components/Menu.jsx +276 -0
- package/src/jsx/components/Modal.jsx +274 -0
- package/src/jsx/components/Navbar.jsx +292 -0
- package/src/jsx/components/Pagination.jsx +268 -0
- package/src/jsx/components/Progress.jsx +252 -0
- package/src/jsx/components/Radio.jsx +208 -0
- package/src/jsx/components/Select.jsx +397 -0
- package/src/jsx/components/Sidebar.jsx +250 -0
- package/src/jsx/components/Slider.jsx +310 -0
- package/src/jsx/components/Spinner.jsx +198 -0
- package/src/jsx/components/Switch.jsx +201 -0
- package/src/jsx/components/Table.jsx +332 -0
- package/src/jsx/components/Tabs.jsx +227 -0
- package/src/jsx/components/Textarea.jsx +212 -0
- package/src/jsx/components/Toast.jsx +270 -0
- package/src/jsx/components/Tooltip.jsx +178 -0
- package/src/jsx/components/Typography.jsx +299 -0
- package/src/jsx/components/index.jsx +70 -0
- package/src/jsx/core/element.js +3 -0
- package/src/jsx/hooks/index.js +356 -0
- package/src/jsx/hooks/useCallback.js +472 -0
- package/src/jsx/hooks/useContext.js +586 -0
- package/src/jsx/hooks/useEffect.js +704 -0
- package/src/jsx/hooks/useLayoutEffect.js +508 -0
- package/src/jsx/hooks/useMemo.js +689 -0
- package/src/jsx/hooks/useReducer.js +729 -0
- package/src/jsx/hooks/useRef.js +542 -0
- package/src/jsx/hooks/useState.js +854 -0
- package/src/jsx/runtime/commit.js +903 -0
- package/src/jsx/runtime/createElement.js +860 -0
- package/src/jsx/runtime/index.js +356 -0
- package/src/jsx/runtime/reconcile.js +687 -0
- package/src/jsx/runtime/render.js +914 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Component for ElementDrawing Framework
|
|
3
|
+
* Supports single/multiple expand, icons, animations, nested, disabled items, custom header
|
|
4
|
+
*/
|
|
5
|
+
const ED = require('../core/element');
|
|
6
|
+
|
|
7
|
+
function AccordionItem(props) {
|
|
8
|
+
const {
|
|
9
|
+
children,
|
|
10
|
+
title,
|
|
11
|
+
header,
|
|
12
|
+
icon,
|
|
13
|
+
expandIcon,
|
|
14
|
+
disabled = false,
|
|
15
|
+
expanded = false,
|
|
16
|
+
onToggle,
|
|
17
|
+
className = '',
|
|
18
|
+
style = {},
|
|
19
|
+
key: itemKey,
|
|
20
|
+
extra,
|
|
21
|
+
showArrow = true,
|
|
22
|
+
destroyInactive = false,
|
|
23
|
+
forceRender = false,
|
|
24
|
+
animated = true,
|
|
25
|
+
} = props;
|
|
26
|
+
|
|
27
|
+
const headerClasses = [
|
|
28
|
+
'ed-flex ed-items-center ed-w-full ed-px-4 ed-py-3 ed-text-left ed-transition-colors ed-duration-200',
|
|
29
|
+
'hover:ed-bg-gray-50 focus:ed-outline-none focus:ed-ring-2 focus:ed-ring-inset focus:ed-ring-blue-500',
|
|
30
|
+
disabled ? 'ed-opacity-50 ed-cursor-not-allowed' : 'ed-cursor-pointer',
|
|
31
|
+
expanded ? 'ed-bg-gray-50' : '',
|
|
32
|
+
'ed-border-b ed-border-gray-100',
|
|
33
|
+
className,
|
|
34
|
+
].filter(Boolean).join(' ');
|
|
35
|
+
|
|
36
|
+
const contentClasses = [
|
|
37
|
+
'ed-overflow-hidden ed-transition-all ed-duration-300',
|
|
38
|
+
animated ? 'ed-transition-[max-height] ed-ease-in-out' : '',
|
|
39
|
+
expanded ? 'ed-max-h-[2000px] ed-opacity-100' : 'ed-max-h-0 ed-opacity-0',
|
|
40
|
+
].filter(Boolean).join(' ');
|
|
41
|
+
|
|
42
|
+
const defaultExpandIcon = ED.createElement('svg', {
|
|
43
|
+
className: `ed-w-5 ed-h-5 ed-transition-transform ed-duration-300 ed-text-gray-400 ${expanded ? 'ed-rotate-180' : ''}`,
|
|
44
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
45
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M19 9l-7 7-7-7' }),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const headerContent = header || ED.createElement(ED.Fragment, null,
|
|
49
|
+
icon
|
|
50
|
+
? ED.createElement('span', { className: 'ed-mr-3 ed-flex ed-items-center ed-justify-center ed-w-5 ed-h-5 ed-text-gray-500' },
|
|
51
|
+
typeof icon === 'string' ? ED.createElement('i', { className: icon }) : icon
|
|
52
|
+
)
|
|
53
|
+
: null,
|
|
54
|
+
ED.createElement('span', { className: 'ed-flex-1 ed-font-medium ed-text-gray-900' }, title),
|
|
55
|
+
extra
|
|
56
|
+
? ED.createElement('span', { className: 'ed-mr-2 ed-text-sm ed-text-gray-500', onClick: (e) => e.stopPropagation() }, extra)
|
|
57
|
+
: null,
|
|
58
|
+
showArrow
|
|
59
|
+
? ED.createElement('span', { className: 'ed-ml-auto ed-flex ed-items-center' },
|
|
60
|
+
expandIcon || defaultExpandIcon
|
|
61
|
+
)
|
|
62
|
+
: null
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const handleToggle = () => {
|
|
66
|
+
if (!disabled) onToggle?.();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const handleKeyDown = (e) => {
|
|
70
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
handleToggle();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
return ED.createElement('div', {
|
|
77
|
+
className: 'ed-border ed-border-gray-200 ed-rounded-lg ed-overflow-hidden ed-mb-2',
|
|
78
|
+
style,
|
|
79
|
+
children: [
|
|
80
|
+
ED.createElement('button', {
|
|
81
|
+
key: 'header',
|
|
82
|
+
className: headerClasses,
|
|
83
|
+
onClick: handleToggle,
|
|
84
|
+
onKeyDown: handleKeyDown,
|
|
85
|
+
'aria-expanded': expanded,
|
|
86
|
+
'aria-disabled': disabled,
|
|
87
|
+
role: 'button',
|
|
88
|
+
tabIndex: disabled ? -1 : 0,
|
|
89
|
+
children: headerContent,
|
|
90
|
+
}),
|
|
91
|
+
ED.createElement('div', {
|
|
92
|
+
key: 'content',
|
|
93
|
+
className: contentClasses,
|
|
94
|
+
role: 'region',
|
|
95
|
+
children: (expanded || forceRender)
|
|
96
|
+
? ED.createElement('div', { className: 'ed-px-4 ed-py-3 ed-text-gray-700 ed-border-t ed-border-gray-100' }, children)
|
|
97
|
+
: null,
|
|
98
|
+
}),
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
AccordionItem.displayName = 'AccordionItem';
|
|
104
|
+
|
|
105
|
+
function Accordion(props) {
|
|
106
|
+
const {
|
|
107
|
+
children,
|
|
108
|
+
items = [],
|
|
109
|
+
multiple = false,
|
|
110
|
+
defaultActiveKey,
|
|
111
|
+
activeKey,
|
|
112
|
+
onChange,
|
|
113
|
+
className = '',
|
|
114
|
+
style = {},
|
|
115
|
+
icon,
|
|
116
|
+
expandIcon,
|
|
117
|
+
animated = true,
|
|
118
|
+
destroyInactive = false,
|
|
119
|
+
bordered = true,
|
|
120
|
+
ghost = false,
|
|
121
|
+
accordion = !multiple,
|
|
122
|
+
size = 'md',
|
|
123
|
+
} = props;
|
|
124
|
+
|
|
125
|
+
const internalActiveKeys = activeKey !== undefined
|
|
126
|
+
? (Array.isArray(activeKey) ? activeKey : [activeKey])
|
|
127
|
+
: defaultActiveKey !== undefined
|
|
128
|
+
? (Array.isArray(defaultActiveKey) ? defaultActiveKey : [defaultActiveKey])
|
|
129
|
+
: [];
|
|
130
|
+
|
|
131
|
+
const handleToggle = (key) => {
|
|
132
|
+
const isOpen = internalActiveKeys.includes(key);
|
|
133
|
+
let newKeys;
|
|
134
|
+
if (accordion || !multiple) {
|
|
135
|
+
newKeys = isOpen ? [] : [key];
|
|
136
|
+
} else {
|
|
137
|
+
newKeys = isOpen ? internalActiveKeys.filter(k => k !== key) : [...internalActiveKeys, key];
|
|
138
|
+
}
|
|
139
|
+
onChange?.(multiple ? newKeys : newKeys[0] || null);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const sizeClasses = {
|
|
143
|
+
sm: 'ed-text-sm',
|
|
144
|
+
md: 'ed-text-base',
|
|
145
|
+
lg: 'ed-text-lg',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const accordionClasses = [
|
|
149
|
+
sizeClasses[size] || sizeClasses.md,
|
|
150
|
+
ghost ? '' : bordered ? 'ed-divide-y ed-divide-gray-200' : '',
|
|
151
|
+
'ed-accordion',
|
|
152
|
+
className,
|
|
153
|
+
].filter(Boolean).join(' ');
|
|
154
|
+
|
|
155
|
+
const renderItems = () => {
|
|
156
|
+
if (items.length > 0) {
|
|
157
|
+
return items.map((item, idx) =>
|
|
158
|
+
ED.createElement(AccordionItem, {
|
|
159
|
+
key: item.key || idx,
|
|
160
|
+
title: item.title,
|
|
161
|
+
icon: item.icon || icon,
|
|
162
|
+
expandIcon: item.expandIcon || expandIcon,
|
|
163
|
+
disabled: item.disabled,
|
|
164
|
+
expanded: internalActiveKeys.includes(item.key || String(idx)),
|
|
165
|
+
onToggle: () => handleToggle(item.key || String(idx)),
|
|
166
|
+
extra: item.extra,
|
|
167
|
+
showArrow: item.showArrow !== undefined ? item.showArrow : true,
|
|
168
|
+
animated,
|
|
169
|
+
destroyInactive,
|
|
170
|
+
forceRender: item.forceRender,
|
|
171
|
+
children: item.children || item.content,
|
|
172
|
+
})
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const childArray = Array.isArray(children) ? children : [children];
|
|
177
|
+
return childArray.map((child, idx) => {
|
|
178
|
+
if (!child || !child.props) return child;
|
|
179
|
+
const childKey = child.props.key || String(idx);
|
|
180
|
+
return ED.cloneElement
|
|
181
|
+
? ED.cloneElement(child, {
|
|
182
|
+
key: childKey,
|
|
183
|
+
expanded: internalActiveKeys.includes(childKey),
|
|
184
|
+
onToggle: () => handleToggle(childKey),
|
|
185
|
+
icon: child.props.icon || icon,
|
|
186
|
+
expandIcon: child.props.expandIcon || expandIcon,
|
|
187
|
+
animated,
|
|
188
|
+
})
|
|
189
|
+
: child;
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const wrapperClasses = ghost
|
|
194
|
+
? [
|
|
195
|
+
'ed-border-0 ed-bg-transparent',
|
|
196
|
+
className,
|
|
197
|
+
].filter(Boolean).join(' ')
|
|
198
|
+
: accordionClasses;
|
|
199
|
+
|
|
200
|
+
return ED.createElement('div', {
|
|
201
|
+
className: wrapperClasses,
|
|
202
|
+
style,
|
|
203
|
+
children: renderItems(),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
Accordion.displayName = 'Accordion';
|
|
208
|
+
Accordion.Item = AccordionItem;
|
|
209
|
+
|
|
210
|
+
module.exports = Accordion;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Alert Component for ElementDrawing Framework
|
|
3
|
+
* Supports variants, closable, icon, title + description, banner mode, auto-dismiss
|
|
4
|
+
*/
|
|
5
|
+
const ED = require('../core/element');
|
|
6
|
+
|
|
7
|
+
const ALERT_VARIANTS = {
|
|
8
|
+
info: {
|
|
9
|
+
container: 'ed-bg-blue-50 ed-border-blue-200 ed-text-blue-800',
|
|
10
|
+
icon: 'ed-text-blue-500',
|
|
11
|
+
close: 'ed-text-blue-500 hover:ed-bg-blue-100',
|
|
12
|
+
},
|
|
13
|
+
success: {
|
|
14
|
+
container: 'ed-bg-green-50 ed-border-green-200 ed-text-green-800',
|
|
15
|
+
icon: 'ed-text-green-500',
|
|
16
|
+
close: 'ed-text-green-500 hover:ed-bg-green-100',
|
|
17
|
+
},
|
|
18
|
+
warning: {
|
|
19
|
+
container: 'ed-bg-yellow-50 ed-border-yellow-200 ed-text-yellow-800',
|
|
20
|
+
icon: 'ed-text-yellow-500',
|
|
21
|
+
close: 'ed-text-yellow-500 hover:ed-bg-yellow-100',
|
|
22
|
+
},
|
|
23
|
+
danger: {
|
|
24
|
+
container: 'ed-bg-red-50 ed-border-red-200 ed-text-red-800',
|
|
25
|
+
icon: 'ed-text-red-500',
|
|
26
|
+
close: 'ed-text-red-500 hover:ed-bg-red-100',
|
|
27
|
+
},
|
|
28
|
+
error: {
|
|
29
|
+
container: 'ed-bg-red-50 ed-border-red-200 ed-text-red-800',
|
|
30
|
+
icon: 'ed-text-red-500',
|
|
31
|
+
close: 'ed-text-red-500 hover:ed-bg-red-100',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const ALERT_ICONS = {
|
|
36
|
+
info: ED.createElement('svg', {
|
|
37
|
+
className: 'ed-w-5 ed-h-5',
|
|
38
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
39
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z' }),
|
|
40
|
+
}),
|
|
41
|
+
success: ED.createElement('svg', {
|
|
42
|
+
className: 'ed-w-5 ed-h-5',
|
|
43
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
44
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M5 13l4 4L19 7' }),
|
|
45
|
+
}),
|
|
46
|
+
warning: ED.createElement('svg', {
|
|
47
|
+
className: 'ed-w-5 ed-h-5',
|
|
48
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
49
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z' }),
|
|
50
|
+
}),
|
|
51
|
+
danger: ED.createElement('svg', {
|
|
52
|
+
className: 'ed-w-5 ed-h-5',
|
|
53
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
54
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z' }),
|
|
55
|
+
}),
|
|
56
|
+
error: ED.createElement('svg', {
|
|
57
|
+
className: 'ed-w-5 ed-h-5',
|
|
58
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
59
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z' }),
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function Alert(props) {
|
|
64
|
+
const {
|
|
65
|
+
children,
|
|
66
|
+
variant = 'info',
|
|
67
|
+
type = variant,
|
|
68
|
+
closable = false,
|
|
69
|
+
onClose,
|
|
70
|
+
showIcon = true,
|
|
71
|
+
icon,
|
|
72
|
+
title,
|
|
73
|
+
description,
|
|
74
|
+
banner = false,
|
|
75
|
+
autoDismiss,
|
|
76
|
+
onDismiss,
|
|
77
|
+
className = '',
|
|
78
|
+
style = {},
|
|
79
|
+
action,
|
|
80
|
+
rounded = true,
|
|
81
|
+
bordered = true,
|
|
82
|
+
outlined = false,
|
|
83
|
+
size = 'md',
|
|
84
|
+
} = props;
|
|
85
|
+
|
|
86
|
+
const currentType = type || variant;
|
|
87
|
+
const variantStyle = ALERT_VARIANTS[currentType] || ALERT_VARIANTS.info;
|
|
88
|
+
|
|
89
|
+
const sizeClasses = {
|
|
90
|
+
sm: 'ed-text-xs ed-py-2 ed-px-3',
|
|
91
|
+
md: 'ed-text-sm ed-py-3 ed-px-4',
|
|
92
|
+
lg: 'ed-text-base ed-py-4 ed-px-5',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const containerClasses = [
|
|
96
|
+
'ed-flex ed-items-start ed-gap-3',
|
|
97
|
+
variantStyle.container,
|
|
98
|
+
banner ? 'ed-rounded-none ed-border-x-0 ed-border-t-0' : rounded ? 'ed-rounded-lg' : '',
|
|
99
|
+
bordered ? 'ed-border' : '',
|
|
100
|
+
outlined ? 'ed-bg-transparent' : '',
|
|
101
|
+
sizeClasses[size] || sizeClasses.md,
|
|
102
|
+
'ed-transition-all ed-duration-300',
|
|
103
|
+
className,
|
|
104
|
+
].filter(Boolean).join(' ');
|
|
105
|
+
|
|
106
|
+
const iconElement = showIcon
|
|
107
|
+
? ED.createElement('span', {
|
|
108
|
+
className: `ed-flex-shrink-0 ed-mt-0.5 ${variantStyle.icon}`,
|
|
109
|
+
children: icon || ALERT_ICONS[currentType] || ALERT_ICONS.info,
|
|
110
|
+
})
|
|
111
|
+
: null;
|
|
112
|
+
|
|
113
|
+
const contentElement = ED.createElement('div', { className: 'ed-flex-1 ed-min-w-0' },
|
|
114
|
+
title
|
|
115
|
+
? ED.createElement('div', { className: 'ed-font-semibold ed-mb-0.5' }, title)
|
|
116
|
+
: null,
|
|
117
|
+
description
|
|
118
|
+
? ED.createElement('div', { className: 'ed-text-sm ed-opacity-80' }, description)
|
|
119
|
+
: null,
|
|
120
|
+
children
|
|
121
|
+
? ED.createElement('div', { className: title || description ? 'ed-mt-1 ed-text-sm ed-opacity-90' : '' }, children)
|
|
122
|
+
: null
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const actionElement = action
|
|
126
|
+
? ED.createElement('div', { className: 'ed-flex-shrink-0 ed-ml-2' }, action)
|
|
127
|
+
: null;
|
|
128
|
+
|
|
129
|
+
const closeElement = closable
|
|
130
|
+
? ED.createElement('button', {
|
|
131
|
+
className: `ed-flex-shrink-0 ed-p-1 ed-rounded ed-transition-colors ${variantStyle.close}`,
|
|
132
|
+
onClick: onClose,
|
|
133
|
+
'aria-label': 'Close alert',
|
|
134
|
+
type: 'button',
|
|
135
|
+
children: ED.createElement('svg', {
|
|
136
|
+
className: 'ed-w-4 ed-h-4',
|
|
137
|
+
fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor',
|
|
138
|
+
children: ED.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M6 18L18 6M6 6l12 12' }),
|
|
139
|
+
}),
|
|
140
|
+
})
|
|
141
|
+
: null;
|
|
142
|
+
|
|
143
|
+
const progressBar = autoDismiss
|
|
144
|
+
? ED.createElement('div', { className: 'ed-absolute ed-bottom-0 ed-left-0 ed-right-0 ed-h-1 ed-rounded-b-lg ed-overflow-hidden' },
|
|
145
|
+
ED.createElement('div', {
|
|
146
|
+
className: `ed-h-full ed-bg-current ed-opacity-30`,
|
|
147
|
+
style: { animation: `ed-shrink ${autoDismiss}ms linear forwards` },
|
|
148
|
+
})
|
|
149
|
+
)
|
|
150
|
+
: null;
|
|
151
|
+
|
|
152
|
+
return ED.createElement('div', {
|
|
153
|
+
className: containerClasses,
|
|
154
|
+
style: { position: 'relative', ...style },
|
|
155
|
+
role: currentType === 'danger' || currentType === 'error' ? 'alert' : 'status',
|
|
156
|
+
children: [
|
|
157
|
+
iconElement,
|
|
158
|
+
contentElement,
|
|
159
|
+
actionElement,
|
|
160
|
+
closeElement,
|
|
161
|
+
progressBar,
|
|
162
|
+
].filter(Boolean),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
Alert.displayName = 'Alert';
|
|
167
|
+
Alert.VARIANTS = ALERT_VARIANTS;
|
|
168
|
+
|
|
169
|
+
module.exports = Alert;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Avatar Component for ElementDrawing Framework
|
|
3
|
+
* Supports sizes, shapes, image/initials/icon, status indicator, avatar group, overlap
|
|
4
|
+
*/
|
|
5
|
+
const ED = require('../core/element');
|
|
6
|
+
|
|
7
|
+
const AVATAR_SIZES = {
|
|
8
|
+
xs: { container: 'ed-w-6 ed-h-6 ed-text-xs', icon: 'ed-w-3 ed-h-3', indicator: 'ed-w-1.5 ed-h-1.5' },
|
|
9
|
+
sm: { container: 'ed-w-8 ed-h-8 ed-text-sm', icon: 'ed-w-4 ed-h-4', indicator: 'ed-w-2 ed-h-2' },
|
|
10
|
+
md: { container: 'ed-w-10 ed-h-10 ed-text-base', icon: 'ed-w-5 ed-h-5', indicator: 'ed-w-2.5 ed-h-2.5' },
|
|
11
|
+
lg: { container: 'ed-w-12 ed-h-12 ed-text-lg', icon: 'ed-w-6 ed-h-6', indicator: 'ed-w-3 ed-h-3' },
|
|
12
|
+
xl: { container: 'ed-w-14 ed-h-14 ed-text-xl', icon: 'ed-w-7 ed-h-7', indicator: 'ed-w-3.5 ed-h-3.5' },
|
|
13
|
+
'2xl': { container: 'ed-w-16 ed-h-16 ed-text-2xl', icon: 'ed-w-8 ed-h-8', indicator: 'ed-w-4 ed-h-4' },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const SHAPE_CLASSES = {
|
|
17
|
+
circle: 'ed-rounded-full',
|
|
18
|
+
square: 'ed-rounded-none',
|
|
19
|
+
rounded: 'ed-rounded-lg',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const STATUS_COLORS = {
|
|
23
|
+
online: 'ed-bg-green-500',
|
|
24
|
+
offline: 'ed-bg-gray-400',
|
|
25
|
+
away: 'ed-bg-yellow-500',
|
|
26
|
+
busy: 'ed-bg-red-500',
|
|
27
|
+
doNotDisturb: 'ed-bg-red-600',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const BG_COLORS = [
|
|
31
|
+
'ed-bg-blue-500',
|
|
32
|
+
'ed-bg-green-500',
|
|
33
|
+
'ed-bg-yellow-500',
|
|
34
|
+
'ed-bg-red-500',
|
|
35
|
+
'ed-bg-purple-500',
|
|
36
|
+
'ed-bg-pink-500',
|
|
37
|
+
'ed-bg-indigo-500',
|
|
38
|
+
'ed-bg-teal-500',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
function getColorFromName(name) {
|
|
42
|
+
if (!name) return BG_COLORS[0];
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (let i = 0; i < name.length; i++) {
|
|
45
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
46
|
+
}
|
|
47
|
+
return BG_COLORS[Math.abs(hash) % BG_COLORS.length];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getInitials(name) {
|
|
51
|
+
if (!name) return '';
|
|
52
|
+
const parts = name.trim().split(/\s+/);
|
|
53
|
+
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
54
|
+
return name.slice(0, 2).toUpperCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function Avatar(props) {
|
|
58
|
+
const {
|
|
59
|
+
src,
|
|
60
|
+
alt = '',
|
|
61
|
+
icon,
|
|
62
|
+
name,
|
|
63
|
+
size = 'md',
|
|
64
|
+
shape = 'circle',
|
|
65
|
+
status,
|
|
66
|
+
statusColor,
|
|
67
|
+
className = '',
|
|
68
|
+
style = {},
|
|
69
|
+
onClick,
|
|
70
|
+
onError,
|
|
71
|
+
bgColor,
|
|
72
|
+
textColor = 'ed-text-white',
|
|
73
|
+
bordered = false,
|
|
74
|
+
borderColor = 'ed-border-white',
|
|
75
|
+
boxShadow,
|
|
76
|
+
draggable = false,
|
|
77
|
+
loading = false,
|
|
78
|
+
fit = 'cover',
|
|
79
|
+
} = props;
|
|
80
|
+
|
|
81
|
+
const sizeConfig = AVATAR_SIZES[size] || AVATAR_SIZES.md;
|
|
82
|
+
const shapeClass = SHAPE_CLASSES[shape] || SHAPE_CLASSES.circle;
|
|
83
|
+
|
|
84
|
+
const containerClasses = [
|
|
85
|
+
'ed-inline-flex ed-items-center ed-justify-center ed-relative ed-flex-shrink-0 ed-overflow-hidden',
|
|
86
|
+
sizeConfig.container,
|
|
87
|
+
shapeClass,
|
|
88
|
+
bgColor || (!src ? getColorFromName(name) : ''),
|
|
89
|
+
textColor,
|
|
90
|
+
bordered ? `ed-border-2 ${borderColor}` : '',
|
|
91
|
+
onClick ? 'ed-cursor-pointer hover:ed-opacity-80 ed-transition-opacity' : '',
|
|
92
|
+
loading ? 'ed-animate-pulse ed-bg-gray-300' : '',
|
|
93
|
+
'ed-font-medium ed-select-none',
|
|
94
|
+
className,
|
|
95
|
+
].filter(Boolean).join(' ');
|
|
96
|
+
|
|
97
|
+
const statusIndicator = status
|
|
98
|
+
? ED.createElement('span', {
|
|
99
|
+
className: [
|
|
100
|
+
'ed-absolute ed-bottom-0 ed-right-0 ed-border-2 ed-border-white ed-rounded-full',
|
|
101
|
+
STATUS_COLORS[status] || statusColor || 'ed-bg-green-500',
|
|
102
|
+
sizeConfig.indicator,
|
|
103
|
+
].join(' '),
|
|
104
|
+
})
|
|
105
|
+
: null;
|
|
106
|
+
|
|
107
|
+
let contentElement;
|
|
108
|
+
if (loading) {
|
|
109
|
+
contentElement = null;
|
|
110
|
+
} else if (src) {
|
|
111
|
+
contentElement = ED.createElement('img', {
|
|
112
|
+
src,
|
|
113
|
+
alt: alt || name || 'Avatar',
|
|
114
|
+
className: `ed-w-full ed-h-full ed-object-${fit}`,
|
|
115
|
+
onError,
|
|
116
|
+
draggable,
|
|
117
|
+
});
|
|
118
|
+
} else if (icon) {
|
|
119
|
+
contentElement = ED.createElement('span', {
|
|
120
|
+
className: sizeConfig.icon,
|
|
121
|
+
children: typeof icon === 'string' ? ED.createElement('i', { className: icon }) : icon,
|
|
122
|
+
});
|
|
123
|
+
} else if (name) {
|
|
124
|
+
contentElement = ED.createElement('span', null, getInitials(name));
|
|
125
|
+
} else {
|
|
126
|
+
contentElement = ED.createElement('svg', {
|
|
127
|
+
className: sizeConfig.icon,
|
|
128
|
+
fill: 'currentColor', viewBox: '0 0 24 24',
|
|
129
|
+
children: ED.createElement('path', { d: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z' }),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return ED.createElement('span', {
|
|
134
|
+
className: containerClasses,
|
|
135
|
+
style: {
|
|
136
|
+
...(boxShadow ? { boxShadow } : {}),
|
|
137
|
+
...style,
|
|
138
|
+
},
|
|
139
|
+
onClick,
|
|
140
|
+
role: onClick ? 'button' : undefined,
|
|
141
|
+
tabIndex: onClick ? 0 : undefined,
|
|
142
|
+
children: [contentElement, statusIndicator],
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
Avatar.displayName = 'Avatar';
|
|
147
|
+
|
|
148
|
+
function AvatarGroup(props) {
|
|
149
|
+
const {
|
|
150
|
+
children,
|
|
151
|
+
maxCount,
|
|
152
|
+
size = 'md',
|
|
153
|
+
shape = 'circle',
|
|
154
|
+
overlap = true,
|
|
155
|
+
className = '',
|
|
156
|
+
style = {},
|
|
157
|
+
direction = 'horizontal',
|
|
158
|
+
maxStyle,
|
|
159
|
+
onMaxClick,
|
|
160
|
+
} = props;
|
|
161
|
+
|
|
162
|
+
const childArray = Array.isArray(children) ? children : [children];
|
|
163
|
+
const displayChildren = maxCount ? childArray.slice(0, maxCount) : childArray;
|
|
164
|
+
const remaining = maxCount ? childArray.length - maxCount : 0;
|
|
165
|
+
|
|
166
|
+
const groupClasses = [
|
|
167
|
+
'ed-flex ed-items-center',
|
|
168
|
+
direction === 'horizontal' ? 'ed-flex-row' : 'ed-flex-col',
|
|
169
|
+
overlap ? (direction === 'horizontal' ? 'ed--space-x-2' : 'ed--space-y-2') : 'ed-gap-1',
|
|
170
|
+
className,
|
|
171
|
+
].filter(Boolean).join(' ');
|
|
172
|
+
|
|
173
|
+
const overflowAvatar = remaining > 0
|
|
174
|
+
? ED.createElement(Avatar, {
|
|
175
|
+
size,
|
|
176
|
+
shape,
|
|
177
|
+
bgColor: 'ed-bg-gray-200',
|
|
178
|
+
textColor: 'ed-text-gray-600',
|
|
179
|
+
className: 'ed-ring-2 ed-ring-white',
|
|
180
|
+
style: maxStyle,
|
|
181
|
+
onClick: onMaxClick,
|
|
182
|
+
name: `+${remaining}`,
|
|
183
|
+
})
|
|
184
|
+
: null;
|
|
185
|
+
|
|
186
|
+
const styledChildren = displayChildren.map((child, idx) => {
|
|
187
|
+
if (!child || !child.props) return child;
|
|
188
|
+
const overlapStyle = overlap
|
|
189
|
+
? { zIndex: displayChildren.length - idx, position: 'relative' }
|
|
190
|
+
: {};
|
|
191
|
+
return ED.cloneElement
|
|
192
|
+
? ED.cloneElement(child, {
|
|
193
|
+
key: idx,
|
|
194
|
+
size: child.props.size || size,
|
|
195
|
+
shape: child.props.shape || shape,
|
|
196
|
+
style: { ...overlapStyle, ...child.props.style },
|
|
197
|
+
bordered: child.props.bordered !== undefined ? child.props.bordered : true,
|
|
198
|
+
})
|
|
199
|
+
: child;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return ED.createElement('div', {
|
|
203
|
+
className: groupClasses,
|
|
204
|
+
style,
|
|
205
|
+
children: [...styledChildren, overflowAvatar].filter(Boolean),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
AvatarGroup.displayName = 'AvatarGroup';
|
|
210
|
+
Avatar.Group = AvatarGroup;
|
|
211
|
+
Avatar.SIZES = AVATAR_SIZES;
|
|
212
|
+
Avatar.SHAPES = SHAPE_CLASSES;
|
|
213
|
+
|
|
214
|
+
module.exports = Avatar;
|