qc-trousse-sdg 1.2.5-dev → 1.3.0-develop.0
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/README.md +18 -3
- package/dist/css/qc-sdg-design-tokens.min.css +1 -1
- package/dist/css/qc-sdg-no-grid.min.css +1 -1
- package/dist/css/qc-sdg.min.css +1 -1
- package/dist/img/QUEBEC_blanc.svg +1 -1
- package/dist/img/QUEBEC_couleur.svg +24 -0
- package/dist/js/qc-sdg.min.js +1 -1
- package/package.json +23 -18
- package/public/css/qc-doc-sdg.css +247 -335
- package/public/css/qc-sdg-design-tokens.css +111 -64
- package/public/css/qc-sdg-no-grid.css +932 -428
- package/public/css/qc-sdg.css +941 -609
- package/public/img/QUEBEC_blanc.svg +1 -1
- package/public/img/QUEBEC_couleur.svg +24 -0
- package/public/img/ampoule.svg +1 -0
- package/public/img/note.svg +1 -0
- package/public/img/piv-MCE-theme-clair.svg +79 -0
- package/public/img/piv-MCE-theme-sombre.svg +62 -0
- package/public/img/piv-bas-MCE-theme-clair.png +0 -0
- package/public/img/piv-bas-MCE-theme-sombre.png +0 -0
- package/public/img/piv-logo-pied-de-page.svg +37 -0
- package/public/index.html +871 -715
- package/public/js/qc-doc-exemple.js +9 -0
- package/public/js/qc-doc-sdg.js +6893 -3724
- package/public/js/qc-sdg.js +2103 -962
- package/rollup.config.js +58 -23
- package/src/doc/components/Code.svelte +69 -0
- package/src/doc/components/Exemple.svelte +71 -0
- package/src/doc/components/Switch.svelte +108 -0
- package/src/doc/components/TopNav.svelte +53 -0
- package/src/doc/components/color-doc.svelte +44 -0
- package/src/doc/qc-doc-sdg.js +25 -14
- package/src/doc/scss/_tables.scss +1 -2
- package/src/doc/scss/components/_button.scss +14 -14
- package/src/doc/scss/components/_code.scss +106 -4
- package/src/doc/scss/jQueryUI/_jquery-ui.autocomplete.scss +48 -0
- package/src/doc/scss/qc-doc-sdg.scss +76 -75
- package/src/sdg/components/Button/IconButton.svelte +29 -0
- package/src/sdg/components/Icon.svelte +39 -0
- package/src/sdg/components/{pivHeader.svelte → PivHeader/pivHeader.svelte} +49 -69
- package/src/sdg/components/SearchBar/searchBar.svelte +87 -0
- package/src/sdg/components/SearchInput/SearchInput.svelte +48 -0
- package/src/sdg/components/alert.svelte +40 -23
- package/src/sdg/components/componentWrapper.js +0 -3
- package/src/sdg/components/externalLink.svelte +92 -0
- package/src/sdg/components/notice.svelte +61 -34
- package/src/sdg/components/pivFooter.svelte +37 -36
- package/src/sdg/components/toTop.svelte +16 -10
- package/src/sdg/components/utils.js +28 -4
- package/src/sdg/qc-sdg.js +11 -3
- package/src/sdg/scss/_qc-sdg-lib.scss +3 -0
- package/src/sdg/scss/base/_accessibility.scss +4 -0
- package/src/sdg/scss/base/_colors.scss +10 -10
- package/src/sdg/scss/base/_figure.scss +14 -9
- package/src/sdg/scss/base/_fonts.scss +4 -4
- package/src/sdg/scss/base/_form.scss +7 -0
- package/src/sdg/scss/base/_layout.scss +45 -0
- package/src/sdg/scss/base/_lists.scss +5 -5
- package/src/sdg/scss/base/_shadings.scss +3 -11
- package/src/sdg/scss/base/_typography.scss +42 -25
- package/src/sdg/scss/components/_alert.scss +11 -34
- package/src/sdg/scss/components/_icons.scss +67 -38
- package/src/sdg/scss/components/_notice.scss +51 -44
- package/src/sdg/scss/components/_pivFooter.scss +35 -23
- package/src/sdg/scss/components/_pivHeader.scss +131 -154
- package/src/sdg/scss/components/_searchBar.scss +75 -0
- package/src/sdg/scss/components/_searchInput.scss +64 -0
- package/src/sdg/scss/components/_separator.scss +2 -5
- package/src/sdg/scss/components/_toTop.scss +4 -6
- package/src/sdg/scss/grid/_grid-lib.scss +516 -0
- package/src/sdg/scss/grid/_grid.scss +78 -0
- package/src/sdg/scss/lib/_functions.scss +78 -0
- package/src/sdg/scss/lib/_gridless-lib.scss +4 -0
- package/src/sdg/scss/lib/_mixins.scss +221 -0
- package/src/sdg/scss/qc-design-tokens.scss +31 -8
- package/src/sdg/scss/qc-sdg-utilities.scss +1 -0
- package/src/sdg/scss/qc-sdg.scss +1 -1
- package/src/sdg/scss/qc-sgd-no-grid.scss +20 -15
- package/src/sdg/scss/settings/_base.scss +58 -0
- package/src/sdg/scss/settings/_tokens.scss +145 -77
- package/src/sdg/scss/utilities/_display.scss +43 -3
- package/src/sdg/scss/utilities/_themes.scss +17 -0
- package/src/sdg/scss/vendor/modern-css-reset/src/reset.css +9 -8
- package/dist/img/logo-quebec-piv-footer.svg +0 -1
- package/dist/img/quebec-logo.svg +0 -13
- package/public/img/logo-quebec-piv-footer.svg +0 -1
- package/src/doc/components/code.svelte +0 -54
- package/src/sdg/scss/base/_grid.scss +0 -9
- package/src/sdg/scss/functions/_tokens.scss +0 -12
- package/src/sdg/scss/functions/_utils.scss +0 -44
- package/src/sdg/scss/modules/_grid.scss +0 -19
- package/src/sdg/scss/modules/_helpers.scss +0 -32
- package/src/sdg/scss/modules/_map.scss +0 -14
- package/src/sdg/scss/modules/_tokens.scss +0 -3
- package/src/sdg/scss/modules/_utils.scss +0 -55
- package/src/sdg/scss/settings/_grid.scss +0 -24
- package/src/sdg/scss/settings/_settings.scss +0 -12
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<svelte:options customElement="{{
|
|
2
|
+
tag: 'qc-search-bar',
|
|
3
|
+
shadow: 'none',
|
|
4
|
+
props: {
|
|
5
|
+
value: {attribute: 'input-value', type:'String'},
|
|
6
|
+
name: {attribute: 'input-name', type:'String'},
|
|
7
|
+
pivBackground: {attribute: 'piv-background', type:'Boolean'},
|
|
8
|
+
}
|
|
9
|
+
}}" />
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
import {Utils} from "../utils";
|
|
13
|
+
import SearchInput from "../SearchInput/SearchInput.svelte";
|
|
14
|
+
import IconButton from "../Button/IconButton.svelte";
|
|
15
|
+
|
|
16
|
+
const
|
|
17
|
+
lang = Utils.getPageLanguage(),
|
|
18
|
+
inputDefaultPlaceholder = lang === "fr"
|
|
19
|
+
? "Rechercher…"
|
|
20
|
+
: "Search",
|
|
21
|
+
submitDefaultAriaLabel = lang === "fr"
|
|
22
|
+
? "Lancer la recherche"
|
|
23
|
+
: "Submit search"
|
|
24
|
+
;
|
|
25
|
+
export let
|
|
26
|
+
value = '',
|
|
27
|
+
name = 'q',
|
|
28
|
+
pivBackground = false
|
|
29
|
+
;
|
|
30
|
+
|
|
31
|
+
let defaultsAttributes = {
|
|
32
|
+
input: {
|
|
33
|
+
"placeholder": inputDefaultPlaceholder,
|
|
34
|
+
"aria-label": inputDefaultPlaceholder
|
|
35
|
+
},
|
|
36
|
+
submit: {
|
|
37
|
+
"aria-label": submitDefaultAriaLabel
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
inputProps = {},
|
|
41
|
+
submitProps = {}
|
|
42
|
+
|
|
43
|
+
$: [inputProps, submitProps] = computeFieldsAttributes($$restProps)
|
|
44
|
+
$: inputProps = {
|
|
45
|
+
"value": value,
|
|
46
|
+
"name": name,
|
|
47
|
+
...inputProps
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {{[p: string]: T}} restProps
|
|
52
|
+
*/
|
|
53
|
+
function computeFieldsAttributes(restProps) {
|
|
54
|
+
return ["input","submit"]
|
|
55
|
+
.map(control => {
|
|
56
|
+
const prefix = `${control}-`;
|
|
57
|
+
return {
|
|
58
|
+
...defaultsAttributes[control],
|
|
59
|
+
...Object.fromEntries(Object
|
|
60
|
+
.entries(restProps)
|
|
61
|
+
.map(([k,v]) => k.startsWith(prefix)
|
|
62
|
+
? [k.replace(prefix, ''),v]
|
|
63
|
+
: null
|
|
64
|
+
)
|
|
65
|
+
.filter(x => x) // élimine les éléments null
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
</script>
|
|
74
|
+
<div class="qc-search-bar"
|
|
75
|
+
class:piv-background={pivBackground}
|
|
76
|
+
>
|
|
77
|
+
<SearchInput {...inputProps}/>
|
|
78
|
+
{#if true}
|
|
79
|
+
<IconButton
|
|
80
|
+
type="submit"
|
|
81
|
+
iconColor={pivBackground ? 'blue-piv' : 'background'}
|
|
82
|
+
icon="loupe-piv-fine"
|
|
83
|
+
iconSize="md"
|
|
84
|
+
{...submitProps}
|
|
85
|
+
/>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<svelte:options customElement="{{
|
|
2
|
+
tag: 'qc-search-input',
|
|
3
|
+
shadow: 'none',
|
|
4
|
+
props: {
|
|
5
|
+
ariaLabel: {attribute:'aria-label'},
|
|
6
|
+
clearAriaLabel: {attribute: 'clear-aria-label'}
|
|
7
|
+
}
|
|
8
|
+
}}" />
|
|
9
|
+
<script>
|
|
10
|
+
import IconButton from "../Button/IconButton.svelte";
|
|
11
|
+
import {Utils} from "../utils";
|
|
12
|
+
const
|
|
13
|
+
lang = Utils.getPageLanguage();
|
|
14
|
+
|
|
15
|
+
export let
|
|
16
|
+
value,
|
|
17
|
+
ariaLabel = lang === "fr"
|
|
18
|
+
? "Rechercher…"
|
|
19
|
+
: "Search_",
|
|
20
|
+
clearAriaLabel = lang === "fr"
|
|
21
|
+
? "Effacer le texte"
|
|
22
|
+
: "Clear text"
|
|
23
|
+
;
|
|
24
|
+
let searchInput;
|
|
25
|
+
|
|
26
|
+
</script>
|
|
27
|
+
<div class="qc-search-input">
|
|
28
|
+
<input bind:this={searchInput}
|
|
29
|
+
bind:value
|
|
30
|
+
type="search"
|
|
31
|
+
autocomplete="off"
|
|
32
|
+
{...(ariaLabel ? {"aria-label": ariaLabel} : {})}
|
|
33
|
+
{...$$restProps}
|
|
34
|
+
/>
|
|
35
|
+
{#if value}
|
|
36
|
+
<IconButton type="button"
|
|
37
|
+
icon="clear-input"
|
|
38
|
+
iconColor="blue-piv"
|
|
39
|
+
iconSize="sm"
|
|
40
|
+
aria-label={clearAriaLabel}
|
|
41
|
+
on:click={e => {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
value = "";
|
|
44
|
+
searchInput.focus();
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
{/if}
|
|
48
|
+
</div>
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
<svelte:options customElement="
|
|
1
|
+
<svelte:options customElement="{{
|
|
2
|
+
tag:'qc-alert',
|
|
3
|
+
props: {
|
|
4
|
+
type : {attribute: 'type'},
|
|
5
|
+
maskable : {attribute: 'maskable'},
|
|
6
|
+
fullWidth : {attribute: 'full-width'},
|
|
7
|
+
content: {attribute: 'content'},
|
|
8
|
+
hide: {attribute: 'hide'},
|
|
9
|
+
}
|
|
10
|
+
}}"/>
|
|
2
11
|
|
|
3
12
|
<script>
|
|
4
13
|
import {Utils} from "./utils";
|
|
14
|
+
import Icon from "./Icon.svelte";
|
|
15
|
+
import IconButton from "./Button/IconButton.svelte";
|
|
5
16
|
|
|
6
17
|
export let
|
|
7
18
|
type = "general"
|
|
8
19
|
, maskable = ""
|
|
9
20
|
, content = ""
|
|
10
21
|
, hide = "false"
|
|
22
|
+
, fullWidth = 'false'
|
|
11
23
|
;
|
|
12
24
|
|
|
13
25
|
let
|
|
@@ -17,8 +29,8 @@
|
|
|
17
29
|
? type
|
|
18
30
|
: 'general'
|
|
19
31
|
, closeLabel = Utils.getPageLanguage() === 'fr'
|
|
20
|
-
? "Fermer"
|
|
21
|
-
: "Close"
|
|
32
|
+
? "Fermer l’alerte"
|
|
33
|
+
: "Close l’alerte"
|
|
22
34
|
, warningLabel = Utils.getPageLanguage() === 'fr'
|
|
23
35
|
? "Information d'importance élevée"
|
|
24
36
|
: "Information of high importance"
|
|
@@ -28,9 +40,12 @@
|
|
|
28
40
|
, label = type === 'general'
|
|
29
41
|
? generalLabel
|
|
30
42
|
: warningLabel
|
|
43
|
+
, containerClass
|
|
31
44
|
;
|
|
32
45
|
|
|
33
46
|
$: hiddenFlag = hide === 'true'
|
|
47
|
+
$: containerClass = "qc-container" + (fullWidth === 'true' ? '-fluid' : '');
|
|
48
|
+
|
|
34
49
|
function hideAlert() {
|
|
35
50
|
hide='true'
|
|
36
51
|
rootElement.dispatchEvent(
|
|
@@ -44,28 +59,30 @@
|
|
|
44
59
|
{#if !hiddenFlag}
|
|
45
60
|
<div bind:this={rootElement}
|
|
46
61
|
class="qc-general-alert {typeClass}"
|
|
47
|
-
role="alert"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<div class="qc-alert-close">
|
|
59
|
-
<button type="button" class="qc-close" aria-label={closeLabel}
|
|
60
|
-
on:click={hideAlert}>
|
|
61
|
-
<span aria-hidden="true"
|
|
62
|
-
class="qc-icon qc-xclose-blue qc-close-alert-icon"
|
|
63
|
-
></span>
|
|
64
|
-
</button>
|
|
62
|
+
role="alert">
|
|
63
|
+
<div class={containerClass}>
|
|
64
|
+
<div class="qc-general-alert-elements">
|
|
65
|
+
<Icon type={type == 'warning' ? 'warning' : 'information'}
|
|
66
|
+
color="{type == 'general' ? 'blue-piv' : 'yellow-dark'}"
|
|
67
|
+
size="nm"
|
|
68
|
+
label={label}
|
|
69
|
+
/>
|
|
70
|
+
<div class="qc-alert-content">
|
|
71
|
+
{@html content}
|
|
72
|
+
<slot />
|
|
65
73
|
</div>
|
|
66
|
-
|
|
74
|
+
{#if maskable === "true"}
|
|
75
|
+
<IconButton aria-label={closeLabel}
|
|
76
|
+
on:click={hideAlert}
|
|
77
|
+
size="nm"
|
|
78
|
+
icon="clear-input"
|
|
79
|
+
iconSize="sm"
|
|
80
|
+
iconColor="text-primary"
|
|
81
|
+
/>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
67
84
|
</div>
|
|
68
85
|
</div>
|
|
69
86
|
{/if}
|
|
70
87
|
<link rel='stylesheet'
|
|
71
|
-
href='{Utils.
|
|
88
|
+
href='{Utils.cssPath}'>
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
Référence : https://github.com/sveltejs/svelte/issues/3852
|
|
3
3
|
*/
|
|
4
4
|
export const customElements = {
|
|
5
|
-
customFoo: function () {
|
|
6
|
-
return "bar";
|
|
7
|
-
},
|
|
8
5
|
define: (tagName, CustomElement) => {
|
|
9
6
|
class CustomElementWrapper extends CustomElement {
|
|
10
7
|
static get observedAttributes() {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<svelte:options customElement="{{
|
|
2
|
+
tag:'qc-external-link',
|
|
3
|
+
shadow:'none',
|
|
4
|
+
props: {
|
|
5
|
+
externalIconAlt : {attribute: 'img-alt'}
|
|
6
|
+
}
|
|
7
|
+
}}"/>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import {Utils} from "./utils";
|
|
11
|
+
import {onMount} from "svelte";
|
|
12
|
+
|
|
13
|
+
export
|
|
14
|
+
let externalIconAlt = Utils.getPageLanguage() == "fr"
|
|
15
|
+
? "Ce lien dirige vers un autre site."
|
|
16
|
+
: "This link directs to another site."
|
|
17
|
+
;
|
|
18
|
+
let imgElement;
|
|
19
|
+
|
|
20
|
+
onMount(() => {
|
|
21
|
+
imgElement.parentElement.querySelectorAll('a').forEach(link => {
|
|
22
|
+
|
|
23
|
+
// Crée un TreeWalker pour parcourir uniquement les nœuds texte visibles
|
|
24
|
+
const walker = document.createTreeWalker(
|
|
25
|
+
link,
|
|
26
|
+
NodeFilter.SHOW_ALL,
|
|
27
|
+
{
|
|
28
|
+
acceptNode: node => {
|
|
29
|
+
if (node instanceof Element) {
|
|
30
|
+
if (node.hasAttribute('hidden')) {
|
|
31
|
+
return NodeFilter.FILTER_REJECT;
|
|
32
|
+
}
|
|
33
|
+
const style = window.getComputedStyle(node);
|
|
34
|
+
// Si l'élément est masqué par CSS (display ou visibility), on l'ignore
|
|
35
|
+
if (style.display === 'none'
|
|
36
|
+
|| style.visibility === 'hidden'
|
|
37
|
+
|| style.position === 'absolute') {
|
|
38
|
+
return NodeFilter.FILTER_REJECT;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!node instanceof Text) {
|
|
42
|
+
return NodeFilter.FILTER_SKIP
|
|
43
|
+
}
|
|
44
|
+
// Ignore les nœuds vides
|
|
45
|
+
if (!/\S/.test(node.textContent)) {
|
|
46
|
+
return NodeFilter.FILTER_SKIP;
|
|
47
|
+
}
|
|
48
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
let lastTextNode = null;
|
|
54
|
+
while (walker.nextNode()) {
|
|
55
|
+
lastTextNode = walker.currentNode;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// S'il n'y a pas de nœud texte visible, on ne fait rien
|
|
59
|
+
if (!lastTextNode) return;
|
|
60
|
+
|
|
61
|
+
// Séparer le contenu du dernier nœud texte en deux parties :
|
|
62
|
+
// le préfixe (éventuel) et le dernier mot
|
|
63
|
+
const text = lastTextNode.textContent;
|
|
64
|
+
const regex = /^(.*\s)?(\S+)\s*$/m;
|
|
65
|
+
const match = text.match(regex);
|
|
66
|
+
if (!match) return;
|
|
67
|
+
const prefix = match[1] || "";
|
|
68
|
+
const lastWord = match[2];
|
|
69
|
+
|
|
70
|
+
// Crée un span avec white-space: nowrap pour empêcher le saut de ligne de l'image de lien externe
|
|
71
|
+
const span = document.createElement('span');
|
|
72
|
+
span.classList.add('img-wrap')
|
|
73
|
+
span.innerHTML = `${lastWord}`;
|
|
74
|
+
span.appendChild(imgElement)
|
|
75
|
+
|
|
76
|
+
// Met à jour le nœud texte : on garde le préfixe et on insère le span après
|
|
77
|
+
if (prefix) {
|
|
78
|
+
lastTextNode.textContent = prefix;
|
|
79
|
+
lastTextNode.parentNode.insertBefore(span, lastTextNode.nextSibling);
|
|
80
|
+
} else {
|
|
81
|
+
lastTextNode.parentNode.replaceChild(span, lastTextNode);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
<span bind:this={imgElement}
|
|
87
|
+
role="img"
|
|
88
|
+
class="qc-ext-link-img"
|
|
89
|
+
aria-label={externalIconAlt}></span>
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
@@ -2,55 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
<script>
|
|
4
4
|
import { Utils } from "./utils"
|
|
5
|
-
import
|
|
5
|
+
import Icon from "./Icon.svelte";
|
|
6
6
|
|
|
7
7
|
const
|
|
8
|
-
|
|
8
|
+
isFr = Utils.getPageLanguage() == 'fr'
|
|
9
|
+
, defaultHeader = 'h2'
|
|
9
10
|
, defaultType = 'information'
|
|
10
|
-
,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
, '
|
|
14
|
-
, '
|
|
15
|
-
|
|
11
|
+
, typesDescriptions = {
|
|
12
|
+
'advice': isFr ? "Avis conseil" : "Advisory notice",
|
|
13
|
+
'note': isFr ? "Avis explicatif" : "Explanatory notice"
|
|
14
|
+
, 'information': isFr ? "Avis général" : "General notice"
|
|
15
|
+
, 'warning': isFr ? "Avis d’avertissement" : "Warning notice"
|
|
16
|
+
, 'success': isFr ? "Avis de réussite" : "Success notice"
|
|
17
|
+
, 'error': isFr ? "Avis d’erreur" : "Error notice"
|
|
18
|
+
}
|
|
19
|
+
, types = Object.keys(typesDescriptions);
|
|
20
|
+
|
|
21
|
+
let noticeElement;
|
|
16
22
|
export let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
header = header.match(/h[1-6]/)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type = types.includes(type)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
title = ""
|
|
24
|
+
, type = defaultType
|
|
25
|
+
, content = ""
|
|
26
|
+
, header = defaultHeader
|
|
27
|
+
, icon;
|
|
28
|
+
|
|
29
|
+
$: header = header.match(/h[1-6]/)
|
|
30
|
+
? header
|
|
31
|
+
: defaultHeader;
|
|
32
|
+
|
|
33
|
+
$: type = types.includes(type)
|
|
34
|
+
? type
|
|
35
|
+
: defaultType;
|
|
36
|
+
|
|
37
|
+
$: role = type === "success"
|
|
38
|
+
? "status"
|
|
39
|
+
: (type === "error" ? "alert" : null);
|
|
40
|
+
|
|
41
|
+
$: if (role) {
|
|
42
|
+
if (noticeElement) {
|
|
43
|
+
const tempNodes = Array.from(noticeElement.childNodes);
|
|
44
|
+
// console.log("temp: ",tempNodes);
|
|
45
|
+
noticeElement.innerHTML = "";
|
|
46
|
+
// Réinsère le contenu pour qu'il soit détecté par le lecteur d'écran.
|
|
47
|
+
tempNodes.forEach(node => noticeElement.appendChild(node)); }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$: shouldUseIcon = type === "advice" || type === "note";
|
|
51
|
+
// Si le type est "advice" ou "note", on force "neutral" (le gris), sinon on garde le type normal
|
|
52
|
+
$: computedType = shouldUseIcon ? "neutral" : type;
|
|
53
|
+
$: iconType = shouldUseIcon ? (icon ?? "note") : type;
|
|
54
|
+
$: iconLabel = typesDescriptions[type] ?? typesDescriptions['information'];
|
|
55
|
+
|
|
56
|
+
|
|
32
57
|
</script>
|
|
33
58
|
|
|
34
59
|
<!-- TODO Confirmer tabindex. On pense que c'est important de recevoir le focus (notamment dans les formulaires) en fait pour nous c'est très important, sinon en mode formulaire au lecteur écran (nav avec TAB, ce n'est jamais lu). -->
|
|
35
60
|
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
36
|
-
<div class="qc-component qc-notice qc-{
|
|
61
|
+
<div class="qc-component qc-notice qc-{computedType}"
|
|
37
62
|
tabindex="0">
|
|
38
63
|
<div class="icon-container">
|
|
39
|
-
<div
|
|
40
|
-
|
|
64
|
+
<div class="qc-icon">
|
|
65
|
+
<Icon type="{iconType}"
|
|
66
|
+
label={iconLabel}
|
|
67
|
+
size="nm"
|
|
68
|
+
/>
|
|
41
69
|
</div>
|
|
42
70
|
</div>
|
|
43
71
|
<div class="content-container">
|
|
44
|
-
<div class="content">
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
<div class="content" {role} bind:this={noticeElement}>
|
|
73
|
+
{#if title}
|
|
74
|
+
<svelte:element this={header}>
|
|
75
|
+
{@html title}
|
|
76
|
+
</svelte:element>
|
|
77
|
+
{/if}
|
|
50
78
|
{@html content}
|
|
51
79
|
<slot />
|
|
52
|
-
</div>
|
|
53
80
|
</div>
|
|
54
81
|
</div>
|
|
55
82
|
</div>
|
|
56
|
-
<link rel='stylesheet' href='{Utils.
|
|
83
|
+
<link rel='stylesheet' href='{Utils.cssPath}'>
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
tag: 'qc-piv-footer'
|
|
3
3
|
, props: {
|
|
4
4
|
logoUrl : {attribute: 'logo-url'}
|
|
5
|
+
, logoSrc : {attribute: 'logo-src'}
|
|
6
|
+
, logoSrcDarkTheme: {attribute: 'logo-src-dark-theme'}
|
|
5
7
|
, logoAlt : {attribute: 'logo-alt'}
|
|
6
|
-
, logoWidth
|
|
7
|
-
, logoHeight
|
|
8
|
-
, copyrightText : {attribute: '
|
|
8
|
+
, logoWidth: {attribute: 'logo-width'}
|
|
9
|
+
, logoHeight: {attribute: 'logo-height'}
|
|
10
|
+
, copyrightText : {attribute: 'copyright-text'}
|
|
9
11
|
, copyrightUrl : {attribute: 'copyright-url'}
|
|
12
|
+
|
|
10
13
|
}}
|
|
11
14
|
}}" />
|
|
12
15
|
|
|
@@ -21,44 +24,42 @@ const
|
|
|
21
24
|
|
|
22
25
|
export let
|
|
23
26
|
logoUrl = '/'
|
|
24
|
-
, logoSrc =
|
|
25
|
-
,
|
|
26
|
-
,
|
|
27
|
-
|
|
27
|
+
, logoSrc = Utils.imagesRelativePath + '/QUEBEC_couleur.svg'
|
|
28
|
+
, logoSrcDarkTheme = Utils.imagesRelativePath + '/QUEBEC_blanc.svg'
|
|
29
|
+
, logoAlt = lang === 'fr'
|
|
30
|
+
? 'Logo du gouvernement du Québec'
|
|
31
|
+
: 'Logo of the Quebec government'
|
|
28
32
|
, copyrightText = '© Gouvernement du Québec, ' + (new Date()).getFullYear()
|
|
33
|
+
, logoWidth = 139
|
|
34
|
+
, logoHeight = 50
|
|
29
35
|
, copyrightUrl = lang === 'fr'
|
|
30
36
|
? 'https://www.quebec.ca/droit-auteur'
|
|
31
37
|
: 'https://www.quebec.ca/en/copyright'
|
|
32
38
|
;
|
|
33
|
-
|
|
34
39
|
</script>
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
</span>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
40
|
+
<div class="qc-piv-footer qc-container-fluid">
|
|
41
|
+
<slot/>
|
|
42
|
+
<a href="{logoUrl}"
|
|
43
|
+
class="logo"
|
|
44
|
+
style:--logo-width={logoWidth}
|
|
45
|
+
style:--logo-height={logoHeight}
|
|
46
|
+
>
|
|
47
|
+
{#each [
|
|
48
|
+
['light', logoSrc],
|
|
49
|
+
['dark', logoSrcDarkTheme]]
|
|
50
|
+
as [theme, src]}
|
|
51
|
+
<img {src}
|
|
52
|
+
alt="{logoAlt}"
|
|
53
|
+
class="qc-{theme}-theme-show"/>
|
|
54
|
+
{/each}
|
|
55
|
+
</a>
|
|
56
|
+
<span class="copyright">
|
|
57
|
+
<slot name="copyright">
|
|
58
|
+
<a href="{copyrightUrl}">
|
|
59
|
+
{copyrightText}
|
|
60
|
+
</a>
|
|
61
|
+
</slot>
|
|
62
|
+
</span>
|
|
61
63
|
</div>
|
|
64
|
+
<link rel='stylesheet' href='{Utils.cssPath}'>
|
|
62
65
|
|
|
63
|
-
<link rel='stylesheet'
|
|
64
|
-
href='{Utils.cssRelativePath}{Utils.cssFileName}'>
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
<svelte:options customElement="
|
|
1
|
+
<svelte:options customElement="{{
|
|
2
|
+
tag: 'qc-to-top',
|
|
3
|
+
shadow: 'none',
|
|
4
|
+
props: {
|
|
5
|
+
text: {attribute: 'text', type:'String'},
|
|
6
|
+
}
|
|
7
|
+
}}" />
|
|
8
|
+
|
|
2
9
|
|
|
3
10
|
<script>
|
|
4
11
|
import { Utils } from "./utils";
|
|
12
|
+
import Icon from "./Icon.svelte";
|
|
5
13
|
|
|
6
14
|
const
|
|
7
15
|
lang = Utils.getPageLanguage();
|
|
8
16
|
export let
|
|
9
|
-
|
|
17
|
+
text = lang === 'fr'
|
|
10
18
|
? "Retour en haut"
|
|
11
19
|
: "Back to top"
|
|
12
20
|
, demo = 'false'
|
|
@@ -65,17 +73,15 @@
|
|
|
65
73
|
|
|
66
74
|
<svelte:window on:scroll = {handleScrollUpButton} />
|
|
67
75
|
|
|
68
|
-
<a href="
|
|
76
|
+
<a href="javascript:;"
|
|
69
77
|
bind:this={toTopElement}
|
|
70
|
-
class="qc-to-top
|
|
71
|
-
tabindex="0"
|
|
78
|
+
class="qc-to-top"
|
|
72
79
|
class:visible
|
|
73
80
|
on:click|preventDefault={scrollToTop}
|
|
74
81
|
on:keydown={handleEnterAndSpace}
|
|
82
|
+
tabindex={visible ? 0 : -1}
|
|
75
83
|
{demo}
|
|
76
84
|
>
|
|
77
|
-
<
|
|
78
|
-
</
|
|
79
|
-
|
|
80
|
-
<link rel='stylesheet'
|
|
81
|
-
href='{Utils.cssRelativePath}{Utils.cssFileName}'>
|
|
85
|
+
<Icon type="arrow-up-white" color="background"/>
|
|
86
|
+
<span>{text}</span>
|
|
87
|
+
</a>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export class Utils {
|
|
2
2
|
|
|
3
3
|
static assetsBasePath =
|
|
4
|
-
|
|
5
|
-
.
|
|
6
|
-
.
|
|
7
|
-
|
|
4
|
+
document
|
|
5
|
+
.currentScript
|
|
6
|
+
.getAttribute('sdg-assets-base-path')
|
|
7
|
+
|| new URL(document.currentScript.src).pathname
|
|
8
|
+
.split('/')
|
|
9
|
+
.slice(0, -2)
|
|
10
|
+
.join('/')
|
|
8
11
|
|| '.'
|
|
9
12
|
static cssRelativePath =
|
|
10
13
|
`${this.assetsBasePath}/css/`
|
|
@@ -17,6 +20,11 @@ export class Utils {
|
|
|
17
20
|
.currentScript
|
|
18
21
|
.getAttribute('sdg-css-filename')
|
|
19
22
|
|| 'qc-sdg.min.css'
|
|
23
|
+
static cssPath =
|
|
24
|
+
document
|
|
25
|
+
.currentScript
|
|
26
|
+
.getAttribute('sdg-css-path')
|
|
27
|
+
|| this.cssRelativePath + this.cssFileName
|
|
20
28
|
static sharedTexts =
|
|
21
29
|
{ openInNewTab :
|
|
22
30
|
{ fr: 'Ce lien s’ouvrira dans un nouvel onglet.'
|
|
@@ -31,4 +39,20 @@ export class Utils {
|
|
|
31
39
|
static getPageLanguage() {
|
|
32
40
|
return document.getElementsByTagName("html")[0].getAttribute("lang") || "fr";
|
|
33
41
|
}
|
|
42
|
+
|
|
43
|
+
static isTruthy(value) {
|
|
44
|
+
if (typeof value === 'boolean') {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
if (typeof value === 'string') {
|
|
48
|
+
return value.toLowerCase() === 'true' || !!parseInt(value); // Vérifie si la chaîne est "true" (insensible à la casse)
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === 'number') {
|
|
51
|
+
return !!value; // Vérifie si le nombre est égal à 1
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
34
58
|
}
|
package/src/sdg/qc-sdg.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
export * from './components/notice.svelte'
|
|
2
|
-
export * from './components/pivHeader.svelte'
|
|
2
|
+
export * from './components/PivHeader/pivHeader.svelte'
|
|
3
3
|
export * from './components/pivFooter.svelte'
|
|
4
4
|
export * from './components/alert.svelte'
|
|
5
5
|
export * from './components/toTop.svelte'
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export * from './components/externalLink.svelte'
|
|
7
|
+
export * from './components/SearchBar/searchBar.svelte'
|
|
8
|
+
export * from './components/SearchInput/SearchInput.svelte'
|
|
9
|
+
export * from './components/Icon.svelte'
|
|
10
|
+
import './scss/qc-sdg.scss' ;
|
|
11
|
+
|
|
12
|
+
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
13
|
+
if (isDarkMode) {
|
|
14
|
+
document.documentElement.classList.add('qc-dark-theme')
|
|
15
|
+
}
|