@floegence/floe-webapp-core 0.48.6 → 0.50.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.
@@ -1,38 +1,17 @@
1
- import { type PickerEnsurePath } from './picker/PickerBase';
2
- import type { FileItem } from '../file-browser/types';
1
+ import { type PickerPanelProps } from './picker/PickerBase';
3
2
  export type DirectoryInputSize = 'sm' | 'md' | 'lg';
4
- export interface DirectoryInputProps {
5
- /** Currently selected directory path */
3
+ export interface DirectoryInputProps extends PickerPanelProps {
6
4
  value?: string;
7
- /** Callback when directory is selected */
8
- onChange?: (path: string) => void;
9
- /** File tree data for the picker */
10
- files: FileItem[];
11
- /** Callback to load directory contents (for lazy loading) */
12
- onExpand?: (path: string) => void | Promise<void>;
13
- /** Async resolver that guarantees a target path exists in the current tree snapshot. */
14
- ensurePath?: PickerEnsurePath;
15
- /** Placeholder text when no directory is selected */
5
+ onChange?: (absolutePath: string) => void;
6
+ /** The containing form's lifecycle; close invalidates outstanding loads. */
7
+ open?: boolean;
16
8
  placeholder?: string;
17
- /** Optional home directory path for display */
18
- homePath?: string;
19
- /** Label for home button in picker */
20
- homeLabel?: string;
21
- /** Initial path when picker opens */
22
- initialPath?: string;
23
- /** Whether the input is disabled */
24
9
  disabled?: boolean;
25
- /** Input size variant */
26
10
  size?: DirectoryInputSize;
27
- /** Error message - also sets visual error state */
28
11
  error?: string;
29
- /** Helper text displayed below the input */
30
12
  helperText?: string;
31
- /** Additional CSS class */
32
13
  class?: string;
33
- /** Maximum height for the tree panel (default: '200px') */
34
- treeMaxHeight?: string;
35
- /** Whether the tree panel is expanded by default (default: true) */
36
14
  defaultExpanded?: boolean;
37
15
  }
16
+ /** Inline picker keeps the surrounding form visible and commits only validated absolute paths. */
38
17
  export declare function DirectoryInput(props: DirectoryInputProps): import("solid-js").JSX.Element;
@@ -1,137 +1,63 @@
1
- import { insert as o, createComponent as a, memo as k, effect as y, className as p, template as c, delegateEvents as S } from "solid-js/web";
2
- import { splitProps as $, createSignal as C, createEffect as f, on as _, Show as g } from "solid-js";
3
- import { cn as u } from "../../utils/cn.js";
4
- import { usePickerTree as T, PickerBreadcrumb as F, PickerFolderTree as L } from "./picker/PickerBase.js";
5
- import { Folder as z, ChevronRight as N } from "../icons/index.js";
6
- var R = /* @__PURE__ */ c('<div class="border border-input rounded-b-md overflow-hidden bg-background shadow-sm border-t-0"><div class="px-2 py-1 border-b border-border/50 bg-muted/30">'), B = /* @__PURE__ */ c('<p class="mt-1 text-[11px] text-error"role=alert>'), D = /* @__PURE__ */ c('<p class="mt-1 text-[11px] text-muted-foreground">'), H = /* @__PURE__ */ c("<div><button type=button><span>");
7
- const M = {
8
- sm: {
9
- container: "h-7 px-2",
10
- icon: "w-3.5 h-3.5",
11
- text: "text-xs"
12
- },
13
- md: {
14
- container: "h-8 px-2.5",
15
- icon: "w-4 h-4",
16
- text: "text-xs"
17
- },
18
- lg: {
19
- container: "h-9 px-3",
20
- icon: "w-4 h-4",
21
- text: "text-sm"
22
- }
23
- };
24
- function A(b) {
25
- const [e] = $(b, ["value", "onChange", "files", "onExpand", "ensurePath", "placeholder", "homePath", "homeLabel", "initialPath", "disabled", "size", "error", "helperText", "class", "treeMaxHeight", "defaultExpanded"]), [d, v] = C(e.defaultExpanded !== !1), P = () => e.size ?? "md", i = () => M[P()];
26
- f(() => {
27
- d() && e.files.length === 0 && e.onExpand && e.onExpand("/");
28
- });
29
- const r = T({
30
- initialPath: () => e.initialPath ?? "/",
31
- open: () => !0,
32
- files: () => e.files,
33
- onExpand: (n) => e.onExpand?.(n),
34
- // eslint-disable-next-line solid/reactivity -- ensurePath is a static callback
35
- ensurePath: e.ensurePath,
36
- homeLabel: () => e.homeLabel,
37
- homePath: () => e.homePath
38
- });
39
- f(_(r.selectedPath, (n) => {
40
- if (!d()) return;
41
- const l = r.toDisplayPath(n);
42
- e.onChange?.(l);
43
- }));
44
- const E = () => {
45
- if (e.disabled) return;
46
- const n = d();
47
- !n && e.files.length === 0 && e.onExpand && e.onExpand("/"), v(!n);
48
- }, w = () => e.value ? e.homePath && e.value.startsWith(e.homePath) ? "~" + (e.value.slice(e.homePath.length) || "") : e.value : null;
1
+ import { insert as r, createComponent as l, mergeProps as $, memo as y, effect as C, className as x, setAttribute as f, template as a, delegateEvents as _ } from "solid-js/web";
2
+ import { createSignal as E, mergeProps as S, Show as d } from "solid-js";
3
+ import { cn as b } from "../../utils/cn.js";
4
+ import { Folder as z, ChevronRight as A } from "../icons/index.js";
5
+ import { formatPickerPath as N } from "./picker/PickerNavigation.js";
6
+ import { usePickerNavigation as T, PickerPanel as D } from "./picker/PickerBase.js";
7
+ var F = /* @__PURE__ */ a("<div class=mt-2>"), I = /* @__PURE__ */ a('<p role=alert class="mt-1 text-xs text-error">'), R = /* @__PURE__ */ a('<p class="mt-1 text-xs text-muted-foreground">'), V = /* @__PURE__ */ a('<div><button type=button><span class="min-w-0 flex-1 truncate">');
8
+ function K(t) {
9
+ const [o, P] = E(t.defaultExpanded !== !1), w = S(t, {
10
+ get initialPath() {
11
+ return t.value || t.initialPath;
12
+ }
13
+ }), s = T(w, () => t.open ?? !0, (i) => t.onChange?.(i)), k = () => N(t.value ?? "", s.context()?.homePathAbs ?? t.homePath);
49
14
  return (() => {
50
- var n = H(), l = n.firstChild, h = l.firstChild;
51
- return l.$$click = E, o(l, a(z, {
52
- get class() {
53
- return u("text-muted-foreground flex-shrink-0", i().icon);
54
- }
55
- }), h), o(h, () => w() || e.placeholder || "Select a directory..."), o(l, a(N, {
15
+ var i = V(), n = i.firstChild, c = n.firstChild;
16
+ return n.$$click = () => P((e) => !e), r(n, l(z, {
17
+ class: "h-4 w-4 shrink-0 text-muted-foreground"
18
+ }), c), r(c, () => k() || t.placeholder || "Select a directory…"), r(n, l(A, {
56
19
  get class() {
57
- return u("text-muted-foreground flex-shrink-0 transition-transform duration-150", i().icon, d() && "rotate-90");
20
+ return b("h-3.5 w-3.5 shrink-0 transition-transform", o() && "rotate-90");
58
21
  }
59
- }), null), o(n, a(g, {
22
+ }), null), r(i, l(d, {
60
23
  get when() {
61
- return d();
24
+ return o();
62
25
  },
63
26
  get children() {
64
- var t = R(), s = t.firstChild;
65
- return o(s, a(F, {
66
- get segments() {
67
- return r.breadcrumbSegments;
68
- },
69
- get onClick() {
70
- return r.handleBreadcrumbClick;
71
- }
72
- })), o(t, a(L, {
73
- get rootFolders() {
74
- return r.rootFolders;
75
- },
76
- get selectedPath() {
77
- return r.selectedPath;
78
- },
79
- get expandedPaths() {
80
- return r.expandedPaths;
81
- },
82
- get revealNonce() {
83
- return r.revealNonce;
84
- },
85
- get onToggle() {
86
- return r.toggleExpand;
87
- },
88
- get onSelect() {
89
- return r.handleSelectFolder;
90
- },
91
- get onSelectRoot() {
92
- return r.handleSelectRoot;
93
- },
94
- get isSelectable() {
95
- return r.isSelectable;
96
- },
97
- get homeLabel() {
98
- return r.homeLabel;
99
- },
100
- class: "border-0 rounded-none",
101
- get style() {
102
- return {
103
- "max-height": e.treeMaxHeight ?? "200px"
104
- };
105
- }
106
- }), null), t;
27
+ var e = F();
28
+ return r(e, l(D, $(t, {
29
+ source: s
30
+ }))), e;
107
31
  }
108
- }), null), o(n, a(g, {
32
+ }), null), r(i, l(d, {
109
33
  get when() {
110
- return e.error;
34
+ return t.error;
111
35
  },
112
36
  get children() {
113
- var t = B();
114
- return o(t, () => e.error), t;
37
+ var e = I();
38
+ return r(e, () => t.error), e;
115
39
  }
116
- }), null), o(n, a(g, {
40
+ }), null), r(i, l(d, {
117
41
  get when() {
118
- return k(() => !!e.helperText)() && !e.error;
42
+ return y(() => !!t.helperText)() && !t.error;
119
43
  },
120
44
  get children() {
121
- var t = D();
122
- return o(t, () => e.helperText), t;
45
+ var e = R();
46
+ return r(e, () => t.helperText), e;
123
47
  }
124
- }), null), y((t) => {
125
- var s = e.disabled, m = u("w-full flex items-center gap-2 rounded border border-input bg-background shadow-sm", "transition-colors duration-100 cursor-pointer", "hover:bg-muted/50", "focus:outline-none focus:ring-1 focus:ring-ring focus:border-ring", "disabled:cursor-not-allowed disabled:opacity-50", e.error && "border-error focus:ring-error", d() && "rounded-b-none border-b-0", i().container, e.class), x = u("flex-1 text-left truncate font-mono", i().text, e.value ? "text-foreground" : "text-muted-foreground/60");
126
- return s !== t.e && (l.disabled = t.e = s), m !== t.t && p(l, t.t = m), x !== t.a && p(h, t.a = x), t;
48
+ }), null), C((e) => {
49
+ var u = t.class, m = t.disabled, h = o(), v = t.value, g = b("flex w-full cursor-pointer items-center gap-2 rounded border border-input bg-background px-2 text-left shadow-sm focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", t.size === "lg" ? "h-9 text-sm" : t.size === "md" ? "h-8 text-xs" : "h-7 text-xs");
50
+ return u !== e.e && x(i, e.e = u), m !== e.t && (n.disabled = e.t = m), h !== e.a && f(n, "aria-expanded", e.a = h), v !== e.o && f(n, "title", e.o = v), g !== e.i && x(n, e.i = g), e;
127
51
  }, {
128
52
  e: void 0,
129
53
  t: void 0,
130
- a: void 0
131
- }), n;
54
+ a: void 0,
55
+ o: void 0,
56
+ i: void 0
57
+ }), i;
132
58
  })();
133
59
  }
134
- S(["click"]);
60
+ _(["click"]);
135
61
  export {
136
- A as DirectoryInput
62
+ K as DirectoryInput
137
63
  };
@@ -1,10 +1,6 @@
1
1
  import { type BasePickerProps } from './picker/PickerBase';
2
2
  export interface DirectoryPickerProps extends BasePickerProps {
3
- /** Called when user confirms selection */
3
+ /** Receives the validated absolute directory path. */
4
4
  onSelect: (path: string) => void;
5
5
  }
6
- /**
7
- * Modal directory picker for selecting a folder path.
8
- * Standalone component — does not depend on FileBrowserContext.
9
- */
10
6
  export declare function DirectoryPicker(props: DirectoryPickerProps): import("solid-js").JSX.Element;
@@ -1,147 +1,58 @@
1
- import { createComponent as r, insert as l, effect as h, setAttribute as g, template as i } from "solid-js/web";
2
- import { Show as d } from "solid-js";
3
- import { cn as m } from "../../utils/cn.js";
1
+ import { createComponent as r, mergeProps as o, insert as i, effect as u, setAttribute as m, template as g } from "solid-js/web";
2
+ import { cn as f } from "../../utils/cn.js";
3
+ import { Button as c } from "./Button.js";
4
4
  import { Dialog as s } from "./Dialog.js";
5
- import { Button as o } from "./Button.js";
6
- import { deferNonBlocking as P } from "../../utils/defer.js";
7
- import { usePickerTree as f, PathInputBar as x, PickerBreadcrumb as C, PickerFolderTree as p, NewFolderSection as S } from "./picker/PickerBase.js";
8
- var b = /* @__PURE__ */ i('<div class="flex flex-col gap-2 -mt-1">'), v = /* @__PURE__ */ i('<div class="flex items-center w-full gap-2"><span class="flex-1 text-[11px] text-muted-foreground truncate">');
9
- function E(t) {
10
- const e = f({
11
- initialPath: () => t.initialPath,
12
- open: () => t.open,
13
- files: () => t.files,
14
- // eslint-disable-next-line solid/reactivity -- filter is a static callback
15
- filter: t.filter ? (n) => t.filter(n) : void 0,
16
- // eslint-disable-next-line solid/reactivity -- onExpand is a static callback
17
- onExpand: t.onExpand,
18
- // eslint-disable-next-line solid/reactivity -- ensurePath is a static callback
19
- ensurePath: t.ensurePath,
20
- homeLabel: () => t.homeLabel,
21
- homePath: () => t.homePath
22
- }), u = () => {
23
- const n = e.selectedPath(), a = t.onSelect;
24
- t.onOpenChange(!1), P(() => a(n));
25
- }, c = () => {
26
- t.onOpenChange(!1);
5
+ import { usePickerNavigation as h, PickerPanel as d, pickerCopy as x } from "./picker/PickerBase.js";
6
+ var C = /* @__PURE__ */ g('<div class="flex w-full items-center gap-2"><span class="min-w-0 flex-1 truncate text-[11px] text-muted-foreground">');
7
+ function w(e) {
8
+ const t = h(e, () => e.open), a = () => {
9
+ if (!t.valid()) return;
10
+ const n = t.currentPath();
11
+ e.onSelect(n), e.onOpenChange(!1);
27
12
  };
28
13
  return r(s, {
29
14
  get open() {
30
- return t.open;
15
+ return e.open;
31
16
  },
32
17
  get onOpenChange() {
33
- return t.onOpenChange;
18
+ return e.onOpenChange;
34
19
  },
35
20
  get title() {
36
- return t.title ?? "Select Directory";
21
+ return e.title ?? "Select Directory";
37
22
  },
38
23
  get class() {
39
- return m("max-w-lg", t.class);
24
+ return f("max-w-lg", e.class);
40
25
  },
41
26
  get footer() {
42
27
  return (() => {
43
- var n = v(), a = n.firstChild;
44
- return l(a, () => e.toDisplayPath(e.selectedPath())), l(n, r(o, {
28
+ var n = C(), l = n.firstChild;
29
+ return i(l, () => t.currentPath()), i(n, r(c, {
45
30
  variant: "ghost",
46
31
  size: "sm",
47
- onClick: c,
32
+ onClick: () => e.onOpenChange(!1),
48
33
  get children() {
49
- return t.cancelText ?? "Cancel";
34
+ return e.cancelText ?? x(e).cancel;
50
35
  }
51
- }), null), l(n, r(o, {
36
+ }), null), i(n, r(c, {
52
37
  variant: "primary",
53
38
  size: "sm",
54
- onClick: u,
39
+ onClick: a,
55
40
  get disabled() {
56
- return e.pathPending();
41
+ return !t.valid();
57
42
  },
58
43
  get children() {
59
- return t.confirmText ?? "Select";
44
+ return e.confirmText ?? "Select";
60
45
  }
61
- }), null), h(() => g(a, "title", e.toDisplayPath(e.selectedPath()))), n;
46
+ }), null), u(() => m(l, "title", t.currentPath())), n;
62
47
  })();
63
48
  },
64
49
  get children() {
65
- var n = b();
66
- return l(n, r(x, {
67
- get value() {
68
- return e.pathInput;
69
- },
70
- onInput: (a) => {
71
- e.setPathInput(a), e.setPathInputError("");
72
- },
73
- get pending() {
74
- return e.pathPending;
75
- },
76
- get error() {
77
- return e.pathInputError;
78
- },
79
- get onGo() {
80
- return e.handlePathInputGo;
81
- },
82
- get onKeyDown() {
83
- return e.handlePathInputKeyDown;
84
- }
85
- }), null), l(n, r(C, {
86
- get segments() {
87
- return e.breadcrumbSegments;
88
- },
89
- get onClick() {
90
- return e.handleBreadcrumbClick;
91
- }
92
- }), null), l(n, r(p, {
93
- get rootFolders() {
94
- return e.rootFolders;
95
- },
96
- get selectedPath() {
97
- return e.selectedPath;
98
- },
99
- get expandedPaths() {
100
- return e.expandedPaths;
101
- },
102
- get revealNonce() {
103
- return e.revealNonce;
104
- },
105
- get onToggle() {
106
- return e.toggleExpand;
107
- },
108
- get onSelect() {
109
- return e.handleSelectFolder;
110
- },
111
- get onSelectRoot() {
112
- return e.handleSelectRoot;
113
- },
114
- get isSelectable() {
115
- return e.isSelectable;
116
- },
117
- get homeLabel() {
118
- return e.homeLabel;
119
- },
120
- style: {
121
- "max-height": "280px",
122
- "min-height": "160px"
123
- }
124
- }), null), l(n, r(d, {
125
- get when() {
126
- return t.onCreateFolder;
127
- },
128
- get children() {
129
- return r(S, {
130
- get parentPath() {
131
- return e.selectedPath;
132
- },
133
- get onCreateFolder() {
134
- return t.onCreateFolder;
135
- },
136
- get toDisplayPath() {
137
- return e.toDisplayPath;
138
- }
139
- });
140
- }
141
- }), null), n;
50
+ return r(d, o(e, {
51
+ source: t
52
+ }));
142
53
  }
143
54
  });
144
55
  }
145
56
  export {
146
- E as DirectoryPicker
57
+ w as DirectoryPicker
147
58
  };