rimecms 0.27.5 → 0.28.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 (231) hide show
  1. package/dist/adapter-sqlite/{area.js → area.server.js} +2 -2
  2. package/dist/adapter-sqlite/{blocks.d.ts → blocks.server.d.ts} +1 -1
  3. package/dist/adapter-sqlite/{blocks.js → blocks.server.js} +1 -1
  4. package/dist/adapter-sqlite/{collection.js → collection.server.js} +17 -8
  5. package/dist/adapter-sqlite/generate-schema/templates.server.d.ts +1 -1
  6. package/dist/adapter-sqlite/generate-schema/templates.server.js +3 -2
  7. package/dist/adapter-sqlite/generate-schema/write.server.js +2 -2
  8. package/dist/adapter-sqlite/index.server.d.ts +8 -8
  9. package/dist/adapter-sqlite/index.server.js +7 -7
  10. package/dist/adapter-sqlite/{orderBy.js → orderBy.server.js} +1 -1
  11. package/dist/adapter-sqlite/{relations.d.ts → relations.server.d.ts} +1 -1
  12. package/dist/adapter-sqlite/{relations.js → relations.server.js} +1 -1
  13. package/dist/adapter-sqlite/{transform.js → transform.server.js} +2 -3
  14. package/dist/adapter-sqlite/{tree.d.ts → tree.server.d.ts} +1 -1
  15. package/dist/adapter-sqlite/{tree.js → tree.server.js} +1 -1
  16. package/dist/adapter-sqlite/url.server.d.ts +1 -1
  17. package/dist/core/areas/local-api.server.d.ts +1 -1
  18. package/dist/core/areas/local-api.server.js +1 -0
  19. package/dist/core/collections/api/delete.server.js +1 -1
  20. package/dist/core/collections/api/get.server.js +1 -1
  21. package/dist/core/collections/api/getById.server.js +3 -1
  22. package/dist/core/collections/config/augment-panel.d.ts +13 -0
  23. package/dist/core/collections/config/augment-panel.js +19 -0
  24. package/dist/core/collections/config/augment-upload.server.d.ts +1 -0
  25. package/dist/core/collections/config/augment-upload.server.js +1 -0
  26. package/dist/core/collections/config/builder.js +3 -1
  27. package/dist/core/collections/config/builder.server.js +3 -1
  28. package/dist/core/collections/local-api.server.js +3 -1
  29. package/dist/core/collections/operations/findById.js +3 -1
  30. package/dist/core/collections/upload/hooks/convert-base64.server.js +1 -1
  31. package/dist/core/config/auth/better-auth.server.d.ts +3 -3
  32. package/dist/core/config/auth/better-auth.server.js +1 -1
  33. package/dist/core/config/client/augment-panel.d.ts +4 -4
  34. package/dist/core/config/client/build-config.d.ts +5 -5
  35. package/dist/core/config/server/augment-directories.server.js +3 -3
  36. package/dist/core/config/server/augment-staff.server.d.ts +1 -1
  37. package/dist/core/config/server/augment-staff.server.js +1 -1
  38. package/dist/core/config/server/build-config.server.d.ts +12 -12
  39. package/dist/core/config/server/build-config.server.js +1 -1
  40. package/dist/core/config/server/{validate.js → validate.server.js} +1 -1
  41. package/dist/core/config/server/{write.js → write.server.js} +1 -1
  42. package/dist/core/config/shared/augment-icons.d.ts +1 -2
  43. package/dist/core/config/shared/get-staff-collection.d.ts +1 -1
  44. package/dist/core/config/shared/upload-directories.js +1 -1
  45. package/dist/core/config/types.d.ts +20 -8
  46. package/dist/core/dev/cli/generate/{index.js → index.server.js} +2 -2
  47. package/dist/core/dev/cli/index.js +3 -3
  48. package/dist/core/dev/cli/init/{index.js → index.server.js} +68 -25
  49. package/dist/core/dev/cli/init/{packageManagerUtil.js → package-manager-util.server.js} +5 -5
  50. package/dist/core/dev/generate/routes/{area.d.ts → area.server.d.ts} +1 -1
  51. package/dist/core/dev/generate/routes/{area.js → area.server.js} +1 -1
  52. package/dist/core/dev/generate/routes/{collection.d.ts → collection.server.d.ts} +1 -1
  53. package/dist/core/dev/generate/routes/{collection.js → collection.server.js} +1 -1
  54. package/dist/core/dev/generate/routes/{common.d.ts → common.server.d.ts} +1 -1
  55. package/dist/core/dev/generate/routes/{common.js → common.server.js} +26 -11
  56. package/dist/core/dev/generate/routes/{index.js → index.server.js} +5 -5
  57. package/dist/core/dev/generate/routes/{util.js → util.server.js} +1 -1
  58. package/dist/core/dev/generate/types/{index.js → index.server.js} +1 -1
  59. package/dist/core/dev/vite/{index.js → index.server.js} +1 -1
  60. package/dist/core/fields/util.d.ts +13 -0
  61. package/dist/core/fields/util.js +77 -4
  62. package/dist/core/i18n/en/common.d.ts +2 -0
  63. package/dist/core/i18n/en/common.js +2 -0
  64. package/dist/core/i18n/fr/common.d.ts +2 -0
  65. package/dist/core/i18n/fr/common.js +2 -0
  66. package/dist/core/operations/hooks/before-read/populate-url.server.js +10 -2
  67. package/dist/core/operations/hooks/before-upsert/handle-new-version.server.js +5 -4
  68. package/dist/core/operations/relations/diff.server.d.ts +1 -1
  69. package/dist/core/operations/relations/extract.server.d.ts +1 -1
  70. package/dist/core/operations/shared/fallback-data-from-original.d.ts +1 -0
  71. package/dist/core/operations/shared/fallback-data-from-original.js +5 -0
  72. package/dist/core/rime.server.d.ts +22 -8
  73. package/dist/core/rime.server.js +5 -5
  74. package/dist/fields/blocks/component/Block.svelte +13 -19
  75. package/dist/fields/blocks/component/Blocks.svelte +6 -13
  76. package/dist/fields/checkbox/index.server.js +1 -1
  77. package/dist/fields/combobox/index.server.js +3 -2
  78. package/dist/fields/date/index.server.js +1 -1
  79. package/dist/fields/email/index.server.js +1 -1
  80. package/dist/fields/group/component/Group.svelte +6 -13
  81. package/dist/fields/link/index.server.js +1 -1
  82. package/dist/fields/number/component/number.css +2 -0
  83. package/dist/fields/number/index.server.js +1 -1
  84. package/dist/fields/radio/index.server.js +1 -1
  85. package/dist/fields/relation/component/default/Default.svelte +1 -7
  86. package/dist/fields/relation/component/upload/upload.css +1 -10
  87. package/dist/fields/relation/index.d.ts +21 -6
  88. package/dist/fields/relation/index.js +41 -11
  89. package/dist/fields/relation/index.server.js +1 -1
  90. package/dist/fields/rich-text/component/RichText.svelte +4 -4
  91. package/dist/fields/rich-text/component/bubble-menu/bubble-menu.svelte +6 -6
  92. package/dist/fields/rich-text/component/bubble-menu/bubble-menu.svelte.d.ts +2 -0
  93. package/dist/fields/rich-text/component/drag-handle/drag-handle.css +1 -0
  94. package/dist/fields/rich-text/component/styles/rich-text.css +0 -7
  95. package/dist/fields/rich-text/core/features/resource/resource.svelte +2 -9
  96. package/dist/fields/rich-text/core/features/upload/upload.svelte +5 -12
  97. package/dist/fields/rich-text/core/render-rich-text.svelte +5 -3
  98. package/dist/fields/rich-text/index.d.ts +1 -1
  99. package/dist/fields/rich-text/index.server.d.ts +1 -1
  100. package/dist/fields/rich-text/index.server.js +1 -1
  101. package/dist/fields/select/component/Select.svelte +5 -11
  102. package/dist/fields/select/index.server.d.ts +1 -1
  103. package/dist/fields/select/index.server.js +2 -1
  104. package/dist/fields/slug/index.server.js +1 -1
  105. package/dist/fields/tabs/index.d.ts +1 -0
  106. package/dist/fields/tabs/index.js +3 -0
  107. package/dist/fields/text/index.server.js +1 -1
  108. package/dist/fields/textarea/component/TextArea.svelte +5 -13
  109. package/dist/fields/textarea/index.server.js +1 -1
  110. package/dist/fields/time/index.server.js +1 -1
  111. package/dist/fields/toggle/index.server.js +1 -1
  112. package/dist/fields/tree/component/TreeBlock.svelte +12 -18
  113. package/dist/fields/types.d.ts +3 -2
  114. package/dist/live.d.ts +2 -1
  115. package/dist/live.js +2 -1
  116. package/dist/panel/components/fields/Error.svelte +1 -7
  117. package/dist/panel/components/sections/auth/AuthForm.svelte +2 -4
  118. package/dist/panel/components/sections/collection/Empty.svelte +1 -0
  119. package/dist/panel/components/sections/collection/folder/Folder.svelte +7 -16
  120. package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte +1 -1
  121. package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte +22 -12
  122. package/dist/panel/components/sections/collection/grid/create-directory-dialog/CreateDirectoryDialog.svelte +4 -5
  123. package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte +41 -33
  124. package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte.d.ts +4 -0
  125. package/dist/panel/components/sections/collection/header/ButtonCreate.svelte +14 -16
  126. package/dist/panel/components/sections/collection/header/ButtonCreate.svelte.d.ts +2 -0
  127. package/dist/panel/components/sections/collection/header/DisplayMode.svelte +10 -10
  128. package/dist/panel/components/sections/collection/header/SearchInput.svelte +2 -8
  129. package/dist/panel/components/sections/collection/list/CollectionList.svelte +32 -3
  130. package/dist/panel/components/sections/collection/list/header/Header.svelte +3 -9
  131. package/dist/panel/components/sections/collection/list/row/Row.svelte +41 -27
  132. package/dist/panel/components/sections/collection/list/row/Row.svelte.d.ts +9 -0
  133. package/dist/panel/components/sections/collection/tree/CollectionTree.svelte +1 -1
  134. package/dist/panel/components/sections/collection/upload-thumb-cell/UploadThumbCell.svelte +11 -1
  135. package/dist/panel/components/sections/document/ButtonStatus.svelte +3 -11
  136. package/dist/panel/components/sections/document/CurrentlyEdited.svelte +1 -2
  137. package/dist/panel/components/sections/document/Document.svelte +24 -41
  138. package/dist/panel/components/sections/document/Document.svelte.d.ts +0 -1
  139. package/dist/panel/components/sections/document/Versions.svelte +1 -2
  140. package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +11 -21
  141. package/dist/panel/components/sections/live/LiveEdit.svelte +114 -0
  142. package/dist/panel/components/sections/live/LiveEdit.svelte.d.ts +32 -0
  143. package/dist/panel/components/sections/live/LiveEditPanel.svelte +53 -0
  144. package/dist/panel/components/sections/live/LiveEditPanel.svelte.d.ts +11 -0
  145. package/dist/panel/components/sections/live/LiveFloatingUI.svelte +106 -0
  146. package/dist/panel/components/sections/live/LiveFloatingUI.svelte.d.ts +12 -0
  147. package/dist/panel/components/sections/live/Provider.svelte +4 -4
  148. package/dist/panel/components/sections/live/Provider.svelte.d.ts +5 -3
  149. package/dist/panel/components/sections/live/live-edit-panel.css +12 -0
  150. package/dist/panel/components/sections/page-layout/Page.svelte +0 -4
  151. package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +2 -9
  152. package/dist/panel/components/ui/button/button.svelte +35 -54
  153. package/dist/panel/components/ui/calendar/calendar.css +11 -0
  154. package/dist/panel/components/ui/card-document/card-document.svelte +21 -14
  155. package/dist/panel/components/ui/card-resource/card-resource.svelte +8 -14
  156. package/dist/panel/components/ui/checkbox/checkbox.svelte +1 -1
  157. package/dist/panel/components/ui/command/command-group.css +1 -0
  158. package/dist/panel/components/ui/dialog/dialog-overlay.css +1 -2
  159. package/dist/panel/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +1 -7
  160. package/dist/panel/components/ui/input/input.svelte +13 -23
  161. package/dist/panel/components/ui/label/label.css +0 -1
  162. package/dist/panel/components/ui/nav/NavItemButton.svelte +2 -8
  163. package/dist/panel/components/ui/page-header/PageHeader.svelte +6 -13
  164. package/dist/panel/components/ui/radio-group/radio-group.css +2 -0
  165. package/dist/panel/components/ui/scroll-area/scroll-area.css +0 -4
  166. package/dist/panel/components/ui/sheet/sheet.css +1 -18
  167. package/dist/panel/components/ui/tabs/tabs.css +7 -0
  168. package/dist/panel/context/collection.svelte.d.ts +0 -4
  169. package/dist/panel/context/collection.svelte.js +0 -3
  170. package/dist/panel/context/documentForm.svelte.js +1 -0
  171. package/dist/panel/context/live.svelte.d.ts +8 -20
  172. package/dist/panel/context/live.svelte.js +65 -35
  173. package/dist/panel/context/livePanel.svelte.d.ts +11 -0
  174. package/dist/panel/context/livePanel.svelte.js +8 -0
  175. package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +1 -7
  176. package/dist/panel/pages/collection/Collection.svelte +3 -1
  177. package/dist/panel/pages/dashboard/Dashboard.svelte +52 -28
  178. package/dist/panel/pages/dashboard/DashboardCollection.svelte +91 -0
  179. package/dist/panel/pages/dashboard/DashboardCollection.svelte.d.ts +9 -0
  180. package/dist/panel/pages/dashboard/load.server.js +30 -14
  181. package/dist/panel/pages/dashboard/types.d.ts +1 -0
  182. package/dist/panel/pages/live/Live.svelte +244 -67
  183. package/dist/panel/pages/live/Live.svelte.d.ts +9 -1
  184. package/dist/panel/pages/live/load.server.js +14 -1
  185. package/dist/panel/style/index.css +563 -8
  186. package/dist/panel/style/mixins/index.css +1 -3
  187. package/dist/panel/util/upload.d.ts +1 -1
  188. package/dist/util/object.js +3 -0
  189. package/package.json +12 -10
  190. package/dist/panel/components/sections/document/FloatingUI.svelte +0 -81
  191. package/dist/panel/components/sections/document/FloatingUI.svelte.d.ts +0 -8
  192. package/dist/panel/components/sections/live/SidePanel.svelte +0 -61
  193. package/dist/panel/components/sections/live/SidePanel.svelte.d.ts +0 -14
  194. package/dist/panel/components/sections/live/side-panel.css +0 -15
  195. /package/dist/adapter-sqlite/{area.d.ts → area.server.d.ts} +0 -0
  196. /package/dist/adapter-sqlite/{collection.d.ts → collection.server.d.ts} +0 -0
  197. /package/dist/adapter-sqlite/{orderBy.d.ts → orderBy.server.d.ts} +0 -0
  198. /package/dist/adapter-sqlite/{transform.d.ts → transform.server.d.ts} +0 -0
  199. /package/dist/adapter-sqlite/{types.d.ts → types.server.d.ts} +0 -0
  200. /package/dist/adapter-sqlite/{types.js → types.server.js} +0 -0
  201. /package/dist/adapter-sqlite/{util.d.ts → util.server.d.ts} +0 -0
  202. /package/dist/adapter-sqlite/{util.js → util.server.js} +0 -0
  203. /package/dist/adapter-sqlite/{where.d.ts → where.server.d.ts} +0 -0
  204. /package/dist/adapter-sqlite/{where.js → where.server.js} +0 -0
  205. /package/dist/adapter-sqlite/{with.d.ts → with.server.d.ts} +0 -0
  206. /package/dist/adapter-sqlite/{with.js → with.server.js} +0 -0
  207. /package/dist/core/collections/upload/util/{converter.d.ts → converter.server.d.ts} +0 -0
  208. /package/dist/core/collections/upload/util/{converter.js → converter.server.js} +0 -0
  209. /package/dist/core/config/auth/{better-auth-hooks.d.ts → better-auth-hooks.server.d.ts} +0 -0
  210. /package/dist/core/config/auth/{better-auth-hooks.js → better-auth-hooks.server.js} +0 -0
  211. /package/dist/core/config/server/{augment-cors.d.ts → augment-cors.server.d.ts} +0 -0
  212. /package/dist/core/config/server/{augment-cors.js → augment-cors.server.js} +0 -0
  213. /package/dist/core/config/server/{validate.d.ts → validate.server.d.ts} +0 -0
  214. /package/dist/core/config/server/{write.d.ts → write.server.d.ts} +0 -0
  215. /package/dist/core/dev/cache/{index.d.ts → index.server.d.ts} +0 -0
  216. /package/dist/core/dev/cache/{index.js → index.server.js} +0 -0
  217. /package/dist/core/dev/cli/clear/{index.d.ts → index.server.d.ts} +0 -0
  218. /package/dist/core/dev/cli/clear/{index.js → index.server.js} +0 -0
  219. /package/dist/core/dev/cli/generate/{index.d.ts → index.server.d.ts} +0 -0
  220. /package/dist/core/dev/cli/init/{getPackageName.d.ts → get-package-info.server.d.ts} +0 -0
  221. /package/dist/core/dev/cli/init/{getPackageName.js → get-package-info.server.js} +0 -0
  222. /package/dist/core/dev/cli/init/{index.d.ts → index.server.d.ts} +0 -0
  223. /package/dist/core/dev/cli/init/{packageManagerUtil.d.ts → package-manager-util.server.d.ts} +0 -0
  224. /package/dist/core/dev/generate/routes/{custom-css.d.ts → custom-css.server.d.ts} +0 -0
  225. /package/dist/core/dev/generate/routes/{custom-css.js → custom-css.server.js} +0 -0
  226. /package/dist/core/dev/generate/routes/{index.d.ts → index.server.d.ts} +0 -0
  227. /package/dist/core/dev/generate/routes/{util.d.ts → util.server.d.ts} +0 -0
  228. /package/dist/core/dev/generate/sanitize/{index.d.ts → index.server.d.ts} +0 -0
  229. /package/dist/core/dev/generate/sanitize/{index.js → index.server.js} +0 -0
  230. /package/dist/core/dev/generate/types/{index.d.ts → index.server.d.ts} +0 -0
  231. /package/dist/core/dev/vite/{index.d.ts → index.server.d.ts} +0 -0
@@ -1,20 +1,26 @@
1
+ import { page } from '$app/state';
2
+ import { env } from '$env/dynamic/public';
1
3
  import { apiUrl } from '../../core/api/index.js';
4
+ import { PARAMS } from '../../core/constant.js';
2
5
  import { toKebabCase } from '../../util/string.js';
3
6
  import { getContext, setContext } from 'svelte';
4
- import { isObjectLiteral, setValueAtPath } from '../../util/object.js';
7
+ import { getValueAtPath, isObjectLiteral, setValueAtPath } from '../../util/object.js';
5
8
  const LIVE_KEY = Symbol('rime.live');
6
9
  function createStore(href) {
7
10
  let enabled = $state(false);
8
11
  let doc = $state();
9
- const callbacks = [];
10
- let currentFocusedElement = $state();
12
+ const liveStore = $state({});
13
+ let activePanelKey = $state(null);
14
+ const origin = new URL(env.PUBLIC_RIME_URL).origin;
11
15
  /**
12
16
  * Handles navigation within iframe to maintain live editing mode
13
17
  */
14
18
  const beforeNavigate = (params) => {
15
- if (window && window.top && params.to?.url.href && enabled) {
16
- // Send navigation message to parent with live=1 param
17
- window.top.postMessage({ location: params.to.url.href + '?live=1' });
19
+ if (params.type === 'leave')
20
+ return;
21
+ const url = params.to?.url.href;
22
+ if (window && window.top && url && enabled) {
23
+ window.top.postMessage({ location: url + '?live=1' });
18
24
  params.cancel();
19
25
  }
20
26
  };
@@ -22,6 +28,9 @@ function createStore(href) {
22
28
  * Processes messages from parent window
23
29
  */
24
30
  const onMessage = async (e) => {
31
+ // Only accept messages from the trusted panel origin
32
+ if (e.origin !== origin)
33
+ return;
25
34
  // Handle handshake request
26
35
  if (e.data.handshake) {
27
36
  enabled = true;
@@ -30,14 +39,20 @@ function createStore(href) {
30
39
  window.top.postMessage({ handshake: href });
31
40
  }
32
41
  }
33
- // Handle field updates
42
+ // Handle panel store updates (new protocol — has `update` key)
43
+ else if (e.data.update !== undefined &&
44
+ e.data.path !== undefined &&
45
+ e.data.value !== undefined) {
46
+ await handlePanelUpdate(e.data);
47
+ }
48
+ // Handle active panel notification from parent
49
+ else if ('activePanel' in e.data) {
50
+ activePanelKey = e.data.activePanel ?? null;
51
+ }
52
+ // Handle field updates (legacy single-doc protocol)
34
53
  else if (e.data.path && e.data.value !== undefined) {
35
54
  await handleFieldUpdate(e.data);
36
55
  }
37
- // Handle focus requests
38
- else if (e.data.focus && typeof e.data.focus === 'string' && typeof document !== 'undefined') {
39
- handleFocusField(e.data.focus);
40
- }
41
56
  };
42
57
  /**
43
58
  * Recursively processes relation objects in any data structure
@@ -109,6 +124,19 @@ function createStore(href) {
109
124
  // Return primitives as is
110
125
  return value;
111
126
  };
127
+ /**
128
+ * Handles panel store updates (new multi-panel protocol)
129
+ */
130
+ const handlePanelUpdate = async (data) => {
131
+ const processedValue = await populate(data.value);
132
+ if (!data.path) {
133
+ // Empty path = full doc seed (sent on panel activation)
134
+ liveStore[data.update] = processedValue;
135
+ return;
136
+ }
137
+ const current = liveStore[data.update] ?? {};
138
+ liveStore[data.update] = setValueAtPath(data.path, current, processedValue);
139
+ };
112
140
  /**
113
141
  * Handles field value updates
114
142
  */
@@ -120,34 +148,36 @@ function createStore(href) {
120
148
  // Update the document
121
149
  doc = setValueAtPath(data.path, doc, processedValue);
122
150
  };
123
- /**
124
- * Handles focusing a specific field in the UI
125
- */
126
- const handleFocusField = (focusPath) => {
127
- const element = document.querySelector(`[data-field="${focusPath}"]`);
128
- if (element) {
129
- const ringStyle = '0px 0px 0px 1px red';
130
- // Scroll to the element
131
- element.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' });
132
- // Add highlight style
133
- element.style.boxShadow = ringStyle;
134
- if (currentFocusedElement) {
135
- currentFocusedElement.style.boxShadow = '';
136
- }
137
- currentFocusedElement = element;
138
- }
139
- };
140
- /**
141
- * Registers a callback for data changes
142
- */
143
- const onData = (callback) => {
144
- callbacks.push(callback);
145
- };
146
151
  // Return public facade
147
152
  return {
148
153
  beforeNavigate,
149
154
  onMessage,
150
- onData,
155
+ get documentUpdateURI() {
156
+ const doc = page.data.doc;
157
+ if (!doc)
158
+ throw new Error('live.doc has not been set before accessing documentAPIUpdateURL');
159
+ let uri = `/${doc._type}`;
160
+ if (doc._prototype === 'collection')
161
+ uri += `/${doc.id}`;
162
+ const params = [];
163
+ if (doc.versionId)
164
+ params.push(`${PARAMS.VERSION_ID}=${doc.versionId}`);
165
+ if (doc.locale)
166
+ params.push(`${PARAMS.LOCALE}=${doc.locale}`);
167
+ if (params.length)
168
+ uri += `?${params.join('&')}`;
169
+ return uri;
170
+ },
171
+ getPanelValue: (update, path) => {
172
+ const entry = liveStore[update];
173
+ if (!entry) {
174
+ return undefined;
175
+ }
176
+ return getValueAtPath(path, entry);
177
+ },
178
+ get activePanelKey() {
179
+ return activePanelKey;
180
+ },
151
181
  get data() {
152
182
  return { doc };
153
183
  },
@@ -0,0 +1,11 @@
1
+ export type ActivePanel = {
2
+ key: string;
3
+ update: string;
4
+ fieldPath: string;
5
+ };
6
+ export type LivePanelStore = {
7
+ readonly activePanel: ActivePanel | null;
8
+ readonly panelStack: ActivePanel[];
9
+ };
10
+ export declare function setLivePanelContext(store: LivePanelStore): LivePanelStore;
11
+ export declare function getLivePanelContext(): LivePanelStore;
@@ -0,0 +1,8 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ const KEY = Symbol('rime.live-panel');
3
+ export function setLivePanelContext(store) {
4
+ return setContext(KEY, store);
5
+ }
6
+ export function getLivePanelContext() {
7
+ return getContext(KEY);
8
+ }
@@ -51,13 +51,7 @@
51
51
  {/if}
52
52
  </AuthForm>
53
53
 
54
- <style>/**************************************/
55
-
56
- /* Font */
57
-
58
- /**************************************/
59
-
60
- p {
54
+ <style>p {
61
55
  font-size: var(--rz-text-lg);
62
56
  font-variation-settings: 'wght' 600;
63
57
  font-weight: 600;
@@ -76,7 +76,9 @@
76
76
  {/snippet}
77
77
 
78
78
  {#snippet bottomLeft()}
79
- <ButtonCreate size="sm" />
79
+ {#if collection.canCreate}
80
+ <ButtonCreate config={collection.config} size="sm" />
81
+ {/if}
80
82
  {#if collection.isUpload}
81
83
  <Separator />
82
84
  <Button
@@ -8,6 +8,7 @@
8
8
  import PageHeader from '../../components/ui/page-header/PageHeader.svelte';
9
9
  import { getConfigContext } from '../../context/config.svelte.js';
10
10
  import { Eye } from '@lucide/svelte';
11
+ import DashboardCollection from './DashboardCollection.svelte';
11
12
  import type { DashboardEntry } from './types.js';
12
13
 
13
14
  type Props = { entries: DashboardEntry[]; user?: User };
@@ -43,30 +44,36 @@
43
44
  <CustomDashBoard {entries} />
44
45
  {:else}
45
46
  <div class="rz-dashboard__content">
46
- {#each entries as entry, index (index)}
47
- {@const Icon = config.raw.icons[entry.slug]}
48
- <a class="rz-dashboard__entry" href={entry.link}>
49
- <div class="rz-dashboard__entry-icon">
50
- <Icon size="16" strokeWidth="1" />
51
- </div>
52
- <div>
53
- <header>
54
- <h2>{entry.title}</h2>
55
- </header>
56
- {#if entry.description}
57
- <p class="rz-dashboard__entry-description">{entry.description}</p>
58
- {/if}
59
- </div>
60
- </a>
61
- {/each}
47
+ <div class="rz-dashboard__collections">
48
+ {#each entries.filter((e) => e.prototype === 'collection') as entry, index (index)}
49
+ <DashboardCollection {entry} />
50
+ {/each}
51
+ </div>
52
+ <div class="rz-dashboard__areas">
53
+ {#each entries.filter((e) => e.prototype === 'area') as entry, index (index)}
54
+ {@const Icon = config.raw.icons[entry.slug]}
55
+ <a class="rz-dashboard__area" href={entry.link}>
56
+ <div class="rz-dashboard__area-icon">
57
+ <Icon size="16" strokeWidth="1" />
58
+ </div>
59
+ <div>
60
+ <header>
61
+ <h2>{entry.title}</h2>
62
+ </header>
63
+ {#if entry.description}
64
+ <p class="rz-dashboard__area-description">{entry.description}</p>
65
+ {/if}
66
+ </div>
67
+ </a>
68
+ {/each}
69
+ </div>
62
70
  </div>
63
71
  {/if}
64
72
  </div>
65
73
  {/snippet}
66
74
  </Page>
67
75
 
68
- <style>
69
- .rz-dashboard {
76
+ <style>.rz-dashboard {
70
77
  background-color: hsl(var(--rz-color-bg));
71
78
  min-height: 100vh;
72
79
 
@@ -76,10 +83,24 @@
76
83
  font-weight: 500;
77
84
  }
78
85
  }
79
- .rz-dashboard__entry {
80
- height: 100%;
81
- background-color: light-dark(hsl(var(--rz-gray-16)), hsl(var(--rz-gray-3)));
82
- border-radius: var(--rz-radius-md);
86
+
87
+ .rz-dashboard__collections {
88
+ grid-column: span 2;
89
+ display: grid;
90
+ gap: var(--rz-size-6);
91
+ }
92
+
93
+ .rz-dashboard__areas {
94
+ grid-column: span 1;
95
+ gap: var(--rz-size-4);
96
+ display: flex;
97
+ flex-direction: column;
98
+ }
99
+
100
+ .rz-dashboard__area {
101
+ background-color: light-dark(hsl(var(--rz-gray-18)), hsl(var(--rz-gray-3)));
102
+ border: var(--rz-border);
103
+ border-radius: var(--rz-radius-xl);
83
104
  padding: var(--rz-size-4);
84
105
  position: relative;
85
106
  min-height: 130px;
@@ -89,7 +110,7 @@
89
110
  transition: background-color 0.3s ease-out;
90
111
 
91
112
  &:hover {
92
- background-color: light-dark(hsl(var(--rz-gray-15)), hsl(var(--rz-gray-4)));
113
+ background-color: light-dark(hsl(var(--rz-gray-19)), hsl(var(--rz-gray-4)));
93
114
  }
94
115
 
95
116
  :global(svg) {
@@ -103,26 +124,29 @@
103
124
  gap: var(--rz-size-2);
104
125
  }
105
126
  }
106
- .rz-dashboard__entry-icon {
127
+ .rz-dashboard__area-icon {
107
128
  width: var(--rz-size-8);
108
129
  height: var(--rz-size-8);
109
- background-color: light-dark(hsl(var(--rz-gray-13)), hsl(var(--rz-gray-0)));
130
+ background-color: light-dark(hsl(var(--rz-gray-16)), hsl(var(--rz-gray-0)));
110
131
  border-radius: var(--rz-size-10);
111
132
  display: flex;
112
133
  align-items: center;
113
134
  justify-content: center;
114
135
  }
115
136
 
116
- .rz-dashboard__entry-description {
137
+ .rz-dashboard__area-description {
117
138
  opacity: 0.5;
118
139
  margin-top: var(--rz-size-1);
119
140
  }
120
141
 
121
142
  .rz-dashboard__content {
122
143
  display: grid;
123
- gap: var(--rz-size-4);
144
+ gap: var(--rz-size-16);
124
145
  padding: var(--rz-size-8) var(--rz-page-gutter);
125
146
  height: 100%;
126
- grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
147
+ grid-template-columns: repeat(1, minmax(0, 1fr));
148
+ @media (min-width: 1024px) {
149
+ grid-template-columns: repeat(3, minmax(0, 1fr));
150
+ }
127
151
  }
128
152
  </style>
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import { t__ } from '../../../core/i18n/index.js';
3
+ import Empty from '../../components/sections/collection/Empty.svelte';
4
+ import GridItem from '../../components/sections/collection/grid/grid-item/GridItem.svelte';
5
+ import ButtonCreate from '../../components/sections/collection/header/ButtonCreate.svelte';
6
+ import Row from '../../components/sections/collection/list/row/Row.svelte';
7
+ import Button from '../../components/ui/button/button.svelte';
8
+ import { getConfigContext } from '../../context/config.svelte.js';
9
+ import { ChevronRight } from '@lucide/svelte';
10
+
11
+ import type { DashboardEntry } from './types.js';
12
+
13
+ type Props = { entry: DashboardEntry & { prototype: 'collection' } };
14
+ const { entry }: Props = $props();
15
+
16
+ const config = getConfigContext();
17
+ const collectionConfig = $derived(config.getCollection(entry.slug));
18
+ </script>
19
+
20
+ <section>
21
+ <header>
22
+ <div>
23
+ <h2>{entry.title}</h2>
24
+ {#if entry.canCreate}
25
+ <ButtonCreate config={collectionConfig} size="sm" />
26
+ {/if}
27
+ <p>{entry.description}</p>
28
+ </div>
29
+ <Button variant="text" href={entry.link}>
30
+ {t__('common.view_all')}
31
+ <ChevronRight size={12} />
32
+ </Button>
33
+ </header>
34
+ {#if entry.lastEdited?.length === 0}
35
+ <Empty config={collectionConfig} />
36
+ {:else}
37
+ <div class="rz-dashboard-collection__list rz-dashboard-collection__list--{entry.layout}">
38
+ {#each entry.lastEdited as doc, index (index)}
39
+ {#if entry.layout === 'grid'}
40
+ <GridItem isSelectMode={false} config={collectionConfig} {doc} checked={false} />
41
+ {:else}
42
+ <Row isSelectMode={false} config={collectionConfig} {doc} checked={false} />
43
+ {/if}
44
+ {/each}
45
+ </div>
46
+ {/if}
47
+ </section>
48
+
49
+ <style>header {
50
+ display: flex;
51
+ gap: var(--rz-size-2);
52
+ align-items: center;
53
+ justify-content: space-between;
54
+ margin-bottom: var(--rz-size-2);
55
+ > div {
56
+ display: flex;
57
+ gap: var(--rz-size-2);
58
+ align-items: center;
59
+ }
60
+ p {
61
+ opacity: 0.5;
62
+ overflow: hidden;
63
+ display: -webkit-box;
64
+ -webkit-box-orient: vertical;
65
+ -webkit-line-clamp: 1;
66
+ }
67
+ }
68
+ h2 {
69
+ font-weight: 600;
70
+ font-size: var(--rz-size-4);
71
+ }
72
+
73
+ .rz-dashboard-collection__list {
74
+ display: grid;
75
+ gap: var(--rz-size-2);
76
+ }
77
+
78
+ .rz-dashboard-collection__list--grid {
79
+ --columns: 1;
80
+ grid-template-columns: repeat(var(--columns), minmax(150px, 1fr));
81
+ @media (min-width: 640px) {
82
+ --columns: 2;
83
+ }
84
+ @media (min-width: 1024px) {
85
+ --columns: 3;
86
+ }
87
+ @media (min-width: 1280px) {
88
+ --columns: 4;
89
+ }
90
+ }
91
+ </style>
@@ -0,0 +1,9 @@
1
+ import type { DashboardEntry } from './types.js';
2
+ type Props = {
3
+ entry: DashboardEntry & {
4
+ prototype: 'collection';
5
+ };
6
+ };
7
+ declare const DashboardCollection: import("svelte").Component<Props, {}, "">;
8
+ type DashboardCollection = ReturnType<typeof DashboardCollection>;
9
+ export default DashboardCollection;
@@ -3,20 +3,36 @@ import { capitalize } from '../../../util/string.js';
3
3
  export const dashboardLoad = async (event) => {
4
4
  const { locale, user, rime } = event.locals;
5
5
  const entries = [];
6
- const buildBaseEntry = (c) => ({
7
- prototype: 'collection',
8
- description: c.panel && c.panel?.description ? c.panel.description : null,
9
- slug: c.slug,
10
- canCreate: user && c.access.create(user, {}),
11
- link: panelUrl(c.kebab),
12
- titleSingular: c.label.singular,
13
- title: c.label.plural
14
- });
15
- const getLastEdited = async (c) => {
6
+ const normalizedPanelConfig = (c) => {
7
+ const incomingConfig = c.panel || {};
8
+ const incomingDashboardConfig = incomingConfig.dashboard || {};
9
+ return {
10
+ ...incomingConfig,
11
+ dashboard: {
12
+ layout: incomingDashboardConfig.layout ? incomingDashboardConfig.layout : 'rows',
13
+ maxEntries: incomingDashboardConfig.maxEntries || 8
14
+ }
15
+ };
16
+ };
17
+ const buildBaseEntry = (c) => {
18
+ const panelConfig = normalizedPanelConfig(c);
19
+ return {
20
+ prototype: 'collection',
21
+ description: panelConfig.description || null,
22
+ slug: c.slug,
23
+ canCreate: user && c.access.create(user, {}),
24
+ link: panelUrl(c.kebab),
25
+ titleSingular: c.label.singular,
26
+ title: c.label.plural,
27
+ layout: panelConfig.dashboard.layout
28
+ };
29
+ };
30
+ const getLastEdited = async (c, limit = 8) => {
16
31
  try {
17
32
  return await rime.collection(c.slug).find({
18
- limit: 6,
19
- locale
33
+ limit,
34
+ locale,
35
+ draft: true
20
36
  });
21
37
  }
22
38
  catch (err) {
@@ -27,10 +43,10 @@ export const dashboardLoad = async (event) => {
27
43
  };
28
44
  const promiseEntries = rime.config.raw.collections
29
45
  .filter((collection) => user && collection.access.read(user, {}))
30
- .filter((collection) => collection.panel !== false)
46
+ .filter((collection) => collection.panel !== false && collection.panel?.dashboard !== false)
31
47
  .map(async (collection) => {
32
48
  if (collection.panel) {
33
- return getLastEdited(collection).then((docs) => ({
49
+ return getLastEdited(collection, normalizedPanelConfig(collection).dashboard?.maxEntries).then((docs) => ({
34
50
  ...buildBaseEntry(collection),
35
51
  lastEdited: docs
36
52
  }));
@@ -5,6 +5,7 @@ export type DashboardEntry = {
5
5
  titleSingular: string;
6
6
  link: string;
7
7
  canCreate?: boolean;
8
+ layout?: 'rows' | 'grid';
8
9
  prototype: 'collection';
9
10
  description: string | null;
10
11
  lastEdited?: GenericDoc[];