@byline/ui 6.7.2 → 6.9.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/README.md +43 -5
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/icons/passkey-icon.d.ts +6 -0
- package/dist/icons/passkey-icon.js +43 -0
- package/dist/uikit.d.ts +1 -0
- package/dist/uikit.js +1 -0
- package/package.json +12 -3
- package/src/components/accordion/accordion.stories.tsx +121 -0
- package/src/components/animation/fade-in-lift.stories.tsx +80 -0
- package/src/components/avatar/avatar.stories.tsx +39 -0
- package/src/components/badge/badge.stories.tsx +41 -0
- package/src/components/button/button-group.stories.tsx +44 -0
- package/src/components/button/button-intents.stories.tsx +97 -0
- package/src/components/button/button-overrides.stories.tsx +59 -0
- package/src/components/button/button-test.stories.tsx +59 -0
- package/src/components/button/button-variants.stories.tsx +57 -0
- package/src/components/button/combo-buttons.stories.tsx +82 -0
- package/src/components/button/control-buttons.stories.tsx +60 -0
- package/src/components/button/copy-button.stories.tsx +50 -0
- package/src/components/button/icon-button.stories.tsx +140 -0
- package/src/components/card/card.stories.tsx +60 -0
- package/src/components/chips/chip.stories.tsx +120 -0
- package/src/components/container/container.stories.tsx +35 -0
- package/src/components/dropdown/dropdown.stories.tsx +108 -0
- package/src/components/hamburger/hamburger.stories.tsx +33 -0
- package/src/components/inputs/autocomplete.stories.tsx +189 -0
- package/src/components/inputs/calendar.stories.tsx +141 -0
- package/src/components/inputs/checkbox-group.stories.tsx +43 -0
- package/src/components/inputs/checkbox.stories.tsx +284 -0
- package/src/components/inputs/input.stories.tsx +189 -0
- package/src/components/inputs/radio-group.stories.tsx +73 -0
- package/src/components/inputs/select.stories.tsx +70 -0
- package/src/components/inputs/text-area.stories.tsx +45 -0
- package/src/components/notifications/alert.stories.tsx +75 -0
- package/src/components/notifications/toast.stories.tsx +40 -0
- package/src/components/pager/pagination.stories.tsx +189 -0
- package/src/components/scroll-area/scroll-area.stories.tsx +33 -0
- package/src/components/shimmer/shimmer.stories.tsx +24 -0
- package/src/components/table/table.stories.tsx +94 -0
- package/src/components/tabs/tabs.stories.tsx +47 -0
- package/src/components/tooltip/tooltip.stories.tsx +56 -0
- package/src/icons/icons.stories.tsx +67 -0
- package/src/icons/index.stories.tsx +24 -0
- package/src/icons/index.ts +1 -0
- package/src/icons/passkey-icon.tsx +39 -0
- package/src/loaders/loaders.stories.tsx +188 -0
- package/src/styles/base/colors.stories.tsx +671 -0
- package/src/styles/theme/theme.stories.tsx +40 -0
- package/src/styles/typography/article.stories.tsx +39 -0
- package/src/styles/typography/code.stories.tsx +73 -0
- package/src/styles/typography/default.stories.tsx +49 -0
- package/src/styles/typography/lists.stories.tsx +48 -0
- package/src/styles/typography/quote.stories.tsx +38 -0
- package/src/uikit.ts +1 -0
- package/src/widgets/datepicker/datepicker.stories.tsx +42 -0
- package/src/widgets/drawer/drawer.stories.tsx +281 -0
- package/src/widgets/modal/modal.stories.tsx +63 -0
- package/src/widgets/search/search.stories.tsx +18 -0
- package/src/widgets/timeline/timeline.stories.tsx +50 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
|
|
3
|
+
import { SignOutIcon } from '../../icons/sign-out-icon.js'
|
|
4
|
+
import { UserIcon } from '../../icons/user-icon.js'
|
|
5
|
+
import { Button } from '../button/button.js'
|
|
6
|
+
import { Dropdown as DropdownComponent } from './dropdown.js'
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
/* 👇 The title prop is optional.
|
|
10
|
+
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
|
|
11
|
+
* to learn how to generate automatic titles
|
|
12
|
+
*/
|
|
13
|
+
title: 'Components/Dropdown',
|
|
14
|
+
component: DropdownComponent.Root,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default meta
|
|
18
|
+
|
|
19
|
+
type Story = StoryObj<typeof DropdownComponent.Root>
|
|
20
|
+
|
|
21
|
+
export const Dropdown: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
modal: false,
|
|
24
|
+
},
|
|
25
|
+
render: (args) => {
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<style>
|
|
29
|
+
{`
|
|
30
|
+
.dropdown-item-content {
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.dropdown-item-content-icon {
|
|
36
|
+
display: inline-block;
|
|
37
|
+
width: 28px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.dropdown-item-content-text {
|
|
41
|
+
text-align: left;
|
|
42
|
+
display: inline-block;
|
|
43
|
+
width: 100%;
|
|
44
|
+
flex: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
`}
|
|
48
|
+
</style>
|
|
49
|
+
<div
|
|
50
|
+
style={{
|
|
51
|
+
maxWidth: '400px',
|
|
52
|
+
margin: '2rem 0 24px',
|
|
53
|
+
display: 'flex',
|
|
54
|
+
justifyContent: 'center',
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<DropdownComponent.Root {...args}>
|
|
58
|
+
<DropdownComponent.Trigger render={<Button size="sm" variant="filled" />}>
|
|
59
|
+
+
|
|
60
|
+
</DropdownComponent.Trigger>
|
|
61
|
+
|
|
62
|
+
<DropdownComponent.Portal>
|
|
63
|
+
<DropdownComponent.Content align="end" data-side="top" sideOffset={10}>
|
|
64
|
+
<DropdownComponent.Item>
|
|
65
|
+
<div className="dropdown-item-content">
|
|
66
|
+
<span className="dropdown-item-content-icon">
|
|
67
|
+
<UserIcon width="22px" height="22px" />
|
|
68
|
+
</span>
|
|
69
|
+
<span className="dropdown-item-content-text">Account</span>
|
|
70
|
+
</div>
|
|
71
|
+
</DropdownComponent.Item>
|
|
72
|
+
<DropdownComponent.Item>
|
|
73
|
+
<div className="dropdown-item-content">
|
|
74
|
+
<span className="dropdown-item-content-icon" />
|
|
75
|
+
<span className="dropdown-item-content-text">Menu Item 2</span>
|
|
76
|
+
</div>
|
|
77
|
+
</DropdownComponent.Item>
|
|
78
|
+
<DropdownComponent.Separator />
|
|
79
|
+
<DropdownComponent.Item>
|
|
80
|
+
<div className="dropdown-item-content">
|
|
81
|
+
<span className="dropdown-item-content-icon">
|
|
82
|
+
<SignOutIcon />
|
|
83
|
+
</span>
|
|
84
|
+
<span className="dropdown-item-content-text">
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
style={{
|
|
88
|
+
textAlign: 'left',
|
|
89
|
+
display: 'inline-block',
|
|
90
|
+
width: '100%',
|
|
91
|
+
flex: 1,
|
|
92
|
+
lineHeight: 1,
|
|
93
|
+
color: 'var(--text)',
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
Sign Out
|
|
97
|
+
</button>
|
|
98
|
+
</span>
|
|
99
|
+
</div>
|
|
100
|
+
</DropdownComponent.Item>
|
|
101
|
+
</DropdownComponent.Content>
|
|
102
|
+
</DropdownComponent.Portal>
|
|
103
|
+
</DropdownComponent.Root>
|
|
104
|
+
</div>
|
|
105
|
+
</>
|
|
106
|
+
)
|
|
107
|
+
},
|
|
108
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import type { Meta } from '@storybook/react-vite'
|
|
5
|
+
|
|
6
|
+
import { Section } from '../section/section.js'
|
|
7
|
+
import { Hamburger as HamburgerComponent } from './hamburger.js'
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof HamburgerComponent> = {
|
|
10
|
+
/* 👇 The title prop is optional.
|
|
11
|
+
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
|
|
12
|
+
* to learn how to generate automatic titles
|
|
13
|
+
*/
|
|
14
|
+
title: 'Components/Hamburger',
|
|
15
|
+
component: HamburgerComponent,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
|
|
20
|
+
export const Hamburger = (): React.JSX.Element => {
|
|
21
|
+
const [open, setOpen] = useState(false)
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Section style={{ height: '100vh', margin: '2rem auto' }}>
|
|
25
|
+
<HamburgerComponent
|
|
26
|
+
open={open}
|
|
27
|
+
onChange={(open) => {
|
|
28
|
+
setOpen(open)
|
|
29
|
+
}}
|
|
30
|
+
/>
|
|
31
|
+
</Section>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
|
|
3
|
+
import { capitalize } from '../../utils/capitalize.js'
|
|
4
|
+
import { intent } from '../@types/shared.js'
|
|
5
|
+
import { size, variant } from './@types/autocomplete.js'
|
|
6
|
+
import { Autocomplete, AutocompleteItem } from './autocomplete.js'
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Components/Inputs/Autocomplete',
|
|
10
|
+
component: Autocomplete,
|
|
11
|
+
argTypes: {},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Tag {
|
|
15
|
+
id: string
|
|
16
|
+
value: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const tags: Tag[] = [
|
|
20
|
+
{ id: 't1', value: 'feature' },
|
|
21
|
+
{ id: 't2', value: 'fix' },
|
|
22
|
+
{ id: 't3', value: 'bug' },
|
|
23
|
+
{ id: 't4', value: 'docs' },
|
|
24
|
+
{ id: 't5', value: 'internal' },
|
|
25
|
+
{ id: 't6', value: 'mobile' },
|
|
26
|
+
{ id: 'c-accordion', value: 'component: accordion' },
|
|
27
|
+
{ id: 'c-alert-dialog', value: 'component: alert dialog' },
|
|
28
|
+
{ id: 'c-autocomplete', value: 'component: autocomplete' },
|
|
29
|
+
{ id: 'c-avatar', value: 'component: avatar' },
|
|
30
|
+
{ id: 'c-checkbox', value: 'component: checkbox' },
|
|
31
|
+
{ id: 'c-dialog', value: 'component: dialog' },
|
|
32
|
+
{ id: 'c-input', value: 'component: input' },
|
|
33
|
+
{ id: 'c-select', value: 'component: select' },
|
|
34
|
+
{ id: 'c-tabs', value: 'component: tabs' },
|
|
35
|
+
{ id: 'c-toast', value: 'component: toast' },
|
|
36
|
+
{ id: 'c-tooltip', value: 'component: tooltip' },
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
export const Default = (): React.JSX.Element => {
|
|
40
|
+
return (
|
|
41
|
+
<div style={{ maxWidth: '600px', margin: '2rem auto' }}>
|
|
42
|
+
<Autocomplete<Tag>
|
|
43
|
+
id="tags-default"
|
|
44
|
+
label="Search tags"
|
|
45
|
+
placeholder="e.g. feature"
|
|
46
|
+
helpText="Start typing to filter tags."
|
|
47
|
+
items={tags}
|
|
48
|
+
>
|
|
49
|
+
{(tag: Tag) => (
|
|
50
|
+
<AutocompleteItem key={tag.id} value={tag}>
|
|
51
|
+
{tag.value}
|
|
52
|
+
</AutocompleteItem>
|
|
53
|
+
)}
|
|
54
|
+
</Autocomplete>
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const Variants = (): React.JSX.Element => {
|
|
60
|
+
return (
|
|
61
|
+
<div style={{ maxWidth: '1100px', margin: '0 auto' }}>
|
|
62
|
+
{variant.map((v) => {
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
key={v}
|
|
66
|
+
style={{
|
|
67
|
+
marginBottom: '2rem',
|
|
68
|
+
display: 'grid',
|
|
69
|
+
gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
|
|
70
|
+
alignItems: 'center',
|
|
71
|
+
gap: '3rem',
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{size.map((s) => {
|
|
75
|
+
return (
|
|
76
|
+
<Autocomplete<Tag>
|
|
77
|
+
key={`${v}-${s}`}
|
|
78
|
+
id={`${v}-${s}`}
|
|
79
|
+
variant={v}
|
|
80
|
+
inputSize={s}
|
|
81
|
+
label={`${capitalize(v)} ${s.toUpperCase()}`}
|
|
82
|
+
placeholder={`${capitalize(v)} ${s.toUpperCase()}`}
|
|
83
|
+
helpText={`${capitalize(v)} variant, ${s.toUpperCase()} size.`}
|
|
84
|
+
items={tags}
|
|
85
|
+
>
|
|
86
|
+
{(tag: Tag) => (
|
|
87
|
+
<AutocompleteItem key={tag.id} value={tag}>
|
|
88
|
+
{tag.value}
|
|
89
|
+
</AutocompleteItem>
|
|
90
|
+
)}
|
|
91
|
+
</Autocomplete>
|
|
92
|
+
)
|
|
93
|
+
})}
|
|
94
|
+
<Autocomplete<Tag>
|
|
95
|
+
key={`${v}-disabled`}
|
|
96
|
+
id={`${v}-disabled`}
|
|
97
|
+
variant={v}
|
|
98
|
+
disabled
|
|
99
|
+
label={`${capitalize(v)} Disabled`}
|
|
100
|
+
placeholder={`${capitalize(v)} disabled`}
|
|
101
|
+
helpText={`${capitalize(v)} variant, disabled.`}
|
|
102
|
+
items={tags}
|
|
103
|
+
>
|
|
104
|
+
{(tag: Tag) => (
|
|
105
|
+
<AutocompleteItem key={tag.id} value={tag}>
|
|
106
|
+
{tag.value}
|
|
107
|
+
</AutocompleteItem>
|
|
108
|
+
)}
|
|
109
|
+
</Autocomplete>
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
})}
|
|
113
|
+
</div>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const Intents = (): React.JSX.Element => {
|
|
118
|
+
return (
|
|
119
|
+
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
|
120
|
+
{intent.map((i) => {
|
|
121
|
+
return (
|
|
122
|
+
<div key={i} style={{ marginBottom: '12px' }}>
|
|
123
|
+
<Autocomplete<Tag>
|
|
124
|
+
id={`intent-${i}`}
|
|
125
|
+
variant="outlined"
|
|
126
|
+
intent={i}
|
|
127
|
+
inputSize="md"
|
|
128
|
+
label={capitalize(i)}
|
|
129
|
+
placeholder={capitalize(i)}
|
|
130
|
+
helpText={`${capitalize(i)} intent autocomplete.`}
|
|
131
|
+
items={tags}
|
|
132
|
+
>
|
|
133
|
+
{(tag: Tag) => (
|
|
134
|
+
<AutocompleteItem key={tag.id} value={tag}>
|
|
135
|
+
{tag.value}
|
|
136
|
+
</AutocompleteItem>
|
|
137
|
+
)}
|
|
138
|
+
</Autocomplete>
|
|
139
|
+
</div>
|
|
140
|
+
)
|
|
141
|
+
})}
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// biome-ignore lint/suspicious/noShadowRestrictedNames: storybook convention
|
|
147
|
+
export const Error = (): React.JSX.Element => {
|
|
148
|
+
return (
|
|
149
|
+
<div style={{ maxWidth: '600px', margin: '0 auto' }}>
|
|
150
|
+
<Autocomplete<Tag>
|
|
151
|
+
id="tags-error"
|
|
152
|
+
required
|
|
153
|
+
label="Search tags"
|
|
154
|
+
placeholder="e.g. feature"
|
|
155
|
+
helpText="Please select a tag."
|
|
156
|
+
error={true}
|
|
157
|
+
errorText="Please select a valid tag."
|
|
158
|
+
items={tags}
|
|
159
|
+
>
|
|
160
|
+
{(tag: Tag) => (
|
|
161
|
+
<AutocompleteItem key={tag.id} value={tag}>
|
|
162
|
+
{tag.value}
|
|
163
|
+
</AutocompleteItem>
|
|
164
|
+
)}
|
|
165
|
+
</Autocomplete>
|
|
166
|
+
</div>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const WithoutCustomItem = (): React.JSX.Element => {
|
|
171
|
+
const fruits = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape']
|
|
172
|
+
return (
|
|
173
|
+
<div style={{ maxWidth: '600px', margin: '2rem auto' }}>
|
|
174
|
+
<Autocomplete<string>
|
|
175
|
+
id="fruits"
|
|
176
|
+
label="Search fruits"
|
|
177
|
+
placeholder="e.g. Apple"
|
|
178
|
+
helpText="Using plain strings without AutocompleteItem wrapper."
|
|
179
|
+
items={fruits}
|
|
180
|
+
>
|
|
181
|
+
{(fruit: string) => (
|
|
182
|
+
<AutocompleteItem key={fruit} value={fruit}>
|
|
183
|
+
{fruit}
|
|
184
|
+
</AutocompleteItem>
|
|
185
|
+
)}
|
|
186
|
+
</Autocomplete>
|
|
187
|
+
</div>
|
|
188
|
+
)
|
|
189
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { useRef, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { Meta } from '@storybook/react-vite'
|
|
4
|
+
import { format } from 'date-fns'
|
|
5
|
+
import type { DateRange } from 'react-day-picker'
|
|
6
|
+
|
|
7
|
+
import { Button } from '../button/button.js'
|
|
8
|
+
import { Calendar as CalendarComponent } from './calendar.js'
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof CalendarComponent> = {
|
|
11
|
+
/* 👇 The title prop is optional.
|
|
12
|
+
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
|
|
13
|
+
* to learn how to generate automatic titles
|
|
14
|
+
*/
|
|
15
|
+
title: 'Components/Inputs/Calendar',
|
|
16
|
+
component: CalendarComponent,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default meta
|
|
20
|
+
|
|
21
|
+
export const Calendar = (): React.JSX.Element => {
|
|
22
|
+
const [_isOpen, setIsOpen] = useState(false)
|
|
23
|
+
const [time, _setTime] = useState<string>('05:00')
|
|
24
|
+
const [date, setDate] = useState<Date>(new Date())
|
|
25
|
+
const [month, setMonth] = useState<Date>(date)
|
|
26
|
+
|
|
27
|
+
const calendarRef = useRef<HTMLDivElement | null>(null)
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div style={{ height: '100vh', margin: '2rem 0' }}>
|
|
31
|
+
<div ref={calendarRef} style={{ position: 'relative', width: 'fit-content', margin: 'auto' }}>
|
|
32
|
+
<CalendarComponent
|
|
33
|
+
required
|
|
34
|
+
mode="single"
|
|
35
|
+
captionLayout="dropdown"
|
|
36
|
+
selected={date}
|
|
37
|
+
month={month}
|
|
38
|
+
onMonthChange={setMonth}
|
|
39
|
+
onSelect={(selectedDate: Date) => {
|
|
40
|
+
if (selectedDate) {
|
|
41
|
+
const [hours, minutes] = time.split(':')
|
|
42
|
+
selectedDate.setHours(Number.parseInt(hours, 10), Number.parseInt(minutes, 10))
|
|
43
|
+
setDate(selectedDate)
|
|
44
|
+
setMonth(selectedDate)
|
|
45
|
+
}
|
|
46
|
+
}}
|
|
47
|
+
onDayClick={() => setIsOpen(false)}
|
|
48
|
+
// fromYear={2000}
|
|
49
|
+
// toYear={new Date().getFullYear()}
|
|
50
|
+
// disabled={(date: Date) =>
|
|
51
|
+
// Number(date) < Date.now() - 1000 * 60 * 60 * 24 ||
|
|
52
|
+
// Number(date) > Date.now() + 1000 * 60 * 60 * 24 * 30
|
|
53
|
+
// }
|
|
54
|
+
/>
|
|
55
|
+
<div style={{ paddingLeft: '1rem', paddingTop: '1rem' }}>
|
|
56
|
+
{date ? `${format(date, 'PPPp')}` : 'No date selected'}
|
|
57
|
+
</div>
|
|
58
|
+
<div style={{ paddingLeft: '1rem', paddingTop: '1rem' }}>
|
|
59
|
+
<Button
|
|
60
|
+
size="sm"
|
|
61
|
+
intent="noeffect"
|
|
62
|
+
style={{ marginTop: '0.5rem' }}
|
|
63
|
+
onClick={() => {
|
|
64
|
+
const today = new Date()
|
|
65
|
+
setDate(today)
|
|
66
|
+
setMonth(today)
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
Today
|
|
70
|
+
</Button>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const Multiple = (): React.JSX.Element => {
|
|
78
|
+
const [_isOpen, setIsOpen] = useState(false)
|
|
79
|
+
const [dates, setDates] = useState<Date[] | undefined>([new Date()])
|
|
80
|
+
|
|
81
|
+
const calendarRef = useRef<HTMLDivElement | null>(null)
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div style={{ height: '100vh', margin: '2rem 0' }}>
|
|
85
|
+
<div ref={calendarRef} style={{ position: 'relative', width: 'fit-content', margin: 'auto' }}>
|
|
86
|
+
<CalendarComponent
|
|
87
|
+
required
|
|
88
|
+
mode="multiple"
|
|
89
|
+
captionLayout="dropdown"
|
|
90
|
+
selected={dates}
|
|
91
|
+
onSelect={(selectedDates: Date[]) => {
|
|
92
|
+
if (selectedDates) {
|
|
93
|
+
// selectedDate.setHours(Number.parseInt(hours), Number.parseInt(minutes))
|
|
94
|
+
setDates(selectedDates)
|
|
95
|
+
}
|
|
96
|
+
}}
|
|
97
|
+
onDayClick={() => setIsOpen(false)}
|
|
98
|
+
// fromYear={2000}
|
|
99
|
+
// toYear={new Date().getFullYear()}
|
|
100
|
+
// disabled={(date: Date) =>
|
|
101
|
+
// Number(date) < Date.now() - 1000 * 60 * 60 * 24 ||
|
|
102
|
+
// Number(date) > Date.now() + 1000 * 60 * 60 * 24 * 30
|
|
103
|
+
// }
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const Range = (): React.JSX.Element => {
|
|
111
|
+
const [_isOpen, setIsOpen] = useState(false)
|
|
112
|
+
const [dateRange, setDateRange] = useState<DateRange | undefined>(undefined)
|
|
113
|
+
|
|
114
|
+
const calendarRef = useRef<HTMLDivElement | null>(null)
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div style={{ height: '100vh', margin: '2rem 0' }}>
|
|
118
|
+
<div ref={calendarRef} style={{ position: 'relative', width: 'fit-content', margin: 'auto' }}>
|
|
119
|
+
<CalendarComponent
|
|
120
|
+
required
|
|
121
|
+
mode="range"
|
|
122
|
+
captionLayout="dropdown"
|
|
123
|
+
selected={dateRange}
|
|
124
|
+
onSelect={(selectedDateRange: DateRange) => {
|
|
125
|
+
if (selectedDateRange) {
|
|
126
|
+
// selectedDate.setHours(Number.parseInt(hours), Number.parseInt(minutes))
|
|
127
|
+
setDateRange(selectedDateRange)
|
|
128
|
+
}
|
|
129
|
+
}}
|
|
130
|
+
onDayClick={() => setIsOpen(false)}
|
|
131
|
+
// fromYear={2000}
|
|
132
|
+
// toYear={new Date().getFullYear()}
|
|
133
|
+
// disabled={(date: Date) =>
|
|
134
|
+
// Number(date) < Date.now() - 1000 * 60 * 60 * 24 ||
|
|
135
|
+
// Number(date) > Date.now() + 1000 * 60 * 60 * 24 * 30
|
|
136
|
+
// }
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import { CheckboxGroup } from './checkbox-group.js'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/Inputs/CheckboxGroup',
|
|
8
|
+
component: CheckboxGroup,
|
|
9
|
+
argTypes: {},
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Default = (): React.JSX.Element => {
|
|
13
|
+
const [checked, setChecked] = useState(false)
|
|
14
|
+
|
|
15
|
+
const _handleOnClick = (): void => {
|
|
16
|
+
console.log('clicked')
|
|
17
|
+
setChecked(!checked)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ maxWidth: '800px', margin: '2rem auto 2rem' }}>
|
|
22
|
+
<h2 style={{ fontSize: '1.25rem', marginBottom: '1rem' }}>Checkbox Group</h2>
|
|
23
|
+
<div
|
|
24
|
+
style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: '1rem' }}
|
|
25
|
+
>
|
|
26
|
+
<div style={{ minWidth: 0 }}>
|
|
27
|
+
<CheckboxGroup
|
|
28
|
+
groupName="roles"
|
|
29
|
+
// TODO: Nullability of role.name
|
|
30
|
+
checkBoxes={[
|
|
31
|
+
{ id: 'admin', label: 'Admin' },
|
|
32
|
+
{ id: 'editor', label: 'Editor' },
|
|
33
|
+
{ id: 'viewer', label: 'Viewer' },
|
|
34
|
+
]}
|
|
35
|
+
// onChange={(selected) => {
|
|
36
|
+
// handleOnClick(selected)
|
|
37
|
+
// }}
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
}
|