@reshape-biotech/design-system 1.2.5 → 1.2.7
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 +3 -1
- package/dist/app.css +97 -97
- package/dist/components/activity/Activity.stories.svelte +104 -104
- package/dist/components/activity/Activity.svelte +112 -112
- package/dist/components/avatar/Avatar.stories.svelte +23 -23
- package/dist/components/avatar/Avatar.svelte +54 -54
- package/dist/components/banner/Banner.stories.svelte +105 -105
- package/dist/components/banner/Banner.svelte +42 -42
- package/dist/components/button/Button.stories.svelte +61 -61
- package/dist/components/button/Button.svelte +95 -95
- package/dist/components/card/Card.stories.svelte +112 -112
- package/dist/components/card/Card.svelte +18 -18
- package/dist/components/checkbox/Checkbox.stories.svelte +8 -8
- package/dist/components/checkbox/Checkbox.svelte +17 -17
- package/dist/components/collapsible/Collapsible.stories.svelte +26 -26
- package/dist/components/collapsible/components/collapsible-content.svelte +20 -20
- package/dist/components/collapsible/components/collapsible-trigger.svelte +12 -12
- package/dist/components/combobox/Combobox.stories.svelte +412 -412
- package/dist/components/combobox/components/combobox-add.svelte +8 -8
- package/dist/components/combobox/components/combobox-content.svelte +39 -39
- package/dist/components/combobox/components/combobox-indicator.svelte +1 -1
- package/dist/components/datepicker/DatePicker.stories.svelte +196 -196
- package/dist/components/datepicker/DatePicker.svelte +173 -173
- package/dist/components/divider/Divider.stories.svelte +7 -7
- package/dist/components/divider/Divider.svelte +9 -9
- package/dist/components/drawer/Drawer.stories.svelte +51 -51
- package/dist/components/drawer/Drawer.svelte +33 -33
- package/dist/components/drawer/DrawerLabel.svelte +10 -10
- package/dist/components/dropdown/Dropdown.stories.svelte +210 -210
- package/dist/components/dropdown/Dropdown.svelte +57 -57
- package/dist/components/dropdown/components/DropdownContent.svelte +16 -16
- package/dist/components/dropdown/components/DropdownMenu.svelte +10 -10
- package/dist/components/dropdown/components/DropdownTrigger.svelte +37 -37
- package/dist/components/dropdown/components/OutlinedButton.svelte +9 -9
- package/dist/components/empty-content/EmptyContent.stories.svelte +38 -38
- package/dist/components/empty-content/EmptyContent.svelte +12 -12
- package/dist/components/graphs/bar-chart/BarChart.stories.svelte +91 -91
- package/dist/components/graphs/bar-chart/BarChart.svelte +147 -147
- package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte +57 -57
- package/dist/components/graphs/bar-chart/StackedBarChart.svelte +198 -199
- package/dist/components/graphs/chart/Chart.stories.svelte +96 -96
- package/dist/components/graphs/chart/Chart.svelte +207 -207
- package/dist/components/graphs/line/LineChart.stories.svelte +138 -138
- package/dist/components/graphs/line/LineChart.svelte +140 -142
- package/dist/components/graphs/matrix/Matrix.stories.svelte +117 -117
- package/dist/components/graphs/matrix/Matrix.svelte +141 -141
- package/dist/components/graphs/multiline/MultiLineChart.stories.svelte +168 -168
- package/dist/components/graphs/multiline/MultiLineChart.svelte +236 -236
- package/dist/components/graphs/scatterplot/Scatterplot.stories.svelte +84 -84
- package/dist/components/graphs/scatterplot/Scatterplot.svelte +302 -302
- package/dist/components/graphs/utils/duration.d.ts +1 -0
- package/dist/components/graphs/utils/duration.js +33 -0
- package/dist/components/graphs/utils/tooltipFormatter.js +1 -1
- package/dist/components/icon-button/IconButton.stories.svelte +64 -64
- package/dist/components/icon-button/IconButton.svelte +88 -88
- package/dist/components/icons/AnalysisIcon.stories.svelte +18 -18
- package/dist/components/icons/AnalysisIcon.svelte +96 -96
- package/dist/components/icons/Icon.stories.svelte +111 -111
- package/dist/components/icons/Icon.svelte +17 -17
- package/dist/components/icons/PrincipalIcon.svelte +59 -59
- package/dist/components/icons/custom/Halo.svelte +31 -31
- package/dist/components/icons/custom/Well.svelte +27 -27
- package/dist/components/icons/index.d.ts +3 -2
- package/dist/components/icons/index.js +3 -1
- package/dist/components/image/Image.svelte +42 -42
- package/dist/components/input/Input.stories.svelte +55 -55
- package/dist/components/input/Input.svelte +121 -121
- package/dist/components/label/Label.stories.svelte +18 -18
- package/dist/components/label/Label.svelte +11 -11
- package/dist/components/list/List.stories.svelte +84 -84
- package/dist/components/list/List.svelte +20 -20
- package/dist/components/logo/Logo.stories.svelte +15 -15
- package/dist/components/logo/Logo.svelte +30 -30
- package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte +102 -102
- package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte +557 -565
- package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte +11 -11
- package/dist/components/markdown/Markdown.stories.svelte +10 -10
- package/dist/components/markdown/Markdown.svelte +6 -6
- package/dist/components/modal/Modal.stories.svelte +29 -29
- package/dist/components/modal/Modal.svelte +71 -71
- package/dist/components/multi-cfu-counter/MultiCFUCounter.stories.svelte +215 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.stories.svelte.d.ts +3 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.svelte +662 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.svelte.d.ts +32 -0
- package/dist/components/multi-cfu-counter/index.d.ts +1 -0
- package/dist/components/multi-cfu-counter/index.js +1 -0
- package/dist/components/multi-cfu-counter/test/MultiCFUCounterTestWrapper.svelte +28 -0
- package/dist/components/multi-cfu-counter/test/MultiCFUCounterTestWrapper.svelte.d.ts +20 -0
- package/dist/components/notification-popup/NotificationPopup.stories.svelte +18 -18
- package/dist/components/notification-popup/NotificationPopup.svelte +26 -26
- package/dist/components/notifications/Notifications.stories.svelte +101 -101
- package/dist/components/notifications/Notifications.svelte +9 -9
- package/dist/components/pill/Pill.stories.svelte +8 -8
- package/dist/components/pill/Pill.svelte +27 -27
- package/dist/components/progress-circle/ProgressCircle.stories.svelte +8 -8
- package/dist/components/progress-circle/ProgressCircle.svelte +54 -54
- package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte +18 -18
- package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte +14 -14
- package/dist/components/segmented-control-buttons/ControlButton.svelte +36 -36
- package/dist/components/segmented-control-buttons/SegmentedControlButtons.stories.svelte +35 -35
- package/dist/components/segmented-control-buttons/SegmentedControlButtons.svelte +13 -13
- package/dist/components/select/Select.stories.svelte +77 -77
- package/dist/components/select/Select.svelte +114 -114
- package/dist/components/select-new/Select.stories.svelte +188 -188
- package/dist/components/select-new/components/Group.svelte +17 -17
- package/dist/components/select-new/components/MultiSelectTrigger.svelte +57 -57
- package/dist/components/select-new/components/SelectContent.svelte +22 -22
- package/dist/components/select-new/components/SelectGroupHeading.svelte +10 -10
- package/dist/components/select-new/components/SelectItem.svelte +25 -25
- package/dist/components/select-new/components/SelectTrigger.svelte +38 -38
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte +76 -76
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte +53 -53
- package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/sjsfCustomTheme.js +1 -1
- package/dist/components/skeleton-loader/SkeletonLoader.stories.svelte +32 -32
- package/dist/components/skeleton-loader/SkeletonLoader.svelte +10 -10
- package/dist/components/skeleton-loader/StatcardSkeleton.svelte +9 -9
- package/dist/components/skeleton-loader/components/Skeleton.svelte +7 -7
- package/dist/components/skeleton-loader/components/SkeletonImage.svelte +12 -12
- package/dist/components/slider/Slider.stories.svelte +23 -23
- package/dist/components/slider/Slider.svelte +107 -107
- package/dist/components/spinner/Spinner.stories.svelte +8 -8
- package/dist/components/spinner/Spinner.svelte +18 -18
- package/dist/components/stat-card/StatCard.stories.svelte +26 -26
- package/dist/components/stat-card/StatCard.svelte +128 -128
- package/dist/components/status-badge/StatusBadge.stories.svelte +365 -365
- package/dist/components/status-badge/StatusBadge.svelte +54 -54
- package/dist/components/stepper/Stepper.stories.svelte +219 -219
- package/dist/components/stepper/components/stepper-root.svelte +12 -12
- package/dist/components/stepper/components/stepper-step.svelte +83 -83
- package/dist/components/table/Table.stories.svelte +87 -87
- package/dist/components/table/Table.svelte +32 -32
- package/dist/components/table/components/TBody.svelte +7 -7
- package/dist/components/table/components/THead.svelte +7 -7
- package/dist/components/table/components/Td.svelte +8 -8
- package/dist/components/table/components/Th.svelte +8 -8
- package/dist/components/table/components/Tr.svelte +11 -11
- package/dist/components/tabs/Tabs.stories.svelte +20 -20
- package/dist/components/tabs/Tabs.svelte +8 -8
- package/dist/components/tabs/components/Content.svelte +8 -8
- package/dist/components/tabs/components/Tab.svelte +14 -14
- package/dist/components/tabs/components/Tabs.svelte +7 -7
- package/dist/components/tag/Tag.stories.svelte +57 -57
- package/dist/components/tag/Tag.svelte +95 -95
- package/dist/components/textarea/Textarea.stories.svelte +70 -70
- package/dist/components/textarea/Textarea.svelte +76 -76
- package/dist/components/toast/Toast.stories.svelte +204 -204
- package/dist/components/toast/Toast.svelte +53 -53
- package/dist/components/toggle/Toggle.stories.svelte +9 -9
- package/dist/components/toggle/Toggle.svelte +53 -53
- package/dist/components/toggle-icon-button/ToggleIconButton.stories.svelte +152 -152
- package/dist/components/toggle-icon-button/ToggleIconButton.svelte +99 -99
- package/dist/components/tooltip/Tooltip.stories.svelte +105 -105
- package/dist/components/tooltip/Tooltip.svelte +26 -26
- package/dist/fonts/index.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -1
- package/dist/notifications.d.ts +1 -4
- package/dist/notifications.js +1 -1
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +4 -0
- package/dist/tailwind-safelist.js +406 -398
- package/dist/tailwind.preset.d.ts +4 -0
- package/dist/tailwind.preset.js +10 -10
- package/dist/tokens/colors.d.ts +246 -0
- package/dist/tokens/colors.js +139 -0
- package/dist/tokens/index.d.ts +3 -0
- package/dist/tokens/index.js +5 -0
- package/dist/tokens/typography.d.ts +48 -0
- package/dist/tokens/typography.js +48 -0
- package/dist/tokens.d.ts +16 -252
- package/dist/tokens.js +33 -164
- package/dist/types/fonts.d.ts +2 -2
- package/package.json +398 -78
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<!-- src/lib/design-system/src/lib/components/manual-cfu-counter/ManualCFUCounterTestWrapper.svelte -->
|
|
2
2
|
<script lang="ts">
|
|
3
|
-
|
|
3
|
+
import ManualCFUCounter from '../ManualCFUCounter.svelte';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
interface Props {
|
|
6
|
+
initialTestMarks?: Array<{ x: number; y: number }>;
|
|
7
|
+
imageUrl?: string;
|
|
8
|
+
onclick?: (event: MouseEvent, marks: Array<{ x: number; y: number }>) => void;
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
let { initialTestMarks = [], imageUrl = 'test-image.jpg', onclick }: Props = $props();
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
let marks = $state([...initialTestMarks]);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export function getCurrentMarks() {
|
|
16
|
+
return marks;
|
|
17
|
+
}
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<ManualCFUCounter bind:marks {imageUrl} {onclick} />
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<script module>
|
|
2
|
-
|
|
2
|
+
import Markdown from './Markdown.svelte';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
component: Markdown,
|
|
8
|
+
title: 'Design System/Markdown',
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
});
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<Story name="Primary" asChild>
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
<Markdown
|
|
15
|
+
markdown={`# Welcome to My Markdown Story
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -37,5 +37,5 @@ greet('Storybook');
|
|
|
37
37
|
---
|
|
38
38
|
|
|
39
39
|
Happy storytelling with Markdown!`}
|
|
40
|
-
|
|
40
|
+
/>
|
|
41
41
|
</Story>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { marked } from 'marked';
|
|
3
|
+
interface Props {
|
|
4
|
+
markdown: string;
|
|
5
|
+
}
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
let { markdown }: Props = $props();
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<div class="prose text-sm text-secondary dark:prose-invert">
|
|
11
|
-
|
|
11
|
+
{@html marked.parse(markdown ?? '')}
|
|
12
12
|
</div>
|
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import Button from '../button/Button.svelte';
|
|
3
|
+
import Modal from '../modal/Modal.svelte';
|
|
4
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
component: Modal,
|
|
8
|
+
title: 'Design System/Modal',
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
});
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
let defaultOpen = $state(true);
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<Story name="Default" asChild>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
<Modal>
|
|
17
|
+
{#snippet Trigger({ openModal })}
|
|
18
|
+
<Button onClick={openModal}>Open Modal</Button>
|
|
19
|
+
{/snippet}
|
|
20
|
+
{#snippet Content()}
|
|
21
|
+
<div>
|
|
22
|
+
<p>Modal Content</p>
|
|
23
|
+
</div>
|
|
24
|
+
{/snippet}
|
|
25
|
+
</Modal>
|
|
26
26
|
</Story>
|
|
27
27
|
|
|
28
28
|
<Story name="Default open" asChild>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
<Modal {defaultOpen} onclose={() => (defaultOpen = false)}>
|
|
30
|
+
{#snippet Trigger({ openModal })}
|
|
31
|
+
<Button onClick={openModal}>Open Modal</Button>
|
|
32
|
+
{/snippet}
|
|
33
|
+
{#snippet Content()}
|
|
34
|
+
<div>
|
|
35
|
+
<p>Modal Content</p>
|
|
36
|
+
</div>
|
|
37
|
+
{/snippet}
|
|
38
|
+
</Modal>
|
|
39
39
|
</Story>
|
|
@@ -1,81 +1,81 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { type Snippet } from 'svelte';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
import IconButton from '../icon-button/IconButton.svelte';
|
|
5
|
+
import { Icon } from '../icons';
|
|
6
|
+
import Divider from '../divider/Divider.svelte';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
8
|
+
type ModalProps = {
|
|
9
|
+
Trigger?: Snippet<[{ openModal: () => void; closeModal: () => void }]>;
|
|
10
|
+
Header?: Snippet;
|
|
11
|
+
Content: Snippet;
|
|
12
|
+
Footer?: Snippet;
|
|
13
|
+
onclose?: () => void;
|
|
14
|
+
defaultOpen?: boolean;
|
|
15
|
+
id?: string;
|
|
16
|
+
withClose?: boolean;
|
|
17
|
+
closeOnClickOutside?: boolean;
|
|
18
|
+
class?: string;
|
|
19
|
+
contentClass?: string;
|
|
20
|
+
};
|
|
21
|
+
let {
|
|
22
|
+
Trigger,
|
|
23
|
+
Header,
|
|
24
|
+
Content,
|
|
25
|
+
Footer,
|
|
26
|
+
onclose,
|
|
27
|
+
defaultOpen = false,
|
|
28
|
+
id = 'modal-' + uuidv4(),
|
|
29
|
+
withClose = true,
|
|
30
|
+
closeOnClickOutside = true,
|
|
31
|
+
class: modalClass,
|
|
32
|
+
contentClass = 'p-4',
|
|
33
|
+
}: ModalProps = $props();
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
const modalOpen = $state(defaultOpen);
|
|
36
|
+
const openModal = () => {
|
|
37
|
+
const dialog = document.getElementById(id) as HTMLDialogElement | null;
|
|
38
|
+
dialog?.showModal();
|
|
39
|
+
};
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
const closeModal = () => {
|
|
42
|
+
const dialog = document.getElementById(id) as HTMLDialogElement | null;
|
|
43
|
+
dialog?.close();
|
|
44
|
+
onclose?.();
|
|
45
|
+
};
|
|
46
46
|
</script>
|
|
47
47
|
|
|
48
48
|
{#if Trigger}
|
|
49
|
-
|
|
49
|
+
{@render Trigger({ openModal, closeModal })}
|
|
50
50
|
{/if}
|
|
51
51
|
<dialog {id} class="modal w-full max-w-full" class:modal-open={modalOpen}>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
52
|
+
<div class="modal-box relative flex max-w-full flex-col rounded-xl bg-surface p-0 {modalClass}">
|
|
53
|
+
{#if Header}
|
|
54
|
+
<div class="flex h-12 items-center px-4">
|
|
55
|
+
{@render Header()}
|
|
56
|
+
</div>
|
|
57
|
+
<Divider />
|
|
58
|
+
{/if}
|
|
59
|
+
{#if withClose}
|
|
60
|
+
<div class="absolute right-0 top-0 z-10 p-2">
|
|
61
|
+
<IconButton onclick={closeModal} size="md" variant="transparent" rounded={false}>
|
|
62
|
+
<Icon iconName="X" />
|
|
63
|
+
</IconButton>
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
66
|
+
<div class="flex-1 {contentClass}">
|
|
67
|
+
{@render Content()}
|
|
68
|
+
</div>
|
|
69
|
+
{#if Footer}
|
|
70
|
+
<Divider />
|
|
71
|
+
<div class="px-4 py-2">
|
|
72
|
+
{@render Footer()}
|
|
73
|
+
</div>
|
|
74
|
+
{/if}
|
|
75
|
+
</div>
|
|
76
|
+
{#if closeOnClickOutside}
|
|
77
|
+
<form method="dialog" class="modal-backdrop">
|
|
78
|
+
<button onclick={closeModal}>close</button>
|
|
79
|
+
</form>
|
|
80
|
+
{/if}
|
|
81
81
|
</dialog>
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import MultiCFUCounter from './MultiCFUCounter.svelte';
|
|
4
|
+
const { Story } = defineMeta({
|
|
5
|
+
component: MultiCFUCounter,
|
|
6
|
+
title: 'Design System/MultiCFUCounter',
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
args: {
|
|
9
|
+
imageUrl: '/imgs/ris.jpg',
|
|
10
|
+
marks: [],
|
|
11
|
+
disabled: false,
|
|
12
|
+
hideMarkers: false,
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
imageUrl: {
|
|
16
|
+
control: 'text',
|
|
17
|
+
description: 'URL of the image to display',
|
|
18
|
+
},
|
|
19
|
+
marks: {
|
|
20
|
+
control: 'object',
|
|
21
|
+
description: 'Array of marker coordinates. Bindable for two-way data flow.',
|
|
22
|
+
},
|
|
23
|
+
onclick: {
|
|
24
|
+
action: 'clicked',
|
|
25
|
+
description: 'Event handler for when a marker is added',
|
|
26
|
+
},
|
|
27
|
+
disabled: {
|
|
28
|
+
control: 'boolean',
|
|
29
|
+
description: 'Disables interaction with the counter',
|
|
30
|
+
},
|
|
31
|
+
hideMarkers: {
|
|
32
|
+
control: 'boolean',
|
|
33
|
+
description: 'Hides the markers and prevents new ones from being added',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const largeImage = '/imgs/ris.jpg';
|
|
39
|
+
|
|
40
|
+
function handleUpdate(event: MouseEvent, marks: Array<{ x: number; y: number }>) {
|
|
41
|
+
console.log('Marker count:', marks.length);
|
|
42
|
+
console.log('Marker positions:', marks);
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<script lang="ts">
|
|
47
|
+
let activeConfigIndex = $state(0);
|
|
48
|
+
let allMarksMultiConfig = $state([
|
|
49
|
+
// Yeast Count (config 0) - blue markers
|
|
50
|
+
{ x: 120, y: 150, configIndex: 0, color: 'icon-blue', id: 'yeast-1' },
|
|
51
|
+
{ x: 180, y: 220, configIndex: 0, color: 'icon-blue', id: 'yeast-2' },
|
|
52
|
+
{ x: 250, y: 180, configIndex: 0, color: 'icon-blue', id: 'yeast-3' },
|
|
53
|
+
|
|
54
|
+
// Mold Count (config 1) - orange markers
|
|
55
|
+
{ x: 320, y: 160, configIndex: 1, color: 'icon-orange', id: 'mold-1' },
|
|
56
|
+
{ x: 380, y: 240, configIndex: 1, color: 'icon-orange', id: 'mold-2' },
|
|
57
|
+
|
|
58
|
+
// Colony Type (config 2) - lime markers
|
|
59
|
+
{ x: 400, y: 120, configIndex: 2, color: 'icon-lime', id: 'type-1' },
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
const configurations = [
|
|
63
|
+
{ name: 'Yeast Count', color: 'icon-blue', configIndex: 0 },
|
|
64
|
+
{ name: 'Mold Count', color: 'icon-orange', configIndex: 1 },
|
|
65
|
+
{ name: 'Colony Type', color: 'icon-lime', configIndex: 2 },
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
function handleMultiConfigUpdate(event: MouseEvent, marks: Array<{ x: number; y: number }>) {
|
|
69
|
+
console.log(`Configuration ${activeConfigIndex} updated:`, marks.length, 'marks');
|
|
70
|
+
|
|
71
|
+
allMarksMultiConfig = allMarksMultiConfig.filter(
|
|
72
|
+
(mark) => mark.configIndex !== activeConfigIndex
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const newMarks = marks.map((mark, index) => ({
|
|
76
|
+
x: mark.x,
|
|
77
|
+
y: mark.y,
|
|
78
|
+
configIndex: activeConfigIndex,
|
|
79
|
+
color: configurations[activeConfigIndex].color,
|
|
80
|
+
id: `config-${activeConfigIndex}-${index + 1}`,
|
|
81
|
+
}));
|
|
82
|
+
|
|
83
|
+
allMarksMultiConfig = [...allMarksMultiConfig, ...newMarks];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function switchConfiguration(configIndex: number) {
|
|
87
|
+
activeConfigIndex = configIndex;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const activeConfigMarks = $derived(
|
|
91
|
+
allMarksMultiConfig
|
|
92
|
+
.filter((mark) => mark.configIndex === activeConfigIndex)
|
|
93
|
+
.map((mark) => ({ x: mark.x, y: mark.y }))
|
|
94
|
+
);
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<Story name="Default" asChild>
|
|
98
|
+
<div class="p-4">
|
|
99
|
+
<h3 class="mb-4 text-lg font-semibold">Manual CFU Counter</h3>
|
|
100
|
+
<p class="mb-4 text-sm text-secondary">
|
|
101
|
+
Click to add markers. Pan by clicking and dragging. Zoom with the mouse wheel.
|
|
102
|
+
</p>
|
|
103
|
+
<div class="h-[600px] rounded-lg border border-static p-4">
|
|
104
|
+
<MultiCFUCounter imageUrl={largeImage} onclick={handleUpdate} activeMarkerName="Yeast" />
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</Story>
|
|
108
|
+
|
|
109
|
+
<Story name="Multi-Configuration Mode" asChild>
|
|
110
|
+
<div class="p-4">
|
|
111
|
+
<h3 class="mb-4 text-lg font-semibold">Multi-Configuration CFU Counter</h3>
|
|
112
|
+
<p class="mb-4 text-sm text-secondary">
|
|
113
|
+
This example demonstrates the multi-configuration mode used in assay analysis validation.
|
|
114
|
+
Switch between different configurations to count different types of objects with color-coded
|
|
115
|
+
markers.
|
|
116
|
+
</p>
|
|
117
|
+
|
|
118
|
+
<div class="mb-4 flex gap-2">
|
|
119
|
+
{#each configurations as config, index}
|
|
120
|
+
<button
|
|
121
|
+
class="flex items-center gap-2 rounded-lg border px-3 py-2 text-sm transition-colors"
|
|
122
|
+
class:border-interactive={activeConfigIndex === index}
|
|
123
|
+
class:bg-surface-secondary={activeConfigIndex === index}
|
|
124
|
+
class:border-neutral={activeConfigIndex !== index}
|
|
125
|
+
onclick={() => switchConfiguration(index)}
|
|
126
|
+
>
|
|
127
|
+
<div
|
|
128
|
+
class="h-3 w-3 rounded-full"
|
|
129
|
+
style="background-color: var(--text-{config.color})"
|
|
130
|
+
></div>
|
|
131
|
+
{config.name}
|
|
132
|
+
<span class="text-xs text-tertiary">
|
|
133
|
+
({allMarksMultiConfig.filter((m) => m.configIndex === index).length})
|
|
134
|
+
</span>
|
|
135
|
+
</button>
|
|
136
|
+
{/each}
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<div class="mb-4 rounded-lg border border-neutral bg-surface-secondary p-3">
|
|
140
|
+
<div class="mb-2 flex items-center gap-2">
|
|
141
|
+
<div
|
|
142
|
+
class="h-4 w-4 rounded-full"
|
|
143
|
+
style="background-color: var(--text-{configurations[activeConfigIndex].color})"
|
|
144
|
+
></div>
|
|
145
|
+
<span class="font-medium">Active: {configurations[activeConfigIndex].name}</span>
|
|
146
|
+
</div>
|
|
147
|
+
<p class="text-sm text-secondary">
|
|
148
|
+
Click on the image to add markers for {configurations[
|
|
149
|
+
activeConfigIndex
|
|
150
|
+
].name.toLowerCase()}. Each configuration maintains its own set of markers with distinct
|
|
151
|
+
colors.
|
|
152
|
+
</p>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div class="h-[600px] rounded-lg border border-static p-4">
|
|
156
|
+
<MultiCFUCounter
|
|
157
|
+
imageUrl={largeImage}
|
|
158
|
+
marks={activeConfigMarks}
|
|
159
|
+
allMarks={allMarksMultiConfig}
|
|
160
|
+
showMultiConfig={true}
|
|
161
|
+
activeMarkerColor={configurations[activeConfigIndex].color}
|
|
162
|
+
activeMarkerName={configurations[activeConfigIndex].name}
|
|
163
|
+
editableConfigIndex={activeConfigIndex}
|
|
164
|
+
onclick={handleMultiConfigUpdate}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<div class="mt-4 grid grid-cols-3 gap-4">
|
|
169
|
+
{#each configurations as config, index}
|
|
170
|
+
<div class="rounded-lg border border-neutral bg-surface p-3">
|
|
171
|
+
<div class="mb-1 flex items-center gap-2">
|
|
172
|
+
<div
|
|
173
|
+
class="h-3 w-3 rounded-full"
|
|
174
|
+
style="background-color: var(--text-{config.color})"
|
|
175
|
+
></div>
|
|
176
|
+
<span class="text-sm font-medium">{config.name}</span>
|
|
177
|
+
</div>
|
|
178
|
+
<p class="text-lg font-bold">
|
|
179
|
+
{allMarksMultiConfig.filter((m) => m.configIndex === index).length}
|
|
180
|
+
</p>
|
|
181
|
+
<p class="text-xs text-tertiary">objects counted</p>
|
|
182
|
+
</div>
|
|
183
|
+
{/each}
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<details class="mt-4 text-sm">
|
|
187
|
+
<summary>All Marks Data:</summary>
|
|
188
|
+
<pre class="mt-2 rounded bg-surface-secondary p-2 text-xs">{JSON.stringify(
|
|
189
|
+
allMarksMultiConfig,
|
|
190
|
+
null,
|
|
191
|
+
2
|
|
192
|
+
)}</pre>
|
|
193
|
+
</details>
|
|
194
|
+
</div>
|
|
195
|
+
</Story>
|
|
196
|
+
|
|
197
|
+
<Story name="Disabled" asChild>
|
|
198
|
+
<div class="p-4">
|
|
199
|
+
<h3 class="mb-4 text-lg font-semibold">Disabled Counter</h3>
|
|
200
|
+
<p class="mb-4 text-sm text-secondary">No interactions are possible in disabled mode.</p>
|
|
201
|
+
<div class="h-[600px] rounded-lg border border-static p-4">
|
|
202
|
+
<MultiCFUCounter
|
|
203
|
+
imageUrl={largeImage}
|
|
204
|
+
marks={activeConfigMarks}
|
|
205
|
+
allMarks={allMarksMultiConfig}
|
|
206
|
+
showMultiConfig={true}
|
|
207
|
+
activeMarkerColor={configurations[activeConfigIndex].color}
|
|
208
|
+
activeMarkerName={configurations[activeConfigIndex].name}
|
|
209
|
+
editableConfigIndex={activeConfigIndex}
|
|
210
|
+
onclick={handleMultiConfigUpdate}
|
|
211
|
+
disabled
|
|
212
|
+
/>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</Story>
|