iconograph-ui 1.2.25 → 1.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +3 -0
  2. package/example/.dockerignore +3 -0
  3. package/example/Dockerfile +17 -0
  4. package/example/Dockerfile.dev +19 -0
  5. package/example/README.md +38 -0
  6. package/example/jsconfig.json +19 -0
  7. package/example/package.json +26 -0
  8. package/example/src/app.d.ts +13 -0
  9. package/example/src/app.html +15 -0
  10. package/example/src/lib/assets/favicon.svg +1 -0
  11. package/example/src/lib/components/CustomInput.svelte +10 -0
  12. package/example/src/lib/components/CustomLabel.svelte +21 -0
  13. package/example/src/lib/components/CustomLink.svelte +8 -0
  14. package/example/src/lib/components/CustomTable.svelte +37 -0
  15. package/example/src/lib/components/types/input.js +4 -0
  16. package/example/src/lib/index.js +1 -0
  17. package/example/src/routes/+layout.svelte +101 -0
  18. package/example/src/routes/+page.svelte +85 -0
  19. package/example/src/routes/example/+server.js +16 -0
  20. package/example/src/routes/user/+page.svelte +104 -0
  21. package/example/src/routes/user/+server.js +23 -0
  22. package/example/static/css/style.css +133 -0
  23. package/example/static/css/testapp.css +30 -0
  24. package/example/static/favicon.svg +1 -0
  25. package/example/static/icons/icon-calendar-g.png +0 -0
  26. package/example/static/icons/icon-calendar-v.png +0 -0
  27. package/example/static/icons/icon-calendar.png +0 -0
  28. package/example/static/robots.txt +3 -0
  29. package/example/svelte.config.js +39 -0
  30. package/example/vite.config.js +19 -0
  31. package/lib/inputs/Editor.svelte +99 -0
  32. package/lib/table/CellLink.svelte +1 -1
  33. package/lib/table/Table.svelte +3 -1
  34. package/lib/table/TableColumnFilter.svelte +31 -0
  35. package/lib/table/TableFilter.svelte +51 -0
  36. package/lib/user/UserSelect.svelte +1 -5
  37. package/package.json +2 -1
package/README.md CHANGED
@@ -2,4 +2,7 @@
2
2
 
3
3
  A Svelte Kit components library
4
4
 
5
+ # Instructions
6
+
7
+ In the main repository, run `docker compose up` that starts a server accessible on `http://localhost:8001`
5
8
 
@@ -0,0 +1,3 @@
1
+ .svelte-kit
2
+ node_modules
3
+ package-lock.json
@@ -0,0 +1,17 @@
1
+ FROM node:24.6-alpine3.22 AS frnt-bibliapedia
2
+ LABEL maintainer="nathan.chevalier@asso-parabole.fr"
3
+
4
+ RUN mkdir -p /usr/src/app/node_modules && mkdir -p /usr/src/app/.svelte-kit && chown -R node:node /usr/src/app
5
+
6
+ WORKDIR /usr/src/app
7
+ COPY . .
8
+
9
+ RUN npm install
10
+
11
+ RUN npm run build
12
+
13
+ RUN rm -rf src/ static/
14
+
15
+ USER node:node
16
+
17
+ CMD [ "npm" , "run", "start" ]
@@ -0,0 +1,19 @@
1
+ FROM node:24.6-alpine3.22 AS frnt-bibliapedia-dev
2
+ LABEL maintainer="nathan.chevalier@asso-parabole.fr"
3
+
4
+ RUN mkdir -p /usr/src/app/node_modules && mkdir -p /usr/src/app/.svelte-kit && chown -R node:node /usr/src/app
5
+
6
+ WORKDIR /usr/src/app
7
+
8
+ COPY ["package.json", "package-lock.json*", "./"]
9
+
10
+ RUN npm install --save-dev --loglevel verbose
11
+
12
+ USER node:node
13
+
14
+ COPY --chown=node:node . .
15
+
16
+ EXPOSE 5173
17
+ EXPOSE 24678
18
+
19
+ CMD ["npm", "run", "dev", "--", "--no-open", "--host", "0.0.0.0"]
@@ -0,0 +1,38 @@
1
+ # sv
2
+
3
+ Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
4
+
5
+ ## Creating a project
6
+
7
+ If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+ ```sh
10
+ # create a new project in the current directory
11
+ npx sv create
12
+
13
+ # create a new project in my-app
14
+ npx sv create my-app
15
+ ```
16
+
17
+ ## Developing
18
+
19
+ Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+ ```sh
22
+ npm run dev
23
+
24
+ # or start the server and open the app in a new browser tab
25
+ npm run dev -- --open
26
+ ```
27
+
28
+ ## Building
29
+
30
+ To create a production version of your app:
31
+
32
+ ```sh
33
+ npm run build
34
+ ```
35
+
36
+ You can preview the production build with `npm run preview`.
37
+
38
+ > To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "checkJs": true,
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "resolveJsonModule": true,
9
+ "skipLibCheck": true,
10
+ "sourceMap": true,
11
+ "strict": true,
12
+ "moduleResolution": "bundler"
13
+ }
14
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
15
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
16
+ //
17
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
18
+ // from the referenced tsconfig.json - TypeScript does not merge them in
19
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "frnt-bibliapedia",
3
+ "private": true,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite dev",
8
+ "build": "vite build",
9
+ "preview": "vite preview",
10
+ "prepare": "svelte-kit sync || echo ''",
11
+ "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
12
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
13
+ },
14
+ "devDependencies": {
15
+ "@sveltejs/adapter-auto": "^6.0.0",
16
+ "@sveltejs/adapter-node": "^5.3.1",
17
+ "@sveltejs/kit": "^2.22.0",
18
+ "@sveltejs/vite-plugin-svelte": "^6.0.0",
19
+ "svelte": "^5.0.0",
20
+ "quill": "^2.0.3",
21
+ "svelte-check": "^4.0.0",
22
+ "svelte-portal": "2.2.1",
23
+ "typescript": "^5.0.0",
24
+ "vite": "^7.0.4"
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ // See https://svelte.dev/docs/kit/types#app.d.ts
2
+ // for information about these interfaces
3
+ declare global {
4
+ namespace App {
5
+ // interface Error {}
6
+ // interface Locals {}
7
+ // interface PageData {}
8
+ // interface PageState {}
9
+ // interface Platform {}
10
+ }
11
+ }
12
+
13
+ export {};
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ %sveltekit.head%
7
+ <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
8
+ <link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
9
+ <link rel="stylesheet" href="%sveltekit.assets%/css/style.css" />
10
+ <link rel="stylesheet" href="%sveltekit.assets%/css/testapp.css" />
11
+ </head>
12
+ <body data-sveltekit-preload-data="hover">
13
+ <div style="display: contents">%sveltekit.body%</div>
14
+ </body>
15
+ </html>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
@@ -0,0 +1,10 @@
1
+ <script>
2
+ export let name;
3
+ export let value;
4
+ </script>
5
+
6
+ <input type="color" bind:value={value}/>
7
+
8
+ <style>
9
+
10
+ </style>
@@ -0,0 +1,21 @@
1
+ <script>
2
+ export let type;
3
+ </script>
4
+
5
+ <div>
6
+ {type}
7
+ </div>
8
+
9
+ <style>
10
+ div {
11
+ font-weight: 600;
12
+ text-transform: uppercase;
13
+ font-size: 13px;
14
+ color: #777;
15
+ background-color: #ddd;
16
+ padding: 5px 16px;
17
+ height: 16px;
18
+ line-height: 16px;
19
+ border-radius: 20px;
20
+ }
21
+ </style>
@@ -0,0 +1,8 @@
1
+ <script>
2
+ import CellLink from "$lib/iconograph-ui/table/CellLink.svelte";
3
+
4
+ export let id;
5
+ export let name;
6
+ </script>
7
+
8
+ <CellLink url="/org/{id}" text={name} ></CellLink>
@@ -0,0 +1,37 @@
1
+ <script>
2
+ // @ts-nocheck
3
+ import Table from "$lib/iconograph-ui/table/Table.svelte";
4
+ import CustomInput from "./CustomInput.svelte";
5
+ import CustomLabel from "./CustomLabel.svelte";
6
+ import CustomLink from "./CustomLink.svelte";
7
+ import { enumType } from "./types/input";
8
+
9
+ let statuses = [
10
+ { name: 'ALL', value: 0 },
11
+ { name: 'DRAFT', value: 1 },
12
+ { name: 'REJECTED', value: 2 },
13
+ { name: 'CONVERGED', value: 3 },
14
+ { name: 'APPROVED', value: 4 },
15
+ { name: 'PUBLISHED', value: 5 },
16
+ { name: 'DISABLED', value: 6 },
17
+ { name: 'DELETED', value: 7 },
18
+ { name: 'REPORTED', value: 8 },
19
+ { name: 'MOD_L1', value: 9 },
20
+ { name: 'MODING', value: 10 }
21
+ ];
22
+
23
+ let settings = [
24
+ {
25
+ field: "name", label: "Nom", component: CustomLink, width: 120, props: {},
26
+ sort: (a, b) => a.name.localeCompare(b.name)
27
+ },
28
+ { field: "city", label: "Ville", component: null, props: {}, width: 200, sort: (a, b) => a.name.localeCompare(b.name)},
29
+ { field: "type", label: "Type", component: CustomLabel, props: {}, width: 120, sort: (a, b) => null, filterOptions: enumType},
30
+ { field: "status", label: "Statut", component: null, props: {}, width: 120, sort: (a, b) => null},
31
+ ]
32
+
33
+ let uri = "/example"
34
+
35
+ </script>
36
+
37
+ <Table uri={uri} columns={settings} actions={false}></Table>
@@ -0,0 +1,4 @@
1
+ export const enumType = [
2
+ { A: "Option A" },
3
+ { C: "Option C" }
4
+ ];
@@ -0,0 +1 @@
1
+ // place files you want to import through the `$lib` alias in this folder.
@@ -0,0 +1,101 @@
1
+ <script>
2
+ // @ts-nocheck
3
+ import { page } from '$app/stores';
4
+ import { afterUpdate } from 'svelte';
5
+
6
+ import NotificationWrapper from '$lib/iconograph-ui/notification/NotificationWrapper.svelte';
7
+ import MainMenu from "$lib/iconograph-ui/navigation/MainMenu.svelte";
8
+
9
+ let current_url = $page.url.pathname.split('/');
10
+
11
+ afterUpdate(() => {
12
+ current_url = $page.url.pathname.split('/');
13
+ });
14
+
15
+ let isMenuOpen = false;
16
+
17
+ let menu = {
18
+ logo: "",
19
+ main: [
20
+ { name: 'Home', uri: '', icon: '/icons/icon-calendar-g.png', iconHover: '/icons/icon-calendar-v.png', selected: current_url[1] == ''},
21
+ { name: 'Home', uri: '', icon: '/icons/icon-calendar-g.png', iconHover: '/icons/icon-calendar-v.png', selected: current_url[1] == '1' },
22
+ { name: 'Home', uri: '', icon: '/icons/icon-calendar-g.png', iconHover: '/icons/icon-calendar-v.png', selected: current_url[1] == '1' },
23
+ { name: 'Home', uri: '', icon: '/icons/icon-calendar-g.png', iconHover: '/icons/icon-calendar-v.png', selected: current_url[1] == '1' },
24
+ ],
25
+ };
26
+
27
+ </script>
28
+
29
+ <MainMenu menu={menu} isOpen={isMenuOpen} ></MainMenu>
30
+
31
+ <div id="main-container" class="{isMenuOpen ? 'menu-open' : ''}" >
32
+ <div style="display: contents">
33
+
34
+ <slot />
35
+
36
+ </div>
37
+ </div>
38
+
39
+ <NotificationWrapper></NotificationWrapper>
40
+
41
+ <style>
42
+ #main-container {
43
+ position: relative;
44
+ display: flex;
45
+ flex-direction: column;
46
+ justify-content: center;
47
+ left: 85px;
48
+ width: calc(100% - 85px);
49
+ transition: 0.3s all ease-in-out;
50
+ padding-bottom: 48px;
51
+ }
52
+ #main-container.menu-open {
53
+ width: calc(100% - 300px);
54
+ left: 300px;
55
+ }
56
+
57
+
58
+ #main-container section > article {
59
+ width: calc(100% - 48px);
60
+ max-width: min(calc(100% - 24px), 1100px) !important;
61
+ margin-bottom: 30px;
62
+ padding: 24px 24px;
63
+ background-color: #ffffff;
64
+ box-sizing: border-box;
65
+ border: 1px solid #e4e4e4;
66
+ border-radius: 8px;
67
+ }
68
+
69
+ @media (max-width: 1040px) {
70
+ #main-container.menu-open > section {
71
+ width: 100%;
72
+ min-width: 300px;
73
+ }
74
+ nav {
75
+ z-index: 50;
76
+ }
77
+ #main-container.menu-open section > article {
78
+ width: calc(100% - 88px);
79
+ }
80
+ }
81
+
82
+ @media (max-width: 780px) {
83
+ #main-container {
84
+ left: 0px;
85
+ margin-top: 0px;
86
+ }
87
+ #main-container.menu-open {
88
+ width: 100vw;
89
+ left: 0px;
90
+ }
91
+ article {
92
+ width: calc(100% - 88px);
93
+ margin-bottom: 30px;
94
+ padding: 24px 24px;
95
+ }
96
+ #main-container section > article {
97
+ width: calc(100% - 88px);
98
+ }
99
+ }
100
+ </style>
101
+
@@ -0,0 +1,85 @@
1
+ <script>
2
+ import HeadSection from "$lib/iconograph-ui/layout/HeadSection.svelte";
3
+ import BodySection from "$lib/iconograph-ui/layout/BodySection.svelte";
4
+ import Card from "$lib/iconograph-ui/layout/Card.svelte";
5
+ import Modal from "$lib/iconograph-ui/layout/Modal.svelte";
6
+ import Form from "$lib/iconograph-ui/form/Form.svelte";
7
+ import FlexForm from "$lib/iconograph-ui/form/FlexForm.svelte";
8
+ import Input from "$lib/iconograph-ui/form/Input.svelte";
9
+ import SexeChoiceInput from "$lib/iconograph-ui/form/SexeChoiceInput.svelte";
10
+ import CustomInput from "$lib/components/CustomInput.svelte";
11
+ import CustomTable from "../lib/components/CustomTable.svelte";
12
+ import Editor from "$lib/iconograph-ui/inputs/Editor.svelte";
13
+ import SegmentedSwitchInput from "$lib/iconograph-ui/form/SegmentedSwitchInput.svelte"
14
+
15
+ let options = [{ key: "Value" }]
16
+ let inputs = [
17
+ { component: Input, props: { type: "text", name: "title", label: "Titre" } },
18
+ { component: Input, props: { type: "select", name: "title", label: "Titre" } },
19
+ { component: Input, props: { type: "select", name: "custom", label: "Custom", options: options } },
20
+ { component: Input, props: { type: "email", name: "email", label: "Email"}, value: "test@example.com" },
21
+ { component: SexeChoiceInput, props: { name: "sexe", label: "Sexe" } },
22
+ { component: CustomInput, props: { name: "color", label: "Couleur" } },
23
+ ];
24
+
25
+ let button = {
26
+ label: "Enregistrer",
27
+ }
28
+
29
+ let open = false;
30
+ let section = 'Doc';
31
+
32
+ function onEditorChange(event) {
33
+ console.log("HTML:", event.detail.html);
34
+ }
35
+ </script>
36
+
37
+ <HeadSection>
38
+
39
+ <h1 style="margin-top: 40px;">Welcome to SvelteKit</h1>
40
+ <p style="margin-bottom: 24px;">Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
41
+
42
+ </HeadSection>
43
+
44
+ <BodySection>
45
+
46
+ <Card padding={'0px'} >
47
+ <CustomTable></CustomTable>
48
+ </Card>
49
+
50
+ <Card>
51
+ <div on:click={() => open = true}>Open Modal</div>
52
+ </Card>
53
+
54
+ <Card padding={'24px'}>
55
+ <h1>My Form</h1>
56
+
57
+ <Form inputs={inputs} uri={'/test'} button={button}>
58
+ </Form>
59
+
60
+ </Card>
61
+
62
+ <Card padding={'0px'}>
63
+ <Editor on:change={onEditorChange}></Editor>
64
+ </Card>
65
+ </BodySection>
66
+
67
+ <Modal bind:open={open}>
68
+ <div style="padding: 24px; width: 600px; height: 350px; margin-bottom: 24px;">
69
+ <FlexForm inputs={inputs} uri={'/test'} button={button}>
70
+ <SegmentedSwitchInput options={['Doc', 'Group', 'Entité']} bind:selected={section} ></SegmentedSwitchInput>
71
+ <p style="margin: 12px;">{section} is selected</p>
72
+
73
+ {#each inputs as input}
74
+ {#if !input.disabled }
75
+ <div class="form-row">
76
+ <div>
77
+ <label for="{input.props.name}" class="mandatory">{input.props.label}</label>
78
+ <svelte:component this={input.component} {...input.props} bind:value={input.value} />
79
+ </div>
80
+ </div>
81
+ {/if}
82
+ {/each}
83
+ </FlexForm>
84
+ </div>
85
+ </Modal>
@@ -0,0 +1,16 @@
1
+ // @ts-nocheck
2
+ import { json } from '@sveltejs/kit';
3
+
4
+ export async function GET({ request, cookies }) {
5
+
6
+ let response = [
7
+ { id: "1234", name: "Saint Louis", city: "Paris", type: "HOMME", status: "ACTIVE" },
8
+ { id: "1234", name: "Saint Jean", city: "Jérusalem", type: "HOMME", status: "DISABLED" },
9
+ { id: "1234", name: "Sainte Blandine", city: "Lyon", type: "FEMME", status: "ACTIVE" },
10
+ { id: "1234", name: "Saint Christophe", city: "Corinthe", type: "HOMME", status: "ACTIVE" },
11
+ { id: "1234", name: "Sainte Rita", city: "Lupiano", type: "FEMME", status: "DELETED" },
12
+ { id: "1234", name: "Saint François d'Assise", city: "Assise", type: "HOMME", status: "ACTIVE" }
13
+ ]
14
+
15
+ return json({ data: response }, { status: 201 });
16
+ }
@@ -0,0 +1,104 @@
1
+ <script>
2
+ import HeadSection from "$lib/iconograph-ui/layout/HeadSection.svelte";
3
+ import BodySection from "$lib/iconograph-ui/layout/BodySection.svelte";
4
+ import Card from "$lib/iconograph-ui/layout/Card.svelte";
5
+ import UserPicture from "$lib/iconograph-ui/user/UserPicture.svelte";
6
+ import NavBar from "$lib/iconograph-ui/navigation/NavBar.svelte";
7
+ import SelectUserInput from "$lib/iconograph-ui/user/SelectUserInput.svelte";
8
+ import UserSelect from "$lib/iconograph-ui/user/UserSelect.svelte";
9
+
10
+ import Form from "$lib/iconograph-ui/form/Form.svelte";
11
+ import Input from "$lib/iconograph-ui/form/Input.svelte";
12
+ import SexeChoiceInput from "$lib/iconograph-ui/form/SexeChoiceInput.svelte";
13
+ import CustomInput from "$lib/components/CustomInput.svelte";
14
+
15
+ let inputs = [
16
+ { component: Input, props: { type: "text", name: "title", label: "Titre" } },
17
+ { component: Input, props: { type: "select", name: "title", label: "Titre", options: ['Maison', 'Voiture']} },
18
+ { component: Input, props: { type: "email", name: "email", label: "Email"}, value: "test@example.com" },
19
+ { component: SexeChoiceInput, props: { name: "sexe", label: "Sexe" } },
20
+ { component: CustomInput, props: { name: "color", label: "Couleur" } },
21
+ ];
22
+
23
+ let button = {
24
+ label: "Enregistrer",
25
+ }
26
+
27
+ let user = {
28
+ firstname: "Nathan",
29
+ lastname: "Chevalier",
30
+ }
31
+
32
+ let users = [{
33
+ id: 1234,
34
+ firstname: "Nathan",
35
+ lastname: "Chevalier",
36
+ }]
37
+
38
+ let tabs = { infos: 'Informations', docs: 'Documents', groups: 'Groupes' };
39
+ let currentTab;
40
+
41
+ function handleManagerSelection(e) {
42
+ console.log(e.detail.id);
43
+ }
44
+
45
+
46
+ </script>
47
+
48
+ <HeadSection>
49
+
50
+ <div class="flex-row center" style="margin-top: 64px; margin-bottom: 24px;">
51
+ <div class="picture-medium">
52
+ <UserPicture user={user} size={120}></UserPicture>
53
+ </div>
54
+ <div class="flex-fill margin-l-l">
55
+ <div class="flex-row">
56
+ <div>
57
+ <div style="display: flex; align-items: center;" >
58
+ <h2 class="margin-l-s margin-r-m">{user.firstname} {user.lastname}</h2>
59
+ </div>
60
+ <span class="margin-l-s" style="text-transform: uppercase; color: #888; font-weight: 600;"></span>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <NavBar tabs={tabs} currentTab={currentTab} ></NavBar>
67
+
68
+ </HeadSection>
69
+
70
+ <BodySection>
71
+
72
+ <Card>
73
+
74
+ <SelectUserInput></SelectUserInput>
75
+
76
+ </Card>
77
+
78
+ <Card>
79
+
80
+ <div style="width: 120px;">
81
+ <UserSelect></UserSelect>
82
+ </div>
83
+
84
+ </Card>
85
+
86
+ <Card>
87
+
88
+ <UserSelect></UserSelect>
89
+
90
+ </Card>
91
+
92
+
93
+ <Card padding={'24px'}>
94
+ <h1>My Form</h1>
95
+
96
+ <Form inputs={inputs} uri={'/test'} button={button}>
97
+ </Form>
98
+
99
+ </Card>
100
+
101
+ </BodySection>
102
+
103
+ <style>
104
+ </style>
@@ -0,0 +1,23 @@
1
+ // @ts-nocheck
2
+ import { json } from '@sveltejs/kit';
3
+
4
+ export async function GET({ request, cookies, params, url }) {
5
+ let search = url.searchParams.get('contains')
6
+
7
+ let users = [
8
+ { id: 1, firstname: "Alice", lastname:"Dupont", avatar: "https://i.pravatar.cc/40?u=alice" },
9
+ { id: 2, firstname: "Bob", lastname:"Martin", avatar: "https://i.pravatar.cc/40?u=bob" },
10
+ { id: 3, firstname: "Charlie", lastname:"Mabrier", avatar: "https://i.pravatar.cc/40?u=charlie" },
11
+ { id: 4, firstname: "David", lastname:"Pascal", avatar: "https://i.pravatar.cc/40?u=david" },
12
+ { id: 5, firstname: "Zoé", lastname:"Brauen", avatar: "https://i.pravatar.cc/40?u=charlie" },
13
+ { id: 6, firstname: "Nathan", lastname:"Chevalier", avatar: "https://i.pravatar.cc/40?u=david" },
14
+ ];
15
+
16
+ let filteredUsers = users.filter((user) => {
17
+ let str = (user.firstname + ' ' + user.lastname).normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
18
+ const inputStr = search.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
19
+ return str.includes(inputStr);
20
+ });
21
+
22
+ return json({ data: filteredUsers }, { status: 201 });
23
+ }
@@ -0,0 +1,133 @@
1
+ * {
2
+ margin: 0px;
3
+ padding: 0px;
4
+ font-family: "Roboto", serif;
5
+ }
6
+ body {
7
+ background-color: #fcfcfa;
8
+ }
9
+ a {
10
+ color: inherit;
11
+ text-decoration: none;
12
+ }
13
+ a:visited {
14
+ color: inherit;
15
+ }
16
+
17
+ h2 {
18
+ font-family: 'Montserrat', sans-serif;
19
+ font-weight: 800;
20
+ color: #3b339c;
21
+ color: #111
22
+ }
23
+ h3 {
24
+ font-family: 'Montserrat', sans-serif;
25
+ font-weight: 700;
26
+ color: #09025f;
27
+ color: #111
28
+ }
29
+ h4 {
30
+ font-family: 'Montserrat', sans-serif;
31
+ font-weight: 700;
32
+ color: #09025f;
33
+ }
34
+ h5 {
35
+ font-family: 'Montserrat', sans-serif;
36
+ font-weight: 700;
37
+ color: #212121;
38
+ font-size: 17px;
39
+ }
40
+ h6 {
41
+ font-family: 'Montserrat', sans-serif;
42
+ font-weight: 700;
43
+ color: #555555;
44
+ font-size: 16px;
45
+ }
46
+ span {
47
+ font-family: 'Montserrat', sans-serif;
48
+ font-weight: 500;
49
+ color: #aaa;
50
+ font-size: 14px;
51
+ }
52
+
53
+
54
+
55
+ .flex-row {
56
+ display: flex;
57
+ flex-direction: row;
58
+ justify-content: space-between;
59
+ }
60
+ .flex-col {
61
+ display: flex;
62
+ flex-direction: column;
63
+ }
64
+ .flex-row > .flex-col {
65
+ flex: 1;
66
+ }
67
+ .flex-fill {
68
+ flex: 10;
69
+ }
70
+ .center {
71
+ align-items: center;
72
+ }
73
+ .start {
74
+ justify-content: flex-start;
75
+ }
76
+ .wrap {
77
+ flex-wrap: wrap;
78
+ }
79
+ .break {
80
+ flex-basis: 100%;
81
+ height: 0;
82
+ }
83
+
84
+ /**
85
+ * Margin / Padding
86
+ **/
87
+ .margin-t-l {
88
+ margin-top: 24px;
89
+ }
90
+ .margin-t-m {
91
+ margin-top: 12px;
92
+ }
93
+ .margin-t-s {
94
+ margin-top: 4px;
95
+ }
96
+ .margin-b-l {
97
+ margin-bottom: 24px;
98
+ }
99
+ .margin-b-m {
100
+ margin-bottom: 12px;
101
+ }
102
+ .margin-b-s {
103
+ margin-bottom: 4px;
104
+ }
105
+ .margin-l-l {
106
+ margin-left: 24px;
107
+ }
108
+ .margin-l-m {
109
+ margin-left: 12px;
110
+ }
111
+ .margin-l-s {
112
+ margin-left: 4px;
113
+ }
114
+
115
+ #project-wrapper {
116
+ width: calc(100% - 40px) ! important;
117
+ max-width: 748px !important;
118
+ }
119
+ .project-card-wrapper {
120
+ min-width: calc(50% - 12px);
121
+ margin-right: 24px;
122
+ }
123
+ @media (max-width: 600px) {
124
+ .flex-row {
125
+ flex-direction: column;
126
+ }
127
+ .project-card-wrapper {
128
+ margin-right: 0px;
129
+ }
130
+ #project-wrapper {
131
+ width: calc(100% - 48px) !important;
132
+ }
133
+ }
@@ -0,0 +1,30 @@
1
+ :root {
2
+ --background-color: #fcfcfc;
3
+ --main-bg-color: #ffffff;
4
+ --main-border-color: #e4e4e4;
5
+
6
+ --disabled-background-color: #555555;
7
+
8
+ /** Theme */
9
+ --theme-main-color: #6046c5;
10
+ --theme-main-color-hover: #44338b;
11
+ --theme-bg-color-light: #6046c511;
12
+ --theme-text-font: 'Roboto';
13
+
14
+ /** Inputs */
15
+ --theme-input-bg-color: #f5f5f9;
16
+ --theme-input-bg-highlight: #efeff5;
17
+ --theme-input-bg-hover: #dfdfe4;
18
+ --theme-input-border: none; /*2px solid ebebed*/
19
+ --theme-input-outline: 2px solid var(--theme-main-color);
20
+ --theme-input-outline-offset: 2px;
21
+ --theme-input-border-failure: 2px solid #f95959;
22
+ --theme-input-height: 40px;
23
+ --theme-input-text-color: #111;
24
+
25
+ /** Icons */
26
+ --logo-minimized: url('/favicon.svg');
27
+
28
+ /** Fonts */
29
+ --theme-main-font: 'Montserrat';
30
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
@@ -0,0 +1,3 @@
1
+ # allow crawling everything by default
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,39 @@
1
+ // svelte.config.js
2
+
3
+ import nodeAdapter from '@sveltejs/adapter-node';
4
+ import autoAdapter from '@sveltejs/adapter-auto';
5
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
6
+
7
+ /** @type {import('@sveltejs/kit').Config} */
8
+ let config = {
9
+ kit: {
10
+ adapter: nodeAdapter()
11
+ },
12
+ server: {
13
+ port: 5173,
14
+ strictPort: true,
15
+ },
16
+ onwarn: (warning, handler) => {
17
+ if (warning.code.includes("a11y")) return;
18
+ handler(warning);
19
+ },
20
+ };
21
+
22
+ if (process.env.NODE_ENV == 'development') {
23
+ config = {
24
+ preprocess: vitePreprocess(),
25
+ kit: {
26
+ adapter: autoAdapter()
27
+ },
28
+ server: {
29
+ port: 5173,
30
+ strictPort: true,
31
+ },
32
+ onwarn: (warning, handler) => {
33
+ if (warning.code.includes("a11y")) return;
34
+ handler(warning);
35
+ },
36
+ };
37
+ }
38
+
39
+ export default config;
@@ -0,0 +1,19 @@
1
+ import { sveltekit } from '@sveltejs/kit/vite';
2
+ import { defineConfig } from 'vite';
3
+
4
+ export default defineConfig({
5
+ optimizeDeps: {
6
+ exclude: ["rrule"], // Stop Vite from pre-bundling `rrule`
7
+ },
8
+ resolve: {
9
+ alias: {
10
+ "rrule": "rrule/dist/esm", // Use correct ESM version
11
+ },
12
+ },
13
+ build: {
14
+ commonjsOptions: {
15
+ transformMixedEsModules: true, // Allow mixed ES & CJS modules
16
+ },
17
+ },
18
+ plugins: [sveltekit()]
19
+ });
@@ -0,0 +1,99 @@
1
+ <script>
2
+ import { onMount, createEventDispatcher } from "svelte";
3
+ import "quill/dist/quill.snow.css";
4
+
5
+ const dispatch = createEventDispatcher();
6
+
7
+ export let content = "";
8
+ export let theme = "snow";
9
+
10
+ let editorEl;
11
+ let editor;
12
+
13
+ const tooltips = {
14
+ bold: "Bold",
15
+ italic: "Italic",
16
+ underline: "Underline",
17
+ strike: "Strikethrough",
18
+ link: "Insert Link",
19
+ image: "Insert Image",
20
+ blockquote: "Blockquote",
21
+ clean: "Remove Formatting",
22
+ };
23
+
24
+ function addTooltips() {
25
+ const toolbar = document.querySelector(".ql-toolbar");
26
+ if (!toolbar) return;
27
+
28
+ toolbar.querySelectorAll("button, select").forEach((btn) => {
29
+ const format =
30
+ btn.className.match(/ql-(\w+)/)?.[1] ||
31
+ btn.getAttribute("value") ||
32
+ null;
33
+ if (format && tooltips[format]) {
34
+ btn.setAttribute("title", tooltips[format]);
35
+ }
36
+ });
37
+ }
38
+
39
+ onMount(async () => {
40
+ const Quill = (await import("quill")).default;
41
+ editor = new Quill(editorEl, {
42
+ theme,
43
+ modules: {
44
+ toolbar: [
45
+ [{ size: [] }],
46
+ ["bold", "italic", "underline", "strike"],
47
+ [{ color: [] }, { background: [] }],
48
+ ["blockquote"],
49
+ [{ list: "ordered" }, { list: "bullet" }],
50
+ [{ align: [] }],
51
+ ["link"],
52
+ ["clean"],
53
+
54
+ /*
55
+ All the configuration:
56
+ [{ font: [] }, { size: [] }],
57
+ ["bold", "italic", "underline", "strike"],
58
+ [{ color: [] }, { background: [] }],
59
+ [{ script: "sub" }, { script: "super" }],
60
+ [{ header: "1" }, { header: "2" }, "blockquote", "code-block"],
61
+ [{ list: "ordered" }, { list: "bullet" }, { indent: "-1" }, { indent: "+1" }],
62
+ [{ direction: "rtl" }, { align: [] }],
63
+ ["link", "image", "video", "formula"],
64
+ ["clean"], // remove formatting button
65
+ */
66
+ ],
67
+ },
68
+ placeholder: 'Redigez votre message',
69
+ });
70
+
71
+ if (content) {
72
+ editor.clipboard.dangerouslyPasteHTML(content);
73
+ }
74
+
75
+ editor.on("text-change", () => {
76
+ console.log("editor on text change")
77
+ const html = editor.root.innerHTML;
78
+ const delta = editor.getContents();
79
+ dispatch("change", { html, delta });
80
+ });
81
+ /*
82
+ Use like this
83
+ <Editor on:change={onEditorChange} />
84
+
85
+ function onEditorChange(event) {
86
+ console.log("HTML:", event.detail.html);
87
+ console.log("Delta:", event.detail.delta);
88
+ }
89
+ */
90
+
91
+ addTooltips();
92
+ });
93
+ </script>
94
+
95
+ <div bind:this={editorEl} style="width: 100%; height: 200px;"></div>
96
+
97
+ <style>
98
+ /* TODO */
99
+ </style>
@@ -4,7 +4,7 @@
4
4
  </script>
5
5
 
6
6
  <span>
7
- <a href="{url}">{text ? text : ''}</a>
7
+ <a href="{url}" data-sveltekit-preload-data="off">{text ? text : ''}</a>
8
8
  </span>
9
9
 
10
10
  <style>
@@ -2,6 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { onMount } from 'svelte';
4
4
  import TableRow from "./TableRow.svelte";
5
+ import TableFilter from './TableFilter.svelte';
5
6
 
6
7
  export let columns = [];
7
8
  export let uri;
@@ -98,6 +99,7 @@
98
99
  </div>
99
100
  </div>-->
100
101
 
102
+ <TableFilter columns={columns}></TableFilter>
101
103
  <div class="table-header">
102
104
  <div><div>
103
105
  {#each columns as c}
@@ -272,4 +274,4 @@
272
274
  background-color: #fff;
273
275
  margin-left: 60px;
274
276
  }
275
- </style>
277
+ </style>
@@ -0,0 +1,31 @@
1
+ <script>
2
+ export let filter;
3
+ export let value;
4
+ </script>
5
+
6
+ <div class="wrapper">
7
+ <div class="row">
8
+ {#if filter}
9
+ <div style="min-width: {filter.width}px; width: {filter.width}px;">
10
+ {filter.label}
11
+ {#if filter.filterOptions}
12
+ <select bind:value={value}>
13
+ {#each filter.filterOptions as o}
14
+ <option value={Object.keys(o)[0]}>{Object.values(o)[0]}</option>
15
+ {/each}
16
+ </select>
17
+ {:else}
18
+ <input type="text" bind:value={value}/>
19
+ {/if}
20
+ </div>
21
+ {:else}
22
+ <div>
23
+ ERROR: TableFilterRow should have a column
24
+ </div>
25
+ {/if}
26
+ </div>
27
+ </div>
28
+
29
+ <style>
30
+ /* TODO */
31
+ </style>
@@ -0,0 +1,51 @@
1
+ <script>
2
+ // @ts-nocheck
3
+ import { onMount } from 'svelte';
4
+ import TableColumnFilter from './TableColumnFilter.svelte';
5
+
6
+ export let columns;
7
+
8
+ let selectedColumnsToFilter = [];
9
+ let selectedColumn = '';
10
+ let aggregateFilters = {};
11
+
12
+ async function addFilter() {
13
+ if (selectedColumn && !selectedColumnsToFilter.includes(selectedColumn)) {
14
+ selectedColumnsToFilter = [...selectedColumnsToFilter, selectedColumn];
15
+ }
16
+ }
17
+
18
+ async function submitFilter() {
19
+ console.log("TODO: submit filter with a request. ", aggregateFilters);
20
+ }
21
+
22
+ $: {
23
+ selectedColumnsToFilter.forEach(f => {
24
+ aggregateFilters[f.field] = f.filterValue;
25
+ });
26
+ };
27
+ </script>
28
+
29
+ <div class="tableFilter-wrapper">
30
+ <div>
31
+ <div class="tableFilter-body">
32
+ {#each selectedColumnsToFilter as f}
33
+ <TableColumnFilter filter={f} bind:value={f.filterValue}></TableColumnFilter>
34
+ {/each}
35
+ <select bind:value={selectedColumn}>
36
+ <option value="" disabled selected>Select column to filter</option>
37
+ {#each columns as col}
38
+ <option value={col}>{col.label}</option>
39
+ {/each}
40
+ </select>
41
+ <button on:click={addFilter}>Add Filter</button>
42
+ {#if selectedColumnsToFilter.length > 0}
43
+ <button on:click={submitFilter}>Run filter</button>
44
+ {/if}
45
+ </div>
46
+ </div>
47
+ </div>
48
+
49
+ <style>
50
+ /* TODO */
51
+ </style>
@@ -19,7 +19,7 @@
19
19
  async function handleFilter() {
20
20
  waiting = true;
21
21
 
22
- const response = await fetch(`${uri}?contains=${search}&limit=100&page=1`, {
22
+ const response = await fetch(`${uri}?contains=${search}&limit=15&page=1`, {
23
23
  method: 'GET',
24
24
  headers: { 'Content-Type': 'application/json' }
25
25
  });
@@ -30,10 +30,6 @@
30
30
  waiting = false;
31
31
  }
32
32
 
33
- onMount(() => {
34
- handleFilter();
35
- });
36
-
37
33
  function openDropdown() {
38
34
  const rect = dropdownEl.getBoundingClientRect();
39
35
  coords = { top: rect.bottom, left: rect.left, width: rect.width };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iconograph-ui",
3
- "version": "1.2.25",
3
+ "version": "1.2.26",
4
4
  "description": "A Svelte Kit components library",
5
5
  "main": "./index.js",
6
6
  "svelte": "./index.js",
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/asso-parabole/iconograph-ui#readme",
29
29
  "dependencies": {
30
+ "quill": "^2.0.3",
30
31
  "svelte": "^5.38.1"
31
32
  },
32
33
  "peerDependencies": {