rimecms 0.26.5 → 0.26.7

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 (57) 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 +3 -3
  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 +16 -10
  24. package/dist/fields/rich-text/core/features/upload/upload.svelte +22 -17
  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/api-proxy.svelte.d.ts +12 -11
  49. package/dist/panel/context/api-proxy.svelte.js +6 -5
  50. package/dist/panel/context/collection.svelte.d.ts +1 -2
  51. package/dist/panel/context/collection.svelte.js +2 -2
  52. package/dist/panel/context/documentForm.svelte.d.ts +2 -3
  53. package/dist/panel/context/documentForm.svelte.js +19 -20
  54. package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +7 -3
  55. package/dist/panel/pages/auth/sign-in/SignIn.svelte +1 -0
  56. package/dist/panel/pages/collection/Collection.svelte +14 -12
  57. package/package.json +6 -6
@@ -6,7 +6,7 @@
6
6
  import * as Command from '../../../../../panel/components/ui/command/index.js';
7
7
  import * as Dialog from '../../../../../panel/components/ui/dialog/index.js';
8
8
  import Input from '../../../../../panel/components/ui/input/input.svelte';
9
- import { API_PROXY, setAPIProxyContext } from '../../../../../panel/context/api-proxy.svelte.js';
9
+ import { API_PROXY, getAPIProxyContext } from '../../../../../panel/context/api-proxy.svelte.js';
10
10
  import { X } from '@lucide/svelte';
11
11
  import type { NodeViewProps } from '@tiptap/core';
12
12
  import { onMount } from 'svelte';
@@ -51,17 +51,16 @@
51
51
  }
52
52
  } else {
53
53
  selected = null;
54
- isDialogOpen = true;
55
54
  }
56
55
  });
57
56
 
58
- // Need to set a local APIProxy because the app one is not
59
- // available from inside tiptap rendered components
60
- // TODO try to pass it as a prop in a near future
61
- const APIProxy = setAPIProxyContext(API_PROXY.TIPTAP);
57
+ const APIProxy = getAPIProxyContext(API_PROXY.DOCUMENT);
58
+
59
+ // svelte-ignore state_referenced_locally
62
60
  const url = extension.options.query
63
- ? apiUrl(extension.options.slug, extension.options.query)
61
+ ? apiUrl(extension.options.slug, `?${extension.options.query}`)
64
62
  : apiUrl(extension.options.slug);
63
+
65
64
  const ressource = APIProxy.getRessource<{ docs: UploadDoc[] }>(url);
66
65
  let docs = $state<UploadDoc[]>([]);
67
66
 
@@ -125,9 +124,9 @@
125
124
  <NodeViewWrapper>
126
125
  <div data-drag-handle class="rz-richtext-media" class:rz-richtext-media--selected={!!selected}>
127
126
  {#if !selected}
128
- <Button class="rz-richtext-media__add" variant="outline" onclick={handleClick}
129
- >Add a media</Button
130
- >
127
+ <Button class="rz-richtext-media__add" variant="outline" onclick={handleClick}>
128
+ Add a media
129
+ </Button>
131
130
  {:else}
132
131
  <div class="rz-richtext-media__actions">
133
132
  <Button
@@ -178,7 +177,7 @@
178
177
  </div>
179
178
  {/snippet}
180
179
 
181
- <Command.Dialog bind:open={isDialogOpen} onOpenChange={(val) => (isDialogOpen = val)}>
180
+ <Command.Dialog bind:open={isDialogOpen}>
182
181
  <Command.Input placeholder="Select an image" />
183
182
 
184
183
  <Command.List>
@@ -203,8 +202,13 @@
203
202
  </Dialog.Content>
204
203
  </Dialog.Root>
205
204
 
206
- <style>
207
- :global(.ProseMirror-selectednode .rz-richtext-media) {
205
+ <style>/**************************************/
206
+
207
+ /* Font */
208
+
209
+ /**************************************/
210
+
211
+ :global(.ProseMirror-selectednode .rz-richtext-media) {
208
212
  .rz-richtext-media__media,
209
213
  :global(button.rz-richtext-media__add) {
210
214
  box-shadow:
@@ -216,15 +220,16 @@
216
220
  }
217
221
  }
218
222
 
219
- .rz-richtext-media {
223
+ .rz-richtext-media {
220
224
  position: relative;
221
225
  }
222
226
 
223
- .rz-richtext-media__media {
227
+ .rz-richtext-media__media {
224
228
  border-radius: var(--rz-radius-lg);
225
229
  overflow: hidden;
226
230
  }
227
- .rz-richtext-media__actions {
231
+
232
+ .rz-richtext-media__actions {
228
233
  position: absolute;
229
234
  font-size: var(--rz-text-sm);
230
235
  right: var(--rz-size-3);
@@ -251,7 +256,7 @@
251
256
  }
252
257
  }
253
258
 
254
- .rz-richtext-media__legend {
259
+ .rz-richtext-media__legend {
255
260
  font-style: italic;
256
261
  font-size: var(--rz-text-sm);
257
262
  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');