qc-trousse-sdg 1.4.5 → 1.4.7

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 (73) hide show
  1. package/README.md +16 -0
  2. package/dist/css/qc-sdg-no-grid.min.css +1 -1
  3. package/dist/css/qc-sdg.min.css +1 -1
  4. package/dist/js/qc-sdg.min.js +1 -1
  5. package/package-lock.json +4689 -0
  6. package/package.json +1 -1
  7. package/plugins/buildHtmlDoc.js +5 -1
  8. package/public/css/qc-doc-sdg.css +69 -34
  9. package/public/css/qc-sdg-no-grid.css +86 -45
  10. package/public/css/qc-sdg.css +86 -45
  11. package/public/index.html +82 -51
  12. package/public/js/qc-doc-sdg.js +8081 -3972
  13. package/public/js/qc-sdg.js +8772 -5119
  14. package/rollup.config.js +3 -4
  15. package/src/doc/components/Code.svelte +13 -5
  16. package/src/doc/components/Exemple.svelte +0 -13
  17. package/src/doc/qc-doc-sdg.js +6 -1
  18. package/src/doc/scss/components/_code.scss +4 -21
  19. package/src/doc/scss/components/_exemple.scss +25 -0
  20. package/src/doc/scss/qc-doc-sdg.scss +23 -4
  21. package/src/sdg/bases/Icon/Icon.svelte +2 -0
  22. package/src/sdg/bases/links/_links.html +10 -10
  23. package/src/sdg/bases/links/_links.scss +18 -12
  24. package/src/sdg/components/Alert/Alert.svelte +28 -9
  25. package/src/sdg/components/Alert/AlertWC.svelte +20 -5
  26. package/src/sdg/components/Alert/Test/AlertSvelteTest.svelte +25 -0
  27. package/src/sdg/components/Alert/Test/alertBaselineTest.html +13 -0
  28. package/src/sdg/components/Alert/Test/alertSvelteTest.html +1 -0
  29. package/src/sdg/components/Alert/_alert.html +25 -13
  30. package/src/sdg/components/Checkbox/Checkbox.svelte +6 -5
  31. package/src/sdg/components/ChoiceGroup/_choiceGroup.html +0 -2
  32. package/src/sdg/components/DropdownList/DropdownList.svelte +65 -14
  33. package/src/sdg/components/DropdownList/DropdownListButton/DropdownListButton.svelte +2 -6
  34. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItems.svelte +4 -22
  35. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsMultiple/DropdownListItemsMultiple.svelte +2 -1
  36. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsSingle/DropdownListItemsSingle.svelte +2 -1
  37. package/src/sdg/components/DropdownList/SelectWC.svelte +39 -13
  38. package/src/sdg/components/DropdownList/Test/DropdownListSvelteTest.svelte +2 -2
  39. package/src/sdg/components/DropdownList/Test/dropdownListBaselineTest.html +7 -0
  40. package/src/sdg/components/DropdownList/_dropdownList.scss +7 -5
  41. package/src/sdg/components/DropdownList/_select.html +31 -5
  42. package/src/sdg/components/ExternalLink/ExternalLink.svelte +36 -74
  43. package/src/sdg/components/ExternalLink/ExternalLinkWC.svelte +44 -1
  44. package/src/sdg/components/ExternalLink/externalLinkBaselineTest.html +45 -0
  45. package/src/sdg/components/Fieldset/_fieldset.scss +1 -1
  46. package/src/sdg/components/FormfieldRow/_formfieldRow.html +7 -7
  47. package/src/sdg/components/Label/LabelText.svelte +2 -1
  48. package/src/sdg/components/Label/_label.scss +10 -2
  49. package/src/sdg/components/Notice/_notice.html +3 -3
  50. package/src/sdg/components/PivFooter/_pivFooter.html +4 -4
  51. package/src/sdg/components/PivHeader/Test/pivHeaderBaselineTest.html +2 -2
  52. package/src/sdg/components/PivHeader/Test/pivHeaderEmbeddedTest.svelte +2 -1
  53. package/src/sdg/components/PivHeader/_pivHeader.html +2 -2
  54. package/src/sdg/components/PivHeader/_pivHeader.scss +6 -4
  55. package/src/sdg/components/TextField/Test/TextFieldEmbededTest.svelte +19 -3
  56. package/src/sdg/components/TextField/Test/textFieldBaselineTest.html +5 -2
  57. package/src/sdg/components/TextField/TextField.svelte +12 -6
  58. package/src/sdg/components/TextField/TextFieldWC.svelte +27 -13
  59. package/src/sdg/components/TextField/_textField.html +0 -5
  60. package/src/sdg/components/TextField/textFieldUtils.js +3 -2
  61. package/src/sdg/components/utils.js +78 -14
  62. package/src/sdg/qc-sdg-test.js +2 -1
  63. package/src/sdg/scss/lib/_mixins.scss +6 -0
  64. package/src/sdg/scss/utilities/_states.scss +1 -1
  65. package/tests/alert-baseline.spec.ts +23 -0
  66. package/tests/alert-svelte.spec.ts +23 -0
  67. package/tests/buildSvelteTestsIgnore.json +2 -1
  68. package/tests/dropdown-list-baseline.spec.ts +8 -0
  69. package/tests/external-link-baseline.spec.ts +30 -0
  70. package/tests/textfield-baseline.spec.ts +5 -5
  71. package/tests/textfield-svelte.spec.ts +5 -5
  72. package/src/sdg/components/CharCount/_charCount.html +0 -7
  73. package/src/sdg/components/RadioButton/_radioButton.html +0 -24
@@ -8,8 +8,51 @@
8
8
 
9
9
  <script>
10
10
  import ExternalLink from "./ExternalLink.svelte";
11
+ import {onDestroy, onMount, tick} from "svelte";
12
+ import {Utils} from "../utils";
11
13
 
12
14
  const props = $props();
15
+ const nestedExternalLinks = $host().querySelector('qc-external-link');
16
+
17
+ let links = $state([]);
18
+ const observer = Utils.createMutationObserver($host(), refreshLinks);
19
+ let isUpdating = $state(false);
20
+ let pendingUpdate = false;
21
+
22
+ function queryLinks() {
23
+ return Array.from($host().querySelectorAll('a'));
24
+ }
25
+
26
+ function refreshLinks() {
27
+ if (isUpdating || pendingUpdate) {
28
+ return;
29
+ }
30
+ pendingUpdate = true;
31
+ tick().then(() => {
32
+ if (isUpdating) {
33
+ pendingUpdate = false;
34
+ return;
35
+ }
36
+
37
+ links = queryLinks();
38
+ pendingUpdate = false;
39
+ });
40
+ }
41
+
42
+ onMount(() => {
43
+ $host().classList.add('qc-external-link');
44
+ links = queryLinks();
45
+
46
+ observer?.observe($host(), {
47
+ childList: true,
48
+ characterData: true,
49
+ subtree: true,
50
+ });
51
+ });
52
+
53
+ onDestroy(() => {
54
+ observer?.disconnect();
55
+ });
13
56
  </script>
14
57
 
15
- <ExternalLink {...props} />
58
+ <ExternalLink {links} bind:isUpdating {nestedExternalLinks} {...props} />
@@ -0,0 +1,45 @@
1
+ <div style="border: 1px solid var(--qc-color-text-primary); padding: var(--qc-spacer-sm); max-width: 376px;">
2
+ <p>
3
+ <qc-external-link>
4
+ <a href="#multi-links"
5
+ target="_blank"
6
+ rel="noreferrer nofollow"
7
+ data-external-link="true"
8
+ >
9
+ https:/<wbr>/<wbr>www.quebec.ca/<wbr>gouvernement/<wbr>ministere/<wbr>travail/<wbr>lois-<wbr>reglements#c335465
10
+ </a>
11
+ </qc-external-link>
12
+ </p>
13
+ </div>
14
+
15
+ <p class="qc-font-size-xl">
16
+ Lorem ipsum
17
+ <qc-external-link><a href="http://www.external.domain.com/">Lorem ipsum dolor sit amet, consectetur
18
+ adipiscing</a></qc-external-link>
19
+ elit
20
+ </p>
21
+ <p class="qc-font-size-lg">
22
+ Lorem ipsum
23
+ <qc-external-link><a href="http://www.external.domain.com/">Lorem ipsum dolor sit amet, consectetur
24
+ adipiscing</a></qc-external-link>
25
+ elit
26
+ </p>
27
+ <p class="qc-font-size-md">
28
+ Lorem ipsum
29
+ <qc-external-link><a href="http://www.external.domain.com/">Lorem ipsum dolor sit amet, consectetur
30
+ adipiscing</a></qc-external-link>
31
+ elit
32
+ </p>
33
+ <p class="qc-font-size-sm">
34
+ Lorem ipsum
35
+ <qc-external-link><a href="http://www.external.domain.com/">Lorem ipsum dolor sit amet, consectetur
36
+ adipiscing</a></qc-external-link>
37
+ elit
38
+ </p>
39
+
40
+ <p class="qc-font-size-md">
41
+ <qc-external-link id="multi-links">
42
+ <a href="http://www.external.domain.com/">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</a>
43
+ <a href="https://www.google.com/">Google</a>
44
+ </qc-external-link>
45
+ </p>
@@ -7,9 +7,9 @@
7
7
  margin: 0 0 rem(32);
8
8
  justify-items: start;
9
9
  legend {
10
- font-weight: token-value(font weight content bold);
11
10
  display: inline-block;
12
11
  margin-bottom: token-value(spacer, md);
12
+ white-space: nowrap;
13
13
  }
14
14
  &.qc-compact {
15
15
  margin-bottom: token-value(spacer, sm);
@@ -1,6 +1,11 @@
1
- <h3 id="champs-alignes">Champs alignés horizontalement (classe <code>qc‑textfield‑row</code>)</h3>
1
+ <h3 id="champs-alignes">Champs alignés horizontalement (classe <code>qc‑formfield‑row</code>)</h3>
2
2
 
3
- <p>Les champs regroupés sur une ligne doivent être placés dans un div avec la classe <code>qc-textfield-row</code> pour correctement afficher les messages d’erreur en cas de soumission invalide.</p>
3
+ <p>
4
+ Les champs regroupés sur une ligne doivent être placés dans un <code>div</code> avec la classe <code>qc-formfield-row</code>.
5
+ De cette façon, les messages d'erreur ne provoquent pas de décalage.
6
+ <br/><br/>
7
+ Voir le code des champs Téléphone et Poste dans l'exemple ci-dessus.
8
+ </p>
4
9
 
5
10
  <h4>Exemple</h4>
6
11
  <qc-doc-exemple caption="Exemple de champs sur une seule ligne">
@@ -101,8 +106,3 @@
101
106
  }
102
107
  });
103
108
  </script>
104
-
105
- <h4>Documentation technique</h4>
106
- <p>Placer les champs à regrouper sur une seule ligne dans un div avec la classe <code>qc-formfield-row</code></p>
107
-
108
-
@@ -1,4 +1,5 @@
1
1
  <script>
2
2
  let {text, required} = $props()
3
3
  </script>
4
- {@html text}{#if required}<span class="qc-required" aria-hidden="true">*</span>{/if}
4
+
5
+ <span class="qc-label-text">{@html text}</span>{#if required}<span class="qc-required" aria-hidden="true">*</span>{/if}
@@ -1,9 +1,10 @@
1
1
  @use "qc-sdg-lib" as *;
2
2
 
3
3
  .qc-label {
4
- font-weight: token-value(font weight content bold);
5
- display: block;
4
+ display: inline-block;
6
5
  width: fit-content;
6
+ white-space: nowrap;
7
+ margin: 0;
7
8
 
8
9
  &.qc-compact {
9
10
  font-size: token-value(font size sm);
@@ -18,3 +19,10 @@
18
19
  cursor: not-allowed;
19
20
  }
20
21
  }
22
+
23
+ .qc-label-text {
24
+ white-space: wrap;
25
+ margin: 0;
26
+
27
+ @include content-font(md, bold);
28
+ }
@@ -61,13 +61,13 @@
61
61
  title="Des erreurs sont présentes dans le formulaire :">
62
62
  <ul>
63
63
  <li>
64
- <a href="javascript:;">Le champ « Nom de famille » est obligatoire ;</a>
64
+ <a href="#">Le champ « Nom de famille » est obligatoire ;</a>
65
65
  </li>
66
66
  <li>
67
- <a href="javascript:;">Le champ « Prénom » est obligatoire ;</a>
67
+ <a href="#">Le champ « Prénom » est obligatoire ;</a>
68
68
  </li>
69
69
  <li>
70
- <a href="javascript:;">Le champ « Numéro de dossier » est obligatoire.</a>
70
+ <a href="#">Le champ « Numéro de dossier » est obligatoire.</a>
71
71
  </li>
72
72
  </ul>
73
73
  </qc-notice>
@@ -70,7 +70,7 @@
70
70
  <td>Le chemin de l’image en thème clair.</td>
71
71
  <td>Le chemin vers l’image dist/img/QUEBEC_couleur.svg de la trousse</td>
72
72
  <td>Adresse de l’image du pied de page en thème clair (fond transparent, texte et drapeaux en
73
- couleur, voir <a href="#piv-footer-ex-2">l’exemple de pied de page PIV personnalisé</a>).
73
+ couleur, voir <a href="#piv-footer-ex-2">l’exemple de pied de page du PIV personnalisé</a>).
74
74
  </td>
75
75
  </tr>
76
76
  <tr>
@@ -78,7 +78,7 @@
78
78
  <td>Le chemin de l’image en thème sombre.</td>
79
79
  <td>Le chemin vers l’image dist/img/QUEBEC_blanc.svg de la trousse</td>
80
80
  <td>Adresse de l’image du pied de page en thème sombre (fond transparent, texte et drapeaux en
81
- blanc, voir <a href="#piv-footer-ex-2">l’exemple de pied de page PIV personnalisé</a>).
81
+ blanc, voir <a href="#piv-footer-ex-2">l’exemple de pied de page du PIV personnalisé</a>).
82
82
  </td>
83
83
  </tr>
84
84
  <tr>
@@ -129,7 +129,7 @@
129
129
  </table>
130
130
  </div>
131
131
 
132
- <qc-notice type="information">Les images du pied de page PIV doivent respecter
132
+ <qc-notice type="information">Les images du pied de page du PIV doivent respecter
133
133
  <qc-external-link><a href="https://www.piv.gouv.qc.ca/fileadmin/documents/guide/section1_general.pdf">les
134
134
  normes graphiques du système d’identification visuelle.</a>. Nous vous invitons à privilégier le format
135
135
  SVG, qui permet de conserver la lisibilité de l’image en cas de zoom.
@@ -140,7 +140,7 @@
140
140
 
141
141
  <p>Ci-dessous, les zones d’ajout de contenu HTML (balise &lt;slot&gt;) délimitées en pointillé.</p>
142
142
  <qc-doc-exemple id="qc-piv-footer-slots"
143
- caption="Présentation des zones d’ajout de contenu du pied de page PIV">
143
+ caption="Présentation des zones d’ajout de contenu du pied de page du PIV">
144
144
  <qc-piv-footer>
145
145
  <div style="border:2px dashed;padding: var(--qc-spacer-xs);">
146
146
  Contenu par défaut
@@ -13,7 +13,7 @@
13
13
  <ul>
14
14
  <li><a href="#fakeEnglish">English</a>
15
15
  </li>
16
- <li><a href="javascript:;">Nous joindre</a>
16
+ <li><a href="#">Nous joindre</a>
17
17
  </li>
18
18
  </ul>
19
19
  </nav>
@@ -30,7 +30,7 @@
30
30
  <ul slot="links">
31
31
  <li><a href="#fakeEnglish">English</a>
32
32
  </li>
33
- <li><a href="javascript:;">Nous joindre</a>
33
+ <li><a href="#">Nous joindre</a>
34
34
  </li>
35
35
  </ul>
36
36
 
@@ -13,7 +13,8 @@
13
13
  <ul>
14
14
  <li><a href="#fakeEnglish">English</a>
15
15
  </li>
16
- <li><a href="javascript:;">Nous joindre</a>
16
+ <!-- svelte-ignore a11y_invalid_attribute -->
17
+ <li><a href="#">Nous joindre</a>
17
18
  </li>
18
19
  </ul>
19
20
  </nav>
@@ -26,7 +26,7 @@
26
26
  <ul>
27
27
  <li><a href="#fakeEnglish">English</a>
28
28
  </li>
29
- <li><a href="javascript:;">Nous joindre</a>
29
+ <li><a href="#">Nous joindre</a>
30
30
  </li>
31
31
  </ul>
32
32
  </nav>
@@ -47,7 +47,7 @@
47
47
  <ul slot="links">
48
48
  <li><a href="#fakeEnglish">English</a>
49
49
  </li>
50
- <li><a href="javascript:;">Nous joindre</a>
50
+ <li><a href="#">Nous joindre</a>
51
51
  </li>
52
52
  </ul>
53
53
 
@@ -142,10 +142,6 @@ qc-piv-header,
142
142
  --qc-color-link-visited: white;
143
143
  --qc-color-link-active: white;
144
144
 
145
- font-family: token-value(font family header);
146
- text-decoration: none;
147
- font-weight: token-value(font weight regular);
148
-
149
145
  &:hover {
150
146
  text-decoration: underline;
151
147
  }
@@ -155,6 +151,12 @@ qc-piv-header,
155
151
  outline-offset: -2px;
156
152
  }
157
153
  }
154
+
155
+ a, span {
156
+ font-family: token-value(font family header);
157
+ text-decoration: none;
158
+ font-weight: token-value(font weight regular);
159
+ }
158
160
  }
159
161
 
160
162
  .go-to-content {
@@ -28,6 +28,7 @@
28
28
  >
29
29
  <input type="text"
30
30
  name="text-md"
31
+ id="text-md"
31
32
  placeholder="Long placeholder lorem ipsum dolor sit amet"
32
33
  />
33
34
  </TextField>
@@ -39,6 +40,7 @@
39
40
  required>
40
41
  <input type="text"
41
42
  name="text-lg"
43
+ id="text-lg"
42
44
  />
43
45
  </TextField>
44
46
 
@@ -54,10 +56,24 @@
54
56
  />
55
57
  </TextField>
56
58
 
59
+ <div style="width: 500px; max-width: 100%;padding: 10px; border: 1px solid #ccc;">
60
+ <TextField
61
+ label="Très large"
62
+ size="xl"
63
+
64
+ >
65
+ <input type="text"
66
+ placeholder="Long placeholder lorem ipsum dolor sit amet"
67
+ name="text-xl"
68
+ disabled
69
+ />
70
+ </TextField>
71
+ </div>
72
+
57
73
  <div class="qc-formfield-row">
58
74
  <TextField
59
- label="Combiné 1"
60
- size="sm"
75
+ label="Combiné 1 Long placeholder lorem ipsum dolor sit amet"
76
+ size="lg"
61
77
  >
62
78
  <input type="text"
63
79
  placeholder="Long placeholder lorem ipsum dolor sit amet"
@@ -66,7 +82,7 @@
66
82
  </TextField>
67
83
 
68
84
  <TextField
69
- label="Combiné 2"
85
+ label="Combiné 2 Long placeholder lorem ipsum dolor sit amet"
70
86
  size="xs"
71
87
  >
72
88
  <input type="text"
@@ -22,17 +22,20 @@
22
22
  >
23
23
  <input type="text"
24
24
  name="text-md"
25
+ id="text-md"
25
26
  placeholder="Long placeholder lorem ipsum dolor sit amet"
26
27
  />
27
28
  </qc-textfield>
28
29
 
29
30
  <qc-textfield name="text-lg"
30
- label="Large"
31
31
  size="lg"
32
32
  placeholder="Long placeholder lorem ipsum dolor sit amet"
33
- required>
33
+ >
34
+ <label for="text-lg">Large</label>
34
35
  <input type="text"
35
36
  name="text-lg"
37
+ id="text-lg"
38
+ required
36
39
  />
37
40
  </qc-textfield>
38
41
  <qc-textfield
@@ -34,7 +34,9 @@
34
34
  rootElement = $state(),
35
35
  textFieldRow = $state(),
36
36
  defaultInvalidText = $derived.by(() => {
37
- if (!maxlengthReached) return '';
37
+ if (!maxlengthReached) {
38
+ return undefined;
39
+ }
38
40
  return lang === 'fr'
39
41
  ? `La limite de caractères du champ ${label} est dépassée.`
40
42
  : `The character limit for the ${label} field has been exceeded.`
@@ -44,13 +46,18 @@
44
46
  onMount(() => {
45
47
  if (webComponentMode) return;
46
48
  if (!input) {
47
- input = rootElement.querySelector('input,textarea');
49
+ input = rootElement?.querySelector('input,textarea');
48
50
  }
49
51
  onMountInput(
50
52
  input,
51
53
  textFieldRowParam => textFieldRow = textFieldRowParam,
52
54
  valueParam => value = valueParam,
53
- invalidParam => invalid = invalidParam
55
+ invalidParam => invalid = invalidParam,
56
+ requiredParam => {
57
+ if (requiredParam) {
58
+ required = requiredParam;
59
+ }
60
+ }
54
61
  )
55
62
  })
56
63
 
@@ -117,7 +124,6 @@
117
124
  input.setAttribute('aria-invalid', invalid)
118
125
  input.setAttribute('aria-required', required)
119
126
  })
120
-
121
127
  </script>
122
128
 
123
129
  {#snippet textfield()}
@@ -140,7 +146,7 @@
140
146
  </div>
141
147
  {/if}
142
148
 
143
- {@render children()}
149
+ {@render children?.()}
144
150
 
145
151
  {#if maxlength && maxlength !== null}
146
152
  <div
@@ -157,7 +163,7 @@
157
163
  {/if}
158
164
 
159
165
  <FormError {invalid}
160
- invalidText={invalidText ? invalidText : defaultInvalidText}
166
+ invalidText={invalidText ? invalidText : defaultInvalidText}
161
167
  label={label ? label : input?.getAttribute("aria-label")}
162
168
  bind:id={errorId}
163
169
  extraClasses={['qc-xs-mt']}
@@ -40,11 +40,22 @@
40
40
  textFieldRow = $state()
41
41
  ;
42
42
  onMount(() => {
43
- input = $host().querySelector('input,textarea');
43
+ const initialLabelElement = $host()?.querySelector('label');
44
+ if (initialLabelElement) {
45
+ label = initialLabelElement.innerHTML;
46
+ initialLabelElement.remove();
47
+ }
48
+
49
+ input = $host()?.querySelector('input,textarea');
44
50
  onMountInput(input,
45
51
  textFieldRowParam => textFieldRow = textFieldRowParam,
46
52
  valueParam => value = valueParam,
47
- invalidParam => invalid = invalidParam
53
+ invalidParam => invalid = invalidParam,
54
+ requiredParam => {
55
+ if (requiredParam) {
56
+ required = requiredParam;
57
+ }
58
+ }
48
59
  )
49
60
  })
50
61
 
@@ -55,24 +66,27 @@
55
66
 
56
67
  $effect(() => {
57
68
  if (!input) return;
58
- if (label) {
59
- input.before(labelElement);
60
- }
61
69
  if (description) {
62
70
  input.before(descriptionElement);
63
71
  }
64
- if (invalid) {
65
- if (textFieldRow) {
66
- textFieldRow.appendChild(formErrorElement);
67
- }
68
- else {
69
- input.after(formErrorElement);
70
- }
71
- }
72
72
  if (maxlength) {
73
73
  input.after(maxlengthElement);
74
74
  }
75
75
  })
76
+
77
+ $effect(() => {
78
+ if (!formErrorElement) return;
79
+ if (textFieldRow) {
80
+ textFieldRow.appendChild(formErrorElement);
81
+ }
82
+ else {
83
+ if (maxlengthElement) {
84
+ maxlengthElement.after(formErrorElement);
85
+ } else {
86
+ input.after(formErrorElement);
87
+ }
88
+ }
89
+ })
76
90
  </script>
77
91
 
78
92
  <TextField
@@ -182,11 +182,6 @@
182
182
  </table>
183
183
  </div>
184
184
 
185
- <h4>Champs alignés horizontalement (classe <code>qc-textfield-row</code>)</h4>
186
-
187
- <p>Les champs regroupés sur une ligne peuvent être placés dans un div avec la classe <code>qc-textfield-row</code>. De cette façon, les messages d'erreur ne provoquent pas de décalage. <br/>
188
- Voir le code des champs Téléphone et Poste dans l'exemple ci-dessus.</p>
189
-
190
185
  <h4>Propriété js</h4>
191
186
  <div class="table-overflow">
192
187
  <table class="qc-table qc-striped component-attributes-description">
@@ -1,6 +1,6 @@
1
1
  import {Utils} from "../utils";
2
2
 
3
- export function onMountInput(input, setTextFieldRow, setValue, setInvalid) {
3
+ export function onMountInput(input, setTextFieldRow, setValue, setInvalid, setRequired) {
4
4
  if (!input) return;
5
5
  if (!input.autocomplete) {
6
6
  input.autocomplete = "off"
@@ -8,7 +8,8 @@ export function onMountInput(input, setTextFieldRow, setValue, setInvalid) {
8
8
  if (!input.id) {
9
9
  input.id = Utils.generateId(input.type);
10
10
  }
11
- setValue(input.value)
11
+ setValue(input.value);
12
+ setRequired(input.required);
12
13
  input.addEventListener(
13
14
  'input',
14
15
  () => {
@@ -16,15 +16,14 @@ export class Utils {
16
16
  `${this.assetsBasePath}/img/`
17
17
  .replace('//','/')
18
18
  static cssFileName =
19
- document
20
- .currentScript
21
- .getAttribute('sdg-css-filename')
22
- || 'qc-sdg.min.css'
19
+ getCssFileName(document.currentScript.getAttribute('sdg-css-filename'), document.currentScript.src);
23
20
  static cssPath =
24
- document
25
- .currentScript
26
- .getAttribute('sdg-css-path')
27
- || this.cssRelativePath + this.cssFileName
21
+ getCssPath(
22
+ document.currentScript.getAttribute('sdg-css-path'),
23
+ document.currentScript.src,
24
+ this.cssRelativePath,
25
+ this.cssFileName
26
+ );
28
27
  static sharedTexts =
29
28
  { openInNewTab :
30
29
  { fr: 'Ce lien s’ouvrira dans un nouvel onglet.'
@@ -33,8 +32,8 @@ export class Utils {
33
32
  }
34
33
 
35
34
  /**
36
- * Get current page language based on html lang attribute
37
- * @returns {string} language code (fr/en).
35
+ * Get current page language based on HTML lang attribute
36
+ * @returns {string} language code (fr/en).
38
37
  */
39
38
  static getPageLanguage() {
40
39
  return document.getElementsByTagName("html")[0].getAttribute("lang") || "fr";
@@ -56,12 +55,12 @@ export class Utils {
56
55
  /**
57
56
  * extract and clean prefixed attributes
58
57
  * example:
59
- * computeFieldsAttributes("radio" , {"radio-class":"my-radio", "radio-data-foo":"foo", "other":"other value"})
58
+ * computeFieldsAttributes("radio", {"radio-class": "my-radio", "radio-data-foo": "foo", "other": "other value"})
60
59
  * return {"class":"my-radio", "data-foo":"foo"}
61
60
  *
62
61
  </div>
63
62
  * @param {(string|string[])} prefix - Une chaîne de caractères ou un tableau de chaînes.
64
- * @param restProps - ojbect of attributes
63
+ * @param restProps - object of attributes
65
64
  * @returns {*} - object of attributes
66
65
  */
67
66
  static computeFieldsAttributes(prefix , restProps) {
@@ -125,8 +124,8 @@ export class Utils {
125
124
  word = replaceAccents(word, /[ùûü]/gi, 'u');
126
125
  word = replaceAccents(word, /[ïî]/gi, 'i');
127
126
  word = replaceAccents(word, /[ôö]/gi, 'i');
128
- word = replaceAccents(word, /[œ]/gi, 'oe');
129
- word = replaceAccents(word, /[æ]/gi, 'ae');
127
+ word = replaceAccents(word, /œ/gi, 'oe');
128
+ word = replaceAccents(word, /æ/gi, 'ae');
130
129
 
131
130
  // Remplace les caractères spéciaux par des espaces.
132
131
  word = word.replaceAll(/[-_—–]/gi, ' ');
@@ -135,4 +134,69 @@ export class Utils {
135
134
  // Convertit le mot en minuscules.
136
135
  return word.toLowerCase();
137
136
  }
137
+
138
+ static now() {
139
+ return (new Date()).getTime();
140
+ }
141
+
142
+ /**
143
+ * Creates a MutationObserver instance with selector nesting check
144
+ * @param rootElement
145
+ * @param callback
146
+ * @param selector
147
+ * @returns {MutationObserver | null}
148
+ */
149
+ static createMutationObserver(rootElement, callback, selector) {
150
+ if (!selector) {
151
+ selector = rootElement.tagName.toLowerCase();
152
+ }
153
+ if (rootElement.querySelector(selector)) {
154
+ console.warn(`Imbrication d'éléments "${selector}" détectée. Le MutationObserver n'est pas créé`);
155
+ return null;
156
+ }
157
+
158
+ return new MutationObserver(callback);
159
+ }
160
+ }
161
+
162
+ function getCacheBustingParam(cssPath, currentScriptSrc) {
163
+ const pattern = /\?.*$/;
164
+
165
+ const cssCacheBustingParam = cssPath?.match(pattern);
166
+ if (cssCacheBustingParam && cssCacheBustingParam.length > 0) {
167
+ return '';
168
+ }
169
+
170
+ const scriptCacheBustingParam = currentScriptSrc?.match(pattern);
171
+ if (scriptCacheBustingParam && scriptCacheBustingParam.length > 0) {
172
+ return scriptCacheBustingParam[0];
173
+ }
174
+
175
+ return '';
176
+ }
177
+
178
+ function getCssFileName(sdgCssFilename, src) {
179
+ const cssPattern =/^.*\.css/;
180
+
181
+ if (!cssPattern.test(sdgCssFilename)) {
182
+ return 'qc-sdg.min.css' + getCacheBustingParam(
183
+ 'qc-sdg.min.css', src
184
+ );
185
+ } else {
186
+ return sdgCssFilename + getCacheBustingParam(
187
+ sdgCssFilename, src
188
+ );
189
+ }
190
+ }
191
+
192
+ function getCssPath(sdgCssPath, src, cssRelativePath, cssFileName) {
193
+ const cssPattern =/^.*\.css/;
194
+
195
+ if (!cssPattern.test(sdgCssPath)) {
196
+ return cssRelativePath + cssFileName;
197
+ } else {
198
+ return sdgCssPath + getCacheBustingParam(
199
+ sdgCssPath, src
200
+ );
201
+ }
138
202
  }
@@ -7,4 +7,5 @@ export * from './components/TextField/Test/TextFieldEmbededTest.svelte';
7
7
  export * from "./components/DropdownList/Test/DropdownListSvelteTest.svelte";
8
8
  export * from "./components/ChoiceGroup/Test/ChoiceGroupeEmbededTest.svelte";
9
9
  export * from "./components/ToggleSwitch/Test/ToggleSwitchEmbeddedTest.svelte";
10
- export * from "./components/PivHeader/Test/pivHeaderEmbeddedTest.svelte";
10
+ export * from "./components/PivHeader/Test/pivHeaderEmbeddedTest.svelte";
11
+ export * from "./components/Alert/Test/AlertSvelteTest.svelte";