@reshape-biotech/design-system 1.1.2 → 1.2.1
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/dist/components/graphs/bar-chart/BarChart.stories.svelte +38 -0
- package/dist/components/graphs/bar-chart/BarChart.svelte +14 -1
- package/dist/components/graphs/bar-chart/BarChart.svelte.d.ts +1 -0
- package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte +32 -0
- package/dist/components/graphs/bar-chart/StackedBarChart.svelte +16 -3
- package/dist/components/graphs/bar-chart/StackedBarChart.svelte.d.ts +3 -2
- package/dist/components/graphs/line/LineChart.stories.svelte +20 -0
- package/dist/components/graphs/line/LineChart.svelte +14 -20
- package/dist/components/graphs/line/LineChart.svelte.d.ts +1 -0
- package/dist/components/graphs/multiline/MultiLineChart.svelte +0 -20
- package/dist/components/icons/index.d.ts +1 -1
- package/dist/components/icons/index.js +2 -0
- package/dist/components/notifications/Notifications.stories.svelte +107 -0
- package/dist/components/notifications/Notifications.stories.svelte.d.ts +19 -0
- package/dist/components/notifications/Notifications.svelte +32 -0
- package/dist/components/notifications/Notifications.svelte.d.ts +18 -0
- package/dist/components/notifications/index.d.ts +1 -0
- package/dist/components/notifications/index.js +1 -0
- package/dist/components/select-new/index.d.ts +1 -1
- package/dist/components/toast/Toast.stories.svelte +209 -0
- package/dist/components/toast/Toast.stories.svelte.d.ts +19 -0
- package/dist/components/toast/Toast.svelte +62 -0
- package/dist/components/toast/Toast.svelte.d.ts +7 -0
- package/dist/components/toast/index.d.ts +1 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/notifications.d.ts +22 -0
- package/dist/notifications.js +27 -0
- package/package.json +2 -1
|
@@ -79,3 +79,41 @@
|
|
|
79
79
|
name="Empty Data"
|
|
80
80
|
args={{ data: [], xAxisName: 'category', yAxisName: 'Value', height: '400px' }}
|
|
81
81
|
/>
|
|
82
|
+
|
|
83
|
+
<Story
|
|
84
|
+
name="With Capture Interval"
|
|
85
|
+
args={{
|
|
86
|
+
data: [
|
|
87
|
+
{ category: '0', value: 10 },
|
|
88
|
+
{ category: '1', value: 20 },
|
|
89
|
+
{ category: '2', value: 15 },
|
|
90
|
+
{ category: '3', value: 25 },
|
|
91
|
+
{ category: '4', value: 30 },
|
|
92
|
+
{ category: '5', value: 18 },
|
|
93
|
+
{ category: '6', value: 22 }
|
|
94
|
+
],
|
|
95
|
+
xAxisName: 'category',
|
|
96
|
+
yAxisName: 'Value',
|
|
97
|
+
height: '400px',
|
|
98
|
+
captureInterval: 3600
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
<Story
|
|
103
|
+
name="With Capture Interval - Short Duration"
|
|
104
|
+
args={{
|
|
105
|
+
data: [
|
|
106
|
+
{ category: '0', value: 10 },
|
|
107
|
+
{ category: '1', value: 20 },
|
|
108
|
+
{ category: '2', value: 15 },
|
|
109
|
+
{ category: '3', value: 25 },
|
|
110
|
+
{ category: '4', value: 30 },
|
|
111
|
+
{ category: '5', value: 18 },
|
|
112
|
+
{ category: '6', value: 22 }
|
|
113
|
+
],
|
|
114
|
+
xAxisName: 'category',
|
|
115
|
+
yAxisName: 'Value',
|
|
116
|
+
height: '400px',
|
|
117
|
+
captureInterval: 600
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import Chart, { type GenericChartProps } from '../chart/Chart.svelte';
|
|
4
4
|
import type { EChartsOption, BarSeriesOption } from 'echarts';
|
|
5
5
|
import { createTooltipFormatter } from '../utils/tooltipFormatter';
|
|
6
|
+
import { Duration } from 'luxon';
|
|
6
7
|
|
|
7
8
|
type DataItem = {
|
|
8
9
|
value: number;
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
colors?: Record<string, string>; // Optional: Color mapping per x-axis category
|
|
15
16
|
rotateXAxisLabels?: boolean;
|
|
16
17
|
grid?: EChartsOption['grid'];
|
|
18
|
+
captureInterval?: number;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
let {
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
rotateXAxisLabels = false,
|
|
23
25
|
xAxisName,
|
|
24
26
|
yAxisName,
|
|
27
|
+
captureInterval,
|
|
25
28
|
...props
|
|
26
29
|
}: BarChartProps = $props();
|
|
27
30
|
|
|
@@ -38,6 +41,16 @@
|
|
|
38
41
|
|
|
39
42
|
const xAxisData = $derived(data.map((item) => item[xAxisName]));
|
|
40
43
|
|
|
44
|
+
const captureIntervals = captureInterval
|
|
45
|
+
? Array(data.length)
|
|
46
|
+
.fill(null)
|
|
47
|
+
.map((_, timeIndex) => {
|
|
48
|
+
const seconds = timeIndex * captureInterval;
|
|
49
|
+
const duration = Duration.fromObject({ seconds }).shiftTo('days', 'hours', 'minutes');
|
|
50
|
+
return duration.days >= 1 ? duration.toFormat('dd:hh:mm') : duration.toFormat('hh:mm');
|
|
51
|
+
})
|
|
52
|
+
: undefined;
|
|
53
|
+
|
|
41
54
|
const createBarDataItem = (value: number | null, color: string) => ({
|
|
42
55
|
value,
|
|
43
56
|
itemStyle: {
|
|
@@ -94,7 +107,7 @@
|
|
|
94
107
|
},
|
|
95
108
|
xAxis: {
|
|
96
109
|
type: 'category',
|
|
97
|
-
data: xAxisData,
|
|
110
|
+
data: captureIntervals || xAxisData,
|
|
98
111
|
axisTick: {
|
|
99
112
|
show: false,
|
|
100
113
|
alignWithLabel: true
|
|
@@ -9,6 +9,7 @@ interface BarChartProps extends Omit<GenericChartProps, 'timeIndex'> {
|
|
|
9
9
|
colors?: Record<string, string>;
|
|
10
10
|
rotateXAxisLabels?: boolean;
|
|
11
11
|
grid?: EChartsOption['grid'];
|
|
12
|
+
captureInterval?: number;
|
|
12
13
|
}
|
|
13
14
|
declare const BarChart: import("svelte").Component<BarChartProps, {}, "">;
|
|
14
15
|
type BarChart = ReturnType<typeof BarChart>;
|
|
@@ -40,3 +40,35 @@
|
|
|
40
40
|
yAxisName: 'Count'
|
|
41
41
|
}}
|
|
42
42
|
/>
|
|
43
|
+
|
|
44
|
+
<Story
|
|
45
|
+
name="With Capture Interval"
|
|
46
|
+
args={{
|
|
47
|
+
xAxisCategories: ['0', '1', '2', '3', '4', '5', '6'],
|
|
48
|
+
series: [
|
|
49
|
+
{ name: 'Halo', data: [120, 132, 101, 134, 90, 230, 210] },
|
|
50
|
+
{ name: 'Spot', data: [220, 182, 191, 234, 290, 330, 310] },
|
|
51
|
+
{ name: 'Microbial', data: [150, 232, 201, 154, 190, 330, 410] }
|
|
52
|
+
],
|
|
53
|
+
height: '400px',
|
|
54
|
+
xAxisName: 'Time',
|
|
55
|
+
yAxisName: 'Count',
|
|
56
|
+
captureInterval: 3600
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<Story
|
|
61
|
+
name="With Capture Interval - Short Duration"
|
|
62
|
+
args={{
|
|
63
|
+
xAxisCategories: ['0', '1', '2', '3', '4', '5', '6'],
|
|
64
|
+
series: [
|
|
65
|
+
{ name: 'Halo', data: [120, 132, 101, 134, 90, 230, 210] },
|
|
66
|
+
{ name: 'Spot', data: [220, 182, 191, 234, 290, 330, 310] },
|
|
67
|
+
{ name: 'Microbial', data: [150, 232, 201, 154, 190, 330, 410] }
|
|
68
|
+
],
|
|
69
|
+
height: '400px',
|
|
70
|
+
xAxisName: 'Time',
|
|
71
|
+
yAxisName: 'Count',
|
|
72
|
+
captureInterval: 600
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
@@ -3,25 +3,28 @@
|
|
|
3
3
|
import Chart, { type GenericChartProps } from '../chart/Chart.svelte';
|
|
4
4
|
import type { EChartsOption, BarSeriesOption } from 'echarts';
|
|
5
5
|
import type { CallbackDataParams } from 'echarts/types/dist/shared';
|
|
6
|
+
import { Duration } from 'luxon';
|
|
6
7
|
|
|
7
8
|
type StackedSeriesItem = {
|
|
8
9
|
name: string;
|
|
9
10
|
data: (number | null)[];
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
interface StackedBarChartProps extends GenericChartProps {
|
|
13
14
|
xAxisCategories: (string | number)[];
|
|
14
15
|
series: StackedSeriesItem[];
|
|
15
16
|
colors?: Record<string, string>; // Optional: Color mapping per series name
|
|
16
17
|
rotateXAxisLabels?: boolean;
|
|
17
18
|
grid?: EChartsOption['grid'];
|
|
18
|
-
|
|
19
|
+
captureInterval?: number;
|
|
20
|
+
}
|
|
19
21
|
|
|
20
22
|
let {
|
|
21
23
|
xAxisCategories,
|
|
22
24
|
series,
|
|
23
25
|
colors,
|
|
24
26
|
rotateXAxisLabels = false,
|
|
27
|
+
captureInterval,
|
|
25
28
|
...props
|
|
26
29
|
}: StackedBarChartProps = $props();
|
|
27
30
|
|
|
@@ -38,6 +41,16 @@
|
|
|
38
41
|
|
|
39
42
|
const xAxisData = $derived(xAxisCategories);
|
|
40
43
|
|
|
44
|
+
const captureIntervals = captureInterval
|
|
45
|
+
? Array(xAxisCategories.length)
|
|
46
|
+
.fill(null)
|
|
47
|
+
.map((_, timeIndex) => {
|
|
48
|
+
const seconds = timeIndex * captureInterval;
|
|
49
|
+
const duration = Duration.fromObject({ seconds }).shiftTo('days', 'hours', 'minutes');
|
|
50
|
+
return duration.days >= 1 ? duration.toFormat('dd:hh:mm') : duration.toFormat('hh:mm');
|
|
51
|
+
})
|
|
52
|
+
: undefined;
|
|
53
|
+
|
|
41
54
|
const createBarDataItem = (value: number | null, color: string) => ({
|
|
42
55
|
value,
|
|
43
56
|
itemStyle: {
|
|
@@ -135,7 +148,7 @@
|
|
|
135
148
|
},
|
|
136
149
|
xAxis: {
|
|
137
150
|
type: 'category',
|
|
138
|
-
data: xAxisData,
|
|
151
|
+
data: captureIntervals || xAxisData,
|
|
139
152
|
axisTick: {
|
|
140
153
|
show: false,
|
|
141
154
|
alignWithLabel: true
|
|
@@ -4,13 +4,14 @@ type StackedSeriesItem = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
data: (number | null)[];
|
|
6
6
|
};
|
|
7
|
-
|
|
7
|
+
interface StackedBarChartProps extends GenericChartProps {
|
|
8
8
|
xAxisCategories: (string | number)[];
|
|
9
9
|
series: StackedSeriesItem[];
|
|
10
10
|
colors?: Record<string, string>;
|
|
11
11
|
rotateXAxisLabels?: boolean;
|
|
12
12
|
grid?: EChartsOption['grid'];
|
|
13
|
-
|
|
13
|
+
captureInterval?: number;
|
|
14
|
+
}
|
|
14
15
|
declare const StackedBarChart: import("svelte").Component<StackedBarChartProps, {}, "">;
|
|
15
16
|
type StackedBarChart = ReturnType<typeof StackedBarChart>;
|
|
16
17
|
export default StackedBarChart;
|
|
@@ -109,6 +109,26 @@
|
|
|
109
109
|
<LineChart {xAxisName} yAxisName="Value" data={[10, 8, 13, 7, 9, 6, 11]} timeIndex={3} />
|
|
110
110
|
</div>
|
|
111
111
|
</Story>
|
|
112
|
+
<Story name="With Capture Interval" asChild>
|
|
113
|
+
<div class="h-[400px] w-full">
|
|
114
|
+
<LineChart
|
|
115
|
+
{xAxisName}
|
|
116
|
+
yAxisName="Value"
|
|
117
|
+
data={[10, 8, 13, 7, 9, 6, 11, 15, 12, 8, 14, 16]}
|
|
118
|
+
captureInterval={3600}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
</Story>
|
|
122
|
+
<Story name="With Capture Interval - Short Duration" asChild>
|
|
123
|
+
<div class="h-[400px] w-full">
|
|
124
|
+
<LineChart
|
|
125
|
+
{xAxisName}
|
|
126
|
+
yAxisName="Value"
|
|
127
|
+
data={[10, 8, 13, 7, 9, 6, 11, 15, 12, 8, 14, 16]}
|
|
128
|
+
captureInterval={600}
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
</Story>
|
|
112
132
|
<Story
|
|
113
133
|
name="Interactive Current Location"
|
|
114
134
|
asChild
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
import * as echarts from 'echarts/core';
|
|
6
6
|
import type { GenericChartProps } from '../chart/Chart.svelte';
|
|
7
7
|
import { createTooltipFormatter } from '../utils/tooltipFormatter';
|
|
8
|
+
import { Duration } from 'luxon';
|
|
8
9
|
|
|
9
10
|
interface LineChartProps extends GenericChartProps {
|
|
10
11
|
data: (number | null)[];
|
|
11
12
|
withArea?: boolean;
|
|
12
13
|
color?: string;
|
|
13
14
|
grid?: EChartsOption['grid'];
|
|
15
|
+
captureInterval?: number;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
let {
|
|
@@ -19,6 +21,7 @@
|
|
|
19
21
|
yAxisName,
|
|
20
22
|
withArea = false,
|
|
21
23
|
color = textColor['icon-blue'],
|
|
24
|
+
captureInterval,
|
|
22
25
|
...props
|
|
23
26
|
}: LineChartProps = $props();
|
|
24
27
|
|
|
@@ -37,6 +40,16 @@
|
|
|
37
40
|
maximumFractionDigits: fractionDigits
|
|
38
41
|
}) ?? '';
|
|
39
42
|
|
|
43
|
+
const captureIntervals = captureInterval
|
|
44
|
+
? Array(data.length)
|
|
45
|
+
.fill(null)
|
|
46
|
+
.map((_, timeIndex) => {
|
|
47
|
+
const seconds = timeIndex * captureInterval;
|
|
48
|
+
const duration = Duration.fromObject({ seconds }).shiftTo('days', 'hours', 'minutes');
|
|
49
|
+
return duration.days >= 1 ? duration.toFormat('dd:hh:mm') : duration.toFormat('hh:mm');
|
|
50
|
+
})
|
|
51
|
+
: undefined;
|
|
52
|
+
|
|
40
53
|
let options: EChartsOption = $derived({
|
|
41
54
|
grid: {
|
|
42
55
|
top: 10,
|
|
@@ -55,26 +68,7 @@
|
|
|
55
68
|
axisLine: {
|
|
56
69
|
onZero: false
|
|
57
70
|
},
|
|
58
|
-
|
|
59
|
-
interval: (index: number, value: string) => {
|
|
60
|
-
const dataLength = data.length;
|
|
61
|
-
if (dataLength <= 1) return true; // Show label if only one point
|
|
62
|
-
|
|
63
|
-
const targetLabelCount = 10; // Aim for about 10 labels
|
|
64
|
-
// Calculate interval, ensuring it's at least 1
|
|
65
|
-
const calculatedInterval = Math.max(1, Math.ceil(dataLength / targetLabelCount));
|
|
66
|
-
|
|
67
|
-
// Show the first label (index 0)
|
|
68
|
-
if (index === 0) return true;
|
|
69
|
-
// Show the last label if data exists
|
|
70
|
-
if (dataLength > 0 && index === dataLength - 1) return true;
|
|
71
|
-
// Show labels at the calculated interval, but not the last one if it was already shown
|
|
72
|
-
if (index % calculatedInterval === 0 && index !== dataLength - 1) return true;
|
|
73
|
-
// Hide others
|
|
74
|
-
return false;
|
|
75
|
-
},
|
|
76
|
-
hideOverlap: true
|
|
77
|
-
},
|
|
71
|
+
data: captureIntervals,
|
|
78
72
|
...props.xAxisOptions
|
|
79
73
|
} as any as EChartsOption['xAxis'],
|
|
80
74
|
yAxis: {
|
|
@@ -5,6 +5,7 @@ interface LineChartProps extends GenericChartProps {
|
|
|
5
5
|
withArea?: boolean;
|
|
6
6
|
color?: string;
|
|
7
7
|
grid?: EChartsOption['grid'];
|
|
8
|
+
captureInterval?: number;
|
|
8
9
|
}
|
|
9
10
|
declare const LineChart: import("svelte").Component<LineChartProps, {}, "">;
|
|
10
11
|
type LineChart = ReturnType<typeof LineChart>;
|
|
@@ -116,26 +116,6 @@
|
|
|
116
116
|
onZero: false
|
|
117
117
|
},
|
|
118
118
|
data: captureIntervals,
|
|
119
|
-
axisLabel: {
|
|
120
|
-
interval: (index: number, value: string) => {
|
|
121
|
-
const dataLength = longestSeries;
|
|
122
|
-
if (dataLength <= 1) return true; // Show label if only one point
|
|
123
|
-
|
|
124
|
-
const targetLabelCount = 10; // Aim for about 10 labels
|
|
125
|
-
// Calculate interval, ensuring it's at least 1
|
|
126
|
-
const calculatedInterval = Math.max(1, Math.ceil(dataLength / targetLabelCount));
|
|
127
|
-
|
|
128
|
-
// Show the first label (index 0)
|
|
129
|
-
if (index === 0) return true;
|
|
130
|
-
// Show the last label if data exists
|
|
131
|
-
if (dataLength > 0 && index === dataLength - 1) return true;
|
|
132
|
-
// Show labels at the calculated interval, but not the last one if it was already shown
|
|
133
|
-
if (index % calculatedInterval === 0 && index !== dataLength - 1) return true;
|
|
134
|
-
// Hide others
|
|
135
|
-
return false;
|
|
136
|
-
},
|
|
137
|
-
hideOverlap: true
|
|
138
|
-
},
|
|
139
119
|
...props.xAxisOptions
|
|
140
120
|
},
|
|
141
121
|
yAxis: {
|
|
@@ -2,7 +2,7 @@ import type { IconComponentProps } from 'phosphor-svelte';
|
|
|
2
2
|
import type { Component } from 'svelte';
|
|
3
3
|
import type { textColor } from './../../tokens';
|
|
4
4
|
export type PhosphorIconProps = Component<IconComponentProps, object, ''>;
|
|
5
|
-
export type IconName = 'Aperture' | 'ArrowFatLineRight' | 'ArrowCounterClockwise' | 'ArrowRight' | 'ArrowUpRight' | 'ArrowUpLeft' | 'ArrowUUpLeft' | 'Barcode' | 'Bell' | 'BookOpen' | 'BookOpenText' | 'BowlingBall' | 'BugBeetle' | 'Calendar' | 'CalendarBlank' | 'Camera' | 'CameraSlash' | 'CaretDown' | 'CaretLeft' | 'CaretRight' | 'CaretUp' | 'CaretUpDown' | 'ChatTeardropDots' | 'Check' | 'CheckCircle' | 'CheckFat' | 'Circle' | 'CircleDashed' | 'CircleHalf' | 'CirclesFour' | 'CirclesThreePlus' | 'Clock' | 'ClockCountdown' | 'Copy' | 'Crop' | 'Cube' | 'Database' | 'Dna' | 'DotsThree' | 'DotsThreeOutlineVertical' | 'DownloadSimple' | 'Drop' | 'EnvelopeSimple' | 'Eye' | 'Eyedropper' | 'FileCsv' | 'Flag' | 'Flask' | 'Folder' | 'FolderDashed' | 'FolderSimplePlus' | 'FunnelSimple' | 'Gear' | 'GlobeSimple' | 'GlobeSimpleX' | 'GridFour' | 'Hash' | 'House' | 'ImageSquare' | 'ImagesSquare' | 'Info' | 'Lock' | 'LineSegments' | 'List' | 'Link' | 'ListMagnifyingGlass' | 'MagnifyingGlass' | 'MegaphoneSimple' | 'MicrosoftExcelLogo' | 'Moon' | 'Minus' | 'Palette' | 'Pause' | 'Pencil' | 'PencilSimple' | 'Percent' | 'Phone' | 'Plant' | 'Play' | 'Plus' | 'PlusMinus' | 'Question' | 'SealCheck' | 'RadioButton' | 'SealQuestion' | 'SealWarning' | 'SelectionAll' | 'Share' | 'SidebarSimple' | 'SkipBack' | 'SkipForward' | 'SignIn' | 'SignOut' | 'SortAscending' | 'Sparkle' | 'SpinnerGap' | 'SquaresFour' | 'Star' | 'Stop' | 'StopCircle' | 'Sun' | 'Table' | 'Tag' | 'Target' | 'TestTube' | 'Trash' | 'TrashSimple' | 'TreeStructure' | 'UserCircle' | 'UserPlus' | 'Video' | 'Warning' | 'WarningCircle' | 'WifiSlash' | 'X';
|
|
5
|
+
export type IconName = 'Aperture' | 'ArrowFatLineRight' | 'ArrowCounterClockwise' | 'ArrowRight' | 'ArrowUpRight' | 'ArrowUpLeft' | 'ArrowUUpLeft' | 'Barcode' | 'Bell' | 'BookOpen' | 'BookOpenText' | 'BowlingBall' | 'BugBeetle' | 'Calendar' | 'CalendarBlank' | 'Camera' | 'CameraSlash' | 'CaretDown' | 'CaretLeft' | 'CaretRight' | 'CaretUp' | 'CaretUpDown' | 'ChatTeardropDots' | 'Check' | 'CheckCircle' | 'CheckFat' | 'Circle' | 'CircleDashed' | 'CircleHalf' | 'CirclesFour' | 'CirclesThreePlus' | 'Clock' | 'ClockCountdown' | 'Copy' | 'Crop' | 'Cube' | 'Database' | 'Dna' | 'DotsThree' | 'DotsThreeOutlineVertical' | 'DownloadSimple' | 'Drop' | 'EnvelopeSimple' | 'Eye' | 'Eyedropper' | 'FileCsv' | 'Flag' | 'Flask' | 'Folder' | 'FolderDashed' | 'FolderSimplePlus' | 'FunnelSimple' | 'Gear' | 'GlobeSimple' | 'GlobeSimpleX' | 'GridFour' | 'Hash' | 'House' | 'ImageSquare' | 'ImagesSquare' | 'Info' | 'Lock' | 'LineSegments' | 'List' | 'Link' | 'ListMagnifyingGlass' | 'MagnifyingGlass' | 'MegaphoneSimple' | 'MicrosoftExcelLogo' | 'Moon' | 'Minus' | 'Palette' | 'Pause' | 'Pencil' | 'PencilSimple' | 'Percent' | 'Phone' | 'Plant' | 'Play' | 'Plus' | 'PlusMinus' | 'Ruler' | 'Question' | 'SealCheck' | 'RadioButton' | 'SealQuestion' | 'SealWarning' | 'SelectionAll' | 'Share' | 'SidebarSimple' | 'SkipBack' | 'SkipForward' | 'SignIn' | 'SignOut' | 'SortAscending' | 'Sparkle' | 'SpinnerGap' | 'SquaresFour' | 'Star' | 'Stop' | 'StopCircle' | 'Sun' | 'Table' | 'Tag' | 'Target' | 'TestTube' | 'Trash' | 'TrashSimple' | 'TreeStructure' | 'UserCircle' | 'UserPlus' | 'Video' | 'Warning' | 'WarningCircle' | 'WifiSlash' | 'X';
|
|
6
6
|
export declare const iconMap: Record<IconName, PhosphorIconProps>;
|
|
7
7
|
export declare function renderIcon(iconName: keyof typeof iconMap): PhosphorIconProps;
|
|
8
8
|
export type IconColor = keyof typeof textColor;
|
|
@@ -79,6 +79,7 @@ import Plant from 'phosphor-svelte/lib/Plant';
|
|
|
79
79
|
import Play from 'phosphor-svelte/lib/Play';
|
|
80
80
|
import Plus from 'phosphor-svelte/lib/Plus';
|
|
81
81
|
import PlusMinus from 'phosphor-svelte/lib/PlusMinus';
|
|
82
|
+
import Ruler from 'phosphor-svelte/lib/Ruler';
|
|
82
83
|
import Question from 'phosphor-svelte/lib/Question';
|
|
83
84
|
import SealCheck from 'phosphor-svelte/lib/SealCheck';
|
|
84
85
|
import RadioButton from 'phosphor-svelte/lib/RadioButton';
|
|
@@ -196,6 +197,7 @@ export const iconMap = {
|
|
|
196
197
|
Plus,
|
|
197
198
|
PlusMinus,
|
|
198
199
|
RadioButton,
|
|
200
|
+
Ruler,
|
|
199
201
|
Question,
|
|
200
202
|
SealCheck,
|
|
201
203
|
SealQuestion,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { notifications } from '../../../notifications';
|
|
3
|
+
import Button from '../button/Button.svelte';
|
|
4
|
+
import Notifications from '../notifications/Notifications.svelte';
|
|
5
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
6
|
+
|
|
7
|
+
const { Story } = defineMeta({
|
|
8
|
+
component: Notifications,
|
|
9
|
+
title: 'Design System/Notifications',
|
|
10
|
+
tags: ['autodocs']
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Story name="Notifications" asChild>
|
|
15
|
+
<Notifications></Notifications>
|
|
16
|
+
<div class="h-24 rounded-md border"></div>
|
|
17
|
+
<div class="pt-4">
|
|
18
|
+
<div class="flex flex-row justify-between gap-2">
|
|
19
|
+
<div class="flex flex-col gap-2">
|
|
20
|
+
<h5>Default</h5>
|
|
21
|
+
<Button
|
|
22
|
+
onClick={() => {
|
|
23
|
+
notifications.default('This is a default notification');
|
|
24
|
+
}}>Show default</Button
|
|
25
|
+
>
|
|
26
|
+
<Button
|
|
27
|
+
onClick={() => {
|
|
28
|
+
notifications.danger('This is a danger notification');
|
|
29
|
+
}}>Show danger</Button
|
|
30
|
+
>
|
|
31
|
+
<Button
|
|
32
|
+
onClick={() => {
|
|
33
|
+
notifications.warning('This is a warning notification');
|
|
34
|
+
}}>Show warning</Button
|
|
35
|
+
>
|
|
36
|
+
<Button
|
|
37
|
+
onClick={() => {
|
|
38
|
+
notifications.info('This is an info notification');
|
|
39
|
+
}}>Show info</Button
|
|
40
|
+
>
|
|
41
|
+
<Button
|
|
42
|
+
onClick={() => {
|
|
43
|
+
notifications.success('This is a success notification');
|
|
44
|
+
}}>Show success</Button
|
|
45
|
+
>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="grow"></div>
|
|
48
|
+
<div class="flex flex-col gap-2">
|
|
49
|
+
<h5>Icons</h5>
|
|
50
|
+
<Button
|
|
51
|
+
onClick={() => {
|
|
52
|
+
notifications.default('This is a default icon notification', 'Bell');
|
|
53
|
+
}}>Show default</Button
|
|
54
|
+
>
|
|
55
|
+
<Button
|
|
56
|
+
onClick={() => {
|
|
57
|
+
notifications.danger('This is a danger icon notification', 'SealWarning');
|
|
58
|
+
}}>Show danger</Button
|
|
59
|
+
>
|
|
60
|
+
<Button
|
|
61
|
+
onClick={() => {
|
|
62
|
+
notifications.warning('This is a warning icon notification', 'Warning');
|
|
63
|
+
}}>Show warning</Button
|
|
64
|
+
>
|
|
65
|
+
<Button
|
|
66
|
+
onClick={() => {
|
|
67
|
+
notifications.info('This is an info icon notification', 'Info');
|
|
68
|
+
}}>Show info</Button
|
|
69
|
+
>
|
|
70
|
+
<Button
|
|
71
|
+
onClick={() => {
|
|
72
|
+
notifications.success('This is a success icon notification', 'Check');
|
|
73
|
+
}}>Show success</Button
|
|
74
|
+
>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="grow"></div>
|
|
77
|
+
<div class="flex flex-col gap-2">
|
|
78
|
+
<h5>Dismissable</h5>
|
|
79
|
+
<Button
|
|
80
|
+
onClick={() => {
|
|
81
|
+
notifications.default('This is a default icon notification', 'Bell', true);
|
|
82
|
+
}}>Show default</Button
|
|
83
|
+
>
|
|
84
|
+
<Button
|
|
85
|
+
onClick={() => {
|
|
86
|
+
notifications.danger('This is a danger icon notification', 'SealWarning', true);
|
|
87
|
+
}}>Show danger</Button
|
|
88
|
+
>
|
|
89
|
+
<Button
|
|
90
|
+
onClick={() => {
|
|
91
|
+
notifications.warning('This is a warning icon notification', 'Warning', true);
|
|
92
|
+
}}>Show warning</Button
|
|
93
|
+
>
|
|
94
|
+
<Button
|
|
95
|
+
onClick={() => {
|
|
96
|
+
notifications.info('This is an info icon notification', 'Info', true);
|
|
97
|
+
}}>Show info</Button
|
|
98
|
+
>
|
|
99
|
+
<Button
|
|
100
|
+
onClick={() => {
|
|
101
|
+
notifications.success('This is a success icon notification', 'Check', true);
|
|
102
|
+
}}>Show success</Button
|
|
103
|
+
>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</Story>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Notifications from '../notifications/Notifications.svelte';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const Notifications: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {}, {}, string>;
|
|
18
|
+
type Notifications = InstanceType<typeof Notifications>;
|
|
19
|
+
export default Notifications;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { flip } from 'svelte/animate';
|
|
3
|
+
import { fly } from 'svelte/transition';
|
|
4
|
+
import { notifications } from '../../notifications';
|
|
5
|
+
import { type IconColor } from '../icons';
|
|
6
|
+
import { tokens } from '../../tokens';
|
|
7
|
+
import Toast from '../toast/Toast.svelte';
|
|
8
|
+
|
|
9
|
+
const color = {
|
|
10
|
+
danger: tokens.backgroundColor['danger-inverse'],
|
|
11
|
+
success: tokens.backgroundColor['success-inverse-hover'],
|
|
12
|
+
warning: tokens.backgroundColor['warning-inverse-hover'],
|
|
13
|
+
info: tokens.backgroundColor['blue-inverse'],
|
|
14
|
+
default: tokens.backgroundColor.surface
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const textColor: Record<string, IconColor | 'inherit'> = {
|
|
18
|
+
danger: 'primary-inverse',
|
|
19
|
+
success: 'primary-inverse',
|
|
20
|
+
warning: 'primary-inverse',
|
|
21
|
+
info: 'primary-inverse',
|
|
22
|
+
default: 'inherit'
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div class="fixed left-0 right-0 top-2 z-50 mx-auto flex w-fit flex-col items-center justify-start">
|
|
27
|
+
{#each $notifications as notification (notification.id)}
|
|
28
|
+
<div animate:flip transition:fly={{ y: -10 }}>
|
|
29
|
+
<Toast {notification} />
|
|
30
|
+
</div>
|
|
31
|
+
{/each}
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const Notifications: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type Notifications = InstanceType<typeof Notifications>;
|
|
18
|
+
export default Notifications;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Notifications } from './Notifications.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Notifications } from './Notifications.svelte';
|
|
@@ -4,7 +4,7 @@ import GroupHeading from './components/SelectGroupHeading.svelte';
|
|
|
4
4
|
import Trigger from './components/SelectTrigger.svelte';
|
|
5
5
|
import MultiSelectTrigger from './components/MultiSelectTrigger.svelte';
|
|
6
6
|
import Group from './components/Group.svelte';
|
|
7
|
-
export declare const Root: import("svelte").Component<import("bits-ui").
|
|
7
|
+
export declare const Root: import("svelte").Component<import("bits-ui").SelectRootPropsWithoutHTML, {}, "open" | "value">;
|
|
8
8
|
export declare const Portal: import("svelte").Component<import("bits-ui").PortalProps, {}, "">;
|
|
9
9
|
export { Content, Item, Group, GroupHeading, Trigger, MultiSelectTrigger };
|
|
10
10
|
export * from './types';
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Notification } from '../../../notifications';
|
|
3
|
+
import Toast from './Toast.svelte';
|
|
4
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
component: Toast,
|
|
8
|
+
title: 'Design System/Toast',
|
|
9
|
+
tags: ['autodocs']
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const defaultNotification: Notification = {
|
|
13
|
+
id: '1',
|
|
14
|
+
type: 'default',
|
|
15
|
+
message: 'This is a default notification',
|
|
16
|
+
dismissable: false
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const dangerNotification: Notification = {
|
|
20
|
+
id: '2',
|
|
21
|
+
type: 'danger',
|
|
22
|
+
message: 'This is a danger notification',
|
|
23
|
+
dismissable: false
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const warningNotification: Notification = {
|
|
27
|
+
id: '3',
|
|
28
|
+
type: 'warning',
|
|
29
|
+
message: 'This is a warning notification',
|
|
30
|
+
dismissable: false
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const infoNotification: Notification = {
|
|
34
|
+
id: '4',
|
|
35
|
+
type: 'info',
|
|
36
|
+
message: 'This is an info notification',
|
|
37
|
+
dismissable: false
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const successNotification: Notification = {
|
|
41
|
+
id: '5',
|
|
42
|
+
type: 'success',
|
|
43
|
+
message: 'This is a success notification',
|
|
44
|
+
dismissable: false
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const defaultIconNotification: Notification = {
|
|
48
|
+
id: '6',
|
|
49
|
+
type: 'default',
|
|
50
|
+
message: 'This is a default notification with icon',
|
|
51
|
+
icon: 'Bell',
|
|
52
|
+
dismissable: false
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const dangerIconNotification: Notification = {
|
|
56
|
+
id: '7',
|
|
57
|
+
type: 'danger',
|
|
58
|
+
message: 'This is a danger notification with icon',
|
|
59
|
+
icon: 'SealWarning',
|
|
60
|
+
dismissable: false
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const warningIconNotification: Notification = {
|
|
64
|
+
id: '8',
|
|
65
|
+
type: 'warning',
|
|
66
|
+
message: 'This is a warning notification with icon',
|
|
67
|
+
icon: 'Warning',
|
|
68
|
+
dismissable: false
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const infoIconNotification: Notification = {
|
|
72
|
+
id: '9',
|
|
73
|
+
type: 'info',
|
|
74
|
+
message: 'This is an info notification with icon',
|
|
75
|
+
icon: 'Info',
|
|
76
|
+
dismissable: false
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const successIconNotification: Notification = {
|
|
80
|
+
id: '10',
|
|
81
|
+
type: 'success',
|
|
82
|
+
message: 'This is a success notification with icon',
|
|
83
|
+
icon: 'Check',
|
|
84
|
+
dismissable: false
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const defaultDismissableNotificationWithIcon: Notification = {
|
|
88
|
+
id: '11',
|
|
89
|
+
type: 'default',
|
|
90
|
+
message: 'This is a dismissable default notification with icon',
|
|
91
|
+
icon: 'Bell',
|
|
92
|
+
dismissable: true
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const dangerDismissableNotificationWithIcon: Notification = {
|
|
96
|
+
id: '12',
|
|
97
|
+
type: 'danger',
|
|
98
|
+
message: 'This is a dismissable danger notification with icon',
|
|
99
|
+
icon: 'SealWarning',
|
|
100
|
+
dismissable: true
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const warningDismissableNotificationWithIcon: Notification = {
|
|
104
|
+
id: '13',
|
|
105
|
+
type: 'warning',
|
|
106
|
+
message: 'This is a dismissable warning notification with icon',
|
|
107
|
+
icon: 'Warning',
|
|
108
|
+
dismissable: true
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const infoDismissableNotificationWithIcon: Notification = {
|
|
112
|
+
id: '14',
|
|
113
|
+
type: 'info',
|
|
114
|
+
message: 'This is a dismissable info notification with icon',
|
|
115
|
+
icon: 'Info',
|
|
116
|
+
dismissable: true
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const successDismissableNotificationWithIcon: Notification = {
|
|
120
|
+
id: '15',
|
|
121
|
+
type: 'success',
|
|
122
|
+
message: 'This is a dismissable success notification with icon',
|
|
123
|
+
icon: 'Check',
|
|
124
|
+
dismissable: true
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const defaultDismissableNoIconNotification: Notification = {
|
|
128
|
+
id: '16',
|
|
129
|
+
type: 'default',
|
|
130
|
+
message: 'This is a dismissable default notification without icon',
|
|
131
|
+
dismissable: true
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const dangerDismissableNoIconNotification: Notification = {
|
|
135
|
+
id: '17',
|
|
136
|
+
type: 'danger',
|
|
137
|
+
message: 'This is a dismissable danger notification without icon',
|
|
138
|
+
dismissable: true
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const warningDismissableNoIconNotification: Notification = {
|
|
142
|
+
id: '18',
|
|
143
|
+
type: 'warning',
|
|
144
|
+
message: 'This is a dismissable warning notification without icon',
|
|
145
|
+
dismissable: true
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const infoDismissableNoIconNotification: Notification = {
|
|
149
|
+
id: '19',
|
|
150
|
+
type: 'info',
|
|
151
|
+
message: 'This is a dismissable info notification without icon',
|
|
152
|
+
dismissable: true
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const successDismissableNoIconNotification: Notification = {
|
|
156
|
+
id: '20',
|
|
157
|
+
type: 'success',
|
|
158
|
+
message: 'This is a dismissable success notification without icon',
|
|
159
|
+
dismissable: true
|
|
160
|
+
};
|
|
161
|
+
</script>
|
|
162
|
+
|
|
163
|
+
<Story name="Notifications" asChild>
|
|
164
|
+
<div class="space-y-8">
|
|
165
|
+
<div class="space-y-4">
|
|
166
|
+
<h5 class="text-lg font-semibold">Basic Notifications</h5>
|
|
167
|
+
<div class="space-y-2">
|
|
168
|
+
<Toast notification={defaultNotification} />
|
|
169
|
+
<Toast notification={dangerNotification} />
|
|
170
|
+
<Toast notification={warningNotification} />
|
|
171
|
+
<Toast notification={infoNotification} />
|
|
172
|
+
<Toast notification={successNotification} />
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<div class="space-y-4">
|
|
177
|
+
<h5 class="text-lg font-semibold">Notifications with Icons</h5>
|
|
178
|
+
<div class="space-y-2">
|
|
179
|
+
<Toast notification={defaultIconNotification} />
|
|
180
|
+
<Toast notification={dangerIconNotification} />
|
|
181
|
+
<Toast notification={warningIconNotification} />
|
|
182
|
+
<Toast notification={infoIconNotification} />
|
|
183
|
+
<Toast notification={successIconNotification} />
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<div class="space-y-4">
|
|
188
|
+
<h5 class="text-lg font-semibold">Dismissable Notifications</h5>
|
|
189
|
+
<div class="space-y-2">
|
|
190
|
+
<Toast notification={defaultDismissableNoIconNotification} />
|
|
191
|
+
<Toast notification={dangerDismissableNoIconNotification} />
|
|
192
|
+
<Toast notification={warningDismissableNoIconNotification} />
|
|
193
|
+
<Toast notification={infoDismissableNoIconNotification} />
|
|
194
|
+
<Toast notification={successDismissableNoIconNotification} />
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<div class="space-y-4">
|
|
199
|
+
<h5 class="text-lg font-semibold">Dismissable Notifications with Icons</h5>
|
|
200
|
+
<div class="space-y-2">
|
|
201
|
+
<Toast notification={defaultDismissableNotificationWithIcon} />
|
|
202
|
+
<Toast notification={dangerDismissableNotificationWithIcon} />
|
|
203
|
+
<Toast notification={warningDismissableNotificationWithIcon} />
|
|
204
|
+
<Toast notification={infoDismissableNotificationWithIcon} />
|
|
205
|
+
<Toast notification={successDismissableNotificationWithIcon} />
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</Story>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Toast from './Toast.svelte';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const Toast: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {}, {}, string>;
|
|
18
|
+
type Toast = InstanceType<typeof Toast>;
|
|
19
|
+
export default Toast;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type Notification, notifications } from '../../notifications';
|
|
3
|
+
import Icon from '../icons/Icon.svelte';
|
|
4
|
+
import { type IconColor } from '../icons';
|
|
5
|
+
import { tokens } from '../../tokens';
|
|
6
|
+
import IconButton from '../icon-button/IconButton.svelte';
|
|
7
|
+
|
|
8
|
+
let { notification }: { notification: Notification } = $props();
|
|
9
|
+
|
|
10
|
+
const color = {
|
|
11
|
+
danger: tokens.backgroundColor['danger-inverse'],
|
|
12
|
+
success: tokens.backgroundColor['success-inverse-hover'],
|
|
13
|
+
warning: tokens.backgroundColor['warning-inverse-hover'],
|
|
14
|
+
info: tokens.backgroundColor['blue-inverse'],
|
|
15
|
+
default: tokens.backgroundColor.surface
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const textColor: Record<string, IconColor | 'inherit'> = {
|
|
19
|
+
danger: 'primary-inverse',
|
|
20
|
+
success: 'primary-inverse',
|
|
21
|
+
warning: 'primary-inverse',
|
|
22
|
+
info: 'primary-inverse',
|
|
23
|
+
default: 'inherit'
|
|
24
|
+
};
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
class="my-1 flex min-h-10 min-w-80 flex-row items-center rounded-lg px-2 shadow-md"
|
|
29
|
+
style="background: {color[notification.type]}"
|
|
30
|
+
class:border={notification.type === 'default'}
|
|
31
|
+
class:border-base-200={notification.type === 'default'}
|
|
32
|
+
>
|
|
33
|
+
{#if notification.icon}
|
|
34
|
+
<Icon
|
|
35
|
+
color={textColor[notification.type]}
|
|
36
|
+
size={'14'}
|
|
37
|
+
iconName={notification.icon}
|
|
38
|
+
class="flex h-6 w-6 items-center justify-center rounded-md {notification.type !== 'default'
|
|
39
|
+
? 'bg-neutral-inverse-hover'
|
|
40
|
+
: 'bg-neutral'} p-1 {textColor[notification.type]}"
|
|
41
|
+
/>
|
|
42
|
+
{/if}
|
|
43
|
+
<div
|
|
44
|
+
class="p-2 font-medium"
|
|
45
|
+
style="display:block"
|
|
46
|
+
class:text-base-white-default={notification.type !== 'default'}
|
|
47
|
+
>
|
|
48
|
+
{notification.message}
|
|
49
|
+
</div>
|
|
50
|
+
{#if notification.dismissable}
|
|
51
|
+
<div class="grow"></div>
|
|
52
|
+
<div class="py-2">
|
|
53
|
+
<IconButton rounded={false} size="xs" onclick={() => notifications.dismiss(notification.id)}>
|
|
54
|
+
<Icon
|
|
55
|
+
color={textColor[notification.type]}
|
|
56
|
+
iconName={'X'}
|
|
57
|
+
class="rounded-md {textColor[notification.type]}"
|
|
58
|
+
/>
|
|
59
|
+
</IconButton>
|
|
60
|
+
</div>
|
|
61
|
+
{/if}
|
|
62
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Toast } from './Toast.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Toast } from './Toast.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './components/markdown/';
|
|
|
22
22
|
export * from './components/modal/';
|
|
23
23
|
export * from './components/manual-cfu-counter/';
|
|
24
24
|
export * from './components/notification-popup/';
|
|
25
|
+
export * from './components/notifications/';
|
|
25
26
|
export * from './components/pill/';
|
|
26
27
|
export * from './components/progress-circle/';
|
|
27
28
|
export * from './components/required-status-indicator/';
|
|
@@ -37,6 +38,7 @@ export * from './components/stepper/';
|
|
|
37
38
|
export * from './components/table/';
|
|
38
39
|
export * from './components/tabs/';
|
|
39
40
|
export * from './components/tag/';
|
|
41
|
+
export * from './components/toast/';
|
|
40
42
|
export * from './components/toggle-icon-button/';
|
|
41
43
|
export * from './components/textarea/index';
|
|
42
44
|
export * from './components/tooltip/';
|
|
@@ -44,4 +46,5 @@ export * from './components/toggle/';
|
|
|
44
46
|
export * from './components/checkbox/';
|
|
45
47
|
export * from './components/sjsf-wrappers/';
|
|
46
48
|
export { tokens } from './tokens';
|
|
49
|
+
export { notifications } from './notifications';
|
|
47
50
|
import './app.css';
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export * from './components/markdown/';
|
|
|
23
23
|
export * from './components/modal/';
|
|
24
24
|
export * from './components/manual-cfu-counter/';
|
|
25
25
|
export * from './components/notification-popup/';
|
|
26
|
+
export * from './components/notifications/';
|
|
26
27
|
export * from './components/pill/';
|
|
27
28
|
export * from './components/progress-circle/';
|
|
28
29
|
export * from './components/required-status-indicator/';
|
|
@@ -38,6 +39,7 @@ export * from './components/stepper/';
|
|
|
38
39
|
export * from './components/table/';
|
|
39
40
|
export * from './components/tabs/';
|
|
40
41
|
export * from './components/tag/';
|
|
42
|
+
export * from './components/toast/';
|
|
41
43
|
export * from './components/toggle-icon-button/';
|
|
42
44
|
export * from './components/textarea/index';
|
|
43
45
|
export * from './components/tooltip/';
|
|
@@ -46,4 +48,5 @@ export * from './components/checkbox/';
|
|
|
46
48
|
export * from './components/sjsf-wrappers/';
|
|
47
49
|
// Styles and Tokens
|
|
48
50
|
export { tokens } from './tokens';
|
|
51
|
+
export { notifications } from './notifications';
|
|
49
52
|
import './app.css';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IconName } from './';
|
|
2
|
+
export type NotificationType = 'info' | 'success' | 'warning' | 'danger' | 'default';
|
|
3
|
+
export interface Notification {
|
|
4
|
+
id: string;
|
|
5
|
+
type: NotificationType;
|
|
6
|
+
message: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
icon?: IconName;
|
|
9
|
+
dismissable: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const notifications: {
|
|
12
|
+
subscribe: {
|
|
13
|
+
(this: void, run: import("svelte/store").Subscriber<Notification[]>, invalidate?: (() => void) | undefined): import("svelte/store").Unsubscriber;
|
|
14
|
+
(this: void, run: import("svelte/store").Subscriber<Notification[]>, invalidate?: (() => void) | undefined): import("svelte/store").Unsubscriber;
|
|
15
|
+
};
|
|
16
|
+
dismiss: (id: string) => void;
|
|
17
|
+
default: (message: string, icon?: IconName, dismissable?: boolean, timeout?: number) => void;
|
|
18
|
+
danger: (message: string, icon?: IconName, dismissable?: boolean, timeout?: number) => void;
|
|
19
|
+
warning: (message: string, icon?: IconName, dismissable?: boolean, timeout?: number) => void;
|
|
20
|
+
info: (message: string, icon?: IconName, dismissable?: boolean, timeout?: number) => void;
|
|
21
|
+
success: (message: string, icon?: IconName, dismissable?: boolean, timeout?: number) => void;
|
|
22
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
const TIMEOUT = 3000;
|
|
3
|
+
const createNotificationStore = () => {
|
|
4
|
+
const { subscribe, update } = writable([]);
|
|
5
|
+
const send = (message, type = 'default', iconName, dismissable = false, timeout = 3000) => {
|
|
6
|
+
const notification = { id: id(), type, message, timeout, icon: iconName, dismissable };
|
|
7
|
+
update((state) => [...state, notification]);
|
|
8
|
+
setTimeout(() => {
|
|
9
|
+
update((state) => state.filter((n) => n.id !== notification.id));
|
|
10
|
+
}, timeout);
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
subscribe,
|
|
14
|
+
dismiss: (id) => {
|
|
15
|
+
update((state) => state.filter((n) => n.id !== id));
|
|
16
|
+
},
|
|
17
|
+
default: (message, icon, dismissable = false, timeout = TIMEOUT) => send(message, 'default', icon, dismissable, timeout),
|
|
18
|
+
danger: (message, icon, dismissable = false, timeout = TIMEOUT) => send(message, 'danger', icon, dismissable, timeout),
|
|
19
|
+
warning: (message, icon, dismissable = false, timeout = TIMEOUT) => send(message, 'warning', icon, dismissable, timeout),
|
|
20
|
+
info: (message, icon, dismissable = false, timeout = TIMEOUT) => send(message, 'info', icon, dismissable, timeout),
|
|
21
|
+
success: (message, icon, dismissable = false, timeout = TIMEOUT) => send(message, 'success', icon, dismissable, timeout)
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
const id = () => {
|
|
25
|
+
return crypto.randomUUID();
|
|
26
|
+
};
|
|
27
|
+
export const notifications = createNotificationStore();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reshape-biotech/design-system",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"default": "./dist/index.js"
|
|
29
29
|
},
|
|
30
30
|
"./tokens": "./dist/tokens.js",
|
|
31
|
+
"./notifications": "./dist/notifications.js",
|
|
31
32
|
"./styles": "./dist/app.css",
|
|
32
33
|
"./tailwind": "./dist/tailwind.preset.js",
|
|
33
34
|
"./tailwind-safelist": "./dist/tailwind-safelist.js"
|