iconograph-ui 1.2.13 → 1.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -13,7 +13,7 @@ import Table from "./lib/table/Table.svelte"
13
13
  import CellLink from "./lib/table/CellLink.svelte"
14
14
  import UserPicture from "./lib/user/UserPicture.svelte";
15
15
  import NavBar from "./lib/navigation/NavBar.svelte";
16
- import UserSelectSingle from "./lib/user/UserSelectSingle.svelte";
16
+ import SelectUserInput from "./lib/user/SelectUserInput.svelte";
17
17
 
18
18
  export {
19
19
  Button,
@@ -31,5 +31,5 @@ export {
31
31
  CellLink,
32
32
  UserPicture,
33
33
  NavBar,
34
- UserSelectSingle,
34
+ SelectUserInput,
35
35
  };
@@ -92,9 +92,9 @@
92
92
  }
93
93
  label {
94
94
  display: inline-block;
95
- padding: 0px 6px;
95
+ padding: 0px 0px;
96
96
  margin: 4px 6px;
97
- font-family: 'Montserrat', sans-serif;
97
+ font-family: var(--theme-text-font);
98
98
  font-size: 14px;
99
99
  font-weight: 600;
100
100
  color: #222;
@@ -22,37 +22,33 @@
22
22
 
23
23
  <style>
24
24
 
25
- input, textarea {
26
- background-color: #f5f5fb;
27
- border: none;
28
- border-radius: 6px;
29
- padding: 7px 14px;
25
+ input, textarea, select {
26
+ background-color: var(--theme-input-bg-color, #ebebed);
27
+ height: var(--theme-input-height, 40px);
28
+ border: var(--theme-input-border, none);
29
+ border-radius: 8px;
30
+ padding: 0px 16px;
30
31
  font-size: 14px;
31
- line-height: 14px;
32
- font-weight: 500;
33
- border: 1px solid #f3f3f3; /*#d1d9e0;*/
32
+ line-height: 16px;
33
+ font-weight: 400;
34
+ font-family: var(--theme-text-font);
35
+ color: var(--theme-input-text-font);
36
+ }
37
+ input:focus, textarea:focus, select:focus {
38
+ outline: var(--theme-input-outline, 2px solid #3B94FC);
39
+ outline-offset: var(--theme-input-outline-offset, 0px);
34
40
  }
35
41
  textarea {
36
42
  padding: 12px 14px;
37
43
  max-width: calc(100% - 28px);
38
44
  min-height: 100px;
39
45
  }
40
- select {
41
- font-family: var(--theme-text-font);
42
- background-color: #f5f5fb;
43
- border: none;
44
- border-radius: 6px;
45
- padding: 7px 14px;
46
- font-size: 14px;
47
- line-height: 14px;
48
- font-weight: 500;
49
- }
50
46
  option {
51
47
  font-family: var(--theme-text-font);
48
+ color: var(--theme-input-text-font);
52
49
  padding: 7px 14px;
53
50
  font-size: 14px;
54
51
  line-height: 14px;
55
- font-weight: 500;
56
52
  }
57
53
 
58
54
  </style>
@@ -1,8 +1,6 @@
1
1
  <script>
2
2
  export let name;
3
3
  export let value;
4
-
5
- console.log(value);
6
4
  </script>
7
5
 
8
6
  <div class="selector">
@@ -1,8 +1,6 @@
1
1
  <script>
2
2
  export let tabs;
3
3
  export let currentTab;
4
-
5
- console.log(currentTab);
6
4
  </script>
7
5
 
8
6
  <aside class="horizontal-navbar">
@@ -0,0 +1,81 @@
1
+ <script>
2
+ // @ts-nocheck
3
+ import UserSelect from "./UserSelect.svelte";
4
+ import UserPicture from './UserPicture.svelte';
5
+
6
+ let user;
7
+ export let name;
8
+ export const value = user;
9
+
10
+ function handleRemove() {
11
+ user = undefined;
12
+ }
13
+
14
+ </script>
15
+
16
+ <div id="single-select-wrapper" name={name} >
17
+ {#if !user}
18
+ <UserSelect uri={'/user'} bind:selected={user} ></UserSelect>
19
+ {:else}
20
+ <div>
21
+ <UserPicture size={24} user={user}></UserPicture>
22
+ <span>{user.firstname} {user.lastname}</span>
23
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
24
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
25
+ <div on:click={handleRemove}>+</div>
26
+ </div>
27
+ {/if}
28
+ </div>
29
+
30
+ <style>
31
+ #single-select-wrapper {
32
+ display: flex;
33
+ width: 100%;
34
+ }
35
+ #single-select-wrapper > div {
36
+ display: flex;
37
+ align-items: center;
38
+ background-color: var(--theme-input-bg-color, #ebebed);
39
+ height: var(--theme-input-height, 40px);
40
+ border: var(--theme-input-border, none);
41
+ border-radius: 8px;
42
+ padding: 0px 16px;
43
+ font-size: 14px;
44
+ line-height: 16px;
45
+ font-weight: 400;
46
+ font-family: var(--theme-text-font);
47
+ color: var(--theme-input-text-font);
48
+ flex: 1;
49
+ }
50
+ #single-select-wrapper > div > span {
51
+ font-size: 14px;
52
+ line-height: 16px;
53
+ font-weight: 400;
54
+ font-family: var(--theme-text-font);
55
+ color: var(--theme-input-text-color);
56
+ overflow: hidden;
57
+ white-space: nowrap;
58
+ text-overflow: ellipsis;
59
+ margin-left: 8px;
60
+ flex: 1;
61
+ }
62
+ #single-select-wrapper > div > div:nth-of-type(2) {
63
+ cursor: pointer;
64
+ margin-left: 8px;
65
+ height: 16px;
66
+ width: 16px;
67
+ min-width: 16px;
68
+ background-color: #ddd;
69
+ border-radius: 20px;
70
+ font-weight: 600;
71
+ text-align: center;
72
+ line-height: 16px;
73
+ color: #777;
74
+ transform: rotate(45deg);
75
+ transition: all ease-in-out 0.14s;
76
+ }
77
+ #single-select-wrapper > div > div:nth-of-type(2):hover {
78
+ background-color: #ccc;
79
+ }
80
+
81
+ </style>
@@ -17,6 +17,10 @@
17
17
  ]
18
18
 
19
19
  //let firstname = (user.)
20
+ if (!user.firstname) {
21
+ user.firstname = user.name;
22
+ user.lastname = "";
23
+ }
20
24
  let colorId = (user.firstname.charCodeAt(0) + user.lastname.charCodeAt(0)) % colors.length;
21
25
  </script>
22
26
 
@@ -1,117 +1,147 @@
1
1
  <script>
2
2
  // @ts-nocheck
3
- import { createEventDispatcher } from 'svelte';
3
+ import { onMount } from 'svelte';
4
+ import Portal from 'svelte-portal';
5
+ import UserPicture from './UserPicture.svelte';
4
6
  import {clickOutside} from './../utils/clickOutside.js';
5
- import UserPicture from './UserPicture.svelte';
6
7
 
7
- const dispatch = createEventDispatcher();
8
+ export let uri = '/user';
9
+ export let selected;
8
10
 
9
- function handleUserSelection(uid) {
10
- isOpen = false;
11
- inputFilter = null;
12
- filteredUsers = users;
11
+ let users = [];
12
+ let waiting = false;
13
+ let open = false;
14
+ let search = "";
13
15
 
14
- dispatch('selectUser', {
15
- id: uid
16
- });
17
- }
16
+ let dropdownEl;
17
+ let coords = { top: 0, left: 0, width: 0 };
18
+
19
+ async function handleFilter() {
20
+ waiting = true;
18
21
 
19
- function handleFilter() {
20
- filteredUsers = users.filter((user) => {
21
- let str = (user.firstname + ' ' + user.lastname).normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
22
- const inputStr = inputFilter.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
23
- return (typeFilter == null || user.type.value == typeFilter) && str.includes(inputStr);
22
+ const response = await fetch(`${uri}?contains=${search}&limit=100&page=1`, {
23
+ method: 'GET',
24
+ headers: { 'Content-Type': 'application/json' }
24
25
  });
25
- }
26
26
 
27
- export let users = []
28
- export let typeFilter = null;
27
+ const resBody = await response.json();
28
+ users = resBody.data;
29
29
 
30
- let inputFilter;
31
- let filteredUsers = users.filter((user) => {
32
- return (typeFilter == null || user.type.value == typeFilter);
30
+ waiting = false;
31
+ }
32
+
33
+ onMount(() => {
34
+ handleFilter();
33
35
  });
34
- let isOpen = false;
36
+
37
+ function openDropdown() {
38
+ const rect = dropdownEl.getBoundingClientRect();
39
+ coords = { top: rect.bottom, left: rect.left, width: rect.width };
40
+ open = !open;
41
+ }
42
+
43
+ function selectUser(user) {
44
+ selected = user;
45
+ open = false;
46
+ search = "";
47
+ }
48
+
35
49
  </script>
36
50
 
37
- <div id="user-select-wrapper" use:clickOutside on:click_outside={() => {isOpen = false}}>
38
- <div>
39
- <input type="text" bind:value={inputFilter} on:keyup={handleFilter} on:focus={() => (isOpen = !isOpen)} placeholder="Ajouter un utilisateur"/>
40
- </div>
41
- {#if isOpen}
42
- <div>
43
- {#each filteredUsers as user}
44
- <!-- svelte-ignore a11y-click-events-have-key-events -->
45
- <!-- svelte-ignore a11y-no-static-element-interactions -->
46
- <div on:click|stopPropagation|preventDefault={handleUserSelection(user.id)}>
51
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
52
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
53
+ <div class="dropdown {open ? 'open' : ''}" bind:this={dropdownEl} use:clickOutside on:click_outside={() => {open = false}}
54
+ on:click|preventDefault|stopPropagation={openDropdown}>
55
+ <input on:keyup={handleFilter} bind:value={search}
56
+ class="search-input" type="text" placeholder="Rechercher..." />
57
+
58
+ <!-- Liste déroulante -->
59
+ {#if open}
60
+ <Portal target="body" >
61
+ <div class="list" style="position: absolute; top:{coords.top}px; left:{coords.left}px; width: {coords.width}px;" >
62
+ <!-- Options -->
63
+ {#each users as user}
64
+ <div class="option" on:click={() => selectUser(user)}>
47
65
  <UserPicture user={user} size={24}></UserPicture>
48
66
  <span>{user.firstname} {user.lastname}</span>
49
67
  </div>
68
+ {:else}
69
+ <div class="option"><span>Aucun résultat</span></div>
50
70
  {/each}
51
71
  </div>
72
+ </Portal>
52
73
  {/if}
53
74
  </div>
54
75
 
55
76
  <style>
56
- input {
57
- border: none
58
- }
59
- #user-select-wrapper {
60
- background-color: #f5f5fb;
61
- border-radius: 6px;
62
- padding: 2px 0px;
63
- transition: 0.3s ease-in-out all;
64
- width: 220px;
77
+ .dropdown {
65
78
  position: relative;
66
- z-index: 100;
67
- }
68
- #user-select-wrapper > div:nth-of-type(1) {
69
- background-image: url('/icons/icon-user-add.svg');
70
- background-size: 20px auto;
71
- background-repeat: no-repeat;
72
- background-position: left center;
73
- margin-right: 6px;
74
- margin-left: 12px;
75
- padding-left: 24px;
76
- }
77
- #user-select-wrapper > div:nth-of-type(1) > input{
78
- background-color: #f5f5fb;
79
- border-radius: 0px;
80
- padding: 4px 6px;
81
- height: 20px;
79
+ display: flex;
80
+ background-color: var(--theme-input-bg-color, #ebebed);
81
+ height: var(--theme-input-height, 40px);
82
+ border: var(--theme-input-border, none);
83
+ border-radius: 8px;
84
+ padding: 0px 16px;
82
85
  font-size: 14px;
83
- font-weight: 500;
84
- color: #333;
85
- cursor: pointer;
86
- width: calc(100% - 12px);
86
+ line-height: 16px;
87
+ font-weight: 400;
88
+ font-family: var(--theme-text-font);
89
+ color: var(--theme-input-text-font);
90
+ flex: 1;
87
91
  }
88
- #user-select-wrapper > div:nth-of-type(1) > input:focus{
89
- cursor: initial;
92
+ .dropdown.open {
93
+ border-bottom-left-radius: 0px;
94
+ border-bottom-right-radius: 0px;
90
95
  }
91
- #user-select-wrapper > div:nth-of-type(1) > input::placeholder {
92
- color: #777;
96
+ .search-input {
97
+ background-color: transparent;
98
+ height: 40px;
99
+ border: none;
100
+ border-radius: 8px;
101
+ cursor: pointer;
102
+ padding: 0px;
103
+ font-size: 14px;
104
+ line-height: 16px;
105
+ font-weight: 400;
106
+ font-family: var(--theme-text-font);
107
+ color: var(--theme-input-text-font);
108
+ flex: 1;
109
+ outline: none;
93
110
  }
94
- #user-select-wrapper > div:nth-of-type(2) {
95
- display: flex;
96
- flex-direction: column;
97
- padding-bottom: 8px;
98
- background-color: #f5f5fb;
99
- width: 220px;
100
- z-index: 1000;
111
+
112
+ .list {
113
+ position: absolute;
114
+ top: 100%;
115
+ left: 0;
116
+ right: 0;
117
+ background: var(--theme-input-bg-highlight, #ebebed);
118
+ border-radius: 8px;
119
+ border-top-left-radius: 0px;
120
+ border-top-right-radius: 0px;
121
+ padding: 4px 0px;
122
+ max-height: 220px;
123
+ overflow-y: auto;
124
+ z-index: 9999;
101
125
  }
102
- #user-select-wrapper > div:nth-of-type(2) > div {
103
- padding: 4px 12px;
104
- flex: 1;
126
+
127
+ .option {
105
128
  display: flex;
106
129
  align-items: center;
107
- }
108
- #user-select-wrapper > div:nth-of-type(2) > div > span {
109
- color: #333;
110
- font-weight: 600;
130
+ padding: 8px 12px;
131
+ gap: 8px;
111
132
  cursor: pointer;
112
- margin-left: 8px;
113
133
  }
114
- #user-select-wrapper > div:nth-of-type(2) > div:hover {
115
- background-color: #eee;
134
+ .option > span {
135
+ font-size: 14px;
136
+ line-height: 16px;
137
+ font-weight: 400;
138
+ font-family: var(--theme-text-font);
139
+ color: var(--theme-input-text-color);
140
+ overflow: hidden;
141
+ white-space: nowrap;
142
+ text-overflow: ellipsis;
143
+ }
144
+ .option:hover {
145
+ background: var(--theme-input-bg-hover);
116
146
  }
117
147
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iconograph-ui",
3
- "version": "1.2.13",
3
+ "version": "1.2.15",
4
4
  "description": "A Svelte Kit components library",
5
5
  "main": "./index.js",
6
6
  "svelte": "./index.js",
@@ -28,5 +28,8 @@
28
28
  "homepage": "https://github.com/asso-parabole/iconograph-ui#readme",
29
29
  "dependencies": {
30
30
  "svelte": "^5.38.1"
31
+ },
32
+ "peerDependencies": {
33
+ "svelte-portal": "2.2.1"
31
34
  }
32
35
  }
@@ -1,90 +0,0 @@
1
- <script>
2
- // @ts-nocheck
3
- import { createEventDispatcher } from 'svelte';
4
- import UserSelect from "./UserSelect.svelte";
5
- import UserPicture from './UserPicture.svelte';
6
-
7
- const dispatch = createEventDispatcher();
8
-
9
- export let users = [];
10
- export let typeFilter = null;
11
- export let selected = false;
12
- export let selectedUser = null;
13
-
14
- function handleUserSelection(e) {
15
- selectedUser = users.filter((user) => {
16
- return user.id == e.detail.id;
17
- }).at(-1);
18
- selected = true;
19
-
20
- dispatch('selectUser', {
21
- id: e.detail.id
22
- });
23
- }
24
-
25
- function handleRemove() {
26
- selected = false;
27
- selectedUser = null;
28
-
29
- dispatch('selectUser', {
30
- id: null
31
- });
32
- }
33
- </script>
34
-
35
- <div id="single-select-wrapper">
36
- {#if !selected}
37
- <UserSelect on:selectUser={handleUserSelection} users={users} typeFilter={typeFilter}></UserSelect>
38
- {:else}
39
- <div>
40
- <UserPicture size={24} user={selectedUser}></UserPicture>
41
- <span>{selectedUser.firstname} {selectedUser.lastname}</span>
42
- <div on:click={handleRemove}>+</div>
43
- </div>
44
- {/if}
45
- </div>
46
-
47
- <style>
48
- #single-select-wrapper {
49
- display: flex;
50
- position: relative;
51
- z-index: 1000;
52
- }
53
- #single-select-wrapper > div {
54
- background-color: #f5f5fb;
55
- border-radius: 6px;
56
- width: inherit;
57
- transition: 0.3s ease-in-out all;
58
- display: flex;
59
- height: 34px;
60
- align-items: center;
61
- padding-left: 12px;
62
- }
63
- #single-select-wrapper > div > span {
64
- color: #333;
65
- font-weight: 600;
66
- max-width: 125px;
67
- flex: 1;
68
- margin-left: 8px;
69
- margin-right: 8px;
70
- overflow: hidden;
71
- white-space: nowrap;
72
- text-overflow: ellipsis;
73
- }
74
- #single-select-wrapper > div > div:nth-of-type(2) {
75
- cursor: pointer;
76
- margin-right: 12px;
77
- margin-left: 8px;
78
- height: 16px;
79
- width: 16px;
80
- min-width: 16px;
81
- background-color: #ddd;
82
- border-radius: 20px;
83
- font-weight: 600;
84
- text-align: center;
85
- line-height: 16px;
86
- color: #777;
87
- transform: rotate(45deg);
88
- }
89
-
90
- </style>