@cocoar/vue-file-explorer-core 2.6.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.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @cocoar/vue-file-explorer-core
2
+
3
+ VSCode-style file/asset explorer for Vue 3 — a single composable + a pluggable `AssetStore<T>` contract that decouples the UX from your backend (HTTP, IndexedDB, in-memory, whatever).
4
+
5
+ > **Status: Preview tier.** API is stable enough to consume, but small tweaks may land before the Preview marker drops. Full VitePress reference + live demos coming soon.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @cocoar/vue-file-explorer-core @cocoar/vue-ui
11
+ ```
12
+
13
+ `@cocoar/vue-ui` (for `CoarTree` + `CoarTreeNodeLabel`) is the only required peer. `@cocoar/vue-script-editor` is optional — it's only pulled if you want the resolver's Monaco-language-typed `language` field on `FileMeta`.
14
+
15
+ ## What you get
16
+
17
+ | Piece | Role |
18
+ |---|---|
19
+ | `AssetStore<T>` | The data-plane contract a backend implements (load, mutate, conflict-resolve). |
20
+ | `createInMemoryAssetStore` | Default impl with reactive latency / failure / sortMode / lazy / conflict knobs — perfect for demos, tests, and rapid prototyping. |
21
+ | `useFileExplorer({store})` | The composable. Owns tree + tab state machine, async-loading bookkeeping, blob-URL leases, `beforeunload` warning, keyboard-driven UX. Returns refs to bind to `<CoarTree>` plus ops to call on user input. |
22
+ | `defaultFileMetaFromName` + `resolveFileMeta` | 3-stage fallback (`asset.editor` → `config.getFileMeta` → extension heuristic) that picks an editor + language for every file. Extension table covers ~40 Monaco-supported languages plus markdown / PDF / image. |
23
+
24
+ ## Quick start
25
+
26
+ ```ts
27
+ import {
28
+ createInMemoryAssetStore,
29
+ useFileExplorer,
30
+ type Asset,
31
+ } from '@cocoar/vue-file-explorer-core';
32
+
33
+ const seed: Asset[] = [
34
+ { id: 'src', name: 'src', kind: 'folder', parentId: null },
35
+ { id: 'utils', name: 'utils.ts', kind: 'file', parentId: 'src' },
36
+ { id: 'docs', name: 'docs', kind: 'folder', parentId: null },
37
+ { id: 'readme', name: 'README.md', kind: 'file', parentId: 'docs' },
38
+ ];
39
+ const store = createInMemoryAssetStore({
40
+ initialTree: seed,
41
+ initialContent: {
42
+ utils: `export function clamp(...){}`,
43
+ readme: `# Hello`,
44
+ },
45
+ });
46
+
47
+ const fe = useFileExplorer({
48
+ store,
49
+ onError: (op, err, ctx) => console.warn(`[file-explorer] ${op}:`, err, ctx),
50
+ });
51
+ ```
52
+
53
+ Then bind into `<CoarTree>` and your own tab bar + editor dispatch:
54
+
55
+ ```vue
56
+ <CoarTree
57
+ :nodes="fe.rootNodes.value"
58
+ :get-id="fe.getId"
59
+ :get-children="fe.getChildren"
60
+ :get-label="fe.getLabel"
61
+ :is-expandable="fe.isExpandable"
62
+ v-model:expanded="fe.expanded.value"
63
+ v-model:selected="fe.selectedId.value"
64
+ draggable
65
+ renamable
66
+ @activate="fe.activateNode"
67
+ @rename="({node, newName}) => fe.rename(node.id, newName)"
68
+ @node-move="fe.moveNode"
69
+ >
70
+ <template #default="{ node }">
71
+ <CoarIcon :name="node.kind === 'folder' ? 'folder' : 'file'" />
72
+ <CoarTreeNodeLabel :label="node.name" />
73
+ </template>
74
+ </CoarTree>
75
+ ```
76
+
77
+ The composable also returns `openTabs`, `activeTab`, `breadcrumbPath`, `loadingNodes`, `savingNodes`, `pathOf`, plus imperative ops `openFile` / `saveTab` / `closeTab` / `pinTab` / `unpinTab` / `reorderTab` / `addFolder` / `addFiles` / `deleteNode` / `setContent` / `refresh`.
78
+
79
+ ## Wiring your own backend
80
+
81
+ Implement the `AssetStore<T>` methods — `createAssetStore(config)` returns the typed store:
82
+
83
+ ```ts
84
+ import { createAssetStore, type AssetStore } from '@cocoar/vue-file-explorer-core';
85
+
86
+ interface MyAsset { mimeType: string; size: number }
87
+
88
+ const store: AssetStore<MyAsset> = createAssetStore({
89
+ async loadTree() {
90
+ return (await fetch('/api/assets').then(r => r.json())) as Asset<MyAsset>[];
91
+ },
92
+ async loadContent(id) { return await fetch(`/api/assets/${id}`).then(r => r.text()); },
93
+ async createFolder(parentId, name) { /* … */ },
94
+ async createFile(parentId, name) { /* … */ },
95
+ async uploadFile(parentId, file) { /* … */ },
96
+ async save(id, content) { /* … */ },
97
+ async rename(id, newName) { /* … */ },
98
+ async delete(id) { /* … */ },
99
+ async move(id, parentId, position?) { /* … */ },
100
+ // optional — opt into lazy loading
101
+ async loadChildren(parentId) { /* … */ },
102
+ onError: (op, err, ctx) => myToast.error(err.message),
103
+ getFileMeta: (asset) => asset.payload?.mimeType === 'application/pdf'
104
+ ? { editor: 'pdf' }
105
+ : null,
106
+ });
107
+ ```
108
+
109
+ The composable's behavior is identical for any store implementation — eager / lazy mode is detected from the presence of `loadChildren`.
110
+
111
+ ## v1 scope
112
+
113
+ - ✅ `AssetStore<T>` contract + `createAssetStore` passthrough + `createInMemoryAssetStore` reference impl
114
+ - ✅ Lazy mode (`loadChildren` opt-in)
115
+ - ✅ Sort modes: `'folders-first'` (default), `'alphabetical'`, `'manual'`, custom comparator
116
+ - ✅ Conflict policy: `'rename'` (default), `'overwrite'`, `'prompt'`, `'error'`, custom function
117
+ - ✅ Tab state machine: preview / pinned, auto-pin-on-edit, dirty marker, save flow, drag-to-reorder
118
+ - ✅ Composable-driven inline rename via `CoarTree :renamable` + `CoarTreeNodeLabel`
119
+ - ✅ Error funnel via single `onError(op, err, ctx)` callback
120
+ - ❌ `<CoarFileExplorer>` wrapper component — for v1, consumers compose the shell themselves (see the playground POC for a 1280-LoC worked example). A wrapper is a candidate for v2 once the API surface settles.
121
+ - ❌ Split-pane editors, find-in-files, ETag / optimistic-conflict — deferred to post-v1.
@@ -0,0 +1,284 @@
1
+ import { CoarScriptEditorLanguage } from '@cocoar/vue-script-editor';
2
+ import { Ref } from 'vue';
3
+ /**
4
+ * Which built-in editor renders an asset.
5
+ * - `script` — `<CoarScriptEditor>` (Monaco); `language` picks the grammar.
6
+ * - `markdown` — `<CoarMarkdownEditor>` (Milkdown WYSIWYG).
7
+ * - `pdf` — `<CoarDocumentViewer>` with `pdfSource()`.
8
+ * - `image` — `<CoarDocumentViewer>` with `imageSource()`.
9
+ */
10
+ export type FileEditor = 'script' | 'markdown' | 'pdf' | 'image';
11
+ /** Editor dispatch metadata for one file. */
12
+ export interface FileMeta {
13
+ editor: FileEditor;
14
+ /** Only meaningful when `editor === 'script'`. */
15
+ language?: CoarScriptEditorLanguage;
16
+ }
17
+ /**
18
+ * The canonical shape the file-explorer works with.
19
+ *
20
+ * Hierarchy + name + kind live at the top level — the framework needs them.
21
+ * `payload` is the consumer's bag of domain data, fully generic.
22
+ *
23
+ * `editor` / `language` are optional escape hatches: when present they win
24
+ * over `config.getFileMeta` and the extension-based default.
25
+ */
26
+ export interface Asset<T = unknown> {
27
+ id: string;
28
+ name: string;
29
+ kind: 'folder' | 'file';
30
+ parentId: string | null;
31
+ /**
32
+ * Lazy-load hint. When present and the store implements `loadChildren`,
33
+ * the folder renders as expandable even before its children are fetched.
34
+ * Ignored in eager mode.
35
+ */
36
+ hasChildren?: boolean;
37
+ editor?: FileEditor;
38
+ language?: CoarScriptEditorLanguage;
39
+ /** Consumer's domain payload — anything not in the framework's contract. */
40
+ payload?: T;
41
+ }
42
+ /**
43
+ * What to do with the conflict the policy resolved.
44
+ *
45
+ * - `'overwrite'` — replace the existing entry; the store recursively
46
+ * deletes it and then performs the create/upload.
47
+ * - `'rename'` + newName — create with the supplied alternative name.
48
+ * - `'cancel'` — abort the op; the store throws a conflict error.
49
+ */
50
+ export type ConflictResolution = {
51
+ action: 'overwrite';
52
+ } | {
53
+ action: 'rename';
54
+ newName: string;
55
+ } | {
56
+ action: 'cancel';
57
+ };
58
+ /** Context handed to a function-shaped policy so it can build a smart response. */
59
+ export interface ConflictInfo<T = unknown> {
60
+ /** The colliding existing asset. */
61
+ existing: Asset<T>;
62
+ /** What the caller asked to add (name + kind only — no id yet). */
63
+ incoming: {
64
+ name: string;
65
+ kind: 'folder' | 'file';
66
+ };
67
+ /** Where the new entry would have lived. */
68
+ parentId: string | null;
69
+ /** Auto-rename candidate ("foo.txt" → "foo (2).txt"). */
70
+ suggestedRename: string;
71
+ }
72
+ /**
73
+ * How the store should handle a sibling-name collision on create / upload.
74
+ * Default: `'rename'` (silent auto-suffix — matches macOS Finder / VSCode).
75
+ *
76
+ * - `'rename'` — auto-rename: "foo.txt" → "foo (2).txt", etc.
77
+ * - `'overwrite'` — delete the existing entry (recursively) and proceed.
78
+ * - `'prompt'` — `window.prompt` for an alternative name, default to
79
+ * the auto-rename suggestion. Cancel → throws conflict.
80
+ * - `'error'` — never resolve; always throw the conflict error.
81
+ * - `(info) => …` — custom resolver; sync or async.
82
+ *
83
+ * `move` and `rename` deliberately bypass the policy — they're explicit
84
+ * user intent, not file additions, so silently changing the requested
85
+ * name would be surprising.
86
+ */
87
+ export type ConflictPolicy<T = unknown> = 'rename' | 'overwrite' | 'prompt' | 'error' | ((info: ConflictInfo<T>) => ConflictResolution | Promise<ConflictResolution>);
88
+ /** Operation tag passed to `onError` so the consumer can format its message. */
89
+ export type AssetOp = 'loadTree' | 'loadChildren' | 'loadContent' | 'createFolder' | 'createFile' | 'uploadFile' | 'save' | 'rename' | 'delete' | 'move';
90
+ /** Context object passed alongside `op` + `error` to `onError`. */
91
+ export interface AssetOpContext {
92
+ /** Affected asset id, when known. */
93
+ id?: string;
94
+ /** Target parent id, for create/move ops. */
95
+ parentId?: string | null;
96
+ /** Asset name, for create/rename ops. */
97
+ name?: string;
98
+ /** Original file, for uploadFile. */
99
+ file?: File;
100
+ }
101
+ /**
102
+ * The contract a backend implements. The composable calls these and adapts
103
+ * the result into reactive state. Implementations should throw on failure;
104
+ * the composable funnels throws through `onError`.
105
+ *
106
+ * Returned `Asset<T>` objects on create/upload MUST have a stable `id`
107
+ * already assigned by the backend — optimistic UI uses that id to reconcile.
108
+ */
109
+ export interface AssetStore<T = unknown> {
110
+ /**
111
+ * Eager: full hierarchy. Lazy: just root-level entries; mark folders with
112
+ * `hasChildren: true` so the tree knows they're expandable.
113
+ */
114
+ loadTree(): Promise<Asset<T>[]>;
115
+ /**
116
+ * Present → store opts into lazy loading. Called on first expand of each
117
+ * folder. Absent → composable runs fully eager off `loadTree()`.
118
+ */
119
+ loadChildren?(parentId: string): Promise<Asset<T>[]>;
120
+ /**
121
+ * Fetch the content of a file. Return value depends on the editor:
122
+ * - `script` / `markdown` → `string`
123
+ * - `pdf` / `image` → `string` (URL) OR `Blob`
124
+ *
125
+ * Composable caches the result; subsequent opens hit cache until invalidated.
126
+ */
127
+ loadContent(id: string): Promise<string | Blob>;
128
+ createFolder(parentId: string | null, name: string): Promise<Asset<T>>;
129
+ /**
130
+ * Create a new empty file. The editor + language are derived from `name`
131
+ * via the standard fallback chain (or carried on the returned `Asset` if
132
+ * the backend wants explicit control).
133
+ */
134
+ createFile(parentId: string | null, name: string): Promise<Asset<T>>;
135
+ /**
136
+ * Upload an OS File (from drop or `<input type=file>`). Distinct from
137
+ * `createFile` so backends can pick multipart / signed-URL transports.
138
+ */
139
+ uploadFile(parentId: string | null, file: File): Promise<Asset<T>>;
140
+ /** Persist new file content. Composable calls this on Ctrl+S. */
141
+ save(id: string, content: string | Blob): Promise<void>;
142
+ rename(id: string, newName: string): Promise<void>;
143
+ delete(id: string): Promise<void>;
144
+ /**
145
+ * Move `id` under `newParentId`. `position` is the destination index
146
+ * inside the new parent's children. When `undefined`, append at end.
147
+ * `newParentId === null` means "to the root".
148
+ */
149
+ move(id: string, newParentId: string | null, position?: number): Promise<void>;
150
+ }
151
+ /**
152
+ * `createAssetStore(config)` produces an `AssetStore<T>`. The config is
153
+ * just a struct of the same method signatures plus framework-level concerns
154
+ * (`onError`, `getFileMeta`).
155
+ *
156
+ * Splitting `AssetStoreConfig` from `AssetStore` lets us add cross-cutting
157
+ * helpers (debouncing, retry, optimistic flags) inside `createAssetStore`
158
+ * without leaking them into the runtime interface every consumer of the
159
+ * store sees.
160
+ */
161
+ export interface AssetStoreConfig<T = unknown> {
162
+ loadTree: AssetStore<T>['loadTree'];
163
+ loadChildren?: AssetStore<T>['loadChildren'];
164
+ loadContent: AssetStore<T>['loadContent'];
165
+ createFolder: AssetStore<T>['createFolder'];
166
+ createFile: AssetStore<T>['createFile'];
167
+ uploadFile: AssetStore<T>['uploadFile'];
168
+ save: AssetStore<T>['save'];
169
+ rename: AssetStore<T>['rename'];
170
+ delete: AssetStore<T>['delete'];
171
+ move: AssetStore<T>['move'];
172
+ /**
173
+ * Called whenever any store operation throws. The composable will already
174
+ * have rolled back the optimistic mutation by the time this fires.
175
+ * No return value — consumer decides what to show.
176
+ */
177
+ onError?: (op: AssetOp, error: unknown, ctx: AssetOpContext) => void;
178
+ /**
179
+ * Per-asset editor/language override. Runs AFTER `asset.editor` is
180
+ * checked but BEFORE the extension-based default. Use this when the
181
+ * editor choice depends on something other than the filename — MIME
182
+ * type, a backend `type` field, user preferences.
183
+ *
184
+ * Return `null` to fall through to the default heuristic.
185
+ */
186
+ getFileMeta?: (asset: Asset<T>) => FileMeta | null;
187
+ }
188
+ /**
189
+ * Comparator for two siblings, used in non-manual `sortMode`. Returns the
190
+ * standard `< 0 / 0 / > 0` semantics. Folders and files arrive mixed — the
191
+ * comparator decides any grouping (e.g. folders-first).
192
+ */
193
+ export type AssetComparator<T = unknown> = (a: Asset<T>, b: Asset<T>) => number;
194
+ /**
195
+ * How siblings inside a folder are ordered. Default `'folders-first'`
196
+ * matches VSCode's explorer; pick `'manual'` when you have a backend that
197
+ * can persist per-entry order (asset DB, CMS, etc.).
198
+ *
199
+ * In any non-manual mode the composable disables drop-between-siblings at
200
+ * the tree level — only drop-INTO-folder works.
201
+ */
202
+ export type SortMode<T = unknown> = 'manual' | 'folders-first' | 'alphabetical' | AssetComparator<T>;
203
+ /**
204
+ * Top-level config for `useFileExplorer(...)`. The store is the only
205
+ * required input — everything else is presentation polish.
206
+ */
207
+ export interface FileExplorerConfig<T = unknown> {
208
+ store: AssetStore<T>;
209
+ /**
210
+ * Sibling ordering strategy. Default `'folders-first'` (VSCode-style).
211
+ * See the `SortMode` docs for the trade-offs.
212
+ */
213
+ sortMode?: SortMode<T>;
214
+ /** Initial selection, if any. Pass the id of a file to preselect-and-open. */
215
+ initialSelectionId?: string;
216
+ /** Folder ids that should start expanded. Default: root-level folders. */
217
+ initialExpandedIds?: readonly string[];
218
+ }
219
+ /**
220
+ * Imperative + reactive surface returned by `useFileExplorer`. Mirrors the
221
+ * shape of `useTree`'s api (loading refs first, then methods).
222
+ *
223
+ * Tabs / breadcrumb / context-menu plumbing builds on top of this — they're
224
+ * not part of the data plane and don't belong here.
225
+ */
226
+ export interface FileExplorerApi<T = unknown> {
227
+ /** True while `store.loadTree()` is in flight (initial load only). */
228
+ readonly loading: Readonly<Ref<boolean>>;
229
+ /** Folder + file ids currently fetching children or content. */
230
+ readonly loadingNodes: Readonly<Ref<ReadonlySet<string>>>;
231
+ /** Ids with an in-flight save/rename/delete/move. */
232
+ readonly savingNodes: Readonly<Ref<ReadonlySet<string>>>;
233
+ /** Reactive tree, ordered. Pass directly to `<CoarTree :builder>`. */
234
+ readonly tree: Readonly<Ref<readonly Asset<T>[]>>;
235
+ /**
236
+ * Whether sibling reordering is honored by the configured `sortMode`.
237
+ * Read by the tree wiring to flip CoarTree between `'reorder'` and
238
+ * `'move'` draggable modes. Reactive so consumers can toggle sort modes
239
+ * at runtime (e.g. a "manual reorder" toggle in the toolbar).
240
+ */
241
+ readonly reorderable: Readonly<Ref<boolean>>;
242
+ createFolder(parentId: string | null, name: string): Promise<Asset<T>>;
243
+ createFile(parentId: string | null, name: string): Promise<Asset<T>>;
244
+ uploadFiles(parentId: string | null, files: readonly File[]): Promise<Asset<T>[]>;
245
+ save(id: string, content: string | Blob): Promise<void>;
246
+ rename(id: string, newName: string): Promise<void>;
247
+ delete(id: string): Promise<void>;
248
+ /**
249
+ * `position` is honored only when `sortMode === 'manual'`; otherwise it
250
+ * is silently dropped (the comparator decides the final position after
251
+ * the parent change).
252
+ */
253
+ move(id: string, newParentId: string | null, position?: number): Promise<void>;
254
+ /**
255
+ * Resolve a file's editor/language using the 3-stage fallback chain.
256
+ * Returns `null` for unsupported / likely-binary files (caller logs +
257
+ * skips, same as the POC does today).
258
+ */
259
+ fileMeta(asset: Asset<T>): FileMeta | null;
260
+ /** Force a re-fetch of the tree (or one folder). */
261
+ refresh(folderId?: string | null): Promise<void>;
262
+ }
263
+ /**
264
+ * Wraps a config into a fully-typed `AssetStore<T>`. Today this is a thin
265
+ * passthrough; the wrapper exists so future cross-cutting concerns
266
+ * (request dedup, retry, telemetry) have a home.
267
+ */
268
+ export declare function createAssetStore<T = unknown>(config: AssetStoreConfig<T>): AssetStore<T>;
269
+ /**
270
+ * Browser-only default implementation. Backed by a `ref<Asset<T>[]>` plus
271
+ * an `id → content` map. Used by the playground POC and by any consumer
272
+ * that wants offline / demo behaviour.
273
+ */
274
+ export declare function createInMemoryAssetStore<T = unknown>(options?: {
275
+ /** Seed data. Optimistic ops mutate this ref in place. */
276
+ initialTree?: readonly Asset<T>[];
277
+ /** Seed file contents by id. */
278
+ initialContent?: Readonly<Record<string, string | Blob>>;
279
+ /** Artificial latency per op, for visualising loading states. Default 0. */
280
+ latencyMs?: number;
281
+ /** Random-failure rate (0..1), for exercising the error path. Default 0. */
282
+ failureRate?: number;
283
+ }): AssetStore<T>;
284
+ //# sourceMappingURL=asset-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-store.d.ts","sourceRoot":"","sources":["../src/asset-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAI/B;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjE,6CAA6C;AAC7C,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,GAAG,OAAO;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,CAAC;CACb;AAID;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEzB,mFAAmF;AACnF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,oCAAoC;IACpC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACnB,mEAAmE;IACnE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;KAAE,CAAC;IACpD,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAClC,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,OAAO,GACP,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAElF,gFAAgF;AAChF,MAAM,MAAM,OAAO,GACf,UAAU,GACV,cAAc,GACd,aAAa,GACb,cAAc,GACd,YAAY,GACZ,YAAY,GACZ,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,MAAM,CAAC;AAEX,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IAGrC;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhC;;;OAGG;IACH,YAAY,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAErD;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAIhD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,iEAAiE;IACjE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;;OAIG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAID;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAC7C,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAC1C,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5C,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IAErE;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAG,IAAI,CAAC;CACpD;AAID;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;AAEhF;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,OAAO,IAC5B,QAAQ,GACR,eAAe,GACf,cAAc,GACd,eAAe,CAAC,CAAC,CAAC,CAAC;AAEvB;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvB,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAG1C,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1D,qDAAqD;IACrD,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEzD,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAElD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAI7C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAClF,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAI/E;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC;IAE3C,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAID;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAClD,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC1B,UAAU,CAAC,CAAC,CAAC,CAAC;AAEjB;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE;IACtE,0DAA0D;IAC1D,WAAW,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,gCAAgC;IAChC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACzD,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
2
+ import { Asset, AssetStore, AssetStoreConfig, ConflictPolicy } from './asset-store';
3
+ export declare function createAssetStore<T = unknown>(config: AssetStoreConfig<T>): AssetStore<T>;
4
+ export interface InMemoryAssetStoreOptions<T = unknown> {
5
+ /** Seed data. Mutations replace this ref's contents in place. */
6
+ initialTree?: readonly Asset<T>[];
7
+ /** Seed file contents by id. */
8
+ initialContent?: Readonly<Record<string, string | Blob>>;
9
+ /**
10
+ * Artificial latency per op, for visualising loading states. Default 0.
11
+ * Reactive: pass a `Ref<number>` / getter to retune at runtime (the
12
+ * playground simulator dropdown does exactly that).
13
+ */
14
+ latencyMs?: MaybeRefOrGetter<number>;
15
+ /**
16
+ * Random-failure rate (0..1), for exercising the error path. Default 0.
17
+ * Reactive (see `latencyMs`).
18
+ */
19
+ failureRate?: MaybeRefOrGetter<number>;
20
+ /**
21
+ * ID factory. Default: `crypto.randomUUID()`. Override for tests that
22
+ * need stable ids.
23
+ */
24
+ idFactory?: () => string;
25
+ /**
26
+ * What to do when a create / upload collides with an existing sibling
27
+ * name. Default `'rename'` (auto-suffix, macOS Finder pattern). Reactive
28
+ * via `Ref` / getter so the simulator can flip policies live.
29
+ */
30
+ onConflict?: MaybeRefOrGetter<ConflictPolicy<T>>;
31
+ /**
32
+ * Opt into lazy loading. When `true`:
33
+ * - `loadTree()` only returns root-level entries, enriched with
34
+ * `hasChildren: boolean` so the tree knows which folders are
35
+ * expandable without their kids loaded.
36
+ * - `loadChildren(parentId)` is exposed and returns one level deep.
37
+ * - `_assets` is a computed projection over a `_publishedIds` Set —
38
+ * only the published subset is visible to the composable. The full
39
+ * dataset still lives in `_complete` for the store's own bookkeeping.
40
+ * Default: `false` (eager — composable sees everything from the start).
41
+ */
42
+ lazy?: boolean;
43
+ }
44
+ /**
45
+ * In-memory store + a peek at its raw state. Returned together so the POC
46
+ * (and tests) can inspect / mutate the underlying ref without going through
47
+ * the async API — useful for seeding, debugging, snapshotting.
48
+ *
49
+ * `_assets` is a reactive projection. In eager mode it equals the full data
50
+ * set; in lazy mode it equals only the published subset (root + whatever
51
+ * has been fetched on expand).
52
+ */
53
+ export interface InMemoryAssetStore<T = unknown> extends AssetStore<T> {
54
+ /** Published subset (computed in lazy mode, equals everything in eager). */
55
+ readonly _assets: Ref<Asset<T>[]> | ComputedRef<Asset<T>[]>;
56
+ /** The raw content map. Mutate at your own risk. */
57
+ readonly _contents: Map<string, string | Blob>;
58
+ }
59
+ export declare function createInMemoryAssetStore<T = unknown>(options?: InMemoryAssetStoreOptions<T>): InMemoryAssetStore<T>;
60
+ //# sourceMappingURL=create-asset-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-asset-store.d.ts","sourceRoot":"","sources":["../src/create-asset-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA0B,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAEhG,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAsB,MAAM,eAAe,CAAC;AAI7G,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAgBxF;AAID,MAAM,WAAW,yBAAyB,CAAC,CAAC,GAAG,OAAO;IACpD,iEAAiE;IACjE,WAAW,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,gCAAgC;IAChC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACzD;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;IACpE,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5D,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CAChD;AAED,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,OAAO,EAClD,OAAO,GAAE,yBAAyB,CAAC,CAAC,CAAM,GACzC,kBAAkB,CAAC,CAAC,CAAC,CAqVvB"}
@@ -0,0 +1,36 @@
1
+ import { Asset, FileMeta } from './asset-store';
2
+ /** One row in an asset info / details panel. */
3
+ export interface AssetProperty {
4
+ /**
5
+ * Stable identifier for the row (`'name'`, `'type'`, `'language'`,
6
+ * `'extension'`, `'path'`). Lets consumers key a `v-for`, filter out rows
7
+ * they don't want, or splice their own rows in at a known position.
8
+ */
9
+ key: string;
10
+ /** Human-readable label, e.g. `'Type'`. */
11
+ label: string;
12
+ /** Human-readable value, e.g. `'Markdown'`. */
13
+ value: string;
14
+ }
15
+ /** Inputs `buildAssetProperties` needs beyond the asset itself. */
16
+ export interface DescribeAssetContext {
17
+ /**
18
+ * Resolved editor/language for the asset, or `null` for folders and
19
+ * unrecognised files. `useFileExplorer().describeAsset` passes
20
+ * `fileMeta(asset)` for files and `null` for folders.
21
+ */
22
+ meta: FileMeta | null;
23
+ /**
24
+ * Name path from the tree root to the asset, inclusive — i.e. the result of
25
+ * `pathOf(asset.id)`. A single-element path (a root-level asset) omits the
26
+ * `'path'` row, since it would just repeat the name.
27
+ */
28
+ path: readonly string[];
29
+ }
30
+ /**
31
+ * Build the default, framework-known property rows for an asset. Folders get
32
+ * Name + Type (+ Path); files additionally get Language (script editor only),
33
+ * Extension, and Path. Returns a fresh array each call.
34
+ */
35
+ export declare function buildAssetProperties<T>(asset: Asset<T>, ctx: DescribeAssetContext): AssetProperty[];
36
+ //# sourceMappingURL=describe-asset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe-asset.d.ts","sourceRoot":"","sources":["../src/describe-asset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAErD,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB;AAkDD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,GAAG,EAAE,oBAAoB,GACxB,aAAa,EAAE,CAyBjB"}
@@ -0,0 +1,21 @@
1
+ import { Asset, AssetStoreConfig, FileMeta } from './asset-store';
2
+ /**
3
+ * Map a filename to its `{ editor, language }`. Returns `null` for
4
+ * extensions that are recognised as binary-only (.exe, .zip, .mp4, …).
5
+ *
6
+ * The caller is expected to skip unrecognised files with a warning —
7
+ * matching the POC's behaviour.
8
+ */
9
+ export declare function defaultFileMetaFromName(name: string): FileMeta | null;
10
+ /**
11
+ * 3-stage fallback: `asset.editor` wins → then `config.getFileMeta(asset)`
12
+ * → then `defaultFileMetaFromName(asset.name)`. Returns `null` if all three
13
+ * decline (consumer override returned null + name is unrecognised).
14
+ *
15
+ * `language` is normalized to `'plaintext'` whenever the resolved editor is
16
+ * `'script'` but no language was supplied. Saves every consumer the
17
+ * `?? 'plaintext'` dance when binding to `<CoarScriptEditor :language>`;
18
+ * matches Monaco's own fallback for unrecognized files.
19
+ */
20
+ export declare function resolveFileMeta<T>(asset: Asset<T>, config?: Pick<AssetStoreConfig<T>, 'getFileMeta'>): FileMeta | null;
21
+ //# sourceMappingURL=file-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-meta.d.ts","sourceRoot":"","sources":["../src/file-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAyErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,MAAM,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,GAChD,QAAQ,GAAG,IAAI,CAOjB"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `@cocoar/vue-file-explorer-core` — VSCode-style file/asset explorer composable
3
+ * over a pluggable `AssetStore<T>` backend.
4
+ *
5
+ * Three layers:
6
+ *
7
+ * - **`AssetStore<T>` contract** + types — what a backend implements.
8
+ * The store is the data plane: load, mutate, conflict-resolve. The
9
+ * composable knows nothing about HTTP / IndexedDB / etc.
10
+ * - **`createInMemoryAssetStore`** — reference implementation for
11
+ * browser-only / demo use. Configurable latency, failure simulation,
12
+ * lazy mode, conflict policy.
13
+ * - **`useFileExplorer({store, ...})`** — the composable that wires the
14
+ * store into reactive tree + tab state + async-loading bookkeeping +
15
+ * keyboard-driven UX. Returns the full surface a file-explorer view
16
+ * needs: refs to bind to `<CoarTree>`, ops to call on user input,
17
+ * `revealInTree` / `breadcrumbPath` / `pathOf` for navigation.
18
+ *
19
+ * See the playground POC (apps/playground/src/views/FileExplorerPocView.vue)
20
+ * for a worked end-to-end example.
21
+ */
22
+ export type { Asset, AssetComparator, AssetOp, AssetOpContext, AssetStore, AssetStoreConfig, ConflictInfo, ConflictPolicy, ConflictResolution, FileEditor, FileExplorerApi, FileExplorerConfig, FileMeta, SortMode, } from './asset-store';
23
+ export { createAssetStore, createInMemoryAssetStore, type InMemoryAssetStore, type InMemoryAssetStoreOptions, } from './create-asset-store';
24
+ export { defaultFileMetaFromName, resolveFileMeta, } from './file-meta';
25
+ export { buildAssetProperties, type AssetProperty, type DescribeAssetContext, } from './describe-asset';
26
+ export { useFileExplorer, type OpenTab, type UseFileExplorerOptions, type UseFileExplorerReturn, } from './use-file-explorer';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,KAAK,EACL,eAAe,EACf,OAAO,EACP,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,QAAQ,GACT,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,uBAAuB,EACvB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,eAAe,EACf,KAAK,OAAO,EACZ,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC"}