@reshape-biotech/design-system 0.0.52 → 1.1.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.
Files changed (184) hide show
  1. package/dist/components/activity/Activity.stories.svelte +21 -8
  2. package/dist/components/activity/Activity.svelte +49 -9
  3. package/dist/components/activity/Activity.svelte.d.ts +1 -1
  4. package/dist/components/avatar/Avatar.stories.svelte +7 -17
  5. package/dist/components/avatar/Avatar.svelte +2 -2
  6. package/dist/components/avatar/Avatar.svelte.d.ts +2 -2
  7. package/dist/components/banner/Banner.stories.svelte +5 -5
  8. package/dist/components/button/Button.stories.svelte +54 -21
  9. package/dist/components/button/Button.svelte +58 -11
  10. package/dist/components/button/Button.svelte.d.ts +4 -3
  11. package/dist/components/card/Card.stories.svelte +130 -0
  12. package/dist/components/card/Card.stories.svelte.d.ts +19 -0
  13. package/dist/components/card/Card.svelte +25 -0
  14. package/dist/components/card/Card.svelte.d.ts +10 -0
  15. package/dist/components/card/index.d.ts +1 -0
  16. package/dist/components/card/index.js +1 -0
  17. package/dist/components/checkbox/Checkbox.stories.svelte +22 -0
  18. package/dist/components/checkbox/Checkbox.stories.svelte.d.ts +19 -0
  19. package/dist/components/checkbox/Checkbox.svelte +24 -0
  20. package/dist/components/checkbox/Checkbox.svelte.d.ts +5 -0
  21. package/dist/components/checkbox/index.d.ts +1 -0
  22. package/dist/components/checkbox/index.js +1 -0
  23. package/dist/components/collapsible/Collapsible.stories.svelte +5 -4
  24. package/dist/components/collapsible/components/collapsible-trigger.svelte +1 -1
  25. package/dist/components/combobox/Combobox.stories.svelte +7 -5
  26. package/dist/components/combobox/components/combobox-add.svelte +2 -1
  27. package/dist/components/combobox/components/combobox-content.svelte +4 -0
  28. package/dist/components/combobox/types.d.ts +2 -0
  29. package/dist/components/datepicker/DatePicker.stories.svelte +8 -14
  30. package/dist/components/divider/Divider.stories.svelte +1 -3
  31. package/dist/components/divider/Divider.svelte +8 -2
  32. package/dist/components/divider/Divider.svelte.d.ts +2 -0
  33. package/dist/components/drawer/Drawer.stories.svelte +3 -3
  34. package/dist/components/dropdown/Dropdown.stories.svelte +8 -8
  35. package/dist/components/empty-content/EmptyContent.stories.svelte +2 -2
  36. package/dist/components/graphs/bar-chart/BarChart.stories.svelte +81 -0
  37. package/dist/components/graphs/bar-chart/BarChart.stories.svelte.d.ts +19 -0
  38. package/dist/components/graphs/bar-chart/BarChart.svelte +136 -0
  39. package/dist/components/graphs/bar-chart/BarChart.svelte.d.ts +15 -0
  40. package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte +42 -0
  41. package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte.d.ts +19 -0
  42. package/dist/components/graphs/bar-chart/StackedBarChart.svelte +177 -0
  43. package/dist/components/graphs/bar-chart/StackedBarChart.svelte.d.ts +16 -0
  44. package/dist/components/graphs/chart/Chart.stories.svelte +31 -23
  45. package/dist/components/graphs/chart/Chart.svelte +104 -32
  46. package/dist/components/graphs/chart/Chart.svelte.d.ts +15 -5
  47. package/dist/components/graphs/index.d.ts +3 -0
  48. package/dist/components/graphs/index.js +3 -0
  49. package/dist/components/graphs/line/LineChart.stories.svelte +107 -15
  50. package/dist/components/graphs/line/LineChart.svelte +90 -51
  51. package/dist/components/graphs/line/LineChart.svelte.d.ts +6 -13
  52. package/dist/components/graphs/matrix/Matrix.stories.svelte +156 -0
  53. package/dist/components/graphs/matrix/Matrix.stories.svelte.d.ts +19 -0
  54. package/dist/components/graphs/matrix/Matrix.svelte +149 -0
  55. package/dist/components/graphs/matrix/Matrix.svelte.d.ts +24 -0
  56. package/dist/components/graphs/matrix/index.d.ts +3 -0
  57. package/dist/components/graphs/matrix/index.js +3 -0
  58. package/dist/components/graphs/multiline/MultiLineChart.stories.svelte +130 -18
  59. package/dist/components/graphs/multiline/MultiLineChart.svelte +187 -50
  60. package/dist/components/graphs/multiline/MultiLineChart.svelte.d.ts +9 -12
  61. package/dist/components/graphs/scatterplot/Scatterplot.stories.svelte +68 -41
  62. package/dist/components/graphs/scatterplot/Scatterplot.svelte +312 -45
  63. package/dist/components/graphs/scatterplot/Scatterplot.svelte.d.ts +23 -13
  64. package/dist/components/graphs/utils/tooltipFormatter.d.ts +10 -0
  65. package/dist/components/graphs/utils/tooltipFormatter.js +52 -0
  66. package/dist/components/icon-button/IconButton.stories.svelte +6 -6
  67. package/dist/components/icon-button/IconButton.svelte +50 -9
  68. package/dist/components/icon-button/IconButton.svelte.d.ts +3 -5
  69. package/dist/components/icons/AnalysisIcon.stories.svelte +15 -21
  70. package/dist/components/icons/AnalysisIcon.svelte +53 -43
  71. package/dist/components/icons/Icon.stories.svelte +4 -4
  72. package/dist/components/icons/Icon.svelte +1 -1
  73. package/dist/components/icons/PrincipalIcon.svelte +96 -0
  74. package/dist/components/icons/PrincipalIcon.svelte.d.ts +10 -0
  75. package/dist/components/icons/custom/Halo.svelte +14 -8
  76. package/dist/components/icons/custom/Halo.svelte.d.ts +7 -25
  77. package/dist/components/icons/custom/Well.svelte +14 -6
  78. package/dist/components/icons/custom/Well.svelte.d.ts +7 -25
  79. package/dist/components/icons/index.d.ts +3 -2
  80. package/dist/components/icons/index.js +26 -0
  81. package/dist/components/input/Input.stories.svelte +16 -22
  82. package/dist/components/input/Input.svelte +140 -134
  83. package/dist/components/input/Input.svelte.d.ts +12 -13
  84. package/dist/components/label/Label.stories.svelte +28 -0
  85. package/dist/components/label/Label.stories.svelte.d.ts +19 -0
  86. package/dist/components/label/Label.svelte +17 -0
  87. package/dist/components/label/Label.svelte.d.ts +9 -0
  88. package/dist/components/list/List.stories.svelte +3 -3
  89. package/dist/components/logo/Logo.stories.svelte +1 -1
  90. package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte +125 -0
  91. package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte.d.ts +3 -0
  92. package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte +577 -0
  93. package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte.d.ts +16 -0
  94. package/dist/components/manual-cfu-counter/index.d.ts +1 -0
  95. package/dist/components/manual-cfu-counter/index.js +1 -0
  96. package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte +22 -0
  97. package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte.d.ts +19 -0
  98. package/dist/components/markdown/Markdown.stories.svelte +1 -1
  99. package/dist/components/markdown/Markdown.svelte +1 -1
  100. package/dist/components/modal/Modal.stories.svelte +2 -2
  101. package/dist/components/modal/Modal.svelte +27 -22
  102. package/dist/components/modal/Modal.svelte.d.ts +4 -1
  103. package/dist/components/notification-popup/NotificationPopup.stories.svelte +1 -1
  104. package/dist/components/pill/Pill.stories.svelte +13 -0
  105. package/dist/components/pill/Pill.stories.svelte.d.ts +19 -0
  106. package/dist/components/progress-circle/ProgressCircle.stories.svelte +15 -0
  107. package/dist/components/progress-circle/ProgressCircle.stories.svelte.d.ts +19 -0
  108. package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte +28 -0
  109. package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte.d.ts +19 -0
  110. package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte +22 -0
  111. package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte.d.ts +8 -0
  112. package/dist/components/required-status-indicator/index.d.ts +1 -0
  113. package/dist/components/required-status-indicator/index.js +1 -0
  114. package/dist/components/segmented-control-buttons/SegmentedControlButtons.stories.svelte +3 -3
  115. package/dist/components/select/Select.stories.svelte +12 -12
  116. package/dist/components/select/Select.svelte +0 -2
  117. package/dist/components/select-new/Select.stories.svelte +219 -0
  118. package/dist/components/select-new/Select.stories.svelte.d.ts +19 -0
  119. package/dist/components/select-new/components/Group.svelte +23 -0
  120. package/dist/components/select-new/components/Group.svelte.d.ts +10 -0
  121. package/dist/components/select-new/components/MultiSelectTrigger.svelte +66 -0
  122. package/dist/components/select-new/components/MultiSelectTrigger.svelte.d.ts +17 -0
  123. package/dist/components/select-new/components/SelectContent.svelte +33 -0
  124. package/dist/components/select-new/components/SelectContent.svelte.d.ts +10 -0
  125. package/dist/components/select-new/components/SelectGroupHeading.svelte +19 -0
  126. package/dist/components/select-new/components/SelectGroupHeading.svelte.d.ts +9 -0
  127. package/dist/components/select-new/components/SelectItem.svelte +41 -0
  128. package/dist/components/select-new/components/SelectItem.svelte.d.ts +9 -0
  129. package/dist/components/select-new/components/SelectTrigger.svelte +48 -0
  130. package/dist/components/select-new/components/SelectTrigger.svelte.d.ts +12 -0
  131. package/dist/components/select-new/index.d.ts +10 -0
  132. package/dist/components/select-new/index.js +12 -0
  133. package/dist/components/select-new/types.d.ts +25 -0
  134. package/dist/components/select-new/types.js +1 -0
  135. package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte +92 -0
  136. package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte.d.ts +3 -0
  137. package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte +65 -0
  138. package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte.d.ts +3 -0
  139. package/dist/components/sjsf-wrappers/index.d.ts +2 -0
  140. package/dist/components/sjsf-wrappers/index.js +2 -0
  141. package/dist/components/sjsf-wrappers/sjsfCustomTheme.d.ts +2 -0
  142. package/dist/components/sjsf-wrappers/sjsfCustomTheme.js +8 -0
  143. package/dist/components/skeleton-loader/SkeletonLoader.stories.svelte +4 -4
  144. package/dist/components/slider/Slider.stories.svelte +4 -4
  145. package/dist/components/spinner/Spinner.stories.svelte +13 -0
  146. package/dist/components/spinner/Spinner.stories.svelte.d.ts +19 -0
  147. package/dist/components/stat-card/StatCard.stories.svelte +27 -19
  148. package/dist/components/stat-card/StatCard.svelte +100 -6
  149. package/dist/components/stat-card/StatCard.svelte.d.ts +3 -0
  150. package/dist/components/status-badge/StatusBadge.stories.svelte +6 -6
  151. package/dist/components/status-badge/StatusBadge.svelte +5 -3
  152. package/dist/components/table/Table.stories.svelte +1 -1
  153. package/dist/components/table/components/Td.svelte +3 -2
  154. package/dist/components/table/components/Td.svelte.d.ts +1 -0
  155. package/dist/components/table/components/Tr.svelte +3 -2
  156. package/dist/components/table/components/Tr.svelte.d.ts +1 -0
  157. package/dist/components/tabs/Tabs.stories.svelte +1 -1
  158. package/dist/components/tag/Tag.stories.svelte +38 -7
  159. package/dist/components/tag/Tag.svelte +34 -21
  160. package/dist/components/tag/Tag.svelte.d.ts +1 -1
  161. package/dist/components/textarea/Textarea.stories.svelte +97 -0
  162. package/dist/components/textarea/Textarea.stories.svelte.d.ts +19 -0
  163. package/dist/components/textarea/Textarea.svelte +94 -0
  164. package/dist/components/textarea/Textarea.svelte.d.ts +17 -0
  165. package/dist/components/textarea/index.d.ts +1 -0
  166. package/dist/components/textarea/index.js +1 -0
  167. package/dist/components/toggle/Toggle.stories.svelte +1 -1
  168. package/dist/components/toggle/Toggle.svelte +3 -2
  169. package/dist/components/toggle/Toggle.svelte.d.ts +1 -0
  170. package/dist/components/toggle-icon-button/ToggleIconButton.stories.svelte +173 -0
  171. package/dist/components/toggle-icon-button/ToggleIconButton.stories.svelte.d.ts +19 -0
  172. package/dist/components/toggle-icon-button/ToggleIconButton.svelte +117 -0
  173. package/dist/components/toggle-icon-button/ToggleIconButton.svelte.d.ts +15 -0
  174. package/dist/components/toggle-icon-button/index.d.ts +3 -0
  175. package/dist/components/toggle-icon-button/index.js +3 -0
  176. package/dist/components/tooltip/Tooltip.stories.svelte +6 -6
  177. package/dist/components/tooltip/Tooltip.svelte +1 -1
  178. package/dist/index.d.ts +7 -0
  179. package/dist/index.js +7 -0
  180. package/dist/tailwind-safelist.js +2 -0
  181. package/dist/tailwind.preset.d.ts +2 -0
  182. package/dist/tokens.d.ts +4 -0
  183. package/dist/tokens.js +3 -1
  184. package/package.json +1 -2
@@ -0,0 +1,92 @@
1
+ <script lang="ts">
2
+ import type { ComponentProps } from '@sjsf/form';
3
+ import { getFormContext, inputAttributes } from '@sjsf/form';
4
+ import Input from '../input/Input.svelte';
5
+ import type { FocusEventHandler } from 'svelte/elements';
6
+
7
+ type Props = ComponentProps['numberWidget'];
8
+
9
+ let { value = $bindable(), config, handlers, errors }: Props = $props();
10
+
11
+ const ctx = getFormContext();
12
+
13
+ const derivedAttrs = $derived(
14
+ inputAttributes(ctx, config, 'number', handlers, {
15
+ type: 'number'
16
+ })
17
+ );
18
+ const placeholder = $derived(
19
+ config?.uiSchema?.['ui:placeholder'] ||
20
+ config?.schema?.description ||
21
+ (Array.isArray(config?.schema?.examples) && config.schema.examples.length > 0
22
+ ? String(config.schema.examples[0]) // Ensure the example is also a string
23
+ : '') ||
24
+ ''
25
+ );
26
+
27
+ const readonly = $derived(config?.schema?.readOnly ?? false);
28
+ const currentClass = $derived(derivedAttrs?.class ?? 'w-full');
29
+
30
+ const onBlurHandler = $derived(
31
+ derivedAttrs.onblur
32
+ ? (event: FocusEvent) =>
33
+ (derivedAttrs.onblur as FocusEventHandler<HTMLInputElement>)(event as any)
34
+ : undefined
35
+ );
36
+
37
+ const onChangeHandler = $derived(
38
+ derivedAttrs.onchange
39
+ ? (event: Event) =>
40
+ (derivedAttrs.onchange as FocusEventHandler<HTMLInputElement>)(event as any)
41
+ : undefined
42
+ );
43
+
44
+ const onInputHandler = $derived(
45
+ derivedAttrs.oninput
46
+ ? (event: Event) =>
47
+ (derivedAttrs.oninput as FocusEventHandler<HTMLInputElement>)(event as any)
48
+ : undefined
49
+ );
50
+
51
+ const getStringValue = () => {
52
+ if (value === undefined || value === null || isNaN(value)) {
53
+ return '';
54
+ }
55
+ return String(value);
56
+ };
57
+
58
+ const setNumericValue = (newValueFromInput: unknown) => {
59
+ const stringifiedInput =
60
+ newValueFromInput === null || newValueFromInput === undefined
61
+ ? ''
62
+ : String(newValueFromInput);
63
+
64
+ if (stringifiedInput.trim() === '') {
65
+ value = undefined;
66
+ } else {
67
+ const num = parseFloat(stringifiedInput);
68
+ value = isNaN(num) ? undefined : num;
69
+ }
70
+ };
71
+ </script>
72
+
73
+ <Input
74
+ bind:value={() => getStringValue(), (v) => setNumericValue(v)}
75
+ placeholder={String(placeholder)}
76
+ type={'number'}
77
+ {readonly}
78
+ id={String(derivedAttrs.id)}
79
+ name={String(derivedAttrs.name)}
80
+ disabled={derivedAttrs.disabled}
81
+ required={derivedAttrs.required}
82
+ step={config?.schema?.multipleOf ?? (config?.schema?.type === 'integer' ? 1 : 'any')}
83
+ min={config?.schema?.minimum ?? config?.schema?.exclusiveMinimum}
84
+ max={config?.schema?.maximum ?? config?.schema?.exclusiveMaximum}
85
+ aria-invalid={errors && errors.length > 0 ? true : undefined}
86
+ aria-describedby={errors && errors.length > 0 ? `${String(derivedAttrs.id)}-errors` : undefined}
87
+ class={String(currentClass)}
88
+ autocomplete="off"
89
+ oninput={onInputHandler}
90
+ onchange={onChangeHandler}
91
+ onblur={onBlurHandler}
92
+ />
@@ -0,0 +1,3 @@
1
+ declare const SjsfNumberInputWrapper: import("svelte").Component<any, {}, "value">;
2
+ type SjsfNumberInputWrapper = ReturnType<typeof SjsfNumberInputWrapper>;
3
+ export default SjsfNumberInputWrapper;
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import type { ComponentProps } from '@sjsf/form';
3
+ import { getFormContext, inputAttributes } from '@sjsf/form';
4
+ import Input from '../input/Input.svelte';
5
+ import type { FormEventHandler, FocusEventHandler } from 'svelte/elements';
6
+
7
+ type Props = ComponentProps['textWidget'];
8
+
9
+ let { value = $bindable(), config, handlers, errors }: Props = $props();
10
+
11
+ const ctx = getFormContext();
12
+
13
+ const derivedAttrs = $derived(
14
+ inputAttributes(ctx, config, 'text', handlers, {
15
+ type: 'text'
16
+ })
17
+ );
18
+
19
+ const placeholder = $derived(
20
+ config?.uiSchema?.['ui:placeholder'] ||
21
+ config?.schema?.description ||
22
+ (Array.isArray(config?.schema?.examples) && config.schema.examples.length > 0
23
+ ? String(config.schema.examples[0])
24
+ : '') ||
25
+ ''
26
+ );
27
+
28
+ const readonly = $derived(config?.schema?.readOnly ?? false);
29
+ const currentClass = $derived(derivedAttrs?.class ?? 'w-full');
30
+
31
+ const onInput = $derived(
32
+ derivedAttrs.oninput
33
+ ? (event: Event) => (derivedAttrs.oninput as FormEventHandler<HTMLInputElement>)(event as any)
34
+ : undefined
35
+ );
36
+ const onChange = $derived(
37
+ derivedAttrs.onchange
38
+ ? (event: Event) =>
39
+ (derivedAttrs.onchange as FormEventHandler<HTMLInputElement>)(event as any)
40
+ : undefined
41
+ );
42
+ const onBlur = $derived(
43
+ derivedAttrs.onblur
44
+ ? (event: FocusEvent) =>
45
+ (derivedAttrs.onblur as FocusEventHandler<HTMLInputElement>)(event as any)
46
+ : undefined
47
+ );
48
+ </script>
49
+
50
+ <Input
51
+ bind:value
52
+ placeholder={String(placeholder)}
53
+ type="text"
54
+ {readonly}
55
+ id={String(derivedAttrs.id)}
56
+ name={String(derivedAttrs.name)}
57
+ disabled={derivedAttrs.disabled}
58
+ required={derivedAttrs.required}
59
+ oninput={onInput}
60
+ onchange={onChange}
61
+ onblur={onBlur}
62
+ aria-invalid={errors && errors.length > 0 ? true : undefined}
63
+ aria-describedby={errors && errors.length > 0 ? `${String(derivedAttrs.id)}-errors` : undefined}
64
+ class={String(currentClass)}
65
+ />
@@ -0,0 +1,3 @@
1
+ declare const SjsfTextInputWrapper: import("svelte").Component<any, {}, "value">;
2
+ type SjsfTextInputWrapper = ReturnType<typeof SjsfTextInputWrapper>;
3
+ export default SjsfTextInputWrapper;
@@ -0,0 +1,2 @@
1
+ export { default as SjsfTextInputWrapper } from './SjsfTextInputWrapper.svelte';
2
+ export { default as SjsfNumberInputWrapper } from './SjsfNumberInputWrapper.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as SjsfTextInputWrapper } from './SjsfTextInputWrapper.svelte';
2
+ export { default as SjsfNumberInputWrapper } from './SjsfNumberInputWrapper.svelte';
@@ -0,0 +1,2 @@
1
+ import type { Theme } from '@sjsf/form';
2
+ export declare const sjsfCustomTheme: Theme;
@@ -0,0 +1,8 @@
1
+ import { theme as BasicTheme } from '@sjsf/basic-theme';
2
+ import { overrideByRecord } from '@sjsf/form/lib/resolver';
3
+ import SjsfNumberInputWrapper from './SjsfNumberInputWrapper.svelte';
4
+ import SjsfTextInputWrapper from './SjsfTextInputWrapper.svelte';
5
+ export const sjsfCustomTheme = overrideByRecord(BasicTheme, {
6
+ numberWidget: SjsfNumberInputWrapper,
7
+ textWidget: SjsfTextInputWrapper
8
+ });
@@ -10,15 +10,15 @@
10
10
  });
11
11
  </script>
12
12
 
13
- <Story name="Primary">
14
- <SkeletonLoader class="h-[20px] w-[200px]">
13
+ <Story name="Primary" asChild>
14
+ <SkeletonLoader class="h-[50px] w-[200px]">
15
15
  {#snippet children({ Skeleton })}
16
16
  <Skeleton class="h-full w-full" />
17
17
  {/snippet}
18
18
  </SkeletonLoader>
19
19
  </Story>
20
20
 
21
- <Story name="ImagePlaceholder">
21
+ <Story name="ImagePlaceholder" asChild>
22
22
  <SkeletonLoader class="h-[100px] w-[500px]">
23
23
  {#snippet children({ Skeleton, SkeletonImage })}
24
24
  <div class="flex h-full gap-2">
@@ -36,7 +36,7 @@
36
36
  </SkeletonLoader>
37
37
  </Story>
38
38
 
39
- <Story name="StatCard">
39
+ <Story name="StatCard" asChild>
40
40
  <div class="flex w-[900px] gap-4">
41
41
  <StatcardSkeleton />
42
42
  <StatcardSkeleton />
@@ -12,19 +12,19 @@
12
12
  let value = 3;
13
13
  </script>
14
14
 
15
- <Story name="Default">
15
+ <Story name="Default" asChild>
16
16
  Value: {value + 1}
17
17
  <Slider bind:value bind:buffer={value} max={4}></Slider>
18
18
  </Story>
19
- <Story name="Playback Controls Running Job">
19
+ <Story name="Playback Controls Running Job" asChild>
20
20
  Value: {value + 1}
21
21
  <Slider bind:value buffer={35} max={49} bufferColorClass="bg-warning-inverse"></Slider>
22
22
  </Story>
23
- <Story name="Modern stepStyle">
23
+ <Story name="Modern stepStyle" asChild>
24
24
  Value: {value + 1}
25
25
  <Slider bind:value bind:buffer={value} max={4} showSteps={true}></Slider>
26
26
  </Story>
27
- <Story name="Create Job Capture Interval">
27
+ <Story name="Create Job Capture Interval" asChild>
28
28
  Value: {value + 1}
29
29
  <Slider
30
30
  bind:value
@@ -0,0 +1,13 @@
1
+ <script lang="ts" module>
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Spinner from './Spinner.svelte';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
6
+ const { Story } = defineMeta({
7
+ title: 'Design System/Spinner',
8
+ component: Spinner,
9
+ tags: ['autodocs']
10
+ });
11
+ </script>
12
+
13
+ <Story name="Base" />
@@ -0,0 +1,19 @@
1
+ import Spinner from './Spinner.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 Spinner: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type Spinner = InstanceType<typeof Spinner>;
19
+ export default Spinner;
@@ -9,24 +9,32 @@
9
9
  });
10
10
  </script>
11
11
 
12
- <Story name="Default">
13
- <StatCard title="Title" value="Value" unit="unit" titleTooltip="Title tooltip" />
14
- </Story>
12
+ <Story
13
+ name="Default"
14
+ args={{ title: 'Title', value: 'Value', unit: 'unit', titleTooltip: 'Title tooltip' }}
15
+ />
15
16
 
16
- <Story name="Germination Rate">
17
- <StatCard
18
- title="Germination Rate"
19
- value="2"
20
- unit="%"
21
- titleTooltip="Something that explains what this is..."
22
- showTitleTooltip={true}
23
- />
24
- </Story>
17
+ <Story
18
+ name="Germination Rate"
19
+ args={{
20
+ title: 'Germination Rate',
21
+ value: '2',
22
+ unit: '%',
23
+ titleTooltip: 'Something that explains what this is...',
24
+ showTitleTooltip: true
25
+ }}
26
+ />
25
27
 
26
- <Story name="Home Page">
27
- <div class="flex w-full gap-4">
28
- <StatCard title="Current jobs" value="3" unit="of 5" />
29
- <StatCard title="Run time" value="5.4" unit="hours" />
30
- <StatCard title="Images taken" value="1366" />
31
- </div>
32
- </Story>
28
+ <Story name="Home Page" args={{ title: 'Current jobs', value: '3', unit: 'of 5' }} />
29
+
30
+ <Story
31
+ name="Editable"
32
+ args={{
33
+ title: 'Germination Rate',
34
+ value: '2',
35
+ unit: '%',
36
+ titleTooltip: 'Something that explains what this is...',
37
+ showTitleTooltip: true,
38
+ editable: true
39
+ }}
40
+ />
@@ -1,7 +1,10 @@
1
1
  <script lang="ts">
2
+ import IconButton from '../icon-button/IconButton.svelte';
2
3
  import { Icon } from '../icons';
3
4
  import Spinner from '../spinner/Spinner.svelte';
4
5
  import Tooltip from '../tooltip/Tooltip.svelte';
6
+ import { Input } from '../input';
7
+ import { tick } from 'svelte';
5
8
 
6
9
  interface Props {
7
10
  title: string;
@@ -9,6 +12,9 @@
9
12
  unit?: string | null;
10
13
  titleTooltip?: string;
11
14
  showTitleTooltip?: boolean;
15
+ editable?: boolean;
16
+ onsubmit?: (value: string | number) => void;
17
+ inputType?: 'text' | 'number';
12
18
  }
13
19
 
14
20
  let {
@@ -16,13 +22,82 @@
16
22
  value = null,
17
23
  unit = '',
18
24
  titleTooltip = '',
19
- showTitleTooltip = false
25
+ showTitleTooltip = false,
26
+ editable = false,
27
+ inputType = 'text',
28
+ onsubmit
20
29
  }: Props = $props();
21
30
  const formattedValue = $derived(typeof value === 'number' ? value.toLocaleString() : value);
31
+ let isEditing = $state(false);
32
+ let inputValue = $state('');
33
+ let inputComponent = $state<Input | null>(null);
34
+
35
+ function startEditing(event?: MouseEvent) {
36
+ if (event) {
37
+ event.stopPropagation();
38
+ }
39
+ isEditing = true;
40
+ inputValue = value !== null ? value.toString() : '';
41
+ }
42
+
43
+ function handleCardClick() {
44
+ if (editable && !isEditing && value !== null) {
45
+ startEditing();
46
+ }
47
+ }
48
+
49
+ function handleInputBlur(event: Event) {
50
+ const target = event.target as HTMLInputElement;
51
+ inputValue = target.value;
52
+ submitValue();
53
+ }
54
+
55
+ function handleInputKeydown(event: KeyboardEvent) {
56
+ const target = event.target as HTMLInputElement;
57
+ inputValue = target.value;
58
+ if (event.key === 'Escape') {
59
+ isEditing = false;
60
+ }
61
+ if (event.key === 'Enter') {
62
+ submitValue();
63
+ }
64
+ }
65
+
66
+ function submitValue() {
67
+ if (inputValue.trim() === '') {
68
+ isEditing = false;
69
+ return;
70
+ }
71
+
72
+ // Try to parse as number if possible
73
+ const numValue = parseFloat(inputValue);
74
+ const newValue = isNaN(numValue) ? inputValue : numValue;
75
+
76
+ if (onsubmit) {
77
+ onsubmit(newValue);
78
+ }
79
+
80
+ isEditing = false;
81
+ }
82
+
83
+ $effect(() => {
84
+ if (isEditing && inputComponent) {
85
+ tick().then(() => {
86
+ inputComponent?.focus();
87
+ });
88
+ }
89
+ });
22
90
  </script>
23
91
 
92
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
24
93
  <div
25
- class="flex w-full flex-shrink-0 flex-grow basis-0 flex-col items-start gap-2 overflow-clip rounded-lg bg-neutral p-4"
94
+ data-testid="stat-card-body"
95
+ class="flex w-full flex-shrink-0 flex-grow basis-0 flex-col items-start gap-2 overflow-clip rounded-lg bg-neutral p-4 text-left transition-colors"
96
+ class:hover:bg-neutral-hover={editable && !isEditing && value !== null}
97
+ class:cursor-pointer={editable && !isEditing && value !== null}
98
+ onclick={editable && !isEditing && value !== null ? handleCardClick : undefined}
99
+ onkeydown={editable && !isEditing && value !== null ? handleInputKeydown : undefined}
100
+ aria-label={editable && !isEditing && value !== null ? `Edit ${title}` : undefined}
26
101
  >
27
102
  <p class="flex items-center justify-start gap-2 truncate font-medium text-secondary">
28
103
  {title}
@@ -39,11 +114,30 @@
39
114
  </Tooltip>
40
115
  {/if}
41
116
  </p>
42
- <div class="flex items-baseline gap-1">
117
+ <div class="flex h-10 w-full items-center gap-1">
43
118
  {#if value !== null}
44
- <p class="text-2xl font-medium">{formattedValue}</p>
45
- {#if unit}
46
- <p class="truncate text-2xl font-medium text-tertiary">{unit}</p>
119
+ {#if isEditing}
120
+ <div class="flex-1">
121
+ <Input
122
+ bind:this={inputComponent}
123
+ type={inputType}
124
+ value={inputValue}
125
+ onblur={handleInputBlur}
126
+ onkeydown={handleInputKeydown}
127
+ />
128
+ </div>
129
+ {:else}
130
+ <div class="flex flex-1 flex-nowrap items-baseline gap-1">
131
+ <p class="text-2xl font-medium">{formattedValue}</p>
132
+ {#if unit}
133
+ <p class="flex-1 truncate text-2xl font-medium text-tertiary">{unit}</p>
134
+ {/if}
135
+ </div>
136
+ {#if editable}
137
+ <IconButton onclick={(e) => startEditing(e)}>
138
+ <Icon iconName="PencilSimple" />
139
+ </IconButton>
140
+ {/if}
47
141
  {/if}
48
142
  {:else}
49
143
  <Spinner />
@@ -4,6 +4,9 @@ interface Props {
4
4
  unit?: string | null;
5
5
  titleTooltip?: string;
6
6
  showTitleTooltip?: boolean;
7
+ editable?: boolean;
8
+ onsubmit?: (value: string | number) => void;
9
+ inputType?: 'text' | 'number';
7
10
  }
8
11
  declare const StatCard: import("svelte").Component<Props, {}, "">;
9
12
  type StatCard = ReturnType<typeof StatCard>;
@@ -14,7 +14,7 @@
14
14
  let calculated_progress = 32;
15
15
  </script>
16
16
 
17
- <Story name="Neutral">
17
+ <Story name="Neutral" asChild>
18
18
  <p class="font-mono text-xs">Medium:</p>
19
19
  <div class="flex flex-row gap-4">
20
20
  <div class="flex flex-row gap-1">
@@ -84,7 +84,7 @@
84
84
  </div>
85
85
  </Story>
86
86
 
87
- <Story name="Success">
87
+ <Story name="Success" asChild>
88
88
  <p class="font-mono text-xs">Medium:</p>
89
89
  <div class="flex flex-row gap-4">
90
90
  <div class="flex flex-row gap-1">
@@ -198,7 +198,7 @@
198
198
  </div>
199
199
  </Story>
200
200
 
201
- <Story name="Progress">
201
+ <Story name="Progress" asChild>
202
202
  <p class="font-mono text-xs">Medium:</p>
203
203
  <div class="flex flex-row gap-1">
204
204
  <Tooltip>
@@ -268,7 +268,7 @@
268
268
  </div>
269
269
  </Story>
270
270
 
271
- <Story name="Warning">
271
+ <Story name="Warning" asChild>
272
272
  <p class="font-mono text-xs">Medium:</p>
273
273
  <div class="flex flex-row gap-1">
274
274
  <Tooltip>
@@ -326,7 +326,7 @@
326
326
  </div>
327
327
  </Story>
328
328
 
329
- <Story name="Error">
329
+ <Story name="Error" asChild>
330
330
  <p class="font-mono text-xs">Medium:</p>
331
331
  <div class="flex flex-row gap-1">
332
332
  <Tooltip>
@@ -384,7 +384,7 @@
384
384
  </div>
385
385
  </Story>
386
386
 
387
- <Story name="Icon only">
387
+ <Story name="Icon only" asChild>
388
388
  <StatusBadge type="neutral" iconOnly>
389
389
  {#snippet icon()}
390
390
  <Icon iconName="SpinnerGap" />
@@ -28,9 +28,11 @@
28
28
  class:badge-icon-only={iconOnly}
29
29
  data-testid="status-badge"
30
30
  >
31
- <div class={`icon`}>
32
- {@render icon?.()}
33
- </div>
31
+ {#if icon}
32
+ <div class={`icon`}>
33
+ {@render icon?.()}
34
+ </div>
35
+ {/if}
34
36
  <div class="gap-2">
35
37
  {@render content?.()}
36
38
  {@render progress?.()}
@@ -64,7 +64,7 @@
64
64
  ];
65
65
  </script>
66
66
 
67
- <Story name="Base">
67
+ <Story name="Base" asChild>
68
68
  <Table>
69
69
  {#snippet children({ THead, TBody, Tr, Th, Td })}
70
70
  <THead>
@@ -3,12 +3,13 @@
3
3
 
4
4
  interface Props {
5
5
  dataTestId?: string;
6
+ align?: 'left' | 'right';
6
7
  children?: Snippet;
7
8
  }
8
9
 
9
- let { dataTestId = '', children }: Props = $props();
10
+ let { dataTestId = '', align = 'left', children }: Props = $props();
10
11
  </script>
11
12
 
12
- <td data-testid={dataTestId} class={`text-left text-sm font-normal`}>
13
+ <td data-testid={dataTestId} class={`text-${align} text-sm font-normal`}>
13
14
  {@render children?.()}
14
15
  </td>
@@ -1,6 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  interface Props {
3
3
  dataTestId?: string;
4
+ align?: 'left' | 'right';
4
5
  children?: Snippet;
5
6
  }
6
7
  declare const Td: import("svelte").Component<Props, {}, "">;
@@ -4,12 +4,13 @@
4
4
  interface Props {
5
5
  disabled?: boolean;
6
6
  children?: Snippet;
7
+ class?: string;
7
8
  }
8
9
 
9
- let { disabled = false, children }: Props = $props();
10
+ let { disabled = false, children, class: className = '' }: Props = $props();
10
11
  </script>
11
12
 
12
- <tr class="my-2 border-static [&.disabled]:text-tertiary" class:disabled>
13
+ <tr class={`border-static py-2 [&.disabled]:text-tertiary ${className}`} class:disabled>
13
14
  {@render children?.()}
14
15
  </tr>
15
16
 
@@ -2,6 +2,7 @@ import type { Snippet } from 'svelte';
2
2
  interface Props {
3
3
  disabled?: boolean;
4
4
  children?: Snippet;
5
+ class?: string;
5
6
  }
6
7
  declare const Tr: import("svelte").Component<Props, {}, "">;
7
8
  type Tr = ReturnType<typeof Tr>;
@@ -11,7 +11,7 @@
11
11
  let activeTab = 'tab-1';
12
12
  </script>
13
13
 
14
- <Story name="Primary">
14
+ <Story name="Primary" asChild>
15
15
  <Tabs>
16
16
  {#snippet children({ Tabs, Tab, Content })}
17
17
  <Tabs>