}) => ({
+ Component: Comment,
+ props: args
+ })
+};
+
+export const Main = {
+ args: {
+ comment: comments[0]
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/Comment/Comment.svelte b/platforms/pictique/src/lib/fragments/Comment/Comment.svelte
new file mode 100644
index 00000000..86a5a068
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Comment/Comment.svelte
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
{comment.name}
+
{comment.comment}
+
+
+
+
+
{comment.upVotes}
+
+
+
+
+
{comment.time}
+
+ {#if comment?.replies?.length}
+
+ {#each comment.replies.slice(0, visibleReplies) as reply}
+ -
+
+
+
+
{reply.name}
+
{reply.comment}
+
+
+
+
+
{reply.upVotes}
+
+
+
+
+
{reply.time}
+
+
+ {/each}
+ {#if comment.replies.length > visibleReplies}
+
+ {/if}
+
+ {/if}
+
diff --git a/platforms/pictique/src/lib/fragments/CreatePostModal/CreatePostModal.svelte b/platforms/pictique/src/lib/fragments/CreatePostModal/CreatePostModal.svelte
new file mode 100644
index 00000000..67c14581
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/CreatePostModal/CreatePostModal.svelte
@@ -0,0 +1,106 @@
+
+
+
+
+
+
Create Post
+
+
+
+
+
+
+
+ {#if images.length > 0}
+
+ {#each images as image, index}
+
+

+
+
+ {/each}
+
+ {/if}
+
+
+
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.snippet.svelte b/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.snippet.svelte
new file mode 100644
index 00000000..2bb573d8
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.snippet.svelte
@@ -0,0 +1,84 @@
+
+
+{#snippet DrawerContent()}
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero dolore, necessitatibus quam
+ expedita repudiandae cum nulla totam officiis itaque earum explicabo vel soluta libero ea
+ exercitationem iusto velit incidunt quibusdam. Incidunt maiores sed, voluptas magnam magni
+ reiciendis ipsa. Totam molestias commodi incidunt obcaecati fugiat temporibus voluptatum ea
+ excepturi cumque, nostrum quod quae aperiam, nemo asperiores consectetur doloremque
+ repellat, alias consequatur. Inventore deleniti aliquam sapiente, vel ipsam tempore
+ veritatis explicabo minus harum hic itaque dolorem nostrum tenetur dicta dolores delectus
+ eveniet nisi accusantium aperiam cumque iure culpa, eos adipisci! Vel, iusto. Repellendus
+ unde incidunt a saepe reiciendis? Nam, esse voluptas aliquam repellendus cupiditate placeat
+ quis autem minima reiciendis ex unde eveniet neque qui dolorum. Dignissimos inventore quidem
+ ipsum sequi non vel? Nemo aspernatur incidunt veniam quia animi vel asperiores quidem,
+ expedita eum in qui provident, consequuntur officiis veritatis quisquam quo, necessitatibus
+ similique autem odit officia numquam cum dolore pariatur eius! Cupiditate. Facilis aliquid
+ nihil doloremque officiis fugit in minus dicta et, omnis nesciunt suscipit sequi atque
+ perferendis alias exercitationem eaque aliquam provident praesentium quae sunt quas magni
+ consequatur. Praesentium, dolor ipsa? Et, veritatis saepe animi harum eligendi fugit
+ accusamus tempore, reiciendis eveniet, dolores rerum optio earum magnam nam laudantium
+ necessitatibus incidunt minima labore laboriosam voluptatum mollitia quia? Consectetur,
+ reprehenderit! Mollitia, neque. Optio nam eius voluptatem. Facilis hic cum non est quod modi
+ sapiente ex asperiores earum, temporibus ipsum dolore optio aut mollitia fuga ducimus ipsam
+ deleniti et adipisci maxime in velit. Praesentium doloribus earum sunt quasi voluptas quo
+ expedita tempora consequatur ratione maiores accusantium dolorem sit corporis quibusdam esse
+ molestias facilis nemo, non quam? Dolores recusandae neque ex consequatur in atque? Animi
+ recusandae minus eaque nisi dicta earum sit tempore neque porro vero assumenda tempora
+ alias, quis sunt iste illo fuga in inventore quaerat? Magnam cum vero fugiat quaerat
+ provident necessitatibus. Consequatur iusto est sint doloribus quis porro quibusdam
+ inventore numquam nisi nam ullam consectetur mollitia molestiae molestias necessitatibus
+ recusandae voluptate cum aut pariatur, asperiores nobis et perspiciatis ipsam labore.
+ Delectus. Laborum quisquam ea eligendi ut nesciunt aut minima iusto sint esse laboriosam!
+ Doloremque deserunt enim et recusandae quo, nobis expedita maxime error inventore, officiis
+ nulla ipsa tempora eos commodi beatae! Atque vel vitae perspiciatis quam soluta eaque sed
+ illo autem ea ut, exercitationem sit ad quidem eius modi alias facilis labore porro esse.
+ Vel nihil expedita reprehenderit culpa facilis omnis! Non eum minima eius sapiente quo nulla
+ culpa maiores laudantium quos! Consequatur adipisci ad neque nemo! Iste aperiam, tenetur
+ nisi distinctio saepe, reiciendis sed reprehenderit, eum assumenda vel provident in. Magni
+ ex commodi soluta quod ipsum repellendus laborum assumenda velit, aperiam praesentium nemo,
+ dolor aut similique libero tenetur eum! Atque maxime laborum tenetur similique nam ipsam
+ possimus eos officia voluptates. Deleniti quas amet corporis enim possimus nostrum
+ laboriosam nisi. Quisquam, perspiciatis. Quidem unde ut sequi maxime omnis inventore sed qui
+ minima neque, accusamus officia, labore delectus et itaque repellendus. Quia. Quod unde id
+ ipsum labore ex. Non quam, provident, excepturi expedita in, fuga repellendus quibusdam qui
+ numquam similique eaque corrupti exercitationem dolorem mollitia quas! Eius facere nihil
+ natus rerum saepe. Quos atque dolorem, eaque explicabo vel sequi, nam debitis nihil velit
+ adipisci libero praesentium. Modi blanditiis odio, quis explicabo minus vel sunt eius! Odit,
+ libero exercitationem dolore sequi odio assumenda. Cum nostrum iusto ratione excepturi
+ mollitia reiciendis illo eius quisquam veniam non sunt ullam, porro suscipit beatae nesciunt
+ temporibus optio quam tempora possimus. Facere, officia quasi tempora repudiandae quo rem!
+ Explicabo cum ratione sapiente. Obcaecati at enim delectus aperiam iure ex, dolore, quae, id
+ cupiditate quam facere similique perferendis voluptates vel ut. Dolorum delectus, officiis
+ placeat amet rerum inventore nesciunt! Qui voluptas dolor similique id ratione magnam quas
+ dolore ipsum dolores consectetur, error consequuntur nemo veniam tempora temporibus modi
+ fugiat, quam officia exercitationem iusto veritatis dicta magni. Doloribus, harum provident.
+ Veniam tempora quasi, pariatur omnis temporibus ipsam modi mollitia eum fuga tempore quia?
+ Vel aliquam odit aut a! Perspiciatis sint nisi quidem, fuga eligendi architecto porro quos
+ nemo ex provident! Modi nesciunt, aspernatur iure accusamus laborum incidunt? Suscipit amet
+ dolor nihil odio id blanditiis beatae quos harum. Quasi dolorum voluptatum eaque sed vero
+ cum. Impedit, esse. Voluptates tempora saepe repellendus! Quaerat quod animi suscipit error.
+ Similique quae eaque accusantium fugit sint vero voluptas alias quidem? Animi cumque
+ repudiandae quas deleniti ea repellat provident, esse, voluptatum nam dolore consequatur non
+ blanditiis? Qui reiciendis quidem dicta iusto minima aliquam, iste itaque illo dolor earum
+ eligendi, harum sed doloremque quo voluptatum amet consectetur at quod a officiis
+ perspiciatis! Debitis perferendis pariatur cum odio! Est eveniet commodi dolorem numquam
+ voluptatibus aliquid, unde accusamus, tempora laudantium consequatur autem repudiandae,
+ quaerat magnam ducimus atque hic facilis officiis aspernatur. Ducimus necessitatibus, labore
+ praesentium consectetur libero at voluptatibus. Consequatur repudiandae magnam sit
+ blanditiis impedit fugiat totam reiciendis facilis porro sapiente harum veniam in, quos
+ excepturi commodi perspiciatis ad voluptas! Perferendis cum nulla soluta ipsa at? Fugit,
+ dignissimos mollitia! Adipisci voluptatem molestiae doloribus alias quisquam neque commodi
+ incidunt libero maiores aut consequatur error corrupti, modi illo veritatis itaque numquam
+ facere eveniet? Tenetur consectetur ipsum excepturi quaerat, facilis labore modi? Alias
+ harum dolor tempora voluptatibus nam? Incidunt laborum debitis consequuntur, blanditiis
+ laudantium ad facilis laboriosam, cupiditate optio similique saepe a, praesentium veniam
+ dignissimos modi placeat reiciendis! Quia doloribus blanditiis labore. Suscipit dolorum
+ nobis incidunt voluptatibus fugiat minima nostrum natus cum, quas magni obcaecati qui
+ perspiciatis maxime, eligendi aperiam doloribus doloremque totam asperiores a labore!
+ Explicabo quaerat doloremque labore harum vitae!
+
+{/snippet}
diff --git a/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.ts b/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.ts
new file mode 100644
index 00000000..02ea5ca1
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Drawer/Drawer.stories.ts
@@ -0,0 +1,19 @@
+import type { ComponentProps } from 'svelte';
+import { Drawer } from '..';
+import { DrawerContent } from './Drawer.stories.snippet.svelte';
+
+export default {
+ title: 'UI/Drawer',
+ component: Drawer,
+ tags: ['autodocs'],
+ render: (args: { Component: Drawer; props: ComponentProps }) => ({
+ Component: Drawer,
+ props: args
+ })
+};
+
+export const Main = {
+ args: {
+ children: DrawerContent
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/Drawer/Drawer.svelte b/platforms/pictique/src/lib/fragments/Drawer/Drawer.svelte
new file mode 100644
index 00000000..e01b1ad4
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Drawer/Drawer.svelte
@@ -0,0 +1,74 @@
+
+
+ ({
+ timeframe: 300,
+ minSwipeDistance: 60
+ })}
+ onswipe={handleDrawerSwipe}
+ class={cn(restProps.class)}
+>
+
+ {@render children?.()}
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/Header/Header.stories.ts b/platforms/pictique/src/lib/fragments/Header/Header.stories.ts
new file mode 100644
index 00000000..597e9f58
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Header/Header.stories.ts
@@ -0,0 +1,52 @@
+import type { ComponentProps } from 'svelte';
+import Header from './Header.svelte';
+
+export default {
+ title: 'UI/Header',
+ component: Header,
+ tags: ['autodocs'],
+ render: (args: { Component: Header; props: ComponentProps }) => ({
+ Component: Header,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {
+ variant: 'primary',
+ heading: 'metagram',
+ isCallBackNeeded: true,
+ callback: () => alert('clicked')
+ }
+};
+
+export const PrimaryWithNoFlash = {
+ args: {
+ variant: 'primary',
+ heading: 'messages'
+ }
+};
+
+export const Secondary = {
+ args: {
+ variant: 'secondary',
+ heading: 'Account'
+ }
+};
+
+export const SecondaryWithMenu = {
+ args: {
+ variant: 'secondary',
+ heading: 'Account',
+ isCallBackNeeded: true,
+ callback: () => alert('menu clicked')
+ }
+};
+
+export const Tertiary = {
+ args: {
+ variant: 'tertiary',
+ isCallBackNeeded: true,
+ callback: () => alert('clicked')
+ }
+};
diff --git a/platforms/metagram/src/lib/fragments/Header/Header.svelte b/platforms/pictique/src/lib/fragments/Header/Header.svelte
similarity index 100%
rename from platforms/metagram/src/lib/fragments/Header/Header.svelte
rename to platforms/pictique/src/lib/fragments/Header/Header.svelte
diff --git a/platforms/pictique/src/lib/fragments/InputFile/InputFile.stories.ts b/platforms/pictique/src/lib/fragments/InputFile/InputFile.stories.ts
new file mode 100644
index 00000000..d0d9bf93
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/InputFile/InputFile.stories.ts
@@ -0,0 +1,15 @@
+import { InputFile } from '..';
+
+export default {
+ title: 'UI/InputFile',
+ component: InputFile,
+ tags: ['autodocs'],
+ render: (args: { type: string; placeholder: string; helperText: string }) => ({
+ Component: InputFile,
+ props: args
+ })
+};
+
+export const Main = {
+ args: {}
+};
diff --git a/platforms/pictique/src/lib/fragments/InputFile/InputFile.svelte b/platforms/pictique/src/lib/fragments/InputFile/InputFile.svelte
new file mode 100644
index 00000000..14e80402
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/InputFile/InputFile.svelte
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/Message/Message.stories.ts b/platforms/pictique/src/lib/fragments/Message/Message.stories.ts
new file mode 100644
index 00000000..d2c8a074
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Message/Message.stories.ts
@@ -0,0 +1,32 @@
+import type { ComponentProps } from 'svelte';
+import Message from './Message.svelte';
+
+export default {
+ title: 'UI/Message',
+ component: Message,
+ tags: ['autodocs'],
+ render: (args: { Component: Message; props: ComponentProps }) => ({
+ Component: Message,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {
+ avatar: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ username: 'donaldthefirstt',
+ text: 'i was thinking of making it to the conference so we could take some more fire pictures like last time',
+ unread: false,
+ callback: () => alert('Message clicked')
+ }
+};
+
+export const Unread = {
+ args: {
+ avatar: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ username: 'donaldthefirstt',
+ text: 'i was thinking of making it to the conference so we could take some more fire pictures like last time',
+ unread: true,
+ callback: () => alert('Message clicked')
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/Message/Message.svelte b/platforms/pictique/src/lib/fragments/Message/Message.svelte
new file mode 100644
index 00000000..0d704f1e
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Message/Message.svelte
@@ -0,0 +1,68 @@
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.stories.ts b/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.stories.ts
new file mode 100644
index 00000000..2b4d51d1
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.stories.ts
@@ -0,0 +1,29 @@
+import type { ComponentProps } from 'svelte';
+import MessageInput from './MessageInput.svelte';
+
+export default {
+ title: 'UI/MessageInput',
+ component: MessageInput,
+ tags: ['autodocs'],
+ render: (args: { Component: MessageInput; props: ComponentProps }) => ({
+ Component: MessageInput,
+ props: args
+ })
+};
+
+export const Comment = {
+ args: {
+ variant: 'comment',
+ placeholder: 'Write your comment',
+ handleSend: () => alert('sent')
+ }
+};
+
+export const Dm = {
+ args: {
+ variant: 'dm',
+ placeholder: 'Write your message',
+ handleAdd: () => alert('add'),
+ handleSend: () => alert('sent')
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.svelte b/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.svelte
new file mode 100644
index 00000000..200bd0b7
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/MessageInput/MessageInput.svelte
@@ -0,0 +1,60 @@
+
+
+
+ {#if variant === 'comment'}
+
+ {:else}
+
+
+ {/if}
+
{
+ if (e.key === 'Enter') handleSend();
+ }}
+ />
+
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/Modal/Modal.stories.snippet.svelte b/platforms/pictique/src/lib/fragments/Modal/Modal.stories.snippet.svelte
new file mode 100644
index 00000000..6ac5d57d
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Modal/Modal.stories.snippet.svelte
@@ -0,0 +1,11 @@
+
+
+{#snippet ModalContent()}
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam rem ipsum possimus maxime
+ modi laborum inventore autem cupiditate, voluptas ex quas, eaque accusantium ipsam natus
+ sapiente libero fuga temporibus eligendi.
+
+{/snippet}
diff --git a/platforms/pictique/src/lib/fragments/Modal/Modal.stories.ts b/platforms/pictique/src/lib/fragments/Modal/Modal.stories.ts
new file mode 100644
index 00000000..1d253c83
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Modal/Modal.stories.ts
@@ -0,0 +1,19 @@
+import type { ComponentProps } from 'svelte';
+import { Modal } from '..';
+import { ModalContent } from './Modal.stories.snippet.svelte';
+
+export default {
+ title: 'UI/Modal',
+ component: Modal,
+ tags: ['autodocs'],
+ render: (args: { Component: Modal; props: ComponentProps }) => ({
+ Component: Modal,
+ props: args
+ })
+};
+
+export const Main = {
+ args: {
+ children: ModalContent
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/Modal/Modal.svelte b/platforms/pictique/src/lib/fragments/Modal/Modal.svelte
new file mode 100644
index 00000000..ff99a6f9
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Modal/Modal.svelte
@@ -0,0 +1,81 @@
+
+
+
+ {#if children}
+ {@render children?.()}
+ {/if}
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/Post/Post.stories.ts b/platforms/pictique/src/lib/fragments/Post/Post.stories.ts
new file mode 100644
index 00000000..c48995ef
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Post/Post.stories.ts
@@ -0,0 +1,41 @@
+import type { ComponentProps } from 'svelte';
+import Post from './Post.svelte';
+
+export default {
+ title: 'ui/Post',
+ component: Post,
+ tags: ['autodocs'],
+ render: (args: { Component: Post; props: ComponentProps }) => ({
+ Component: Post,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {
+ avatar: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ username: 'blurryface',
+ imgUris: [
+ 'https://graphicsfamily.com/wp-content/uploads/edd/2023/01/Free-Photographer-Social-Media-Post-Design-Template-870x870.jpg',
+ 'https://picsum.photos/200'
+ ],
+ postAlt: 'Sample',
+ text: 'Took some pictures today! Really love how this one in particular turned out! ',
+ time: '2 hours ago',
+ count: {
+ likes: 100,
+ comments: 50
+ },
+ callback: {
+ like: () => {
+ alert('Like clicked');
+ },
+ comment: () => {
+ alert('Comment clicked');
+ },
+ menu: () => {
+ alert('Menu clicked');
+ }
+ }
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/Post/Post.svelte b/platforms/pictique/src/lib/fragments/Post/Post.svelte
new file mode 100644
index 00000000..7e26dcb1
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Post/Post.svelte
@@ -0,0 +1,203 @@
+
+
+
+ {#if count}
+
+
+
+
goto(`/profile/${userId}`)}
+ >
+
+
{username}
+
+
+
+ {/if}
+ {#if imgUris.length > 0}
+
+ {#if imgUris.length > 1}
+
+ {/if}
+
+ {#if imgUris.length > 1}
+
+ {#if imgUris.length > 1}
+
+ {#each imgUris as _, i}
+
+ {/each}
+
+ {/if}
+
+ {/if}
+ {#if imgUris.length > 1}
+
+ {/if}
+
+ {/if}
+ {#if count}
+ {text}
+ {time}
+ {/if}
+
+ {#if count}
+
+
+
+
+ {/if}
+ {#if count}
+
+
{count?.likes} likes
+
+
{count?.comments} comments
+
+ {/if}
+
+
diff --git a/platforms/pictique/src/lib/fragments/Profile/Profile.svelte b/platforms/pictique/src/lib/fragments/Profile/Profile.svelte
new file mode 100644
index 00000000..661c9f71
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/Profile/Profile.svelte
@@ -0,0 +1,72 @@
+
+
+
+
+

+
+
{profileData.username}
+
{profileData.userBio}
+
+ {#if variant === 'other'}
+
+
+
+
+ {/if}
+
+
+
+
+
{profileData.totalPosts}
+
Posts
+
+
+
+
+
+
+ {#each profileData.posts.filter((e) => e.imgUris && e.imgUris.length > 0) as post}
+
+ {
+ try {
+ } catch (err) {}
+ },
+ comment: () => {
+ if (window.matchMedia('(max-width: 768px)').matches) {
+ } else {
+ }
+ },
+ menu: () => alert('menu')
+ }}
+ />
+
+ {/each}
+
+
diff --git a/platforms/pictique/src/lib/fragments/RightAside/RightAside.svelte b/platforms/pictique/src/lib/fragments/RightAside/RightAside.svelte
new file mode 100644
index 00000000..ed40f706
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/RightAside/RightAside.svelte
@@ -0,0 +1,22 @@
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/SettingsDeleteButton/SettingsDeleteButton.svelte b/platforms/pictique/src/lib/fragments/SettingsDeleteButton/SettingsDeleteButton.svelte
new file mode 100644
index 00000000..17ddffca
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsDeleteButton/SettingsDeleteButton.svelte
@@ -0,0 +1,27 @@
+
+
+
+
+
+ {@render children?.()}
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.snippet.svelte b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.snippet.svelte
new file mode 100644
index 00000000..e9b61065
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.snippet.svelte
@@ -0,0 +1,14 @@
+
+
+{#snippet ButtonText()}
+ Settings Button
+{/snippet}
+
+{#snippet ButtonIcon()}
+
+{/snippet}
diff --git a/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.ts b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.ts
new file mode 100644
index 00000000..ce182577
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.stories.ts
@@ -0,0 +1,42 @@
+import type { ComponentProps } from 'svelte';
+import { SettingsNavigationButton } from '..';
+import { ButtonIcon, ButtonText } from './SettingsNavigationButton.stories.snippet.svelte';
+
+export default {
+ title: 'UI/SettingsNavigationButton',
+ component: SettingsNavigationButton,
+ tags: ['autodocs'],
+ render: (args: {
+ Component: SettingsNavigationButton;
+ props: ComponentProps;
+ }) => ({
+ Component: SettingsNavigationButton,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {
+ children: ButtonText,
+ leadingIcon: ButtonIcon,
+ onclick: () => alert('clicked'),
+ hasTrailingIcon: true
+ }
+};
+export const ProfileSrc = {
+ args: {
+ children: ButtonText,
+ profileSrc: 'https://picsum.photos/200/300',
+ onclick: () => alert('clicked'),
+ hasTrailingIcon: true
+ }
+};
+
+export const Secondary = {
+ args: {
+ children: ButtonText,
+ leadingIcon: ButtonIcon,
+ onclick: () => alert('clicked'),
+ hasTrailingIcon: false
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.svelte b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.svelte
new file mode 100644
index 00000000..fda243ca
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsNavigationButton/SettingsNavigationButton.svelte
@@ -0,0 +1,53 @@
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/SettingsPage/SettingsPage.svelte b/platforms/pictique/src/lib/fragments/SettingsPage/SettingsPage.svelte
new file mode 100644
index 00000000..4697280f
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsPage/SettingsPage.svelte
@@ -0,0 +1,84 @@
+
+
+
+
goto(`/settings/account`)}
+ profileSrc="https://picsum.photos/200/300"
+ >
+ {#snippet children()}
+
+
{username}
+
{userEmail}
+
+ {/snippet}
+
+
+
+
+
Personalisation
+
+ goto(`/settings/notifications`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Notifications
+ {/snippet}
+
+
+
+
+
+
System
+
+ goto(`/settings/data-and-storage`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Data & Storage
+ {/snippet}
+
+
+
+ goto(`/settings/logout`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Logout
+ {/snippet}
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/SettingsToggleButton/SettingsToggleButton.svelte b/platforms/pictique/src/lib/fragments/SettingsToggleButton/SettingsToggleButton.svelte
new file mode 100644
index 00000000..582e6cc5
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SettingsToggleButton/SettingsToggleButton.svelte
@@ -0,0 +1,24 @@
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/SideBar/SideBar.stories.ts b/platforms/pictique/src/lib/fragments/SideBar/SideBar.stories.ts
new file mode 100644
index 00000000..428afba8
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SideBar/SideBar.stories.ts
@@ -0,0 +1,16 @@
+import type { ComponentProps } from 'svelte';
+import { SideBar } from '..';
+
+export default {
+ title: 'UI/SideBar',
+ component: SideBar,
+ tags: ['autodocs'],
+ render: (args: { Component: SideBar; props: ComponentProps }) => ({
+ Component: SideBar,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {}
+};
diff --git a/platforms/pictique/src/lib/fragments/SideBar/SideBar.svelte b/platforms/pictique/src/lib/fragments/SideBar/SideBar.svelte
new file mode 100644
index 00000000..51897fd9
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/SideBar/SideBar.svelte
@@ -0,0 +1,176 @@
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/UploadedPostView/UploadedPostView.stories.ts b/platforms/pictique/src/lib/fragments/UploadedPostView/UploadedPostView.stories.ts
new file mode 100644
index 00000000..34e024a1
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/UploadedPostView/UploadedPostView.stories.ts
@@ -0,0 +1,51 @@
+import type { ComponentProps } from 'svelte';
+import UploadedPostView from './UploadedPostView.svelte';
+
+export default {
+ title: 'UI/UploadedPostView',
+ component: UploadedPostView,
+ tags: ['autodocs'],
+ render: (args: {
+ Component: UploadedPostView;
+ props: ComponentProps;
+ }) => ({
+ Component: UploadedPostView,
+ props: args
+ })
+};
+
+let images = [
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ },
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ },
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ },
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ },
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ },
+ {
+ url: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ alt: 'Sample Image 1'
+ }
+];
+
+export const Primary = {
+ args: {
+ images: images,
+ callback: (i: number) => {
+ images = images.filter((_, index) => index !== i);
+ }
+ }
+};
diff --git a/platforms/metagram/src/lib/fragments/UploadedPostView/UploadedPostView.svelte b/platforms/pictique/src/lib/fragments/UploadedPostView/UploadedPostView.svelte
similarity index 100%
rename from platforms/metagram/src/lib/fragments/UploadedPostView/UploadedPostView.svelte
rename to platforms/pictique/src/lib/fragments/UploadedPostView/UploadedPostView.svelte
diff --git a/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.stories.ts b/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.stories.ts
new file mode 100644
index 00000000..44a8d000
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.stories.ts
@@ -0,0 +1,22 @@
+import type { ComponentProps } from 'svelte';
+import { UserRequest } from '..';
+
+export default {
+ title: 'UI/UserRequest',
+ component: UserRequest,
+ tags: ['autodocs'],
+ render: (args: { Component: UserRequest; props: ComponentProps }) => ({
+ Component: UserRequest,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {
+ userImgSrc: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ userName: 'luffythethird',
+ description:
+ 'I’ve always wished life came at me fast. Funny how that wish never came through',
+ handleFollow: () => alert('Adsad')
+ }
+};
diff --git a/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.svelte b/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.svelte
new file mode 100644
index 00000000..7e67fd6b
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/UserRequest/UserRequest.svelte
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
{userName}
+
{description}
+
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/fragments/index.ts b/platforms/pictique/src/lib/fragments/index.ts
new file mode 100644
index 00000000..abe4ed0e
--- /dev/null
+++ b/platforms/pictique/src/lib/fragments/index.ts
@@ -0,0 +1,19 @@
+export { default as Profile } from './Profile/Profile.svelte';
+export { default as Header } from './Header/Header.svelte';
+export { default as BottomNav } from './BottomNav/BottomNav.svelte';
+export { default as SettingsNavigationButton } from './SettingsNavigationButton/SettingsNavigationButton.svelte';
+export { default as MessageInput } from './MessageInput/MessageInput.svelte';
+export { default as InputFile } from './InputFile/InputFile.svelte';
+export { default as Drawer } from './Drawer/Drawer.svelte';
+export { default as Message } from './Message/Message.svelte';
+export { default as ActionMenu } from './ActionMenu/ActionMenu.svelte';
+export { default as Modal } from './Modal/Modal.svelte';
+export { default as SideBar } from './SideBar/SideBar.svelte';
+export { default as RightAside } from './RightAside/RightAside.svelte';
+export { default as SettingsToggleButton } from './SettingsToggleButton/SettingsToggleButton.svelte';
+export { default as Post } from './Post/Post.svelte';
+export { default as ChatMessage } from './ChatMessage/ChatMessage.svelte';
+export { default as Comment } from './Comment/Comment.svelte';
+export { default as SettingsDeleteButton } from './SettingsDeleteButton/SettingsDeleteButton.svelte';
+export { default as UserRequest } from './UserRequest/UserRequest.svelte';
+export { default as UploadedPostView } from './UploadedPostView/UploadedPostView.svelte';
diff --git a/platforms/pictique/src/lib/icons/Camera.svelte b/platforms/pictique/src/lib/icons/Camera.svelte
new file mode 100644
index 00000000..d793fb29
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Camera.svelte
@@ -0,0 +1,26 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/CommentIcon.svelte b/platforms/pictique/src/lib/icons/CommentIcon.svelte
new file mode 100644
index 00000000..f9e1301c
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/CommentIcon.svelte
@@ -0,0 +1,28 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/CommentsTwo.svelte b/platforms/pictique/src/lib/icons/CommentsTwo.svelte
new file mode 100644
index 00000000..8247b7ab
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/CommentsTwo.svelte
@@ -0,0 +1,28 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Cross.svelte b/platforms/pictique/src/lib/icons/Cross.svelte
new file mode 100644
index 00000000..13777e71
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Cross.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Flash.svelte b/platforms/pictique/src/lib/icons/Flash.svelte
new file mode 100644
index 00000000..47d415ce
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Flash.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Home.svelte b/platforms/pictique/src/lib/icons/Home.svelte
new file mode 100644
index 00000000..255e5bba
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Home.svelte
@@ -0,0 +1,30 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Icons.stories.ts b/platforms/pictique/src/lib/icons/Icons.stories.ts
new file mode 100644
index 00000000..0538c9ab
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Icons.stories.ts
@@ -0,0 +1,16 @@
+import Icons from './Icons.svelte';
+
+export default {
+ title: 'UI/Icons',
+ component: Icons,
+ tags: ['autodocs'],
+ decorators: [() => null],
+ render: (args: Record) => ({
+ Component: Icons,
+ props: args
+ })
+};
+
+export const Default = {
+ args: {}
+};
diff --git a/platforms/pictique/src/lib/icons/Icons.svelte b/platforms/pictique/src/lib/icons/Icons.svelte
new file mode 100644
index 00000000..d98ee94e
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Icons.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Like.svelte b/platforms/pictique/src/lib/icons/Like.svelte
new file mode 100644
index 00000000..9ec26816
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Like.svelte
@@ -0,0 +1,29 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Refresh.svelte b/platforms/pictique/src/lib/icons/Refresh.svelte
new file mode 100644
index 00000000..410e2f81
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Refresh.svelte
@@ -0,0 +1,22 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Search.svelte b/platforms/pictique/src/lib/icons/Search.svelte
new file mode 100644
index 00000000..f5cef932
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Search.svelte
@@ -0,0 +1,29 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/Settings.svelte b/platforms/pictique/src/lib/icons/Settings.svelte
new file mode 100644
index 00000000..daddf35d
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/Settings.svelte
@@ -0,0 +1,31 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/VerticalDots.svelte b/platforms/pictique/src/lib/icons/VerticalDots.svelte
new file mode 100644
index 00000000..a19cce6f
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/VerticalDots.svelte
@@ -0,0 +1,36 @@
+
+
+
diff --git a/platforms/pictique/src/lib/icons/index.ts b/platforms/pictique/src/lib/icons/index.ts
new file mode 100644
index 00000000..4e216554
--- /dev/null
+++ b/platforms/pictique/src/lib/icons/index.ts
@@ -0,0 +1,12 @@
+export { default as Icons } from './Icons.svelte';
+export { default as Like } from './Like.svelte';
+export { default as Refresh } from './Refresh.svelte';
+export { default as CommentIcon } from './CommentIcon.svelte';
+export { default as VerticalDots } from './VerticalDots.svelte';
+export { default as Home } from './Home.svelte';
+export { default as Flash } from './Flash.svelte';
+export { default as CommentsTwo } from './CommentsTwo.svelte';
+export { default as Search } from './Search.svelte';
+export { default as Camera } from './Camera.svelte';
+export { default as Settings } from './Settings.svelte';
+export { default as Cross } from './Cross.svelte';
diff --git a/platforms/pictique/src/lib/index.ts b/platforms/pictique/src/lib/index.ts
new file mode 100644
index 00000000..648b5d03
--- /dev/null
+++ b/platforms/pictique/src/lib/index.ts
@@ -0,0 +1,2 @@
+// place files you want to import through the `$lib` alias in this folder.
+export {};
diff --git a/platforms/metagram/src/lib/store/store.svelte.ts b/platforms/pictique/src/lib/store/store.svelte.ts
similarity index 100%
rename from platforms/metagram/src/lib/store/store.svelte.ts
rename to platforms/pictique/src/lib/store/store.svelte.ts
diff --git a/platforms/pictique/src/lib/stores/auth.ts b/platforms/pictique/src/lib/stores/auth.ts
new file mode 100644
index 00000000..0225c01d
--- /dev/null
+++ b/platforms/pictique/src/lib/stores/auth.ts
@@ -0,0 +1,24 @@
+import { writable } from 'svelte/store';
+import { apiClient, setAuthToken, removeAuthToken } from '$lib/utils/axios';
+
+export const isAuthenticated = writable(false);
+
+export const initializeAuth = () => {
+ const token = localStorage.getItem('pictique_auth_token');
+ if (token) {
+ apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
+ isAuthenticated.set(true);
+ }
+};
+
+export const login = (token: string) => {
+ setAuthToken(token);
+ apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
+ isAuthenticated.set(true);
+};
+
+export const logout = () => {
+ removeAuthToken();
+ delete apiClient.defaults.headers.common['Authorization'];
+ isAuthenticated.set(false);
+};
\ No newline at end of file
diff --git a/platforms/pictique/src/lib/stores/comments.ts b/platforms/pictique/src/lib/stores/comments.ts
new file mode 100644
index 00000000..36af8fe9
--- /dev/null
+++ b/platforms/pictique/src/lib/stores/comments.ts
@@ -0,0 +1,47 @@
+import { writable } from 'svelte/store';
+import { apiClient } from '$lib/utils/axios';
+
+export interface Comment {
+ id: string;
+ text: string;
+ createdAt: string;
+ author: {
+ id: string;
+ handle: string;
+ name: string;
+ avatarUrl: string;
+ };
+}
+
+export const comments = writable([]);
+export const isLoading = writable(false);
+export const error = writable(null);
+export const activePostId = writable();
+
+export const fetchComments = async (postId: string) => {
+ try {
+ isLoading.set(true);
+ error.set(null);
+ const response = await apiClient.get(`/api/posts/${postId}/comments`);
+ comments.set(response.data);
+ } catch (err) {
+ error.set(err instanceof Error ? err.message : 'Failed to fetch comments');
+ } finally {
+ isLoading.set(false);
+ }
+};
+
+export const createComment = async (postId: string, text: string) => {
+ try {
+ isLoading.set(true);
+ error.set(null);
+ const response = await apiClient.post('/api/comments', { postId, text });
+ await fetchComments(postId); // Refresh comments after creating
+ return response.data;
+ } catch (err) {
+ error.set(err instanceof Error ? err.message : 'Failed to create comment');
+ throw err;
+ } finally {
+ isLoading.set(false);
+ }
+};
diff --git a/platforms/pictique/src/lib/stores/posts.ts b/platforms/pictique/src/lib/stores/posts.ts
new file mode 100644
index 00000000..5743f76a
--- /dev/null
+++ b/platforms/pictique/src/lib/stores/posts.ts
@@ -0,0 +1,75 @@
+import { writable } from 'svelte/store';
+import { apiClient } from '$lib/utils/axios';
+
+export interface Post {
+ id: string;
+ text: string;
+ images: string[];
+ author: {
+ id: string;
+ handle: string;
+ name: string;
+ avatarUrl: string;
+ };
+ createdAt: string;
+ likedBy: string[];
+ comments: {
+ id: string;
+ text: string;
+ author: {
+ id: string;
+ handle: string;
+ name: string;
+ avatarUrl: string;
+ };
+ createdAt: string;
+ }[];
+}
+
+export const posts = writable([]);
+export const isLoading = writable(false);
+export const error = writable(null);
+export const isCreatePostModalOpen = writable(false);
+
+export const openCreatePostModal = () => isCreatePostModalOpen.set(true);
+export const closeCreatePostModal = () => isCreatePostModalOpen.set(false);
+
+export const fetchFeed = async (page = 1, limit = 10) => {
+ try {
+ isLoading.set(true);
+ error.set(null);
+ const response = await apiClient.get(`/api/posts/feed?page=${page}&limit=${limit}`);
+ posts.set(response.data);
+ } catch (err) {
+ error.set(err instanceof Error ? err.message : 'Failed to fetch feed');
+ } finally {
+ isLoading.set(false);
+ }
+};
+
+export const createPost = async (text: string, images: string[]) => {
+ try {
+ isLoading.set(true);
+ error.set(null);
+ const response = await apiClient.post('/api/posts', {
+ text,
+ images: images.map((img) => img)
+ });
+ await fetchFeed(1);
+ return response.data;
+ } catch (err) {
+ error.set(err instanceof Error ? err.message : 'Failed to create post');
+ throw err;
+ } finally {
+ isLoading.set(false);
+ }
+};
+
+export const toggleLike = async (postId: string) => {
+ try {
+ const response = await apiClient.post(`/api/posts/${postId}/like`);
+ return response.data;
+ } catch (err) {
+ throw new Error(err instanceof Error ? err.message : 'Failed to toggle like');
+ }
+};
diff --git a/platforms/pictique/src/lib/stores/users.ts b/platforms/pictique/src/lib/stores/users.ts
new file mode 100644
index 00000000..bad67bee
--- /dev/null
+++ b/platforms/pictique/src/lib/stores/users.ts
@@ -0,0 +1,44 @@
+import { writable } from 'svelte/store';
+import { apiClient } from '$lib/utils/axios';
+
+export interface User {
+ id: string;
+ handle: string;
+ name: string;
+ description: string;
+ avatarUrl: string;
+ isVerified: boolean;
+}
+
+export const searchResults = writable([]);
+export const isSearching = writable(false);
+export const searchError = writable(null);
+
+export const searchUsers = async (query: string) => {
+ if (!query.trim()) {
+ searchResults.set([]);
+ return;
+ }
+
+ try {
+ isSearching.set(true);
+ searchError.set(null);
+ const response = await apiClient.get(`/api/users/search?q=${encodeURIComponent(query)}`);
+ searchResults.set(response.data);
+ } catch (err) {
+ searchError.set(err instanceof Error ? err.message : 'Failed to search users');
+ searchResults.set([]);
+ } finally {
+ isSearching.set(false);
+ }
+};
+
+export const followUser = async (followingId: string) => {
+ try {
+ await apiClient.post('/api/users/follow', { followingId });
+ return true;
+ } catch (err) {
+ console.error('Failed to follow user:', err);
+ return false;
+ }
+};
\ No newline at end of file
diff --git a/platforms/metagram/src/lib/types.ts b/platforms/pictique/src/lib/types.ts
similarity index 100%
rename from platforms/metagram/src/lib/types.ts
rename to platforms/pictique/src/lib/types.ts
diff --git a/platforms/pictique/src/lib/ui/Avatar/Avatar.stories.ts b/platforms/pictique/src/lib/ui/Avatar/Avatar.stories.ts
new file mode 100644
index 00000000..81214f10
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Avatar/Avatar.stories.ts
@@ -0,0 +1,40 @@
+import type { ComponentProps } from 'svelte';
+import Avatar from './Avatar.svelte';
+
+export default {
+ title: 'UI/Avatar',
+ component: Avatar,
+ tags: ['autodocs'],
+ render: (args: { Component: Avatar; props: ComponentProps }) => ({
+ Component: Avatar,
+ props: args
+ })
+};
+
+export const Large = {
+ args: {
+ src: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ size: 'lg'
+ }
+};
+
+export const Medium = {
+ args: {
+ src: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ size: 'md'
+ }
+};
+
+export const Small = {
+ args: {
+ src: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ size: 'sm'
+ }
+};
+
+export const ExtraSmall = {
+ args: {
+ src: 'https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250',
+ size: 'xs'
+ }
+};
diff --git a/platforms/pictique/src/lib/ui/Avatar/Avatar.svelte b/platforms/pictique/src/lib/ui/Avatar/Avatar.svelte
new file mode 100644
index 00000000..768136ee
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Avatar/Avatar.svelte
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/ui/Button/Button.stories.snippet.svelte b/platforms/pictique/src/lib/ui/Button/Button.stories.snippet.svelte
new file mode 100644
index 00000000..6ccd33a3
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Button/Button.stories.snippet.svelte
@@ -0,0 +1,24 @@
+
+
+{#snippet ButtonText()}
+ Button
+{/snippet}
+
+{#snippet ButtonNavText()}
+ Nav Button
+{/snippet}
+
+{#snippet ButtonNavSettings()}
+
+
+{/snippet}
diff --git a/platforms/pictique/src/lib/ui/Button/Button.stories.ts b/platforms/pictique/src/lib/ui/Button/Button.stories.ts
new file mode 100644
index 00000000..c55b3cdb
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Button/Button.stories.ts
@@ -0,0 +1,42 @@
+import type { ComponentProps } from 'svelte';
+import { ButtonText } from './Button.stories.snippet.svelte';
+import Button from './Button.svelte';
+
+export default {
+ title: 'UI/Button',
+ component: Button,
+ tags: ['autodocs'],
+ render: (args: { Component: Button; props: ComponentProps }) => ({
+ Component: Button,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: { variant: 'primary', children: ButtonText }
+};
+
+export const Secondary = {
+ args: {
+ variant: 'secondary',
+ blockingClick: true,
+ children: ButtonText,
+ callback: async () => {
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ }
+ }
+};
+
+export const Loading = {
+ args: { isLoading: true, children: ButtonText }
+};
+
+export const BlockingClick = {
+ args: {
+ blockingClick: true,
+ children: ButtonText,
+ callback: async () => {
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ }
+ }
+};
diff --git a/platforms/pictique/src/lib/ui/Button/Button.svelte b/platforms/pictique/src/lib/ui/Button/Button.svelte
new file mode 100644
index 00000000..3c9658aa
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Button/Button.svelte
@@ -0,0 +1,152 @@
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/ui/Helper/Helper.stories.snippet.svelte b/platforms/pictique/src/lib/ui/Helper/Helper.stories.snippet.svelte
new file mode 100644
index 00000000..daf231bf
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Helper/Helper.stories.snippet.svelte
@@ -0,0 +1,7 @@
+
+
+{#snippet HelperText()}
+ this is label
+{/snippet}
diff --git a/platforms/pictique/src/lib/ui/Helper/Helper.stories.ts b/platforms/pictique/src/lib/ui/Helper/Helper.stories.ts
new file mode 100644
index 00000000..bb4c91fe
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Helper/Helper.stories.ts
@@ -0,0 +1,17 @@
+import type { ComponentProps } from 'svelte';
+import Helper from './Helper.svelte';
+import { HelperText } from './Helper.stories.snippet.svelte';
+
+export default {
+ title: 'UI/Helper',
+ component: Helper,
+ tags: ['autodocs'],
+ render: (args: { Component: Helper; props: ComponentProps }) => ({
+ Component: Helper,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: { children: HelperText }
+};
diff --git a/platforms/pictique/src/lib/ui/Helper/Helper.svelte b/platforms/pictique/src/lib/ui/Helper/Helper.svelte
new file mode 100644
index 00000000..6719ad51
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Helper/Helper.svelte
@@ -0,0 +1,17 @@
+
+
+
+ {@render children?.()}
+
diff --git a/platforms/metagram/src/lib/ui/Input/Input.stories.ts b/platforms/pictique/src/lib/ui/Input/Input.stories.ts
similarity index 100%
rename from platforms/metagram/src/lib/ui/Input/Input.stories.ts
rename to platforms/pictique/src/lib/ui/Input/Input.stories.ts
diff --git a/platforms/metagram/src/lib/ui/Input/Input.svelte b/platforms/pictique/src/lib/ui/Input/Input.svelte
similarity index 100%
rename from platforms/metagram/src/lib/ui/Input/Input.svelte
rename to platforms/pictique/src/lib/ui/Input/Input.svelte
diff --git a/platforms/pictique/src/lib/ui/Label/Label.stories.snippet.svelte b/platforms/pictique/src/lib/ui/Label/Label.stories.snippet.svelte
new file mode 100644
index 00000000..4066b5be
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Label/Label.stories.snippet.svelte
@@ -0,0 +1,7 @@
+
+
+{#snippet LabelText()}
+ this is label
+{/snippet}
diff --git a/platforms/pictique/src/lib/ui/Label/Label.stories.ts b/platforms/pictique/src/lib/ui/Label/Label.stories.ts
new file mode 100644
index 00000000..69d4f7e0
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Label/Label.stories.ts
@@ -0,0 +1,17 @@
+import type { ComponentProps } from 'svelte';
+import { Label } from '..';
+import { LabelText } from './Label.stories.snippet.svelte';
+
+export default {
+ title: 'UI/Label',
+ component: Label,
+ tags: ['autodocs'],
+ render: (args: { Component: Label; props: ComponentProps }) => ({
+ Component: Label,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: { children: LabelText }
+};
diff --git a/platforms/pictique/src/lib/ui/Label/Label.svelte b/platforms/pictique/src/lib/ui/Label/Label.svelte
new file mode 100644
index 00000000..3be3ade7
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Label/Label.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/platforms/pictique/src/lib/ui/Modal/Modal.svelte b/platforms/pictique/src/lib/ui/Modal/Modal.svelte
new file mode 100644
index 00000000..abce30a8
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Modal/Modal.svelte
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/ui/Qr/Qr.svelte b/platforms/pictique/src/lib/ui/Qr/Qr.svelte
new file mode 100644
index 00000000..b1555443
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Qr/Qr.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/platforms/pictique/src/lib/ui/Select/Select.stories.ts b/platforms/pictique/src/lib/ui/Select/Select.stories.ts
new file mode 100644
index 00000000..ddd68e6e
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Select/Select.stories.ts
@@ -0,0 +1,16 @@
+import type { ComponentProps } from 'svelte';
+import { Select } from '..';
+
+export default {
+ title: 'UI/Select',
+ component: Select,
+ tags: ['autodocs'],
+ render: (args: { Component: Select; props: ComponentProps }) => ({
+ Component: Select,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {}
+};
diff --git a/platforms/pictique/src/lib/ui/Select/Select.svelte b/platforms/pictique/src/lib/ui/Select/Select.svelte
new file mode 100644
index 00000000..007a4e0a
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Select/Select.svelte
@@ -0,0 +1,39 @@
+
+
+
+
{options.find((c) => c.code === selectedCode)?.icon}
+
+
diff --git a/platforms/pictique/src/lib/ui/Toggle/Toggle.stories.ts b/platforms/pictique/src/lib/ui/Toggle/Toggle.stories.ts
new file mode 100644
index 00000000..d814315a
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Toggle/Toggle.stories.ts
@@ -0,0 +1,16 @@
+import type { ComponentProps } from 'svelte';
+import Toggle from './Toggle.svelte';
+
+export default {
+ title: 'UI/Toggle',
+ component: Toggle,
+ tags: ['autodocs'],
+ render: (args: { Component: Toggle; props: ComponentProps }) => ({
+ Component: Toggle,
+ props: args
+ })
+};
+
+export const Primary = {
+ args: {}
+};
diff --git a/platforms/pictique/src/lib/ui/Toggle/Toggle.svelte b/platforms/pictique/src/lib/ui/Toggle/Toggle.svelte
new file mode 100644
index 00000000..76b656da
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/Toggle/Toggle.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
diff --git a/platforms/pictique/src/lib/ui/index.ts b/platforms/pictique/src/lib/ui/index.ts
new file mode 100644
index 00000000..52f1d457
--- /dev/null
+++ b/platforms/pictique/src/lib/ui/index.ts
@@ -0,0 +1,8 @@
+export { default as Button } from './Button/Button.svelte';
+export { default as Avatar } from './Avatar/Avatar.svelte';
+export { default as Input } from './Input/Input.svelte';
+export { default as Select } from './Select/Select.svelte';
+export { default as Label } from './Label/Label.svelte';
+export { default as Toggle } from './Toggle/Toggle.svelte';
+export { default as Helper } from './Helper/Helper.svelte';
+export { default as Qr } from './Qr/Qr.svelte';
diff --git a/platforms/pictique/src/lib/utils/axios.ts b/platforms/pictique/src/lib/utils/axios.ts
new file mode 100644
index 00000000..9c1585d8
--- /dev/null
+++ b/platforms/pictique/src/lib/utils/axios.ts
@@ -0,0 +1,27 @@
+import axios, { type AxiosInstance } from 'axios';
+import { PUBLIC_PICTIQUE_BASE_URL } from '$env/static/public';
+
+const TOKEN_KEY = 'pictique_auth_token';
+
+// Create axios instance with base configuration
+export const apiClient: AxiosInstance = axios.create({
+ baseURL: PUBLIC_PICTIQUE_BASE_URL,
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${localStorage.getItem(TOKEN_KEY)}`
+ }
+});
+
+// Utility function to store auth token
+export const setAuthToken = (token: string): void => {
+ localStorage.setItem(TOKEN_KEY, token);
+};
+
+export const getAuthToken = () => {
+ return localStorage.getItem(TOKEN_KEY);
+};
+
+// Utility function to remove auth token
+export const removeAuthToken = (): void => {
+ localStorage.removeItem(TOKEN_KEY);
+};
diff --git a/platforms/pictique/src/lib/utils/clickOutside.ts b/platforms/pictique/src/lib/utils/clickOutside.ts
new file mode 100644
index 00000000..74ad1c69
--- /dev/null
+++ b/platforms/pictique/src/lib/utils/clickOutside.ts
@@ -0,0 +1,17 @@
+/** Dispatch event on click outside of node */
+export const clickOutside = (node: HTMLElement, callback: () => void) => {
+ const handleClick = (event: Event) => {
+ if (node && !node.contains(event.target as Node) && !event.defaultPrevented) {
+ callback(); // Call the provided callback
+ node.dispatchEvent(new CustomEvent('click_outside'));
+ }
+ };
+
+ document.addEventListener('click', handleClick, true);
+
+ return {
+ destroy() {
+ document.removeEventListener('click', handleClick, true);
+ }
+ };
+};
diff --git a/platforms/pictique/src/lib/utils/index.ts b/platforms/pictique/src/lib/utils/index.ts
new file mode 100644
index 00000000..2a7af005
--- /dev/null
+++ b/platforms/pictique/src/lib/utils/index.ts
@@ -0,0 +1,4 @@
+export * from './mergeClasses';
+export * from './clickOutside';
+export * from './axios';
+export * from './memoryHelper';
diff --git a/platforms/metagram/src/lib/utils/memoryHelper.ts b/platforms/pictique/src/lib/utils/memoryHelper.ts
similarity index 75%
rename from platforms/metagram/src/lib/utils/memoryHelper.ts
rename to platforms/pictique/src/lib/utils/memoryHelper.ts
index 28d648a4..c9cff633 100644
--- a/platforms/metagram/src/lib/utils/memoryHelper.ts
+++ b/platforms/pictique/src/lib/utils/memoryHelper.ts
@@ -1,4 +1,4 @@
-import type { Image } from "$lib/types";
+import type { Image } from '$lib/types';
export const revokeImageUrls = (imageArray: Image[]) => {
imageArray?.forEach((img) => URL.revokeObjectURL(img.url));
diff --git a/platforms/pictique/src/lib/utils/mergeClasses.ts b/platforms/pictique/src/lib/utils/mergeClasses.ts
new file mode 100644
index 00000000..256f86ff
--- /dev/null
+++ b/platforms/pictique/src/lib/utils/mergeClasses.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/platforms/pictique/src/routes/(auth)/auth/+page.svelte b/platforms/pictique/src/routes/(auth)/auth/+page.svelte
new file mode 100644
index 00000000..5d7c49f6
--- /dev/null
+++ b/platforms/pictique/src/routes/(auth)/auth/+page.svelte
@@ -0,0 +1,48 @@
+
+
+
+
+

+
+
+
+
Scan the QR to Login
+
+
diff --git a/platforms/pictique/src/routes/(protected)/+layout.svelte b/platforms/pictique/src/routes/(protected)/+layout.svelte
new file mode 100644
index 00000000..06ecf5ba
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/+layout.svelte
@@ -0,0 +1,157 @@
+
+
+
+ {
+ openCreatePostModal();
+ }}
+ />
+
+ {#if route === '/home' || route === '/messages'}
+
+ {/if}
+
+ {#if route !== `/messages/${idFromParams}`}
+
+ {/if}
+
+
+{#if $isCreatePostModalOpen}
+
+{/if}
diff --git a/platforms/pictique/src/routes/(protected)/discover/+page.svelte b/platforms/pictique/src/routes/(protected)/discover/+page.svelte
new file mode 100644
index 00000000..b95f5748
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/discover/+page.svelte
@@ -0,0 +1,73 @@
+
+
+
+ handleSearch((e.target as HTMLInputElement).value)}
+ />
+
+ {#if $isSearching}
+ Searching...
+ {:else if $searchError}
+ {$searchError}
+ {:else if searchValue && $searchResults.length === 0}
+ No users found
+ {:else if searchValue}
+
+ {#each $searchResults as user}
+ -
+ handleFollow(user.id)}
+ onclick={() => handleProfileClick(user.id)}
+ />
+
+ {/each}
+
+ {/if}
+
diff --git a/platforms/metagram/src/routes/(protected)/home/+page.svelte b/platforms/pictique/src/routes/(protected)/home/+page.svelte
similarity index 58%
rename from platforms/metagram/src/routes/(protected)/home/+page.svelte
rename to platforms/pictique/src/routes/(protected)/home/+page.svelte
index 0a94f524..3e33b5e1 100644
--- a/platforms/metagram/src/routes/(protected)/home/+page.svelte
+++ b/platforms/pictique/src/routes/(protected)/home/+page.svelte
@@ -1,41 +1,24 @@
-
-
-{#if loading}
- Loading more posts…
-{/if}
+
- {comments.length} Comments
+ {_comments.length} Comments
{#each _comments as comment}
-
+ import { goto } from '$app/navigation';
+ import { Message } from '$lib/fragments';
+ import { onMount } from 'svelte';
+ import { apiClient } from '$lib/utils/axios';
+
+ let messages = $state([]);
+
+ onMount(async () => {
+ const { data } = await apiClient.get('/api/chats');
+ const { data: userData } = await apiClient.get('/api/users');
+ messages = data.chats.map((c) => {
+ const members = c.participants.filter((u) => u.id !== userData.id);
+ console.log(members);
+ const memberNames = members.map((m) => m.name ?? m.handle ?? m.ename);
+ const avatar = members.length > 1 ? '/images/group.png' : members[0].avatarUrl;
+ return {
+ id: c.id,
+ avatar,
+ username: memberNames.join(', '),
+ unread: c.latestMessage.isRead,
+ text: c.latestMessage.text
+ };
+ });
+ });
+
+
+
+ {#each messages as message}
+ goto(`/messages/${message.id}`)}
+ />
+ {/each}
+
diff --git a/platforms/pictique/src/routes/(protected)/messages/[id]/+page.svelte b/platforms/pictique/src/routes/(protected)/messages/[id]/+page.svelte
new file mode 100644
index 00000000..e1ee2d8e
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/messages/[id]/+page.svelte
@@ -0,0 +1,94 @@
+
+
+
+
+ {#each messages as msg (msg.id)}
+
+ {/each}
+
+
+
diff --git a/platforms/pictique/src/routes/(protected)/post/+page.svelte b/platforms/pictique/src/routes/(protected)/post/+page.svelte
new file mode 100644
index 00000000..e69de29b
diff --git a/platforms/pictique/src/routes/(protected)/profile/+page.svelte b/platforms/pictique/src/routes/(protected)/profile/+page.svelte
new file mode 100644
index 00000000..0fbba997
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/profile/+page.svelte
@@ -0,0 +1,2 @@
+
diff --git a/platforms/pictique/src/routes/(protected)/profile/[id]/+page.svelte b/platforms/pictique/src/routes/(protected)/profile/[id]/+page.svelte
new file mode 100644
index 00000000..2aeea589
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/profile/[id]/+page.svelte
@@ -0,0 +1,104 @@
+
+
+
+ {#if loading}
+
+ {:else if error}
+
+ {:else if profile}
+ handlePostClick(post)}
+ {handleFollow}
+ {handleMessage}
+ />
+
+ {#if profile}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/if}
+ {/if}
+
diff --git a/platforms/pictique/src/routes/(protected)/settings/+layout.svelte b/platforms/pictique/src/routes/(protected)/settings/+layout.svelte
new file mode 100644
index 00000000..2f3999fb
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/+layout.svelte
@@ -0,0 +1,7 @@
+
+
+
+ {@render children()}
+
diff --git a/platforms/pictique/src/routes/(protected)/settings/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/+page.svelte
new file mode 100644
index 00000000..70433ebb
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/+page.svelte
@@ -0,0 +1,74 @@
+
+
+
+
goto(`/settings/account`)} profileSrc={userImage}>
+ {#snippet children()}
+
+
{username}
+
{userEmail}
+
+ {/snippet}
+
+
+
+
+
Personalisation
+
+ goto(`/settings/notifications`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Notifications
+ {/snippet}
+
+
+
+ goto(`/settings/data-and-storage`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Data & Storage
+ {/snippet}
+
+
+
+
+ goto(`/settings/logout`)}>
+ {#snippet leadingIcon()}
+
+ {/snippet}
+ {#snippet children()}
+ Logout
+ {/snippet}
+
+
+
diff --git a/platforms/pictique/src/routes/(protected)/settings/account/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/account/+page.svelte
new file mode 100644
index 00000000..40e62177
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/account/+page.svelte
@@ -0,0 +1,8 @@
+
diff --git a/platforms/pictique/src/routes/(protected)/settings/account/username/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/account/username/+page.svelte
new file mode 100644
index 00000000..429ee12e
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/account/username/+page.svelte
@@ -0,0 +1,73 @@
+
+
+
+
+
+
{
+ profileImageDataUrl = '';
+ files = undefined;
+ }}
+ />
+ {#if profileImageDataUrl}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platforms/pictique/src/routes/(protected)/settings/data-and-storage/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/data-and-storage/+page.svelte
new file mode 100644
index 00000000..27c9c9e4
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/data-and-storage/+page.svelte
@@ -0,0 +1,12 @@
+
+
+
+
+ {#snippet children()}
+ Merul will add things here (as per out discussion)
+ {/snippet}
+
+
+
diff --git a/platforms/metagram/src/routes/(protected)/settings/account/deactivate/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/logout/+page.svelte
similarity index 65%
rename from platforms/metagram/src/routes/(protected)/settings/account/deactivate/+page.svelte
rename to platforms/pictique/src/routes/(protected)/settings/logout/+page.svelte
index 67214d5b..d1fca886 100644
--- a/platforms/metagram/src/routes/(protected)/settings/account/deactivate/+page.svelte
+++ b/platforms/pictique/src/routes/(protected)/settings/logout/+page.svelte
@@ -1,15 +1,17 @@
-
-
+ goto(`/settings/data-and-storage`)}
+ >
{#snippet children()}
-
- Are you sure you want to deactivate this account?
-
+
Do you want to log out?
You can log back in anytime
{/snippet}
diff --git a/platforms/pictique/src/routes/(protected)/settings/notifications/+page.svelte b/platforms/pictique/src/routes/(protected)/settings/notifications/+page.svelte
new file mode 100644
index 00000000..fe6abb9e
--- /dev/null
+++ b/platforms/pictique/src/routes/(protected)/settings/notifications/+page.svelte
@@ -0,0 +1,39 @@
+
+
+
+
+ {#snippet children()}
+
+
Push Notifications
+
+ {/snippet}
+
+
+
+ {#snippet children()}
+
+
Post Interactions
+
Likes and comments on your post
+
+ {/snippet}
+
+
+
+ {#snippet children()}
+
+
DM Requests
+
+ {/snippet}
+
+
+
+ {#snippet children()}
+
+
New Followers
+
+ {/snippet}
+
+
+
diff --git a/platforms/metagram/src/routes/+layout.svelte b/platforms/pictique/src/routes/+layout.svelte
similarity index 100%
rename from platforms/metagram/src/routes/+layout.svelte
rename to platforms/pictique/src/routes/+layout.svelte
diff --git a/platforms/pictique/src/routes/+layout.ts b/platforms/pictique/src/routes/+layout.ts
new file mode 100644
index 00000000..ceccaaf6
--- /dev/null
+++ b/platforms/pictique/src/routes/+layout.ts
@@ -0,0 +1,2 @@
+export const prerender = true;
+export const ssr = false;
diff --git a/platforms/pictique/src/routes/+page.svelte b/platforms/pictique/src/routes/+page.svelte
new file mode 100644
index 00000000..ab9f5e28
--- /dev/null
+++ b/platforms/pictique/src/routes/+page.svelte
@@ -0,0 +1,7 @@
+
diff --git a/platforms/pictique/static/favicon.png b/platforms/pictique/static/favicon.png
new file mode 100644
index 00000000..825b9e65
Binary files /dev/null and b/platforms/pictique/static/favicon.png differ
diff --git a/platforms/pictique/static/fonts/Geist-VariableFont_wght.ttf b/platforms/pictique/static/fonts/Geist-VariableFont_wght.ttf
new file mode 100644
index 00000000..ad6f2c5a
Binary files /dev/null and b/platforms/pictique/static/fonts/Geist-VariableFont_wght.ttf differ
diff --git a/platforms/metagram/static/images/Logo.svg b/platforms/pictique/static/images/Logo.svg
similarity index 100%
rename from platforms/metagram/static/images/Logo.svg
rename to platforms/pictique/static/images/Logo.svg
diff --git a/platforms/pictique/svelte.config.js b/platforms/pictique/svelte.config.js
new file mode 100644
index 00000000..27ddeeee
--- /dev/null
+++ b/platforms/pictique/svelte.config.js
@@ -0,0 +1,14 @@
+import adapter from '@sveltejs/adapter-static';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+const config = {
+ preprocess: vitePreprocess(),
+ kit: {
+ adapter: adapter(),
+ env: {
+ dir: '../../'
+ }
+ }
+};
+
+export default config;
diff --git a/platforms/pictique/tsconfig.json b/platforms/pictique/tsconfig.json
new file mode 100644
index 00000000..0b2d8865
--- /dev/null
+++ b/platforms/pictique/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/platforms/pictique/vite.config.ts b/platforms/pictique/vite.config.ts
new file mode 100644
index 00000000..2d35c4f5
--- /dev/null
+++ b/platforms/pictique/vite.config.ts
@@ -0,0 +1,7 @@
+import tailwindcss from '@tailwindcss/vite';
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [tailwindcss(), sveltekit()]
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6bd9cdb4..dcfa528e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -350,7 +350,7 @@ importers:
version: 3.3.0
vitest:
specifier: ^3.1.2
- version: 3.1.4(@types/node@20.17.50)(@vitest/browser@3.1.4)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
+ version: 3.1.4(@types/node@22.15.21)(@vitest/browser@3.1.4)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
devDependencies:
'@types/jest':
specifier: ^29.5.0
@@ -366,10 +366,10 @@ importers:
version: 8.57.1
jest:
specifier: ^29.5.0
- version: 29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3))
+ version: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
ts-jest:
specifier: ^29.1.0
- version: 29.3.4(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3)))(typescript@5.8.3)
+ version: 29.3.4(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0))(typescript@5.8.3)
typescript:
specifier: ^5.0.4
version: 5.8.3
@@ -412,7 +412,7 @@ importers:
packages/typescript-config: {}
- platforms/metagram:
+ platforms/blabsy:
dependencies:
'-':
specifier: ^0.0.1
@@ -420,6 +420,12 @@ importers:
D:
specifier: ^1.0.0
version: 1.0.0
+ axios:
+ specifier: ^1.6.7
+ version: 1.9.0
+ svelte-qrcode:
+ specifier: ^1.0.1
+ version: 1.0.1
tailwind-merge:
specifier: ^3.0.2
version: 3.3.0
@@ -521,6 +527,194 @@ importers:
specifier: ^6.2.6
version: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
+ platforms/pictique:
+ dependencies:
+ '-':
+ specifier: ^0.0.1
+ version: 0.0.1
+ D:
+ specifier: ^1.0.0
+ version: 1.0.0
+ axios:
+ specifier: ^1.6.7
+ version: 1.9.0
+ moment:
+ specifier: ^2.30.1
+ version: 2.30.1
+ svelte-qrcode:
+ specifier: ^1.0.1
+ version: 1.0.1
+ tailwind-merge:
+ specifier: ^3.0.2
+ version: 3.3.0
+ devDependencies:
+ '@chromatic-com/storybook':
+ specifier: ^3
+ version: 3.2.6(react@19.1.0)(storybook@8.6.14(prettier@3.5.3))
+ '@eslint/compat':
+ specifier: ^1.2.5
+ version: 1.2.9(eslint@9.27.0(jiti@2.4.2))
+ '@eslint/js':
+ specifier: ^9.18.0
+ version: 9.27.0
+ '@hugeicons/core-free-icons':
+ specifier: ^1.0.13
+ version: 1.0.14
+ '@hugeicons/svelte':
+ specifier: ^1.0.2
+ version: 1.0.2(svelte@5.33.1)
+ '@storybook/addon-essentials':
+ specifier: ^8.6.12
+ version: 8.6.14(@types/react@19.1.5)(storybook@8.6.14(prettier@3.5.3))
+ '@storybook/addon-svelte-csf':
+ specifier: ^5.0.0-next.0
+ version: 5.0.1(@storybook/svelte@8.6.14(storybook@8.6.14(prettier@3.5.3))(svelte@5.33.1))(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)))(babel-plugin-macros@3.1.0)(storybook@8.6.14(prettier@3.5.3))(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
+ '@storybook/blocks':
+ specifier: ^8.6.12
+ version: 8.6.14(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@8.6.14(prettier@3.5.3))
+ '@storybook/svelte':
+ specifier: ^8.6.12
+ version: 8.6.14(storybook@8.6.14(prettier@3.5.3))(svelte@5.33.1)
+ '@storybook/sveltekit':
+ specifier: ^8.6.12
+ version: 8.6.14(@babel/core@7.27.1)(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)))(postcss-load-config@3.1.4(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)))(postcss@8.5.3)(storybook@8.6.14(prettier@3.5.3))(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
+ '@storybook/test':
+ specifier: ^8.6.12
+ version: 8.6.14(storybook@8.6.14(prettier@3.5.3))
+ '@sveltejs/adapter-static':
+ specifier: ^3.0.8
+ version: 3.0.8(@sveltejs/kit@2.21.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)))(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)))
+ '@sveltejs/kit':
+ specifier: ^2.16.0
+ version: 2.21.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)))(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
+ '@sveltejs/vite-plugin-svelte':
+ specifier: ^5.0.0
+ version: 5.0.3(svelte@5.33.1)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
+ '@tailwindcss/vite':
+ specifier: ^4.0.0
+ version: 4.1.7(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ cupertino-pane:
+ specifier: ^1.4.22
+ version: 1.4.22
+ eslint:
+ specifier: ^9.18.0
+ version: 9.27.0(jiti@2.4.2)
+ eslint-config-prettier:
+ specifier: ^10.0.1
+ version: 10.1.5(eslint@9.27.0(jiti@2.4.2))
+ eslint-plugin-svelte:
+ specifier: ^3.0.0
+ version: 3.9.0(eslint@9.27.0(jiti@2.4.2))(svelte@5.33.1)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ globals:
+ specifier: ^16.0.0
+ version: 16.1.0
+ prettier:
+ specifier: ^3.4.2
+ version: 3.5.3
+ prettier-plugin-svelte:
+ specifier: ^3.3.3
+ version: 3.4.0(prettier@3.5.3)(svelte@5.33.1)
+ prettier-plugin-tailwindcss:
+ specifier: ^0.6.11
+ version: 0.6.11(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.33.1))(prettier@3.5.3)
+ storybook:
+ specifier: ^8.6.12
+ version: 8.6.14(prettier@3.5.3)
+ svelte:
+ specifier: ^5.0.0
+ version: 5.33.1
+ svelte-check:
+ specifier: ^4.0.0
+ version: 4.2.1(picomatch@4.0.2)(svelte@5.33.1)(typescript@5.8.3)
+ svelte-gestures:
+ specifier: ^5.1.3
+ version: 5.1.4
+ tailwindcss:
+ specifier: ^4.0.0
+ version: 4.1.7
+ typescript:
+ specifier: ^5.0.0
+ version: 5.8.3
+ typescript-eslint:
+ specifier: ^8.20.0
+ version: 8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
+ vite:
+ specifier: ^6.2.6
+ version: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
+
+ platforms/piqtique-api:
+ dependencies:
+ axios:
+ specifier: ^1.6.7
+ version: 1.9.0
+ cors:
+ specifier: ^2.8.5
+ version: 2.8.5
+ dotenv:
+ specifier: ^16.4.5
+ version: 16.5.0
+ eventsource-polyfill:
+ specifier: ^0.9.6
+ version: 0.9.6
+ express:
+ specifier: ^4.18.2
+ version: 4.21.2
+ jsonwebtoken:
+ specifier: ^9.0.2
+ version: 9.0.2
+ pg:
+ specifier: ^8.11.3
+ version: 8.16.0
+ reflect-metadata:
+ specifier: ^0.2.1
+ version: 0.2.2
+ typeorm:
+ specifier: ^0.3.20
+ version: 0.3.24(babel-plugin-macros@3.1.0)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3))
+ uuid:
+ specifier: ^9.0.1
+ version: 9.0.1
+ devDependencies:
+ '@types/cors':
+ specifier: ^2.8.17
+ version: 2.8.18
+ '@types/express':
+ specifier: ^4.17.21
+ version: 4.17.22
+ '@types/jsonwebtoken':
+ specifier: ^9.0.5
+ version: 9.0.9
+ '@types/node':
+ specifier: ^20.11.24
+ version: 20.17.50
+ '@types/pg':
+ specifier: ^8.11.2
+ version: 8.15.4
+ '@types/uuid':
+ specifier: ^9.0.8
+ version: 9.0.8
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^7.0.1
+ version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)
+ '@typescript-eslint/parser':
+ specifier: ^7.0.1
+ version: 7.18.0(eslint@8.57.1)(typescript@5.8.3)
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ nodemon:
+ specifier: ^3.0.3
+ version: 3.1.10
+ ts-node:
+ specifier: ^10.9.2
+ version: 10.9.2(@types/node@20.17.50)(typescript@5.8.3)
+ typescript:
+ specifier: ^5.3.3
+ version: 5.8.3
+
platforms/registry:
dependencies:
'@fastify/cors':
@@ -2339,12 +2533,18 @@ packages:
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+ '@types/jsonwebtoken@9.0.9':
+ resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==}
+
'@types/mdx@2.0.13':
resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
'@types/mime@1.3.5':
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/node-fetch@2.6.12':
resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==}
@@ -2436,6 +2636,17 @@ packages:
typescript:
optional: true
+ '@typescript-eslint/eslint-plugin@7.18.0':
+ resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^7.0.0
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@typescript-eslint/eslint-plugin@8.32.1':
resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2454,6 +2665,16 @@ packages:
typescript:
optional: true
+ '@typescript-eslint/parser@7.18.0':
+ resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@typescript-eslint/parser@8.32.1':
resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2465,6 +2686,10 @@ packages:
resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@typescript-eslint/scope-manager@7.18.0':
+ resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
'@typescript-eslint/scope-manager@8.32.1':
resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2479,6 +2704,16 @@ packages:
typescript:
optional: true
+ '@typescript-eslint/type-utils@7.18.0':
+ resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@typescript-eslint/type-utils@8.32.1':
resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2490,6 +2725,10 @@ packages:
resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@typescript-eslint/types@7.18.0':
+ resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
'@typescript-eslint/types@8.32.1':
resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2503,6 +2742,15 @@ packages:
typescript:
optional: true
+ '@typescript-eslint/typescript-estree@7.18.0':
+ resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@typescript-eslint/typescript-estree@8.32.1':
resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2515,6 +2763,12 @@ packages:
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ '@typescript-eslint/utils@7.18.0':
+ resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+
'@typescript-eslint/utils@8.32.1':
resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2526,6 +2780,10 @@ packages:
resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@typescript-eslint/visitor-keys@7.18.0':
+ resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
'@typescript-eslint/visitor-keys@8.32.1':
resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2980,6 +3238,9 @@ packages:
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
engines: {node: '>=8.0.0'}
+ buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -3692,6 +3953,9 @@ packages:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
+ eventsource-polyfill@0.9.6:
+ resolution: {integrity: sha512-LyMFp2oPDGhum2lMvkjqKZEwWd2/AoXyt8aoyftTBMWwPHNgU+2tdxhTHPluDxoz+z4gNj0uHAPR9nqevATMbg==}
+
execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
@@ -4544,10 +4808,20 @@ packages:
engines: {node: '>=18.0.0'}
hasBin: true
+ jsonwebtoken@9.0.2:
+ resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
+ engines: {node: '>=12', npm: '>=6'}
+
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
+ jwa@1.4.2:
+ resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==}
+
+ jws@3.2.2:
+ resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -4669,15 +4943,33 @@ packages:
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
+ lodash.includes@4.3.0:
+ resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+
+ lodash.isboolean@3.0.3:
+ resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+
+ lodash.isinteger@4.0.4:
+ resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+
+ lodash.isnumber@3.0.3:
+ resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+ lodash.isstring@4.0.1:
+ resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+
lodash.memoize@4.1.2:
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ lodash.once@4.1.1:
+ resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
@@ -4843,6 +5135,9 @@ packages:
mnemonist@0.39.8:
resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==}
+ moment@2.30.1:
+ resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -5361,6 +5656,9 @@ packages:
pure-rand@6.1.0:
resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+ qrious@4.0.2:
+ resolution: {integrity: sha512-xWPJIrK1zu5Ypn898fBp8RHkT/9ibquV2Kv24S/JY9VYEhMBMKur1gHVsOiNUh7PHP9uCgejjpZUHUIXXKoU/g==}
+
qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
@@ -5934,6 +6232,9 @@ packages:
typescript:
optional: true
+ svelte-qrcode@1.0.1:
+ resolution: {integrity: sha512-l1RcxDWkQqtBWUkolYee/IHGVKSgm1I2PdF8yVoIRqzKCc3kXpCXSVsMfrMSavWW2/BXvKu5Orv+JGbrO5onsw==}
+
svelte2tsx@0.7.39:
resolution: {integrity: sha512-NX8a7eSqF1hr6WKArvXr7TV7DeE+y0kDFD7L5JP7TWqlwFidzGKaG415p992MHREiiEWOv2xIWXJ+mlONofs0A==}
peerDependencies:
@@ -6073,6 +6374,12 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
+ ts-api-utils@1.4.3:
+ resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ typescript: '>=4.2.0'
+
ts-api-utils@2.1.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
engines: {node: '>=18.12'}
@@ -8640,10 +8947,17 @@ snapshots:
'@types/json-schema@7.0.15': {}
+ '@types/jsonwebtoken@9.0.9':
+ dependencies:
+ '@types/ms': 2.1.0
+ '@types/node': 20.17.50
+
'@types/mdx@2.0.13': {}
'@types/mime@1.3.5': {}
+ '@types/ms@2.1.0': {}
+
'@types/node-fetch@2.6.12':
dependencies:
'@types/node': 20.17.50
@@ -8665,7 +8979,7 @@ snapshots:
'@types/pg@8.15.4':
dependencies:
- '@types/node': 22.15.21
+ '@types/node': 20.17.50
pg-protocol: 1.10.0
pg-types: 2.2.0
@@ -8752,6 +9066,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.1
+ '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.8.3)
+ '@typescript-eslint/scope-manager': 7.18.0
+ '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.8.3)
+ '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 7.18.0
+ eslint: 8.57.1
+ graphemer: 1.4.0
+ ignore: 5.3.2
+ natural-compare: 1.4.0
+ ts-api-utils: 1.4.3(typescript@5.8.3)
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -8781,6 +9113,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 7.18.0
+ '@typescript-eslint/types': 7.18.0
+ '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 7.18.0
+ debug: 4.4.1(supports-color@5.5.0)
+ eslint: 8.57.1
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.32.1
@@ -8798,6 +9143,11 @@ snapshots:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
+ '@typescript-eslint/scope-manager@7.18.0':
+ dependencies:
+ '@typescript-eslint/types': 7.18.0
+ '@typescript-eslint/visitor-keys': 7.18.0
+
'@typescript-eslint/scope-manager@8.32.1':
dependencies:
'@typescript-eslint/types': 8.32.1
@@ -8815,6 +9165,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.8.3)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3)
+ '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.8.3)
+ debug: 4.4.1(supports-color@5.5.0)
+ eslint: 8.57.1
+ ts-api-utils: 1.4.3(typescript@5.8.3)
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/type-utils@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
@@ -8828,6 +9190,8 @@ snapshots:
'@typescript-eslint/types@5.62.0': {}
+ '@typescript-eslint/types@7.18.0': {}
+
'@typescript-eslint/types@8.32.1': {}
'@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)':
@@ -8844,6 +9208,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/typescript-estree@7.18.0(typescript@5.8.3)':
+ dependencies:
+ '@typescript-eslint/types': 7.18.0
+ '@typescript-eslint/visitor-keys': 7.18.0
+ debug: 4.4.1(supports-color@5.5.0)
+ globby: 11.1.0
+ is-glob: 4.0.3
+ minimatch: 9.0.5
+ semver: 7.7.2
+ ts-api-utils: 1.4.3(typescript@5.8.3)
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)':
dependencies:
'@typescript-eslint/types': 8.32.1
@@ -8873,6 +9252,17 @@ snapshots:
- supports-color
- typescript
+ '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.8.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1)
+ '@typescript-eslint/scope-manager': 7.18.0
+ '@typescript-eslint/types': 7.18.0
+ '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3)
+ eslint: 8.57.1
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
'@typescript-eslint/utils@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.27.0(jiti@2.4.2))
@@ -8889,6 +9279,11 @@ snapshots:
'@typescript-eslint/types': 5.62.0
eslint-visitor-keys: 3.4.3
+ '@typescript-eslint/visitor-keys@7.18.0':
+ dependencies:
+ '@typescript-eslint/types': 7.18.0
+ eslint-visitor-keys: 3.4.3
+
'@typescript-eslint/visitor-keys@8.32.1':
dependencies:
'@typescript-eslint/types': 8.32.1
@@ -8903,26 +9298,6 @@ snapshots:
'@veriff/js-sdk@1.5.1': {}
- '@vitest/browser@3.1.4(playwright@1.52.0)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))(vitest@3.1.4)':
- dependencies:
- '@testing-library/dom': 10.4.0
- '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0)
- '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
- '@vitest/utils': 3.1.4
- magic-string: 0.30.17
- sirv: 3.0.1
- tinyrainbow: 2.0.0
- vitest: 3.1.4(@types/node@20.17.50)(@vitest/browser@3.1.4)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
- ws: 8.18.2
- optionalDependencies:
- playwright: 1.52.0
- transitivePeerDependencies:
- - bufferutil
- - msw
- - utf-8-validate
- - vite
- optional: true
-
'@vitest/browser@3.1.4(playwright@1.52.0)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))(vitest@3.1.4)':
dependencies:
'@testing-library/dom': 10.4.0
@@ -8982,14 +9357,6 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))':
- dependencies:
- '@vitest/spy': 3.1.4
- estree-walker: 3.0.3
- magic-string: 0.30.17
- optionalDependencies:
- vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
-
'@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))':
dependencies:
'@vitest/spy': 3.1.4
@@ -9492,6 +9859,8 @@ snapshots:
buffer-crc32@1.0.0: {}
+ buffer-equal-constant-time@1.0.1: {}
+
buffer-from@1.1.2: {}
buffer@5.7.1:
@@ -9708,6 +10077,21 @@ snapshots:
- supports-color
- ts-node
+ create-jest@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0):
+ dependencies:
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-config: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
+ jest-util: 29.7.0
+ prompts: 2.4.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
create-require@1.1.1: {}
cross-inspect@1.0.1:
@@ -10413,6 +10797,8 @@ snapshots:
events@3.3.0: {}
+ eventsource-polyfill@0.9.6: {}
+
execa@5.1.1:
dependencies:
cross-spawn: 7.0.6
@@ -11211,6 +11597,25 @@ snapshots:
- supports-color
- ts-node
+ jest-cli@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0):
+ dependencies:
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3))
+ '@jest/test-result': 29.7.0
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ create-jest: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
+ exit: 0.1.2
+ import-local: 3.2.0
+ jest-config: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
jest-config@29.7.0(@types/node@20.17.50)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3)):
dependencies:
'@babel/core': 7.27.1
@@ -11242,6 +11647,36 @@ snapshots:
- babel-plugin-macros
- supports-color
+ jest-config@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0):
+ dependencies:
+ '@babel/core': 7.27.1
+ '@jest/test-sequencer': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.27.1)
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-circus: 29.7.0(babel-plugin-macros@3.1.0)
+ jest-environment-node: 29.7.0
+ jest-get-type: 29.6.3
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-runner: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.15.21
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
jest-diff@29.7.0:
dependencies:
chalk: 4.1.2
@@ -11469,6 +11904,18 @@ snapshots:
- supports-color
- ts-node
+ jest@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0):
+ dependencies:
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.50)(typescript@5.8.3))
+ '@jest/types': 29.6.3
+ import-local: 3.2.0
+ jest-cli: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
jiti@2.4.2: {}
jose@5.10.0: {}
@@ -11534,6 +11981,19 @@ snapshots:
'@jsep-plugin/regex': 1.0.4(jsep@1.4.0)
jsep: 1.4.0
+ jsonwebtoken@9.0.2:
+ dependencies:
+ jws: 3.2.2
+ lodash.includes: 4.3.0
+ lodash.isboolean: 3.0.3
+ lodash.isinteger: 4.0.4
+ lodash.isnumber: 3.0.3
+ lodash.isplainobject: 4.0.6
+ lodash.isstring: 4.0.1
+ lodash.once: 4.1.1
+ ms: 2.1.3
+ semver: 7.7.2
+
jsx-ast-utils@3.3.5:
dependencies:
array-includes: 3.1.8
@@ -11541,6 +12001,17 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
+ jwa@1.4.2:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+
+ jws@3.2.2:
+ dependencies:
+ jwa: 1.4.2
+ safe-buffer: 5.2.1
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -11636,12 +12107,24 @@ snapshots:
lodash.castarray@4.4.0: {}
+ lodash.includes@4.3.0: {}
+
+ lodash.isboolean@3.0.3: {}
+
+ lodash.isinteger@4.0.4: {}
+
+ lodash.isnumber@3.0.3: {}
+
lodash.isplainobject@4.0.6: {}
+ lodash.isstring@4.0.1: {}
+
lodash.memoize@4.1.2: {}
lodash.merge@4.6.2: {}
+ lodash.once@4.1.1: {}
+
lodash@4.17.21: {}
long@5.3.2: {}
@@ -11778,6 +12261,8 @@ snapshots:
dependencies:
obliterator: 2.0.5
+ moment@2.30.1: {}
+
mri@1.2.0: {}
mrmime@2.0.1: {}
@@ -12246,6 +12731,8 @@ snapshots:
pure-rand@6.1.0: {}
+ qrious@4.0.2: {}
+
qs@6.13.0:
dependencies:
side-channel: 1.1.0
@@ -12915,6 +13402,10 @@ snapshots:
postcss-load-config: 3.1.4(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
typescript: 5.8.3
+ svelte-qrcode@1.0.1:
+ dependencies:
+ qrious: 4.0.2
+
svelte2tsx@0.7.39(svelte@5.33.1)(typescript@5.8.3):
dependencies:
dedent-js: 1.0.1
@@ -13087,6 +13578,10 @@ snapshots:
tree-kill@1.2.2: {}
+ ts-api-utils@1.4.3(typescript@5.8.3):
+ dependencies:
+ typescript: 5.8.3
+
ts-api-utils@2.1.0(typescript@5.8.3):
dependencies:
typescript: 5.8.3
@@ -13113,6 +13608,26 @@ snapshots:
'@jest/types': 29.6.3
babel-jest: 29.7.0(@babel/core@7.27.1)
+ ts-jest@29.3.4(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0))(typescript@5.8.3):
+ dependencies:
+ bs-logger: 0.2.6
+ ejs: 3.1.10
+ fast-json-stable-stringify: 2.1.0
+ jest: 29.7.0(@types/node@22.15.21)(babel-plugin-macros@3.1.0)
+ jest-util: 29.7.0
+ json5: 2.2.3
+ lodash.memoize: 4.1.2
+ make-error: 1.3.6
+ semver: 7.7.2
+ type-fest: 4.41.0
+ typescript: 5.8.3
+ yargs-parser: 21.1.1
+ optionalDependencies:
+ '@babel/core': 7.27.1
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.27.1)
+
ts-node-dev@2.0.0(@types/node@20.17.50)(typescript@5.8.3):
dependencies:
chokidar: 3.6.0
@@ -13431,27 +13946,6 @@ snapshots:
- supports-color
- terser
- vite-node@3.1.4(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
- dependencies:
- cac: 6.7.14
- debug: 4.4.1(supports-color@5.5.0)
- es-module-lexer: 1.7.0
- pathe: 2.0.3
- vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
- transitivePeerDependencies:
- - '@types/node'
- - jiti
- - less
- - lightningcss
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
vite-node@3.1.4(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
dependencies:
cac: 6.7.14
@@ -13483,22 +13977,6 @@ snapshots:
fsevents: 2.3.3
lightningcss: 1.30.1
- vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
- dependencies:
- esbuild: 0.25.4
- fdir: 6.4.4(picomatch@4.0.2)
- picomatch: 4.0.2
- postcss: 8.5.3
- rollup: 4.41.0
- tinyglobby: 0.2.13
- optionalDependencies:
- '@types/node': 20.17.50
- fsevents: 2.3.3
- jiti: 2.4.2
- lightningcss: 1.30.1
- tsx: 4.19.4
- yaml: 2.8.0
-
vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
dependencies:
esbuild: 0.25.4
@@ -13553,46 +14031,6 @@ snapshots:
- supports-color
- terser
- vitest@3.1.4(@types/node@20.17.50)(@vitest/browser@3.1.4)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
- dependencies:
- '@vitest/expect': 3.1.4
- '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))
- '@vitest/pretty-format': 3.1.4
- '@vitest/runner': 3.1.4
- '@vitest/snapshot': 3.1.4
- '@vitest/spy': 3.1.4
- '@vitest/utils': 3.1.4
- chai: 5.2.0
- debug: 4.4.1(supports-color@5.5.0)
- expect-type: 1.2.1
- magic-string: 0.30.17
- pathe: 2.0.3
- std-env: 3.9.0
- tinybench: 2.9.0
- tinyexec: 0.3.2
- tinyglobby: 0.2.13
- tinypool: 1.0.2
- tinyrainbow: 2.0.0
- vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
- vite-node: 3.1.4(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)
- why-is-node-running: 2.3.0
- optionalDependencies:
- '@types/node': 20.17.50
- '@vitest/browser': 3.1.4(playwright@1.52.0)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))(vitest@3.1.4)
- transitivePeerDependencies:
- - jiti
- - less
- - lightningcss
- - msw
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
vitest@3.1.4(@types/node@22.15.21)(@vitest/browser@3.1.4)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0):
dependencies:
'@vitest/expect': 3.1.4
diff --git a/scripts/expose-ports.sh b/scripts/expose-ports.sh
new file mode 100644
index 00000000..377dad5e
--- /dev/null
+++ b/scripts/expose-ports.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+MINIKUBE_IP="192.168.49.2"
+START_PORT=30000
+END_PORT=32767
+
+for ((port = $START_PORT; port <= $END_PORT; port++)); do
+ echo "Forwarding port $port to $MINIKUBE_IP:$port"
+ nohup socat TCP4-LISTEN:$port,fork TCP4:$MINIKUBE_IP:$port >/dev/null 2>&1 &
+done
diff --git a/services/ontology/package.json b/services/ontology/package.json
index 69e44787..d6e3761c 100644
--- a/services/ontology/package.json
+++ b/services/ontology/package.json
@@ -1,12 +1,20 @@
{
- "name": "ontology",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "keywords": [],
- "author": "",
- "license": "ISC"
+ "name": "ontology",
+ "version": "1.0.0",
+ "description": "Service for serving JSON schemas",
+ "main": "src/index.js",
+ "scripts": {
+ "start": "node src/index.js",
+ "dev": "nodemon src/index.js"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "cors": "^2.8.5",
+ "express": "^4.21.2"
+ },
+ "devDependencies": {
+ "nodemon": "^3.0.2"
+ }
}
diff --git a/services/ontology/schemas/socialMediaPost.json b/services/ontology/schemas/socialMediaPost.json
new file mode 100644
index 00000000..49ec4dc7
--- /dev/null
+++ b/services/ontology/schemas/socialMediaPost.json
@@ -0,0 +1,71 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "schemaId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
+ "title": "SocialMediaPost",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "The unique identifier for the post"
+ },
+ "authorId": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Reference to the user who created the post"
+ },
+ "content": {
+ "type": "string",
+ "maxLength": 500,
+ "description": "The main content of the post"
+ },
+ "mediaUrls": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "uri"
+ },
+ "description": "Array of URLs to media attachments (images, videos, etc.)"
+ },
+ "comments": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Array of comment IDs associated with this post"
+ },
+ "likes": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "Array of user IDs who liked this post"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "pattern": "^#[a-zA-Z0-9_]+$"
+ },
+ "description": "Array of hashtags associated with the post"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the post was created"
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the post was last updated"
+ },
+ "isDeleted": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether the post has been deleted"
+ }
+ },
+ "required": ["id", "authorId", "content", "createdAt"],
+ "additionalProperties": false
+}
diff --git a/services/ontology/schemas/user.json b/services/ontology/schemas/user.json
new file mode 100644
index 00000000..e9ca352d
--- /dev/null
+++ b/services/ontology/schemas/user.json
@@ -0,0 +1,28 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "schemaId": "550e8400-e29b-41d4-a716-446655440000",
+ "title": "User",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The unique identifier for the user"
+ },
+ "name": {
+ "type": "string",
+ "description": "The user's full name"
+ },
+ "email": {
+ "type": "string",
+ "format": "email",
+ "description": "The user's email address"
+ },
+ "age": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "The user's age"
+ }
+ },
+ "required": ["id", "name", "email"],
+ "additionalProperties": false
+}
diff --git a/services/ontology/schemas/userProfile.json b/services/ontology/schemas/userProfile.json
new file mode 100644
index 00000000..7fcff6e1
--- /dev/null
+++ b/services/ontology/schemas/userProfile.json
@@ -0,0 +1,63 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "schemaId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
+ "title": "UserProfile",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "The unique identifier for the user profile"
+ },
+ "username": {
+ "type": "string",
+ "minLength": 3,
+ "maxLength": 30,
+ "pattern": "^[a-zA-Z0-9_]+$",
+ "description": "The user's unique username"
+ },
+ "displayName": {
+ "type": "string",
+ "maxLength": 50,
+ "description": "The user's display name"
+ },
+ "bio": {
+ "type": "string",
+ "maxLength": 160,
+ "description": "User's biography"
+ },
+ "avatarUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to the user's avatar image"
+ },
+ "followers": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "Array of user IDs who follow this user"
+ },
+ "following": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "Array of user IDs this user follows"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the profile was created"
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the profile was last updated"
+ }
+ },
+ "required": ["id", "username", "displayName", "createdAt"],
+ "additionalProperties": false
+}
diff --git a/services/ontology/src/index.js b/services/ontology/src/index.js
new file mode 100644
index 00000000..da13733b
--- /dev/null
+++ b/services/ontology/src/index.js
@@ -0,0 +1,93 @@
+const express = require('express');
+const cors = require('cors');
+const fs = require('fs').promises;
+const path = require('path');
+
+const app = express();
+const PORT = process.env.PORT || 3000;
+
+// Middleware
+app.use(cors());
+app.use(express.json());
+
+// Schema directory path
+const SCHEMAS_DIR = path.join(__dirname, '../schemas');
+
+// In-memory schema index
+let schemaIndex = new Map();
+
+// Load all schemas into memory
+async function loadSchemas() {
+ try {
+ const files = await fs.readdir(SCHEMAS_DIR);
+ const schemaFiles = files.filter(file => file.endsWith('.json'));
+
+ for (const file of schemaFiles) {
+ const content = await fs.readFile(path.join(SCHEMAS_DIR, file), 'utf8');
+ const schema = JSON.parse(content);
+
+ if (!schema.schemaId) {
+ console.warn(`Warning: Schema in ${file} is missing schemaId`);
+ continue;
+ }
+
+ schemaIndex.set(schema.schemaId, schema);
+ }
+
+ console.log(`Loaded ${schemaIndex.size} schemas`);
+ } catch (error) {
+ console.error('Error loading schemas:', error);
+ throw error;
+ }
+}
+
+// Ensure schemas directory exists
+async function ensureSchemasDirectory() {
+ try {
+ await fs.access(SCHEMAS_DIR);
+ } catch {
+ await fs.mkdir(SCHEMAS_DIR, { recursive: true });
+ }
+}
+
+// Get schema by UUID
+app.get('/schemas/:uuid', async (req, res) => {
+ try {
+ const schemaId = req.params.uuid;
+ const schema = schemaIndex.get(schemaId);
+
+ if (!schema) {
+ return res.status(404).json({ error: 'Schema not found' });
+ }
+
+ res.json(schema);
+ } catch (error) {
+ res.status(500).json({ error: 'Internal server error' });
+ }
+});
+
+// List all available schemas
+app.get('/schemas', async (req, res) => {
+ try {
+ const schemas = Array.from(schemaIndex.entries()).map(([id, schema]) => ({
+ id,
+ title: schema.title
+ }));
+
+ res.json(schemas);
+ } catch (error) {
+ res.status(500).json({ error: 'Internal server error' });
+ }
+});
+
+// Start server
+async function startServer() {
+ await ensureSchemasDirectory();
+ await loadSchemas();
+
+ app.listen(PORT, () => {
+ console.log(`Schema service running on port ${PORT}`);
+ });
+}
+
+startServer();
\ No newline at end of file