@brftech/filex-core 0.1.56 → 0.1.60

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 (82) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +108 -108
  3. package/dist/{ArchiveViewer-CJdaw5x3.js → ArchiveViewer-CbUUEREI.js} +20 -20
  4. package/dist/ArchiveViewer-CbUUEREI.js.map +1 -0
  5. package/dist/{CsvViewer-QYx_tePQ.js → CsvViewer-72rDsQJX.js} +3 -3
  6. package/dist/CsvViewer-72rDsQJX.js.map +1 -0
  7. package/dist/{DrawioViewer-GWt0TyB7.js → DrawioViewer-DSyMwGvg.js} +7 -7
  8. package/dist/DrawioViewer-DSyMwGvg.js.map +1 -0
  9. package/dist/{EpubViewer-Je0ywklQ.js → EpubViewer-DvDa17d7.js} +3 -3
  10. package/dist/EpubViewer-DvDa17d7.js.map +1 -0
  11. package/dist/{IpynbViewer-TsB4gqP-.js → IpynbViewer-DibIkdsz.js} +3 -3
  12. package/dist/IpynbViewer-DibIkdsz.js.map +1 -0
  13. package/dist/{MermaidViewer-CXfeDS-7.js → MermaidViewer-BoFLtGvl.js} +3 -3
  14. package/dist/MermaidViewer-BoFLtGvl.js.map +1 -0
  15. package/dist/{PsdViewer-VtPpxKVe.js → PsdViewer-K2iZkwax.js} +3 -3
  16. package/dist/PsdViewer-K2iZkwax.js.map +1 -0
  17. package/dist/{TiffViewer-OINn9bbb.js → TiffViewer-JzDzbqpO.js} +3 -3
  18. package/dist/TiffViewer-JzDzbqpO.js.map +1 -0
  19. package/dist/{Viewer3D-xvvyiWHd.js → Viewer3D-WEMYCP8l.js} +7 -7
  20. package/dist/Viewer3D-WEMYCP8l.js.map +1 -0
  21. package/dist/filex-core.js +1 -1
  22. package/dist/filex-core.umd.cjs +4 -4
  23. package/dist/filex-core.umd.cjs.map +1 -1
  24. package/dist/{index-CmSYzt6L.js → index-B5YT-m5Q.js} +209 -209
  25. package/dist/index-B5YT-m5Q.js.map +1 -0
  26. package/dist/style.css +1 -1
  27. package/dist/useViewerFetch-czqbd2Lj.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/Breadcrumb.vue +282 -282
  30. package/src/components/ContextMenu.vue +152 -152
  31. package/src/components/GridView.vue +166 -166
  32. package/src/components/ListView.vue +212 -212
  33. package/src/components/PendingOpsTray.vue +91 -91
  34. package/src/components/RecentlyOpened.vue +155 -155
  35. package/src/components/StarButton.vue +101 -101
  36. package/src/components/TagPicker.vue +184 -184
  37. package/src/components/Toolbar.vue +220 -220
  38. package/src/components/UploadProgress.vue +78 -78
  39. package/src/composables/useFileApi.ts +692 -692
  40. package/src/composables/useKeyboardShortcuts.ts +144 -144
  41. package/src/composables/useLocale.ts +60 -60
  42. package/src/composables/useMonacoLoader.ts +98 -98
  43. package/src/composables/usePendingOps.ts +200 -200
  44. package/src/composables/useSelection.ts +81 -81
  45. package/src/composables/useUploadChunked.ts +250 -250
  46. package/src/composables/useViewerFetch.ts +58 -58
  47. package/src/index.ts +80 -80
  48. package/src/locales/en.ts +122 -122
  49. package/src/locales/index.ts +12 -12
  50. package/src/locales/tr.ts +122 -122
  51. package/src/modals/DeleteConfirmModal.vue +32 -32
  52. package/src/modals/Modal.vue +104 -104
  53. package/src/modals/NewFolderModal.vue +64 -64
  54. package/src/modals/PermissionsModal.vue +815 -815
  55. package/src/modals/PreviewModal.vue +1070 -1070
  56. package/src/modals/RenameModal.vue +58 -58
  57. package/src/modals/ShareModal.vue +135 -135
  58. package/src/styles/base.css +1224 -1224
  59. package/src/styles/variables.css +90 -90
  60. package/src/types/FileNode.ts +136 -136
  61. package/src/types/index.ts +27 -27
  62. package/src/types/peers.d.ts +45 -45
  63. package/src/viewers/ArchiveViewer.vue +186 -186
  64. package/src/viewers/CsvViewer.vue +319 -319
  65. package/src/viewers/DrawioViewer.vue +243 -243
  66. package/src/viewers/EpubViewer.vue +307 -307
  67. package/src/viewers/IpynbViewer.vue +365 -365
  68. package/src/viewers/MermaidViewer.vue +259 -259
  69. package/src/viewers/PdfViewer.vue +562 -562
  70. package/src/viewers/PsdViewer.vue +264 -264
  71. package/src/viewers/TiffViewer.vue +273 -273
  72. package/src/viewers/Viewer3D.vue +120 -120
  73. package/dist/ArchiveViewer-CJdaw5x3.js.map +0 -1
  74. package/dist/CsvViewer-QYx_tePQ.js.map +0 -1
  75. package/dist/DrawioViewer-GWt0TyB7.js.map +0 -1
  76. package/dist/EpubViewer-Je0ywklQ.js.map +0 -1
  77. package/dist/IpynbViewer-TsB4gqP-.js.map +0 -1
  78. package/dist/MermaidViewer-CXfeDS-7.js.map +0 -1
  79. package/dist/PsdViewer-VtPpxKVe.js.map +0 -1
  80. package/dist/TiffViewer-OINn9bbb.js.map +0 -1
  81. package/dist/Viewer3D-xvvyiWHd.js.map +0 -1
  82. package/dist/index-CmSYzt6L.js.map +0 -1
@@ -1,184 +1,184 @@
1
- <script setup lang="ts">
2
- /**
3
- * TagPicker — small chip list with add/remove for a node.
4
- *
5
- * Reads `GET /api/files/manager/tags?node_id=…` on mount, writes the
6
- * full new array via `POST /api/files/manager/tags`.
7
- *
8
- * Tag colors are deterministic: hash(name) → palette index. Consumers
9
- * can override with the `palette` prop.
10
- */
11
- import { ref, watch, onMounted, computed } from 'vue';
12
-
13
- const props = defineProps<{
14
- nodeId: number;
15
- apiBase?: string;
16
- authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
17
- /** Optional list of palette swatches; one is picked per tag deterministically. */
18
- palette?: string[];
19
- }>();
20
-
21
- const emit = defineEmits<{
22
- (e: 'change', tags: string[]): void;
23
- (e: 'error', message: string): void;
24
- }>();
25
-
26
- const tags = ref<string[]>([]);
27
- const loading = ref(false);
28
- const adding = ref(false);
29
- const newTag = ref('');
30
-
31
- const palette = computed(() => props.palette ?? [
32
- '#ef4444', '#f59e0b', '#10b981', '#3b82f6',
33
- '#8b5cf6', '#ec4899', '#14b8a6', '#f97316',
34
- ]);
35
-
36
- function colorFor(tag: string): string {
37
- let h = 0;
38
- for (let i = 0; i < tag.length; i++) h = (h * 31 + tag.charCodeAt(i)) | 0;
39
- const arr = palette.value;
40
- return arr[Math.abs(h) % arr.length];
41
- }
42
-
43
- async function buildHeaders(extra: Record<string, string> = {}): Promise<Record<string, string>> {
44
- return { ...(await (props.authHeaders ?? (() => ({})))()), ...extra };
45
- }
46
-
47
- async function load() {
48
- loading.value = true;
49
- try {
50
- const base = props.apiBase ?? '';
51
- const res = await fetch(`${base}/api/files/manager/tags?node_id=${props.nodeId}`, {
52
- headers: await buildHeaders(),
53
- credentials: 'include',
54
- });
55
- if (res.ok) {
56
- const body = await res.json();
57
- tags.value = Array.isArray(body.tags) ? body.tags : [];
58
- }
59
- } catch (err) {
60
- emit('error', err instanceof Error ? err.message : String(err));
61
- } finally {
62
- loading.value = false;
63
- }
64
- }
65
-
66
- async function persist(next: string[]) {
67
- const previous = [...tags.value];
68
- tags.value = next;
69
- try {
70
- const base = props.apiBase ?? '';
71
- const res = await fetch(`${base}/api/files/manager/tags`, {
72
- method: 'POST',
73
- headers: await buildHeaders({ 'Content-Type': 'application/json' }),
74
- credentials: 'include',
75
- body: JSON.stringify({ node_id: props.nodeId, tags: next }),
76
- });
77
- if (!res.ok) throw new Error(`tag save failed: ${res.status}`);
78
- emit('change', next);
79
- } catch (err) {
80
- tags.value = previous;
81
- emit('error', err instanceof Error ? err.message : String(err));
82
- }
83
- }
84
-
85
- function add() {
86
- const v = newTag.value.trim();
87
- if (!v || tags.value.includes(v)) {
88
- newTag.value = '';
89
- adding.value = false;
90
- return;
91
- }
92
- persist([...tags.value, v]);
93
- newTag.value = '';
94
- adding.value = false;
95
- }
96
-
97
- function remove(tag: string) {
98
- persist(tags.value.filter((t) => t !== tag));
99
- }
100
-
101
- onMounted(load);
102
- watch(() => props.nodeId, load);
103
- </script>
104
-
105
- <template>
106
- <div class="filex-tag-picker" :class="{ 'is-loading': loading }">
107
- <span
108
- v-for="tag in tags"
109
- :key="tag"
110
- class="filex-tag"
111
- :style="{ '--filex-tag-color': colorFor(tag) }"
112
- >
113
- {{ tag }}
114
- <button class="filex-tag-x" type="button" @click="remove(tag)" aria-label="Remove tag">×</button>
115
- </span>
116
-
117
- <form v-if="adding" class="filex-tag-add" @submit.prevent="add">
118
- <input
119
- v-model="newTag"
120
- autofocus
121
- placeholder="tag name"
122
- @blur="add"
123
- @keydown.escape="adding = false; newTag = ''"
124
- />
125
- </form>
126
- <button v-else class="filex-tag-add-btn" type="button" @click="adding = true">+ Add tag</button>
127
- </div>
128
- </template>
129
-
130
- <style scoped>
131
- .filex-tag-picker {
132
- display: flex;
133
- flex-wrap: wrap;
134
- gap: 6px;
135
- align-items: center;
136
- }
137
- .filex-tag-picker.is-loading {
138
- opacity: 0.6;
139
- pointer-events: none;
140
- }
141
- .filex-tag {
142
- display: inline-flex;
143
- align-items: center;
144
- gap: 4px;
145
- border-radius: 999px;
146
- padding: 2px 10px;
147
- font-size: 12px;
148
- font-weight: 500;
149
- color: #fff;
150
- background: var(--filex-tag-color);
151
- }
152
- .filex-tag-x {
153
- background: transparent;
154
- border: none;
155
- color: rgba(255, 255, 255, 0.85);
156
- cursor: pointer;
157
- padding: 0 2px;
158
- font-size: 14px;
159
- line-height: 1;
160
- }
161
- .filex-tag-x:hover {
162
- color: #fff;
163
- }
164
- .filex-tag-add input {
165
- border: 1px solid var(--filex-border, #d1d5db);
166
- border-radius: 12px;
167
- padding: 2px 10px;
168
- font-size: 12px;
169
- width: 110px;
170
- }
171
- .filex-tag-add-btn {
172
- border: 1px dashed var(--filex-border, #d1d5db);
173
- background: transparent;
174
- border-radius: 999px;
175
- padding: 2px 10px;
176
- font-size: 12px;
177
- color: var(--filex-text-muted, #6b7280);
178
- cursor: pointer;
179
- }
180
- .filex-tag-add-btn:hover {
181
- border-color: var(--filex-accent, #6366f1);
182
- color: var(--filex-accent, #6366f1);
183
- }
184
- </style>
1
+ <script setup lang="ts">
2
+ /**
3
+ * TagPicker — small chip list with add/remove for a node.
4
+ *
5
+ * Reads `GET /api/files/manager/tags?node_id=…` on mount, writes the
6
+ * full new array via `POST /api/files/manager/tags`.
7
+ *
8
+ * Tag colors are deterministic: hash(name) → palette index. Consumers
9
+ * can override with the `palette` prop.
10
+ */
11
+ import { ref, watch, onMounted, computed } from 'vue';
12
+
13
+ const props = defineProps<{
14
+ nodeId: number;
15
+ apiBase?: string;
16
+ authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
17
+ /** Optional list of palette swatches; one is picked per tag deterministically. */
18
+ palette?: string[];
19
+ }>();
20
+
21
+ const emit = defineEmits<{
22
+ (e: 'change', tags: string[]): void;
23
+ (e: 'error', message: string): void;
24
+ }>();
25
+
26
+ const tags = ref<string[]>([]);
27
+ const loading = ref(false);
28
+ const adding = ref(false);
29
+ const newTag = ref('');
30
+
31
+ const palette = computed(() => props.palette ?? [
32
+ '#ef4444', '#f59e0b', '#10b981', '#3b82f6',
33
+ '#8b5cf6', '#ec4899', '#14b8a6', '#f97316',
34
+ ]);
35
+
36
+ function colorFor(tag: string): string {
37
+ let h = 0;
38
+ for (let i = 0; i < tag.length; i++) h = (h * 31 + tag.charCodeAt(i)) | 0;
39
+ const arr = palette.value;
40
+ return arr[Math.abs(h) % arr.length];
41
+ }
42
+
43
+ async function buildHeaders(extra: Record<string, string> = {}): Promise<Record<string, string>> {
44
+ return { ...(await (props.authHeaders ?? (() => ({})))()), ...extra };
45
+ }
46
+
47
+ async function load() {
48
+ loading.value = true;
49
+ try {
50
+ const base = props.apiBase ?? '';
51
+ const res = await fetch(`${base}/api/files/manager/tags?node_id=${props.nodeId}`, {
52
+ headers: await buildHeaders(),
53
+ credentials: 'include',
54
+ });
55
+ if (res.ok) {
56
+ const body = await res.json();
57
+ tags.value = Array.isArray(body.tags) ? body.tags : [];
58
+ }
59
+ } catch (err) {
60
+ emit('error', err instanceof Error ? err.message : String(err));
61
+ } finally {
62
+ loading.value = false;
63
+ }
64
+ }
65
+
66
+ async function persist(next: string[]) {
67
+ const previous = [...tags.value];
68
+ tags.value = next;
69
+ try {
70
+ const base = props.apiBase ?? '';
71
+ const res = await fetch(`${base}/api/files/manager/tags`, {
72
+ method: 'POST',
73
+ headers: await buildHeaders({ 'Content-Type': 'application/json' }),
74
+ credentials: 'include',
75
+ body: JSON.stringify({ node_id: props.nodeId, tags: next }),
76
+ });
77
+ if (!res.ok) throw new Error(`tag save failed: ${res.status}`);
78
+ emit('change', next);
79
+ } catch (err) {
80
+ tags.value = previous;
81
+ emit('error', err instanceof Error ? err.message : String(err));
82
+ }
83
+ }
84
+
85
+ function add() {
86
+ const v = newTag.value.trim();
87
+ if (!v || tags.value.includes(v)) {
88
+ newTag.value = '';
89
+ adding.value = false;
90
+ return;
91
+ }
92
+ persist([...tags.value, v]);
93
+ newTag.value = '';
94
+ adding.value = false;
95
+ }
96
+
97
+ function remove(tag: string) {
98
+ persist(tags.value.filter((t) => t !== tag));
99
+ }
100
+
101
+ onMounted(load);
102
+ watch(() => props.nodeId, load);
103
+ </script>
104
+
105
+ <template>
106
+ <div class="filex-tag-picker" :class="{ 'is-loading': loading }">
107
+ <span
108
+ v-for="tag in tags"
109
+ :key="tag"
110
+ class="filex-tag"
111
+ :style="{ '--filex-tag-color': colorFor(tag) }"
112
+ >
113
+ {{ tag }}
114
+ <button class="filex-tag-x" type="button" @click="remove(tag)" aria-label="Remove tag">×</button>
115
+ </span>
116
+
117
+ <form v-if="adding" class="filex-tag-add" @submit.prevent="add">
118
+ <input
119
+ v-model="newTag"
120
+ autofocus
121
+ placeholder="tag name"
122
+ @blur="add"
123
+ @keydown.escape="adding = false; newTag = ''"
124
+ />
125
+ </form>
126
+ <button v-else class="filex-tag-add-btn" type="button" @click="adding = true">+ Add tag</button>
127
+ </div>
128
+ </template>
129
+
130
+ <style scoped>
131
+ .filex-tag-picker {
132
+ display: flex;
133
+ flex-wrap: wrap;
134
+ gap: 6px;
135
+ align-items: center;
136
+ }
137
+ .filex-tag-picker.is-loading {
138
+ opacity: 0.6;
139
+ pointer-events: none;
140
+ }
141
+ .filex-tag {
142
+ display: inline-flex;
143
+ align-items: center;
144
+ gap: 4px;
145
+ border-radius: 999px;
146
+ padding: 2px 10px;
147
+ font-size: 12px;
148
+ font-weight: 500;
149
+ color: #fff;
150
+ background: var(--filex-tag-color);
151
+ }
152
+ .filex-tag-x {
153
+ background: transparent;
154
+ border: none;
155
+ color: rgba(255, 255, 255, 0.85);
156
+ cursor: pointer;
157
+ padding: 0 2px;
158
+ font-size: 14px;
159
+ line-height: 1;
160
+ }
161
+ .filex-tag-x:hover {
162
+ color: #fff;
163
+ }
164
+ .filex-tag-add input {
165
+ border: 1px solid var(--filex-border, #d1d5db);
166
+ border-radius: 12px;
167
+ padding: 2px 10px;
168
+ font-size: 12px;
169
+ width: 110px;
170
+ }
171
+ .filex-tag-add-btn {
172
+ border: 1px dashed var(--filex-border, #d1d5db);
173
+ background: transparent;
174
+ border-radius: 999px;
175
+ padding: 2px 10px;
176
+ font-size: 12px;
177
+ color: var(--filex-text-muted, #6b7280);
178
+ cursor: pointer;
179
+ }
180
+ .filex-tag-add-btn:hover {
181
+ border-color: var(--filex-accent, #6366f1);
182
+ color: var(--filex-accent, #6366f1);
183
+ }
184
+ </style>