@supersoniks/concorde 3.2.2 → 3.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supersoniks/concorde",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "",
@@ -99,8 +99,13 @@ export default class Icons {
99
99
  * MiniCache de session
100
100
  */
101
101
  if (iconCache.icons[url]) {
102
- libIcons[libIconsKey] = iconCache.icons[url];
103
- return unsafeHTML(iconCache.icons[url]);
102
+ const cached = iconCache.icons[url];
103
+ const isSvgCached = /^\s*<svg[\s>]/i.test(cached || "");
104
+ if (isSvgCached) {
105
+ libIcons[libIconsKey] = cached;
106
+ return unsafeHTML(cached);
107
+ }
108
+ delete iconCache.icons[url];
104
109
  }
105
110
  /**
106
111
  * on utilise une promise mutualisée pour ne pas faire plusieurs appels concurents d'une même icone
@@ -128,11 +133,11 @@ export default class Icons {
128
133
  const isSvg = /^\s*<svg[\s>]/i.test(text);
129
134
  resolve(isSvg ? text : "");
130
135
  } catch (e) {
131
- resolve(null);
136
+ resolve("");
132
137
  }
133
138
  } catch (error) {
134
139
  log("concorde icon loading error", params);
135
- resolve(null);
140
+ resolve("");
136
141
  }
137
142
  });
138
143
  loadingGetPromises.set(url, promise as Promise<string>);
@@ -144,13 +149,16 @@ export default class Icons {
144
149
  loadingGetPromises.delete(url);
145
150
 
146
151
  libIcons[libIconsKey] = result || "";
147
- iconCache.icons[url] = result || "";
152
+ if (result && /^\s*<svg[\s>]/i.test(result)) {
153
+ iconCache.icons[url] = result;
154
+ iconCache.names.push(url);
155
+ }
148
156
  if (iconCache.names.length > iconCacheMaxSize) {
149
157
  const key = iconCache.names.shift();
150
158
  delete iconCache.icons[key];
151
159
  }
152
160
  sessionStorage.setItem("sonicIconsCache", JSON.stringify(iconCache));
153
- return unsafeHTML(result);
161
+ return result ? unsafeHTML(result) : "";
154
162
  }
155
163
  /**
156
164
  * svgs "locaux"
@@ -264,6 +264,36 @@
264
264
  <sonic-icon library="iconoir" name="clock-outline" slot="prefix"></sonic-icon>
265
265
  History
266
266
  </sonic-menu-item>
267
+ <sonic-menu-item >
268
+ <sonic-icon library="iconoir" name="bag" slot="prefix"></sonic-icon>
269
+ Orders
270
+ </sonic-menu-item> <sonic-menu-item variant="ghost">
271
+ <sonic-icon library="iconoir" name="home" slot="prefix"></sonic-icon>
272
+ Home
273
+ </sonic-menu-item>
274
+ <sonic-menu-item>
275
+ <sonic-icon library="iconoir" name="user" slot="prefix"></sonic-icon>
276
+ Profile
277
+ </sonic-menu-item>
278
+ <sonic-menu-item >
279
+ <sonic-icon library="iconoir" name="clock-outline" slot="prefix"></sonic-icon>
280
+ History
281
+ </sonic-menu-item>
282
+ <sonic-menu-item >
283
+ <sonic-icon library="iconoir" name="bag" slot="prefix"></sonic-icon>
284
+ Orders
285
+ </sonic-menu-item> <sonic-menu-item variant="ghost">
286
+ <sonic-icon library="iconoir" name="home" slot="prefix"></sonic-icon>
287
+ Home
288
+ </sonic-menu-item>
289
+ <sonic-menu-item>
290
+ <sonic-icon library="iconoir" name="user" slot="prefix"></sonic-icon>
291
+ Profile
292
+ </sonic-menu-item>
293
+ <sonic-menu-item >
294
+ <sonic-icon library="iconoir" name="clock-outline" slot="prefix"></sonic-icon>
295
+ History
296
+ </sonic-menu-item>
267
297
  <sonic-menu-item >
268
298
  <sonic-icon library="iconoir" name="bag" slot="prefix"></sonic-icon>
269
299
  Orders
@@ -276,11 +306,22 @@
276
306
  <sonic-icon library="iconoir" name="chat-bubble" slot="prefix"></sonic-icon>
277
307
  Messages
278
308
  </sonic-menu-item>
279
- <sonic-menu-item type="danger">
280
- <sonic-icon library="iconoir" name="log-out" slot="prefix"></sonic-icon>
281
- Log out
282
- </sonic-menu-item>
283
- </sonic-menu>
309
+ <sonic-menu slot="more">
310
+ <sonic-menu-item >
311
+ <sonic-icon library="iconoir" name="settings" slot="prefix"></sonic-icon>
312
+ Settings
313
+ </sonic-menu-item>
314
+ <sonic-menu-item >
315
+ <sonic-icon library="iconoir" name="chat-bubble" slot="prefix"></sonic-icon>
316
+ Messages
317
+ </sonic-menu-item>
318
+ <sonic-divider></sonic-divider>
319
+ <sonic-menu-item type="danger">
320
+ <sonic-icon library="iconoir" name="log-out" slot="prefix"></sonic-icon>
321
+ Log out
322
+ </sonic-menu-item>
323
+ </sonic-menu>
324
+
284
325
  </template>
285
326
  </sonic-code>
286
327
 
@@ -23,9 +23,8 @@ export class MenuItems extends LitElement {
23
23
 
24
24
  :host > menu {
25
25
  display: flex;
26
- border-radius: min(calc(var(--sc-btn-rounded) * 2), 0.4em);
26
+ padding: 0;
27
27
  margin: 0;
28
- padding: 0.35em;
29
28
  }
30
29
 
31
30
  .hidden {
@@ -33,26 +32,34 @@ export class MenuItems extends LitElement {
33
32
  }
34
33
 
35
34
  /* SCROLLABLE*/
36
- :host([scrollable]) {
35
+ :host([scrollable]) #menu-content {
37
36
  scrollbar-width: none;
37
+ max-width: 100%;
38
38
  -ms-overflow-style: none;
39
- }
40
- :host([scrollable]) menu > * {
41
39
  scroll-snap-align: start;
42
40
  white-space: nowrap;
41
+ display: flex;
42
+ gap: var(--sc-menu-gap);
43
+ border-radius: min(calc(var(--sc-btn-rounded) * 2), 0.4em);
44
+ margin: 0;
45
+ padding: 0.35em;
46
+ transition: mask-image 0.15s linear;
43
47
  }
44
- :host([scrollable][direction="row"]) {
48
+
49
+ :host([scrollable][direction="row"]) #menu-content {
45
50
  overflow-x: scroll;
51
+ scroll-snap-align: start;
46
52
  scroll-snap-type: x mandatory;
47
53
  }
48
- :host([scrollable][direction="column"]) {
54
+ :host([scrollable][direction="column"]) #menu-content {
49
55
  overflow-y: scroll;
56
+ scroll-snap-align: start;
50
57
  scroll-snap-type: y mandatory;
51
58
  }
52
59
  :host([scrollable])::-webkit-scrollbar {
53
60
  display: none !important;
54
61
  }
55
- :host([scrollable][direction="row"].shadow-right) {
62
+ :host([scrollable][direction="row"].shadow-right) #menu-content {
56
63
  -webkit-mask-image: linear-gradient(
57
64
  to left,
58
65
  rgba(0, 0, 0, 0),
@@ -64,7 +71,7 @@ export class MenuItems extends LitElement {
64
71
  rgba(0, 0, 0, 1) 10%
65
72
  );
66
73
  }
67
- :host([scrollable][direction="row"].shadow-left) {
74
+ :host([scrollable][direction="row"].shadow-left) #menu-content {
68
75
  -webkit-mask-image: linear-gradient(
69
76
  to right,
70
77
  rgba(0, 0, 0, 0),
@@ -76,7 +83,8 @@ export class MenuItems extends LitElement {
76
83
  rgba(0, 0, 0, 1) 10%
77
84
  );
78
85
  }
79
- :host([scrollable][direction="row"].shadow-left.shadow-right) {
86
+ :host([scrollable][direction="row"].shadow-left.shadow-right)
87
+ #menu-content {
80
88
  -webkit-mask-image: linear-gradient(
81
89
  to right,
82
90
  rgba(0, 0, 0, 0) 0%,
@@ -92,7 +100,7 @@ export class MenuItems extends LitElement {
92
100
  rgba(0, 0, 0, 0) 100%
93
101
  );
94
102
  }
95
- :host([scrollable][direction="column"].shadow-top) {
103
+ :host([scrollable][direction="column"].shadow-top) #menu-content {
96
104
  -webkit-mask-image: linear-gradient(
97
105
  to bottom,
98
106
  rgba(0, 0, 0, 0),
@@ -104,7 +112,7 @@ export class MenuItems extends LitElement {
104
112
  rgba(0, 0, 0, 1) 10%
105
113
  );
106
114
  }
107
- :host([scrollable][direction="column"].shadow-bottom) {
115
+ :host([scrollable][direction="column"].shadow-bottom) #menu-content {
108
116
  -webkit-mask-image: linear-gradient(
109
117
  to top,
110
118
  rgba(0, 0, 0, 0),
@@ -116,7 +124,8 @@ export class MenuItems extends LitElement {
116
124
  rgba(0, 0, 0, 1) 10%
117
125
  );
118
126
  }
119
- :host([scrollable][direction="column"].shadow-top.shadow-bottom) {
127
+ :host([scrollable][direction="column"].shadow-top.shadow-bottom)
128
+ #menu-content {
120
129
  -webkit-mask-image: linear-gradient(
121
130
  to top,
122
131
  rgba(0, 0, 0, 0) 0%,
@@ -162,6 +171,7 @@ export class MenuItems extends LitElement {
162
171
  @property({ type: Boolean }) scrollable = false;
163
172
 
164
173
  observer: ResizeObserver | null = null;
174
+ attributeObserver: MutationObserver | null = null;
165
175
 
166
176
  /**
167
177
  * Propriété min-width du bouton
@@ -169,8 +179,9 @@ export class MenuItems extends LitElement {
169
179
  @property({ type: String }) minWidth = "0";
170
180
 
171
181
  @query("menu") menu!: HTMLElement;
182
+ @query("#menu-content") menuContent!: HTMLElement;
172
183
 
173
- @queryAssignedElements({ selector: "sonic-menu-item" })
184
+ @queryAssignedElements({ selector: "*" })
174
185
  menuChildren!: Array<HTMLElement>;
175
186
 
176
187
  @queryAssignedElements({ slot: "more", selector: "*" })
@@ -180,6 +191,10 @@ export class MenuItems extends LitElement {
180
191
  checkIfMore() {
181
192
  this.hasMoreElements = !!this.moreElements?.length;
182
193
  }
194
+ moreSlotChange() {
195
+ this.checkIfMore();
196
+ this.updateIsScollable();
197
+ }
183
198
 
184
199
  updated(_changedProperties: PropertyValues): void {
185
200
  const moreBtn = this.querySelector(".more-btn");
@@ -201,24 +216,77 @@ export class MenuItems extends LitElement {
201
216
  mainSlotChange() {
202
217
  this.setChildrenSize(this.menuChildren);
203
218
  this.updateIsScollable();
219
+ this.updateScrollPosition();
220
+ this.observeMenuItemsAttributes();
221
+ }
222
+
223
+ observeMenuItemsAttributes() {
224
+ // Déconnecter l'ancien observer si existant
225
+ this.attributeObserver?.disconnect();
226
+
227
+ // Créer un nouvel observer pour surveiller les changements d'attribut 'active'
228
+ this.attributeObserver = new MutationObserver(() => {
229
+ this.updateScrollPosition();
230
+ });
231
+
232
+ // Observer chaque menu-item
233
+ this.menuChildren.forEach((item) => {
234
+ this.attributeObserver!.observe(item, {
235
+ attributes: true,
236
+ attributeFilter: ["active"],
237
+ });
238
+ });
239
+ }
240
+
241
+ updateScrollPosition() {
242
+ // Si on est en mode scrollable et qu'il y a exactement un seul menu-item actif
243
+ if (this.scrollable) {
244
+ const activeItems = this.menuChildren.filter(
245
+ (item) =>
246
+ item.hasAttribute("active") && item.getAttribute("active") !== "false"
247
+ );
248
+
249
+ if (activeItems.length === 1) {
250
+ requestAnimationFrame(() => {
251
+ activeItems[0].scrollIntoView({
252
+ behavior: "smooth",
253
+ block: "nearest",
254
+ inline: "center",
255
+ });
256
+ });
257
+ }
258
+ }
204
259
  }
205
260
 
206
261
  connectedCallback(): void {
207
262
  this.observer = new ResizeObserver(this.updateIsScollable);
208
263
  // observe if menu elements are overflowing and initiate scrollable
209
264
  this.observer.observe(this);
265
+
210
266
  super.connectedCallback();
211
267
  }
212
268
 
269
+ protected firstUpdated(_changedProperties: PropertyValues): void {
270
+ this.menuContent.addEventListener("scrollend", this.handleScrollEnd);
271
+ }
272
+
273
+ // Écouter l'événement scrollend pour mettre à jour les ombres après le scroll
274
+ handleScrollEnd = () => {
275
+ this.setScrollShadow(this.menuContent, this.direction);
276
+ };
277
+
213
278
  disconnectedCallback(): void {
214
279
  this.observer?.disconnect();
280
+ this.attributeObserver?.disconnect();
281
+ this.menuContent.removeEventListener("scrollend", this.handleScrollEnd);
282
+
215
283
  super.disconnectedCallback();
216
284
  }
217
285
 
218
286
  updateIsScollable = () => {
219
287
  if (this.scrollable) {
220
288
  this.initScrollable();
221
- this.setScrollShadow(this, this.direction);
289
+ this.setScrollShadow(this.menuContent, this.direction);
222
290
  }
223
291
  };
224
292
 
@@ -231,8 +299,9 @@ export class MenuItems extends LitElement {
231
299
  this.addEventListener("mousedown", (e) => {
232
300
  isDown = true;
233
301
  this.classList.add("active");
234
- startX = e.pageX - this.offsetLeft;
235
- scrollLeft = this.scrollLeft;
302
+
303
+ startX = e.pageX - this.menuContent.offsetLeft;
304
+ scrollLeft = this.menuContent.scrollLeft;
236
305
  });
237
306
  this.addEventListener("mouseleave", () => {
238
307
  isDown = false;
@@ -245,16 +314,16 @@ export class MenuItems extends LitElement {
245
314
  this.addEventListener("mousemove", (e) => {
246
315
  if (!isDown) return;
247
316
  e.preventDefault();
248
- const x = e.pageX - this.offsetLeft;
317
+ const x = e.pageX - this.menuContent.offsetLeft;
249
318
  const walk = (x - startX) * 1.5; //scroll-fast
250
- this.scrollLeft = scrollLeft - walk;
251
- this.setScrollShadow(this, this.direction);
319
+ this.menuContent.scrollLeft = scrollLeft - walk;
320
+ this.setScrollShadow(this.menuContent, this.direction);
252
321
  });
253
322
  this.addEventListener("scroll", (e) => {
254
323
  e.preventDefault();
255
324
  // const delta = Math.sign(e.deltaY);
256
325
  // this.scrollLeft += delta * 50;
257
- this.setScrollShadow(this, this.direction);
326
+ this.setScrollShadow(this.menuContent, this.direction);
258
327
  });
259
328
  }
260
329
  }
@@ -331,7 +400,7 @@ export class MenuItems extends LitElement {
331
400
  class="shadowable"
332
401
  style=${styleMap(menuStyles)}
333
402
  >
334
- <slot @slotchange=${this.mainSlotChange}></slot>
403
+ <slot @slotchange=${this.mainSlotChange} id="menu-content"></slot>
335
404
  <sonic-pop
336
405
  style=${styleMap(popStyles)}
337
406
  class=${!this.hasMoreElements ? "hidden" : ""}
@@ -347,7 +416,11 @@ export class MenuItems extends LitElement {
347
416
  name=${isMenuRow ? "more-vert" : "more-horiz"}
348
417
  ></sonic-icon>
349
418
  </sonic-menu-item>
350
- <slot name="more" @slotchange=${this.checkIfMore} slot="content"></slot>
419
+ <slot
420
+ name="more"
421
+ @slotchange=${this.moreSlotChange}
422
+ slot="content"
423
+ ></slot>
351
424
  </sonic-pop>
352
425
  </menu>`;
353
426
  }
@@ -125,12 +125,12 @@ export class Modal extends Subscriber(LitElement) {
125
125
  /* Layout des éléments slottés */
126
126
  ::slotted(sonic-modal-title),
127
127
  sonic-modal-title {
128
- margin-bottom: 1.75rem;
128
+ margin-bottom: 1.2rem;
129
129
  }
130
130
  ::slotted(sonic-modal-subtitle),
131
131
  sonic-modal-subtitle {
132
- margin-bottom: 1.75rem;
133
- margin-top: -1.25rem;
132
+ margin-bottom: 1.2rem;
133
+ margin-top: -1rem;
134
134
  }
135
135
 
136
136
  :host([align="left"]) ::slotted(sonic-modal-title),
@@ -331,7 +331,7 @@ export class Modal extends Subscriber(LitElement) {
331
331
  maxHeight: this.maxHeight,
332
332
  width: this.width,
333
333
  height: this.height,
334
- pointerEvents: this._animationState === "visible" ? "auto" : "none",
334
+ pointerEvents: this._animationState !== "hidden" ? "auto" : "none",
335
335
  };
336
336
 
337
337
  const overlayStyles = {