Skip to content

Commit 78e31ce

Browse files
authored
[refactor] rewrite BG Icon, Input Group, Collapse, Accordion & Month Calendar components (#20)
1 parent e2af9e9 commit 78e31ce

12 files changed

+386
-260
lines changed

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "boot-cell",
3-
"version": "2.0.0-beta.7",
3+
"version": "2.0.0-beta.9",
44
"license": "LGPL-3.0",
55
"author": "[email protected]",
66
"description": "Web Components UI library based on WebCell v3, BootStrap v5, BootStrap Icon v1 & FontAwesome v6",
@@ -29,7 +29,7 @@
2929
"dom-renderer": "^2.0.6",
3030
"mobx": "^6.12.0",
3131
"regenerator-runtime": "^0.14.1",
32-
"web-cell": "^3.0.0-rc.7",
32+
"web-cell": "^3.0.0-rc.8",
3333
"web-utility": "^4.1.3"
3434
},
3535
"peerDependencies": {
@@ -70,7 +70,7 @@
7070
"ts-jest": "^29.1.1",
7171
"ts-node": "^10.9.2",
7272
"typedoc": "^0.25.7",
73-
"typedoc-plugin-mdn-links": "^3.1.12",
73+
"typedoc-plugin-mdn-links": "^3.1.13",
7474
"typescript": "~5.3.3"
7575
},
7676
"scripts": {

pnpm-lock.yaml

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

source/Accordion.tsx

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { observable } from 'mobx';
2+
import {
3+
FC,
4+
WebCell,
5+
WebCellProps,
6+
attribute,
7+
component,
8+
observer,
9+
on,
10+
reaction
11+
} from 'web-cell';
12+
13+
import { CollapseProps, Collapse } from './Collapse';
14+
15+
export const AccordionItem: FC<WebCellProps<HTMLDivElement>> = ({
16+
className = '',
17+
children,
18+
...props
19+
}) => (
20+
<div className={`accordion-item ${className}`} {...props}>
21+
{children}
22+
</div>
23+
);
24+
25+
export const AccordionHeader: FC<WebCellProps<HTMLHeadingElement>> = ({
26+
className = '',
27+
children,
28+
onClick,
29+
...props
30+
}) => (
31+
<h2 className={`accordion-header ${className}`} {...props}>
32+
<button className="accordion-button" type="button" onClick={onClick}>
33+
{children}
34+
</button>
35+
</h2>
36+
);
37+
38+
export const AccordionBody: FC<CollapseProps> = ({
39+
className = '',
40+
children,
41+
...props
42+
}) => (
43+
<Collapse className={`accordion-collapse ${className}`} {...props}>
44+
<div className="accordion-body">{children}</div>
45+
</Collapse>
46+
);
47+
48+
export interface AccordionProps {
49+
flush?: boolean;
50+
alwaysOpen?: boolean;
51+
}
52+
53+
export interface Accordion extends WebCell<AccordionProps> {}
54+
55+
@component({
56+
tagName: 'accordion-box',
57+
mode: 'open'
58+
})
59+
@observer
60+
export class Accordion extends HTMLElement implements WebCell<AccordionProps> {
61+
@attribute
62+
@observable
63+
accessor flush = false;
64+
65+
@attribute
66+
@observable
67+
accessor alwaysOpen = false;
68+
69+
connectedCallback() {
70+
this.classList.add('accordion');
71+
}
72+
73+
@reaction(({ flush }) => flush)
74+
handleFlush(flush: boolean) {
75+
this.classList.toggle('accordion-flush', flush);
76+
}
77+
78+
@on('click', '.accordion-header')
79+
handleClick(
80+
_,
81+
{ nextElementSibling: currentCollapse }: HTMLHeadingElement
82+
) {
83+
if (!this.alwaysOpen)
84+
for (const collapse of this.querySelectorAll<HTMLDivElement>(
85+
'.accordion-collapse'
86+
))
87+
if (collapse !== currentCollapse) {
88+
collapse.classList.remove('show');
89+
collapse.previousElementSibling.querySelector(
90+
'button'
91+
).ariaExpanded = 'false';
92+
}
93+
currentCollapse.classList.toggle('show');
94+
currentCollapse.previousElementSibling.querySelector(
95+
'button'
96+
).ariaExpanded = 'false';
97+
}
98+
99+
render() {
100+
return <slot />;
101+
}
102+
}

source/Button.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ export const Button: FC<ButtonProps> = ({
1818
className,
1919
href,
2020
variant,
21+
size,
2122
active,
2223
children,
2324
...props
2425
}) => {
2526
const { disabled, tabIndex } = props,
26-
Class = classNames('btn', variant && `btn-${variant}`, className);
27+
Class = classNames(
28+
'btn',
29+
variant && `btn-${variant}`,
30+
size && `btn-${size}`,
31+
className
32+
);
2733

2834
return href ? (
2935
<a

source/Collapse.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import classNames from 'classnames';
2+
import { FC, WebCellProps } from 'web-cell';
3+
4+
export interface CollapseProps extends WebCellProps<HTMLElement> {
5+
dimension?: 'width' | 'height';
6+
in?: boolean;
7+
}
8+
9+
export const Collapse: FC<CollapseProps> = ({
10+
className,
11+
dimension = 'width',
12+
in: show,
13+
children,
14+
...props
15+
}) => (
16+
<div
17+
className={classNames(
18+
'collapse',
19+
{ 'collapse-horizontal': dimension === 'height', show },
20+
className
21+
)}
22+
{...props}
23+
>
24+
{children}
25+
</div>
26+
);

source/Form.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,38 @@ export const FloatingLabel: FC<FloatingLabelProps> = ({
3838
</div>
3939
);
4040

41+
export interface InputGroupProps extends WebCellProps<HTMLDivElement> {
42+
size?: 'sm' | 'lg';
43+
}
44+
45+
export const InputGroup: FC<InputGroupProps> = ({
46+
className = '',
47+
size,
48+
children,
49+
...props
50+
}) => (
51+
<div
52+
className={classNames(
53+
'input-group',
54+
size && `input-group-${size}`,
55+
className
56+
)}
57+
{...props}
58+
>
59+
{children}
60+
</div>
61+
);
62+
63+
export const InputGroupText: FC<WebCellProps<HTMLSpanElement>> = ({
64+
className = '',
65+
children,
66+
...props
67+
}) => (
68+
<span className={`input-group-text ${className}`} {...props}>
69+
{children}
70+
</span>
71+
);
72+
4173
export type FormControlTag = 'input' | 'textarea' | 'select';
4274

4375
export type FormControlProps<T extends FormControlTag> = WebCellProps &

source/Icon.tsx

+40-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import classNames from 'classnames';
2-
import { WebCellProps } from 'web-cell';
2+
import { FC, WebCellProps } from 'web-cell';
33

44
import { Color } from './type';
55

@@ -9,27 +9,50 @@ export interface IconProps extends WebCellProps {
99
size?: number;
1010
}
1111

12-
export function Icon({
12+
export const Icon: FC<IconProps> = ({
1313
className,
1414
style,
1515
color,
1616
name,
1717
size,
1818
children,
1919
...rest
20-
}: IconProps) {
21-
return (
22-
<i
23-
className={classNames(
24-
`bi-${name}`,
25-
color && `text-${color}`,
26-
className
27-
)}
28-
style={{
29-
...style,
30-
fontSize: size ? `${size}rem` : undefined
31-
}}
32-
{...rest}
33-
/>
34-
);
20+
}) => (
21+
<i
22+
className={classNames(
23+
`bi-${name}`,
24+
color && `text-${color}`,
25+
className
26+
)}
27+
style={{
28+
...style,
29+
fontSize: size ? `${size}rem` : undefined
30+
}}
31+
{...rest}
32+
/>
33+
);
34+
35+
export interface BGIconProps extends IconProps {
36+
type?: 'square' | 'circle';
3537
}
38+
39+
export const BGIcon: FC<BGIconProps> = ({
40+
className = '',
41+
type = 'square',
42+
color = 'primary',
43+
children,
44+
...props
45+
}) => (
46+
<span
47+
className={classNames(
48+
'd-inline-block',
49+
'p-3',
50+
`bg-${color}`,
51+
`rounded${type === 'square' ? '' : '-circle'}`,
52+
className
53+
)}
54+
{...props}
55+
>
56+
<Icon color={color === 'light' ? 'dark' : 'light'} {...props} />
57+
</span>
58+
);

0 commit comments

Comments
 (0)