@axium/storage 0.6.1 → 0.6.2

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/lib/Add.svelte ADDED
@@ -0,0 +1,93 @@
1
+ <script lang="ts">
2
+ import { forMime } from '@axium/core/icons';
3
+ import { FormDialog, Icon, Popover, Upload } from '@axium/server/components';
4
+ import { uploadItem } from '@axium/storage/client';
5
+ import type { StorageItemMetadata } from '@axium/storage/common';
6
+
7
+ const { parentId, onadd }: { parentId?: string; onadd?(item: StorageItemMetadata): void } = $props();
8
+
9
+ let uploadDialog = $state<HTMLDialogElement>()!;
10
+ let input = $state<HTMLInputElement>();
11
+
12
+ let createDialog = $state<HTMLDialogElement>()!;
13
+ let createType = $state<string>();
14
+ let createIncludesContent = $state(false);
15
+ </script>
16
+
17
+ {#snippet _item(type: string, text: string, includeContent: boolean = false)}
18
+ <span
19
+ class="icon-text add-menu-item"
20
+ onclick={() => {
21
+ createType = type;
22
+ createIncludesContent = includeContent;
23
+ createDialog.showModal();
24
+ }}
25
+ >
26
+ <Icon i={forMime(type)} />
27
+ {text}
28
+ </span>
29
+ {/snippet}
30
+
31
+ <Popover>
32
+ {#snippet toggle()}
33
+ <button class="icon-text"><Icon i="plus" />Add</button>
34
+ {/snippet}
35
+
36
+ <div class="add-menu">
37
+ <span class="icon-text add-menu-item" onclick={() => uploadDialog.showModal()}><Icon i="upload" />Upload</span>
38
+ {@render _item('inode/directory', 'New Folder')}
39
+ {@render _item('text/plain', 'Plain Text')}
40
+ {@render _item('text/x-uri', 'URL', true)}
41
+ </div>
42
+ </Popover>
43
+
44
+ <FormDialog
45
+ bind:dialog={uploadDialog}
46
+ submitText="Upload"
47
+ submit={async () => {
48
+ for (const file of input?.files!) {
49
+ const item = await uploadItem(file, { parentId });
50
+ onadd?.(item);
51
+ }
52
+ }}
53
+ >
54
+ <Upload bind:input multiple />
55
+ </FormDialog>
56
+
57
+ <FormDialog
58
+ bind:dialog={createDialog}
59
+ submitText="Create"
60
+ submit={async (data: { name: string; content?: string }) => {
61
+ const file = new File(createIncludesContent ? [data.content!] : [], data.name, { type: createType });
62
+ const item = await uploadItem(file, { parentId });
63
+ onadd?.(item);
64
+ }}
65
+ >
66
+ <div>
67
+ <label for="name">Name</label>
68
+ <input name="name" type="text" required />
69
+ </div>
70
+ {#if createIncludesContent}
71
+ <div>
72
+ <label for="content">Content</label>
73
+ <input name="content" type="text" size="40" required />
74
+ </div>
75
+ {/if}
76
+ </FormDialog>
77
+
78
+ <style>
79
+ .add-menu {
80
+ display: flex;
81
+ flex-direction: column;
82
+ }
83
+
84
+ .add-menu-item {
85
+ border-radius: 0.5em;
86
+ padding: 0.25em 0.25em;
87
+ }
88
+
89
+ .add-menu-item:hover {
90
+ cursor: pointer;
91
+ background-color: #4455;
92
+ }
93
+ </style>
package/lib/List.svelte CHANGED
@@ -7,7 +7,7 @@
7
7
  import '../styles/list.css';
8
8
 
9
9
  let {
10
- items = $bindable([]),
10
+ items = $bindable(),
11
11
  appMode,
12
12
  emptyText = 'Folder is empty.',
13
13
  }: { appMode?: boolean; items: StorageItemMetadata[]; emptyText?: string } = $props();
package/lib/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { default as StorageAdd } from './Add.svelte';
1
2
  export { default as StorageList } from './List.svelte';
2
3
  export { default as StorageSidebar } from './Sidebar.svelte';
3
4
  export { default as StorageSidebarItem } from './SidebarItem.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/storage",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
5
5
  "description": "User file storage for Axium",
6
6
  "funding": {
@@ -2,9 +2,8 @@
2
2
  import { Icon } from '@axium/server/components';
3
3
  import { StorageUsage } from '@axium/storage/components';
4
4
  import { capitalize } from 'utilium';
5
- import type { LayoutProps } from './$types';
6
5
 
7
- let { children, data }: LayoutProps = $props();
6
+ let { children, data } = $props();
8
7
  </script>
9
8
 
10
9
  <div class="app">
@@ -15,8 +15,5 @@ export async function load({ url, route }: LayoutLoadEvent) {
15
15
  { name: 'shared', href: '/files/shared', icon: 'user-group', active: route.id.endsWith('/files/shared') },
16
16
  ] satisfies { name: string; href: LayoutRouteId; icon: string; active: boolean }[];
17
17
 
18
- return {
19
- session: await getCurrentSession(),
20
- tabs,
21
- };
18
+ return { session, tabs };
22
19
  }
@@ -1,12 +1,13 @@
1
1
  <script lang="ts">
2
- import { StorageList } from '@axium/storage/components';
3
- import type { PageProps } from './$types';
2
+ import { StorageAdd, StorageList } from '@axium/storage/components';
4
3
 
5
- const { data }: PageProps = $props();
4
+ const { data } = $props();
5
+ let items = $state(data.items!);
6
6
  </script>
7
7
 
8
8
  <svelte:head>
9
9
  <title>Files</title>
10
10
  </svelte:head>
11
11
 
12
- <StorageList appMode bind:items={data.items} />
12
+ <StorageList appMode bind:items />
13
+ <StorageAdd onadd={item => items.push(item)} />
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { Icon } from '@axium/server/components';
3
- import { StorageList } from '@axium/storage/components';
3
+ import { StorageAdd, StorageList } from '@axium/storage/components';
4
4
  import type { PageProps } from './$types';
5
5
  import { updateItemMetadata } from '@axium/storage/client';
6
6
 
@@ -26,6 +26,7 @@
26
26
  </button>
27
27
  {:else if item.type == 'inode/directory'}
28
28
  <StorageList appMode bind:items />
29
+ <StorageAdd parentId={item.id} onadd={item => items.push(item)} />
29
30
  {:else}
30
31
  <p>No preview available.</p>
31
32
  {/if}