@boostdev/design-system-components 0.1.17 → 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/AGENTS.md +65 -27
- package/README.md +64 -29
- package/dist/client.cjs +412 -241
- package/dist/client.css +1380 -1186
- package/dist/client.d.cts +43 -16
- package/dist/client.d.ts +43 -16
- package/dist/client.js +414 -245
- package/dist/index.cjs +412 -241
- package/dist/index.css +1380 -1186
- package/dist/index.d.cts +43 -16
- package/dist/index.d.ts +43 -16
- package/dist/index.js +414 -245
- package/package.json +9 -4
- package/src/components/interaction/Button/Button.mdx +2 -5
- package/src/components/interaction/Button/Button.module.css +74 -44
- package/src/components/interaction/Button/Button.stories.tsx +4 -4
- package/src/components/interaction/Button/Button.tsx +5 -5
- package/src/components/interaction/Button/index.ts +1 -0
- package/src/components/interaction/Command/Command.module.css +53 -38
- package/src/components/interaction/Command/Command.spec.tsx +24 -0
- package/src/components/interaction/Command/Command.tsx +5 -0
- package/src/components/interaction/Dialog/Dialog.mdx +2 -2
- package/src/components/interaction/Dialog/Dialog.module.css +20 -10
- package/src/components/interaction/Dialog/Dialog.spec.tsx +19 -0
- package/src/components/interaction/Dialog/Dialog.tsx +22 -0
- package/src/components/interaction/Drawer/Drawer.module.css +13 -11
- package/src/components/interaction/Drawer/Drawer.spec.tsx +30 -0
- package/src/components/interaction/Drawer/Drawer.tsx +7 -3
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +24 -19
- package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +4 -4
- package/src/components/interaction/Popover/Popover.module.css +17 -12
- package/src/components/interaction/Popover/Popover.spec.tsx +25 -4
- package/src/components/interaction/Popover/Popover.stories.tsx +1 -1
- package/src/components/interaction/Popover/Popover.tsx +5 -2
- package/src/components/interaction/Rating/Rating.module.css +3 -3
- package/src/components/interaction/Toast/Toast.module.css +19 -19
- package/src/components/interaction/Toast/Toast.tsx +1 -1
- package/src/components/interaction/form/Checkbox/Checkbox.mdx +2 -2
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +22 -18
- package/src/components/interaction/form/Checkbox/Checkbox.tsx +2 -2
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +29 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +87 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.stories.tsx +62 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +46 -0
- package/src/components/interaction/form/CheckboxGroup/index.ts +2 -0
- package/src/components/interaction/form/Combobox/Combobox.module.css +44 -34
- package/src/components/interaction/form/Combobox/Combobox.tsx +0 -1
- package/src/components/interaction/form/FileInput/FileInput.module.css +24 -16
- package/src/components/interaction/form/FileInput/FileInput.tsx +5 -2
- package/src/components/interaction/form/FormInput/FormInput.module.css +21 -16
- package/src/components/interaction/form/FormInput/FormInput.tsx +3 -0
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +25 -19
- package/src/components/interaction/form/NumberInput/NumberInput.tsx +5 -2
- package/src/components/interaction/form/Radio/Radio.mdx +3 -3
- package/src/components/interaction/form/Radio/Radio.module.css +28 -24
- package/src/components/interaction/form/Radio/Radio.stories.tsx +1 -1
- package/src/components/interaction/form/Radio/Radio.tsx +2 -2
- package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +29 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +75 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.stories.tsx +64 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +46 -0
- package/src/components/interaction/form/RadioGroup/index.ts +2 -0
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +5 -5
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +26 -26
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +4 -0
- package/src/components/interaction/form/Select/Select.module.css +24 -19
- package/src/components/interaction/form/Select/Select.tsx +3 -0
- package/src/components/interaction/form/Slider/Slider.mdx +1 -1
- package/src/components/interaction/form/Slider/Slider.module.css +24 -24
- package/src/components/interaction/form/Slider/Slider.tsx +1 -0
- package/src/components/interaction/form/Switch/Switch.mdx +4 -4
- package/src/components/interaction/form/Switch/Switch.module.css +22 -16
- package/src/components/interaction/form/Switch/Switch.tsx +1 -1
- package/src/components/interaction/form/Textarea/Textarea.module.css +23 -18
- package/src/components/interaction/form/Textarea/Textarea.tsx +3 -0
- package/src/components/interaction/form/atoms/InputContainer.module.css +2 -2
- package/src/components/interaction/form/atoms/Label.module.css +2 -2
- package/src/components/interaction/form/atoms/Message.module.css +2 -2
- package/src/components/layout/ButtonGroup/ButtonGroup.module.css +2 -2
- package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +2 -2
- package/src/components/layout/ButtonGroup/ButtonGroup.tsx +8 -3
- package/src/components/layout/ButtonGroup/index.ts +1 -0
- package/src/components/layout/Card/Card.module.css +30 -16
- package/src/components/layout/Card/Card.tsx +1 -1
- package/src/components/layout/IconWrapper/IconWrapper.mdx +2 -2
- package/src/components/layout/IconWrapper/IconWrapper.module.css +5 -5
- package/src/components/layout/IconWrapper/IconWrapper.tsx +4 -3
- package/src/components/layout/IconWrapper/index.ts +1 -0
- package/src/components/layout/SectionHeader/SectionHeader.module.css +23 -23
- package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +2 -2
- package/src/components/layout/SectionHeader/SectionHeader.tsx +2 -2
- package/src/components/ui/Accordion/Accordion.module.css +23 -18
- package/src/components/ui/Alert/Alert.module.css +31 -27
- package/src/components/ui/Avatar/Avatar.module.css +6 -6
- package/src/components/ui/Avatar/Avatar.tsx +1 -1
- package/src/components/ui/Badge/Badge.mdx +2 -2
- package/src/components/ui/Badge/Badge.module.css +15 -15
- package/src/components/ui/Breadcrumb/Breadcrumb.module.css +11 -11
- package/src/components/ui/Calendar/Calendar.module.css +39 -29
- package/src/components/ui/Calendar/Calendar.tsx +6 -2
- package/src/components/ui/Carousel/Carousel.module.css +15 -10
- package/src/components/ui/Carousel/Carousel.stories.tsx +1 -1
- package/src/components/ui/Collapsible/Collapsible.mdx +6 -6
- package/src/components/ui/Collapsible/Collapsible.module.css +18 -18
- package/src/components/ui/DescriptionList/DescriptionList.module.css +8 -8
- package/src/components/ui/Link/Link.module.css +14 -14
- package/src/components/ui/Loading/Loading.module.css +8 -2
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +27 -23
- package/src/components/ui/Pagination/Pagination.module.css +22 -17
- package/src/components/ui/Progress/Progress.mdx +1 -1
- package/src/components/ui/Progress/Progress.module.css +10 -10
- package/src/components/ui/ProgressCircle/ProgressCircle.module.css +8 -8
- package/src/components/ui/Separator/Separator.module.css +1 -1
- package/src/components/ui/Separator/Separator.tsx +1 -1
- package/src/components/ui/Skeleton/Skeleton.module.css +5 -5
- package/src/components/ui/SkipLink/SkipLink.module.css +17 -12
- package/src/components/ui/Table/Table.module.css +35 -30
- package/src/components/ui/Table/Table.tsx +2 -1
- package/src/components/ui/Tabs/Tabs.module.css +17 -17
- package/src/components/ui/Tabs/Tabs.tsx +0 -1
- package/src/components/ui/Tooltip/Tooltip.module.css +12 -12
- package/src/components/ui/Tooltip/Tooltip.spec.tsx +3 -3
- package/src/components/ui/Tooltip/Tooltip.tsx +10 -2
- package/src/components/ui/Typography/Typography.module.css +18 -18
- package/src/css/bdc.css +61 -0
- package/src/css/index.css +5 -0
- package/src/index.ts +7 -0
- package/src/stories/DesignSystem/Borders.mdx +158 -0
- package/src/stories/DesignSystem/Colors.mdx +196 -0
- package/src/stories/DesignSystem/Elevation.mdx +127 -0
- package/src/stories/DesignSystem/Grid.mdx +140 -0
- package/src/stories/DesignSystem/Motion.mdx +96 -0
- package/src/stories/DesignSystem/Overview.mdx +99 -0
- package/src/stories/DesignSystem/Spacing.mdx +74 -0
- package/src/stories/DesignSystem/Typography.mdx +110 -0
- package/src/stories/Introduction.css +2 -2
- package/src/stories/Introduction.mdx +7 -7
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Design System/Spacing" />
|
|
4
|
+
|
|
5
|
+
export const SpaceStep = ({ token, mobile, tablet, desktop }) => (
|
|
6
|
+
<div style={{ display: 'grid', gridTemplateColumns: '10rem auto 1fr', gap: '0 1.5rem', alignItems: 'center', padding: '0.625rem 0', borderBottom: '1px solid var(--bds-grey--subtle)' }}>
|
|
7
|
+
<code style={{ fontSize: '0.75rem' }}>{token}</code>
|
|
8
|
+
<div style={{ width: `var(${token})`, height: '1.25rem', background: 'var(--bds-interactive)', borderRadius: '0.125rem', minWidth: '2px' }} />
|
|
9
|
+
<div style={{ fontSize: '0.75rem', color: 'var(--bds-grey)', fontFamily: 'monospace' }}>
|
|
10
|
+
{mobile}{tablet !== mobile ? ` → ${tablet}` : ''}{desktop !== tablet ? ` → ${desktop}` : ''}
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
# Spacing
|
|
16
|
+
|
|
17
|
+
All spacing values use a named scale — `xxxs` through `xxxxl`. Larger values are responsive and grow at `40rem`, `48rem`, and `64rem` breakpoints. Use these tokens for margins, paddings, and gaps everywhere.
|
|
18
|
+
|
|
19
|
+
**Never use raw `px` or `rem` values in component CSS.** Use the scale tokens.
|
|
20
|
+
|
|
21
|
+
## Scale
|
|
22
|
+
|
|
23
|
+
<SpaceStep token="--bds-space_xxxs" mobile="2px" tablet="2px" desktop="2px" />
|
|
24
|
+
<SpaceStep token="--bds-space_xxs" mobile="4px" tablet="4px" desktop="4px" />
|
|
25
|
+
<SpaceStep token="--bds-space_xs" mobile="8px" tablet="8px" desktop="8px" />
|
|
26
|
+
<SpaceStep token="--bds-space_s" mobile="12px" tablet="12px" desktop="12px" />
|
|
27
|
+
<SpaceStep token="--bds-space_m" mobile="16px" tablet="16px" desktop="16px" />
|
|
28
|
+
<SpaceStep token="--bds-space_l" mobile="16px" tablet="24px" desktop="24px" />
|
|
29
|
+
<SpaceStep token="--bds-space_xl" mobile="16px" tablet="24px" desktop="32px" />
|
|
30
|
+
<SpaceStep token="--bds-space_xxl" mobile="24px" tablet="32px" desktop="48px" />
|
|
31
|
+
<SpaceStep token="--bds-space_xxxl" mobile="32px" tablet="40px" desktop="64px" />
|
|
32
|
+
<SpaceStep token="--bds-space_xxxxl" mobile="40px" tablet="48px" desktop="96px" />
|
|
33
|
+
|
|
34
|
+
## Responsive values
|
|
35
|
+
|
|
36
|
+
| Token | Mobile | 40rem+ | 48rem+ |
|
|
37
|
+
|-------|--------|--------|--------|
|
|
38
|
+
| `--bds-space_xxxs` | 0.125rem | 0.125rem | 0.125rem |
|
|
39
|
+
| `--bds-space_xxs` | 0.25rem | 0.25rem | 0.25rem |
|
|
40
|
+
| `--bds-space_xs` | 0.5rem | 0.5rem | 0.5rem |
|
|
41
|
+
| `--bds-space_s` | 0.75rem | 0.75rem | 0.75rem |
|
|
42
|
+
| `--bds-space_m` | 1rem | 1rem | 1rem |
|
|
43
|
+
| `--bds-space_l` | 1rem | 1.5rem | 1.5rem |
|
|
44
|
+
| `--bds-space_xl` | 1rem | 1.5rem | 2rem |
|
|
45
|
+
| `--bds-space_xxl` | 1.5rem | 2rem | 3rem |
|
|
46
|
+
| `--bds-space_xxxl` | 2rem | 2.5rem | 4rem |
|
|
47
|
+
| `--bds-space_xxxxl` | 2.5rem | 3rem | 6rem |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Container tokens
|
|
52
|
+
|
|
53
|
+
| Token | Value | Use |
|
|
54
|
+
|-------|-------|-----|
|
|
55
|
+
| `--bds-container_max-width` | Responsive | Page-level container width |
|
|
56
|
+
| `--bds-container_max-width--narrow` | 48rem (fixed) | Narrow content like forms, articles |
|
|
57
|
+
| `--bds-container_min-width` | min-content | Prevents overflow |
|
|
58
|
+
| `--bds-container_spacing` | Responsive | Outer page margin |
|
|
59
|
+
| `--bds-container_spacing-inline` | Responsive | Horizontal gutter padding |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
.card {
|
|
67
|
+
padding: var(--bds-space_m);
|
|
68
|
+
gap: var(--bds-space_s);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.section {
|
|
72
|
+
padding-block: var(--bds-space_xxxl);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Design System/Typography" />
|
|
4
|
+
|
|
5
|
+
export const TypeScale = ({ token, label, style = {} }) => (
|
|
6
|
+
<div style={{ display: 'grid', gridTemplateColumns: '10rem 1fr', gap: '0.5rem 1.5rem', alignItems: 'baseline', padding: '0.75rem 0', borderBottom: '1px solid var(--bds-grey--subtle)' }}>
|
|
7
|
+
<div style={{ fontSize: '0.75rem', fontFamily: 'monospace', color: 'var(--bds-on-bg--muted, var(--bds-grey))', lineHeight: 1.4 }}>
|
|
8
|
+
{token}
|
|
9
|
+
</div>
|
|
10
|
+
<div style={{ fontFamily: 'var(--bds-font_family--body)', fontSize: `var(${token})`, ...style }}>
|
|
11
|
+
{label}
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export const WeightSample = ({ weight, token, label }) => (
|
|
17
|
+
<div style={{ display: 'grid', gridTemplateColumns: '12rem 1fr', gap: '0.5rem 1.5rem', alignItems: 'baseline', padding: '0.75rem 0', borderBottom: '1px solid var(--bds-grey--subtle)' }}>
|
|
18
|
+
<div style={{ fontSize: '0.75rem', fontFamily: 'monospace', color: 'var(--bds-grey)' }}>
|
|
19
|
+
<div>{token}</div>
|
|
20
|
+
<div style={{ opacity: 0.7 }}>{weight}</div>
|
|
21
|
+
</div>
|
|
22
|
+
<div style={{ fontFamily: 'var(--bds-font_family--body)', fontWeight: `var(${token})`, fontSize: '1.25rem' }}>
|
|
23
|
+
{label} — The quick brown fox
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const TrackingSample = ({ token, label, value }) => (
|
|
29
|
+
<div style={{ display: 'grid', gridTemplateColumns: '12rem 1fr', gap: '0.5rem 1.5rem', alignItems: 'baseline', padding: '0.75rem 0', borderBottom: '1px solid var(--bds-grey--subtle)' }}>
|
|
30
|
+
<div style={{ fontSize: '0.75rem', fontFamily: 'monospace', color: 'var(--bds-grey)' }}>
|
|
31
|
+
<div>{token}</div>
|
|
32
|
+
<div style={{ opacity: 0.7 }}>{value}</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div style={{ fontFamily: 'var(--bds-font_family--body)', letterSpacing: `var(${token})`, fontSize: '1rem' }}>
|
|
35
|
+
{label}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
# Typography
|
|
41
|
+
|
|
42
|
+
## Font families
|
|
43
|
+
|
|
44
|
+
| Token | Value |
|
|
45
|
+
|-------|-------|
|
|
46
|
+
| `--bds-font_family--heading` | Arial, Helvetica, sans-serif |
|
|
47
|
+
| `--bds-font_family--body` | Arial, Helvetica, sans-serif |
|
|
48
|
+
|
|
49
|
+
Override both tokens to apply a custom typeface globally:
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
@layer tokens.override {
|
|
53
|
+
:root {
|
|
54
|
+
--bds-font_family--heading: 'Inter', sans-serif;
|
|
55
|
+
--bds-font_family--body: 'Inter', sans-serif;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Font size scale
|
|
63
|
+
|
|
64
|
+
Font sizes are responsive — they grow at `48rem` and `64rem` breakpoints.
|
|
65
|
+
The values shown reflect the **desktop** (64rem+) scale.
|
|
66
|
+
|
|
67
|
+
<TypeScale token="--bds-font_size--display" label="Display — Hero headlines" style={{ fontWeight: 700, lineHeight: 1.05 }} />
|
|
68
|
+
<TypeScale token="--bds-font_size--heading-1" label="Heading 1 — Page titles" style={{ fontWeight: 700, lineHeight: 1.2 }} />
|
|
69
|
+
<TypeScale token="--bds-font_size--heading-2" label="Heading 2 — Section titles" style={{ fontWeight: 700, lineHeight: 1.2 }} />
|
|
70
|
+
<TypeScale token="--bds-font_size--heading-3" label="Heading 3 — Sub-sections" style={{ fontWeight: 600, lineHeight: 1.2 }} />
|
|
71
|
+
<TypeScale token="--bds-font_size--body" label="Body — Default paragraph text" />
|
|
72
|
+
<TypeScale token="--bds-font_size--body--s" label="Body small — Captions, hints, meta" />
|
|
73
|
+
|
|
74
|
+
### Responsive values
|
|
75
|
+
|
|
76
|
+
| Token | Mobile | Tablet (48rem) | Desktop (64rem) |
|
|
77
|
+
|-------|--------|----------------|-----------------|
|
|
78
|
+
| `--bds-font_size--display` | 3.5rem | 4.5rem | 6rem |
|
|
79
|
+
| `--bds-font_size--heading-1` | 2rem | 2.5rem | 3rem |
|
|
80
|
+
| `--bds-font_size--heading-2` | 1.5rem | 1.75rem | 2rem |
|
|
81
|
+
| `--bds-font_size--heading-3` | 1.25rem | 1.375rem | 1.5rem |
|
|
82
|
+
| `--bds-font_size--body` | 1em | 1em | 1em |
|
|
83
|
+
| `--bds-font_size--body--s` | 0.875em | 0.875em | 0.875em |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Font weight
|
|
88
|
+
|
|
89
|
+
<WeightSample token="--bds-font_weight--light" weight="300" label="Light" />
|
|
90
|
+
<WeightSample token="--bds-font_weight--medium" weight="400" label="Medium / Body" />
|
|
91
|
+
<WeightSample token="--bds-font_weight--semibold" weight="600" label="Semibold / Subheading" />
|
|
92
|
+
<WeightSample token="--bds-font_weight--bold" weight="700" label="Bold / Heading" />
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Line height
|
|
97
|
+
|
|
98
|
+
| Token | Value | Use |
|
|
99
|
+
|-------|-------|-----|
|
|
100
|
+
| `--bds-font_line-height--display` | 1.05 | Display headings — very tight |
|
|
101
|
+
| `--bds-font_line-height--heading` | 1.2 | Section headings |
|
|
102
|
+
| `--bds-font_line-height--body` | 1.6 | Body text — comfortable reading |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Letter spacing (tracking)
|
|
107
|
+
|
|
108
|
+
<TrackingSample token="--bds-font_tracking--tight" label="Display headlines use tight tracking" value="-0.02em" />
|
|
109
|
+
<TrackingSample token="--bds-font_tracking--normal" label="Body text uses normal tracking" value="0" />
|
|
110
|
+
<TrackingSample token="--bds-font_tracking--wide" label="SMALL CAPS, BADGES USE WIDE TRACKING" value="0.06em" />
|
|
@@ -20,8 +20,8 @@ import {Card} from "../components/layout/Card/index.ts";
|
|
|
20
20
|
Accessible, token-driven React components. Zero extra runtime.
|
|
21
21
|
</p>
|
|
22
22
|
<ButtonGroup variant="content">
|
|
23
|
-
<Button variant="
|
|
24
|
-
<Button variant="
|
|
23
|
+
<Button variant="ghost" href="https://www.npmjs.com/package/@boostdev/design-system-foundation">DS Foundation</Button>
|
|
24
|
+
<Button variant="ghost" href="https://www.npmjs.com/package/@boostdev/design-system-components">DS Components</Button>
|
|
25
25
|
</ButtonGroup>
|
|
26
26
|
</div>
|
|
27
27
|
---
|
|
@@ -93,11 +93,11 @@ import {Card} from "../components/layout/Card/index.ts";
|
|
|
93
93
|
```css
|
|
94
94
|
@layer tokens.override {
|
|
95
95
|
:root {
|
|
96
|
-
--
|
|
97
|
-
--
|
|
98
|
-
--
|
|
99
|
-
--
|
|
100
|
-
--
|
|
96
|
+
--bds-cta: var(--bds-BASE__color--orange);
|
|
97
|
+
--bds-on-cta: var(--bds-BASE__color--white);
|
|
98
|
+
--bds-interactive: var(--bds-BASE__color--orange);
|
|
99
|
+
--bds-active: var(--bds-BASE__color--orange);
|
|
100
|
+
--bds-on-active: var(--bds-BASE__color--white);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
```
|