@runwisp/ui 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +215 -0
  2. package/README.md +20 -0
  3. package/package.json +128 -0
  4. package/src/app.d.ts +8 -0
  5. package/src/app.html +12 -0
  6. package/src/astro/CTABand.astro +32 -0
  7. package/src/astro/Hero.astro +58 -0
  8. package/src/astro/SiteFooter.astro +47 -0
  9. package/src/astro/SiteHeader.astro +46 -0
  10. package/src/lib/actions/portal.ts +16 -0
  11. package/src/lib/assets/runwisp-logo.svg +16 -0
  12. package/src/lib/components/Accordion.svelte +20 -0
  13. package/src/lib/components/AccordionItem.svelte +74 -0
  14. package/src/lib/components/Alert.svelte +107 -0
  15. package/src/lib/components/AlertDialog.svelte +63 -0
  16. package/src/lib/components/Avatar.svelte +88 -0
  17. package/src/lib/components/Badge.svelte +131 -0
  18. package/src/lib/components/Breadcrumb.svelte +58 -0
  19. package/src/lib/components/Button.svelte +69 -0
  20. package/src/lib/components/Card.svelte +70 -0
  21. package/src/lib/components/Checkbox.svelte +90 -0
  22. package/src/lib/components/CodeBlock.svelte +66 -0
  23. package/src/lib/components/CronInput.svelte +130 -0
  24. package/src/lib/components/DataGrid.svelte +368 -0
  25. package/src/lib/components/Drawer.svelte +156 -0
  26. package/src/lib/components/Dropdown.svelte +195 -0
  27. package/src/lib/components/DurationInput.svelte +170 -0
  28. package/src/lib/components/EmptyState.svelte +46 -0
  29. package/src/lib/components/ErrorState.svelte +73 -0
  30. package/src/lib/components/FeatureCard.svelte +35 -0
  31. package/src/lib/components/FeatureGrid.svelte +37 -0
  32. package/src/lib/components/FormField.svelte +53 -0
  33. package/src/lib/components/Heading.svelte +46 -0
  34. package/src/lib/components/Input.svelte +114 -0
  35. package/src/lib/components/Kbd.svelte +31 -0
  36. package/src/lib/components/Link.svelte +56 -0
  37. package/src/lib/components/LinkButton.svelte +55 -0
  38. package/src/lib/components/LogConsole.svelte +424 -0
  39. package/src/lib/components/Logo.svelte +34 -0
  40. package/src/lib/components/Modal.svelte +138 -0
  41. package/src/lib/components/PageContainer.svelte +38 -0
  42. package/src/lib/components/Pagination.svelte +96 -0
  43. package/src/lib/components/Popover.svelte +130 -0
  44. package/src/lib/components/Progress.svelte +68 -0
  45. package/src/lib/components/Prose.svelte +43 -0
  46. package/src/lib/components/Radio.svelte +82 -0
  47. package/src/lib/components/RadioGroup.svelte +53 -0
  48. package/src/lib/components/Select.svelte +454 -0
  49. package/src/lib/components/Separator.svelte +30 -0
  50. package/src/lib/components/Skeleton.svelte +75 -0
  51. package/src/lib/components/Sparkline.svelte +58 -0
  52. package/src/lib/components/Spinner.svelte +44 -0
  53. package/src/lib/components/StatusIndicator.svelte +203 -0
  54. package/src/lib/components/Table.svelte +19 -0
  55. package/src/lib/components/TableBody.svelte +17 -0
  56. package/src/lib/components/TableCell.svelte +34 -0
  57. package/src/lib/components/TableHead.svelte +19 -0
  58. package/src/lib/components/TableRow.svelte +22 -0
  59. package/src/lib/components/Tabs.svelte +148 -0
  60. package/src/lib/components/Text.svelte +57 -0
  61. package/src/lib/components/Textarea.svelte +81 -0
  62. package/src/lib/components/ThemeToggle.svelte +47 -0
  63. package/src/lib/components/TimezoneSelect.svelte +127 -0
  64. package/src/lib/components/ToastContainer.svelte +84 -0
  65. package/src/lib/components/Toggle.svelte +84 -0
  66. package/src/lib/components/Tooltip.svelte +56 -0
  67. package/src/lib/components/button-styles.ts +51 -0
  68. package/src/lib/components/dashboard/RunDetailPanel.svelte +252 -0
  69. package/src/lib/components/dashboard/RunsList.svelte +331 -0
  70. package/src/lib/components/dashboard/run-helpers.ts +12 -0
  71. package/src/lib/components/dashboard/status-config.ts +141 -0
  72. package/src/lib/components/dashboard/types.ts +35 -0
  73. package/src/lib/index.ts +122 -0
  74. package/src/lib/log-console/LogCache.svelte.ts +93 -0
  75. package/src/lib/log-console/LogFetcher.svelte.ts +179 -0
  76. package/src/lib/log-console/types.ts +24 -0
  77. package/src/lib/theme-tokens.css +235 -0
  78. package/src/lib/theme.css +276 -0
  79. package/src/lib/utils/error.ts +18 -0
  80. package/src/lib/utils/format.ts +76 -0
  81. package/src/lib/utils/id.ts +6 -0
  82. package/src/lib/utils/toast.svelte.ts +87 -0
  83. package/src/lib/utils/toast.ts +60 -0
  84. package/src/routes/+layout.svelte +10 -0
  85. package/src/routes/+page.svelte +5 -0
  86. package/src/routes/layout.css +3 -0
  87. package/src/stories/Alert.stories.svelte +64 -0
  88. package/src/stories/Avatar.stories.svelte +76 -0
  89. package/src/stories/Badge.stories.svelte +76 -0
  90. package/src/stories/Breadcrumb.stories.svelte +64 -0
  91. package/src/stories/Button.stories.svelte +101 -0
  92. package/src/stories/Card.stories.svelte +106 -0
  93. package/src/stories/Checkbox.stories.svelte +77 -0
  94. package/src/stories/DataGrid.stories.svelte +130 -0
  95. package/src/stories/Dropdown.stories.svelte +81 -0
  96. package/src/stories/EmptyState.stories.svelte +74 -0
  97. package/src/stories/Input.stories.svelte +88 -0
  98. package/src/stories/Logo.stories.svelte +82 -0
  99. package/src/stories/Modal.stories.svelte +101 -0
  100. package/src/stories/Progress.stories.svelte +65 -0
  101. package/src/stories/Select.stories.svelte +158 -0
  102. package/src/stories/Tabs.stories.svelte +103 -0
  103. package/src/stories/Textarea.stories.svelte +45 -0
  104. package/src/stories/Toggle.stories.svelte +74 -0
  105. package/src/stories/Tooltip.stories.svelte +77 -0
  106. package/src/stories/Welcome.mdx +241 -0
  107. package/src/stories/assets/runwisp_c.svg +16 -0
  108. package/src/svelte-shims.d.ts +18 -0
@@ -0,0 +1,76 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Badge from "$lib/components/Badge.svelte";
7
+
8
+ const { Story } = defineMeta({
9
+ title: "Core/Badge",
10
+ component: Badge,
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ variant: {
14
+ control: "select",
15
+ options: ["default", "primary", "success", "warning", "danger", "info"],
16
+ },
17
+ size: {
18
+ control: "select",
19
+ options: ["sm", "md", "lg"],
20
+ },
21
+ },
22
+ });
23
+ </script>
24
+
25
+ <Story name="Default" args={{ variant: "default" }}>Default</Story>
26
+
27
+ <Story name="All Variants" asChild>
28
+ <div class="flex flex-wrap items-center gap-2">
29
+ <Badge variant="default">Default</Badge>
30
+ <Badge variant="primary">Primary</Badge>
31
+ <Badge variant="success">Success</Badge>
32
+ <Badge variant="warning">Warning</Badge>
33
+ <Badge variant="danger">Danger</Badge>
34
+ <Badge variant="info">Info</Badge>
35
+ </div>
36
+ </Story>
37
+
38
+ <Story name="Outline Variants" asChild>
39
+ <div class="flex flex-wrap items-center gap-2">
40
+ <Badge variant="default" outline>Default</Badge>
41
+ <Badge variant="primary" outline>Primary</Badge>
42
+ <Badge variant="success" outline>Success</Badge>
43
+ <Badge variant="warning" outline>Warning</Badge>
44
+ <Badge variant="danger" outline>Danger</Badge>
45
+ <Badge variant="info" outline>Info</Badge>
46
+ </div>
47
+ </Story>
48
+
49
+ <Story name="With Dot Indicator" asChild>
50
+ <div class="flex flex-wrap items-center gap-2">
51
+ <Badge variant="default" dot>Inactive</Badge>
52
+ <Badge variant="primary" dot>Scheduled</Badge>
53
+ <Badge variant="success" dot>Running</Badge>
54
+ <Badge variant="warning" dot>Pending</Badge>
55
+ <Badge variant="danger" dot>Failed</Badge>
56
+ <Badge variant="info" dot>Processing</Badge>
57
+ </div>
58
+ </Story>
59
+
60
+ <Story name="Sizes" asChild>
61
+ <div class="flex flex-wrap items-center gap-2">
62
+ <Badge size="sm" variant="primary">Small</Badge>
63
+ <Badge size="md" variant="primary">Medium</Badge>
64
+ <Badge size="lg" variant="primary">Large</Badge>
65
+ </div>
66
+ </Story>
67
+
68
+ <Story name="Task Status Example" asChild>
69
+ <div class="flex flex-wrap items-center gap-2">
70
+ <Badge variant="success" dot>Completed</Badge>
71
+ <Badge variant="primary" dot>Running</Badge>
72
+ <Badge variant="warning" dot>Queued</Badge>
73
+ <Badge variant="danger" dot>Failed</Badge>
74
+ <Badge variant="default" dot>Cancelled</Badge>
75
+ </div>
76
+ </Story>
@@ -0,0 +1,64 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Breadcrumb from "$lib/components/Breadcrumb.svelte";
7
+ import { House } from "@lucide/svelte";
8
+
9
+ const { Story } = defineMeta({
10
+ title: "Navigation/Breadcrumb",
11
+ component: Breadcrumb,
12
+ tags: ["autodocs"],
13
+ });
14
+ </script>
15
+
16
+ <Story
17
+ name="Default"
18
+ args={{
19
+ items: [
20
+ { label: "Dashboard", href: "/" },
21
+ { label: "Tasks", href: "/tasks" },
22
+ { label: "backup-database" },
23
+ ],
24
+ }}
25
+ />
26
+
27
+ <Story
28
+ name="With Home Icon"
29
+ args={{
30
+ items: [
31
+ { label: "Home", href: "/", icon: House },
32
+ { label: "Schedules", href: "/schedules" },
33
+ { label: "Create New" },
34
+ ],
35
+ }}
36
+ />
37
+
38
+ <Story
39
+ name="Long Path"
40
+ args={{
41
+ items: [
42
+ { label: "Home", href: "/" },
43
+ { label: "Projects", href: "/projects" },
44
+ { label: "RunWisp", href: "/projects/runwisp" },
45
+ { label: "Tasks", href: "/projects/runwisp/tasks" },
46
+ { label: "backup-database" },
47
+ ],
48
+ }}
49
+ />
50
+
51
+ <Story name="In Page Context" asChild>
52
+ <div class="rounded-xl border border-mist-200 bg-white p-6">
53
+ <Breadcrumb
54
+ items={[
55
+ { label: "Dashboard", href: "/" },
56
+ { label: "Tasks", href: "/tasks" },
57
+ { label: "backup-database" },
58
+ ]}
59
+ class="mb-4"
60
+ />
61
+ <h1 class="text-2xl font-semibold text-mist-900">backup-database</h1>
62
+ <p class="mt-1 text-mist-500">Daily database backup task</p>
63
+ </div>
64
+ </Story>
@@ -0,0 +1,101 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Button from "$lib/components/Button.svelte";
7
+ import { Play, Plus, ArrowRight, Download, Trash2 } from "@lucide/svelte";
8
+
9
+ const { Story } = defineMeta({
10
+ title: "Core/Button",
11
+ component: Button,
12
+ tags: ["autodocs"],
13
+ argTypes: {
14
+ variant: {
15
+ control: "select",
16
+ options: ["primary", "secondary", "ghost", "danger", "success"],
17
+ },
18
+ size: {
19
+ control: "select",
20
+ options: ["xs", "sm", "md", "lg"],
21
+ },
22
+ },
23
+ });
24
+ </script>
25
+
26
+ <Story name="Primary" args={{ variant: "primary" }}>Primary Button</Story>
27
+
28
+ <Story name="Secondary" args={{ variant: "secondary" }}>Secondary Button</Story>
29
+
30
+ <Story name="Ghost" args={{ variant: "ghost" }}>Ghost Button</Story>
31
+
32
+ <Story name="Danger" args={{ variant: "danger" }}>Danger Button</Story>
33
+
34
+ <Story name="Success" args={{ variant: "success" }}>Success Button</Story>
35
+
36
+ <Story name="All Variants" asChild>
37
+ <div class="flex flex-wrap items-center gap-3">
38
+ <Button variant="primary">Primary</Button>
39
+ <Button variant="secondary">Secondary</Button>
40
+ <Button variant="ghost">Ghost</Button>
41
+ <Button variant="danger">Danger</Button>
42
+ <Button variant="success">Success</Button>
43
+ </div>
44
+ </Story>
45
+
46
+ <Story name="Sizes" asChild>
47
+ <div class="flex flex-wrap items-center gap-3">
48
+ <Button size="xs">Extra Small</Button>
49
+ <Button size="sm">Small</Button>
50
+ <Button size="md">Medium</Button>
51
+ <Button size="lg">Large</Button>
52
+ </div>
53
+ </Story>
54
+
55
+ <Story name="With Icons" asChild>
56
+ <div class="flex flex-wrap items-center gap-3">
57
+ <Button variant="primary">
58
+ {#snippet icon()}<Play size={16} />{/snippet}
59
+ Run Task
60
+ </Button>
61
+ <Button variant="secondary">
62
+ {#snippet icon()}<Plus size={16} />{/snippet}
63
+ Add Schedule
64
+ </Button>
65
+ <Button variant="ghost">
66
+ {#snippet iconRight()}<ArrowRight size={16} />{/snippet}
67
+ View Details
68
+ </Button>
69
+ <Button variant="primary">
70
+ {#snippet icon()}<Download size={16} />{/snippet}
71
+ Export
72
+ </Button>
73
+ <Button variant="danger">
74
+ {#snippet icon()}<Trash2 size={16} />{/snippet}
75
+ Delete
76
+ </Button>
77
+ </div>
78
+ </Story>
79
+
80
+ <Story name="Loading State" asChild>
81
+ <div class="flex flex-wrap items-center gap-3">
82
+ <Button variant="primary" loading>Loading...</Button>
83
+ <Button variant="secondary" loading>Processing</Button>
84
+ <Button variant="danger" loading>Deleting</Button>
85
+ </div>
86
+ </Story>
87
+
88
+ <Story name="Disabled" asChild>
89
+ <div class="flex flex-wrap items-center gap-3">
90
+ <Button variant="primary" disabled>Disabled Primary</Button>
91
+ <Button variant="secondary" disabled>Disabled Secondary</Button>
92
+ <Button variant="ghost" disabled>Disabled Ghost</Button>
93
+ </div>
94
+ </Story>
95
+
96
+ <Story name="Full Width" asChild>
97
+ <div class="max-w-sm space-y-3">
98
+ <Button variant="primary" fullWidth>Full Width Primary</Button>
99
+ <Button variant="secondary" fullWidth>Full Width Secondary</Button>
100
+ </div>
101
+ </Story>
@@ -0,0 +1,106 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Card from "$lib/components/Card.svelte";
7
+ import Button from "$lib/components/Button.svelte";
8
+ import Badge from "$lib/components/Badge.svelte";
9
+
10
+ const { Story } = defineMeta({
11
+ title: "Core/Card",
12
+ component: Card,
13
+ tags: ["autodocs"],
14
+ argTypes: {
15
+ padding: {
16
+ control: "select",
17
+ options: ["none", "sm", "md", "lg"],
18
+ },
19
+ shadow: {
20
+ control: "select",
21
+ options: ["none", "sm", "md", "lg"],
22
+ },
23
+ },
24
+ });
25
+ </script>
26
+
27
+ <Story name="Default" args={{}}>
28
+ <h3 class="mb-2 text-lg font-semibold text-mist-900">Card Title</h3>
29
+ <p class="text-mist-600">This is a basic card component with default padding and styling.</p>
30
+ </Story>
31
+
32
+ <Story name="With Header and Footer" asChild>
33
+ <Card>
34
+ {#snippet header()}
35
+ <div class="flex items-center justify-between">
36
+ <h3 class="font-semibold text-mist-900">Task Configuration</h3>
37
+ <Badge variant="success" dot>Active</Badge>
38
+ </div>
39
+ {/snippet}
40
+
41
+ <div class="space-y-3">
42
+ <p class="text-sm text-mist-600">
43
+ Configure your scheduled task settings and execution parameters.
44
+ </p>
45
+ <div class="text-sm">
46
+ <span class="text-mist-500">Schedule:</span>
47
+ <span class="ml-2 font-mono text-mist-800">*/5 * * * *</span>
48
+ </div>
49
+ </div>
50
+
51
+ {#snippet footer()}
52
+ <div class="flex justify-end gap-2">
53
+ <Button variant="ghost" size="sm">Cancel</Button>
54
+ <Button variant="primary" size="sm">Save Changes</Button>
55
+ </div>
56
+ {/snippet}
57
+ </Card>
58
+ </Story>
59
+
60
+ <Story name="Hoverable" asChild>
61
+ <div class="grid max-w-3xl grid-cols-3 gap-4">
62
+ <Card hover>
63
+ <h4 class="mb-1 font-semibold text-mist-900">Total Tasks</h4>
64
+ <p class="text-2xl font-bold text-wisp-600">156</p>
65
+ </Card>
66
+ <Card hover>
67
+ <h4 class="mb-1 font-semibold text-mist-900">Active</h4>
68
+ <p class="text-2xl font-bold text-success-600">142</p>
69
+ </Card>
70
+ <Card hover>
71
+ <h4 class="mb-1 font-semibold text-mist-900">Failed</h4>
72
+ <p class="text-2xl font-bold text-danger-600">3</p>
73
+ </Card>
74
+ </div>
75
+ </Story>
76
+
77
+ <Story name="Different Padding" asChild>
78
+ <div class="max-w-md space-y-4">
79
+ <Card padding="sm">
80
+ <p class="text-sm text-mist-600">Small padding card</p>
81
+ </Card>
82
+ <Card padding="md">
83
+ <p class="text-sm text-mist-600">Medium padding card (default)</p>
84
+ </Card>
85
+ <Card padding="lg">
86
+ <p class="text-sm text-mist-600">Large padding card</p>
87
+ </Card>
88
+ </div>
89
+ </Story>
90
+
91
+ <Story name="Different Shadows" asChild>
92
+ <div class="flex gap-4">
93
+ <Card shadow="none">
94
+ <p class="text-sm text-mist-600">No shadow</p>
95
+ </Card>
96
+ <Card shadow="sm">
97
+ <p class="text-sm text-mist-600">Small shadow</p>
98
+ </Card>
99
+ <Card shadow="md">
100
+ <p class="text-sm text-mist-600">Medium shadow</p>
101
+ </Card>
102
+ <Card shadow="lg">
103
+ <p class="text-sm text-mist-600">Large shadow</p>
104
+ </Card>
105
+ </div>
106
+ </Story>
@@ -0,0 +1,77 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Checkbox from "$lib/components/Checkbox.svelte";
7
+
8
+ const { Story } = defineMeta({
9
+ title: "Forms/Checkbox",
10
+ component: Checkbox,
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ size: {
14
+ control: "select",
15
+ options: ["sm", "md", "lg"],
16
+ },
17
+ },
18
+ });
19
+ </script>
20
+
21
+ <Story name="Default" />
22
+
23
+ <Story name="With Label" args={{ label: "Enable notifications" }} />
24
+
25
+ <Story
26
+ name="With Description"
27
+ args={{
28
+ label: "Email notifications",
29
+ description: "Receive email alerts when tasks fail or complete",
30
+ }}
31
+ />
32
+
33
+ <Story name="Checked" args={{ label: "Auto-retry failed tasks", checked: true }} />
34
+
35
+ <Story
36
+ name="Indeterminate"
37
+ args={{ label: "Select all tasks", indeterminate: true, checked: true }}
38
+ />
39
+
40
+ <Story name="Sizes" asChild>
41
+ <div class="space-y-4">
42
+ <Checkbox size="sm" label="Small checkbox" />
43
+ <Checkbox size="md" label="Medium checkbox (default)" />
44
+ <Checkbox size="lg" label="Large checkbox" />
45
+ </div>
46
+ </Story>
47
+
48
+ <Story name="Disabled" asChild>
49
+ <div class="space-y-4">
50
+ <Checkbox label="Unchecked disabled" disabled />
51
+ <Checkbox label="Checked disabled" checked disabled />
52
+ </div>
53
+ </Story>
54
+
55
+ <Story name="Settings Example" asChild>
56
+ <div class="max-w-md space-y-4 rounded-xl border border-mist-200 bg-white p-4">
57
+ <h3 class="font-semibold text-mist-900">Notification Preferences</h3>
58
+ <div class="space-y-3">
59
+ <Checkbox
60
+ label="Task completion alerts"
61
+ description="Get notified when scheduled tasks complete successfully"
62
+ checked
63
+ />
64
+ <Checkbox
65
+ label="Failure alerts"
66
+ description="Receive immediate notifications on task failures"
67
+ checked
68
+ />
69
+ <Checkbox label="Weekly digest" description="Weekly summary of all task executions" />
70
+ <Checkbox
71
+ label="Performance warnings"
72
+ description="Alert when task execution time exceeds threshold"
73
+ checked
74
+ />
75
+ </div>
76
+ </div>
77
+ </Story>
@@ -0,0 +1,130 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import DataGrid from "$lib/components/DataGrid.svelte";
7
+ import StatusIndicator from "$lib/components/StatusIndicator.svelte";
8
+ import Dropdown from "$lib/components/Dropdown.svelte";
9
+ import { Play, Pause, Trash2, SquarePen } from "@lucide/svelte";
10
+
11
+ const { Story } = defineMeta({
12
+ title: "Data/DataGrid",
13
+ component: DataGrid,
14
+ tags: ["autodocs"],
15
+ });
16
+
17
+ const columns = [
18
+ { key: "name", label: "Task Name", sortable: true },
19
+ { key: "schedule", label: "Schedule" },
20
+ { key: "lastRun", label: "Last Run", sortable: true },
21
+ { key: "status", label: "Status" },
22
+ { key: "duration", label: "Duration", align: /** @type {'right'} */ ("right") },
23
+ ];
24
+
25
+ const tasks = [
26
+ {
27
+ id: "1",
28
+ name: "backup-database",
29
+ schedule: "0 2 * * *",
30
+ lastRun: "2024-01-15 02:00",
31
+ status: "success",
32
+ duration: "45s",
33
+ },
34
+ {
35
+ id: "2",
36
+ name: "cleanup-logs",
37
+ schedule: "*/30 * * * *",
38
+ lastRun: "2024-01-15 10:30",
39
+ status: "running",
40
+ duration: "12s",
41
+ },
42
+ {
43
+ id: "3",
44
+ name: "sync-data",
45
+ schedule: "0 */4 * * *",
46
+ lastRun: "2024-01-15 08:00",
47
+ status: "failed",
48
+ duration: "2m 15s",
49
+ },
50
+ {
51
+ id: "4",
52
+ name: "generate-report",
53
+ schedule: "0 9 * * 1",
54
+ lastRun: "2024-01-08 09:00",
55
+ status: "success",
56
+ duration: "1m 30s",
57
+ },
58
+ {
59
+ id: "5",
60
+ name: "send-notifications",
61
+ schedule: "0 8 * * *",
62
+ lastRun: "2024-01-15 08:00",
63
+ status: "success",
64
+ duration: "8s",
65
+ },
66
+ ];
67
+
68
+ const menuItems = [
69
+ { label: "Edit", icon: SquarePen },
70
+ { label: "Run Now", icon: Play },
71
+ { label: "Pause", icon: Pause },
72
+ { divider: true },
73
+ { label: "Delete", icon: Trash2, danger: true },
74
+ ];
75
+ </script>
76
+
77
+ {#snippet statusCell(/** @type {any} */ row)}
78
+ <div class="inline-flex items-center">
79
+ <StatusIndicator status={row.status} size="sm" />
80
+ </div>
81
+ {/snippet}
82
+
83
+ {#snippet durationCell(/** @type {any} */ row)}
84
+ <span class="font-mono text-mist-700">{row.duration}</span>
85
+ {/snippet}
86
+
87
+ <Story name="Basic" args={{ columns, data: tasks }} />
88
+
89
+ <Story name="With Custom Rendering" asChild>
90
+ <DataGrid
91
+ columns={[
92
+ { key: "name", label: "Task Name", sortable: true },
93
+ { key: "schedule", label: "Schedule" },
94
+ { key: "lastRun", label: "Last Run", sortable: true },
95
+ { key: "status", label: "Status", render: statusCell },
96
+ {
97
+ key: "duration",
98
+ label: "Duration",
99
+ align: /** @type {'right'} */ ("right"),
100
+ render: durationCell,
101
+ },
102
+ ]}
103
+ data={tasks}
104
+ />
105
+ </Story>
106
+
107
+ <Story name="Selectable" args={{ columns, data: tasks, selectable: true }} />
108
+
109
+ <Story name="Sortable" args={{ columns, data: tasks, sortKey: "name", sortDirection: "asc" }} />
110
+
111
+ <Story
112
+ name="Filterable"
113
+ args={{ columns, data: tasks, filterable: true, filterPlaceholder: "Filter tasks…" }}
114
+ />
115
+
116
+ <Story name="Paginated" args={{ columns, data: tasks, paginate: true, pageSize: 2 }} />
117
+
118
+ <Story name="Striped" args={{ columns, data: tasks, striped: true }} />
119
+
120
+ <Story name="Compact" args={{ columns, data: tasks, compact: true }} />
121
+
122
+ <Story name="Empty State" args={{ columns, data: [], emptyMessage: "No scheduled tasks found" }} />
123
+
124
+ <Story name="With Row Actions" asChild>
125
+ <DataGrid {columns} data={tasks}>
126
+ {#snippet rowAction()}
127
+ <Dropdown items={menuItems} />
128
+ {/snippet}
129
+ </DataGrid>
130
+ </Story>
@@ -0,0 +1,81 @@
1
+ <!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+
4
+ <script module>
5
+ import { defineMeta } from "@storybook/addon-svelte-csf";
6
+ import Dropdown from "$lib/components/Dropdown.svelte";
7
+ import { Play, Pause, SquarePen, Copy, Trash2, Settings, ChevronDown } from "@lucide/svelte";
8
+
9
+ const { Story } = defineMeta({
10
+ title: "Core/Dropdown",
11
+ component: Dropdown,
12
+ tags: ["autodocs"],
13
+ argTypes: {
14
+ align: {
15
+ control: "select",
16
+ options: ["left", "right"],
17
+ },
18
+ },
19
+ });
20
+
21
+ const taskActions = [
22
+ { label: "Run Now", icon: Play, onClick: () => console.log("Run") },
23
+ { label: "Edit", icon: SquarePen, onClick: () => console.log("Edit") },
24
+ { label: "Duplicate", icon: Copy, onClick: () => console.log("Duplicate") },
25
+ { label: "Pause", icon: Pause, onClick: () => console.log("Pause") },
26
+ { divider: true },
27
+ { label: "Delete", icon: Trash2, danger: true, onClick: () => console.log("Delete") },
28
+ ];
29
+
30
+ const settingsMenu = [
31
+ { label: "Profile Settings", href: "/settings/profile" },
32
+ { label: "Team Settings", href: "/settings/team" },
33
+ { label: "Notifications", href: "/settings/notifications" },
34
+ { divider: true },
35
+ { label: "API Keys", href: "/settings/api" },
36
+ { label: "Billing", href: "/settings/billing" },
37
+ ];
38
+ </script>
39
+
40
+ <Story name="Default" args={{ items: taskActions }} />
41
+
42
+ <Story name="Custom Trigger" asChild>
43
+ <div class="flex justify-center py-8">
44
+ <Dropdown items={settingsMenu}>
45
+ {#snippet trigger()}
46
+ <div class="flex items-center gap-2">
47
+ <Settings size={18} />
48
+ <span class="text-sm">Settings</span>
49
+ <ChevronDown size={16} />
50
+ </div>
51
+ {/snippet}
52
+ </Dropdown>
53
+ </div>
54
+ </Story>
55
+
56
+ <Story name="Align Left" args={{ items: taskActions, align: "left" }} />
57
+
58
+ <Story
59
+ name="With Disabled Items"
60
+ args={{
61
+ items: [
62
+ { label: "Run Now", icon: Play },
63
+ { label: "Edit", icon: SquarePen },
64
+ { label: "Duplicate", icon: Copy, disabled: true },
65
+ { divider: true },
66
+ { label: "Delete", icon: Trash2, danger: true, disabled: true },
67
+ ],
68
+ }}
69
+ />
70
+
71
+ <Story name="In Context" asChild>
72
+ <div class="max-w-md rounded-xl border border-mist-200 bg-white p-4">
73
+ <div class="flex items-center justify-between">
74
+ <div>
75
+ <h3 class="font-semibold text-mist-900">backup-database</h3>
76
+ <p class="text-sm text-mist-500">Daily at 2:00 AM</p>
77
+ </div>
78
+ <Dropdown items={taskActions} />
79
+ </div>
80
+ </div>
81
+ </Story>