@supersoniks/concorde 3.2.2 → 3.2.4

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.4",
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,36 @@ export class MenuItems extends LitElement {
33
32
  }
34
33
 
35
34
  /* SCROLLABLE*/
36
- :host([scrollable]) {
35
+ #menu-content {
36
+ display: flex;
37
+ padding: 0.35em;
38
+ margin: 0;
39
+ }
40
+
41
+ :host([scrollable]) #menu-content {
37
42
  scrollbar-width: none;
43
+ max-width: 100%;
38
44
  -ms-overflow-style: none;
39
- }
40
- :host([scrollable]) menu > * {
41
45
  scroll-snap-align: start;
42
46
  white-space: nowrap;
47
+ border-radius: min(calc(var(--sc-btn-rounded) * 2), 0.4em);
48
+ transition: mask-image 0.15s linear;
43
49
  }
44
- :host([scrollable][direction="row"]) {
50
+
51
+ :host([scrollable][direction="row"]) #menu-content {
45
52
  overflow-x: scroll;
53
+ scroll-snap-align: start;
46
54
  scroll-snap-type: x mandatory;
47
55
  }
48
- :host([scrollable][direction="column"]) {
56
+ :host([scrollable][direction="column"]) #menu-content {
49
57
  overflow-y: scroll;
58
+ scroll-snap-align: start;
50
59
  scroll-snap-type: y mandatory;
51
60
  }
52
61
  :host([scrollable])::-webkit-scrollbar {
53
62
  display: none !important;
54
63
  }
55
- :host([scrollable][direction="row"].shadow-right) {
64
+ :host([scrollable][direction="row"].shadow-right) #menu-content {
56
65
  -webkit-mask-image: linear-gradient(
57
66
  to left,
58
67
  rgba(0, 0, 0, 0),
@@ -64,7 +73,7 @@ export class MenuItems extends LitElement {
64
73
  rgba(0, 0, 0, 1) 10%
65
74
  );
66
75
  }
67
- :host([scrollable][direction="row"].shadow-left) {
76
+ :host([scrollable][direction="row"].shadow-left) #menu-content {
68
77
  -webkit-mask-image: linear-gradient(
69
78
  to right,
70
79
  rgba(0, 0, 0, 0),
@@ -76,7 +85,8 @@ export class MenuItems extends LitElement {
76
85
  rgba(0, 0, 0, 1) 10%
77
86
  );
78
87
  }
79
- :host([scrollable][direction="row"].shadow-left.shadow-right) {
88
+ :host([scrollable][direction="row"].shadow-left.shadow-right)
89
+ #menu-content {
80
90
  -webkit-mask-image: linear-gradient(
81
91
  to right,
82
92
  rgba(0, 0, 0, 0) 0%,
@@ -92,7 +102,7 @@ export class MenuItems extends LitElement {
92
102
  rgba(0, 0, 0, 0) 100%
93
103
  );
94
104
  }
95
- :host([scrollable][direction="column"].shadow-top) {
105
+ :host([scrollable][direction="column"].shadow-top) #menu-content {
96
106
  -webkit-mask-image: linear-gradient(
97
107
  to bottom,
98
108
  rgba(0, 0, 0, 0),
@@ -104,7 +114,7 @@ export class MenuItems extends LitElement {
104
114
  rgba(0, 0, 0, 1) 10%
105
115
  );
106
116
  }
107
- :host([scrollable][direction="column"].shadow-bottom) {
117
+ :host([scrollable][direction="column"].shadow-bottom) #menu-content {
108
118
  -webkit-mask-image: linear-gradient(
109
119
  to top,
110
120
  rgba(0, 0, 0, 0),
@@ -116,7 +126,8 @@ export class MenuItems extends LitElement {
116
126
  rgba(0, 0, 0, 1) 10%
117
127
  );
118
128
  }
119
- :host([scrollable][direction="column"].shadow-top.shadow-bottom) {
129
+ :host([scrollable][direction="column"].shadow-top.shadow-bottom)
130
+ #menu-content {
120
131
  -webkit-mask-image: linear-gradient(
121
132
  to top,
122
133
  rgba(0, 0, 0, 0) 0%,
@@ -162,6 +173,7 @@ export class MenuItems extends LitElement {
162
173
  @property({ type: Boolean }) scrollable = false;
163
174
 
164
175
  observer: ResizeObserver | null = null;
176
+ attributeObserver: MutationObserver | null = null;
165
177
 
166
178
  /**
167
179
  * Propriété min-width du bouton
@@ -169,8 +181,9 @@ export class MenuItems extends LitElement {
169
181
  @property({ type: String }) minWidth = "0";
170
182
 
171
183
  @query("menu") menu!: HTMLElement;
184
+ @query("#menu-content") menuContent!: HTMLElement;
172
185
 
173
- @queryAssignedElements({ selector: "sonic-menu-item" })
186
+ @queryAssignedElements({ selector: "*" })
174
187
  menuChildren!: Array<HTMLElement>;
175
188
 
176
189
  @queryAssignedElements({ slot: "more", selector: "*" })
@@ -180,45 +193,103 @@ export class MenuItems extends LitElement {
180
193
  checkIfMore() {
181
194
  this.hasMoreElements = !!this.moreElements?.length;
182
195
  }
196
+ moreSlotChange() {
197
+ this.checkIfMore();
198
+ this.updateIsScollable();
199
+ }
183
200
 
184
201
  updated(_changedProperties: PropertyValues): void {
185
202
  const moreBtn = this.querySelector(".more-btn");
186
203
  if (this.size && moreBtn) {
187
204
  moreBtn.setAttribute("size", this.size);
188
205
  }
206
+ super.updated(_changedProperties);
207
+ }
189
208
 
190
- const dividers = this.querySelectorAll("sonic-divider");
191
-
192
- dividers.forEach((elt) => {
193
- if (!elt.hasAttribute("size")) {
194
- elt.setAttribute("size", "xs");
195
- }
209
+ setDividersSize(assignedElements: Array<HTMLElement>) {
210
+ assignedElements.forEach((elt) => {
211
+ elt.setAttribute("size", "sm");
212
+ this.direction == "row"
213
+ ? elt.style.setProperty("margin", "0 .1rem ")
214
+ : elt.style.setProperty("margin", " 0.1rem 0");
196
215
  });
197
-
198
- super.updated(_changedProperties);
199
216
  }
200
217
 
201
218
  mainSlotChange() {
202
219
  this.setChildrenSize(this.menuChildren);
220
+ this.setDividersSize(this.menuChildren);
203
221
  this.updateIsScollable();
222
+ this.updateScrollPosition();
223
+ this.observeMenuItemsAttributes();
224
+ }
225
+
226
+ observeMenuItemsAttributes() {
227
+ // Déconnecter l'ancien observer si existant
228
+ this.attributeObserver?.disconnect();
229
+
230
+ // Créer un nouvel observer pour surveiller les changements d'attribut 'active'
231
+ this.attributeObserver = new MutationObserver(() => {
232
+ this.updateScrollPosition();
233
+ });
234
+
235
+ // Observer chaque menu-item
236
+ this.menuChildren.forEach((item) => {
237
+ this.attributeObserver!.observe(item, {
238
+ attributes: true,
239
+ attributeFilter: ["active"],
240
+ });
241
+ });
242
+ }
243
+
244
+ updateScrollPosition() {
245
+ // Si on est en mode scrollable et qu'il y a exactement un seul menu-item actif
246
+ if (this.scrollable) {
247
+ const activeItems = this.menuChildren.filter(
248
+ (item) =>
249
+ item.hasAttribute("active") && item.getAttribute("active") !== "false"
250
+ );
251
+
252
+ if (activeItems.length === 1) {
253
+ requestAnimationFrame(() => {
254
+ activeItems[0].scrollIntoView({
255
+ behavior: "smooth",
256
+ block: "nearest",
257
+ inline: "center",
258
+ });
259
+ });
260
+ }
261
+ }
204
262
  }
205
263
 
206
264
  connectedCallback(): void {
207
265
  this.observer = new ResizeObserver(this.updateIsScollable);
208
266
  // observe if menu elements are overflowing and initiate scrollable
209
267
  this.observer.observe(this);
268
+
210
269
  super.connectedCallback();
211
270
  }
212
271
 
272
+ protected firstUpdated(_changedProperties: PropertyValues): void {
273
+ this.menuContent.addEventListener("scrollend", this.handleScrollEnd);
274
+ }
275
+
276
+ // Écouter l'événement scrollend pour mettre à jour les ombres après le scroll
277
+ handleScrollEnd = () => {
278
+ this.setScrollShadow(this.menuContent, this.direction);
279
+ };
280
+
213
281
  disconnectedCallback(): void {
214
282
  this.observer?.disconnect();
283
+ this.attributeObserver?.disconnect();
284
+ this.menuContent.removeEventListener("scrollend", this.handleScrollEnd);
285
+
215
286
  super.disconnectedCallback();
216
287
  }
217
288
 
218
289
  updateIsScollable = () => {
219
290
  if (this.scrollable) {
220
291
  this.initScrollable();
221
- this.setScrollShadow(this, this.direction);
292
+ this.setScrollShadow(this.menuContent, this.direction);
222
293
  }
223
294
  };
224
295
 
@@ -231,8 +302,9 @@ export class MenuItems extends LitElement {
231
302
  this.addEventListener("mousedown", (e) => {
232
303
  isDown = true;
233
304
  this.classList.add("active");
234
- startX = e.pageX - this.offsetLeft;
235
- scrollLeft = this.scrollLeft;
305
+
306
+ startX = e.pageX - this.menuContent.offsetLeft;
307
+ scrollLeft = this.menuContent.scrollLeft;
236
308
  });
237
309
  this.addEventListener("mouseleave", () => {
238
310
  isDown = false;
@@ -245,16 +317,16 @@ export class MenuItems extends LitElement {
245
317
  this.addEventListener("mousemove", (e) => {
246
318
  if (!isDown) return;
247
319
  e.preventDefault();
248
- const x = e.pageX - this.offsetLeft;
320
+ const x = e.pageX - this.menuContent.offsetLeft;
249
321
  const walk = (x - startX) * 1.5; //scroll-fast
250
- this.scrollLeft = scrollLeft - walk;
251
- this.setScrollShadow(this, this.direction);
322
+ this.menuContent.scrollLeft = scrollLeft - walk;
323
+ this.setScrollShadow(this.menuContent, this.direction);
252
324
  });
253
325
  this.addEventListener("scroll", (e) => {
254
326
  e.preventDefault();
255
327
  // const delta = Math.sign(e.deltaY);
256
328
  // this.scrollLeft += delta * 50;
257
- this.setScrollShadow(this, this.direction);
329
+ this.setScrollShadow(this.menuContent, this.direction);
258
330
  });
259
331
  }
260
332
  }
@@ -312,10 +384,14 @@ export class MenuItems extends LitElement {
312
384
  const menuStyles = {
313
385
  minWidth: this.minWidth,
314
386
  flexDirection: this.direction,
315
- gap: this.gap,
316
387
  };
317
388
  const isMenuRow = this.direction == "row";
318
389
 
390
+ const menuContentStyles = {
391
+ gap: this.gap,
392
+ flexDirection: this.direction,
393
+ };
394
+
319
395
  const popStyles = {
320
396
  display: "block",
321
397
  alignSelf: isMenuRow ? "center" : "flex-start",
@@ -331,7 +407,11 @@ export class MenuItems extends LitElement {
331
407
  class="shadowable"
332
408
  style=${styleMap(menuStyles)}
333
409
  >
334
- <slot @slotchange=${this.mainSlotChange}></slot>
410
+ <slot
411
+ @slotchange=${this.mainSlotChange}
412
+ id="menu-content"
413
+ style=${styleMap(menuContentStyles)}
414
+ ></slot>
335
415
  <sonic-pop
336
416
  style=${styleMap(popStyles)}
337
417
  class=${!this.hasMoreElements ? "hidden" : ""}
@@ -347,7 +427,11 @@ export class MenuItems extends LitElement {
347
427
  name=${isMenuRow ? "more-vert" : "more-horiz"}
348
428
  ></sonic-icon>
349
429
  </sonic-menu-item>
350
- <slot name="more" @slotchange=${this.checkIfMore} slot="content"></slot>
430
+ <slot
431
+ name="more"
432
+ @slotchange=${this.moreSlotChange}
433
+ slot="content"
434
+ ></slot>
351
435
  </sonic-pop>
352
436
  </menu>`;
353
437
  }
@@ -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 = {