qc-trousse-sdg 1.4.0-develop.1 → 1.4.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.
Files changed (294) hide show
  1. package/README.md +26 -5
  2. package/dist/css/qc-sdg-design-tokens.min.css +1 -1
  3. package/dist/css/qc-sdg-no-grid.min.css +1 -1
  4. package/dist/css/qc-sdg.min.css +1 -1
  5. package/dist/fonts/open-sans-v43-latin-500.woff2 +0 -0
  6. package/dist/fonts/open-sans-v43-latin-500italic.woff2 +0 -0
  7. package/dist/fonts/open-sans-v43-latin-600.woff2 +0 -0
  8. package/dist/fonts/open-sans-v43-latin-600italic.woff2 +0 -0
  9. package/dist/fonts/open-sans-v43-latin-700.woff2 +0 -0
  10. package/dist/fonts/open-sans-v43-latin-700italic.woff2 +0 -0
  11. package/dist/fonts/open-sans-v43-latin-italic.woff2 +0 -0
  12. package/dist/fonts/open-sans-v43-latin-regular.woff2 +0 -0
  13. package/dist/fonts/roboto-mono-v30-latin-500.woff2 +0 -0
  14. package/dist/fonts/roboto-mono-v30-latin-500italic.woff2 +0 -0
  15. package/dist/fonts/roboto-mono-v30-latin-600.woff2 +0 -0
  16. package/dist/fonts/roboto-mono-v30-latin-600italic.woff2 +0 -0
  17. package/dist/fonts/roboto-mono-v30-latin-700.woff2 +0 -0
  18. package/dist/fonts/roboto-mono-v30-latin-700italic.woff2 +0 -0
  19. package/dist/fonts/roboto-mono-v30-latin-italic.woff2 +0 -0
  20. package/dist/fonts/roboto-mono-v30-latin-regular.woff2 +0 -0
  21. package/dist/fonts/roboto-v48-latin-500.woff2 +0 -0
  22. package/dist/fonts/roboto-v48-latin-500italic.woff2 +0 -0
  23. package/dist/fonts/roboto-v48-latin-600.woff2 +0 -0
  24. package/dist/fonts/roboto-v48-latin-600italic.woff2 +0 -0
  25. package/dist/fonts/roboto-v48-latin-700.woff2 +0 -0
  26. package/dist/fonts/roboto-v48-latin-700italic.woff2 +0 -0
  27. package/dist/fonts/roboto-v48-latin-italic.woff2 +0 -0
  28. package/dist/fonts/roboto-v48-latin-regular.woff2 +0 -0
  29. package/dist/img/icon/adresse.svg +4 -0
  30. package/dist/img/icon/arrow-up.svg +3 -0
  31. package/dist/img/icon/calendar.svg +1 -0
  32. package/dist/img/icon/checkmark.svg +3 -0
  33. package/dist/img/icon/chevron-up-thin.svg +5 -0
  34. package/dist/img/{chevron-white.svg → icon/chevron-up.svg} +1 -1
  35. package/{public/img → dist/img/icon}/clipboard.svg +3 -3
  36. package/dist/img/icon/clock.svg +1 -0
  37. package/dist/img/icon/email.svg +1 -0
  38. package/dist/img/icon/error.svg +1 -0
  39. package/{public/img/exclamation-white.svg → dist/img/icon/exclamation.svg} +2 -2
  40. package/{public/img → dist/img/icon}/external-link.svg +2 -2
  41. package/dist/img/icon/information.svg +1 -0
  42. package/dist/img/icon/ligth-bulb.svg +1 -0
  43. package/{public/img → dist/img/icon}/minus.svg +1 -1
  44. package/dist/img/icon/note.svg +1 -0
  45. package/dist/img/icon/phone.svg +1 -0
  46. package/dist/img/{plus.svg → icon/plus.svg} +1 -1
  47. package/{public/img → dist/img/icon}/question-mark.svg +2 -2
  48. package/dist/img/icon/search-thin.svg +10 -0
  49. package/dist/img/icon/search.svg +1 -0
  50. package/dist/img/icon/success.svg +1 -0
  51. package/dist/img/icon/user.svg +6 -0
  52. package/dist/img/icon/warning.svg +1 -0
  53. package/dist/img/icon/website.svg +1 -0
  54. package/dist/img/icon/xclose.svg +1 -0
  55. package/dist/js/qc-sdg.min.js +1 -1
  56. package/package.json +11 -3
  57. package/playwright.config.ts +79 -0
  58. package/plugins/buildDevDoc.js +36 -0
  59. package/plugins/buildHtmlDoc.js +43 -0
  60. package/plugins/buildTestFixtures.js +37 -0
  61. package/public/css/qc-doc-sdg.css +4 -67
  62. package/public/css/qc-sdg-design-tokens.css +17 -0
  63. package/public/css/qc-sdg-no-grid.css +1991 -1108
  64. package/public/css/qc-sdg.css +1992 -1109
  65. package/public/img/checkmark.svg +3 -0
  66. package/public/img/question.svg +10 -0
  67. package/public/index.html +3104 -1387
  68. package/public/js/qc-doc-sdg.js +40847 -33699
  69. package/public/js/qc-sdg.js +6037 -757
  70. package/rollup.config.js +67 -41
  71. package/scripts/buildImagesMap.js +85 -0
  72. package/scripts/check-release-note.sh +11 -0
  73. package/scripts/compile-doc.sh +4 -0
  74. package/src/doc/_index.html +100 -0
  75. package/src/doc/_nav.html +53 -0
  76. package/src/doc/_test.html +32 -0
  77. package/src/doc/components/Code.svelte +6 -2
  78. package/src/doc/components/TopNav.svelte +8 -9
  79. package/src/doc/components/color-doc.svelte +1 -1
  80. package/src/doc/ejs/layout/index.ejs +129 -0
  81. package/src/doc/qc-doc-sdg.js +1 -2
  82. package/src/doc/scss/components/_code.scss +1 -1
  83. package/src/doc/scss/jQueryUI/_jquery-ui.autocomplete.scss +1 -0
  84. package/src/doc/scss/qc-doc-sdg.scss +1 -1
  85. package/src/doc/scss/settings/_base.scss +4 -0
  86. package/src/sdg/_components.js +9 -2
  87. package/src/sdg/{components → bases}/Icon/Icon.svelte +13 -6
  88. package/src/sdg/bases/Icon/IconDoc.ejs +129 -0
  89. package/src/sdg/{components → bases}/Icon/IconWC.svelte +3 -1
  90. package/src/sdg/bases/Icon/Test/IconEmbeddedTest.html +1 -0
  91. package/src/sdg/bases/Icon/Test/IconEmbeddedTest.svelte +168 -0
  92. package/src/sdg/bases/Icon/Test/iconTest.html +156 -0
  93. package/src/sdg/bases/Icon/_icon.html +254 -0
  94. package/src/sdg/bases/Icon/_icons.scss +47 -0
  95. package/src/sdg/{scss/base → bases/accessibility}/_accessibility.scss +1 -1
  96. package/src/sdg/bases/colors/_colors.html +112 -0
  97. package/src/sdg/bases/figures/_figure.html +16 -0
  98. package/src/sdg/{scss/base → bases/form}/_form.scss +10 -3
  99. package/src/sdg/bases/grid/_grid.html +118 -0
  100. package/src/sdg/bases/headings/_headings.html +18 -0
  101. package/src/sdg/bases/headings/_headings.scss +25 -0
  102. package/src/sdg/{scss/base → bases/layout}/_layout.scss +1 -4
  103. package/src/sdg/bases/links/_links.html +104 -0
  104. package/src/sdg/bases/links/_links.scss +51 -0
  105. package/src/sdg/bases/lists/_lists.html +27 -0
  106. package/src/sdg/bases/separator/_separator.html +7 -0
  107. package/src/sdg/bases/separator/_separator.scss +5 -0
  108. package/src/sdg/bases/shadings/_shadings.html +14 -0
  109. package/src/sdg/{scss/base → bases/shadings}/_shadings.scss +1 -1
  110. package/src/sdg/bases/typography/_font.html +45 -0
  111. package/src/sdg/bases/typography/_fonts.scss +162 -0
  112. package/src/sdg/bases/typography/_paragraph.html +17 -0
  113. package/src/sdg/bases/typography/_paragraph.scss +33 -0
  114. package/src/sdg/components/Alert/Alert.svelte +2 -5
  115. package/src/sdg/components/Alert/AlertWC.svelte +3 -2
  116. package/src/sdg/components/Alert/_alert.html +110 -0
  117. package/src/sdg/{scss/components → components/Alert}/_alert.scss +1 -1
  118. package/src/sdg/components/Button/Button.svelte +50 -0
  119. package/src/sdg/components/Button/ButtonWC.svelte +36 -0
  120. package/src/sdg/components/Button/Test/buttonTest.html +349 -0
  121. package/src/sdg/components/Button/_button.html +186 -0
  122. package/src/sdg/components/Button/_button.scss +202 -0
  123. package/src/sdg/components/CharCount/_charCount.html +7 -0
  124. package/src/sdg/components/Checkbox/Checkbox.svelte +77 -0
  125. package/src/sdg/components/Checkbox/CheckboxWC.svelte +49 -0
  126. package/src/sdg/components/Checkbox/_checkbox.html +86 -0
  127. package/src/sdg/components/Checkbox/_checkbox.scss +70 -0
  128. package/src/sdg/components/Checkbox/updateInput.svelte.js +23 -0
  129. package/src/sdg/components/ChoiceGroup/ChoiceGroup.svelte +56 -0
  130. package/src/sdg/components/ChoiceGroup/ChoiceGroupWC.svelte +47 -0
  131. package/src/sdg/components/ChoiceGroup/Test/ChoiceGroupeEmbededTest.svelte +261 -0
  132. package/src/sdg/components/ChoiceGroup/Test/checkboxEmbeddedTest.html +1 -0
  133. package/src/sdg/components/ChoiceGroup/Test/checkboxTest.html +253 -0
  134. package/src/sdg/components/ChoiceGroup/Test/radiosEmbeddedTest.html +1 -0
  135. package/src/sdg/components/ChoiceGroup/Test/radiosTest.html +185 -0
  136. package/src/sdg/components/ChoiceGroup/ToggleSwitchGroupWC.svelte +56 -0
  137. package/src/sdg/components/ChoiceGroup/_choiceGroup.html +285 -0
  138. package/src/sdg/components/ChoiceGroup/_choiceGroup.scss +32 -0
  139. package/src/sdg/components/ChoiceGroup/_selectionButton.scss +53 -0
  140. package/src/sdg/components/ChoiceGroup/_selectionButtons.html +130 -0
  141. package/src/sdg/components/DropdownList/DropdownList.svelte +394 -0
  142. package/src/sdg/components/DropdownList/DropdownListButton/DropdownListButton.svelte +42 -0
  143. package/src/sdg/components/DropdownList/DropdownListButton/_dropdownListButton.scss +55 -0
  144. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItems.svelte +110 -0
  145. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsMultiple/DropdownListItemsMultiple.svelte +185 -0
  146. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsMultiple/_dropdownListItemsMultiple.scss +19 -0
  147. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsSingle/DropdownListItemsSingle.svelte +136 -0
  148. package/src/sdg/components/DropdownList/DropdownListItems/DropdownListItemsSingle/_dropdownListItemsSingle.scss +11 -0
  149. package/src/sdg/components/DropdownList/DropdownListItems/_dropdownListItems.scss +67 -0
  150. package/src/sdg/components/DropdownList/SelectWC.svelte +158 -0
  151. package/src/sdg/components/DropdownList/Test/DropdownListEmbeddedTest.svelte +89 -0
  152. package/src/sdg/components/DropdownList/Test/dropdownListEmbeddedTest.html +1 -0
  153. package/src/sdg/components/DropdownList/Test/dropdownListTest.html +194 -0
  154. package/src/sdg/components/DropdownList/Test/dropdownListTestUtils.js +113 -0
  155. package/src/sdg/components/DropdownList/_dropdownList.scss +73 -0
  156. package/src/sdg/components/DropdownList/_select.html +212 -0
  157. package/src/sdg/components/ExternalLink/ExternalLink.svelte +1 -1
  158. package/src/sdg/components/Fieldset/Fieldset.svelte +73 -0
  159. package/src/sdg/components/Fieldset/_fieldset.scss +95 -0
  160. package/src/sdg/components/FormError/FormError.svelte +51 -0
  161. package/src/sdg/components/FormError/_formError.scss +21 -0
  162. package/src/sdg/components/FormfieldRow/_formfieldRow.html +108 -0
  163. package/src/sdg/components/IconButton/IconButton.svelte +1 -1
  164. package/src/sdg/components/IconButton/_iconButton.scss +14 -0
  165. package/src/sdg/components/Label/Label.svelte +28 -0
  166. package/src/sdg/components/Label/LabelText.svelte +4 -0
  167. package/src/sdg/components/Label/_label.scss +19 -0
  168. package/src/sdg/components/Notice/Notice.svelte +1 -2
  169. package/src/sdg/components/Notice/NoticeWC.svelte +3 -0
  170. package/src/sdg/components/Notice/_notice.html +141 -0
  171. package/src/sdg/{scss/components → components/Notice}/_notice.scss +1 -1
  172. package/src/sdg/components/PivFooter/PivFooter.svelte +8 -9
  173. package/src/sdg/components/PivFooter/PivFooterWC.svelte +6 -14
  174. package/src/sdg/components/PivFooter/_pivFooter.html +153 -0
  175. package/src/sdg/{scss/components → components/PivFooter}/_pivFooter.scss +1 -1
  176. package/src/sdg/components/PivHeader/PivHeader.svelte +47 -53
  177. package/src/sdg/components/PivHeader/PivHeaderWC.svelte +9 -20
  178. package/src/sdg/components/PivHeader/Test/pivHeaderEmbeddedTest.html +1 -0
  179. package/src/sdg/components/PivHeader/Test/pivHeaderEmbeddedTest.svelte +28 -0
  180. package/src/sdg/components/PivHeader/Test/pivHeaderTest.html +43 -0
  181. package/src/sdg/components/PivHeader/_pivHeader.html +221 -0
  182. package/src/sdg/{scss/components → components/PivHeader}/_pivHeader.scss +55 -77
  183. package/src/sdg/components/RadioButton/_radioButton.html +24 -0
  184. package/src/sdg/components/RadioButton/_radioButton.scss +29 -0
  185. package/src/sdg/components/SearchBar/SearchBar.svelte +12 -32
  186. package/src/sdg/components/SearchBar/_searchBar.html +125 -0
  187. package/src/sdg/{scss/components → components/SearchBar}/_searchBar.scss +3 -3
  188. package/src/sdg/components/SearchInput/SearchInput.svelte +26 -4
  189. package/src/sdg/components/SearchInput/SearchInputWC.svelte +3 -1
  190. package/src/sdg/components/SearchInput/_searchInput.html +85 -0
  191. package/src/sdg/{scss/components → components/SearchInput}/_searchInput.scss +27 -2
  192. package/src/sdg/components/TextField/Doc/TextFieldDemo.svelte +143 -0
  193. package/src/sdg/components/TextField/Test/TextFieldEmbededTest.svelte +129 -0
  194. package/src/sdg/components/TextField/Test/textFieldEmbeddedTest.html +1 -0
  195. package/src/sdg/components/TextField/Test/textFieldTest.html +121 -0
  196. package/src/sdg/components/TextField/TextField.svelte +173 -0
  197. package/src/sdg/components/TextField/TextFieldWC.svelte +90 -0
  198. package/src/sdg/components/TextField/_textField.html +218 -0
  199. package/src/sdg/components/TextField/_textField.scss +110 -0
  200. package/src/sdg/components/TextField/textFieldUtils.js +19 -0
  201. package/src/sdg/components/ToTop/ToTop.svelte +2 -4
  202. package/src/sdg/components/ToTop/_toTop.html +45 -0
  203. package/src/sdg/{scss/components → components/ToTop}/_toTop.scss +2 -2
  204. package/src/sdg/components/ToggleSwitch/Test/ToggleSwitchEmbeddedTest.svelte +46 -0
  205. package/src/sdg/components/ToggleSwitch/Test/toggleSwitchEmbeddedTest.html +1 -0
  206. package/src/sdg/components/ToggleSwitch/Test/toggleSwitchTest.html +34 -0
  207. package/src/sdg/components/ToggleSwitch/ToggleSwitch.svelte +34 -0
  208. package/src/sdg/components/ToggleSwitch/ToggleSwitchWC.svelte +66 -0
  209. package/src/sdg/components/ToggleSwitch/_toggleSwitch.html +160 -0
  210. package/src/sdg/components/ToggleSwitch/_toggleSwitch.scss +97 -0
  211. package/src/sdg/components/utils.js +81 -1
  212. package/src/sdg/qc-sdg-test.js +6 -0
  213. package/src/sdg/scss/lib/_functions.scss +10 -2
  214. package/src/sdg/scss/lib/_mixins.scss +63 -26
  215. package/src/sdg/scss/qc-sdg.scss +1 -1
  216. package/src/sdg/scss/qc-sgd-no-grid.scss +30 -18
  217. package/src/sdg/scss/settings/_base.scss +5 -33
  218. package/src/sdg/scss/settings/_images.scss +30 -0
  219. package/src/sdg/scss/settings/_tokens.scss +23 -0
  220. package/src/sdg/scss/utilities/_display.scss +1 -1
  221. package/src/sdg/scss/utilities/_states.scss +13 -0
  222. package/tests/button.spec.ts +11 -0
  223. package/tests/choice-group.spec.ts +36 -0
  224. package/tests/dropdown-list.spec.ts +529 -0
  225. package/tests/icon.spec.ts +19 -0
  226. package/tests/pivHeader.spec.ts +22 -0
  227. package/tests/textfield-svelte.spec.ts +28 -0
  228. package/tests/textfield.spec.ts +37 -0
  229. package/tests/toggle-switch.spec.ts +20 -0
  230. package/dist/img/arrow-up-white.svg +0 -3
  231. package/dist/img/chevron-blue.svg +0 -3
  232. package/dist/img/clipboard.svg +0 -8
  233. package/dist/img/error-white.svg +0 -1
  234. package/dist/img/error.svg +0 -1
  235. package/dist/img/exclamation-white.svg +0 -37
  236. package/dist/img/external-link-white.svg +0 -18
  237. package/dist/img/external-link.svg +0 -10
  238. package/dist/img/facebook.svg +0 -6
  239. package/dist/img/information-white.svg +0 -1
  240. package/dist/img/information.svg +0 -1
  241. package/dist/img/linkedin.svg +0 -5
  242. package/dist/img/loupe-piv-fonce.svg +0 -1
  243. package/dist/img/minus.svg +0 -6
  244. package/dist/img/qc-sprite.svg +0 -1
  245. package/dist/img/question-mark.svg +0 -47
  246. package/dist/img/success-white.svg +0 -1
  247. package/dist/img/success.svg +0 -1
  248. package/dist/img/twitter.svg +0 -8
  249. package/dist/img/warning.svg +0 -1
  250. package/dist/img/xclose-blue.svg +0 -6
  251. package/dist/img/xclose-white.svg +0 -1
  252. package/dist/img/youtube.svg +0 -3
  253. package/public/img/ampoule.svg +0 -1
  254. package/public/img/arrow-up-white.svg +0 -3
  255. package/public/img/chevron-blue.svg +0 -3
  256. package/public/img/chevron-white.svg +0 -3
  257. package/public/img/error-white.svg +0 -1
  258. package/public/img/error.svg +0 -1
  259. package/public/img/external-link-white.svg +0 -18
  260. package/public/img/facebook.svg +0 -6
  261. package/public/img/information-white.svg +0 -1
  262. package/public/img/information.svg +0 -1
  263. package/public/img/linkedin.svg +0 -5
  264. package/public/img/logo-piv-footer-mess.png +0 -0
  265. package/public/img/loupe-piv-droite.svg +0 -1
  266. package/public/img/loupe-piv-fonce.svg +0 -1
  267. package/public/img/note.svg +0 -1
  268. package/public/img/piv-bas-MCE-theme-clair.png +0 -0
  269. package/public/img/piv-bas-MCE-theme-sombre.png +0 -0
  270. package/public/img/piv-logo-pied-de-page.svg +0 -37
  271. package/public/img/plus.svg +0 -6
  272. package/public/img/qc-sprite.svg +0 -1
  273. package/public/img/quebec-logo.svg +0 -13
  274. package/public/img/success-white.svg +0 -1
  275. package/public/img/success.svg +0 -1
  276. package/public/img/twitter.svg +0 -8
  277. package/public/img/warning.svg +0 -1
  278. package/public/img/xclose-blue.svg +0 -6
  279. package/public/img/xclose-white.svg +0 -1
  280. package/public/img/youtube.svg +0 -3
  281. package/src/doc/scss/components/_button.scss +0 -61
  282. package/src/sdg/components/PivFooter/_defaultCopyright.svelte +0 -11
  283. package/src/sdg/components/PivHeader/_defaultLinks.svelte +0 -24
  284. package/src/sdg/components/QcCustomElement.js +0 -10
  285. package/src/sdg/scss/base/_fonts.scss +0 -29
  286. package/src/sdg/scss/base/_typography.scss +0 -94
  287. package/src/sdg/scss/components/_icons.scss +0 -169
  288. package/src/sdg/scss/components/_separator.scss +0 -5
  289. /package/dist/img/{loupe-piv-droite.svg → piv-search.svg} +0 -0
  290. /package/src/sdg/{scss/base → bases/colors}/_colors.scss +0 -0
  291. /package/src/sdg/{scss/base → bases/figures}/_figure.scss +0 -0
  292. /package/src/sdg/{scss → bases}/grid/_grid-lib.scss +0 -0
  293. /package/src/sdg/{scss → bases}/grid/_grid.scss +0 -0
  294. /package/src/sdg/{scss/base → bases/lists}/_lists.scss +0 -0
@@ -0,0 +1,173 @@
1
+ <script>
2
+ import { Utils } from "../utils";
3
+ import Label from "../Label/Label.svelte";
4
+ import {getContext, onMount} from "svelte";
5
+ import FormError from "../FormError/FormError.svelte";
6
+ import {onMountInput} from "./textFieldUtils";
7
+
8
+ const lang = Utils.getPageLanguage();
9
+
10
+ let {
11
+ label = '',
12
+ required = $bindable(false),
13
+ description,
14
+ size,
15
+ maxlength,
16
+ maxlengthReached = $bindable(false),
17
+ invalidAtSubmit = $bindable(false),
18
+ value = $bindable(""),
19
+ invalid = $bindable(false),
20
+ invalidText,
21
+ describedBy = $bindable([]),
22
+ labelElement = $bindable(),
23
+ formErrorElement = $bindable(),
24
+ descriptionElement = $bindable(),
25
+ maxlengthElement = $bindable(),
26
+ input,
27
+ children
28
+ } = $props();
29
+
30
+ const webComponentMode = getContext('webComponentMode');
31
+
32
+ let errorId = $state(),
33
+ charCountText = $state(),
34
+ rootElement = $state(),
35
+ textFieldRow = $state(),
36
+ defaultInvalidText = $derived.by(() => {
37
+ if (!maxlengthReached) return '';
38
+ return lang === 'fr'
39
+ ? `La limite de caractères du champ ${label} est dépassée.`
40
+ : `The character limit for the ${label} field has been exceeded.`
41
+ })
42
+ ;
43
+
44
+ onMount(() => {
45
+ if (webComponentMode) return;
46
+ if (! input) {
47
+ input = rootElement.querySelector('input,textarea');
48
+ }
49
+ onMountInput(
50
+ input,
51
+ textFieldRowParam => textFieldRow = textFieldRowParam,
52
+ valueParam => value = valueParam,
53
+ invalidParam => invalid = invalidParam
54
+ )
55
+ })
56
+
57
+ $effect(() => {
58
+ invalidAtSubmit = (required && !value) || maxlengthReached;
59
+ })
60
+
61
+ $effect(() => {
62
+ if (webComponentMode) return;
63
+ if (invalid && textFieldRow) {
64
+ textFieldRow.appendChild(formErrorElement);
65
+ }
66
+ })
67
+
68
+ $effect(() => {
69
+ if (maxlength && maxlength < 1) {
70
+ maxlength = 0;
71
+ }
72
+ })
73
+
74
+
75
+
76
+ $effect(() => {
77
+ charCountText = ''
78
+ if (!maxlength) return;
79
+ const currentLength = value?.length || 0;
80
+ const remaining = maxlength - currentLength;
81
+ const over = Math.abs(remaining);
82
+ maxlengthReached = remaining < 0;
83
+ const s = over > 1 ? 's' : '';
84
+ charCountText =
85
+ remaining >= 0
86
+ ? lang === 'fr'
87
+ ? `${remaining} caractère${s} restant${s}`
88
+ : `${remaining} character${s} remaining`
89
+ : lang === 'fr'
90
+ ? `${over} caractère${s} en trop`
91
+ : `${over} character${s} over the limit`
92
+
93
+ });
94
+
95
+ // Génération des ID pour le aria-describedby
96
+ const
97
+ descriptionId = Utils.generateId('description-'),
98
+ charCountId = Utils.generateId('charcount-')
99
+ ;
100
+
101
+ $effect(() => {
102
+ if (!input) return;
103
+ input.setAttribute(
104
+ "aria-describedby",
105
+ [
106
+ description && descriptionId,
107
+ invalid && errorId,
108
+ maxlength && charCountId,
109
+ ].filter(Boolean)
110
+ .join(' ')
111
+ )
112
+ input.setAttribute('aria-invalid', invalid)
113
+ input.setAttribute('aria-required', required)
114
+ })
115
+
116
+ </script>
117
+
118
+ {#snippet textfield()}
119
+
120
+ {#if label}
121
+ <Label
122
+ {required}
123
+ disabled={input?.disabled}
124
+ text={label}
125
+ forId={input?.id}
126
+ bind:rootElement={labelElement}
127
+ />
128
+ {/if}
129
+
130
+ {#if description}
131
+ <div
132
+ bind:this={descriptionElement}
133
+ id={descriptionId}
134
+ class="qc-description">
135
+ {@html description}
136
+ </div>
137
+ {/if}
138
+
139
+ {@render children()}
140
+
141
+ {#if maxlength !== null}
142
+ <div
143
+ bind:this={maxlengthElement}
144
+ id={charCountId}
145
+ class={[
146
+ 'qc-textfield-charcount',
147
+ maxlengthReached && 'qc-max-reached'
148
+ ]}
149
+ aria-live="polite"
150
+ >
151
+ {@html charCountText}
152
+ </div>
153
+ {/if}
154
+
155
+ <FormError {invalid}
156
+ invalidText={invalidText ? invalidText : defaultInvalidText}
157
+ label={label ? label : input?.getAttribute("aria-label")}
158
+ bind:id={errorId}
159
+ extraClasses={['qc-xs-mt']}
160
+ bind:rootElement={formErrorElement}
161
+ />
162
+ {/snippet}
163
+ {#if webComponentMode}
164
+ {@render textfield()}
165
+ {:else}
166
+ <div class='qc-textfield'
167
+ {size}
168
+ invalid={invalid ? true : undefined}
169
+ bind:this={rootElement}
170
+ >
171
+ {@render textfield()}
172
+ </div>
173
+ {/if}
@@ -0,0 +1,90 @@
1
+ <svelte:options customElement={{
2
+ tag: 'qc-textfield',
3
+ props: {
4
+ label: { attribute: 'label', type: 'String' },
5
+ required: { attribute: 'required', type: 'Boolean' },
6
+ description: { attribute: 'description', type: 'String' },
7
+ size: { attribute: 'size', type: 'String' },
8
+ maxlength: { attribute: 'max-length', type: 'Number' },
9
+ invalid: { attribute: 'invalid', type: 'Boolean', reflect: true },
10
+ invalidText: { attribute: 'invalid-text', type: 'String' },
11
+ }
12
+ }} />
13
+
14
+ <script>
15
+ import TextField from './TextField.svelte';
16
+ import {onMount, setContext} from "svelte";
17
+ import {Utils} from '../utils.js';
18
+ import {onMountInput} from "./textFieldUtils";
19
+
20
+ setContext('webComponentMode', true)
21
+
22
+ let {
23
+ invalid = $bindable(false),
24
+ invalidText,
25
+ label,
26
+ description,
27
+ required,
28
+ maxlength,
29
+ maxlengthReached = $bindable(false),
30
+ invalidAtSubmit = $bindable(false),
31
+ } = $props();
32
+ let
33
+ labelElement = $state(),
34
+ formErrorElement = $state(),
35
+ descriptionElement = $state(),
36
+ maxlengthElement = $state(),
37
+ value = $state(),
38
+ input = $state(),
39
+ textFieldRow = $state()
40
+ ;
41
+ onMount(() => {
42
+ input = $host().querySelector('input,textarea');
43
+ onMountInput(input,
44
+ textFieldRowParam => textFieldRow = textFieldRowParam,
45
+ valueParam => value = valueParam,
46
+ invalidParam => invalid = invalidParam
47
+ )
48
+ })
49
+ $effect(() => {
50
+ if (!input) return;
51
+ if (label) {
52
+ input.before(labelElement);
53
+ }
54
+ if (description) {
55
+ input.before(descriptionElement);
56
+ }
57
+ if (invalid) {
58
+ if (textFieldRow) {
59
+ textFieldRow.appendChild(formErrorElement);
60
+ }
61
+ else {
62
+ input.after(formErrorElement);
63
+ }
64
+ }
65
+ if (maxlength) {
66
+ input.after(maxlengthElement);
67
+ }
68
+ })
69
+ </script>
70
+
71
+ <TextField
72
+ {label}
73
+ {description}
74
+ {input}
75
+ {required}
76
+ {maxlength}
77
+ {value}
78
+ bind:invalid
79
+ bind:invalidText
80
+ bind:maxlengthReached
81
+ bind:invalidAtSubmit
82
+ bind:labelElement
83
+ bind:formErrorElement
84
+ bind:descriptionElement
85
+ bind:maxlengthElement
86
+ >
87
+ <slot></slot>
88
+ </TextField>
89
+
90
+ <link rel='stylesheet' href='{Utils.cssPath}'>
@@ -0,0 +1,218 @@
1
+ <h3 id="textfield">Champ texte</h3>
2
+ <h4>Exemples</h4>
3
+
4
+ <qc-doc-exemple caption="Exemples 1 - différents champs de texte. Soumettre le formulaire pour voir les messages d'erreur.">
5
+ <form id="formulaire-champs-textes">
6
+ <qc-textfield
7
+ label="Nom complet"
8
+ size="md"
9
+ required
10
+ >
11
+ <input type="text"
12
+ name="code-postal"
13
+ placeholder="ex : Jean Tremblay"
14
+ />
15
+ </qc-textfield>
16
+
17
+ <qc-textfield
18
+ label="Champ désactivé"
19
+ size="md"
20
+ >
21
+ <input type="text"
22
+ name="disabled-field"
23
+ placeholder="Ce champ est désactivé"
24
+ disabled
25
+ />
26
+ </qc-textfield>
27
+
28
+ <qc-textfield
29
+ label="Champ de texte multiligne"
30
+ description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
31
+ size="lg"
32
+ max-length="10"
33
+ required
34
+ >
35
+ <textarea name="zone-xxl"></textarea>
36
+ </qc-textfield>
37
+
38
+ <button type="submit" class="qc-button qc-primary qc-compact">Envoyer</button>
39
+ </form>
40
+
41
+ <script>
42
+ const textfieldForm = document.getElementById("formulaire-champs-textes");
43
+ textfieldForm.addEventListener("submit", (event) => {
44
+ event.preventDefault();
45
+ let isValid = true;
46
+ textfieldForm
47
+ .querySelectorAll("qc-textfield[required]")
48
+ .forEach(formfield => {
49
+ if (formfield.invalidAtSubmit) {
50
+ formfield.invalid = true;
51
+ isValid = false;
52
+ }
53
+ })
54
+ if (isValid) {
55
+ const formData = new FormData(textfieldForm);
56
+ let alertParts = ["Formulaire soumis avec les données suivantes :"];
57
+ for (const [key, val] of formData.entries()) {
58
+ alertParts.push(`${key} : ${val}`);
59
+ }
60
+ alert(alertParts.join("\n"));
61
+ }
62
+ });
63
+ </script>
64
+ </qc-doc-exemple>
65
+
66
+ <qc-doc-exemple id="textfield-sizes" caption="Illustration des différentes tailles de champs texte.">
67
+
68
+ <qc-textfield
69
+ label="Taille extra-petite"
70
+ size="xs"
71
+ >
72
+ <input type="text"
73
+ placeholder="xs"
74
+ />
75
+ </qc-textfield>
76
+
77
+ <qc-textfield
78
+ label="Taille petite"
79
+ size="sm"
80
+ >
81
+ <input type="text"
82
+ placeholder="sm"
83
+ />
84
+ </qc-textfield>
85
+
86
+ <qc-textfield
87
+ label="Taille moyenne"
88
+ size="md"
89
+ >
90
+ <input type="text"
91
+ placeholder="md"
92
+ />
93
+ </qc-textfield>
94
+ <qc-textfield
95
+ label="Taille large"
96
+ size="lg"
97
+ >
98
+ <input type="text"
99
+ placeholder="lg"
100
+ />
101
+ </qc-textfield>
102
+ <qc-textfield
103
+ label="Taille extra-large"
104
+ size="xl"
105
+ >
106
+ <input type="text"
107
+ placeholder="xl"
108
+ />
109
+ </qc-textfield>
110
+
111
+ </qc-doc-exemple>
112
+
113
+
114
+ <h4>Documentation technique</h4>
115
+
116
+ <h4>Attributs</h4>
117
+ <div class="table-overflow">
118
+ <table class="qc-table qc-striped component-attributes-description">
119
+ <thead>
120
+ <tr>
121
+ <th>Nom</th>
122
+ <th>Valeur attendue</th>
123
+ <th>Valeur par défaut</th>
124
+ <th>Description</th>
125
+ </tr>
126
+ </thead>
127
+ <tbody>
128
+ <tr>
129
+ <td>label</td>
130
+ <td>Texte</td>
131
+ <td>""</td>
132
+ <td>Texte du libellé du champ</td>
133
+ </tr>
134
+ <tr>
135
+ <td>size</td>
136
+ <td>"xs", "sm", "md", "lg", "xl"</td>
137
+ <td>lg pour les champs simple (<code>input</code>) <br>
138
+ xl pour les champs multilignes (<code>textarea</code>),
139
+ </td>
140
+ <td>Largeur du champ</td>
141
+ </tr>
142
+ <tr>
143
+ <td>required</td>
144
+ <td>na</td>
145
+ <td>na</td>
146
+ <td>Marque le champ comme obligatoire</td>
147
+ </tr>
148
+ <tr>
149
+ <td>description</td>
150
+ <td>Texte</td>
151
+ <td>""</td>
152
+ <td>Texte descriptif affiché sous l'étiquette</td>
153
+ </tr>
154
+ <tr>
155
+ <td>max-length</td>
156
+ <td>Nombre</td>
157
+ <td>null</td>
158
+ <td>Indique la limite de caractères pour le champ</td>
159
+ </tr>
160
+ <tr>
161
+ <td>invalid</td>
162
+ <td>na</td>
163
+ <td>na</td>
164
+ <td>Indique que le champ est invalide en affichant un message selon l'erreur.
165
+ <dl>
166
+ <dt>Français</dt>
167
+ <dd>Le champ XXX est obligatoire.</dd>
168
+ <dd>La limite de caractères du champ XXX est dépassée.</dd>
169
+ <dt>Anglais</dt>
170
+ <dd>XXX field is required.</dd>
171
+ <dd>The character limit for the ${label} field has been exceeded.</dd>
172
+ </dl>
173
+ </td>
174
+ </tr>
175
+ <tr>
176
+ <td>invalid-text</td>
177
+ <td>Texte</td>
178
+ <td>aucune</td>
179
+ <td>Message d'erreur personnalisé affiché lorsque le champ est invalide</td>
180
+ </tr>
181
+ </tbody>
182
+ </table>
183
+ </div>
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
+ <h4>Propriété js</h4>
191
+ <div class="table-overflow">
192
+ <table class="qc-table qc-striped component-attributes-description">
193
+ <thead>
194
+ <tr>
195
+ <th>Nom</th>
196
+ <th>Valeur</th>
197
+ <th>Description</th>
198
+ </tr>
199
+ </thead>
200
+ <tbody>
201
+ <tr>
202
+ <td>invalidAtSubmit</td>
203
+ <td>Booléen</td>
204
+ <td>Indique si le champ serait invalide s'il était soumis. La vérification porte sur <code>required</code> et <code>max-length</code></td>
205
+ </tr>
206
+ <tr>
207
+ <tr>
208
+ <td>maxlengthReached</td>
209
+ <td>Booléen</td>
210
+ <td>Indique si la limite de caractère est dépassée.</td>
211
+ </tr>
212
+ </tbody>
213
+ </table>
214
+ </div>
215
+
216
+ <h5>Zone d’ajout de contenu HTML</h5>
217
+
218
+ <p>Ce composant ne comporte qu'une seule zone d'ajout de contenu par défaut.</p>
@@ -0,0 +1,110 @@
1
+ @use "qc-sdg-lib" as *;
2
+ @use "../Label/label" as *;
3
+ @use "sass:map";
4
+
5
+ qc-textfield,
6
+ .qc-textfield {
7
+ display: block;
8
+ margin-bottom: rem(32);
9
+
10
+ .qc-description {
11
+ @include content-font(sm);
12
+ color: token-value(color blue dark);
13
+ &:has(~ :disabled) {
14
+ color: token-value(color, grey, regular);
15
+ }
16
+ }
17
+ label {
18
+ @extend .qc-label
19
+ }
20
+ }
21
+
22
+ input,
23
+ textarea {
24
+ .qc-textfield &,
25
+ qc-textfield & {
26
+ display: block;
27
+ width: 100%;
28
+ position: relative;
29
+ color: token-value(color text primary);
30
+ background-color: token-value(color background);
31
+ padding: rem(8);
32
+ text-overflow: ellipsis;
33
+ overflow: hidden;
34
+ margin-top: rem(4);
35
+ border: 1px solid token-value(color formfield border);
36
+
37
+ &::placeholder {
38
+ color: token-value(color grey medium);
39
+ font-weight: normal;
40
+ }
41
+
42
+ &:focus,
43
+ &:focus-visible {
44
+ outline: 2px solid token-value(color formfield focus outline);
45
+ border: 2px solid token-value(color formfield focus border);
46
+ padding: rem(7);
47
+ }
48
+
49
+ &:disabled {
50
+ cursor: not-allowed;
51
+ background-color: token-value(color grey pale);
52
+ border: 1px solid token-value(color, grey, regular);
53
+ }
54
+ }
55
+
56
+ [invalid] > & {
57
+ border-color: token-value(color, red, regular);
58
+ border-width: 2px;
59
+ padding: rem(7);
60
+ }
61
+
62
+ }
63
+
64
+ $sizes: map.get($lg-tokens, size, max-width);
65
+ input ,
66
+ input + .qc-textfield-charcount {
67
+ .qc-textfield &,
68
+ qc-textfield & {
69
+ max-width: token-value(size input max-width);
70
+ }
71
+ }
72
+ textarea,
73
+ textarea + .qc-textfield-charcount {
74
+ .qc-textfield &,
75
+ qc-textfield & {
76
+ max-width: token-value(size textarea max-width);
77
+ }
78
+ }
79
+
80
+ input,
81
+ textarea,
82
+ {
83
+ &,
84
+ & + .qc-textfield-charcount {
85
+ @each $size, $width in $sizes {
86
+ [size="#{$size}"] & {
87
+ max-width: $width;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ textarea {
94
+ .qc-textfield &,
95
+ qc-textfield & {
96
+ min-height: token-value(size textarea min-height);
97
+ resize: vertical;
98
+ }
99
+ }
100
+
101
+ .qc-textfield-charcount {
102
+ @include content-font(sm);
103
+ text-align: right;
104
+ margin-top: rem(4);
105
+ color: token-value(color blue dark);
106
+ &.qc-max-reached {
107
+ color: token-value(color, red, regular);
108
+ font-weight: token-value(font weight content bold);
109
+ }
110
+ }
@@ -0,0 +1,19 @@
1
+ import {Utils} from "../utils";
2
+
3
+ export function onMountInput(input, setTextFieldRow, setValue, setInvalid) {
4
+ if (!input) return;
5
+ if (!input.autocomplete) {
6
+ input.autocomplete = "off"
7
+ }
8
+ if (!input.id) {
9
+ input.id = Utils.generateId(input.type);
10
+ }
11
+ setValue(input.value)
12
+ input.addEventListener(
13
+ 'input',
14
+ () => {
15
+ setValue(input.value);
16
+ setInvalid(false);
17
+ })
18
+ setTextFieldRow(input.closest('.qc-formfield-row'))
19
+ }
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { Utils } from "../utils";
3
- import Icon from "../Icon/Icon.svelte";
3
+ import Icon from "../../bases/Icon/Icon.svelte";
4
4
  import {setContext} from "svelte";
5
5
 
6
6
  const lang = Utils.getPageLanguage();
@@ -15,8 +15,6 @@
15
15
  let minimumScrollHeight = 0;
16
16
  let toTopElement;
17
17
 
18
- const src = `${Utils.imagesRelativePath}arrow-up-white.svg`;
19
-
20
18
  function handleScrollUpButton() {
21
19
  if (Utils.isTruthy(demo)) {
22
20
  return;
@@ -75,6 +73,6 @@
75
73
  tabindex={visible ? 0 : -1}
76
74
  {demo}
77
75
  >
78
- <Icon type="arrow-up-white" color="background"/>
76
+ <Icon type="arrow-up" color="background"/>
79
77
  <span>{text}</span>
80
78
  </a>
@@ -0,0 +1,45 @@
1
+ <h2 id="toTop">Haut de page</h2>
2
+ <p>
3
+ Le composant <i>haut de page</i> est la flèche qui permet à l’utilisateur de revenir en haut de la
4
+ page. Il s'affiche quand l’utilisateur commence à défiler vers le haut.
5
+ Il disparaît quand l’utilisateur commence à défiler vers le bas.
6
+ </p>
7
+ <h4>Exemple</h4>
8
+ <qc-doc-exemple caption="Présentation du composant retour en haut de page"
9
+ code-target-id="to-top-exemple"
10
+ >
11
+ <qc-to-top demo="true"/>
12
+ </qc-doc-exemple>
13
+ <div id="to-top-exemple">
14
+ <qc-to-top></qc-to-top>
15
+ </div>
16
+
17
+ <h3>Documentation technique</h3>
18
+
19
+ <h4>Attributs</h4>
20
+ <div class="table-overflow">
21
+ <table class="qc-table qc-striped">
22
+ <thead>
23
+ <tr>
24
+ <th>Nom</th>
25
+ <th>Valeur attendue</th>
26
+ <th>Valeur par défaut</th>
27
+ <th>Description</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td>text</td>
33
+ <td>Texte</td>
34
+ <td>Retour en haut / Back to top</td>
35
+ <td>la valeur de l’attribut "text" de l’élément.</td>
36
+ </tr>
37
+ <tr>
38
+ <td>demo</td>
39
+ <td>"true" ou "false"</td>
40
+ <td>false</td>
41
+ <td>Pour utiliser le composant en démonstration uniquement.</td>
42
+ </tr>
43
+ </tbody>
44
+ </table>
45
+ </div>
@@ -1,5 +1,5 @@
1
- @use "qc-sdg-lib" as *;
2
- @use "base/shadings" as *;
1
+ @use "../../scss/qc-sdg-lib" as *;
2
+ @use "../../bases/shadings/shadings" as *;
3
3
 
4
4
  .qc-to-top {
5
5
  &[demo="false"] {