@microlight/core 0.10.0 → 0.11.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 (28) hide show
  1. package/dist/server/app/layout.js +2 -18
  2. package/dist/server/app/library/[[...f_path]]/ViewFolder.js +37 -66
  3. package/dist/server/app/monitoring/MonitoringDashboard.js +167 -215
  4. package/dist/server/app/tasks/[slug]/ViewTask.js +81 -173
  5. package/dist/server/app/tasks/[slug]/runs/[r_id]/ViewRun.js +68 -164
  6. package/dist/server/app/tasks/[slug]/runs/[r_id]/_components/DropdownActions/DropdownActions.js +19 -25
  7. package/dist/server/components/Link.js +6 -15
  8. package/dist/server/components/MLInput.js +19 -22
  9. package/dist/server/components/Navbar/Navbar.js +14 -51
  10. package/dist/server/components/Navbar/NavbarContainer.js +7 -20
  11. package/dist/server/components/PageHeader.js +22 -54
  12. package/dist/server/components/StatusChip.js +5 -5
  13. package/dist/server/components/ui/alert.js +61 -0
  14. package/dist/server/components/ui/badge.js +37 -0
  15. package/dist/server/components/ui/breadcrumb.js +82 -0
  16. package/dist/server/components/ui/button.js +65 -0
  17. package/dist/server/components/ui/card.js +81 -0
  18. package/dist/server/components/ui/dropdown-menu.js +222 -0
  19. package/dist/server/components/ui/input.js +21 -0
  20. package/dist/server/components/ui/label.js +20 -0
  21. package/dist/server/components/ui/select.js +165 -0
  22. package/dist/server/components/ui/stack.js +104 -0
  23. package/dist/server/components/ui/table.js +77 -0
  24. package/dist/server/components/ui/tabs.js +59 -0
  25. package/dist/server/components/ui/typography.js +229 -0
  26. package/dist/server/utils/css/cn.js +11 -0
  27. package/package.json +15 -3
  28. package/dist/server/components/Icon.js +0 -22
@@ -0,0 +1,77 @@
1
+ import * as React from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../../utils/css/cn";
4
+ const tableVariants = cva("w-full caption-bottom text-sm", {
5
+ variants: {
6
+ variant: {
7
+ default: "",
8
+ compact: "[&_td]:py-2 [&_th]:py-2 [&_td]:px-2 [&_th]:px-2 [&_td]:text-sm [&_th]:text-xs"
9
+ }
10
+ },
11
+ defaultVariants: {
12
+ variant: "default"
13
+ }
14
+ });
15
+
16
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableElement> & { variant?: 'default' | 'compact' } & React.RefAttributes<HTMLTableElement>>} */
17
+ const Table = React.forwardRef(({
18
+ className,
19
+ variant,
20
+ ...props
21
+ }, ref) => <div className="relative w-full overflow-auto">
22
+ <table ref={ref} className={cn(tableVariants({
23
+ variant,
24
+ className
25
+ }))} {...props} />
26
+ </div>);
27
+ Table.displayName = "Table";
28
+
29
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>} */
30
+ const TableHeader = React.forwardRef(({
31
+ className,
32
+ ...props
33
+ }, ref) => <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />);
34
+ TableHeader.displayName = "TableHeader";
35
+
36
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>} */
37
+ const TableBody = React.forwardRef(({
38
+ className,
39
+ ...props
40
+ }, ref) => <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} />);
41
+ TableBody.displayName = "TableBody";
42
+
43
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>} */
44
+ const TableFooter = React.forwardRef(({
45
+ className,
46
+ ...props
47
+ }, ref) => <tfoot ref={ref} className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)} {...props} />);
48
+ TableFooter.displayName = "TableFooter";
49
+
50
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>} */
51
+ const TableRow = React.forwardRef(({
52
+ className,
53
+ ...props
54
+ }, ref) => <tr ref={ref} className={cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className)} {...props} />);
55
+ TableRow.displayName = "TableRow";
56
+
57
+ /** @type {React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>} */
58
+ const TableHead = React.forwardRef(({
59
+ className,
60
+ ...props
61
+ }, ref) => <th ref={ref} className={cn("h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className)} {...props} />);
62
+ TableHead.displayName = "TableHead";
63
+
64
+ /** @type {React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>} */
65
+ const TableCell = React.forwardRef(({
66
+ className,
67
+ ...props
68
+ }, ref) => <td ref={ref} className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)} {...props} />);
69
+ TableCell.displayName = "TableCell";
70
+
71
+ /** @type {React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>} */
72
+ const TableCaption = React.forwardRef(({
73
+ className,
74
+ ...props
75
+ }, ref) => <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />);
76
+ TableCaption.displayName = "TableCaption";
77
+ export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, tableVariants };
@@ -0,0 +1,59 @@
1
+ // @ts-check
2
+ "use client";
3
+
4
+ import * as React from "react";
5
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
6
+ import { cn } from "../../utils/css/cn";
7
+
8
+ /**
9
+ * @param {{
10
+ * className?: string
11
+ * } & React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>} props
12
+ * @returns {React.JSX.Element}
13
+ */
14
+ function Tabs({
15
+ className,
16
+ ...props
17
+ }) {
18
+ return <TabsPrimitive.Root data-slot="tabs" className={cn("flex flex-col gap-2", className)} {...props} />;
19
+ }
20
+
21
+ /**
22
+ * @param {{
23
+ * className?: string
24
+ * } & React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>} props
25
+ * @returns {React.JSX.Element}
26
+ */
27
+ function TabsList({
28
+ className,
29
+ ...props
30
+ }) {
31
+ return <TabsPrimitive.List data-slot="tabs-list" className={cn("bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]", className)} {...props} />;
32
+ }
33
+
34
+ /**
35
+ * @param {{
36
+ * className?: string
37
+ * } & React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>} props
38
+ * @returns {React.JSX.Element}
39
+ */
40
+ function TabsTrigger({
41
+ className,
42
+ ...props
43
+ }) {
44
+ return <TabsPrimitive.Trigger data-slot="tabs-trigger" className={cn("data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className)} {...props} />;
45
+ }
46
+
47
+ /**
48
+ * @param {{
49
+ * className?: string
50
+ * } & React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>} props
51
+ * @returns {React.JSX.Element}
52
+ */
53
+ function TabsContent({
54
+ className,
55
+ ...props
56
+ }) {
57
+ return <TabsPrimitive.Content data-slot="tabs-content" className={cn("flex-1 outline-none", className)} {...props} />;
58
+ }
59
+ export { Tabs, TabsList, TabsTrigger, TabsContent };
@@ -0,0 +1,229 @@
1
+ import * as React from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../../utils/css/cn";
4
+ const typographyVariants = cva("",
5
+ // base styles
6
+ {
7
+ variants: {
8
+ variant: {
9
+ // Headings
10
+ h1: "scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl",
11
+ h2: "scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0",
12
+ h3: "scroll-m-20 text-2xl font-semibold tracking-tight",
13
+ h4: "scroll-m-20 text-xl font-semibold tracking-tight",
14
+ // Title variants (from MUI Joy mapping)
15
+ "title-lg": "text-lg font-semibold leading-tight",
16
+ "title-md": "text-base font-medium leading-tight",
17
+ "title-sm": "text-sm font-medium leading-tight",
18
+ // Body text variants
19
+ "body-lg": "text-lg leading-7",
20
+ "body-md": "text-base leading-7",
21
+ "body-sm": "text-sm leading-6",
22
+ "body-xs": "text-xs leading-5",
23
+ // Special variants
24
+ lead: "text-xl text-muted-foreground",
25
+ large: "text-lg font-semibold",
26
+ small: "text-sm font-medium leading-none",
27
+ muted: "text-sm text-muted-foreground"
28
+ },
29
+ color: {
30
+ default: "",
31
+ muted: "text-muted-foreground",
32
+ success: "text-green-600",
33
+ warning: "text-yellow-600",
34
+ danger: "text-red-600",
35
+ primary: "text-primary",
36
+ neutral: "text-gray-600"
37
+ },
38
+ weight: {
39
+ normal: "font-normal",
40
+ medium: "font-medium",
41
+ semibold: "font-semibold",
42
+ bold: "font-bold",
43
+ extrabold: "font-extrabold"
44
+ },
45
+ align: {
46
+ left: "text-left",
47
+ center: "text-center",
48
+ right: "text-right",
49
+ justify: "text-justify"
50
+ }
51
+ },
52
+ defaultVariants: {
53
+ variant: "body-md",
54
+ color: "default"
55
+ }
56
+ });
57
+
58
+ /**
59
+ * @typedef {Object} TypographyOwnProps
60
+ * @property {React.ElementType} [as] - The component to render
61
+ * @property {'h1' | 'h2' | 'h3' | 'h4' | 'title-lg' | 'title-md' | 'title-sm' | 'body-lg' | 'body-md' | 'body-sm' | 'body-xs'} [level] - Legacy MUI Joy level prop
62
+ * @property {React.ElementType} [component] - Legacy MUI Joy component prop
63
+ * @property {string} [className] - Custom className
64
+ * @property {React.ReactNode} [children] - Children content
65
+ * @property {'sm' | 'md' | 'lg' | 'xl'} [fontSize] - Legacy MUI Joy fontSize prop
66
+ * @property {'normal' | 'medium' | 'lg' | 'bold'} [fontWeight] - Legacy MUI Joy fontWeight prop
67
+ * @property {React.ReactNode} [startDecorator] - Element to render at the start
68
+ * @property {React.ReactNode} [endDecorator] - Element to render at the end
69
+ * @property {boolean} [noWrap] - Prevents text wrapping
70
+ * @property {React.CSSProperties | Object} [sx] - Style object
71
+ * @property {string} [title] - HTML title attribute
72
+ * @property {string} [variant] - Typography variant
73
+ * @property {'default' | 'muted' | 'success' | 'warning' | 'danger' | 'primary' | 'neutral'} [color] - Text color
74
+ * @property {'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold'} [weight] - Font weight
75
+ * @property {'left' | 'center' | 'right' | 'justify'} [align] - Text alignment
76
+ */
77
+
78
+ /** @typedef {TypographyOwnProps} TypographyProps */
79
+
80
+ /**
81
+ * Get the default semantic element for a given variant/level
82
+ * @param {string | null} [variant]
83
+ * @param {string | null} [level]
84
+ * @returns {React.ElementType}
85
+ */
86
+ function getDefaultElement(variant, level) {
87
+ const target = level || variant;
88
+ switch (target) {
89
+ case "h1":
90
+ return "h1";
91
+ case "h2":
92
+ return "h2";
93
+ case "h3":
94
+ return "h3";
95
+ case "h4":
96
+ return "h4";
97
+ case "title-lg":
98
+ return "h2";
99
+ case "title-md":
100
+ return "h3";
101
+ case "title-sm":
102
+ return "h4";
103
+ case "lead":
104
+ return "p";
105
+ case "large":
106
+ return "div";
107
+ case "small":
108
+ return "small";
109
+ case "muted":
110
+ return "p";
111
+ default:
112
+ return "p";
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Convert legacy MUI Joy props to new variant system
118
+ * @param {TypographyProps} props
119
+ * @returns {string}
120
+ */
121
+ function getLegacyVariant(props) {
122
+ // Handle legacy level prop
123
+ if (props.level) {
124
+ return props.level;
125
+ }
126
+
127
+ // Handle legacy fontSize + fontWeight combination
128
+ if (props.fontSize && props.fontWeight) {
129
+ if (props.fontSize === "md" && props.fontWeight === "lg") return "title-sm";
130
+ if (props.fontSize === "lg" && props.fontWeight === "lg") return "title-md";
131
+ }
132
+
133
+ // Handle standalone fontSize
134
+ if (props.fontSize) {
135
+ switch (props.fontSize) {
136
+ case "sm":
137
+ return "body-sm";
138
+ case "md":
139
+ return "body-md";
140
+ case "lg":
141
+ return "body-lg";
142
+ case "xl":
143
+ return "title-lg";
144
+ }
145
+ }
146
+ return props.variant || "body-md";
147
+ }
148
+
149
+ /**
150
+ * Convert legacy fontWeight to weight prop
151
+ * @param {string} [fontWeight]
152
+ * @returns {'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold' | undefined}
153
+ */
154
+ function getLegacyWeight(fontWeight) {
155
+ switch (fontWeight) {
156
+ case "lg":
157
+ return "medium";
158
+ case "bold":
159
+ return "bold";
160
+ default:
161
+ return undefined;
162
+ }
163
+ }
164
+
165
+ /** @type {React.ForwardRefExoticComponent<TypographyProps & React.HTMLAttributes<HTMLElement> & React.RefAttributes<HTMLElement>>} */
166
+ const Typography = React.forwardRef(({
167
+ as,
168
+ component,
169
+ level,
170
+ variant: variantProp,
171
+ color,
172
+ weight: weightProp,
173
+ align,
174
+ className,
175
+ fontSize,
176
+ fontWeight,
177
+ startDecorator,
178
+ endDecorator,
179
+ noWrap,
180
+ sx,
181
+ title,
182
+ children,
183
+ ...props
184
+ }, ref) => {
185
+ // Handle legacy props
186
+ const variant = getLegacyVariant({
187
+ level,
188
+ variant: variantProp,
189
+ fontSize,
190
+ fontWeight
191
+ });
192
+ const weight = weightProp || getLegacyWeight(fontWeight);
193
+
194
+ // Determine the component to render
195
+ const Component = as || component || getDefaultElement(variant, level);
196
+
197
+ // Build className with noWrap support
198
+ const typographyClasses = cn(typographyVariants({
199
+ variant: variant,
200
+ color,
201
+ weight,
202
+ align
203
+ }), noWrap && "truncate whitespace-nowrap overflow-hidden", className);
204
+
205
+ // Handle sx prop by converting to inline styles (simplified approach)
206
+ const sxStyles = sx ? {
207
+ ...sx
208
+ } : undefined;
209
+
210
+ // If we have decorators, wrap in a flex container
211
+ if (startDecorator || endDecorator) {
212
+ return <Component className={cn("flex items-center gap-2", className)} style={sxStyles} title={noWrap ? title : undefined} ref={ref} {...props}>
213
+ {startDecorator && <span className="flex-shrink-0 flex items-center">
214
+ {startDecorator}
215
+ </span>}
216
+ <span className={typographyClasses}>
217
+ {children}
218
+ </span>
219
+ {endDecorator && <span className="flex-shrink-0 flex items-center">
220
+ {endDecorator}
221
+ </span>}
222
+ </Component>;
223
+ }
224
+ return <Component className={typographyClasses} style={sxStyles} title={noWrap ? title : undefined} ref={ref} {...props}>
225
+ {children}
226
+ </Component>;
227
+ });
228
+ Typography.displayName = "Typography";
229
+ export { Typography, typographyVariants };
@@ -0,0 +1,11 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ /**
5
+ * Merge Tailwind CSS classes with clsx
6
+ * @param {...any} inputs - Class names to merge
7
+ * @returns {string} Merged class names
8
+ */
9
+ export function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microlight/core",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -29,14 +29,23 @@
29
29
  "dependencies": {
30
30
  "@babel/generator": "^7.26.10",
31
31
  "@babel/parser": "^7.26.10",
32
- "@mui/joy": "^5.0.0-beta.51",
32
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
33
+ "@radix-ui/react-label": "^2.1.8",
34
+ "@radix-ui/react-progress": "^1.1.8",
35
+ "@radix-ui/react-select": "^2.2.6",
36
+ "@radix-ui/react-slot": "^1.2.4",
37
+ "@radix-ui/react-tabs": "^1.1.13",
38
+ "@tailwindcss/postcss": "^4.1.18",
33
39
  "@testing-library/jest-dom": "^6.6.4",
34
40
  "@testing-library/react": "^16.3.0",
35
41
  "async": "^3.2.6",
42
+ "class-variance-authority": "^0.7.1",
43
+ "clsx": "^2.1.1",
36
44
  "commander": "^13.1.0",
37
45
  "cronstrue": "^2.53.0",
38
46
  "glob": "^11.0.1",
39
47
  "lodash": "^4.17.21",
48
+ "lucide-react": "^0.562.0",
40
49
  "markdown-it": "^14.1.0",
41
50
  "next": "15.1.4",
42
51
  "next-nprogress-bar": "^2.4.3",
@@ -48,7 +57,10 @@
48
57
  "react-dom": "^19.0.0",
49
58
  "sequelize": "^6.37.5",
50
59
  "sqlite3": "^5.1.7",
51
- "switchless": "0.19.1"
60
+ "switchless": "0.19.1",
61
+ "tailwind-merge": "^3.4.0",
62
+ "tailwindcss": "^4.1.18",
63
+ "tw-animate-css": "^1.4.0"
52
64
  },
53
65
  "devDependencies": {
54
66
  "@babel/preset-env": "^7.28.0",
@@ -1,22 +0,0 @@
1
- /**
2
- * there is an issue with mui icons.
3
- * manually setting the icons.
4
- * the svgs of icons are picked up from fontawesome
5
- * https://fontawesome.com/search?ic=free
6
- */
7
- import React from 'react';
8
- import { AspectRatio } from '@mui/joy';
9
- export default function Icon({
10
- color,
11
- icon
12
- }) {
13
- return <>
14
- <AspectRatio ratio="1" sx={{
15
- width: 20
16
- }} variant="plain">
17
- {icon == 'send' && <svg fill={color} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M498.1 5.6c10.1 7 15.4 19.1 13.5 31.2l-64 416c-1.5 9.7-7.4 18.2-16 23s-18.9 5.4-28 1.6L284 427.7l-68.5 74.1c-8.9 9.7-22.9 12.9-35.2 8.1S160 493.2 160 480l0-83.6c0-4 1.5-7.8 4.2-10.8L331.8 202.8c5.8-6.3 5.6-16-.4-22s-15.7-6.4-22-.7L106 360.8 17.7 316.6C7.1 311.3 .3 300.7 0 288.9s5.9-22.8 16.1-28.7l448-256c10.7-6.1 23.9-5.5 34 1.4z" /></svg>}
18
- {icon == 'folder' && <svg fill={color} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M0 96C0 60.7 28.7 32 64 32l132.1 0c19.1 0 37.4 7.6 50.9 21.1L289.9 96 448 96c35.3 0 64 28.7 64 64l0 256c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96zM64 80c-8.8 0-16 7.2-16 16l0 320c0 8.8 7.2 16 16 16l384 0c8.8 0 16-7.2 16-16l0-256c0-8.8-7.2-16-16-16l-161.4 0c-10.6 0-20.8-4.2-28.3-11.7L213.1 87c-4.5-4.5-10.6-7-17-7L64 80z" /></svg>}
19
- {icon == 'ellipsis-vertical' && <svg fill={color} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z" /></svg>}
20
- </AspectRatio>
21
- </>;
22
- }