@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,60 @@
1
+ /**
2
+ * FileTree — collapsible tree renderer over `FileItem` rows.
3
+ *
4
+ * Lightweight tree over the `FileItem` primitive. Directories render a
5
+ * chevron that toggles expansion; files act as leaves. Supports either
6
+ * uncontrolled expansion (internal state) or controlled via `expandedIds`
7
+ * + `onToggle` (useful for lazy-loading children).
8
+ *
9
+ * Keyboard: rows are reachable via Tab (inherited from `FileItem`). Enter/
10
+ * Space on a file fires `onSelect`; Enter/Space on a dir toggles expansion.
11
+ * ArrowRight expands a dir, ArrowLeft collapses it.
12
+ *
13
+ * @module @mks2508/mks-ui/react/ui/FileTree
14
+ */
15
+ import type { IFileTreeProps } from './FileTree.types';
16
+ /**
17
+ * FileTree — tree of `FileItem` rows with expand/collapse.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <FileTree
22
+ * nodes={[
23
+ * {
24
+ * id: 'src',
25
+ * name: 'src',
26
+ * path: 'src',
27
+ * kind: 'dir',
28
+ * children: [
29
+ * { id: 'src/App.tsx', name: 'App.tsx', path: 'src/App.tsx', kind: 'file' },
30
+ * ],
31
+ * },
32
+ * ]}
33
+ * onSelect={(n) => console.log('selected', n.path)}
34
+ * onToggle={(n, exp) => console.log('toggled', n.path, exp)}
35
+ * />
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // Controlled expansion for lazy loading
41
+ * const [expanded, setExpanded] = useState<Set<string>>(new Set());
42
+ * <FileTree
43
+ * nodes={nodes}
44
+ * expandedIds={expanded}
45
+ * onToggle={(n, exp) => {
46
+ * setExpanded((prev) => {
47
+ * const next = new Set(prev);
48
+ * if (exp) next.add(n.id); else next.delete(n.id);
49
+ * return next;
50
+ * });
51
+ * if (exp && !n.children) loadChildren(n);
52
+ * }}
53
+ * />
54
+ * ```
55
+ */
56
+ export declare const FileTree: import("react").MemoExoticComponent<({ nodes, onSelect, onToggle, expandedIds, selectedId, density, iconBasePath, iconResolve, indentPx, emptyLabel, className, slots, }: IFileTreeProps) => import("react/jsx-runtime").JSX.Element>;
57
+ export { FileTreeStyles, fileTreeVariants } from './FileTree.styles';
58
+ export type { FileTreeSlot } from './FileTree.styles';
59
+ export type { IFileTreeProps, IFileTreeNode, FileTreeNodeKind, FileTreeDensity, } from './FileTree.types';
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/FileTree/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,OAAO,KAAK,EAEV,cAAc,EACf,MAAM,kBAAkB,CAAC;AAkK1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,QAAQ,4KAalB,cAAc,6CAsEf,CAAC;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,226 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../lib/utils.js";
4
+ import { FileItem } from "../FileItem/index.js";
5
+ import { FileTreeStyles, fileTreeVariants } from "./FileTree.styles.js";
6
+ import { memo, useCallback, useMemo, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+
9
+ //#region src/react-ui/ui/FileTree/index.tsx
10
+ /**
11
+ * FileTree — collapsible tree renderer over `FileItem` rows.
12
+ *
13
+ * Lightweight tree over the `FileItem` primitive. Directories render a
14
+ * chevron that toggles expansion; files act as leaves. Supports either
15
+ * uncontrolled expansion (internal state) or controlled via `expandedIds`
16
+ * + `onToggle` (useful for lazy-loading children).
17
+ *
18
+ * Keyboard: rows are reachable via Tab (inherited from `FileItem`). Enter/
19
+ * Space on a file fires `onSelect`; Enter/Space on a dir toggles expansion.
20
+ * ArrowRight expands a dir, ArrowLeft collapses it.
21
+ *
22
+ * @module @mks2508/mks-ui/react/ui/FileTree
23
+ */
24
+ /** Default pixel width per indent level. */
25
+ const DEFAULT_INDENT_PX = 12;
26
+ /** Normalise the `expandedIds` prop into a stable `Set<string>`. */
27
+ function toSet(ids) {
28
+ if (!ids) return null;
29
+ if (ids instanceof Set) return new Set(ids);
30
+ return new Set(ids);
31
+ }
32
+ /** Single row (FileItem + chevron + indent) with recursive children rendering. */
33
+ const NodeRow = memo(function NodeRow({ node, depth, expanded, selectedId, indentPx, density, iconBasePath, iconResolve, slots, onToggle, onSelect }) {
34
+ const isDir = node.kind === "dir";
35
+ const isExpanded = isDir && expanded.has(node.id);
36
+ const isSelected = selectedId === node.id;
37
+ const handleRowSelect = useCallback(() => {
38
+ if (isDir) onToggle(node, !isExpanded);
39
+ else onSelect(node);
40
+ }, [
41
+ isDir,
42
+ isExpanded,
43
+ node,
44
+ onSelect,
45
+ onToggle
46
+ ]);
47
+ const handleChevronClick = useCallback((e) => {
48
+ e.stopPropagation();
49
+ onToggle(node, !isExpanded);
50
+ }, [
51
+ isExpanded,
52
+ node,
53
+ onToggle
54
+ ]);
55
+ const handleKeyDown = useCallback((e) => {
56
+ if (!isDir) return;
57
+ if (e.key === "ArrowRight" && !isExpanded) {
58
+ e.preventDefault();
59
+ onToggle(node, true);
60
+ } else if (e.key === "ArrowLeft" && isExpanded) {
61
+ e.preventDefault();
62
+ onToggle(node, false);
63
+ }
64
+ }, [
65
+ isDir,
66
+ isExpanded,
67
+ node,
68
+ onToggle
69
+ ]);
70
+ const children = isExpanded ? node.children ?? [] : [];
71
+ return /* @__PURE__ */ jsxs("div", {
72
+ className: cn(FileTreeStyles.node, slots?.node),
73
+ role: "none",
74
+ children: [/* @__PURE__ */ jsxs("div", {
75
+ className: cn(FileTreeStyles.row, slots?.row),
76
+ onKeyDown: handleKeyDown,
77
+ children: [
78
+ depth > 0 && /* @__PURE__ */ jsx("span", {
79
+ "aria-hidden": "true",
80
+ className: cn(FileTreeStyles.indent, slots?.indent),
81
+ style: { width: depth * indentPx }
82
+ }),
83
+ /* @__PURE__ */ jsx("button", {
84
+ type: "button",
85
+ "aria-label": isExpanded ? "Collapse" : "Expand",
86
+ "aria-expanded": isDir ? isExpanded : void 0,
87
+ tabIndex: -1,
88
+ onClick: handleChevronClick,
89
+ className: cn(FileTreeStyles.chevron, !isDir && "invisible", isExpanded && "rotate-90", slots?.chevron),
90
+ children: /* @__PURE__ */ jsx("svg", {
91
+ viewBox: "0 0 12 12",
92
+ width: "10",
93
+ height: "10",
94
+ fill: "none",
95
+ stroke: "currentColor",
96
+ strokeWidth: "1.5",
97
+ strokeLinecap: "round",
98
+ strokeLinejoin: "round",
99
+ children: /* @__PURE__ */ jsx("path", { d: "M4.5 3 L8 6 L4.5 9" })
100
+ })
101
+ }),
102
+ /* @__PURE__ */ jsx("div", {
103
+ className: "flex-1 min-w-0",
104
+ children: /* @__PURE__ */ jsx(FileItem, {
105
+ path: node.path,
106
+ kind: node.kind,
107
+ modifiedAt: node.modifiedAt,
108
+ isBoosted: node.isBoosted,
109
+ changeStatus: node.changeStatus,
110
+ selected: isSelected,
111
+ onSelect: handleRowSelect,
112
+ density,
113
+ iconBasePath,
114
+ iconResolve
115
+ })
116
+ })
117
+ ]
118
+ }), isExpanded && children.length > 0 && /* @__PURE__ */ jsx("div", {
119
+ role: "group",
120
+ className: cn(FileTreeStyles.list, slots?.list),
121
+ children: children.map((child) => /* @__PURE__ */ jsx(NodeRow, {
122
+ node: child,
123
+ depth: depth + 1,
124
+ expanded,
125
+ selectedId,
126
+ indentPx,
127
+ density,
128
+ iconBasePath,
129
+ iconResolve,
130
+ slots,
131
+ onToggle,
132
+ onSelect
133
+ }, child.id))
134
+ })]
135
+ });
136
+ });
137
+ /**
138
+ * FileTree — tree of `FileItem` rows with expand/collapse.
139
+ *
140
+ * @example
141
+ * ```tsx
142
+ * <FileTree
143
+ * nodes={[
144
+ * {
145
+ * id: 'src',
146
+ * name: 'src',
147
+ * path: 'src',
148
+ * kind: 'dir',
149
+ * children: [
150
+ * { id: 'src/App.tsx', name: 'App.tsx', path: 'src/App.tsx', kind: 'file' },
151
+ * ],
152
+ * },
153
+ * ]}
154
+ * onSelect={(n) => console.log('selected', n.path)}
155
+ * onToggle={(n, exp) => console.log('toggled', n.path, exp)}
156
+ * />
157
+ * ```
158
+ *
159
+ * @example
160
+ * ```tsx
161
+ * // Controlled expansion for lazy loading
162
+ * const [expanded, setExpanded] = useState<Set<string>>(new Set());
163
+ * <FileTree
164
+ * nodes={nodes}
165
+ * expandedIds={expanded}
166
+ * onToggle={(n, exp) => {
167
+ * setExpanded((prev) => {
168
+ * const next = new Set(prev);
169
+ * if (exp) next.add(n.id); else next.delete(n.id);
170
+ * return next;
171
+ * });
172
+ * if (exp && !n.children) loadChildren(n);
173
+ * }}
174
+ * />
175
+ * ```
176
+ */
177
+ const FileTree = memo(function FileTree({ nodes, onSelect, onToggle, expandedIds, selectedId, density = "compact", iconBasePath, iconResolve, indentPx = DEFAULT_INDENT_PX, emptyLabel = "No files", className, slots }) {
178
+ const controlled = expandedIds !== void 0;
179
+ const controlledSet = useMemo(() => toSet(expandedIds), [expandedIds]);
180
+ const [internal, setInternal] = useState(() => /* @__PURE__ */ new Set());
181
+ const expanded = controlled ? controlledSet : internal;
182
+ const handleToggle = useCallback((node, next) => {
183
+ if (!controlled) setInternal((prev) => {
184
+ const nextSet = new Set(prev);
185
+ if (next) nextSet.add(node.id);
186
+ else nextSet.delete(node.id);
187
+ return nextSet;
188
+ });
189
+ onToggle?.(node, next);
190
+ }, [controlled, onToggle]);
191
+ const handleSelect = useCallback((node) => {
192
+ onSelect?.(node);
193
+ }, [onSelect]);
194
+ if (!nodes || nodes.length === 0) return /* @__PURE__ */ jsx("div", {
195
+ role: "tree",
196
+ className: cn(fileTreeVariants({ density }), slots?.root, className),
197
+ children: /* @__PURE__ */ jsx("div", {
198
+ className: cn(FileTreeStyles.empty, slots?.empty),
199
+ children: emptyLabel
200
+ })
201
+ });
202
+ return /* @__PURE__ */ jsx("div", {
203
+ role: "tree",
204
+ className: cn(fileTreeVariants({ density }), slots?.root, className),
205
+ children: /* @__PURE__ */ jsx("div", {
206
+ role: "group",
207
+ className: cn(FileTreeStyles.list, slots?.list),
208
+ children: nodes.map((node) => /* @__PURE__ */ jsx(NodeRow, {
209
+ node,
210
+ depth: 0,
211
+ expanded,
212
+ selectedId,
213
+ indentPx,
214
+ density,
215
+ iconBasePath,
216
+ iconResolve,
217
+ slots,
218
+ onToggle: handleToggle,
219
+ onSelect: handleSelect
220
+ }, node.id))
221
+ })
222
+ });
223
+ });
224
+
225
+ //#endregion
226
+ export { FileTree };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Types for the GooeyButton component — a clickable pill that reveals a
3
+ * card via a gooey SVG-filter morph.
4
+ *
5
+ * @module @mks2508/mks-ui/react/ui/GooeyButton
6
+ */
7
+ import type { ReactNode } from 'react';
8
+ import type { IGooeyMorphConfig, IGooeyMorphSlots } from '../../../react-ui/primitives/GooeyMorphingSurface';
9
+ export interface IGooeyButtonProps {
10
+ /** Controlled open state. */
11
+ open?: boolean;
12
+ /** Default open state for uncontrolled usage. */
13
+ defaultOpen?: boolean;
14
+ /** Change callback for the open state. */
15
+ onOpenChange?: (open: boolean) => void;
16
+ /** Content rendered inside the pill. */
17
+ pill: ReactNode;
18
+ /** Content rendered inside the card body (revealed when open). */
19
+ card: ReactNode;
20
+ /** Partial override of the morph config. */
21
+ config?: Partial<IGooeyMorphConfig>;
22
+ /** Close when Escape is pressed. Default: true. */
23
+ closeOnEscape?: boolean;
24
+ /** Close when clicking outside the host element. Default: true. */
25
+ closeOnOutside?: boolean;
26
+ /** Disable the trigger. */
27
+ disabled?: boolean;
28
+ /** Extra className for the host. */
29
+ className?: string;
30
+ /** Per-slot className overrides (forwarded to primitive). */
31
+ slots?: IGooeyMorphSlots;
32
+ /** aria-label for the trigger button (defaults to "Toggle"). */
33
+ 'aria-label'?: string;
34
+ }
35
+ //# sourceMappingURL=GooeyButton.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GooeyButton.types.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/GooeyButton/GooeyButton.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EACX,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,4CAA4C,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IACjC,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,wCAAwC;IACxC,IAAI,EAAE,SAAS,CAAC;IAChB,kEAAkE;IAClE,IAAI,EAAE,SAAS,CAAC;IAChB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpC,mDAAmD;IACnD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB"}
File without changes
@@ -0,0 +1,43 @@
1
+ /* =============================================================================
2
+ * GooeyButton — transparent hit area over the pill region.
3
+ *
4
+ * The visual pill is drawn by the <GooeyMorphingSurface> primitive; this
5
+ * layer is a single button that captures clicks in both open and closed
6
+ * states without painting anything. All layout math comes from the
7
+ * primitive's CSS custom props (--gms-pill-w, --gms-pill-h).
8
+ * ============================================================================= */
9
+
10
+ .gbtn-host {
11
+ position: relative;
12
+ display: inline-block;
13
+ }
14
+
15
+ .gbtn-trigger {
16
+ position: absolute;
17
+ top: 0;
18
+ left: 50%;
19
+ transform: translateX(-50%);
20
+ z-index: 3;
21
+ width: var(--gms-pill-w);
22
+ height: var(--gms-pill-h);
23
+ padding: 0;
24
+ margin: 0;
25
+ border: 0;
26
+ background: transparent;
27
+ cursor: pointer;
28
+ font: inherit;
29
+ color: inherit;
30
+ /* Pill-shaped focus ring. */
31
+ border-radius: 9999px;
32
+ }
33
+
34
+ .gbtn-trigger:focus-visible {
35
+ outline: 2px solid var(--ring, currentColor);
36
+ outline-offset: 2px;
37
+ }
38
+
39
+ .gbtn-trigger:disabled {
40
+ cursor: not-allowed;
41
+ pointer-events: none;
42
+ }
43
+
@@ -0,0 +1,26 @@
1
+ /**
2
+ * GooeyButton — clickable pill that reveals a card via a gooey SVG-filter morph.
3
+ *
4
+ * Thin ergonomic wrapper over `<GooeyMorphingSurface>`: owns open/close
5
+ * state (controlled or uncontrolled), toggles on click, and optionally
6
+ * closes on Escape / outside click.
7
+ *
8
+ * @module @mks2508/mks-ui/react/ui/GooeyButton
9
+ */
10
+ import './gooey-button.css';
11
+ import type { IGooeyButtonProps } from './GooeyButton.types';
12
+ export * from './GooeyButton.types';
13
+ /**
14
+ * A pill-shaped button that morphs into a card when opened.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * <GooeyButton
19
+ * pill={<><DownIcon /> <span>Pull origin</span></>}
20
+ * card={<ProgressCard transfer={transfer} />}
21
+ * onOpenChange={(open) => open && startPull()}
22
+ * />
23
+ * ```
24
+ */
25
+ export declare function GooeyButton({ open: controlledOpen, defaultOpen, onOpenChange, pill, card, config, closeOnEscape, closeOnOutside, disabled, className, slots, 'aria-label': ariaLabel, }: IGooeyButtonProps): import("react/jsx-runtime").JSX.Element;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/GooeyButton/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,OAAO,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,cAAc,qBAAqB,CAAC;AAEpC;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAC3B,IAAI,EAAE,cAAc,EACpB,WAAmB,EACnB,YAAY,EACZ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,aAAoB,EACpB,cAAqB,EACrB,QAAgB,EAChB,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAoB,GAClC,EAAE,iBAAiB,2CA6EnB"}
@@ -0,0 +1,109 @@
1
+ import { cn } from "../../lib/utils.js";
2
+ import { DEFAULT_GOOEY_CONFIG } from "../../primitives/GooeyMorphingSurface/GooeyMorphingSurface.types.js";
3
+ import { GooeyMorphingSurface } from "../../primitives/GooeyMorphingSurface/index.js";
4
+ import { useControlledState } from "../../hooks/State/UseControlledState.js";
5
+ import "./gooey-button.js";
6
+ import { useCallback, useEffect, useMemo, useRef } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+
9
+ //#region src/react-ui/ui/GooeyButton/index.tsx
10
+ /**
11
+ * GooeyButton — clickable pill that reveals a card via a gooey SVG-filter morph.
12
+ *
13
+ * Thin ergonomic wrapper over `<GooeyMorphingSurface>`: owns open/close
14
+ * state (controlled or uncontrolled), toggles on click, and optionally
15
+ * closes on Escape / outside click.
16
+ *
17
+ * @module @mks2508/mks-ui/react/ui/GooeyButton
18
+ */
19
+ /**
20
+ * A pill-shaped button that morphs into a card when opened.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * <GooeyButton
25
+ * pill={<><DownIcon /> <span>Pull origin</span></>}
26
+ * card={<ProgressCard transfer={transfer} />}
27
+ * onOpenChange={(open) => open && startPull()}
28
+ * />
29
+ * ```
30
+ */
31
+ function GooeyButton({ open: controlledOpen, defaultOpen = false, onOpenChange, pill, card, config, closeOnEscape = true, closeOnOutside = true, disabled = false, className, slots, "aria-label": ariaLabel = "Toggle" }) {
32
+ const [open, setOpen] = useControlledState({
33
+ value: controlledOpen,
34
+ defaultValue: defaultOpen,
35
+ onChange: onOpenChange
36
+ });
37
+ const hostRef = useRef(null);
38
+ const hostStyle = useMemo(() => {
39
+ const pillWidth = config?.pillWidth ?? DEFAULT_GOOEY_CONFIG.pillWidth;
40
+ const pillHeight = config?.pillHeight ?? DEFAULT_GOOEY_CONFIG.pillHeight;
41
+ return {
42
+ "--gms-pill-w": `${pillWidth}px`,
43
+ "--gms-pill-h": `${pillHeight}px`
44
+ };
45
+ }, [config?.pillWidth, config?.pillHeight]);
46
+ const toggle = useCallback(() => {
47
+ if (disabled) return;
48
+ setOpen(!open);
49
+ }, [
50
+ disabled,
51
+ open,
52
+ setOpen
53
+ ]);
54
+ const close = useCallback(() => setOpen(false), [setOpen]);
55
+ useEffect(() => {
56
+ if (!open || !closeOnEscape) return;
57
+ const onKeyDown = (e) => {
58
+ if (e.key === "Escape") close();
59
+ };
60
+ window.addEventListener("keydown", onKeyDown);
61
+ return () => window.removeEventListener("keydown", onKeyDown);
62
+ }, [
63
+ open,
64
+ closeOnEscape,
65
+ close
66
+ ]);
67
+ useEffect(() => {
68
+ if (!open || !closeOnOutside) return;
69
+ const onPointerDown = (e) => {
70
+ const host = hostRef.current;
71
+ if (!host) return;
72
+ if (e.target instanceof Node && host.contains(e.target)) return;
73
+ close();
74
+ };
75
+ const raf = requestAnimationFrame(() => {
76
+ window.addEventListener("pointerdown", onPointerDown);
77
+ });
78
+ return () => {
79
+ cancelAnimationFrame(raf);
80
+ window.removeEventListener("pointerdown", onPointerDown);
81
+ };
82
+ }, [
83
+ open,
84
+ closeOnOutside,
85
+ close
86
+ ]);
87
+ return /* @__PURE__ */ jsxs("div", {
88
+ ref: hostRef,
89
+ className: cn("gbtn-host", className),
90
+ style: hostStyle,
91
+ children: [/* @__PURE__ */ jsx(GooeyMorphingSurface, {
92
+ open,
93
+ pill,
94
+ card,
95
+ config,
96
+ slots
97
+ }), /* @__PURE__ */ jsx("button", {
98
+ type: "button",
99
+ onClick: toggle,
100
+ disabled,
101
+ "aria-expanded": open,
102
+ "aria-label": ariaLabel,
103
+ className: "gbtn-trigger"
104
+ })]
105
+ });
106
+ }
107
+
108
+ //#endregion
109
+ export { GooeyButton };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Styles for MiddleTruncatePath.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/MiddleTruncatePath
5
+ */
6
+ import type { StyleSlots } from '../../../core/types';
7
+ /** Visual regions of the MiddleTruncatePath component. */
8
+ export type MiddleTruncatePathSlot = 'root' | 'start' | 'end';
9
+ /**
10
+ * Default Tailwind classes for each MiddleTruncatePath slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Container `<span>` wrapping start + end segments |
15
+ * | `start` | Truncatable start segments (ellipsised when narrow) |
16
+ * | `end` | Fixed trailing segments (always visible) |
17
+ */
18
+ export declare const MiddleTruncatePathStyles: StyleSlots<MiddleTruncatePathSlot>;
19
+ /** CVA variants for the MiddleTruncatePath root. */
20
+ export declare const middleTruncatePathVariants: (props?: ({} & import("class-variance-authority/types").ClassProp) | undefined) => string;
21
+ /** Tailwind classes used when the path is short enough to skip splitting. */
22
+ export declare const MiddleTruncatePathShortRootStyles: "truncate";
23
+ //# sourceMappingURL=MiddleTruncatePath.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MiddleTruncatePath.styles.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.styles.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,0DAA0D;AAC1D,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,sBAAsB,CAI9D,CAAC;AAEX,oDAAoD;AACpD,eAAO,MAAM,0BAA0B,2FAGrC,CAAC;AAEH,6EAA6E;AAC7E,eAAO,MAAM,iCAAiC,EAAG,UAAmB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ //#region src/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.styles.ts
4
+ /**
5
+ * Styles for MiddleTruncatePath.
6
+ *
7
+ * @module @mks2508/mks-ui/react/ui/MiddleTruncatePath
8
+ */
9
+ /**
10
+ * Default Tailwind classes for each MiddleTruncatePath slot.
11
+ *
12
+ * | Slot | Region |
13
+ * |------|--------|
14
+ * | `root` | Container `<span>` wrapping start + end segments |
15
+ * | `start` | Truncatable start segments (ellipsised when narrow) |
16
+ * | `end` | Fixed trailing segments (always visible) |
17
+ */
18
+ const MiddleTruncatePathStyles = {
19
+ root: "flex min-w-0 overflow-hidden",
20
+ start: "shrink min-w-0 overflow-hidden text-ellipsis whitespace-nowrap",
21
+ end: "shrink-0 whitespace-nowrap"
22
+ };
23
+ /** CVA variants for the MiddleTruncatePath root. */
24
+ const middleTruncatePathVariants = cva(MiddleTruncatePathStyles.root, {
25
+ variants: {},
26
+ defaultVariants: {}
27
+ });
28
+ /** Tailwind classes used when the path is short enough to skip splitting. */
29
+ const MiddleTruncatePathShortRootStyles = "truncate";
30
+
31
+ //#endregion
32
+ export { MiddleTruncatePathShortRootStyles, MiddleTruncatePathStyles, middleTruncatePathVariants };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Types for MiddleTruncatePath.
3
+ *
4
+ * @module @mks2508/mks-ui/react/ui/MiddleTruncatePath
5
+ */
6
+ import type { SlotOverrides } from '../../../core/types';
7
+ import type { MiddleTruncatePathSlot } from './MiddleTruncatePath.styles';
8
+ /**
9
+ * Props for MiddleTruncatePath.
10
+ *
11
+ * @see {@link MiddleTruncatePathSlot} for available slot names
12
+ */
13
+ export interface IMiddleTruncatePathProps {
14
+ /** Full file path (e.g. `"src/components/shell/AppShell.tsx"`). */
15
+ path: string;
16
+ /** How many trailing segments to always show (parent + filename). Default 2. */
17
+ keepEnd?: number;
18
+ /** Optional CSS class merged onto the root (container). */
19
+ className?: string;
20
+ /**
21
+ * Optional CSS class for the start (truncatable) segment.
22
+ * @deprecated Prefer `slots.start` for new code.
23
+ */
24
+ startClassName?: string;
25
+ /**
26
+ * Optional CSS class for the end (fixed) segment.
27
+ * @deprecated Prefer `slots.end` for new code.
28
+ */
29
+ endClassName?: string;
30
+ /**
31
+ * Override default Tailwind classes per visual slot.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * <MiddleTruncatePath
36
+ * path="src/index.ts"
37
+ * slots={{ start: 'text-muted-foreground/60', end: 'font-semibold' }}
38
+ * />
39
+ * ```
40
+ */
41
+ slots?: SlotOverrides<MiddleTruncatePathSlot>;
42
+ }
43
+ //# sourceMappingURL=MiddleTruncatePath.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MiddleTruncatePath.types.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/MiddleTruncatePath/MiddleTruncatePath.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;CAC/C"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * MiddleTruncatePath — CSS-only middle truncation for file paths.
3
+ *
4
+ * Splits a path into a truncatable start and a fixed end
5
+ * (`parent/filename` by default). When space is limited, the start
6
+ * truncates with ellipsis while the end (the most identifiable part)
7
+ * always remains visible.
8
+ *
9
+ * Pure CSS flex — no JS measurement, no ResizeObserver.
10
+ *
11
+ * Ported from mks-mission-control.
12
+ *
13
+ * @module @mks2508/mks-ui/react/ui/MiddleTruncatePath
14
+ */
15
+ import type { IMiddleTruncatePathProps } from './MiddleTruncatePath.types';
16
+ /**
17
+ * Middle-truncates a file path, keeping the end segments visible.
18
+ *
19
+ * @param slots - Override Tailwind classes per visual slot
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // Full width: src/components/shell/AppShell.tsx
24
+ * // Constrained: src/comp…/shell/AppShell.tsx
25
+ * // Minimum: …/shell/AppShell.tsx
26
+ * <MiddleTruncatePath path="src/components/shell/AppShell.tsx" />
27
+ * ```
28
+ */
29
+ export declare const MiddleTruncatePath: import("react").MemoExoticComponent<({ path, keepEnd, className, startClassName, endClassName, slots, }: IMiddleTruncatePathProps) => import("react/jsx-runtime").JSX.Element>;
30
+ export { MiddleTruncatePathStyles, middleTruncatePathVariants, } from './MiddleTruncatePath.styles';
31
+ export type { MiddleTruncatePathSlot } from './MiddleTruncatePath.styles';
32
+ export type { IMiddleTruncatePathProps } from './MiddleTruncatePath.types';
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/react-ui/ui/MiddleTruncatePath/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,2GAO5B,wBAAwB,6CAqCzB,CAAC;AAEH,OAAO,EACL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,YAAY,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC"}