rimecms 0.24.5 → 0.25.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.
Files changed (48) hide show
  1. package/dist/adapter-sqlite/generate-schema/index.server.js +9 -9
  2. package/dist/adapter-sqlite/generate-schema/root.server.d.ts +5 -0
  3. package/dist/adapter-sqlite/generate-schema/root.server.js +5 -0
  4. package/dist/adapter-sqlite/generate-schema/templates.server.js +9 -6
  5. package/dist/core/collections/upload/hooks/convert-base64.server.js +2 -1
  6. package/dist/core/collections/upload/upload.d.ts +2 -1
  7. package/dist/core/collections/upload/util/converter.js +4 -3
  8. package/dist/core/config/client/augment-directories.d.ts +6 -0
  9. package/dist/core/config/client/augment-directories.js +11 -0
  10. package/dist/core/config/client/build-config.d.ts +2 -0
  11. package/dist/core/config/client/build-config.js +3 -1
  12. package/dist/core/config/server/augment-directories.server.d.ts +6 -0
  13. package/dist/core/config/server/augment-directories.server.js +37 -0
  14. package/dist/core/config/server/build-config.server.d.ts +2 -0
  15. package/dist/core/config/server/build-config.server.js +4 -6
  16. package/dist/core/config/shared/upload-directories.d.ts +7 -2
  17. package/dist/core/config/shared/upload-directories.js +118 -48
  18. package/dist/core/config/types.d.ts +6 -0
  19. package/dist/core/naming.d.ts +1 -1
  20. package/dist/core/naming.js +1 -1
  21. package/dist/fields/relation/component/Relation.svelte +2 -1
  22. package/dist/fields/relation/index.d.ts +3 -2
  23. package/dist/panel/components/fields/RenderFields.svelte +5 -2
  24. package/dist/panel/components/fields/RenderFields.svelte.d.ts +3 -1
  25. package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte +6 -14
  26. package/dist/panel/components/sections/collection/grid/grid-item/FolderEdit.svelte +79 -0
  27. package/dist/panel/components/sections/collection/grid/grid-item/FolderEdit.svelte.d.ts +10 -0
  28. package/dist/panel/components/sections/collection/grid/grid-item/FolderWithActions.svelte +11 -44
  29. package/dist/panel/components/sections/collection/grid/grid-item/FolderWithActions.svelte.d.ts +0 -2
  30. package/dist/panel/components/sections/collection/header/Header.svelte +1 -1
  31. package/dist/panel/components/sections/collection/header/create-folder/CreateFolder.svelte +90 -0
  32. package/dist/panel/components/sections/collection/header/create-folder/CreateFolder.svelte.d.ts +7 -0
  33. package/dist/panel/components/sections/collection/tree/CollectionTree.svelte +1 -1
  34. package/dist/panel/components/sections/document/AuthFooter.svelte +11 -2
  35. package/dist/panel/components/sections/document/Settings.svelte +6 -2
  36. package/dist/panel/components/ui/dialog/dialog-content.svelte +20 -5
  37. package/dist/panel/components/ui/dialog/dialog-content.svelte.d.ts +7 -2
  38. package/dist/panel/context/collection.svelte.js +3 -1
  39. package/dist/panel/context/documentForm.svelte.d.ts +14 -6
  40. package/dist/panel/context/documentForm.svelte.js +15 -7
  41. package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +1 -0
  42. package/dist/util/string.d.ts +14 -0
  43. package/dist/util/string.js +19 -0
  44. package/package.json +1 -1
  45. package/dist/core/collections/upload/directory-input-config.d.ts +0 -2
  46. package/dist/core/collections/upload/directory-input-config.js +0 -12
  47. package/dist/panel/components/sections/collection/header/CreateUploadFolder.svelte +0 -68
  48. package/dist/panel/components/sections/collection/header/CreateUploadFolder.svelte.d.ts +0 -7
@@ -0,0 +1,79 @@
1
+ <script lang="ts">
2
+ import type { Directory } from '../../../../../../core/collections/upload/upload';
3
+ import type { BuiltCollectionClient } from '../../../../../../core/config/types';
4
+ import { withDirectoriesSuffix } from '../../../../../../core/naming';
5
+ import * as Dialog from '../../../../ui/dialog/index.js';
6
+ import { t__ } from '../../../../../../core/i18n';
7
+ import RenderFields from '../../../../../index.server.js/components/fields/RenderFields.svelte';
8
+ import Button from '../../../../../index.server.js/components/ui/button/button.svelte';
9
+ import { API_PROXY, setAPIProxyContext } from '../../../../../index.server.js/context/api-proxy.svelte';
10
+ import { getConfigContext } from '../../../../../index.server.js/context/config.svelte';
11
+ import {
12
+ setDocumentFormContext,
13
+ type FormSuccessData
14
+ } from '../../../../../index.server.js/context/documentForm.svelte';
15
+ import { getUserContext } from '../../../../../index.server.js/context/user.svelte';
16
+
17
+ type Props = {
18
+ open: boolean;
19
+ folder: Directory;
20
+ collection: BuiltCollectionClient;
21
+ };
22
+ let { folder, collection, open = $bindable() }: Props = $props();
23
+
24
+ const user = getUserContext();
25
+ const configCtx = getConfigContext();
26
+ const config = configCtx.getCollection(withDirectoriesSuffix(collection.slug));
27
+ setAPIProxyContext(API_PROXY.DOCUMENT);
28
+ let formElement = $state<HTMLFormElement>();
29
+
30
+ async function beforeRedirect(data?: FormSuccessData) {
31
+ open = false;
32
+ return false;
33
+ }
34
+
35
+ const form = setDocumentFormContext({
36
+ element: () => formElement,
37
+ initial: folder,
38
+ config,
39
+ readOnly: !config.access.update(user.attributes, { id: folder.id }),
40
+ key: folder._type,
41
+ beforeRedirect: beforeRedirect
42
+ });
43
+
44
+ function handleKeyDown(event: KeyboardEvent) {
45
+ if (!open) return;
46
+ if (!formElement) throw Error('formElement is not defined');
47
+ if ((event.ctrlKey || event.metaKey) && event.key === 's') {
48
+ event.preventDefault();
49
+ if (!form.canSubmit) return;
50
+ const saveButton = formElement.querySelector('button[data-submit]');
51
+ if (saveButton) {
52
+ formElement.requestSubmit(saveButton as HTMLButtonElement);
53
+ } else {
54
+ // Fallback to default submit if no specific button found
55
+ formElement.requestSubmit();
56
+ }
57
+ }
58
+ }
59
+ </script>
60
+
61
+ <svelte:window onkeydown={handleKeyDown} />
62
+
63
+ <Dialog.Root bind:open>
64
+ <Dialog.Content>
65
+ {#snippet child({ props })}
66
+ <form use:form.enhance action={form.buildPanelActionUrl()} bind:this={formElement} {...props}>
67
+ <Dialog.Header>
68
+ {t__('common.rename_dialog_title', folder.name)}
69
+ </Dialog.Header>
70
+ <RenderFields {form} fields={config.fields} />
71
+
72
+ <Dialog.Footer --rz-justify-content="space-between">
73
+ <Button data-submit disabled={!form.canSubmit} type="submit">{t__('common.save')}</Button>
74
+ <Button onclick={() => (open = false)} variant="secondary">{t__('common.cancel')}</Button>
75
+ </Dialog.Footer>
76
+ </form>
77
+ {/snippet}
78
+ </Dialog.Content>
79
+ </Dialog.Root>
@@ -0,0 +1,10 @@
1
+ import type { Directory } from '../../../../../../core/collections/upload/upload';
2
+ import type { BuiltCollectionClient } from '../../../../../../core/config/types';
3
+ type Props = {
4
+ open: boolean;
5
+ folder: Directory;
6
+ collection: BuiltCollectionClient;
7
+ };
8
+ declare const FolderEdit: import("svelte").Component<Props, {}, "open">;
9
+ type FolderEdit = ReturnType<typeof FolderEdit>;
10
+ export default FolderEdit;
@@ -1,72 +1,50 @@
1
1
  <script lang="ts">
2
2
  import { goto, invalidateAll } from '$app/navigation';
3
3
  import { apiUrl } from '../../../../../../core/api/index.js';
4
- import { directoryInput } from '../../../../../../core/collections/upload/directory-input-config.js';
5
4
  import type { Directory } from '../../../../../../core/collections/upload/upload.js';
6
- import type { UploadPath } from '../../../../../../core/collections/upload/util/path.js';
7
5
  import type { BuiltCollectionClient } from '../../../../../../core/config/types.js';
8
6
  import { PARAMS } from '../../../../../../core/constant.js';
9
7
  import { withDirectoriesSuffix } from '../../../../../../core/naming.js';
10
8
  import type { GenericDoc } from '../../../../../../core/types/doc.js';
11
- import Input from '../../../../../../fields/text/component/Text.svelte';
12
9
  import Button from '../../../../ui/button/button.svelte';
13
10
  import ContextMenu from '../../../../ui/context-menu/ContextMenu.svelte';
14
11
  import ContextMenuItem from '../../../../ui/context-menu/ContextMenuItem.svelte';
15
12
  import * as Dialog from '../../../../ui/dialog/index.js';
16
13
  import { API_PROXY, getAPIProxyContext } from '../../../../../context/api-proxy.svelte.js';
17
- import { setFormContext } from '../../../../../context/form.svelte.js';
18
14
  import { panelUrl } from '../../../../../util/url.js';
19
15
  import { trycatchFetch } from '../../../../../../util/function.js';
20
16
  import { toast } from 'svelte-sonner';
21
17
  import { t__ } from '../../../../../../core/i18n/index.js';
22
18
  import Folder from './Folder.svelte';
19
+ import FolderEdit from './FolderEdit.svelte';
23
20
 
24
21
  type Props = {
25
22
  folder: Directory;
26
23
  collection: BuiltCollectionClient;
27
24
  onDelete?: (path: string) => void;
28
- onRename?: (oldPath: UploadPath, newPath: UploadPath) => void;
29
25
  onDocumentDrop: (args: { documentId: string; path: string }) => void;
30
26
  draggable?: 'true';
31
27
  };
32
- const { folder, collection, onDelete, onRename, onDocumentDrop, draggable }: Props = $props();
28
+ const { folder, collection, onDelete, onDocumentDrop, draggable }: Props = $props();
33
29
 
34
30
  let deleteConfirmOpen = $state(false);
35
- let renameDialogOpen = $state(false);
31
+ let editFolderDialogOpen = $state(false);
36
32
  let message = $state('');
37
33
  let rootElement = $state<HTMLButtonElement>();
38
34
  let isDragging = $state(false);
39
35
  const isRoot = $derived(folder.name === '...');
40
36
  const APIProxy = getAPIProxyContext(API_PROXY.ROOT);
41
- const childFilesURL = $derived(`${apiUrl(collection.kebab)}?where[_path][equals]=${folder.id}&select=id`);
37
+ const childFilesURL = $derived(
38
+ `${apiUrl(collection.kebab)}?where[_path][equals]=${folder.id}&select=id`
39
+ );
42
40
  const childFiles = $derived(APIProxy.getRessource<{ docs: GenericDoc[] }>(childFilesURL));
43
41
  const childFilesCount = $derived(childFiles.data?.docs?.length || 0);
44
42
  const baseFolderApiURL = $derived(`${apiUrl(withDirectoriesSuffix(collection.kebab))}`);
45
- const childFoldersURL = $derived(`${baseFolderApiURL}?where[parent][equals]=${folder.id}&select=id`);
43
+ const childFoldersURL = $derived(
44
+ `${baseFolderApiURL}?where[parent][equals]=${folder.id}&select=id`
45
+ );
46
46
  const childFolders = $derived(APIProxy.getRessource<{ docs: GenericDoc[] }>(childFoldersURL));
47
47
  const childFoldersCount = $derived(childFolders.data?.docs?.length || 0);
48
- const renameFolderForm = setFormContext({ name: '' }, 'rename-folder');
49
-
50
- const renameField = renameFolderForm.useField('name', directoryInput);
51
-
52
- async function handleRename() {
53
- const renameURL = `${baseFolderApiURL}/${folder.id}`;
54
- const newPath = `${folder.parent}:${renameField.value}` as UploadPath;
55
- const [error] = await trycatchFetch(renameURL, {
56
- method: 'PATCH',
57
- body: JSON.stringify({
58
- id: newPath
59
- })
60
- });
61
- if (error) {
62
- return toast.error('Error renaming folder');
63
- }
64
- toast.success(t__('rename_success'));
65
- renameDialogOpen = false;
66
- if (onRename) {
67
- onRename(folder.id, newPath);
68
- }
69
- }
70
48
 
71
49
  async function handleGetDeleteInfos() {
72
50
  message = t__(
@@ -184,7 +162,7 @@
184
162
  <!-- -->
185
163
  {#snippet content()}
186
164
  <ContextMenuItem onclick={handleGetDeleteInfos}>Delete</ContextMenuItem>
187
- <ContextMenuItem onclick={() => (renameDialogOpen = true)}>Rename</ContextMenuItem>
165
+ <ContextMenuItem onclick={() => (editFolderDialogOpen = true)}>Edit</ContextMenuItem>
188
166
  {/snippet}
189
167
  <!-- -->
190
168
  </ContextMenu>
@@ -208,18 +186,7 @@
208
186
  </Dialog.Content>
209
187
  </Dialog.Root>
210
188
 
211
- <Dialog.Root bind:open={renameDialogOpen}>
212
- <Dialog.Content>
213
- <Dialog.Header>
214
- {t__('common.rename_dialog_title', folder.name)}
215
- </Dialog.Header>
216
- <Input form={renameFolderForm} config={directoryInput} />
217
- <Dialog.Footer --rz-justify-content="space-between">
218
- <Button disabled={!renameFolderForm.canSubmit} onclick={handleRename}>Rename</Button>
219
- <Button onclick={() => (renameDialogOpen = false)} variant="secondary">Cancel</Button>
220
- </Dialog.Footer>
221
- </Dialog.Content>
222
- </Dialog.Root>
189
+ <FolderEdit bind:open={editFolderDialogOpen} {folder} {collection} />
223
190
 
224
191
  <style>
225
192
  :root {
@@ -1,11 +1,9 @@
1
1
  import type { Directory } from '../../../../../../core/collections/upload/upload.js';
2
- import type { UploadPath } from '../../../../../../core/collections/upload/util/path.js';
3
2
  import type { BuiltCollectionClient } from '../../../../../../core/config/types.js';
4
3
  type Props = {
5
4
  folder: Directory;
6
5
  collection: BuiltCollectionClient;
7
6
  onDelete?: (path: string) => void;
8
- onRename?: (oldPath: UploadPath, newPath: UploadPath) => void;
9
7
  onDocumentDrop: (args: {
10
8
  documentId: string;
11
9
  path: string;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { type CollectionContext } from '../../../../context/collection.svelte.js';
3
3
  import { getContext } from 'svelte';
4
- import CreateUploadFolder from './CreateUploadFolder.svelte';
4
+ import CreateUploadFolder from './create-folder/CreateFolder.svelte';
5
5
  import DisplayMode from './DisplayMode.svelte';
6
6
  import SelectUI from './SelectUI.svelte';
7
7
  import Separator from './Separator.svelte';
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ import { invalidateAll } from '$app/navigation';
3
+ import { t__ } from '../../../../../../core/i18n/index.js';
4
+ import { withDirectoriesSuffix } from '../../../../../../core/naming';
5
+ import Button from '../../../../ui/button/button.svelte';
6
+ import * as Dialog from '../../../../ui/dialog/index.js';
7
+ import type { CollectionContext } from '../../../../../context/collection.svelte.js';
8
+ import { FolderPlus } from '@lucide/svelte';
9
+ import RenderFields from '../../../../../index.server.js/components/fields/RenderFields.svelte';
10
+ import { API_PROXY, setAPIProxyContext } from '../../../../../index.server.js/context/api-proxy.svelte';
11
+ import { getConfigContext } from '../../../../../index.server.js/context/config.svelte';
12
+ import {
13
+ setDocumentFormContext,
14
+ type FormSuccessData
15
+ } from '../../../../../index.server.js/context/documentForm.svelte';
16
+
17
+ type Props = { collection: CollectionContext };
18
+ const { collection }: Props = $props();
19
+
20
+ const configCtx = getConfigContext();
21
+ const directoriesConfig = configCtx.getCollection(withDirectoriesSuffix(collection.config.slug));
22
+ let open = $state(false);
23
+ setAPIProxyContext(API_PROXY.DOCUMENT);
24
+ let formElement = $state<HTMLFormElement>();
25
+
26
+ async function beforeRedirect(data?: FormSuccessData) {
27
+ open = false;
28
+ invalidateAll();
29
+ return false;
30
+ }
31
+
32
+ const form = setDocumentFormContext({
33
+ element: () => formElement,
34
+ initial: {
35
+ parent: collection.upload.currentPath
36
+ },
37
+ readOnly: false,
38
+ config: directoriesConfig,
39
+ key: withDirectoriesSuffix(collection.config.slug),
40
+ beforeRedirect: beforeRedirect
41
+ });
42
+
43
+ function handleKeyDown(event: KeyboardEvent) {
44
+ if (!open) return;
45
+ if (!formElement) throw Error('formElement is not defined');
46
+ if ((event.ctrlKey || event.metaKey) && event.key === 's') {
47
+ event.preventDefault();
48
+ if (!form.canSubmit) return;
49
+ const saveButton = formElement.querySelector('button[data-submit]');
50
+ if (saveButton) {
51
+ formElement.requestSubmit(saveButton as HTMLButtonElement);
52
+ } else {
53
+ // Fallback to default submit if no specific button found
54
+ formElement.requestSubmit();
55
+ }
56
+ }
57
+ }
58
+ </script>
59
+
60
+ <svelte:window onkeydown={handleKeyDown} />
61
+
62
+ <Dialog.Root bind:open>
63
+ <Dialog.Trigger>
64
+ {#snippet child(props)}
65
+ <Button
66
+ disabled={collection.selectMode}
67
+ onclick={() => (open = true)}
68
+ size="icon-sm"
69
+ variant="ghost"
70
+ {...props}
71
+ >
72
+ <FolderPlus size={17} />
73
+ </Button>
74
+ {/snippet}
75
+ </Dialog.Trigger>
76
+ <Dialog.Content class="rz-status-dialog">
77
+ {#snippet child({ props })}
78
+ <form use:form.enhance action={form.buildPanelActionUrl()} bind:this={formElement} {...props}>
79
+ <Dialog.Header>{t__('common.create_folder')}</Dialog.Header>
80
+ <RenderFields {form} fields={directoriesConfig.fields} />
81
+ <Dialog.Footer --rz-justify-content="space-between">
82
+ <Button data-submit disabled={!form.canSubmit} type="submit">
83
+ {t__('common.create')}
84
+ </Button>
85
+ <Button variant="secondary" onclick={() => (open = false)}>Cancel</Button>
86
+ </Dialog.Footer>
87
+ </form>
88
+ {/snippet}
89
+ </Dialog.Content>
90
+ </Dialog.Root>
@@ -0,0 +1,7 @@
1
+ import type { CollectionContext } from '../../../../../context/collection.svelte.js';
2
+ type Props = {
3
+ collection: CollectionContext;
4
+ };
5
+ declare const CreateFolder: import("svelte").Component<Props, {}, "">;
6
+ type CreateFolder = ReturnType<typeof CreateFolder>;
7
+ export default CreateFolder;
@@ -27,8 +27,8 @@
27
27
  onEnd: function (evt) {
28
28
  const { newIndex, oldIndex } = evt;
29
29
 
30
- //@ts-expect-error annoying
31
30
  const fromParentId =
31
+ //@ts-expect-error annoying
32
32
  evt.item.getAttribute('data-parent') || evt.item.__attributes?.['data-parent'];
33
33
  //@ts-expect-error annoying
34
34
  const toParentId = evt.to.getAttribute('data-id') || evt.to.__attributes?.['data-id'];
@@ -25,6 +25,7 @@
25
25
  });
26
26
 
27
27
  async function sendPasswordResetLink() {
28
+ // @ts-expect-error better-auth type issue to resolve
28
29
  const { data, error } = await authClient.forgetPassword({
29
30
  email: form.values.email,
30
31
  redirectTo: `/reset-password?slug=staff`
@@ -37,7 +38,10 @@
37
38
  }
38
39
  }
39
40
 
40
- const passwordConfig = text('password').placeholder(t__('fields.password')).required().validate(validate.password);
41
+ const passwordConfig = text('password')
42
+ .placeholder(t__('fields.password'))
43
+ .required()
44
+ .validate(validate.password);
41
45
  const Text = text('mock').component;
42
46
 
43
47
  const confirmPasswordConfig = text('confirmPassword')
@@ -59,7 +63,12 @@
59
63
  {#if operation === 'create'}
60
64
  {#if isAuthConfig(collection) && collection.auth.type === 'password'}
61
65
  <Text {form} type="password" config={passwordConfig.compile()} path="password" />
62
- <Text {form} type="password" config={confirmPasswordConfig.compile()} path="confirmPassword" />
66
+ <Text
67
+ {form}
68
+ type="password"
69
+ config={confirmPasswordConfig.compile()}
70
+ path="confirmPassword"
71
+ />
63
72
  {/if}
64
73
  {:else if user.attributes.roles.includes('admin') && page.data?.hasMailer}
65
74
  {#if isAuthConfig(collection) && collection.auth.type === 'password'}
@@ -21,7 +21,9 @@
21
21
  let deleteConfirmOpen = $state(false);
22
22
  let dupplicateConfirmOpen = $state(false);
23
23
  const isCollection = $derived(form.config.type === 'collection');
24
- const allowDuplicate = $derived(form.config.type === 'collection' && !form.config.auth && !form.config.upload);
24
+ const allowDuplicate = $derived(
25
+ form.config.type === 'collection' && !form.config.auth && !form.config.upload
26
+ );
25
27
  const locale = getLocaleContext();
26
28
 
27
29
  function handleNewDraft() {
@@ -42,7 +44,9 @@
42
44
  const isVersionPage = $derived(page.url.pathname.includes('/versions'));
43
45
 
44
46
  function handleViewVersion() {
45
- const basUrl = isCollection ? panelUrl(form.config.kebab, form.values.id) : panelUrl(form.config.kebab);
47
+ const basUrl = isCollection
48
+ ? panelUrl(form.config.kebab, form.values.id)
49
+ : panelUrl(form.config.kebab);
46
50
  return goto(`${basUrl}/versions?${PARAMS.VERSION_ID}=${form.values.versionId}`);
47
51
  }
48
52
 
@@ -1,8 +1,12 @@
1
1
  <script lang="ts">
2
- import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
2
+ import {
3
+ Dialog as DialogPrimitive,
4
+ type DialogContentSnippetProps,
5
+ type WithoutChildrenOrChild
6
+ } from 'bits-ui';
3
7
  import type { Snippet } from 'svelte';
4
- import * as Dialog from './index.js';
5
8
  import './dialog-content.css';
9
+ import * as Dialog from './index.js';
6
10
 
7
11
  let {
8
12
  ref = $bindable(null),
@@ -11,14 +15,25 @@
11
15
  children,
12
16
  ...restProps
13
17
  }: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
14
- children: Snippet;
15
- size?: 'sm' | 'default' | 'lg'
18
+ children?: Snippet;
19
+ child?: Snippet<
20
+ [
21
+ DialogContentSnippetProps & {
22
+ props: Record<string, unknown>;
23
+ }
24
+ ]
25
+ >;
26
+ size?: 'sm' | 'default' | 'lg';
16
27
  } = $props();
17
28
  </script>
18
29
 
19
30
  <Dialog.Portal>
20
31
  <Dialog.Overlay />
21
- <DialogPrimitive.Content bind:ref class="rz-dialog-content rz-dialog-content--{size} {className}" {...restProps}>
32
+ <DialogPrimitive.Content
33
+ bind:ref
34
+ class="rz-dialog-content rz-dialog-content--{size} {className}"
35
+ {...restProps}
36
+ >
22
37
  {@render children?.()}
23
38
  </DialogPrimitive.Content>
24
39
  </Dialog.Portal>
@@ -1,8 +1,13 @@
1
- import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
1
+ import { Dialog as DialogPrimitive, type DialogContentSnippetProps, type WithoutChildrenOrChild } from 'bits-ui';
2
2
  import type { Snippet } from 'svelte';
3
3
  import './dialog-content.css';
4
4
  type $$ComponentProps = WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
5
- children: Snippet;
5
+ children?: Snippet;
6
+ child?: Snippet<[
7
+ DialogContentSnippetProps & {
8
+ props: Record<string, unknown>;
9
+ }
10
+ ]>;
6
11
  size?: 'sm' | 'default' | 'lg';
7
12
  };
8
13
  declare const DialogContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
@@ -37,7 +37,9 @@ function createCollectionStore(args) {
37
37
  const hasVersions = $derived(!!config.versions);
38
38
  const hasDraft = $derived(config.versions && config.versions.draft);
39
39
  onMount(() => {
40
- displayMode = localStorage.getItem(`collection.${config.slug}.display`) || DISPLAY_MODE.LIST;
40
+ displayMode =
41
+ localStorage.getItem(`collection.${config.slug}.display`) ||
42
+ DISPLAY_MODE.LIST;
41
43
  const localSortBy = localStorage.getItem(`collection.${config.slug}.sortBy`);
42
44
  sortingBy = localSortBy || 'updatedAt';
43
45
  const localSortOrder = localStorage.getItem(`collection.${config.slug}.sortOrder`);
@@ -1,8 +1,8 @@
1
1
  import type { BuiltAreaClient, BuiltCollectionClient } from '../../core/config/types.js';
2
2
  import type { AreaSlug, GenericBlock, GenericDoc, TreeBlock } from '../../core/types/doc.js';
3
3
  import type { FormField, SimplerField } from '../../fields/types.js';
4
- import type { Dic } from '../../util/types.js';
5
- export declare function setDocumentFormContext<T extends GenericDoc>(args: Args<T>): {
4
+ import type { Dic, WithOptional } from '../../util/types.js';
5
+ export declare function setDocumentFormContext<T extends WithOptional<GenericDoc, 'id'>>(args: Args<T>): {
6
6
  key: string;
7
7
  setValue: (path: string, value: any) => void;
8
8
  getRawValue: <T_1>(path: string) => NonNullable<T_1> | null;
@@ -43,7 +43,11 @@ export declare function setDocumentFormContext<T extends GenericDoc>(args: Args<
43
43
  readonly element: HTMLFormElement;
44
44
  readonly canSubmit: boolean;
45
45
  readonly processing: boolean;
46
- values: T;
46
+ values: T & {
47
+ _type: any;
48
+ _prototype: any;
49
+ title: any;
50
+ };
47
51
  readonly changes: Partial<GenericDoc>;
48
52
  readonly errors: {
49
53
  readonly length: number;
@@ -67,7 +71,7 @@ export declare function setDocumentFormContext<T extends GenericDoc>(args: Args<
67
71
  readonly isLive: boolean;
68
72
  setFocusedField(path: string): void;
69
73
  };
70
- export declare function getDocumentFormContext<T extends GenericDoc>(key?: string): {
74
+ export declare function getDocumentFormContext<T extends WithOptional<GenericDoc, 'id'> = GenericDoc>(key?: string): {
71
75
  key: string;
72
76
  setValue: (path: string, value: any) => void;
73
77
  getRawValue: <T_1>(path: string) => NonNullable<T_1> | null;
@@ -108,7 +112,11 @@ export declare function getDocumentFormContext<T extends GenericDoc>(key?: strin
108
112
  readonly element: HTMLFormElement;
109
113
  readonly canSubmit: boolean;
110
114
  readonly processing: boolean;
111
- values: T;
115
+ values: T & {
116
+ _type: any;
117
+ _prototype: any;
118
+ title: any;
119
+ };
112
120
  readonly changes: Partial<GenericDoc>;
113
121
  readonly errors: {
114
122
  readonly length: number;
@@ -132,7 +140,7 @@ export declare function getDocumentFormContext<T extends GenericDoc>(key?: strin
132
140
  readonly isLive: boolean;
133
141
  setFocusedField(path: string): void;
134
142
  };
135
- export type DocumentFormContext<T extends GenericDoc = GenericDoc> = ReturnType<typeof setDocumentFormContext<T>>;
143
+ export type DocumentFormContext<T extends WithOptional<GenericDoc, 'id'> = GenericDoc> = ReturnType<typeof setDocumentFormContext<T>>;
136
144
  type AddBlock = (block: Omit<GenericBlock, 'id' | 'path'>) => void;
137
145
  type MoveBlock = (from: number, to: number) => void;
138
146
  export type FormSuccessData = {
@@ -12,6 +12,7 @@ import { isObjectLiteral, omit } from '../../util/object.js';
12
12
  import cloneDeep from 'clone-deep';
13
13
  import { diff } from 'deep-object-diff';
14
14
  import { flatten } from 'flat';
15
+ import { richTextJSONToText } from '../../fields/rich-text/client.js';
15
16
  import { getContext, setContext } from 'svelte';
16
17
  import { toast } from 'svelte-sonner';
17
18
  import { t__ } from '../../core/i18n/index.js';
@@ -23,16 +24,15 @@ import { getCollectionContext } from './collection.svelte.js';
23
24
  import { setErrorsContext } from './errors.svelte.js';
24
25
  import { getLocaleContext } from './locale.svelte.js';
25
26
  import { getUserContext } from './user.svelte.js';
26
- import { richTextJSONToText } from '../../fields/rich-text/client.js';
27
27
  function createDocumentFormState({ initial, element, config, readOnly, key, onNestedDocumentCreated, onDataChange, beforeSubmit, beforeRedirect, onFieldFocus }) {
28
28
  //
29
- let intialDoc = $state(initial);
29
+ let initialDoc = $state(initial);
30
30
  let doc = $state(initial);
31
31
  const documentConfig = compileDocumentConfig(config);
32
- const changes = $derived(diff(intialDoc, doc));
32
+ const changes = $derived(diff(initialDoc, doc));
33
33
  let isDisabled = $state(readOnly);
34
34
  let processing = $state(false);
35
- const operation = $derived(doc.id ? 'update' : 'create');
35
+ const operation = doc.id ? 'update' : 'create';
36
36
  const user = getUserContext();
37
37
  const errors = setErrorsContext(key);
38
38
  const isCollection = documentConfig.type === 'collection';
@@ -65,7 +65,7 @@ function createDocumentFormState({ initial, element, config, readOnly, key, onNe
65
65
  if (typeof value === 'string') {
66
66
  return value;
67
67
  }
68
- return initialTitle || doc.id;
68
+ return initialTitle || doc.id || '[untitled]';
69
69
  }
70
70
  $effect(() => {
71
71
  const rawTitle = getValueAtPath(documentConfig.asTitle, doc) || '[untitled]';
@@ -511,7 +511,7 @@ function createDocumentFormState({ initial, element, config, readOnly, key, onNe
511
511
  doc = (data?.document || doc);
512
512
  if (nestedLevel === 0) {
513
513
  await invalidateAll();
514
- intialDoc = doc;
514
+ initialDoc = doc;
515
515
  }
516
516
  else {
517
517
  toast.success(t__('common.doc_created'));
@@ -578,6 +578,8 @@ function createDocumentFormState({ initial, element, config, readOnly, key, onNe
578
578
  };
579
579
  };
580
580
  const buildPanelActionUrl = () => {
581
+ console.log('@buildPanelActionUrl----');
582
+ console.log(operation);
581
583
  // Start with the base URI for the panel
582
584
  let panelUri = `/panel/${config.kebab}`;
583
585
  // Add the item ID to the URI if we're updating a collection doc
@@ -686,7 +688,13 @@ function createDocumentFormState({ initial, element, config, readOnly, key, onNe
686
688
  }
687
689
  const FORM_KEY = 'rime.form';
688
690
  export function setDocumentFormContext(args) {
689
- const store = createDocumentFormState(args);
691
+ const initial = {
692
+ ...args.initial,
693
+ _type: args.initial._type || args.config.type,
694
+ _prototype: args.initial._prototype || args.config.slug,
695
+ title: args.initial.title || '[untitled]'
696
+ };
697
+ const store = createDocumentFormState({ ...args, initial });
690
698
  return setContext(`${FORM_KEY}.${args.key}`, store);
691
699
  }
692
700
  export function getDocumentFormContext(key = 'root') {
@@ -27,6 +27,7 @@
27
27
  });
28
28
 
29
29
  async function sendResetPasswordMail() {
30
+ // @ts-expect-error better-auth type issue to resolve
30
31
  const { data, error } = await authClient.forgetPassword({
31
32
  email: context.values.email,
32
33
  redirectTo: `/reset-password`
@@ -15,6 +15,20 @@ export declare const capitalize: (str: string) => string;
15
15
  * toCamelCase("hello-world");
16
16
  */
17
17
  export declare const toCamelCase: (str: string) => string;
18
+ /**
19
+ * Converts a string to camelCase while preserving a trailing _suffix if it exists.
20
+ *
21
+ * @example
22
+ * // Returns "helloWorld"
23
+ * toCamelCasePreserveTrailingUnderscoreSuffix("helloWorld");
24
+ *
25
+ * // Returns "helloWorld_directories"
26
+ * toCamelCasePreserveTrailingUnderscoreSuffix("hello-world_directories");
27
+
28
+ * // Returns "helloWorld_"
29
+ * toCamelCasePreserveTrailingUnderscoreSuffix("hello-world");
30
+ */
31
+ export declare const toCamelCasePreserveTrailingUnderscoreSuffix: (str: string) => string;
18
32
  export declare function toKebabCase(str: string): string;
19
33
  /**
20
34
  * Converts a string to PascalCase.
@@ -18,6 +18,25 @@ export const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
18
18
  * toCamelCase("hello-world");
19
19
  */
20
20
  export const toCamelCase = (str) => camelCase(str);
21
+ /**
22
+ * Converts a string to camelCase while preserving a trailing _suffix if it exists.
23
+ *
24
+ * @example
25
+ * // Returns "helloWorld"
26
+ * toCamelCasePreserveTrailingUnderscoreSuffix("helloWorld");
27
+ *
28
+ * // Returns "helloWorld_directories"
29
+ * toCamelCasePreserveTrailingUnderscoreSuffix("hello-world_directories");
30
+
31
+ * // Returns "helloWorld_"
32
+ * toCamelCasePreserveTrailingUnderscoreSuffix("hello-world");
33
+ */
34
+ export const toCamelCasePreserveTrailingUnderscoreSuffix = (str) => {
35
+ const suffixMatch = str.match(/(_[a-zA-Z]+)$/);
36
+ const suffix = suffixMatch ? suffixMatch[1] : '';
37
+ const baseString = suffix ? str.slice(0, -suffix.length) : str;
38
+ return camelCase(baseString) + suffix;
39
+ };
21
40
  /**
22
41
  * Converts a string to kebab-case.
23
42
  * Source : https://github.com/angus-c/just/blob/master/packages/string-kebab-case
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rimecms",
3
- "version": "0.24.5",
3
+ "version": "0.25.0",
4
4
  "homepage": "https://github.com/bienbiendev/rime",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -1,2 +0,0 @@
1
- import type { SimplerField, TextField } from '../../../fields/types.js';
2
- export declare const directoryInput: SimplerField<TextField>;