@mks2508/mks-ui 0.7.0 → 0.8.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 (109) hide show
  1. package/dist/css/primitives-DotMatrix-dot.css +364 -0
  2. package/dist/css/primitives-GooeyMorphingSurface-gooey.css +112 -0
  3. package/dist/css/ui-GooeyButton-gooey.css +43 -0
  4. package/dist/index.css +531 -0
  5. package/dist/react-ui/components/MorphingPopover/MorphingPopover.types.d.ts +8 -3
  6. package/dist/react-ui/components/MorphingPopover/MorphingPopover.types.d.ts.map +1 -1
  7. package/dist/react-ui/index.js +24 -1
  8. package/dist/react-ui/primitives/DotMatrix/DotMatrix.types.d.ts +109 -0
  9. package/dist/react-ui/primitives/DotMatrix/DotMatrix.types.d.ts.map +1 -0
  10. package/dist/react-ui/primitives/DotMatrix/dot-matrix.js +0 -0
  11. package/dist/react-ui/primitives/DotMatrix/dot.css +364 -0
  12. package/dist/react-ui/primitives/DotMatrix/index.d.ts +7 -0
  13. package/dist/react-ui/primitives/DotMatrix/index.d.ts.map +1 -0
  14. package/dist/react-ui/primitives/DotMatrix/index.js +185 -0
  15. package/dist/react-ui/primitives/DotMatrix/patterns.d.ts +32 -0
  16. package/dist/react-ui/primitives/DotMatrix/patterns.d.ts.map +1 -0
  17. package/dist/react-ui/primitives/DotMatrix/patterns.js +175 -0
  18. package/dist/react-ui/primitives/GooeyMorphingSurface/GooeyMorphingSurface.types.d.ts +100 -0
  19. package/dist/react-ui/primitives/GooeyMorphingSurface/GooeyMorphingSurface.types.d.ts.map +1 -0
  20. package/dist/react-ui/primitives/GooeyMorphingSurface/GooeyMorphingSurface.types.js +20 -0
  21. package/dist/react-ui/primitives/GooeyMorphingSurface/gooey-morphing-surface.js +0 -0
  22. package/dist/react-ui/primitives/GooeyMorphingSurface/gooey-morphing.css +112 -0
  23. package/dist/react-ui/primitives/GooeyMorphingSurface/index.d.ts +36 -0
  24. package/dist/react-ui/primitives/GooeyMorphingSurface/index.d.ts.map +1 -0
  25. package/dist/react-ui/primitives/GooeyMorphingSurface/index.js +141 -0
  26. package/dist/react-ui/primitives/index.d.ts +2 -0
  27. package/dist/react-ui/primitives/index.d.ts.map +1 -1
  28. package/dist/react-ui/primitives/index.js +4 -0
  29. package/dist/react-ui/ui/Badge/Badge.styles.d.ts +1 -1
  30. package/dist/react-ui/ui/Button/Button.styles.d.ts +1 -1
  31. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts +1 -1
  32. package/dist/react-ui/ui/FileIcon/FileIcon.styles.d.ts +25 -0
  33. package/dist/react-ui/ui/FileIcon/FileIcon.styles.d.ts.map +1 -0
  34. package/dist/react-ui/ui/FileIcon/FileIcon.styles.js +31 -0
  35. package/dist/react-ui/ui/FileIcon/FileIcon.types.d.ts +89 -0
  36. package/dist/react-ui/ui/FileIcon/FileIcon.types.d.ts.map +1 -0
  37. package/dist/react-ui/ui/FileIcon/index.d.ts +46 -0
  38. package/dist/react-ui/ui/FileIcon/index.d.ts.map +1 -0
  39. package/dist/react-ui/ui/FileIcon/index.js +138 -0
  40. package/dist/react-ui/ui/FileItem/FileItem.styles.d.ts +47 -0
  41. package/dist/react-ui/ui/FileItem/FileItem.styles.d.ts.map +1 -0
  42. package/dist/react-ui/ui/FileItem/FileItem.styles.js +60 -0
  43. package/dist/react-ui/ui/FileItem/FileItem.types.d.ts +84 -0
  44. package/dist/react-ui/ui/FileItem/FileItem.types.d.ts.map +1 -0
  45. package/dist/react-ui/ui/FileItem/index.d.ts +48 -0
  46. package/dist/react-ui/ui/FileItem/index.d.ts.map +1 -0
  47. package/dist/react-ui/ui/FileItem/index.js +124 -0
  48. package/dist/react-ui/ui/FilePanel/FilePanel.styles.d.ts +34 -0
  49. package/dist/react-ui/ui/FilePanel/FilePanel.styles.d.ts.map +1 -0
  50. package/dist/react-ui/ui/FilePanel/FilePanel.styles.js +57 -0
  51. package/dist/react-ui/ui/FilePanel/FilePanel.types.d.ts +55 -0
  52. package/dist/react-ui/ui/FilePanel/FilePanel.types.d.ts.map +1 -0
  53. package/dist/react-ui/ui/FilePanel/index.d.ts +55 -0
  54. package/dist/react-ui/ui/FilePanel/index.d.ts.map +1 -0
  55. package/dist/react-ui/ui/FilePanel/index.js +107 -0
  56. package/dist/react-ui/ui/FileTree/FileTree.styles.d.ts +31 -0
  57. package/dist/react-ui/ui/FileTree/FileTree.styles.d.ts.map +1 -0
  58. package/dist/react-ui/ui/FileTree/FileTree.styles.js +45 -0
  59. package/dist/react-ui/ui/FileTree/FileTree.types.d.ts +95 -0
  60. package/dist/react-ui/ui/FileTree/FileTree.types.d.ts.map +1 -0
  61. package/dist/react-ui/ui/FileTree/index.d.ts +60 -0
  62. package/dist/react-ui/ui/FileTree/index.d.ts.map +1 -0
  63. package/dist/react-ui/ui/FileTree/index.js +226 -0
  64. package/dist/react-ui/ui/GooeyButton/GooeyButton.types.d.ts +35 -0
  65. package/dist/react-ui/ui/GooeyButton/GooeyButton.types.d.ts.map +1 -0
  66. package/dist/react-ui/ui/GooeyButton/gooey-button.js +0 -0
  67. package/dist/react-ui/ui/GooeyButton/gooey.css +43 -0
  68. package/dist/react-ui/ui/GooeyButton/index.d.ts +26 -0
  69. package/dist/react-ui/ui/GooeyButton/index.d.ts.map +1 -0
  70. package/dist/react-ui/ui/GooeyButton/index.js +109 -0
  71. package/dist/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.styles.d.ts +23 -0
  72. package/dist/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.styles.d.ts.map +1 -0
  73. package/dist/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.styles.js +32 -0
  74. package/dist/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.types.d.ts +43 -0
  75. package/dist/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.types.d.ts.map +1 -0
  76. package/dist/react-ui/ui/MiddleTruncatePath/index.d.ts +33 -0
  77. package/dist/react-ui/ui/MiddleTruncatePath/index.d.ts.map +1 -0
  78. package/dist/react-ui/ui/MiddleTruncatePath/index.js +60 -0
  79. package/dist/react-ui/ui/OperationCard/OperationCard.context.d.ts +17 -0
  80. package/dist/react-ui/ui/OperationCard/OperationCard.context.d.ts.map +1 -0
  81. package/dist/react-ui/ui/OperationCard/OperationCard.context.js +27 -0
  82. package/dist/react-ui/ui/OperationCard/OperationCard.styles.d.ts +19 -0
  83. package/dist/react-ui/ui/OperationCard/OperationCard.styles.d.ts.map +1 -0
  84. package/dist/react-ui/ui/OperationCard/OperationCard.styles.js +39 -0
  85. package/dist/react-ui/ui/OperationCard/OperationCard.types.d.ts +188 -0
  86. package/dist/react-ui/ui/OperationCard/OperationCard.types.d.ts.map +1 -0
  87. package/dist/react-ui/ui/OperationCard/index.d.ts +45 -0
  88. package/dist/react-ui/ui/OperationCard/index.d.ts.map +1 -0
  89. package/dist/react-ui/ui/OperationCard/index.js +118 -0
  90. package/dist/react-ui/ui/OperationCard/parts/OperationCardActions.d.ts +3 -0
  91. package/dist/react-ui/ui/OperationCard/parts/OperationCardActions.d.ts.map +1 -0
  92. package/dist/react-ui/ui/OperationCard/parts/OperationCardActions.js +86 -0
  93. package/dist/react-ui/ui/OperationCard/parts/OperationCardHeader.d.ts +14 -0
  94. package/dist/react-ui/ui/OperationCard/parts/OperationCardHeader.d.ts.map +1 -0
  95. package/dist/react-ui/ui/OperationCard/parts/OperationCardHeader.js +62 -0
  96. package/dist/react-ui/ui/OperationCard/parts/OperationCardProgress.d.ts +3 -0
  97. package/dist/react-ui/ui/OperationCard/parts/OperationCardProgress.d.ts.map +1 -0
  98. package/dist/react-ui/ui/OperationCard/parts/OperationCardProgress.js +37 -0
  99. package/dist/react-ui/ui/OperationCard/parts/OperationCardStats.d.ts +3 -0
  100. package/dist/react-ui/ui/OperationCard/parts/OperationCardStats.d.ts.map +1 -0
  101. package/dist/react-ui/ui/OperationCard/parts/OperationCardStats.js +42 -0
  102. package/dist/react-ui/ui/OperationCard/parts/OperationCardVisualizer.d.ts +3 -0
  103. package/dist/react-ui/ui/OperationCard/parts/OperationCardVisualizer.d.ts.map +1 -0
  104. package/dist/react-ui/ui/OperationCard/parts/OperationCardVisualizer.js +53 -0
  105. package/dist/react-ui/ui/Tabs/Tabs.styles.d.ts +3 -3
  106. package/dist/react-ui/ui/index.d.ts +7 -0
  107. package/dist/react-ui/ui/index.d.ts.map +1 -1
  108. package/dist/react-ui/ui/index.js +19 -0
  109. package/package.json +1 -1
@@ -0,0 +1,124 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../lib/utils.js";
4
+ import { FileIcon } from "../FileIcon/index.js";
5
+ import { MiddleTruncatePath } from "../MiddleTruncatePath/index.js";
6
+ import { FileItemGitStatusClasses, FileItemStyles, fileItemVariants } from "./FileItem.styles.js";
7
+ import { memo, useCallback } from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+
10
+ //#region src/react-ui/ui/FileItem/index.tsx
11
+ /**
12
+ * FileItem — compact file-row primitive (icon + path + modified-chip + boost).
13
+ *
14
+ * Trimmed port of `mks-mission-control`'s FileItem: git-status dots,
15
+ * staging, discard flow, context menu and multi-select were all stripped.
16
+ * This is the row shape expected by mention menus, file pickers and
17
+ * simple file lists.
18
+ *
19
+ * Layout (compact, 28px row):
20
+ * [icon] [path — middle truncated] [modified-chip?] [⭐?]
21
+ *
22
+ * Keyboard: `role="option"`, `tabIndex=0`, Enter/Space fires `onSelect`.
23
+ *
24
+ * @module @mks2508/mks-ui/react/ui/FileItem
25
+ */
26
+ /** Very small relative-time formatter ("3m ago", "4h ago", "2d ago"). */
27
+ function formatRelative(now, then) {
28
+ const diff = Math.max(0, now - then);
29
+ const s = Math.floor(diff / 1e3);
30
+ if (s < 60) return `${s}s ago`;
31
+ const m = Math.floor(s / 60);
32
+ if (m < 60) return `${m}m ago`;
33
+ const h = Math.floor(m / 60);
34
+ if (h < 24) return `${h}h ago`;
35
+ const d = Math.floor(h / 24);
36
+ if (d < 30) return `${d}d ago`;
37
+ const mo = Math.floor(d / 30);
38
+ if (mo < 12) return `${mo}mo ago`;
39
+ return `${Math.floor(mo / 12)}y ago`;
40
+ }
41
+ /**
42
+ * FileItem — single row rendering an icon, path, optional modified chip and boost star.
43
+ *
44
+ * @param density - Row density (`compact` 28px vs `comfortable` 32px)
45
+ * @param slots - Override Tailwind classes per visual slot
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * <FileItem
50
+ * path="src/components/Button/index.tsx"
51
+ * kind="file"
52
+ * modifiedAt={new Date()}
53
+ * isBoosted
54
+ * onSelect={() => console.log('picked')}
55
+ * />
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * // With slot overrides
61
+ * <FileItem
62
+ * path="src/App.tsx"
63
+ * kind="file"
64
+ * slots={{ root: 'rounded-md', boost: 'text-destructive' }}
65
+ * />
66
+ * ```
67
+ */
68
+ const FileItem = memo(function FileItem({ path, kind, modifiedAt, isBoosted = false, changeStatus, selected = false, onSelect, density = "compact", iconBasePath, iconResolve, className, tabIndex = 0, slots }) {
69
+ const filename = path.split("/").pop() ?? path;
70
+ const handleKeyDown = useCallback((e) => {
71
+ if (e.key === "Enter" || e.key === " ") {
72
+ e.preventDefault();
73
+ onSelect?.();
74
+ }
75
+ }, [onSelect]);
76
+ const handleClick = useCallback(() => {
77
+ onSelect?.();
78
+ }, [onSelect]);
79
+ const iconSize = density === "comfortable" ? 16 : 15;
80
+ return /* @__PURE__ */ jsxs("div", {
81
+ role: "option",
82
+ "aria-selected": selected,
83
+ tabIndex,
84
+ "data-active": selected || void 0,
85
+ "data-kind": kind,
86
+ onClick: handleClick,
87
+ onKeyDown: handleKeyDown,
88
+ className: cn(fileItemVariants({ density }), slots?.root, className),
89
+ children: [
90
+ /* @__PURE__ */ jsx(FileIcon, {
91
+ filename,
92
+ size: iconSize,
93
+ basePath: iconBasePath,
94
+ resolve: iconResolve,
95
+ className: cn(FileItemStyles.icon, slots?.icon)
96
+ }),
97
+ changeStatus && /* @__PURE__ */ jsx("span", {
98
+ "aria-label": `git: ${changeStatus}`,
99
+ title: `git: ${changeStatus}`,
100
+ "data-git-status": changeStatus,
101
+ className: cn(FileItemStyles.gitStatus, FileItemGitStatusClasses[changeStatus], slots?.gitStatus)
102
+ }),
103
+ /* @__PURE__ */ jsx(MiddleTruncatePath, {
104
+ path,
105
+ className: cn(FileItemStyles.path, slots?.path),
106
+ startClassName: "text-muted-foreground/60"
107
+ }),
108
+ modifiedAt && /* @__PURE__ */ jsx("span", {
109
+ className: cn(FileItemStyles.modifiedChip, slots?.modifiedChip),
110
+ title: modifiedAt.toISOString(),
111
+ children: formatRelative(Date.now(), modifiedAt.getTime())
112
+ }),
113
+ isBoosted && /* @__PURE__ */ jsx("span", {
114
+ "aria-label": "boosted",
115
+ title: "Boosted",
116
+ className: cn(FileItemStyles.boost, slots?.boost),
117
+ children: "★"
118
+ })
119
+ ]
120
+ });
121
+ });
122
+
123
+ //#endregion
124
+ export { FileItem };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Styles for FilePanel.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/FilePanel
5
+ */
6
+ import type { StyleSlots } from '../../../core/types';
7
+ /** Visual regions of the FilePanel component. */
8
+ export type FilePanelSlot = 'root' | 'header' | 'title' | 'toolbar' | 'search' | 'body' | 'footer' | 'status';
9
+ /**
10
+ * Default Tailwind classes for each FilePanel slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Outer panel frame |
15
+ * | `header` | Sticky header row (title + actions) |
16
+ * | `title` | Panel title text |
17
+ * | `toolbar` | Toolbar strip under the header (search input + chips) |
18
+ * | `search` | Search input slot wrapper |
19
+ * | `body` | Scrollable body that hosts the tree / children |
20
+ * | `footer` | Footer row |
21
+ * | `status` | Status text in the footer |
22
+ */
23
+ export declare const FilePanelStyles: StyleSlots<FilePanelSlot>;
24
+ /**
25
+ * CVA variants for the FilePanel root.
26
+ *
27
+ * Density variants adjust only padding; children (tree, search) pass
28
+ * their own density through their own props.
29
+ */
30
+ export declare const filePanelVariants: (props?: ({
31
+ density?: "compact" | "comfortable" | null | undefined;
32
+ bordered?: boolean | null | undefined;
33
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
34
+ //# sourceMappingURL=FilePanel.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePanel.styles.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FilePanel/FilePanel.styles.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,iDAAiD;AACjD,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,CAAC;AAEb;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,CAAC,aAAa,CAY5C,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;8EAe5B,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ //#region src/react-ui/ui/FilePanel/FilePanel.styles.ts
4
+ /**
5
+ * Styles for FilePanel.
6
+ *
7
+ * @module @mks2508/mks-ui/react/ui/FilePanel
8
+ */
9
+ /**
10
+ * Default Tailwind classes for each FilePanel slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Outer panel frame |
15
+ * | `header` | Sticky header row (title + actions) |
16
+ * | `title` | Panel title text |
17
+ * | `toolbar` | Toolbar strip under the header (search input + chips) |
18
+ * | `search` | Search input slot wrapper |
19
+ * | `body` | Scrollable body that hosts the tree / children |
20
+ * | `footer` | Footer row |
21
+ * | `status` | Status text in the footer |
22
+ */
23
+ const FilePanelStyles = {
24
+ root: "file-panel flex flex-col h-full w-full bg-card text-card-foreground border border-border rounded-lg overflow-hidden",
25
+ header: "shrink-0 flex items-center justify-between gap-2 px-3 h-9 border-b border-border bg-muted/30",
26
+ title: "text-xs font-semibold text-foreground truncate",
27
+ toolbar: "shrink-0 flex items-center gap-2 px-2 py-1.5 border-b border-border bg-background/40",
28
+ search: "flex-1 min-w-0",
29
+ body: "flex-1 min-h-0 overflow-y-auto",
30
+ footer: "shrink-0 flex items-center gap-2 px-3 h-7 border-t border-border bg-muted/20",
31
+ status: "text-[10px] font-mono text-muted-foreground/70 truncate"
32
+ };
33
+ /**
34
+ * CVA variants for the FilePanel root.
35
+ *
36
+ * Density variants adjust only padding; children (tree, search) pass
37
+ * their own density through their own props.
38
+ */
39
+ const filePanelVariants = cva(FilePanelStyles.root, {
40
+ variants: {
41
+ density: {
42
+ compact: "",
43
+ comfortable: ""
44
+ },
45
+ bordered: {
46
+ true: "",
47
+ false: "border-0 rounded-none"
48
+ }
49
+ },
50
+ defaultVariants: {
51
+ density: "compact",
52
+ bordered: true
53
+ }
54
+ });
55
+
56
+ //#endregion
57
+ export { FilePanelStyles, filePanelVariants };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Types for FilePanel.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/FilePanel
5
+ */
6
+ import type { ReactNode } from 'react';
7
+ import type { VariantProps } from 'class-variance-authority';
8
+ import type { SlotOverrides } from '../../../core/types';
9
+ import type { FilePanelSlot, filePanelVariants } from './FilePanel.styles';
10
+ /** Visual density for the panel frame. */
11
+ export type FilePanelDensity = NonNullable<VariantProps<typeof filePanelVariants>['density']>;
12
+ /**
13
+ * Props for FilePanel.
14
+ *
15
+ * FilePanel is a thin **frame**: header (title + actions), toolbar (search),
16
+ * body (tree or any children), and a footer (status). Each region is a slot
17
+ * so consumers compose the content — there is zero business logic here.
18
+ *
19
+ * @see {@link FilePanelSlot}
20
+ */
21
+ export interface IFilePanelProps extends Omit<VariantProps<typeof filePanelVariants>, 'density' | 'bordered'> {
22
+ /** Panel title rendered in the header. */
23
+ title?: ReactNode;
24
+ /** Optional trailing actions (buttons, chips) next to the title. */
25
+ actions?: ReactNode;
26
+ /** Search input slot content (e.g. an `<Input>`). Toolbar is hidden when both this and `toolbar` are absent. */
27
+ search?: ReactNode;
28
+ /** Arbitrary toolbar content rendered next to `search`. */
29
+ toolbar?: ReactNode;
30
+ /** Body content — typically a `<FileTree>` or custom children. */
31
+ children?: ReactNode;
32
+ /** Footer status content (e.g. node count, last refresh). */
33
+ status?: ReactNode;
34
+ /** Optional trailing footer actions. */
35
+ footerActions?: ReactNode;
36
+ /** Density — proxied to child primitives via the consumer. */
37
+ density?: FilePanelDensity;
38
+ /** Whether to render border + rounded frame. Default `true`. */
39
+ bordered?: boolean;
40
+ /** Optional CSS class merged onto the root. */
41
+ className?: string;
42
+ /**
43
+ * Override default Tailwind classes for specific visual regions.
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * <FilePanel
48
+ * title="Files"
49
+ * slots={{ header: 'bg-primary/10', body: 'p-1' }}
50
+ * />
51
+ * ```
52
+ */
53
+ slots?: SlotOverrides<FilePanelSlot>;
54
+ }
55
+ //# sourceMappingURL=FilePanel.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePanel.types.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FilePanel/FilePanel.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,0CAA0C;AAC1C,MAAM,MAAM,gBAAgB,GAAG,WAAW,CACxC,YAAY,CAAC,OAAO,iBAAiB,CAAC,CAAC,SAAS,CAAC,CAClD,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,YAAY,CAAC,OAAO,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAC5E,0CAA0C;IAC1C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gHAAgH;IAChH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,wCAAwC;IACxC,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;CACtC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * FilePanel — IDE-style file-panel frame (header + toolbar + body + footer).
3
+ *
4
+ * Thin frame primitive: no business logic, no data fetching. Each region is
5
+ * a slot so consumers compose what goes inside — typically a `<FileTree>`
6
+ * in the body and an `<Input>` in the search slot.
7
+ *
8
+ * Layout:
9
+ * ┌───────────────────────────────────┐
10
+ * │ header (title · actions) │ (sticky)
11
+ * ├───────────────────────────────────┤
12
+ * │ toolbar (search · extras) │ (optional)
13
+ * ├───────────────────────────────────┤
14
+ * │ │
15
+ * │ body (children — FileTree, etc.) │ (scrollable)
16
+ * │ │
17
+ * ├───────────────────────────────────┤
18
+ * │ footer (status · actions) │ (optional)
19
+ * └───────────────────────────────────┘
20
+ *
21
+ * @module @mks2508/mks-ui/react/ui/FilePanel
22
+ */
23
+ import type { IFilePanelProps } from './FilePanel.types';
24
+ /**
25
+ * FilePanel — frame around file-tree UI (header + toolbar + body + footer).
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <FilePanel
30
+ * title="Files"
31
+ * search={<Input placeholder="Filter..." />}
32
+ * status={`${count} files`}
33
+ * >
34
+ * <FileTree nodes={nodes} onSelect={onSelect} />
35
+ * </FilePanel>
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // Borderless, with trailing actions
41
+ * <FilePanel
42
+ * title="Project"
43
+ * actions={<Button size="sm">Refresh</Button>}
44
+ * bordered={false}
45
+ * slots={{ header: 'bg-primary/5' }}
46
+ * >
47
+ * {tree}
48
+ * </FilePanel>
49
+ * ```
50
+ */
51
+ export declare const FilePanel: import("react").MemoExoticComponent<({ title, actions, search, toolbar, children, status, footerActions, density, bordered, className, slots, }: IFilePanelProps) => import("react/jsx-runtime").JSX.Element>;
52
+ export { FilePanelStyles, filePanelVariants } from './FilePanel.styles';
53
+ export type { FilePanelSlot } from './FilePanel.styles';
54
+ export type { IFilePanelProps, FilePanelDensity } from './FilePanel.types';
55
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FilePanel/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,SAAS,mJAYnB,eAAe,6CAmDhB,CAAC;AAEH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,107 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../lib/utils.js";
4
+ import { FilePanelStyles, filePanelVariants } from "./FilePanel.styles.js";
5
+ import { memo } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+
8
+ //#region src/react-ui/ui/FilePanel/index.tsx
9
+ /**
10
+ * FilePanel — IDE-style file-panel frame (header + toolbar + body + footer).
11
+ *
12
+ * Thin frame primitive: no business logic, no data fetching. Each region is
13
+ * a slot so consumers compose what goes inside — typically a `<FileTree>`
14
+ * in the body and an `<Input>` in the search slot.
15
+ *
16
+ * Layout:
17
+ * ┌───────────────────────────────────┐
18
+ * │ header (title · actions) │ (sticky)
19
+ * ├───────────────────────────────────┤
20
+ * │ toolbar (search · extras) │ (optional)
21
+ * ├───────────────────────────────────┤
22
+ * │ │
23
+ * │ body (children — FileTree, etc.) │ (scrollable)
24
+ * │ │
25
+ * ├───────────────────────────────────┤
26
+ * │ footer (status · actions) │ (optional)
27
+ * └───────────────────────────────────┘
28
+ *
29
+ * @module @mks2508/mks-ui/react/ui/FilePanel
30
+ */
31
+ /**
32
+ * FilePanel — frame around file-tree UI (header + toolbar + body + footer).
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * <FilePanel
37
+ * title="Files"
38
+ * search={<Input placeholder="Filter..." />}
39
+ * status={`${count} files`}
40
+ * >
41
+ * <FileTree nodes={nodes} onSelect={onSelect} />
42
+ * </FilePanel>
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * // Borderless, with trailing actions
48
+ * <FilePanel
49
+ * title="Project"
50
+ * actions={<Button size="sm">Refresh</Button>}
51
+ * bordered={false}
52
+ * slots={{ header: 'bg-primary/5' }}
53
+ * >
54
+ * {tree}
55
+ * </FilePanel>
56
+ * ```
57
+ */
58
+ const FilePanel = memo(function FilePanel({ title, actions, search, toolbar, children, status, footerActions, density = "compact", bordered = true, className, slots }) {
59
+ const hasHeader = title !== void 0 || actions !== void 0;
60
+ const hasToolbar = search !== void 0 || toolbar !== void 0;
61
+ const hasFooter = status !== void 0 || footerActions !== void 0;
62
+ return /* @__PURE__ */ jsxs("div", {
63
+ className: cn(filePanelVariants({
64
+ density,
65
+ bordered
66
+ }), slots?.root, className),
67
+ children: [
68
+ hasHeader && /* @__PURE__ */ jsxs("div", {
69
+ className: cn(FilePanelStyles.header, slots?.header),
70
+ children: [/* @__PURE__ */ jsx("div", {
71
+ className: cn(FilePanelStyles.title, slots?.title),
72
+ children: title
73
+ }), actions && /* @__PURE__ */ jsx("div", {
74
+ className: "flex items-center gap-1 shrink-0",
75
+ children: actions
76
+ })]
77
+ }),
78
+ hasToolbar && /* @__PURE__ */ jsxs("div", {
79
+ className: cn(FilePanelStyles.toolbar, slots?.toolbar),
80
+ children: [search !== void 0 && /* @__PURE__ */ jsx("div", {
81
+ className: cn(FilePanelStyles.search, slots?.search),
82
+ children: search
83
+ }), toolbar && /* @__PURE__ */ jsx("div", {
84
+ className: "flex items-center gap-1 shrink-0",
85
+ children: toolbar
86
+ })]
87
+ }),
88
+ /* @__PURE__ */ jsx("div", {
89
+ className: cn(FilePanelStyles.body, slots?.body),
90
+ children
91
+ }),
92
+ hasFooter && /* @__PURE__ */ jsxs("div", {
93
+ className: cn(FilePanelStyles.footer, slots?.footer),
94
+ children: [/* @__PURE__ */ jsx("div", {
95
+ className: cn(FilePanelStyles.status, slots?.status),
96
+ children: status
97
+ }), footerActions && /* @__PURE__ */ jsx("div", {
98
+ className: "flex items-center gap-1 shrink-0 ml-auto",
99
+ children: footerActions
100
+ })]
101
+ })
102
+ ]
103
+ });
104
+ });
105
+
106
+ //#endregion
107
+ export { FilePanel };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Styles for FileTree.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/FileTree
5
+ */
6
+ import type { StyleSlots } from '../../../core/types';
7
+ /** Visual regions of the FileTree component. */
8
+ export type FileTreeSlot = 'root' | 'list' | 'node' | 'row' | 'indent' | 'chevron' | 'empty';
9
+ /**
10
+ * Default Tailwind classes for each FileTree slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Outer container (role="tree") |
15
+ * | `list` | Child list (`role="group"`) |
16
+ * | `node` | Single node wrapper (row + children) |
17
+ * | `row` | Row line holding indent guides + chevron + FileItem |
18
+ * | `indent` | Leading indent spacer per depth level |
19
+ * | `chevron` | Expand/collapse glyph for directories |
20
+ * | `empty` | "No files" placeholder |
21
+ */
22
+ export declare const FileTreeStyles: StyleSlots<FileTreeSlot>;
23
+ /**
24
+ * CVA variants for the FileTree root.
25
+ *
26
+ * Density variants map to the underlying `FileItem` density so rows align.
27
+ */
28
+ export declare const fileTreeVariants: (props?: ({
29
+ density?: "compact" | "comfortable" | null | undefined;
30
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
31
+ //# sourceMappingURL=FileTree.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTree.styles.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FileTree/FileTree.styles.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,gDAAgD;AAChD,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,MAAM,GACN,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,OAAO,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,EAAE,UAAU,CAAC,YAAY,CAS1C,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;8EAU3B,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ //#region src/react-ui/ui/FileTree/FileTree.styles.ts
4
+ /**
5
+ * Styles for FileTree.
6
+ *
7
+ * @module @mks2508/mks-ui/react/ui/FileTree
8
+ */
9
+ /**
10
+ * Default Tailwind classes for each FileTree slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Outer container (role="tree") |
15
+ * | `list` | Child list (`role="group"`) |
16
+ * | `node` | Single node wrapper (row + children) |
17
+ * | `row` | Row line holding indent guides + chevron + FileItem |
18
+ * | `indent` | Leading indent spacer per depth level |
19
+ * | `chevron` | Expand/collapse glyph for directories |
20
+ * | `empty` | "No files" placeholder |
21
+ */
22
+ const FileTreeStyles = {
23
+ root: "file-tree flex flex-col w-full text-foreground",
24
+ list: "flex flex-col",
25
+ node: "flex flex-col",
26
+ row: "flex items-center w-full",
27
+ indent: "shrink-0 h-full",
28
+ chevron: "shrink-0 inline-flex items-center justify-center size-4 text-muted-foreground/70 hover:text-foreground transition-transform duration-100",
29
+ empty: "px-3 py-2 text-xs font-mono text-muted-foreground/60"
30
+ };
31
+ /**
32
+ * CVA variants for the FileTree root.
33
+ *
34
+ * Density variants map to the underlying `FileItem` density so rows align.
35
+ */
36
+ const fileTreeVariants = cva(FileTreeStyles.root, {
37
+ variants: { density: {
38
+ compact: "",
39
+ comfortable: ""
40
+ } },
41
+ defaultVariants: { density: "compact" }
42
+ });
43
+
44
+ //#endregion
45
+ export { FileTreeStyles, fileTreeVariants };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Types for FileTree.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/FileTree
5
+ */
6
+ import type { VariantProps } from 'class-variance-authority';
7
+ import type { SlotOverrides } from '../../../core/types';
8
+ import type { FileIconResolver } from '../FileIcon/FileIcon.types';
9
+ import type { FileItemChangeStatus } from '../FileItem/FileItem.types';
10
+ import type { FileTreeSlot, fileTreeVariants } from './FileTree.styles';
11
+ /** What kind of filesystem entry a tree node represents. */
12
+ export type FileTreeNodeKind = 'file' | 'dir';
13
+ /**
14
+ * A single node in a file tree.
15
+ *
16
+ * Nodes are identified by `id` (typically the relative path). Directories
17
+ * may have `children` eagerly populated, or `null`/`undefined` to indicate
18
+ * unloaded children that will be fetched lazily via `onToggle`.
19
+ */
20
+ export interface IFileTreeNode {
21
+ /** Stable identifier — usually the relpath. */
22
+ id: string;
23
+ /** Display name (usually basename). */
24
+ name: string;
25
+ /** Full path relative to root (shown in `FileItem`). */
26
+ path: string;
27
+ /** File or directory. */
28
+ kind: FileTreeNodeKind;
29
+ /** Last-modified timestamp (rendered as trailing chip on the row). */
30
+ modifiedAt?: Date;
31
+ /** Whether this node is boosted (⭐ on the row). */
32
+ isBoosted?: boolean;
33
+ /** Optional git change status — proxied to the underlying `FileItem`. */
34
+ changeStatus?: FileItemChangeStatus | null;
35
+ /**
36
+ * Children for directories.
37
+ * - `undefined` → unloaded (will request on expand)
38
+ * - `[]` → loaded, empty
39
+ * - `IFileTreeNode[]` → loaded with entries
40
+ */
41
+ children?: IFileTreeNode[];
42
+ }
43
+ /** Visual density, proxied to `FileItem`. */
44
+ export type FileTreeDensity = NonNullable<VariantProps<typeof fileTreeVariants>['density']>;
45
+ /**
46
+ * Props for FileTree.
47
+ *
48
+ * @see {@link FileTreeSlot}
49
+ */
50
+ export interface IFileTreeProps extends Omit<VariantProps<typeof fileTreeVariants>, 'density'> {
51
+ /** Root nodes to render. */
52
+ nodes: IFileTreeNode[];
53
+ /** Fired when a file row is activated (Enter / click on file). */
54
+ onSelect?: (node: IFileTreeNode) => void;
55
+ /**
56
+ * Fired when a directory is expanded or collapsed.
57
+ *
58
+ * Called with the node and the next-expanded state. Useful for lazy-loading
59
+ * children — consumers can fetch children and push them into `nodes`.
60
+ */
61
+ onToggle?: (node: IFileTreeNode, expanded: boolean) => void;
62
+ /**
63
+ * Controlled expanded-ids. If provided, the tree is controlled and
64
+ * `onToggle` is expected to update this set upstream.
65
+ * If omitted, the tree manages its own expand state internally.
66
+ */
67
+ expandedIds?: ReadonlySet<string> | readonly string[];
68
+ /** Controlled selected id. Highlights the matching row. */
69
+ selectedId?: string;
70
+ /** Row density (proxied to `FileItem`). Default `"compact"`. */
71
+ density?: FileTreeDensity;
72
+ /** Icon base path passed to inner `FileItem` rows. */
73
+ iconBasePath?: string;
74
+ /** Custom file-icon resolver passed to inner `FileItem` rows. */
75
+ iconResolve?: FileIconResolver;
76
+ /** Indent width in px per depth level. Default `12`. */
77
+ indentPx?: number;
78
+ /** Empty-state text shown when `nodes` is empty. Default `"No files"`. */
79
+ emptyLabel?: string;
80
+ /** Optional CSS class merged onto the root. */
81
+ className?: string;
82
+ /**
83
+ * Override default Tailwind classes for specific visual regions.
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <FileTree
88
+ * nodes={tree}
89
+ * slots={{ chevron: 'text-primary', row: 'rounded-md' }}
90
+ * />
91
+ * ```
92
+ */
93
+ slots?: SlotOverrides<FileTreeSlot>;
94
+ }
95
+ //# sourceMappingURL=FileTree.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTree.types.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FileTree/FileTree.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExE,4DAA4D;AAC5D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,gBAAgB,CAAC;IACvB,sEAAsE;IACtE,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yEAAyE;IACzE,YAAY,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG,WAAW,CACvC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,SAAS,CAAC,CACjD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC9D,4BAA4B;IAC5B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,MAAM,EAAE,CAAC;IACtD,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACrC"}