rimecms 0.24.0 → 0.24.1
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.
- package/README.md +32 -19
- package/dist/core/config/shared/find-title.d.ts +2 -2
- package/dist/core/config/shared/find-title.js +1 -1
- package/dist/core/operations/hooks/before-read/set-document-title.server.js +15 -2
- package/dist/fields/relation/component/Cell.svelte +10 -4
- package/dist/fields/relation/component/default/Default.svelte +1 -1
- package/dist/fields/rich-text/index.d.ts +2 -0
- package/dist/fields/rich-text/index.js +4 -0
- package/dist/panel/components/sections/collection/list/row/Row.svelte +2 -0
- package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +4 -0
- package/dist/panel/components/ui/page-header/PageHeader.svelte +4 -0
- package/dist/panel/context/documentForm.svelte.js +13 -1
- package/dist/site/components/avatar/avatar.svelte +1 -1
- package/dist/site/components/avatar/avatar.svelte.d.ts +1 -1
- package/dist/site/components/button/button.svelte +2 -2
- package/dist/site/components/card-document/card-document.svelte +92 -0
- package/dist/site/components/card-document/card-document.svelte.d.ts +7 -0
- package/dist/site/components/dialog/dialog-content.css +47 -0
- package/dist/site/components/dialog/dialog-content.svelte +28 -0
- package/dist/site/components/dialog/dialog-content.svelte.d.ts +10 -0
- package/dist/site/components/dialog/dialog-overlay.css +8 -0
- package/dist/site/components/dialog/dialog-overlay.svelte +12 -0
- package/dist/site/components/dialog/dialog-overlay.svelte.d.ts +5 -0
- package/dist/site/components/dialog/index.d.ts +8 -0
- package/dist/site/components/dialog/index.js +10 -0
- package/dist/site/components/feed/feed.svelte +12 -9
- package/dist/site/components/feed/feed.svelte.d.ts +5 -17
- package/dist/site/components/folder/folder.svelte +53 -0
- package/dist/site/components/folder/folder.svelte.d.ts +7 -0
- package/dist/site/components/nav/nav.svelte +15 -11
- package/dist/site/components/nav/post-button/post-button.svelte +52 -0
- package/dist/site/components/nav/post-button/post-button.svelte.d.ts +3 -0
- package/dist/site/components/post/post-actions/comment-button.svelte +115 -0
- package/dist/site/components/post/post-actions/comment-button.svelte.d.ts +6 -0
- package/dist/site/components/post/post-actions/like-button.svelte +76 -0
- package/dist/site/components/post/post-actions/like-button.svelte.d.ts +6 -0
- package/dist/site/components/post/post-actions/post-actions.svelte +21 -11
- package/dist/site/components/post/post-actions/post-actions.svelte.d.ts +1 -1
- package/dist/site/components/post/post-attachments.svelte +26 -0
- package/dist/site/components/post/post-attachments.svelte.d.ts +6 -0
- package/dist/site/components/post/post-date.svelte +12 -0
- package/dist/site/components/post/post-date.svelte.d.ts +6 -0
- package/dist/site/components/post/post-with-comments.svelte +42 -0
- package/dist/site/components/post/post-with-comments.svelte.d.ts +6 -0
- package/dist/site/components/post/post.svelte +28 -11
- package/dist/site/components/post/post.svelte.d.ts +1 -2
- package/dist/site/components/rich-text/bubble-menu/bubble-menu.css +17 -0
- package/dist/site/components/rich-text/bubble-menu/bubble-menu.svelte +119 -0
- package/dist/site/components/rich-text/bubble-menu/bubble-menu.svelte.d.ts +11 -0
- package/dist/site/components/rich-text/bubble-menu/icon-button/icon-button.css +15 -0
- package/dist/site/components/rich-text/bubble-menu/icon-button/icon-button.svelte +31 -0
- package/dist/site/components/rich-text/bubble-menu/icon-button/icon-button.svelte.d.ts +13 -0
- package/dist/site/components/rich-text/context.svelte.d.ts +12 -0
- package/dist/site/components/rich-text/context.svelte.js +32 -0
- package/dist/site/components/rich-text/features/bold.d.ts +2 -0
- package/dist/site/components/rich-text/features/bold.js +21 -0
- package/dist/site/components/rich-text/features/link/component/link-selector.css +4 -0
- package/dist/site/components/rich-text/features/link/component/link-selector.svelte +214 -0
- package/dist/site/components/rich-text/features/link/component/link-selector.svelte.d.ts +11 -0
- package/dist/site/components/rich-text/features/link/link.d.ts +2 -0
- package/dist/site/components/rich-text/features/link/link.js +36 -0
- package/dist/site/components/rich-text/rich-text.css +170 -0
- package/dist/site/components/rich-text/rich-text.svelte +84 -0
- package/dist/site/components/rich-text/rich-text.svelte.d.ts +9 -0
- package/dist/site/components/upload-thumbnail/upload-thumbnail.svelte +76 -0
- package/dist/site/components/upload-thumbnail/upload-thumbnail.svelte.d.ts +8 -0
- package/dist/site/components/upload-thumbnail/util.d.ts +1 -0
- package/dist/site/components/upload-thumbnail/util.js +13 -0
- package/dist/site/components/user-inline/user-inline.svelte +1 -1
- package/dist/site/components/user-inline/user-inline.svelte.d.ts +1 -1
- package/dist/site/styles/colors.css +2 -0
- package/dist/site/styles/fonts.css +160 -0
- package/dist/site/styles/fonts.mixins.css +5 -0
- package/dist/site/styles/main.css +8 -6
- package/dist/site/styles/shadows.css +10 -0
- package/dist/site/styles/sizes.css +43 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Headless CMS powered by SvelteKit.
|
|
|
31
31
|
### Content Management
|
|
32
32
|
|
|
33
33
|
Fields types:
|
|
34
|
+
|
|
34
35
|
- Blocks
|
|
35
36
|
- Tree (nested array)
|
|
36
37
|
- Tabs
|
|
@@ -52,6 +53,7 @@ Fields types:
|
|
|
52
53
|
npx sv create my-app
|
|
53
54
|
cd my-app
|
|
54
55
|
```
|
|
56
|
+
|
|
55
57
|
> [!NOTE]
|
|
56
58
|
> Select TypeScript when prompted
|
|
57
59
|
|
|
@@ -83,7 +85,7 @@ import { sveltekit } from '@sveltejs/kit/vite';
|
|
|
83
85
|
import { rime } from 'rimecms/vite';
|
|
84
86
|
|
|
85
87
|
export default defineConfig({
|
|
86
|
-
|
|
88
|
+
plugins: [rime(), sveltekit()]
|
|
87
89
|
});
|
|
88
90
|
```
|
|
89
91
|
|
|
@@ -198,29 +200,37 @@ export default rime({
|
|
|
198
200
|
|
|
199
201
|
```ts
|
|
200
202
|
export const load = async (event: LayoutServerLoadEvent) => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
203
|
+
const { rime } = event.locals;
|
|
204
|
+
// Get an Area document
|
|
205
|
+
const menu = await rime.area('menu').find();
|
|
206
|
+
// Get all pages documents
|
|
207
|
+
const pages = await rime.collection('pages').findAll({ locale: 'en' });
|
|
208
|
+
// Get a page byId
|
|
209
|
+
const home = await rime.collection('pages').findById({ locale: 'en', id: 'some-id' });
|
|
210
|
+
// Get a user with a query
|
|
211
|
+
const [user] = await rime.collection('users').find({
|
|
212
|
+
query: `where[email][equals]=some@email.com` // qs query or ParsedQsQuery
|
|
213
|
+
});
|
|
214
|
+
// Get some config values
|
|
215
|
+
const languages = rime.config.getLocalesCodes();
|
|
216
|
+
const collections = rime.config.collections;
|
|
217
|
+
//...
|
|
216
218
|
};
|
|
217
219
|
```
|
|
218
220
|
|
|
219
221
|
### From the API :
|
|
222
|
+
|
|
220
223
|
```ts
|
|
221
|
-
const { docs } = await fetch('http://localhost:5173/api/pages').then(r => r.json())
|
|
222
|
-
const { docs } = await fetch('http://localhost:5173/api/pages?sort=title&limit=1').then(r =>
|
|
223
|
-
|
|
224
|
+
const { docs } = await fetch('http://localhost:5173/api/pages').then((r) => r.json());
|
|
225
|
+
const { docs } = await fetch('http://localhost:5173/api/pages?sort=title&limit=1').then((r) =>
|
|
226
|
+
r.json()
|
|
227
|
+
);
|
|
228
|
+
const { docs } = await fetch(
|
|
229
|
+
'http://localhost:5173/api/pages?where[author][equals]=some-id&locale=en`;'
|
|
230
|
+
).then((r) => r.json());
|
|
231
|
+
const { docs } = await fetch(
|
|
232
|
+
'http://localhost:5173/api/pages?where[author.email][equals]=some@email.com&locale=en`;'
|
|
233
|
+
).then((r) => r.json());
|
|
224
234
|
```
|
|
225
235
|
|
|
226
236
|
## DEPLOYING
|
|
@@ -228,10 +238,12 @@ const { docs } = await fetch('http://localhost:5173/api/pages?where[author][like
|
|
|
228
238
|
For now I am using it with @svelte/adapter-node, other adapter not tested and probably not working.
|
|
229
239
|
|
|
230
240
|
With the node adapter :
|
|
241
|
+
|
|
231
242
|
```sh
|
|
232
243
|
npx rime build
|
|
233
244
|
npx rime build -d # to copy the database directory
|
|
234
245
|
```
|
|
246
|
+
|
|
235
247
|
It's doing bascically `vite build` under the hood and create the polka server file inside an app directory, plus giving some info on how to run it.
|
|
236
248
|
|
|
237
249
|
## ROADMAP
|
|
@@ -246,6 +258,7 @@ It's doing bascically `vite build` under the hood and create the polka server fi
|
|
|
246
258
|
- [x] Document version
|
|
247
259
|
- [x] collection nested
|
|
248
260
|
- [x] more better-auth integration
|
|
261
|
+
- [x] Handle relation poperties in queries
|
|
249
262
|
- [~] Documentation
|
|
250
263
|
- [ ] Live Edit system in practice
|
|
251
264
|
- [ ] auto-saved draft
|
|
@@ -4,8 +4,8 @@ import type { DateField } from '../../../fields/date/index.js';
|
|
|
4
4
|
import type { EmailField } from '../../../fields/email/index.js';
|
|
5
5
|
import type { SlugField } from '../../../fields/slug/index.js';
|
|
6
6
|
import type { TextField } from '../../../fields/text/index.js';
|
|
7
|
-
import type { Field, FormField } from '../../../fields/types.js';
|
|
8
|
-
export declare const hasMaybeTitle: (field: Field) => field is TextField | DateField | SlugField | EmailField;
|
|
7
|
+
import type { Field, FormField, RichTextField } from '../../../fields/types.js';
|
|
8
|
+
export declare const hasMaybeTitle: (field: Field) => field is TextField | DateField | SlugField | EmailField | RichTextField;
|
|
9
9
|
interface TitleFieldResult {
|
|
10
10
|
field: FormFieldBuilder<FormField>;
|
|
11
11
|
path: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FormFieldBuilder } from '../../fields/builders/form-field-builder.js';
|
|
2
2
|
import { isGroupField } from '../../../fields/group/index.js';
|
|
3
3
|
import { TabsBuilder } from '../../../fields/tabs/index.js';
|
|
4
|
-
export const hasMaybeTitle = (field) => ['text', 'date', 'slug', 'email'].includes(field.type);
|
|
4
|
+
export const hasMaybeTitle = (field) => ['text', 'date', 'slug', 'email', 'richText'].includes(field.type);
|
|
5
5
|
export function findTitleField(fields = [], basePath = '') {
|
|
6
6
|
for (const field of fields) {
|
|
7
7
|
// Direct check for isTitle
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getValueAtPath } from '../../../../util/object.js';
|
|
1
|
+
import { getValueAtPath, isObjectLiteral } from '../../../../util/object.js';
|
|
2
|
+
import { richTextJSONToText } from '../../../../fields/rich-text/client.js';
|
|
2
3
|
import { Hooks } from '../index.server.js';
|
|
3
4
|
export const setDocumentTitle = Hooks.beforeRead(async (args) => {
|
|
4
5
|
const config = args.config;
|
|
@@ -7,8 +8,20 @@ export const setDocumentTitle = Hooks.beforeRead(async (args) => {
|
|
|
7
8
|
const hasSelect = Array.isArray(paramSelect) && paramSelect.length;
|
|
8
9
|
const shouldSetTitle = !doc.title && (!hasSelect || (hasSelect && paramSelect.includes('title')));
|
|
9
10
|
if (shouldSetTitle) {
|
|
11
|
+
function computeTitleFromValue(value) {
|
|
12
|
+
// Handle rich text value
|
|
13
|
+
if (isObjectLiteral(value) && 'content' in value) {
|
|
14
|
+
return richTextJSONToText(value);
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === 'string') {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
return doc.id;
|
|
20
|
+
}
|
|
21
|
+
const titleRaw = getValueAtPath(config.asTitle, doc);
|
|
22
|
+
const title = computeTitleFromValue(titleRaw);
|
|
10
23
|
doc = {
|
|
11
|
-
title
|
|
24
|
+
title,
|
|
12
25
|
...doc
|
|
13
26
|
};
|
|
14
27
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
let { value }: Props = $props();
|
|
18
18
|
let displayCount = $derived(value && value.length > 1);
|
|
19
19
|
|
|
20
|
-
const APIProxy = getAPIProxyContext(API_PROXY.
|
|
20
|
+
const APIProxy = getAPIProxyContext(API_PROXY.ROOT);
|
|
21
21
|
|
|
22
22
|
let APIUrl = $derived.by(() => {
|
|
23
23
|
if (value && value.length && value[0].documentId) {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
});
|
|
34
34
|
</script>
|
|
35
35
|
|
|
36
|
-
<span>
|
|
36
|
+
<span class="rz-relation-cell">
|
|
37
37
|
{#if displayCount}
|
|
38
38
|
{value.length} items
|
|
39
39
|
{:else if ressource?.data?.doc}
|
|
@@ -44,15 +44,21 @@
|
|
|
44
44
|
/>
|
|
45
45
|
{ressource.data.doc.title}
|
|
46
46
|
{:else}
|
|
47
|
-
{ressource.data.doc.title}
|
|
47
|
+
<span class="rz-relation-cell__title">{ressource.data.doc.title}</span>
|
|
48
48
|
{/if}
|
|
49
49
|
{/if}
|
|
50
50
|
</span>
|
|
51
51
|
|
|
52
52
|
<style>
|
|
53
|
-
|
|
53
|
+
.rz-relation-cell {
|
|
54
54
|
display: flex;
|
|
55
55
|
gap: var(--rz-size-2);
|
|
56
56
|
align-items: center;
|
|
57
57
|
}
|
|
58
|
+
.rz-relation-cell__title {
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
display: -webkit-box;
|
|
61
|
+
-webkit-box-orient: vertical;
|
|
62
|
+
-webkit-line-clamp: 1;
|
|
63
|
+
}
|
|
58
64
|
</style>
|
|
@@ -9,6 +9,7 @@ export declare class RichTextFieldBuilder extends FormFieldBuilder<RichTextField
|
|
|
9
9
|
get cell(): import("svelte").Component<{
|
|
10
10
|
value: string;
|
|
11
11
|
}, {}, "">;
|
|
12
|
+
isTitle(): this;
|
|
12
13
|
/**
|
|
13
14
|
* Sets a custom TipTap editor configuration for the rich text field.
|
|
14
15
|
*
|
|
@@ -44,6 +45,7 @@ type RichTextContent = {
|
|
|
44
45
|
};
|
|
45
46
|
export type RichTextField = FormField & {
|
|
46
47
|
type: 'richText';
|
|
48
|
+
isTitle?: true;
|
|
47
49
|
features?: Array<RichTextFeature>;
|
|
48
50
|
defaultValue?: RichTextContent | DefaultValueFn<RichTextContent>;
|
|
49
51
|
};
|
|
@@ -23,6 +23,7 @@ import { getCollectionContext } from './collection.svelte.js';
|
|
|
23
23
|
import { setErrorsContext } from './errors.svelte.js';
|
|
24
24
|
import { getLocaleContext } from './locale.svelte.js';
|
|
25
25
|
import { getUserContext } from './user.svelte.js';
|
|
26
|
+
import { richTextJSONToText } from '../../fields/rich-text/client.js';
|
|
26
27
|
function createDocumentFormState({ initial, element, config, readOnly, key, onNestedDocumentCreated, onDataChange, beforeSubmit, beforeRedirect, onFieldFocus }) {
|
|
27
28
|
//
|
|
28
29
|
let intialDoc = $state(initial);
|
|
@@ -56,8 +57,19 @@ function createDocumentFormState({ initial, element, config, readOnly, key, onNe
|
|
|
56
57
|
return documentConfig.label;
|
|
57
58
|
}
|
|
58
59
|
else {
|
|
60
|
+
function computeTitleFromValue(value) {
|
|
61
|
+
// Handle rich text value
|
|
62
|
+
if (isObjectLiteral(value) && 'content' in value) {
|
|
63
|
+
return richTextJSONToText(value);
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === 'string') {
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
return initialTitle || doc.id;
|
|
69
|
+
}
|
|
59
70
|
$effect(() => {
|
|
60
|
-
|
|
71
|
+
const rawTitle = getValueAtPath(documentConfig.asTitle, doc) || '[untitled]';
|
|
72
|
+
title = computeTitleFromValue(rawTitle);
|
|
61
73
|
if (nestedLevel === 0) {
|
|
62
74
|
titleContext.value = title;
|
|
63
75
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { isRelationPopulated } from '../../../fields/relation/client';
|
|
3
3
|
|
|
4
|
-
type Props = { user:
|
|
4
|
+
type Props = { user: StaffDoc };
|
|
5
5
|
const { user }: Props = $props();
|
|
6
6
|
|
|
7
7
|
const avatar = $derived(user.avatar && isRelationPopulated(user.avatar) ? user.avatar : null);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { UploadDoc } from '../../../types';
|
|
3
|
+
import UploadThumbnail from '../upload-thumbnail/upload-thumbnail.svelte';
|
|
4
|
+
|
|
5
|
+
type Props = { doc: UploadDoc };
|
|
6
|
+
const { doc }: Props = $props();
|
|
7
|
+
|
|
8
|
+
const thumbnailUrl = $derived.by(() => {
|
|
9
|
+
if (doc.mimeType && doc.mimeType.includes('image')) {
|
|
10
|
+
return doc._thumbnail;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
});
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="document-card">
|
|
17
|
+
<div class="document-card__preview">
|
|
18
|
+
<UploadThumbnail mimeType={doc.mimeType} url={thumbnailUrl} />
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="document-card__body">
|
|
22
|
+
<p class="document-card__title">
|
|
23
|
+
{doc.title}
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
:root {
|
|
30
|
+
--card-hover-bg: light-dark(var(--gray-14), var(--gray-3));
|
|
31
|
+
--card-bg: light-dark(var(--gray-16), var(--gray-2));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.document-card {
|
|
35
|
+
max-height: 200px;
|
|
36
|
+
border: var(--border);
|
|
37
|
+
background-color: var(--card-bg);
|
|
38
|
+
border-radius: var(--radius-sm);
|
|
39
|
+
aspect-ratio: 4 / 5;
|
|
40
|
+
width: 100%;
|
|
41
|
+
display: grid;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.document-card:hover {
|
|
45
|
+
background-color: var(--card-hover-bg);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.document-card__preview {
|
|
49
|
+
width: 100%;
|
|
50
|
+
height: 100%;
|
|
51
|
+
border-top-left-radius: var(--radius-sm);
|
|
52
|
+
border-top-right-radius: var(--radius-sm);
|
|
53
|
+
background-color: light-dark(var(--gray-12), var(--gray-4));
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.document-card :global(.upload-preview-cell) {
|
|
58
|
+
width: 100%;
|
|
59
|
+
height: 100%;
|
|
60
|
+
aspect-ratio: 5/4;
|
|
61
|
+
border-bottom-left-radius: 0;
|
|
62
|
+
border-bottom-right-radius: 0;
|
|
63
|
+
padding: var(--size-1);
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
> div {
|
|
66
|
+
border-radius: var(--radius-sm);
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.document-card__title {
|
|
72
|
+
margin-top: var(--size-2);
|
|
73
|
+
display: -webkit-box;
|
|
74
|
+
-webkit-line-clamp: 2;
|
|
75
|
+
-webkit-box-orient: vertical;
|
|
76
|
+
overflow: hidden;
|
|
77
|
+
word-break: break-all;
|
|
78
|
+
text-align: left;
|
|
79
|
+
font-family: var(--font-text);
|
|
80
|
+
font-size: var(--font-size-text-xs);
|
|
81
|
+
line-height: 1.33;
|
|
82
|
+
font-weight: 400;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.document-card__body {
|
|
86
|
+
display: flex;
|
|
87
|
+
flex-direction: column;
|
|
88
|
+
gap: var(--size-2);
|
|
89
|
+
text-align: left;
|
|
90
|
+
padding: 0 0.6rem 0.6rem 0.6rem;
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.dialog-content {
|
|
2
|
+
--gutter: var(--size-4);
|
|
3
|
+
background-color: var(--color-bg);
|
|
4
|
+
position: fixed;
|
|
5
|
+
left: calc(50% - var(--gutter));
|
|
6
|
+
top: 30%;
|
|
7
|
+
z-index: 1010;
|
|
8
|
+
display: grid;
|
|
9
|
+
width: calc(100% - 2 * var(--gutter));
|
|
10
|
+
transform: translate(-50%, -50%);
|
|
11
|
+
gap: var(--size-4);
|
|
12
|
+
padding: var(--size-3);
|
|
13
|
+
box-shadow: var(--shadow-lg);
|
|
14
|
+
border-radius: var(--radius-lg);
|
|
15
|
+
margin: 0 var(--gutter);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (min-width: 768px) {
|
|
19
|
+
.dialog-content--sm {
|
|
20
|
+
width: var(--size-xs);
|
|
21
|
+
}
|
|
22
|
+
.dialog-content--default {
|
|
23
|
+
width: var(--size-sm);
|
|
24
|
+
}
|
|
25
|
+
.dialog-content--lg {
|
|
26
|
+
width: var(--size-lg);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.dialog-content__close {
|
|
31
|
+
color: hsl(from var(--color-fg) h s l / 0.7);
|
|
32
|
+
position: absolute;
|
|
33
|
+
right: var(--size-4);
|
|
34
|
+
top: var(--size-3);
|
|
35
|
+
border-radius: var(--radius-sm);
|
|
36
|
+
opacity: 0.7;
|
|
37
|
+
transition: opacity 0.2s;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.dialog-content__close:focus {
|
|
41
|
+
outline-offset: 2px;
|
|
42
|
+
outline: 2px solid var(--color-fg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dialog-content__close:disabled {
|
|
46
|
+
pointer-events: none;
|
|
47
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import * as Dialog from './index.js';
|
|
5
|
+
import './dialog-content.css';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
ref = $bindable(null),
|
|
9
|
+
class: className,
|
|
10
|
+
size = 'default',
|
|
11
|
+
children,
|
|
12
|
+
...restProps
|
|
13
|
+
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
|
14
|
+
children: Snippet;
|
|
15
|
+
size?: 'sm' | 'default' | 'lg';
|
|
16
|
+
} = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<Dialog.Portal>
|
|
20
|
+
<Dialog.Overlay />
|
|
21
|
+
<DialogPrimitive.Content
|
|
22
|
+
bind:ref
|
|
23
|
+
class="dialog-content dialog-content--{size} {className}"
|
|
24
|
+
{...restProps}
|
|
25
|
+
>
|
|
26
|
+
{@render children?.()}
|
|
27
|
+
</DialogPrimitive.Content>
|
|
28
|
+
</Dialog.Portal>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import './dialog-content.css';
|
|
4
|
+
type $$ComponentProps = WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
|
5
|
+
children: Snippet;
|
|
6
|
+
size?: 'sm' | 'default' | 'lg';
|
|
7
|
+
};
|
|
8
|
+
declare const DialogContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
9
|
+
type DialogContent = ReturnType<typeof DialogContent>;
|
|
10
|
+
export default DialogContent;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
3
|
+
import './dialog-overlay.css';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: DialogPrimitive.OverlayProps = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<DialogPrimitive.Overlay bind:ref class="dialog-overlay {className}" {...restProps} />
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
2
|
+
import './dialog-overlay.css';
|
|
3
|
+
declare const DialogOverlay: import("svelte").Component<DialogPrimitive.OverlayProps, {}, "ref">;
|
|
4
|
+
type DialogOverlay = ReturnType<typeof DialogOverlay>;
|
|
5
|
+
export default DialogOverlay;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
2
|
+
import Overlay from './dialog-overlay.svelte';
|
|
3
|
+
import Content from './dialog-content.svelte';
|
|
4
|
+
declare const Root: import("svelte").Component<import("bits-ui").AlertDialogRootPropsWithoutHTML, {}, "open">;
|
|
5
|
+
declare const Trigger: import("svelte").Component<DialogPrimitive.TriggerProps, {}, "ref">;
|
|
6
|
+
declare const Close: import("svelte").Component<DialogPrimitive.TriggerProps, {}, "ref">;
|
|
7
|
+
declare const Portal: import("svelte").Component<import("bits-ui").PortalProps, {}, "">;
|
|
8
|
+
export { Root, Portal, Trigger, Overlay, Content, Close, Root as Dialog, Portal as DialogPortal, Trigger as DialogTrigger, Overlay as DialogOverlay, Content as DialogContent, Close as DialogClose };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
2
|
+
import Overlay from './dialog-overlay.svelte';
|
|
3
|
+
import Content from './dialog-content.svelte';
|
|
4
|
+
const Root = DialogPrimitive.Root;
|
|
5
|
+
const Trigger = DialogPrimitive.Trigger;
|
|
6
|
+
const Close = DialogPrimitive.Close;
|
|
7
|
+
const Portal = DialogPrimitive.Portal;
|
|
8
|
+
export { Root, Portal, Trigger, Overlay, Content, Close,
|
|
9
|
+
//
|
|
10
|
+
Root as Dialog, Portal as DialogPortal, Trigger as DialogTrigger, Overlay as DialogOverlay, Content as DialogContent, Close as DialogClose };
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import Post from '../post/post.svelte';
|
|
3
|
+
|
|
4
|
+
let { posts }: { posts: PostsDoc[] } = $props();
|
|
4
5
|
</script>
|
|
5
6
|
|
|
6
7
|
<div>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
{#each posts as post (post.id)}
|
|
9
|
+
<Post {post} />
|
|
10
|
+
{/each}
|
|
10
11
|
</div>
|
|
11
12
|
|
|
12
13
|
<style>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
div {
|
|
15
|
+
padding-inline: var(--size-8);
|
|
16
|
+
padding-block: var(--size-8);
|
|
17
|
+
display: grid;
|
|
18
|
+
gap: var(--size-10);
|
|
19
|
+
}
|
|
17
20
|
</style>
|
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const Feed: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type Feed = InstanceType<typeof Feed>;
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
posts: PostsDoc[];
|
|
3
|
+
};
|
|
4
|
+
declare const Feed: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
+
type Feed = ReturnType<typeof Feed>;
|
|
18
6
|
export default Feed;
|