@flightlesslabs/dodo-ui-date 0.2.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/README.md +3 -0
- package/dist/components/Calendar/Calendar.scss +147 -0
- package/dist/components/Calendar/Calendar.stories.svelte +136 -0
- package/dist/components/Calendar/Calendar.stories.svelte.d.ts +22 -0
- package/dist/components/Calendar/Calendar.svelte +59 -0
- package/dist/components/Calendar/Calendar.svelte.d.ts +6 -0
- package/dist/components/Calendar/CalendarGrid/CalendarGrid.svelte +16 -0
- package/dist/components/Calendar/CalendarGrid/CalendarGrid.svelte.d.ts +4 -0
- package/dist/components/Calendar/CalendarGrid/TableBody.svelte +25 -0
- package/dist/components/Calendar/CalendarGrid/TableBody.svelte.d.ts +8 -0
- package/dist/components/Calendar/CalendarGrid/TableHead.svelte +19 -0
- package/dist/components/Calendar/CalendarGrid/TableHead.svelte.d.ts +6 -0
- package/dist/components/Calendar/Header.svelte +25 -0
- package/dist/components/Calendar/Header.svelte.d.ts +3 -0
- package/dist/components/DatePicker/DatePicker.scss +55 -0
- package/dist/components/DatePicker/DatePicker.stories.svelte +136 -0
- package/dist/components/DatePicker/DatePicker.stories.svelte.d.ts +22 -0
- package/dist/components/DatePicker/DatePicker.svelte +134 -0
- package/dist/components/DatePicker/DatePicker.svelte.d.ts +63 -0
- package/dist/components/DatePicker/DatePickerInput/DatePickerInput.svelte +95 -0
- package/dist/components/DatePicker/DatePickerInput/DatePickerInput.svelte.d.ts +22 -0
- package/dist/components/DatePicker/DatePickerInput/Segments.svelte +17 -0
- package/dist/components/DatePicker/DatePickerInput/Segments.svelte.d.ts +8 -0
- package/dist/components/DatePicker/DatePickerInput/utils.d.ts +10 -0
- package/dist/components/DatePicker/DatePickerInput/utils.js +26 -0
- package/dist/components/DatePicker/DatePickerPopup/CalendarGrid.svelte +35 -0
- package/dist/components/DatePicker/DatePickerPopup/CalendarGrid.svelte.d.ts +4 -0
- package/dist/components/DatePicker/DatePickerPopup/DatePickerPopup.svelte +50 -0
- package/dist/components/DatePicker/DatePickerPopup/DatePickerPopup.svelte.d.ts +6 -0
- package/dist/components/DatePicker/DatePickerPopup/Header.svelte +25 -0
- package/dist/components/DatePicker/DatePickerPopup/Header.svelte.d.ts +3 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/storybook-types.d.ts +129 -0
- package/dist/storybook-types.js +1 -0
- package/dist/styles/global/_breakpoints.scss +38 -0
- package/dist/styles/main.css +155 -0
- package/dist/styles/main.css.map +1 -0
- package/dist/styles/main.scss +2 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +12 -0
- package/package.json +114 -0
- package/src/lib/components/Calendar/Calendar.scss +147 -0
- package/src/lib/components/Calendar/Calendar.stories.svelte +136 -0
- package/src/lib/components/Calendar/Calendar.svelte +59 -0
- package/src/lib/components/Calendar/CalendarGrid/CalendarGrid.svelte +16 -0
- package/src/lib/components/Calendar/CalendarGrid/TableBody.svelte +25 -0
- package/src/lib/components/Calendar/CalendarGrid/TableHead.svelte +19 -0
- package/src/lib/components/Calendar/Header.svelte +25 -0
- package/src/lib/components/DatePicker/DatePicker.scss +55 -0
- package/src/lib/components/DatePicker/DatePicker.stories.svelte +136 -0
- package/src/lib/components/DatePicker/DatePicker.svelte +134 -0
- package/src/lib/components/DatePicker/DatePickerInput/DatePickerInput.svelte +95 -0
- package/src/lib/components/DatePicker/DatePickerInput/Segments.svelte +17 -0
- package/src/lib/components/DatePicker/DatePickerInput/utils.ts +55 -0
- package/src/lib/components/DatePicker/DatePickerPopup/CalendarGrid.svelte +35 -0
- package/src/lib/components/DatePicker/DatePickerPopup/DatePickerPopup.svelte +50 -0
- package/src/lib/components/DatePicker/DatePickerPopup/Header.svelte +25 -0
- package/src/lib/index.ts +16 -0
- package/src/lib/storybook-types.ts +182 -0
- package/src/lib/styles/global/_breakpoints.scss +38 -0
- package/src/lib/styles/main.scss +2 -0
- package/src/lib/test/setup.ts +13 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export type DatePickerInputProps = {
|
|
5
|
+
size?: ComponentSize;
|
|
6
|
+
roundness?: ComponentRoundnessShape;
|
|
7
|
+
outline?: boolean;
|
|
8
|
+
class?: string;
|
|
9
|
+
error?: boolean;
|
|
10
|
+
focused?: boolean;
|
|
11
|
+
before?: Snippet;
|
|
12
|
+
after?: Snippet;
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
dateFieldInputProps?: DateFieldInputProps;
|
|
15
|
+
datePickerTriggerProps?: DatePickerTriggerProps;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
dateFormat?: DatePickerFormat;
|
|
18
|
+
};
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<script lang="ts">
|
|
22
|
+
import { DatePicker, type DateFieldInputProps, type DatePickerTriggerProps } from 'bits-ui';
|
|
23
|
+
import Icon from '@iconify/svelte';
|
|
24
|
+
import Segments from './Segments.svelte';
|
|
25
|
+
import type { DatePickerFormat } from './utils.js';
|
|
26
|
+
import type { ComponentSize, ComponentRoundnessShape } from '@flightlesslabs/dodo-ui';
|
|
27
|
+
import { InputEnclosure } from '@flightlesslabs/dodo-ui';
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
size = 'normal',
|
|
31
|
+
class: className = '',
|
|
32
|
+
disabled = false,
|
|
33
|
+
error = false,
|
|
34
|
+
focused: forcedFocused = false,
|
|
35
|
+
placeholder,
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
37
|
+
after,
|
|
38
|
+
dateFieldInputProps,
|
|
39
|
+
datePickerTriggerProps,
|
|
40
|
+
dateFormat = 'dd/mm/yyyy',
|
|
41
|
+
...restProps
|
|
42
|
+
}: DatePickerInputProps = $props();
|
|
43
|
+
|
|
44
|
+
let isFocused = $state(false);
|
|
45
|
+
|
|
46
|
+
function handleFocus() {
|
|
47
|
+
isFocused = true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function handleBlur() {
|
|
51
|
+
isFocused = false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const classes = $derived(['dodo-ui-DatePicker', className].filter(Boolean));
|
|
55
|
+
|
|
56
|
+
const triggerClasses = $derived(
|
|
57
|
+
[
|
|
58
|
+
'dodo-ui-UtilityButton',
|
|
59
|
+
`size--${size}`,
|
|
60
|
+
'compact',
|
|
61
|
+
'color--primary',
|
|
62
|
+
'roundness--full',
|
|
63
|
+
error && 'error',
|
|
64
|
+
disabled && 'disabled',
|
|
65
|
+
].filter(Boolean),
|
|
66
|
+
);
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<InputEnclosure
|
|
70
|
+
{size}
|
|
71
|
+
{disabled}
|
|
72
|
+
{error}
|
|
73
|
+
class={classes.join(' ')}
|
|
74
|
+
focused={forcedFocused || isFocused}
|
|
75
|
+
{...restProps}
|
|
76
|
+
>
|
|
77
|
+
<DatePicker.Input
|
|
78
|
+
onfocus={handleFocus}
|
|
79
|
+
onblur={handleBlur}
|
|
80
|
+
{placeholder}
|
|
81
|
+
class="InputBox"
|
|
82
|
+
{...dateFieldInputProps}
|
|
83
|
+
>
|
|
84
|
+
{#snippet children({ segments })}
|
|
85
|
+
<Segments {segments} {dateFormat} />
|
|
86
|
+
{/snippet}
|
|
87
|
+
</DatePicker.Input>
|
|
88
|
+
|
|
89
|
+
{#snippet after()}
|
|
90
|
+
<DatePicker.Trigger class={triggerClasses.join(' ')} {...datePickerTriggerProps}>
|
|
91
|
+
<Icon icon="material-symbols:calendar-month-sharp" />
|
|
92
|
+
</DatePicker.Trigger>
|
|
93
|
+
{@render after?.()}
|
|
94
|
+
{/snippet}
|
|
95
|
+
</InputEnclosure>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DatePicker } from 'bits-ui';
|
|
3
|
+
import { formatSegments, type DatePickerFormat, type DateSegment } from './utils.js';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
segments: DateSegment[];
|
|
7
|
+
dateFormat: DatePickerFormat;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let { segments, dateFormat }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#each formatSegments(segments, dateFormat) as { part, value }, i (part + i)}
|
|
14
|
+
<DatePicker.Segment {part}>
|
|
15
|
+
{value}
|
|
16
|
+
</DatePicker.Segment>
|
|
17
|
+
{/each}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { SegmentPart } from 'bits-ui';
|
|
2
|
+
|
|
3
|
+
// ---- Segment Types ----
|
|
4
|
+
export type DateSegment = {
|
|
5
|
+
part: SegmentPart;
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// ---- Supported format tokens ----
|
|
10
|
+
export type FormatToken = 'dd' | 'mm' | 'yyyy' | 'hh' | 'min' | 'ss';
|
|
11
|
+
|
|
12
|
+
// ---- Optional: stricter format typing ----
|
|
13
|
+
type Separator = '/' | '-' | '.' | ' ';
|
|
14
|
+
|
|
15
|
+
export type DatePickerFormat =
|
|
16
|
+
| `${FormatToken}${Separator}${FormatToken}${Separator}${FormatToken}`
|
|
17
|
+
| `${FormatToken}${Separator}${FormatToken}`
|
|
18
|
+
| `${FormatToken}`;
|
|
19
|
+
|
|
20
|
+
// ---- Formatter ----
|
|
21
|
+
export function formatSegments(segments: DateSegment[], format: DatePickerFormat): DateSegment[] {
|
|
22
|
+
const segmentMap: Partial<Record<SegmentPart, DateSegment>> = Object.fromEntries(
|
|
23
|
+
segments.map((s) => [s.part, s]),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const tokens = format.match(/dd|mm|yyyy|hh|min|ss|./g) ?? [];
|
|
27
|
+
|
|
28
|
+
return tokens.map((token): DateSegment => {
|
|
29
|
+
switch (token) {
|
|
30
|
+
case 'dd':
|
|
31
|
+
return segmentMap.day ?? { part: 'day', value: '' };
|
|
32
|
+
|
|
33
|
+
case 'mm':
|
|
34
|
+
return segmentMap.month ?? { part: 'month', value: '' };
|
|
35
|
+
|
|
36
|
+
case 'yyyy':
|
|
37
|
+
return segmentMap.year ?? { part: 'year', value: '' };
|
|
38
|
+
|
|
39
|
+
case 'hh':
|
|
40
|
+
return segmentMap.hour ?? { part: 'hour', value: '' };
|
|
41
|
+
|
|
42
|
+
case 'min':
|
|
43
|
+
return segmentMap.minute ?? { part: 'minute', value: '' };
|
|
44
|
+
|
|
45
|
+
case 'ss':
|
|
46
|
+
return segmentMap.second ?? { part: 'second', value: '' };
|
|
47
|
+
|
|
48
|
+
default:
|
|
49
|
+
return {
|
|
50
|
+
part: 'literal',
|
|
51
|
+
value: token,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DatePicker, type CalendarRootSnippetProps } from 'bits-ui';
|
|
3
|
+
|
|
4
|
+
let { months, weekdays }: CalendarRootSnippetProps = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="CalendarGrid">
|
|
8
|
+
{#each months as month (month.value)}
|
|
9
|
+
<DatePicker.Grid>
|
|
10
|
+
<DatePicker.GridHead>
|
|
11
|
+
<DatePicker.GridRow>
|
|
12
|
+
{#each weekdays as day (day)}
|
|
13
|
+
<DatePicker.HeadCell>
|
|
14
|
+
<div>{day.slice(0, 2)}</div>
|
|
15
|
+
</DatePicker.HeadCell>
|
|
16
|
+
{/each}
|
|
17
|
+
</DatePicker.GridRow>
|
|
18
|
+
</DatePicker.GridHead>
|
|
19
|
+
<DatePicker.GridBody>
|
|
20
|
+
{#each month.weeks as weekDates (weekDates)}
|
|
21
|
+
<DatePicker.GridRow>
|
|
22
|
+
{#each weekDates as date (date)}
|
|
23
|
+
<DatePicker.Cell {date} month={month.value}>
|
|
24
|
+
<DatePicker.Day>
|
|
25
|
+
<div></div>
|
|
26
|
+
{date.day}
|
|
27
|
+
</DatePicker.Day>
|
|
28
|
+
</DatePicker.Cell>
|
|
29
|
+
{/each}
|
|
30
|
+
</DatePicker.GridRow>
|
|
31
|
+
{/each}
|
|
32
|
+
</DatePicker.GridBody>
|
|
33
|
+
</DatePicker.Grid>
|
|
34
|
+
{/each}
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type DatePickerPopupProps = DatePickerContentProps & Omit<CardProps, 'children' | 'ref'>;
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { DatePicker, type DatePickerContentProps } from 'bits-ui';
|
|
7
|
+
import Header from './Header.svelte';
|
|
8
|
+
import CalendarGrid from './CalendarGrid.svelte';
|
|
9
|
+
import { type CardProps, useThemeContext } from '@flightlesslabs/dodo-ui';
|
|
10
|
+
let {
|
|
11
|
+
roundness = 1,
|
|
12
|
+
outline = false,
|
|
13
|
+
class: className = '',
|
|
14
|
+
theme: cardTheme,
|
|
15
|
+
color = 'default',
|
|
16
|
+
variant = 'text',
|
|
17
|
+
shadow = 2,
|
|
18
|
+
active = false,
|
|
19
|
+
sideOffset = 10,
|
|
20
|
+
align = 'end',
|
|
21
|
+
...restProps
|
|
22
|
+
}: DatePickerPopupProps = $props();
|
|
23
|
+
|
|
24
|
+
const themeContext = useThemeContext();
|
|
25
|
+
const theme = $derived(cardTheme ? cardTheme : themeContext.theme);
|
|
26
|
+
|
|
27
|
+
const popupClasses = $derived(
|
|
28
|
+
[
|
|
29
|
+
'dodo-ui-Card',
|
|
30
|
+
'dodo-ui-Calendar',
|
|
31
|
+
`color--${color}`,
|
|
32
|
+
`variant--${variant}`,
|
|
33
|
+
`roundness--${roundness}`,
|
|
34
|
+
`dodo-shadow-${shadow}`,
|
|
35
|
+
outline && 'outline',
|
|
36
|
+
active && 'active',
|
|
37
|
+
theme ? `dodo-theme--${theme}` : '',
|
|
38
|
+
className,
|
|
39
|
+
].filter(Boolean),
|
|
40
|
+
);
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<DatePicker.Content class={popupClasses.join(' ')} {...restProps} {sideOffset} {align}>
|
|
44
|
+
<DatePicker.Calendar>
|
|
45
|
+
{#snippet children(calendarRootSnippetProps)}
|
|
46
|
+
<Header />
|
|
47
|
+
<CalendarGrid {...calendarRootSnippetProps} />
|
|
48
|
+
{/snippet}
|
|
49
|
+
</DatePicker.Calendar>
|
|
50
|
+
</DatePicker.Content>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '@iconify/svelte';
|
|
3
|
+
import { DatePicker } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
const triggerClasses = $derived(
|
|
6
|
+
[
|
|
7
|
+
'dodo-ui-Button',
|
|
8
|
+
'compact',
|
|
9
|
+
'size--normal',
|
|
10
|
+
'variant--text',
|
|
11
|
+
'color--primary',
|
|
12
|
+
'roundness--1',
|
|
13
|
+
].filter(Boolean),
|
|
14
|
+
);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<DatePicker.Header>
|
|
18
|
+
<DatePicker.PrevButton class={triggerClasses.join(' ')}>
|
|
19
|
+
<Icon icon="material-symbols:chevron-left-rounded" />
|
|
20
|
+
</DatePicker.PrevButton>
|
|
21
|
+
<DatePicker.Heading />
|
|
22
|
+
<DatePicker.NextButton class={triggerClasses.join(' ')}>
|
|
23
|
+
<Icon icon="material-symbols:chevron-right-rounded" />
|
|
24
|
+
</DatePicker.NextButton>
|
|
25
|
+
</DatePicker.Header>
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DatePicker component and related prop types.
|
|
3
|
+
*/
|
|
4
|
+
export {
|
|
5
|
+
default as DatePicker,
|
|
6
|
+
type DatePickerProps,
|
|
7
|
+
} from './components/DatePicker/DatePicker.svelte';
|
|
8
|
+
|
|
9
|
+
export { type DatePickerInputProps } from './components/DatePicker/DatePickerInput/DatePickerInput.svelte';
|
|
10
|
+
|
|
11
|
+
export { type DatePickerPopupProps } from './components/DatePicker/DatePickerPopup/DatePickerPopup.svelte';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Calendar component and related prop types.
|
|
15
|
+
*/
|
|
16
|
+
export { default as Calendar, type CalendarProps } from './components/Calendar/Calendar.svelte';
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
type ControlType =
|
|
2
|
+
| 'object'
|
|
3
|
+
| 'boolean'
|
|
4
|
+
| 'check'
|
|
5
|
+
| 'inline-check'
|
|
6
|
+
| 'radio'
|
|
7
|
+
| 'inline-radio'
|
|
8
|
+
| 'select'
|
|
9
|
+
| 'multi-select'
|
|
10
|
+
| 'number'
|
|
11
|
+
| 'range'
|
|
12
|
+
| 'file'
|
|
13
|
+
| 'color'
|
|
14
|
+
| 'date'
|
|
15
|
+
| 'text';
|
|
16
|
+
|
|
17
|
+
interface ControlBase {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controltype */
|
|
21
|
+
type?: ControlType;
|
|
22
|
+
disable?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type Control =
|
|
26
|
+
| ControlType
|
|
27
|
+
| false
|
|
28
|
+
| (ControlBase &
|
|
29
|
+
(
|
|
30
|
+
| ControlBase
|
|
31
|
+
| {
|
|
32
|
+
type: 'color';
|
|
33
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controlpresetcolors */
|
|
34
|
+
presetColors?: string[];
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
type: 'file';
|
|
38
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controlaccept */
|
|
39
|
+
accept?: string;
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
type: 'inline-check' | 'radio' | 'inline-radio' | 'select' | 'multi-select';
|
|
43
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controllabels */
|
|
44
|
+
labels?: {
|
|
45
|
+
[options: string]: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
type: 'number' | 'range';
|
|
50
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controlmax */
|
|
51
|
+
max?: number;
|
|
52
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controlmin */
|
|
53
|
+
min?: number;
|
|
54
|
+
/** @see https://storybook.js.org/docs/api/arg-types#controlstep */
|
|
55
|
+
step?: number;
|
|
56
|
+
}
|
|
57
|
+
));
|
|
58
|
+
|
|
59
|
+
type ConditionalTest =
|
|
60
|
+
| {
|
|
61
|
+
truthy?: boolean;
|
|
62
|
+
}
|
|
63
|
+
| {
|
|
64
|
+
exists: boolean;
|
|
65
|
+
}
|
|
66
|
+
| {
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
eq: any;
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
neq: any;
|
|
73
|
+
};
|
|
74
|
+
type ConditionalValue =
|
|
75
|
+
| {
|
|
76
|
+
arg: string;
|
|
77
|
+
}
|
|
78
|
+
| {
|
|
79
|
+
global: string;
|
|
80
|
+
};
|
|
81
|
+
type Conditional = ConditionalValue & ConditionalTest;
|
|
82
|
+
|
|
83
|
+
interface Args {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
[name: string]: any;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface SBBaseType {
|
|
89
|
+
required?: boolean;
|
|
90
|
+
raw?: string;
|
|
91
|
+
}
|
|
92
|
+
type SBScalarType = SBBaseType & {
|
|
93
|
+
name: 'boolean' | 'string' | 'number' | 'function' | 'symbol';
|
|
94
|
+
};
|
|
95
|
+
type SBArrayType = SBBaseType & {
|
|
96
|
+
name: 'array';
|
|
97
|
+
value: SBType;
|
|
98
|
+
};
|
|
99
|
+
type SBObjectType = SBBaseType & {
|
|
100
|
+
name: 'object';
|
|
101
|
+
value: Record<string, SBType>;
|
|
102
|
+
};
|
|
103
|
+
type SBEnumType = SBBaseType & {
|
|
104
|
+
name: 'enum';
|
|
105
|
+
value: (string | number)[];
|
|
106
|
+
};
|
|
107
|
+
type SBIntersectionType = SBBaseType & {
|
|
108
|
+
name: 'intersection';
|
|
109
|
+
value: SBType[];
|
|
110
|
+
};
|
|
111
|
+
type SBUnionType = SBBaseType & {
|
|
112
|
+
name: 'union';
|
|
113
|
+
value: SBType[];
|
|
114
|
+
};
|
|
115
|
+
type SBOtherType = SBBaseType & {
|
|
116
|
+
name: 'other';
|
|
117
|
+
value: string;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
type SBType =
|
|
121
|
+
| SBScalarType
|
|
122
|
+
| SBEnumType
|
|
123
|
+
| SBArrayType
|
|
124
|
+
| SBObjectType
|
|
125
|
+
| SBIntersectionType
|
|
126
|
+
| SBUnionType
|
|
127
|
+
| SBOtherType;
|
|
128
|
+
|
|
129
|
+
interface InputType {
|
|
130
|
+
/** @see https://storybook.js.org/docs/api/arg-types#control */
|
|
131
|
+
control?: Control;
|
|
132
|
+
/** @see https://storybook.js.org/docs/api/arg-types#description */
|
|
133
|
+
description?: string;
|
|
134
|
+
/** @see https://storybook.js.org/docs/api/arg-types#if */
|
|
135
|
+
if?: Conditional;
|
|
136
|
+
/** @see https://storybook.js.org/docs/api/arg-types#mapping */
|
|
137
|
+
mapping?: {
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
139
|
+
[key: string]: any;
|
|
140
|
+
};
|
|
141
|
+
/** @see https://storybook.js.org/docs/api/arg-types#name */
|
|
142
|
+
name?: string;
|
|
143
|
+
/** @see https://storybook.js.org/docs/api/arg-types#options */
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
145
|
+
options?: readonly any[];
|
|
146
|
+
/** @see https://storybook.js.org/docs/api/arg-types#table */
|
|
147
|
+
table?: {
|
|
148
|
+
[key: string]: unknown;
|
|
149
|
+
/** @see https://storybook.js.org/docs/api/arg-types#tablecategory */
|
|
150
|
+
category?: string;
|
|
151
|
+
/** @see https://storybook.js.org/docs/api/arg-types#tabledefaultvalue */
|
|
152
|
+
defaultValue?: {
|
|
153
|
+
summary?: string;
|
|
154
|
+
detail?: string;
|
|
155
|
+
};
|
|
156
|
+
/** @see https://storybook.js.org/docs/api/arg-types#tabledisable */
|
|
157
|
+
disable?: boolean;
|
|
158
|
+
/** @see https://storybook.js.org/docs/api/arg-types#tablesubcategory */
|
|
159
|
+
subcategory?: string;
|
|
160
|
+
/** @see https://storybook.js.org/docs/api/arg-types#tabletype */
|
|
161
|
+
type?: {
|
|
162
|
+
summary?: string;
|
|
163
|
+
detail?: string;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
/** @see https://storybook.js.org/docs/api/arg-types#type */
|
|
167
|
+
type?: SBType | SBScalarType['name'];
|
|
168
|
+
/**
|
|
169
|
+
* @deprecated Use `table.defaultValue.summary` instead.
|
|
170
|
+
* @see https://storybook.js.org/docs/api/arg-types#defaultvalue
|
|
171
|
+
*/
|
|
172
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
173
|
+
defaultValue?: any;
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
[key: string]: any;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export type ArgTypes<TArgs = Args> = {
|
|
179
|
+
[name in keyof TArgs]: InputType;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export type StoryBookArgTypes = Partial<ArgTypes<Args>>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
@use 'sass:map';
|
|
2
|
+
|
|
3
|
+
$breakpoints-default: (
|
|
4
|
+
sm: 40rem,
|
|
5
|
+
md: 48rem,
|
|
6
|
+
lg: 64rem,
|
|
7
|
+
xl: 80rem,
|
|
8
|
+
xxl: 96rem,
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
$breakpoints: () !default;
|
|
12
|
+
|
|
13
|
+
$breakpoints: map.merge($breakpoints-default, $breakpoints);
|
|
14
|
+
|
|
15
|
+
@function breakpoint($key) {
|
|
16
|
+
@if not map.has-key($breakpoints, $key) {
|
|
17
|
+
@error "Invalid breakpoint: #{$key}";
|
|
18
|
+
}
|
|
19
|
+
@return map.get($breakpoints, $key);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@mixin up($key) {
|
|
23
|
+
@media (min-width: breakpoint($key)) {
|
|
24
|
+
@content;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@mixin down($key) {
|
|
29
|
+
@media (max-width: breakpoint($key)) {
|
|
30
|
+
@content;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@mixin between($min, $max) {
|
|
35
|
+
@media (min-width: breakpoint($min)) and (max-width: breakpoint($max)) {
|
|
36
|
+
@content;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
// mock matchMedia globally
|
|
5
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
6
|
+
writable: true,
|
|
7
|
+
value: vi.fn().mockImplementation((query: string) => ({
|
|
8
|
+
matches: false,
|
|
9
|
+
media: query,
|
|
10
|
+
addEventListener: vi.fn(),
|
|
11
|
+
removeEventListener: vi.fn(),
|
|
12
|
+
})),
|
|
13
|
+
});
|