rimecms 0.26.4 → 0.26.6

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 (54) hide show
  1. package/dist/core/collections/versions/operations.d.ts +1 -1
  2. package/dist/core/collections/versions/operations.js +1 -1
  3. package/dist/core/config/server/build-config.server.js +0 -2
  4. package/dist/core/dev/generate/routes/common.js +9 -6
  5. package/dist/core/fields/builders/select.js +0 -4
  6. package/dist/core/operations/blocks/extract.server.js +2 -1
  7. package/dist/fields/blocks/component/Block.svelte +23 -31
  8. package/dist/fields/blocks/component/Blocks.svelte +14 -7
  9. package/dist/fields/checkbox/component/Checkbox.svelte +1 -1
  10. package/dist/fields/combobox/component/ComboBox.svelte +1 -1
  11. package/dist/fields/group/component/Group.svelte +20 -12
  12. package/dist/fields/link/component/Link.svelte +14 -12
  13. package/dist/fields/link/index.d.ts +1 -1
  14. package/dist/fields/link/index.js +5 -5
  15. package/dist/fields/radio/index.d.ts +1 -0
  16. package/dist/fields/radio/index.js +8 -0
  17. package/dist/fields/relation/component/Relation.svelte +2 -1
  18. package/dist/fields/rich-text/component/Cell.svelte +1 -1
  19. package/dist/fields/rich-text/component/RichText.svelte +9 -3
  20. package/dist/fields/rich-text/component/bubble-menu/bubble-menu.svelte +1 -1
  21. package/dist/fields/rich-text/core/features/fields/fields.svelte +1 -0
  22. package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +4 -2
  23. package/dist/fields/rich-text/core/features/resource/resource.svelte +12 -3
  24. package/dist/fields/rich-text/core/features/upload/upload.svelte +15 -6
  25. package/dist/fields/select/component/Select.svelte +2 -4
  26. package/dist/fields/slug/component/Slug.svelte +15 -23
  27. package/dist/fields/tabs/component/Tabs.svelte +56 -56
  28. package/dist/fields/toggle/component/Toggle.svelte +1 -1
  29. package/dist/fields/tree/component/Tree.svelte +6 -1
  30. package/dist/fields/tree/component/TreeBlock.svelte +24 -20
  31. package/dist/panel/components/Root.svelte +3 -5
  32. package/dist/panel/components/sections/collection/folder/FolderEdit.svelte +5 -5
  33. package/dist/panel/components/sections/collection/grid/create-directory-dialog/CreateDirectoryDialog.svelte +10 -28
  34. package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte +2 -3
  35. package/dist/panel/components/sections/collection/header/ButtonCreate.svelte +2 -3
  36. package/dist/panel/components/sections/collection/header/DisplayMode.svelte +9 -5
  37. package/dist/panel/components/sections/collection/header/Header.svelte +2 -4
  38. package/dist/panel/components/sections/collection/header/SearchInput.svelte +2 -3
  39. package/dist/panel/components/sections/collection/header/SelectUI.svelte +2 -4
  40. package/dist/panel/components/sections/collection/list/header/Header.svelte +12 -8
  41. package/dist/panel/components/sections/collection/list/row/Row.svelte +15 -10
  42. package/dist/panel/components/sections/document/ButtonStatus.svelte +15 -9
  43. package/dist/panel/components/sections/document/Document.svelte +13 -12
  44. package/dist/panel/components/sections/document/Header.svelte +1 -1
  45. package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +2 -2
  46. package/dist/panel/components/sections/live/SidePanel.svelte +3 -2
  47. package/dist/panel/components/ui/nav/NavItem.svelte +3 -2
  48. package/dist/panel/context/collection.svelte.d.ts +1 -2
  49. package/dist/panel/context/collection.svelte.js +2 -2
  50. package/dist/panel/context/documentForm.svelte.d.ts +2 -3
  51. package/dist/panel/context/documentForm.svelte.js +19 -20
  52. package/dist/panel/pages/auth/sign-in/SignIn.svelte +1 -0
  53. package/dist/panel/pages/collection/Collection.svelte +14 -12
  54. package/package.json +3 -3
@@ -59,9 +59,12 @@
59
59
  // available from inside tiptap rendered components
60
60
  // TODO try to pass it as a prop in a near future
61
61
  const APIProxy = setAPIProxyContext(API_PROXY.TIPTAP);
62
+
63
+ // svelte-ignore state_referenced_locally
62
64
  const url = extension.options.query
63
65
  ? apiUrl(extension.options.slug, extension.options.query)
64
66
  : apiUrl(extension.options.slug);
67
+
65
68
  const ressource = APIProxy.getRessource<{ docs: UploadDoc[] }>(url);
66
69
  let docs = $state<UploadDoc[]>([]);
67
70
 
@@ -203,8 +206,13 @@
203
206
  </Dialog.Content>
204
207
  </Dialog.Root>
205
208
 
206
- <style>
207
- :global(.ProseMirror-selectednode .rz-richtext-media) {
209
+ <style>/**************************************/
210
+
211
+ /* Font */
212
+
213
+ /**************************************/
214
+
215
+ :global(.ProseMirror-selectednode .rz-richtext-media) {
208
216
  .rz-richtext-media__media,
209
217
  :global(button.rz-richtext-media__add) {
210
218
  box-shadow:
@@ -216,15 +224,16 @@
216
224
  }
217
225
  }
218
226
 
219
- .rz-richtext-media {
227
+ .rz-richtext-media {
220
228
  position: relative;
221
229
  }
222
230
 
223
- .rz-richtext-media__media {
231
+ .rz-richtext-media__media {
224
232
  border-radius: var(--rz-radius-lg);
225
233
  overflow: hidden;
226
234
  }
227
- .rz-richtext-media__actions {
235
+
236
+ .rz-richtext-media__actions {
228
237
  position: absolute;
229
238
  font-size: var(--rz-text-sm);
230
239
  right: var(--rz-size-3);
@@ -251,7 +260,7 @@
251
260
  }
252
261
  }
253
262
 
254
- .rz-richtext-media__legend {
263
+ .rz-richtext-media__legend {
255
264
  font-style: italic;
256
265
  font-size: var(--rz-text-sm);
257
266
  opacity: 0.5;
@@ -11,13 +11,11 @@
11
11
  const { path, config, form }: SelectFieldProps = $props();
12
12
 
13
13
  let listHTMLElement: HTMLElement;
14
- const validValues = config.options.map((o) => o.value);
15
14
  let initialized = false;
16
-
15
+ let options = $derived(config.options);
16
+ const validValues = $derived(config.options.map((o) => o.value));
17
17
  const field = $derived(form.useField<string | string[]>(path, config));
18
18
 
19
- let options = $state(config.options);
20
-
21
19
  let isFull = $derived.by(() => {
22
20
  if (!field.value) return false;
23
21
  const notManyAndOneSelected = !config.many && typeof field.value === 'string';
@@ -5,7 +5,6 @@
5
5
  import Button from '../../../panel/components/ui/button/button.svelte';
6
6
  import { Input } from '../../../panel/components/ui/input/index.js';
7
7
  import type { DocumentFormContext } from '../../../panel/context/documentForm.svelte.js';
8
- import { getValueAtPath } from '../../../util/object.js';
9
8
  import { slugify } from '../../../util/string.js';
10
9
  import { Hash } from '@lucide/svelte';
11
10
  import type { SlugField } from '../index';
@@ -14,34 +13,25 @@
14
13
  const { path, config, form }: Props = $props();
15
14
 
16
15
  const field = $derived(form.useField(path, config));
16
+ let isFocused = false;
17
+ // svelte-ignore state_referenced_locally
17
18
  const initialValue = form.getRawValue(path);
18
19
  const initialEmpty = !initialValue;
19
- let internalValue = $state(initialValue);
20
+ const slugifySource = $derived(config.slugify ? form.useField<string>(config.slugify) : null);
20
21
 
21
- $effect(() => {
22
- if (initialEmpty) {
23
- generateFromField();
22
+ const slugifiedValue = $derived.by(() => {
23
+ if (slugifySource && slugifySource.value) {
24
+ return slugify(slugifySource.value);
24
25
  }
26
+ return '';
25
27
  });
26
28
 
27
29
  $effect(() => {
28
- if (internalValue !== field.value) {
29
- field.value = internalValue;
30
+ if (!isFocused && initialEmpty && slugifiedValue && field.value !== slugifiedValue) {
31
+ field.value = slugifiedValue;
30
32
  }
31
33
  });
32
34
 
33
- const generateFromField = () => {
34
- if (config.slugify) {
35
- const source = config.slugify in form.changes ? form.changes : form.values;
36
- const fromValue = getValueAtPath<string>(config.slugify, source);
37
- if (!fromValue) return;
38
- const slugifiedValue = slugify(fromValue);
39
- if (internalValue !== slugifiedValue) {
40
- internalValue = slugifiedValue;
41
- }
42
- }
43
- };
44
-
45
35
  const onInput = (event: Event) => {
46
36
  const inputElement = event.target as HTMLInputElement;
47
37
  const inputValue = inputElement.value;
@@ -49,11 +39,11 @@
49
39
  if (inputValue !== slugifiedValue) {
50
40
  inputElement.value = slugifiedValue;
51
41
  }
52
- internalValue = inputElement.value;
42
+ field.value = inputElement.value;
53
43
  };
54
44
 
55
- const classNameCompact = config.layout === 'compact' ? 'rz-slug-field--compact' : '';
56
- const classNames = `rz-slug-field ${classNameCompact || ''} ${config.className}`;
45
+ const classNameCompact = $derived(config.layout === 'compact' ? 'rz-slug-field--compact' : '');
46
+ const classNames = $derived(`rz-slug-field ${classNameCompact || ''} ${config.className}`);
57
47
  </script>
58
48
 
59
49
  <fieldset class={classNames} use:root={field}>
@@ -69,12 +59,14 @@
69
59
  value={field.value}
70
60
  name={path || config.name}
71
61
  oninput={onInput}
62
+ onfocus={() => (isFocused = true)}
63
+ onblur={() => (isFocused = false)}
72
64
  />
73
65
 
74
66
  {#if config.slugify}
75
67
  <Button
76
68
  disabled={!field.editable}
77
- onclick={generateFromField}
69
+ onclick={() => (field.value = slugifiedValue)}
78
70
  type="button"
79
71
  size="sm"
80
72
  variant="secondary"
@@ -1,96 +1,96 @@
1
1
  <script lang="ts">
2
- import { dev } from '$app/environment';
3
2
  import RichText from '../../rich-text/component/RichText.svelte';
4
3
  import { RichTextFieldBuilder } from '../../rich-text/index.js';
5
4
  import RenderFields from '../../../panel/components/fields/RenderFields.svelte';
6
5
  import * as Tabs from '../../../panel/components/ui/tabs/index.js';
7
6
  import type { DocumentFormContext } from '../../../panel/context/documentForm.svelte.js';
8
- import Cookies from 'js-cookie';
9
7
  import type { TabBuilder, TabsField } from '../index.js';
10
8
 
11
9
  type Props = { config: TabsField; path: string; form: DocumentFormContext };
12
10
 
13
11
  const { config, path: initialPath, form }: Props = $props();
14
12
 
15
- const cookieKey = `rime.Tabs:${form.values.id || 'create'}:${initialPath}:${config.tabs.map((t) => t.name).join('-')}`;
16
- let activeTabName = $state(Cookies.get(cookieKey) || config.tabs[0].name);
13
+ const storageActiveKey = $derived(`rime.Tabs:${form.values.id || 'create'}:${initialPath}`);
14
+ let errorTabs = $state<string[]>([]);
15
+ // Path to prepend to fields inside tabs
16
+ const prependPath = $derived(initialPath === '' ? '' : `${initialPath}.`);
17
+ // Generate unique IDs for each tab to use as data attributes for error handling.
18
+ const tabIds = $derived(
19
+ config.tabs.map((tab) => `${tab.name}-${new Date().getTime().toString()}`)
20
+ );
17
21
 
18
- // Prevent localStorage opened tab to open when tab.live is false
19
- $effect(() => {
20
- if (form.isLive) {
21
- const currentActiveTab = config.tabs.find((tab) => tab.name === activeTabName);
22
- if (!currentActiveTab || currentActiveTab.raw.live === false) {
23
- activeTabName = config.tabs[0].name;
22
+ // Retrieve active tab from localStorage, if not found use the first tab.
23
+ // If the stored active tab is not available in live mode, fallback to the first tab.
24
+ let activeTabName = $derived.by(() => {
25
+ let storedActiveTab = localStorage.getItem(storageActiveKey);
26
+ if (storedActiveTab && form.isLive) {
27
+ const activeTab = config.tabs.find((tab) => tab.name === storedActiveTab);
28
+ if (!activeTab || activeTab.raw.live === false) {
29
+ return config.tabs[0].name;
24
30
  }
25
31
  }
32
+ return storedActiveTab || config.tabs[0].name;
26
33
  });
27
34
 
28
- let tabErrors = $state<string[]>([]);
29
- const tabIds = $derived(
30
- config.tabs.map((tab) => `${tab.name}-${new Date().getTime().toString()}`)
31
- );
35
+ // On live mode only show tabs with live=true
36
+ function isTabVisible(tab: TabBuilder) {
37
+ return form.isLive ? tab.raw.live === true : true;
38
+ }
32
39
 
33
- function onActiveTabChange(value: string | undefined): void {
34
- value = value || config.tabs[0].name;
35
- Cookies.set(cookieKey, value, {
36
- sameSite: 'strict',
37
- secure: !dev
38
- });
40
+ function onActiveTabChange(value: string): void {
41
+ localStorage.setItem(storageActiveKey, value);
39
42
  activeTabName = value;
40
43
  }
41
44
 
42
45
  // Emphasize tabs that includes errors
43
46
  $effect(() => {
44
47
  if (form.errors.length) {
45
- const errorsTabs = document.querySelectorAll<HTMLElement>(
46
- '.rz-tabs-content:has(*[data-error])'
47
- );
48
+ const selector = '.rz-tabs-content:has(*[data-error])';
49
+ const errorsTabs = document.querySelectorAll<HTMLElement>(selector);
48
50
  if (errorsTabs) {
49
- tabErrors = Array.from(errorsTabs)
50
- .map((el: HTMLElement) => (el.dataset.tabId ? el.dataset.tabId : false))
51
- .filter((entry) => typeof entry === 'string');
51
+ errorTabs = Array.from(errorsTabs)
52
+ .map((el) => el.dataset.tabId)
53
+ .filter((str) => typeof str === 'string');
52
54
  }
53
55
  } else {
54
- tabErrors = [];
56
+ errorTabs = [];
55
57
  }
56
58
  });
57
-
58
- const path = $derived(initialPath === '' ? '' : `${initialPath}.`);
59
-
60
- function isTabVisible(tab: TabBuilder) {
61
- return form.isLive ? tab.raw.live === true : true;
62
- }
63
59
  </script>
64
60
 
65
61
  <div class="rz-tabs">
66
62
  <Tabs.Root onValueChange={onActiveTabChange} value={activeTabName}>
67
63
  <Tabs.List>
68
- {#each config.tabs.filter(isTabVisible) as tab, index (index)}
69
- <Tabs.Trigger
70
- data-error={tabErrors.includes(tabIds[index]) ? 'true' : null}
71
- value={tab.name}
72
- >
73
- {tab.raw.label || tab.name}
74
- </Tabs.Trigger>
64
+ {#each config.tabs as tab, index (index)}
65
+ {#if isTabVisible(tab)}
66
+ <Tabs.Trigger
67
+ data-error={errorTabs.includes(tabIds[index]) ? 'true' : null}
68
+ value={tab.name}
69
+ >
70
+ {tab.raw.label || tab.name}
71
+ </Tabs.Trigger>
72
+ {/if}
75
73
  {/each}
76
74
  </Tabs.List>
77
75
 
78
- {#each config.tabs.filter(isTabVisible) as tab, index (index)}
79
- <Tabs.Content data-tab-id={tabIds[index]} value={tab.name}>
80
- <!-- If the first field is a rich text field, render it directly -->
81
- {#if tab.fields.length === 1 && tab.raw.fields[0].type === 'richText'}
82
- {@const firstField = tab.raw.fields[0] as RichTextFieldBuilder}
83
- <RichText
84
- standAlone={true}
85
- path="{path}{tab.name}.{firstField.name}"
86
- config={firstField.raw}
87
- {form}
88
- />
89
- {:else}
90
- <!-- Otherwise, render the fields -->
91
- <RenderFields fields={tab.raw.fields} path="{path}{tab.name}" {form} />
92
- {/if}
93
- </Tabs.Content>
76
+ {#each config.tabs as tab, index (index)}
77
+ {#if isTabVisible(tab)}
78
+ <Tabs.Content data-tab-id={tabIds[index]} value={tab.name}>
79
+ <!-- If the first and only field is a rich text field, render it directly -->
80
+ {#if tab.fields.length === 1 && tab.raw.fields[0].type === 'richText'}
81
+ {@const firstField = tab.raw.fields[0] as RichTextFieldBuilder}
82
+ <RichText
83
+ standAlone={true}
84
+ path="{prependPath}{tab.name}.{firstField.name}"
85
+ config={firstField.raw}
86
+ {form}
87
+ />
88
+ {:else}
89
+ <!-- Otherwise, render the fields -->
90
+ <RenderFields fields={tab.raw.fields} path="{prependPath}{tab.name}" {form} />
91
+ {/if}
92
+ </Tabs.Content>
93
+ {/if}
94
94
  {/each}
95
95
  </Tabs.Root>
96
96
  </div>
@@ -7,7 +7,7 @@
7
7
 
8
8
  const { path, config, form }: ToggleProps = $props();
9
9
  const field = $derived(form.useField<boolean>(path, config));
10
- const inputId = slugify(`${form.key}-${path}`);
10
+ const inputId = $derived(slugify(`${form.key}-${path}`));
11
11
 
12
12
  const onCheckedChange = (bool: boolean) => {
13
13
  field.value = bool;
@@ -117,7 +117,12 @@
117
117
  {/key}
118
118
 
119
119
  <div class="rz-tree__actions">
120
- <AddItemButton addItem={add} class="rz-tree__add-button" size={nested ? 'sm' : 'default'} fields={config.fields}>
120
+ <AddItemButton
121
+ addItem={add}
122
+ class="rz-tree__add-button"
123
+ size={nested ? 'sm' : 'default'}
124
+ fields={config.fields}
125
+ >
121
126
  {config.addItemLabel}
122
127
  </AddItemButton>
123
128
 
@@ -2,7 +2,6 @@
2
2
  import type { TreeBlock } from '../../../core/types/doc.js';
3
3
  import RenderFields from '../../../panel/components/fields/RenderFields.svelte';
4
4
  import { useOnce } from '../../../panel/util/once.svelte.js';
5
- import { snapshot } from '../../../util/state.js';
6
5
  import { GripVertical } from '@lucide/svelte';
7
6
  import { extractFieldName } from '../util.js';
8
7
  import TreeBlockComp from './TreeBlock.svelte';
@@ -11,7 +10,6 @@
11
10
 
12
11
  const { config, treeKey, treeState, form, sorting = false, path }: TreeBlockProps = $props();
13
12
 
14
- const initialPath = $state(snapshot(path));
15
13
  const depth = $derived(
16
14
  path
17
15
  .replace(`${treeState.path}.`, '')
@@ -66,11 +64,12 @@
66
64
  return `${position} - ${config.label || config.name}`;
67
65
  };
68
66
 
69
- $effect(() => {
70
- if (initialPath !== path) {
71
- form.setValue(path, itemValue);
72
- }
73
- });
67
+ // $effect(() => {
68
+ // if (initialPath !== path) {
69
+ // form.setValue(path, itemValue);
70
+ // initialPath = path;
71
+ // }
72
+ // });
74
73
  </script>
75
74
 
76
75
  <div
@@ -119,26 +118,31 @@
119
118
  {/if}
120
119
  </div>
121
120
 
122
- <style>
123
- .rz-tree-item {
121
+ <style>/**************************************/
122
+
123
+ /* Font */
124
+
125
+ /**************************************/
126
+
127
+ .rz-tree-item {
124
128
  position: relative;
125
129
  }
126
130
 
127
- .rz-tree-item__grip {
131
+ .rz-tree-item__grip {
128
132
  cursor: grab;
129
133
  position: absolute;
130
134
  top: 1rem;
131
135
  left: -1rem;
132
136
  }
133
137
 
134
- .rz-tree-item__header:hover {
138
+ .rz-tree-item__header:hover {
135
139
  > :global(.rz-tree-item-actions) {
136
140
  opacity: 1;
137
141
  pointer-events: all;
138
142
  }
139
143
  }
140
144
 
141
- .rz-tree-item__header {
145
+ .rz-tree-item__header {
142
146
  display: flex;
143
147
  align-items: center;
144
148
  justify-content: space-between;
@@ -151,7 +155,7 @@
151
155
  width: 100%;
152
156
  }
153
157
 
154
- .rz-tree-item__content--closed {
158
+ .rz-tree-item__content--closed {
155
159
  .rz-tree-item__header {
156
160
  border-radius: var(--rz-radius-md);
157
161
  }
@@ -162,20 +166,20 @@
162
166
  }
163
167
  }
164
168
 
165
- .rz-tree-item__content + .rz-tree-item__list-placeholder,
169
+ .rz-tree-item__content + .rz-tree-item__list-placeholder,
166
170
  .rz-tree-item__content + .rz-tree__list {
167
171
  margin-top: 1rem;
168
172
  min-height: 5px;
169
173
  }
170
174
 
171
- .rz-tree-item__title {
175
+ .rz-tree-item__title {
172
176
  display: flex;
173
177
  align-items: center;
174
178
  justify-content: center;
175
179
  gap: var(--rz-size-2);
176
180
  }
177
181
 
178
- .rz-tree-item__fields {
182
+ .rz-tree-item__fields {
179
183
  --rz-fields-padding: var(--rz-size-4);
180
184
  background-color: var(--rz-collapse-fields-content-bg);
181
185
  border: var(--rz-border);
@@ -186,21 +190,21 @@
186
190
  flex: 1;
187
191
  }
188
192
 
189
- .rz-tree-item__fields--hidden {
193
+ .rz-tree-item__fields--hidden {
190
194
  display: none;
191
195
  }
192
196
 
193
- .rz-tree-item[data-sorting='true'] .rz-tree-item__grip {
197
+ .rz-tree-item[data-sorting='true'] .rz-tree-item__grip {
194
198
  display: none;
195
199
  }
196
200
 
197
- .rz-tree-item__content--closed:has(:global(.rz-field-error)) {
201
+ .rz-tree-item__content--closed:has(:global(.rz-field-error)) {
198
202
  box-shadow:
199
203
  0 0 0 var(--rz-ring-offset, 0px) hsl(var(--rz-ring-offset-bg, var(--rz-gray-6)) / 1),
200
204
  0 0 0 calc(var(--rz-ring-offset, 0px) + 1px) hsl(var(--rz-color-alert) / var(--rz-ring-opacity, 1));
201
205
  }
202
206
 
203
- :global(.rz-tree-item-actions) {
207
+ :global(.rz-tree-item-actions) {
204
208
  opacity: 0;
205
209
  pointer-events: none;
206
210
  }
@@ -24,16 +24,14 @@
24
24
  let isCollapsed = $state(false);
25
25
  let localeCollapsed = $state<string | null>(null);
26
26
 
27
+ // svelte-ignore state_referenced_locally
27
28
  setConfigContext(config);
29
+ // svelte-ignore state_referenced_locally
28
30
  setUserContext(user);
29
31
  createContext('title', '[untitled]');
30
32
  setAPIProxyContext(API_PROXY.ROOT);
31
33
 
32
- const locale = setLocaleContext(initialeLocale);
33
-
34
- $effect(() => {
35
- locale.code = initialeLocale;
36
- });
34
+ const locale = $derived(setLocaleContext(initialeLocale));
37
35
 
38
36
  function onResize() {
39
37
  if (window.innerWidth < 1024) {
@@ -18,14 +18,14 @@
18
18
  };
19
19
  let { folder, collection, open = $bindable() }: Props = $props();
20
20
 
21
+ setAPIProxyContext(API_PROXY.DOCUMENT);
22
+ let formElement = $state<HTMLFormElement>();
21
23
  const user = getUserContext();
22
24
  const configCtx = getConfigContext();
25
+ // svelte-ignore state_referenced_locally
23
26
  const config = configCtx.getCollection(withDirectoriesSuffix(collection.slug));
24
- let formElement = $state<HTMLFormElement>();
25
- setAPIProxyContext(API_PROXY.DOCUMENT);
26
-
27
+ // svelte-ignore state_referenced_locally
27
28
  const form = setDocumentFormContext({
28
- element: () => formElement,
29
29
  initial: folder,
30
30
  config,
31
31
  readOnly: !config.access.update(user.attributes, { id: folder.id }),
@@ -55,7 +55,7 @@
55
55
  <Dialog.Root bind:open>
56
56
  <Dialog.Content>
57
57
  {#snippet child({ props })}
58
- <form use:form.enhance action={form.buildPanelActionUrl()} bind:this={formElement} {...props}>
58
+ <form use:form.enhance bind:this={formElement} {...props}>
59
59
  <RenderFields {form} fields={config.fields} />
60
60
  <Dialog.Footer --rz-justify-content="space-between">
61
61
  <Button data-submit disabled={!form.canSubmit} type="submit">{t__('common.save')}</Button>
@@ -16,20 +16,13 @@
16
16
  type Props = { collection: CollectionContext; open: boolean };
17
17
  let { collection, open = $bindable() }: Props = $props();
18
18
 
19
- const configCtx = getConfigContext();
20
- const directoriesConfig = configCtx.getCollection(withDirectoriesSuffix(collection.config.slug));
21
-
22
19
  setAPIProxyContext(API_PROXY.DOCUMENT);
23
20
  let formElement = $state<HTMLFormElement>();
24
-
25
- async function beforeRedirect(data?: FormSuccessData) {
26
- open = false;
27
- invalidateAll();
28
- return false;
29
- }
30
-
21
+ const configCtx = getConfigContext();
22
+ // svelte-ignore state_referenced_locally
23
+ const directoriesConfig = configCtx.getCollection(withDirectoriesSuffix(collection.config.slug));
24
+ // svelte-ignore state_referenced_locally
31
25
  const form = setDocumentFormContext({
32
- element: () => formElement,
33
26
  initial: {
34
27
  parent: collection.upload.currentPath
35
28
  },
@@ -39,29 +32,18 @@
39
32
  beforeRedirect: beforeRedirect
40
33
  });
41
34
 
42
- function handleKeyDown(event: KeyboardEvent) {
43
- if (!open) return;
44
- if (!formElement) throw Error('formElement is not defined');
45
- if ((event.ctrlKey || event.metaKey) && event.key === 's') {
46
- event.preventDefault();
47
- if (!form.canSubmit) return;
48
- const saveButton = formElement.querySelector('button[data-submit]');
49
- if (saveButton) {
50
- formElement.requestSubmit(saveButton as HTMLButtonElement);
51
- } else {
52
- // Fallback to default submit if no specific button found
53
- formElement.requestSubmit();
54
- }
55
- }
35
+ // Prevent redirection after directory creation
36
+ async function beforeRedirect(data?: FormSuccessData) {
37
+ open = false;
38
+ invalidateAll();
39
+ return false;
56
40
  }
57
41
  </script>
58
42
 
59
- <svelte:window onkeydown={handleKeyDown} />
60
-
61
43
  <Dialog.Root bind:open>
62
44
  <Dialog.Content class="rz-status-dialog">
63
45
  {#snippet child({ props })}
64
- <form use:form.enhance action={form.buildPanelActionUrl()} bind:this={formElement} {...props}>
46
+ <form use:form.enhance bind:this={formElement} {...props}>
65
47
  <Dialog.Header>{t__('common.create_folder')}</Dialog.Header>
66
48
  <RenderFields {form} fields={directoriesConfig.fields} />
67
49
  <Dialog.Footer --rz-justify-content="space-between">
@@ -6,14 +6,13 @@
6
6
  import type { GenericDoc } from '../../../../../../core/types/doc';
7
7
  import CardDocument from '../../../../ui/card-document/card-document.svelte';
8
8
  import Checkbox from '../../../../ui/checkbox/checkbox.svelte';
9
- import { type CollectionContext } from '../../../../../context/collection.svelte.js';
9
+ import { getCollectionContext } from '../../../../../context/collection.svelte.js';
10
10
  import { panelUrl } from '../../../../../util/url.js';
11
- import { getContext } from 'svelte';
12
11
 
13
12
  type Props = { checked: boolean; doc: GenericDoc; draggable?: 'true' };
14
13
  const { checked, doc, draggable }: Props = $props();
15
14
 
16
- const collection = getContext<CollectionContext>('rime.collectionList');
15
+ const collection = getCollectionContext('list');
17
16
 
18
17
  const isUploadCollection = $derived(isUploadConfig(collection.config));
19
18
 
@@ -3,14 +3,13 @@
3
3
  import { PARAMS } from '../../../../../core/constant.js';
4
4
  import { t__ } from '../../../../../core/i18n/index.js';
5
5
  import Button from '../../../ui/button/button.svelte';
6
- import { type CollectionContext } from '../../../../context/collection.svelte.js';
6
+ import { getCollectionContext } from '../../../../context/collection.svelte.js';
7
7
  import { CirclePlus } from '@lucide/svelte';
8
- import { getContext } from 'svelte';
9
8
 
10
9
  type ButtonSize = 'sm' | 'default';
11
10
  const { size = 'default' }: { size?: ButtonSize } = $props();
12
- const collection = getContext<CollectionContext>('rime.collectionList');
13
11
 
12
+ const collection = getCollectionContext('list');
14
13
  const isSmallSize = $derived(size === 'sm');
15
14
  const buttonVariant = $derived(isSmallSize ? 'ghost' : 'default');
16
15
  const buttonSize = $derived(isSmallSize ? 'icon-sm' : 'default');
@@ -1,14 +1,18 @@
1
1
  <script lang="ts">
2
2
  import Button from '../../../ui/button/button.svelte';
3
- import { DISPLAY_MODE, type CollectionContext, type DisplayMode } from '../../../../context/collection.svelte.js';
3
+ import {
4
+ DISPLAY_MODE,
5
+ getCollectionContext,
6
+ type DisplayMode
7
+ } from '../../../../context/collection.svelte.js';
4
8
  import { LayoutGrid, List, TextQuote } from '@lucide/svelte';
5
- import { getContext } from 'svelte';
6
-
7
- const collection = getContext<CollectionContext>('rime.collectionList');
8
9
 
10
+ const collection = getCollectionContext('list');
9
11
  const listIconClass = $derived(collection.isList() ? 'rz-header-display-mode__icon--active' : '');
10
12
  const gridIconClass = $derived(collection.isGrid() ? 'rz-header-display-mode__icon--active' : '');
11
- const nestedIconClass = $derived(collection.isNested() ? 'rz-header-display-mode__icon--active' : '');
13
+ const nestedIconClass = $derived(
14
+ collection.isNested() ? 'rz-header-display-mode__icon--active' : ''
15
+ );
12
16
 
13
17
  const setVariant = (mode: DisplayMode) => (mode === collection.display ? 'secondary' : 'ghost');
14
18
  const isActive = (mode: DisplayMode) => mode === collection.display;
@@ -1,12 +1,10 @@
1
1
  <script lang="ts">
2
- import { type CollectionContext } from '../../../../context/collection.svelte.js';
3
- import { getContext } from 'svelte';
2
+ import { getCollectionContext } from '../../../../context/collection.svelte.js';
4
3
  import DisplayMode from './DisplayMode.svelte';
5
4
  import SelectUI from './SelectUI.svelte';
6
5
  import Separator from './Separator.svelte';
7
6
 
8
- const collection = getContext<CollectionContext>('rime.collectionList');
9
-
7
+ const collection = getCollectionContext('list');
10
8
  const showSelectUI = $derived(!collection.isNested());
11
9
  const showDisplayMode = $derived(collection.isUpload || collection.config.nested);
12
10
  </script>