@consilioweb/payload-support 0.12.0 → 0.13.1

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.
@@ -71,16 +71,19 @@
71
71
  }
72
72
  }
73
73
 
74
- // detail__title (maquette) : h1 20px/1.3, 600
74
+ // detail__title (maquette) : h1 20px/1.3, 600, text-wrap: pretty
75
+ // Multi-ligne autorisee, on tronque a 2 lignes via line-clamp pour eviter de pousser le header
75
76
  .ticketSubject {
76
77
  font-size: 20px;
77
78
  font-weight: 600;
78
79
  line-height: 1.3;
79
80
  color: var(--theme-text);
80
81
  margin: 0;
82
+ text-wrap: pretty;
83
+ display: -webkit-box;
84
+ -webkit-line-clamp: 2;
85
+ -webkit-box-orient: vertical;
81
86
  overflow: hidden;
82
- text-overflow: ellipsis;
83
- white-space: nowrap;
84
87
  }
85
88
 
86
89
  .topBarRight {
@@ -198,12 +201,12 @@
198
201
  align-items: center;
199
202
  }
200
203
 
201
- // dl/dt/dd (kv maquette) — grid 100px 1fr, gap 8px/12px
204
+ // dl/dt/dd (kv maquette) — grid 100px 1fr, label aligné gauche, value étirée
202
205
  .sideField {
203
- display: flex;
204
- justify-content: space-between;
206
+ display: grid;
207
+ grid-template-columns: 100px 1fr;
205
208
  align-items: center;
206
- gap: 8px;
209
+ gap: 8px 12px;
207
210
  padding: 4px 0;
208
211
  font-size: 13px;
209
212
  line-height: 1.5;
@@ -219,11 +222,14 @@
219
222
  display: flex;
220
223
  align-items: center;
221
224
  gap: 8px;
225
+ min-width: 0;
222
226
  }
223
227
 
224
228
  // Inline select for sidebar editable fields (kv__edit maquette)
229
+ // Left-aligned dans la grid (la valeur s'aligne au début de la colonne 2)
225
230
  .sideSelect {
226
231
  padding: 2px 8px;
232
+ margin: -2px -8px -2px 0;
227
233
  border-radius: 4px;
228
234
  border: 1px solid transparent;
229
235
  background: transparent;
@@ -232,8 +238,10 @@
232
238
  color: var(--theme-text);
233
239
  cursor: pointer;
234
240
  transition: background 80ms ease;
235
- text-align: right;
236
- max-width: 160px;
241
+ text-align: left;
242
+ max-width: 100%;
243
+ width: 100%;
244
+ justify-self: start;
237
245
 
238
246
  &:hover { background: var(--theme-elevation-100); }
239
247
  &:focus {
@@ -468,6 +476,8 @@
468
476
  }
469
477
 
470
478
  // Body bubble : t-body 14px/1.55, padding 12px 16px, border 1px elevation-200
479
+ // Width: prend toute la largeur dispo dans la colonne conversation (suppression du max-width 720px
480
+ // qui créait un vide à droite quand le main est large).
471
481
  .messageBody {
472
482
  font-size: 14px;
473
483
  line-height: 1.55;
@@ -478,8 +488,8 @@
478
488
  padding: 12px 16px;
479
489
  white-space: pre-wrap;
480
490
  word-break: break-word;
481
- max-width: 720px;
482
491
  margin-top: 4px;
492
+ width: 100%;
483
493
  }
484
494
 
485
495
  // Actions hover (msg__actions maquette) : ghost links micro, opacity 0 -> 1
@@ -687,6 +697,18 @@
687
697
  cursor: pointer;
688
698
  font-weight: 500;
689
699
  user-select: none;
700
+ transition: color 120ms ease;
701
+ }
702
+
703
+ // Note interne (1er label) : warning quand cochee
704
+ // Notifier (2e label) : info quand cochee
705
+ // Approximation via :has() — supportee Chrome/Safari/FF >= 121
706
+ > label:nth-of-type(1):has(input:checked) {
707
+ color: var(--theme-warning-500, #c97a0a);
708
+ input[type="checkbox"]:checked { background: var(--theme-warning-500, #c97a0a); }
709
+ }
710
+ > label:nth-of-type(2):has(input:checked) {
711
+ color: var(--theme-info-500, #2a6bd8);
690
712
  }
691
713
 
692
714
  // Toggle switch (toggle__sw maquette) : 28×16, info-500 quand checked
@@ -838,23 +860,49 @@
838
860
  &.timerActive { color: var(--theme-error-500, #c4392c); }
839
861
  }
840
862
 
841
- // Bouton Go / Pause / Save : 30px height, micro typo 600
863
+ // Bouton Go / Pause / Save (tt__go maquette) :
864
+ // - "paused" (Go) : bg theme-text, color theme-bg (carré sombre, contrasté)
865
+ // - "running" (Pause) : bg error-500, color white (stop visible)
866
+ // - "save" (💾) : ghost neutre theme-bg + border elevation-200
867
+ // Approximation : on neutralise par défaut, et les classes appellantes appliquent le style.
842
868
  .timerBtn {
843
869
  display: inline-flex;
844
870
  align-items: center;
871
+ justify-content: center;
845
872
  gap: 6px;
846
873
  height: 30px;
847
874
  padding: 0 12px;
848
875
  border-radius: 4px;
849
- border: 1px solid var(--theme-elevation-200, var(--theme-input-border));
850
- background: var(--theme-bg);
876
+ border: 1px solid var(--theme-text);
877
+ background: var(--theme-text);
878
+ color: var(--theme-bg, #fff);
851
879
  font-size: 12px;
852
- font-weight: 500;
853
- line-height: 1;
854
- color: var(--theme-text);
880
+ font-weight: 600;
855
881
  cursor: pointer;
856
- transition: background 80ms ease;
857
- &:hover { background: var(--theme-elevation-100); }
882
+ transition: background 80ms ease, border-color 80ms ease;
883
+ white-space: nowrap;
884
+ &:hover { background: var(--theme-elevation-800); border-color: var(--theme-elevation-800); }
885
+ &:disabled { opacity: 0.5; cursor: not-allowed; }
886
+ }
887
+
888
+ // Variante running (tt__go--running maquette) : bg error-500 quand le timer tourne
889
+ .timerBtnRunning {
890
+ background: var(--theme-error-500, #c4392c);
891
+ border-color: var(--theme-error-500, #c4392c);
892
+ color: #fff;
893
+ &:hover {
894
+ background: color-mix(in srgb, var(--theme-error-500, #c4392c) 85%, black);
895
+ border-color: color-mix(in srgb, var(--theme-error-500, #c4392c) 85%, black);
896
+ }
897
+ }
898
+
899
+ // Variante "ghost" pour les boutons secondaires (Save / + Ajouter) : neutre, evite le carre noir partout
900
+ .timerBtnGhost {
901
+ background: var(--theme-bg);
902
+ border-color: var(--theme-elevation-200, var(--theme-input-border));
903
+ color: var(--theme-text);
904
+ font-weight: 500;
905
+ &:hover { background: var(--theme-elevation-100); border-color: var(--theme-elevation-200, var(--theme-input-border)); }
858
906
  }
859
907
 
860
908
  // Activity in sidebar
@@ -1257,8 +1257,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
1257
1257
  ":",
1258
1258
  String(timerSeconds % 60).padStart(2, "0")
1259
1259
  ] }),
1260
- !timerRunning ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: () => setTimerRunning(true), "aria-label": "D\xE9marrer le timer", children: timerSeconds > 0 ? "\u25B6" : "\u25B6 Go" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: () => setTimerRunning(false), "aria-label": "Mettre en pause le timer", children: "\u23F8 Pause" }),
1261
- timerSeconds >= 60 && !timerRunning && /* @__PURE__ */ jsxRuntime.jsxs("button", { className: s__default.default.timerBtn, onClick: () => {
1260
+ !timerRunning ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: () => setTimerRunning(true), "aria-label": "D\xE9marrer le timer", children: timerSeconds > 0 ? "\u25B6" : "\u25B6 Go" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.timerBtn} ${s__default.default.timerBtnRunning}`, onClick: () => setTimerRunning(false), "aria-label": "Mettre en pause le timer", children: "\u23F8 Pause" }),
1261
+ timerSeconds >= 60 && !timerRunning && /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.timerBtn} ${s__default.default.timerBtnGhost}`, onClick: () => {
1262
1262
  handleTimerSave();
1263
1263
  localStorage.removeItem(`timer-sec-${ticketId}`);
1264
1264
  localStorage.removeItem(`timer-run-${ticketId}`);
@@ -1271,7 +1271,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
1271
1271
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.timerBar, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.timerBarFill, style: { width: `${Math.min(100, (totalMin + Math.floor(timerSeconds / 60)) / 120 * 100)}%` } }) }),
1272
1272
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 6, marginTop: 8, alignItems: "center" }, children: [
1273
1273
  /* @__PURE__ */ jsxRuntime.jsx("input", { type: "number", min: "1", placeholder: "min", style: { width: 60, padding: "4px 8px", borderRadius: 6, border: "1px solid var(--theme-elevation-200)", fontSize: 12, color: "var(--theme-text)", background: "var(--theme-elevation-0)" }, id: "manual-time-input" }),
1274
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: async () => {
1274
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.timerBtn} ${s__default.default.timerBtnGhost}`, onClick: async () => {
1275
1275
  const input = document.getElementById("manual-time-input");
1276
1276
  const mins = Number(input?.value);
1277
1277
  if (!mins || mins < 1 || !ticketId) return;
@@ -1250,8 +1250,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
1250
1250
  ":",
1251
1251
  String(timerSeconds % 60).padStart(2, "0")
1252
1252
  ] }),
1253
- !timerRunning ? /* @__PURE__ */ jsx("button", { className: s.timerBtn, onClick: () => setTimerRunning(true), "aria-label": "D\xE9marrer le timer", children: timerSeconds > 0 ? "\u25B6" : "\u25B6 Go" }) : /* @__PURE__ */ jsx("button", { className: s.timerBtn, onClick: () => setTimerRunning(false), "aria-label": "Mettre en pause le timer", children: "\u23F8 Pause" }),
1254
- timerSeconds >= 60 && !timerRunning && /* @__PURE__ */ jsxs("button", { className: s.timerBtn, onClick: () => {
1253
+ !timerRunning ? /* @__PURE__ */ jsx("button", { className: s.timerBtn, onClick: () => setTimerRunning(true), "aria-label": "D\xE9marrer le timer", children: timerSeconds > 0 ? "\u25B6" : "\u25B6 Go" }) : /* @__PURE__ */ jsx("button", { className: `${s.timerBtn} ${s.timerBtnRunning}`, onClick: () => setTimerRunning(false), "aria-label": "Mettre en pause le timer", children: "\u23F8 Pause" }),
1254
+ timerSeconds >= 60 && !timerRunning && /* @__PURE__ */ jsxs("button", { className: `${s.timerBtn} ${s.timerBtnGhost}`, onClick: () => {
1255
1255
  handleTimerSave();
1256
1256
  localStorage.removeItem(`timer-sec-${ticketId}`);
1257
1257
  localStorage.removeItem(`timer-run-${ticketId}`);
@@ -1264,7 +1264,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
1264
1264
  /* @__PURE__ */ jsx("div", { className: s.timerBar, "aria-hidden": true, children: /* @__PURE__ */ jsx("div", { className: s.timerBarFill, style: { width: `${Math.min(100, (totalMin + Math.floor(timerSeconds / 60)) / 120 * 100)}%` } }) }),
1265
1265
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, marginTop: 8, alignItems: "center" }, children: [
1266
1266
  /* @__PURE__ */ jsx("input", { type: "number", min: "1", placeholder: "min", style: { width: 60, padding: "4px 8px", borderRadius: 6, border: "1px solid var(--theme-elevation-200)", fontSize: 12, color: "var(--theme-text)", background: "var(--theme-elevation-0)" }, id: "manual-time-input" }),
1267
- /* @__PURE__ */ jsx("button", { className: s.timerBtn, onClick: async () => {
1267
+ /* @__PURE__ */ jsx("button", { className: `${s.timerBtn} ${s.timerBtnGhost}`, onClick: async () => {
1268
1268
  const input = document.getElementById("manual-time-input");
1269
1269
  const mins = Number(input?.value);
1270
1270
  if (!mins || mins < 1 || !ticketId) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consilioweb/payload-support",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "Payload CMS plugin — professional support & ticketing system with AI, SLA, time tracking, live chat, and more",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -71,16 +71,19 @@
71
71
  }
72
72
  }
73
73
 
74
- // detail__title (maquette) : h1 20px/1.3, 600
74
+ // detail__title (maquette) : h1 20px/1.3, 600, text-wrap: pretty
75
+ // Multi-ligne autorisee, on tronque a 2 lignes via line-clamp pour eviter de pousser le header
75
76
  .ticketSubject {
76
77
  font-size: 20px;
77
78
  font-weight: 600;
78
79
  line-height: 1.3;
79
80
  color: var(--theme-text);
80
81
  margin: 0;
82
+ text-wrap: pretty;
83
+ display: -webkit-box;
84
+ -webkit-line-clamp: 2;
85
+ -webkit-box-orient: vertical;
81
86
  overflow: hidden;
82
- text-overflow: ellipsis;
83
- white-space: nowrap;
84
87
  }
85
88
 
86
89
  .topBarRight {
@@ -198,12 +201,12 @@
198
201
  align-items: center;
199
202
  }
200
203
 
201
- // dl/dt/dd (kv maquette) — grid 100px 1fr, gap 8px/12px
204
+ // dl/dt/dd (kv maquette) — grid 100px 1fr, label aligné gauche, value étirée
202
205
  .sideField {
203
- display: flex;
204
- justify-content: space-between;
206
+ display: grid;
207
+ grid-template-columns: 100px 1fr;
205
208
  align-items: center;
206
- gap: 8px;
209
+ gap: 8px 12px;
207
210
  padding: 4px 0;
208
211
  font-size: 13px;
209
212
  line-height: 1.5;
@@ -219,11 +222,14 @@
219
222
  display: flex;
220
223
  align-items: center;
221
224
  gap: 8px;
225
+ min-width: 0;
222
226
  }
223
227
 
224
228
  // Inline select for sidebar editable fields (kv__edit maquette)
229
+ // Left-aligned dans la grid (la valeur s'aligne au début de la colonne 2)
225
230
  .sideSelect {
226
231
  padding: 2px 8px;
232
+ margin: -2px -8px -2px 0;
227
233
  border-radius: 4px;
228
234
  border: 1px solid transparent;
229
235
  background: transparent;
@@ -232,8 +238,10 @@
232
238
  color: var(--theme-text);
233
239
  cursor: pointer;
234
240
  transition: background 80ms ease;
235
- text-align: right;
236
- max-width: 160px;
241
+ text-align: left;
242
+ max-width: 100%;
243
+ width: 100%;
244
+ justify-self: start;
237
245
 
238
246
  &:hover { background: var(--theme-elevation-100); }
239
247
  &:focus {
@@ -468,6 +476,8 @@
468
476
  }
469
477
 
470
478
  // Body bubble : t-body 14px/1.55, padding 12px 16px, border 1px elevation-200
479
+ // Width: prend toute la largeur dispo dans la colonne conversation (suppression du max-width 720px
480
+ // qui créait un vide à droite quand le main est large).
471
481
  .messageBody {
472
482
  font-size: 14px;
473
483
  line-height: 1.55;
@@ -478,8 +488,8 @@
478
488
  padding: 12px 16px;
479
489
  white-space: pre-wrap;
480
490
  word-break: break-word;
481
- max-width: 720px;
482
491
  margin-top: 4px;
492
+ width: 100%;
483
493
  }
484
494
 
485
495
  // Actions hover (msg__actions maquette) : ghost links micro, opacity 0 -> 1
@@ -687,6 +697,18 @@
687
697
  cursor: pointer;
688
698
  font-weight: 500;
689
699
  user-select: none;
700
+ transition: color 120ms ease;
701
+ }
702
+
703
+ // Note interne (1er label) : warning quand cochee
704
+ // Notifier (2e label) : info quand cochee
705
+ // Approximation via :has() — supportee Chrome/Safari/FF >= 121
706
+ > label:nth-of-type(1):has(input:checked) {
707
+ color: var(--theme-warning-500, #c97a0a);
708
+ input[type="checkbox"]:checked { background: var(--theme-warning-500, #c97a0a); }
709
+ }
710
+ > label:nth-of-type(2):has(input:checked) {
711
+ color: var(--theme-info-500, #2a6bd8);
690
712
  }
691
713
 
692
714
  // Toggle switch (toggle__sw maquette) : 28×16, info-500 quand checked
@@ -838,23 +860,49 @@
838
860
  &.timerActive { color: var(--theme-error-500, #c4392c); }
839
861
  }
840
862
 
841
- // Bouton Go / Pause / Save : 30px height, micro typo 600
863
+ // Bouton Go / Pause / Save (tt__go maquette) :
864
+ // - "paused" (Go) : bg theme-text, color theme-bg (carré sombre, contrasté)
865
+ // - "running" (Pause) : bg error-500, color white (stop visible)
866
+ // - "save" (💾) : ghost neutre theme-bg + border elevation-200
867
+ // Approximation : on neutralise par défaut, et les classes appellantes appliquent le style.
842
868
  .timerBtn {
843
869
  display: inline-flex;
844
870
  align-items: center;
871
+ justify-content: center;
845
872
  gap: 6px;
846
873
  height: 30px;
847
874
  padding: 0 12px;
848
875
  border-radius: 4px;
849
- border: 1px solid var(--theme-elevation-200, var(--theme-input-border));
850
- background: var(--theme-bg);
876
+ border: 1px solid var(--theme-text);
877
+ background: var(--theme-text);
878
+ color: var(--theme-bg, #fff);
851
879
  font-size: 12px;
852
- font-weight: 500;
853
- line-height: 1;
854
- color: var(--theme-text);
880
+ font-weight: 600;
855
881
  cursor: pointer;
856
- transition: background 80ms ease;
857
- &:hover { background: var(--theme-elevation-100); }
882
+ transition: background 80ms ease, border-color 80ms ease;
883
+ white-space: nowrap;
884
+ &:hover { background: var(--theme-elevation-800); border-color: var(--theme-elevation-800); }
885
+ &:disabled { opacity: 0.5; cursor: not-allowed; }
886
+ }
887
+
888
+ // Variante running (tt__go--running maquette) : bg error-500 quand le timer tourne
889
+ .timerBtnRunning {
890
+ background: var(--theme-error-500, #c4392c);
891
+ border-color: var(--theme-error-500, #c4392c);
892
+ color: #fff;
893
+ &:hover {
894
+ background: color-mix(in srgb, var(--theme-error-500, #c4392c) 85%, black);
895
+ border-color: color-mix(in srgb, var(--theme-error-500, #c4392c) 85%, black);
896
+ }
897
+ }
898
+
899
+ // Variante "ghost" pour les boutons secondaires (Save / + Ajouter) : neutre, evite le carre noir partout
900
+ .timerBtnGhost {
901
+ background: var(--theme-bg);
902
+ border-color: var(--theme-elevation-200, var(--theme-input-border));
903
+ color: var(--theme-text);
904
+ font-weight: 500;
905
+ &:hover { background: var(--theme-elevation-100); border-color: var(--theme-elevation-200, var(--theme-input-border)); }
858
906
  }
859
907
 
860
908
  // Activity in sidebar
@@ -1202,10 +1202,10 @@ const [clientTyping, setClientTyping] = useState(false)
1202
1202
  {!timerRunning ? (
1203
1203
  <button className={s.timerBtn} onClick={() => setTimerRunning(true)} aria-label="Démarrer le timer">{timerSeconds > 0 ? '▶' : '▶ Go'}</button>
1204
1204
  ) : (
1205
- <button className={s.timerBtn} onClick={() => setTimerRunning(false)} aria-label="Mettre en pause le timer">⏸ Pause</button>
1205
+ <button className={`${s.timerBtn} ${s.timerBtnRunning}`} onClick={() => setTimerRunning(false)} aria-label="Mettre en pause le timer">⏸ Pause</button>
1206
1206
  )}
1207
1207
  {timerSeconds >= 60 && !timerRunning && (
1208
- <button className={s.timerBtn} onClick={() => { handleTimerSave(); localStorage.removeItem(`timer-sec-${ticketId}`); localStorage.removeItem(`timer-run-${ticketId}`) }} aria-label="Sauvegarder le temps">💾 {Math.round(timerSeconds / 60)}m</button>
1208
+ <button className={`${s.timerBtn} ${s.timerBtnGhost}`} onClick={() => { handleTimerSave(); localStorage.removeItem(`timer-sec-${ticketId}`); localStorage.removeItem(`timer-run-${ticketId}`) }} aria-label="Sauvegarder le temps">💾 {Math.round(timerSeconds / 60)}m</button>
1209
1209
  )}
1210
1210
  </div>
1211
1211
  {/* Progress bar (tt__bar maquette) — full = 120 min reference */}
@@ -1215,7 +1215,7 @@ const [clientTyping, setClientTyping] = useState(false)
1215
1215
  {/* Manual time entry */}
1216
1216
  <div style={{ display: 'flex', gap: 6, marginTop: 8, alignItems: 'center' }}>
1217
1217
  <input type="number" min="1" placeholder="min" style={{ width: 60, padding: '4px 8px', borderRadius: 6, border: '1px solid var(--theme-elevation-200)', fontSize: 12, color: 'var(--theme-text)', background: 'var(--theme-elevation-0)' }} id="manual-time-input" />
1218
- <button className={s.timerBtn} onClick={async () => {
1218
+ <button className={`${s.timerBtn} ${s.timerBtnGhost}`} onClick={async () => {
1219
1219
  const input = document.getElementById('manual-time-input') as HTMLInputElement
1220
1220
  const mins = Number(input?.value)
1221
1221
  if (!mins || mins < 1 || !ticketId) return