@floegence/floe-webapp-core 0.35.37 → 0.35.39

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.
@@ -0,0 +1,153 @@
1
+ import { insert as q, effect as G, className as I, setAttribute as J, setStyleProperty as K, template as Q, use as ee, delegateEvents as te } from "solid-js/web";
2
+ import { createSignal as T, untrack as D, createEffect as L, onCleanup as y } from "solid-js";
3
+ import { cn as Y } from "../../utils/cn.js";
4
+ import { isTypingElement as _ } from "../../utils/dom.js";
5
+ import { startHotInteraction as b } from "../../utils/hotInteraction.js";
6
+ var ne = /* @__PURE__ */ Q('<div><div style="transform-origin:0 0">');
7
+ const re = 1, ie = 0.45, oe = 2.2, ae = 14e-4, ce = '[data-floe-canvas-pan-surface="true"]', A = 3;
8
+ function le(n, a, d) {
9
+ return Math.max(a, Math.min(d, n));
10
+ }
11
+ function M(n) {
12
+ return {
13
+ x: Number.isFinite(n.x) ? n.x : 0,
14
+ y: Number.isFinite(n.y) ? n.y : 0,
15
+ scale: Number.isFinite(n.scale) && n.scale > 0 ? n.scale : re
16
+ };
17
+ }
18
+ function se(n, a) {
19
+ return n.deltaMode === 1 ? n.deltaY * 16 : n.deltaMode === 2 ? n.deltaY * (a?.clientHeight ?? window.innerHeight) : n.deltaY;
20
+ }
21
+ function we(n) {
22
+ const [a, d] = T(D(() => M(n.viewport))), [p, S] = T(null);
23
+ let o, f, m = !1, l;
24
+ const X = () => n.interactiveSelector ?? '[data-floe-canvas-interactive="true"]', F = () => n.panSurfaceSelector ?? ce, $ = () => n.minScale ?? ie, k = () => n.maxScale ?? oe, V = () => n.wheelZoomSpeed ?? ae, R = () => {
25
+ const e = p();
26
+ return e ? e.startedFromPanSurface ? e.moved : !0 : !1;
27
+ }, C = () => {
28
+ f !== void 0 && (window.clearTimeout(f), f = void 0);
29
+ }, v = () => {
30
+ m = !1, l !== void 0 && (window.clearTimeout(l), l = void 0);
31
+ }, N = () => {
32
+ if (typeof window > "u") {
33
+ m = !1;
34
+ return;
35
+ }
36
+ l !== void 0 && window.clearTimeout(l), l = window.setTimeout(() => {
37
+ l = void 0, m = !1;
38
+ }, 0);
39
+ }, h = (e) => {
40
+ D(() => n.onViewportChange?.(e));
41
+ }, U = (e) => {
42
+ if (typeof window > "u") {
43
+ h(e);
44
+ return;
45
+ }
46
+ C(), f = window.setTimeout(() => {
47
+ f = void 0, h(e);
48
+ }, 90);
49
+ }, E = (e) => e instanceof Element ? e.closest(X()) ? !0 : _(e) : !1, x = (e) => e instanceof Element ? e.closest(F()) !== null : !1, g = (e) => {
50
+ const t = p();
51
+ if (!t || e !== void 0 && t.pointerId !== e) return;
52
+ t.stopInteraction?.();
53
+ const r = a();
54
+ S(null), o && o.hasPointerCapture(t.pointerId) && o.releasePointerCapture(t.pointerId), t.startedFromPanSurface && t.moved && (m = !0, N()), h(r);
55
+ };
56
+ L(() => {
57
+ p() || d(M(n.viewport));
58
+ }), L(() => {
59
+ const e = o;
60
+ if (!e) return;
61
+ const t = (r) => {
62
+ !m || !x(r.target) || (v(), r.preventDefault(), r.stopPropagation());
63
+ };
64
+ e.addEventListener("click", t, !0), y(() => {
65
+ e.removeEventListener("click", t, !0);
66
+ });
67
+ }), y(() => {
68
+ C(), g(), v();
69
+ });
70
+ const H = (e) => {
71
+ if (e.button !== 0 || _(e.target)) return;
72
+ const t = x(e.target);
73
+ E(e.target) && !t || (C(), v(), t || (e.preventDefault(), o?.setPointerCapture(e.pointerId)), S({
74
+ pointerId: e.pointerId,
75
+ startClientX: e.clientX,
76
+ startClientY: e.clientY,
77
+ startViewport: a(),
78
+ moved: !1,
79
+ startedFromPanSurface: t,
80
+ stopInteraction: t ? void 0 : b({
81
+ kind: "drag",
82
+ cursor: "grabbing"
83
+ })
84
+ }));
85
+ }, O = (e) => {
86
+ const t = p();
87
+ if (!t || t.pointerId !== e.pointerId) return;
88
+ const r = e.clientX - t.startClientX, i = e.clientY - t.startClientY;
89
+ if (!(t.moved || Math.abs(r) > A || Math.abs(i) > A)) return;
90
+ t.moved || (e.preventDefault(), o?.hasPointerCapture(e.pointerId) || o?.setPointerCapture(e.pointerId));
91
+ const u = {
92
+ ...t.startViewport,
93
+ x: t.startViewport.x + r,
94
+ y: t.startViewport.y + i
95
+ };
96
+ t.moved || S({
97
+ ...t,
98
+ moved: !0,
99
+ stopInteraction: t.stopInteraction ?? b({
100
+ kind: "drag",
101
+ cursor: "grabbing"
102
+ })
103
+ }), d(u);
104
+ }, W = (e) => {
105
+ g(e.pointerId);
106
+ }, Z = (e) => {
107
+ g(e.pointerId);
108
+ }, B = (e) => {
109
+ const t = o?.getBoundingClientRect();
110
+ if (!t) return;
111
+ e.preventDefault();
112
+ const r = a(), i = e.clientX - t.left, c = e.clientY - t.top, u = se(e, o), s = le(r.scale * Math.exp(-u * V()), $(), k());
113
+ if (Math.abs(s - r.scale) < 1e-4) return;
114
+ const w = (i - r.x) / r.scale, j = (c - r.y) / r.scale, P = {
115
+ x: i - w * s,
116
+ y: c - j * s,
117
+ scale: s
118
+ };
119
+ d(P), U(P);
120
+ }, z = (e) => {
121
+ if (E(e.target)) return;
122
+ const t = o?.getBoundingClientRect();
123
+ if (!t) return;
124
+ e.preventDefault();
125
+ const r = e.clientX - t.left, i = e.clientY - t.top, c = a();
126
+ n.onCanvasContextMenu?.({
127
+ clientX: e.clientX,
128
+ clientY: e.clientY,
129
+ localX: r,
130
+ localY: i,
131
+ worldX: (r - c.x) / c.scale,
132
+ worldY: (i - c.y) / c.scale
133
+ });
134
+ };
135
+ return (() => {
136
+ var e = ne(), t = e.firstChild;
137
+ e.$$contextmenu = z, e.addEventListener("wheel", B), e.addEventListener("pointercancel", Z), e.$$pointerup = W, e.$$pointermove = O, e.$$pointerdown = H;
138
+ var r = o;
139
+ return typeof r == "function" ? ee(r, e) : o = e, q(t, () => n.children), G((i) => {
140
+ var c = Y("floe-infinite-canvas", R() && "is-panning", n.class), u = n.ariaLabel ?? "Infinite canvas", s = Y("floe-infinite-canvas__viewport", n.contentClass), w = `translate(${a().x}px, ${a().y}px) scale(${a().scale})`;
141
+ return c !== i.e && I(e, i.e = c), u !== i.t && J(e, "aria-label", i.t = u), s !== i.a && I(t, i.a = s), w !== i.o && K(t, "transform", i.o = w), i;
142
+ }, {
143
+ e: void 0,
144
+ t: void 0,
145
+ a: void 0,
146
+ o: void 0
147
+ }), e;
148
+ })();
149
+ }
150
+ te(["pointerdown", "pointermove", "pointerup", "contextmenu"]);
151
+ export {
152
+ we as InfiniteCanvas
153
+ };
@@ -6,12 +6,13 @@ export { FloatingWindow, type FloatingWindowProps } from './FloatingWindow';
6
6
  export { Dropdown, Select, type DropdownProps, type DropdownItem, type SelectProps, } from './Dropdown';
7
7
  export { Tooltip, type TooltipProps } from './Tooltip';
8
8
  export { CommandPalette } from './CommandPalette';
9
+ export { InfiniteCanvas, type InfiniteCanvasProps, type InfiniteCanvasPoint, type InfiniteCanvasContextMenuEvent, } from './InfiniteCanvas';
9
10
  export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Interactive3DCard, AnimatedBorderCard, NeonCard, MorphCard, type CardProps, type CardVariant, type CardHeaderProps, type CardTitleProps, type CardDescriptionProps, type CardContentProps, type CardFooterProps, type Interactive3DCardProps, type AnimatedBorderCardProps, type NeonCardProps, type MorphCardProps, } from './Card';
10
11
  export { Tabs, TabPanel, type TabsProps, type TabPanelProps, type TabItem, type TabsFeatures, type TabsSlotClassNames, type TabsIndicatorMode, type TabsIndicatorColorToken, } from './Tabs';
11
12
  export { DirectoryPicker, type DirectoryPickerProps } from './DirectoryPicker';
12
13
  export { DirectoryInput, type DirectoryInputProps, type DirectoryInputSize, } from './DirectoryInput';
13
14
  export { FileSavePicker, type FileSavePickerProps } from './FileSavePicker';
14
- export { type BasePickerProps } from './picker/PickerBase';
15
+ export { type BasePickerProps, type PickerEnsurePath, type PickerEnsurePathOptions, type PickerPathResolveResult, type PickerPathResolveStatus, type PickerPathNavigateReason, } from './picker/PickerBase';
15
16
  export { QuoteBlock, type QuoteBlockProps } from './QuoteBlock';
16
17
  export { HighlightBlock, InfoBlock, WarningBlock, SuccessBlock, ErrorBlock, NoteBlock, TipBlock, type HighlightBlockProps, type HighlightVariant, } from './HighlightBlock';
17
18
  export { ProcessingIndicator, type ProcessingIndicatorProps, type ProcessingIndicatorVariant, type ProcessingIndicatorStatus, } from './ProcessingIndicator';
@@ -33,7 +33,13 @@ export interface BasePickerProps {
33
33
  * Use this to dynamically load children for the expanded directory.
34
34
  * The path parameter is the internal tree path (not the display path).
35
35
  */
36
- onExpand?: (path: string) => void;
36
+ onExpand?: (path: string) => void | Promise<void>;
37
+ /**
38
+ * Async resolver used when a navigation target may exist outside the current
39
+ * in-memory tree snapshot. A ready result guarantees the target path and its
40
+ * ancestor chain are now represented in `files`.
41
+ */
42
+ ensurePath?: PickerEnsurePath;
37
43
  /** Filter which directories are selectable (return false to grey-out) */
38
44
  filter?: (item: FileItem) => boolean;
39
45
  /** Label for the home/root directory (default: 'Root') */
@@ -67,7 +73,9 @@ export interface UsePickerTreeOptions {
67
73
  * Callback when user expands a directory.
68
74
  * Use this to dynamically load children for the expanded directory.
69
75
  */
70
- onExpand?: (path: string) => void;
76
+ onExpand?: (path: string) => void | Promise<void>;
77
+ /** Async resolver that ensures a target path exists in the current tree snapshot. */
78
+ ensurePath?: PickerEnsurePath;
71
79
  /** Label for the home/root directory in tree and breadcrumb (default: 'Root'). Supports accessor for reactivity. */
72
80
  homeLabel?: string | Accessor<string | undefined>;
73
81
  /**
@@ -84,6 +92,7 @@ export interface PickerTreeState {
84
92
  toggleExpand: (path: string) => void;
85
93
  pathInput: Accessor<string>;
86
94
  setPathInput: (value: string) => void;
95
+ pathPending: Accessor<boolean>;
87
96
  pathInputError: Accessor<string>;
88
97
  setPathInputError: (value: string) => void;
89
98
  folderIndex: Accessor<Map<string, FileItem>>;
@@ -95,6 +104,7 @@ export interface PickerTreeState {
95
104
  handlePathInputGo: () => void;
96
105
  handlePathInputKeyDown: (e: KeyboardEvent) => void;
97
106
  expandToPath: (path: string) => void;
107
+ navigateToPath: (path: string, options: PickerEnsurePathOptions) => Promise<PickerPathResolveResult>;
98
108
  breadcrumbSegments: Accessor<{
99
109
  name: string;
100
110
  path: string;
@@ -104,7 +114,20 @@ export interface PickerTreeState {
104
114
  homeLabel: Accessor<string>;
105
115
  /** Convert internal tree path to display (real filesystem) path */
106
116
  toDisplayPath: (internalPath: string) => string;
117
+ /** Monotonic counter used to reveal the selected row after async navigation. */
118
+ revealNonce: Accessor<number>;
119
+ }
120
+ export type PickerPathResolveStatus = 'ready' | 'missing' | 'error';
121
+ export type PickerPathNavigateReason = 'open' | 'path-input' | 'tree-expand' | 'tree-select' | 'breadcrumb';
122
+ export interface PickerEnsurePathOptions {
123
+ reason: PickerPathNavigateReason;
124
+ }
125
+ export interface PickerPathResolveResult {
126
+ status: PickerPathResolveStatus;
127
+ resolvedPath: string;
128
+ message?: string;
107
129
  }
130
+ export type PickerEnsurePath = (path: string, options: PickerEnsurePathOptions) => PickerPathResolveResult | Promise<PickerPathResolveResult>;
108
131
  export declare function resolvePickerInitialPath(initialPath: string | undefined, homePath: string | undefined): string;
109
132
  export declare function usePickerTree(opts: UsePickerTreeOptions): PickerTreeState;
110
133
  export interface NewFolderSectionProps {
@@ -117,6 +140,7 @@ export declare function NewFolderSection(props: NewFolderSectionProps): JSX.Elem
117
140
  export interface PathInputBarProps {
118
141
  value: Accessor<string>;
119
142
  onInput: (value: string) => void;
143
+ pending?: Accessor<boolean>;
120
144
  error: Accessor<string>;
121
145
  onGo: () => void;
122
146
  onKeyDown: (e: KeyboardEvent) => void;
@@ -135,6 +159,7 @@ export interface PickerFolderTreeProps {
135
159
  rootFolders: Accessor<FileItem[]>;
136
160
  selectedPath: Accessor<string>;
137
161
  expandedPaths: Accessor<Set<string>>;
162
+ revealNonce?: Accessor<number>;
138
163
  onToggle: (path: string) => void;
139
164
  onSelect: (item: FileItem) => void;
140
165
  onSelectRoot: () => void;
@@ -151,8 +176,10 @@ export interface PickerTreeNodeProps {
151
176
  depth: number;
152
177
  selectedPath: Accessor<string>;
153
178
  expandedPaths: Accessor<Set<string>>;
179
+ revealNonce?: Accessor<number>;
154
180
  onToggle: (path: string) => void;
155
181
  onSelect: (item: FileItem) => void;
156
182
  isSelectable: (item: FileItem) => boolean;
183
+ registerRow: (path: string, el: HTMLButtonElement | null) => void;
157
184
  }
158
185
  export declare function PickerTreeNode(props: PickerTreeNodeProps): JSX.Element;