access-settings 0.0.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.
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/index.js +373 -0
- package/dist/index.min.js +196 -0
- package/example/index.html +161 -0
- package/example/styles.css +61 -0
- package/package.json +29 -0
- package/src/createState.js +34 -0
- package/src/globalStyles.js +24 -0
- package/src/index.js +104 -0
- package/src/languages.json +18 -0
- package/src/preferences.js +66 -0
- package/src/style.js +107 -0
- package/src/template.js +52 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
(()=>{var h=document.createElement("style");h.innerHTML=`
|
|
2
|
+
@font-face {
|
|
3
|
+
font-family: open-dyslexic;
|
|
4
|
+
src: url(https://fonts.cdnfonts.com/s/29616/open-dyslexic.woff);
|
|
5
|
+
}
|
|
6
|
+
:root.dyslexic {
|
|
7
|
+
font-family:open-dyslexic, sans-serif;
|
|
8
|
+
}
|
|
9
|
+
:root.invertedColors {
|
|
10
|
+
filter:invert(1);
|
|
11
|
+
}
|
|
12
|
+
@media (prefers-color-scheme: dark) {
|
|
13
|
+
:root:has(access-settings[invert-colors], access-settings[all]) {
|
|
14
|
+
filter:invert(1);
|
|
15
|
+
&.invertedColors {
|
|
16
|
+
filter:invert(0);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`;document.head.append(h);function u(o){let e=[];function i(n){return new Proxy(n,{set(t,s,f){return t[s]=f,e.forEach(z=>z(String(s),f)),!0},get(t,s){return s==="_isProxy"?!0:t[s]?._isProxy?t[s]:t[s]&&typeof t[s]=="object"?i(t[s]):t[s]}})}return{state:i(o),onStateChange(n){e.push(n)},offStateChange(n){let t=e.indexOf(n);t!==-1&&e.splice(t,1)}}}var r=document.documentElement;function g(){let o=getComputedStyle(r).fontSize;return Number.parseInt(o)}function C(){let o=getComputedStyle(r).lineHeight;return Number.parseInt(o)/g()}var y={dyslexicFont:!1,invertedColors:!1,contraste:100,fontSize:g(),lineHeight:C()},{state:l,onStateChange:a,offStateChange:x}=u(y);a((o,e)=>{switch(o){case"dyslexicFont":e?r.classList.add("dyslexic"):r.classList.remove("dyslexic");break;case"invertedColors":e?r.classList.add("invertedColors"):r.classList.remove("invertedColors");break;case"fontSize":r.style.fontSize=e+"px";break;case"lineHeight":r.style.lineHeight=e;break}});var p={...y};function b(){for(let o in p)l[o]=p[o]}var v="preferences";a(()=>{localStorage.setItem(v,JSON.stringify(l))});var m=localStorage.getItem(v);if(m){let o=JSON.parse(m);for(let e in o)l[e]=o[e]}var S=`
|
|
21
|
+
:host {
|
|
22
|
+
font-size:18px;
|
|
23
|
+
line-height:1.5;
|
|
24
|
+
position:fixed;
|
|
25
|
+
top:3px;
|
|
26
|
+
right:5px;
|
|
27
|
+
}
|
|
28
|
+
:host([side="left"]) {
|
|
29
|
+
right:unset;
|
|
30
|
+
left:5px;
|
|
31
|
+
details {
|
|
32
|
+
align-items: flex-start;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
:host([all]), :host([dyslexic-font]) {
|
|
36
|
+
form .field[part=dyslexic-font] {
|
|
37
|
+
display:block;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
:host([all]), :host([invert-colors]) {
|
|
41
|
+
form .field[part=invert-colors] {
|
|
42
|
+
display:block;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
:host([all]), :host([font-size]) {
|
|
46
|
+
form .field[part=font-size] {
|
|
47
|
+
display:block;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
:host([all]), :host([line-height]) {
|
|
51
|
+
form .field[part=line-height] {
|
|
52
|
+
display:block;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
:host([rounded]) ::slotted([slot=icon]), :host([rounded]) #default-icon {
|
|
56
|
+
border-radius:50%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
details {
|
|
60
|
+
display:flex;
|
|
61
|
+
flex-direction:column;
|
|
62
|
+
align-items:flex-end;
|
|
63
|
+
|
|
64
|
+
summary {
|
|
65
|
+
cursor:pointer;
|
|
66
|
+
display:flex;
|
|
67
|
+
align-items:center;
|
|
68
|
+
|
|
69
|
+
#default-icon {
|
|
70
|
+
border:1px solid #ccc;
|
|
71
|
+
background-color:#ddd;
|
|
72
|
+
border-radius:5px;
|
|
73
|
+
width:40px;
|
|
74
|
+
height:40px;
|
|
75
|
+
&:hover {
|
|
76
|
+
background-color:#e1e1e1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
::slotted([slot=icon]) {
|
|
80
|
+
border:1px solid #ccc;
|
|
81
|
+
background-color:#ddd;
|
|
82
|
+
border-radius:5px;
|
|
83
|
+
padding:0 8px;
|
|
84
|
+
font-size:30px;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
form {
|
|
89
|
+
font-size:1em;
|
|
90
|
+
border:1px solid #ccc;
|
|
91
|
+
color:#222;
|
|
92
|
+
background-color:#fafafa;
|
|
93
|
+
line-height:2.5;
|
|
94
|
+
text-align: left;
|
|
95
|
+
border-radius:5px;
|
|
96
|
+
|
|
97
|
+
.field, ::slotted([slot=option]) {
|
|
98
|
+
padding: 0 25px 0 15px;
|
|
99
|
+
display:block;
|
|
100
|
+
&:hover {
|
|
101
|
+
background-color:#eee;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.field {
|
|
106
|
+
display:none;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
input {
|
|
110
|
+
font-size:1em;
|
|
111
|
+
font-family:unset;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
input[type=number] {
|
|
115
|
+
width:5ch;
|
|
116
|
+
border:1px solid #ccc;
|
|
117
|
+
border-radius:5px;
|
|
118
|
+
padding:3px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[part=buttons] {
|
|
122
|
+
text-align:center;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
`;var c=document.createElement("template");c.innerHTML=`
|
|
127
|
+
<style>${S}</style>
|
|
128
|
+
<details part="details">
|
|
129
|
+
<summary part="summary" aria-label="accessibility settings">
|
|
130
|
+
<slot name="icon">
|
|
131
|
+
<svg viewBox="0 0 389.9 389.6" part="icon" id="default-icon">
|
|
132
|
+
<circle fill="none" cx="250.6" cy="146.4" r="35.7" transform="matrix(.160226 -.98708 .98708 .160226 6.75 311.71)"></circle>
|
|
133
|
+
<path d="M191.4 130.7c-23.693 0-42.9-19.207-42.9-42.9s19.207-42.9 42.9-42.9 42.9 19.207 42.9 42.9a42.89 42.89 0 0 1-42.9
|
|
134
|
+
42.9zm0-71.5c-13.69-.038-25.498 9.605-28.197 23.026a28.68 28.68 0 0 0 17.105 32.135c12.641 5.256 27.234.846 34.848-10.531A28.68
|
|
135
|
+
28.68 0 0 0 211.6 67.6a29.06 29.06 0 0 0-20.2-8.4zm52.5 278.6a21.46 21.46 0 0 1-19.5-12.6l-33.1-80.3-32.7 80.1a21.41 21.41 0 0
|
|
136
|
+
1-37.1 4.1 21.57 21.57 0 0 1-2.1-21.5l34.4-87.5a26.63 26.63 0 0 0 1.9-10.4v-16.4a7.09 7.09 0 0 0-6.5-7.1l-60.6-5.5c-11.791
|
|
137
|
+
-.911-20.611-11.209-19.7-23s11.209-20.611 23-19.7l75.1 6.7a97.18 97.18 0 0 0 7.7.3h33.4a99.08 99.08 0 0 0 7.7-.3l75-6.7h.1c11.791
|
|
138
|
+
-.911 22.089 7.909 23 19.7s-7.909 22.089-19.7 23l-60.5 5.5a7.09 7.09 0 0 0-6.5 7.1v16.4a28.29 28.29 0 0 0 2 10.4l34.5 87.9a21.36
|
|
139
|
+
21.36 0 0 1-1.8 20.2 22.06 22.06 0 0 1-18 9.6zm-52.5-107.1a14.11 14.11 0 0 1 13.1 8.8l33 80.1a7.62 7.62 0 0 0 3.9 3.6 7.13 7.13
|
|
140
|
+
0 0 0 9-9.6l-34.6-88.3a42.14 42.14 0 0 1-3-15.7v-16.4c-.054-11.101 8.438-20.376 19.5-21.3l60.6-5.5a7 7 0 0 0 4.9-2.4 6.61 6.61
|
|
141
|
+
0 0 0 1.7-5.2 7 7 0 0 0-7.6-6.6l-74.9 6.7a88.33 88.33 0 0 1-8.9.4h-33.4a87 87 0 0 1-8.9-.4l-75-6.7a7.12 7.12 0 0 0-1 14.2l60.7
|
|
142
|
+
5.5c11.062.924 19.554 10.199 19.5 21.3v16.4a42.14 42.14 0 0 1-3 15.7l-34.5 87.9a7.09 7.09 0 0 0 .3 7.3 7.19 7.19 0 0 0 6.6 3.2
|
|
143
|
+
7 7 0 0 0 5.9-4.3l32.9-79.9a14 14 0 0 1 13.2-8.8z">
|
|
144
|
+
</path>
|
|
145
|
+
</svg>
|
|
146
|
+
</slot>
|
|
147
|
+
</summary>
|
|
148
|
+
<form part="form">
|
|
149
|
+
<div class="field" part="dyslexic-font">
|
|
150
|
+
<input type="checkbox" id="dyslexic-font">
|
|
151
|
+
<label for="dyslexic-font">Police dyslexie</label>
|
|
152
|
+
</div>
|
|
153
|
+
<div class="field" part="invert-colors">
|
|
154
|
+
<input type="checkbox" id="inverted-colors">
|
|
155
|
+
<label for="inverted-colors">Couleurs invers\xE9es</label>
|
|
156
|
+
</div>
|
|
157
|
+
<div class="field" part="font-size">
|
|
158
|
+
<input type="number" id="font-size">
|
|
159
|
+
<label for="font-size">Taille de police</label>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="field" part="line-height">
|
|
162
|
+
<input type="number" id="line-height" step="0.1">
|
|
163
|
+
<label for="line-height">Interligne</label>
|
|
164
|
+
</div>
|
|
165
|
+
<slot name="option"></slot>
|
|
166
|
+
<div part="buttons">
|
|
167
|
+
<input type="button" id="reset" value="R\xE9initialiser"/>
|
|
168
|
+
<input type="button" id="close" value="Terminer"/>
|
|
169
|
+
</div>
|
|
170
|
+
</form>
|
|
171
|
+
</details>
|
|
172
|
+
`;var k={fr:{"dyslexic-font":"Police dyslexie","inverted-colors":"Couleurs invers\xE9es","font-size":"Taille de police","line-height":"Hauteur de ligne",reset:"R\xE9initialiser",close:"Terminer"},en:{"dyslexic-font":"Dyslexic font","inverted-colors":"Inverted colors","font-size":"Font size","line-height":"Line height",reset:"Reset",close:"Close"}};var d=class extends HTMLElement{static languages=k;#e;#t;#i;#o;#s;constructor(){super();let e=this.attachShadow({mode:"open"});e.append(c.content.cloneNode(!0)),this.#e=e.querySelector("#dyslexic-font"),this.#t=e.querySelector("#inverted-colors"),this.#i=e.querySelector("#font-size"),this.#o=e.querySelector("#line-height"),this.#e.addEventListener("change",i=>l.dyslexicFont=i.target.checked),this.#t.addEventListener("change",i=>l.invertedColors=i.target.checked),this.#i.addEventListener("change",i=>l.fontSize=i.target.value),this.#o.addEventListener("change",i=>l.lineHeight=i.target.value),e.querySelector("#reset").addEventListener("click",b),e.querySelector("#close").addEventListener("click",()=>{e.querySelector("details").open=!1}),this.#s=new MutationObserver((i,n)=>{for(let t of i)t.attributeName==="lang"&&this.#n()})}#l=()=>{this.#e.checked=l.dyslexicFont,this.#t.checked=l.invertedColors,this.#i.value=l.fontSize,this.#o.value=l.lineHeight};#n(){let e=document.documentElement.lang,i=this.constructor.languages[e],n=this.shadowRoot.querySelectorAll("label");for(let t of n){let s=t.getAttribute("for");i[s]&&(t.textContent=i[s])}for(let t of["close","reset"])this.shadowRoot.querySelector(`#${t}`).value=i[t]}connectedCallback(){this.#l(),this.#n(),a(this.#l),this.#s.observe(document.documentElement,{attributes:!0})}disconnectedCallback(){x(this.#l),this.#s.disconnect()}};customElements.define("access-settings",d);})();
|
|
173
|
+
/**
|
|
174
|
+
* @license
|
|
175
|
+
* MIT License
|
|
176
|
+
|
|
177
|
+
Copyright (c) 2026 Yannick Bochatay https://github.com/YannickBochatay
|
|
178
|
+
|
|
179
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
180
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
181
|
+
in the Software without restriction, including without limitation the rights
|
|
182
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
183
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
184
|
+
furnished to do so, subject to the following conditions:
|
|
185
|
+
|
|
186
|
+
The above copyright notice and this permission notice shall be included in all
|
|
187
|
+
copies or substantial portions of the Software.
|
|
188
|
+
|
|
189
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
190
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
191
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
192
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
193
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
194
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
195
|
+
SOFTWARE.
|
|
196
|
+
**/
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<link rel="stylesheet" href="styles.css">
|
|
8
|
+
<script src="../src/index.js" type="module"></script>
|
|
9
|
+
<title>Access Settings Demo</title>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<header>
|
|
14
|
+
<h1>Lorem Ipsum</h1>
|
|
15
|
+
|
|
16
|
+
<access-settings side="left" all></access-settings>
|
|
17
|
+
|
|
18
|
+
<access-settings side="left" dyslexic-font font-size rounded>
|
|
19
|
+
<span slot="icon">⚙︎</span>
|
|
20
|
+
</access-settings>
|
|
21
|
+
|
|
22
|
+
<access-settings all side="left" rounded></access-settings>
|
|
23
|
+
|
|
24
|
+
<access-settings all side="left">
|
|
25
|
+
<span slot="icon">👁</span>
|
|
26
|
+
<div slot="option">
|
|
27
|
+
<label>
|
|
28
|
+
<input type="checkbox"/>
|
|
29
|
+
One more option
|
|
30
|
+
</label>
|
|
31
|
+
</div>
|
|
32
|
+
<div slot="option">
|
|
33
|
+
<label>
|
|
34
|
+
<input type="checkbox"/>
|
|
35
|
+
Another more option
|
|
36
|
+
</label>
|
|
37
|
+
</div>
|
|
38
|
+
</access-settings>
|
|
39
|
+
|
|
40
|
+
</header>
|
|
41
|
+
<main>
|
|
42
|
+
<article id="article-1">
|
|
43
|
+
<h2>Article 1</h2>
|
|
44
|
+
<section id="section-1-1">
|
|
45
|
+
<h3>Section 1</h3>
|
|
46
|
+
<p><strong>Lorem ipsum</strong> dolor sit amet, <em>consectetur</em> adipiscing elit. Morbi vel enim vel tortor auctor pharetra sit amet
|
|
47
|
+
in tellus. Vestibulum varius euismod enim vel dignissim. Maecenas aliquam sed nibh in mollis. Sed ut eros at
|
|
48
|
+
diam rhoncus vestibulum. Proin egestas lacinia risus, at vestibulum sapien congue vel. Vivamus non malesuada
|
|
49
|
+
augue. Nam blandit massa nec tellus ultrices, sed luctus mauris pulvinar. Mauris malesuada et erat sit amet
|
|
50
|
+
porta. Proin sit amet malesuada odio.</p>
|
|
51
|
+
<p>Nullam elementum mauris nec tellus vehicula, in commodo tellus tempus. Cras lectus lectus, consequat non mi
|
|
52
|
+
vitae, scelerisque dictum elit. Nulla quis elit rutrum, aliquet nisi at, congue dui. Vestibulum sed lorem sed
|
|
53
|
+
purus aliquet volutpat. Donec viverra laoreet urna sed fermentum. Nulla non tempus erat. Nulla mattis
|
|
54
|
+
venenatis urna in blandit. Morbi tempor in dui ac semper. Ut aliquam erat risus, a imperdiet est rutrum at.
|
|
55
|
+
Cras eros neque, tincidunt a urna nec, condimentum aliquet quam. Nullam vitae urna sit amet magna semper
|
|
56
|
+
gravida.</p>
|
|
57
|
+
</section>
|
|
58
|
+
<section id="section-1-2">
|
|
59
|
+
<h3>Section 2</h3>
|
|
60
|
+
<p>Phasellus et sem est. Vivamus bibendum dictum ligula vel tempor. Maecenas congue, enim eu sodales varius,
|
|
61
|
+
nibh sem laoreet ipsum, vitae fermentum ex tortor non purus. Vestibulum pulvinar malesuada elit, non euismod
|
|
62
|
+
tortor. Phasellus quis finibus urna. Nunc elementum mattis arcu, ac iaculis dui tristique molestie. Nunc
|
|
63
|
+
posuere sagittis leo ut pharetra.</p>
|
|
64
|
+
<p>Praesent in eros eget est tincidunt mattis vitae a sapien. Duis vehicula vulputate vestibulum. Proin vitae ex
|
|
65
|
+
condimentum tortor cursus laoreet. In quis lectus nec lorem imperdiet rutrum. Nam vitae lorem lacus.
|
|
66
|
+
Suspendisse eu rhoncus urna. Proin sed euismod odio. Sed egestas elit nec nisl finibus, in tincidunt leo
|
|
67
|
+
dictum.</p>
|
|
68
|
+
</section>
|
|
69
|
+
</article>
|
|
70
|
+
<article id="article-2">
|
|
71
|
+
<h2>Article 2</h2>
|
|
72
|
+
<section id="section-2-1">
|
|
73
|
+
<h3>Section 1</h3>
|
|
74
|
+
<p>Morbi vulputate sit amet libero id suscipit. Etiam tincidunt tellus eu turpis convallis semper. Pellentesque
|
|
75
|
+
vitae gravida sapien, sit amet commodo ante. Integer vestibulum posuere ex. Nam odio nulla, condimentum sed
|
|
76
|
+
libero in, suscipit viverra lorem. In a felis massa. Sed lacus odio, vulputate non quam a, fringilla faucibus
|
|
77
|
+
est. Phasellus facilisis sapien purus, ac aliquet elit lobortis a. Donec et scelerisque dui. Aenean vel eros
|
|
78
|
+
erat. Sed ultricies lectus in enim cursus, ut aliquam nunc convallis. Suspendisse potenti. Quisque nec
|
|
79
|
+
fermentum massa, blandit commodo dolor. Fusce convallis suscipit ante at suscipit. Quisque imperdiet eu tellus
|
|
80
|
+
ut porta.</p>
|
|
81
|
+
<p>Suspendisse potenti. Nunc sit amet elit ut odio posuere venenatis. Curabitur mattis, purus eu mattis mollis,
|
|
82
|
+
nulla quam consectetur massa, et tempus quam dui accumsan libero. Duis semper lorem quam. Donec nec vestibulum
|
|
83
|
+
eros. Proin sollicitudin maximus sem, ac elementum neque ornare a. Vestibulum consectetur mauris feugiat elit
|
|
84
|
+
euismod, eu commodo quam convallis. Morbi finibus nisi mattis justo egestas porttitor. Integer quis dolor sed
|
|
85
|
+
mauris feugiat interdum eget sit amet diam. Nulla dictum tellus convallis justo congue, et iaculis erat porta.
|
|
86
|
+
</p>
|
|
87
|
+
</section>
|
|
88
|
+
<section id="section-2-2">
|
|
89
|
+
<h3>Section 2</h3>
|
|
90
|
+
<p>Nulla tempus ligula non urna euismod hendrerit. Vestibulum egestas pretium suscipit. Nam sagittis justo ac
|
|
91
|
+
magna pellentesque, ut rutrum mauris eleifend. Vestibulum nisi risus, semper ut luctus dignissim, dignissim et
|
|
92
|
+
nibh. Nulla quis tincidunt erat, quis auctor libero. Suspendisse potenti. Morbi venenatis tristique vulputate.
|
|
93
|
+
Ut ut ullamcorper quam, vel auctor arcu. Fusce malesuada diam ac porttitor feugiat.</p>
|
|
94
|
+
<p>Mauris suscipit cursus arcu, ac elementum elit fermentum non. Aenean vitae convallis ante. Suspendisse
|
|
95
|
+
potenti. Proin faucibus, elit cursus aliquet hendrerit, metus lacus gravida purus, sed tempor tortor massa in
|
|
96
|
+
sem. Donec elementum at nisi at blandit. Nam accumsan bibendum dui, vel bibendum orci tincidunt pellentesque.
|
|
97
|
+
Proin consequat, libero eu sollicitudin lacinia, diam augue venenatis erat, sed pulvinar eros eros at nisl.
|
|
98
|
+
Nunc a placerat est. Aliquam facilisis vehicula nulla quis mattis. Ut tristique eros at finibus posuere. In
|
|
99
|
+
tempor, arcu vel facilisis commodo, lorem ante ultrices orci, ac faucibus neque leo eu leo. Aenean placerat mi
|
|
100
|
+
ac sollicitudin efficitur. Pellentesque nisi ante, tempor quis rutrum sed, tincidunt ac mauris. Vivamus
|
|
101
|
+
fringilla felis sed malesuada dictum. Ut tincidunt porta ipsum, eget scelerisque velit elementum id.</p>
|
|
102
|
+
</section>
|
|
103
|
+
</article>
|
|
104
|
+
<article id="article-3">
|
|
105
|
+
<h2>Article 3</h2>
|
|
106
|
+
<section id="section-3-1">
|
|
107
|
+
<h3>Section 1</h3>
|
|
108
|
+
<p>
|
|
109
|
+
Fusce et elit laoreet, pharetra dui in, accumsan felis. Phasellus volutpat, nibh a tempor dapibus, nisi magna feugiat augue, in volutpat sapien eros ac est. Sed dui leo, laoreet sit amet est tincidunt, bibendum maximus massa. Nunc sit amet blandit ante. Proin accumsan varius orci et interdum. Aenean pharetra ligula ac enim ornare, non accumsan turpis dictum. In non tellus quis urna fermentum luctus. Aenean suscipit dignissim orci, ut tempus arcu congue vitae. Nam tincidunt lobortis dapibus. Donec suscipit et ipsum vel posuere. Suspendisse at ligula purus.
|
|
110
|
+
</p>
|
|
111
|
+
<p>
|
|
112
|
+
Etiam placerat, ante a lobortis pretium, ex dolor tincidunt magna, non ullamcorper quam nisi at tellus. Sed accumsan eleifend egestas. Donec scelerisque tellus eget lacus rhoncus, consectetur semper nulla mattis. Praesent justo arcu, facilisis non tortor semper, mollis tincidunt leo. Aenean malesuada at lectus eget scelerisque. Maecenas faucibus turpis eget blandit fringilla. Nunc nulla ligula, dignissim non faucibus at, suscipit vel felis. Cras condimentum suscipit turpis. Nullam dapibus venenatis pretium. Phasellus elementum, nulla sit amet tristique faucibus, justo massa laoreet lectus, non maximus nulla nibh eu ante. Aenean posuere, ligula et ullamcorper ullamcorper, nisi arcu mollis ligula, a bibendum justo lectus ut nisi. Fusce dictum dictum lacus, at auctor ex consequat quis. Aenean suscipit tincidunt dui vel iaculis.
|
|
113
|
+
</p>
|
|
114
|
+
</section>
|
|
115
|
+
<section id="section-3-2">
|
|
116
|
+
<h3>Section 2</h3>
|
|
117
|
+
<p>
|
|
118
|
+
Fusce maximus libero quis scelerisque congue. Nam elementum elementum elementum. Nunc imperdiet, nunc ut porttitor aliquam, lacus neque ullamcorper elit, non commodo mi elit sit amet leo. Proin vehicula urna ac dui porta suscipit. Suspendisse non augue neque. Proin at fermentum libero, ut porttitor libero. Maecenas et pharetra felis. Curabitur quis porttitor mi. Integer convallis leo at quam ultrices volutpat.
|
|
119
|
+
</p>
|
|
120
|
+
<p>
|
|
121
|
+
Duis ac odio eget sapien cursus auctor non a justo. Nunc aliquam nulla ante, sed facilisis sem ultrices et. Fusce sed pharetra mi. Vestibulum vitae est et augue iaculis sollicitudin id ac risus. Aliquam urna nunc, pretium tincidunt tristique sed, vestibulum id urna. Vivamus leo magna, congue sit amet odio quis, viverra imperdiet lectus. Curabitur ac libero velit. Proin gravida urna id ipsum volutpat accumsan. Sed lacinia risus sapien, ac feugiat augue gravida ac. Cras et lacinia purus. Nulla nunc lacus, maximus rhoncus interdum et, luctus eu nisl.
|
|
122
|
+
</p>
|
|
123
|
+
</section>
|
|
124
|
+
</article>
|
|
125
|
+
<article id="article-4">
|
|
126
|
+
<h2>Article 4</h2>
|
|
127
|
+
<section id="section-4-1">
|
|
128
|
+
<h3>Section 1</h3>
|
|
129
|
+
<p>
|
|
130
|
+
Vestibulum ac sem massa. Nunc non finibus augue. Pellentesque scelerisque ipsum eu venenatis consectetur. Nullam nec sagittis velit. Vivamus faucibus lobortis aliquet. Duis commodo ex ac lacus sodales scelerisque. Integer ut dolor at ex lobortis viverra.
|
|
131
|
+
</p>
|
|
132
|
+
<p>
|
|
133
|
+
Donec urna nisl, lacinia in tincidunt vel, blandit nec arcu. Phasellus eget ipsum a nisi pellentesque lacinia. Nullam vel metus euismod, pellentesque lectus vitae, pretium ante. Morbi lacinia purus ut leo volutpat, eu luctus lectus posuere. Aenean eget dolor ornare mi dictum imperdiet. Nunc porta eleifend mauris sed pellentesque. Ut a massa sit amet metus vestibulum malesuada ac non odio. Fusce sollicitudin consequat ex non bibendum. Proin dignissim vulputate nisl, porta congue mi tincidunt et. Nunc egestas aliquet blandit.
|
|
134
|
+
</p>
|
|
135
|
+
</section>
|
|
136
|
+
<section id="section-4-2">
|
|
137
|
+
<h3>Section 2</h3>
|
|
138
|
+
<p>
|
|
139
|
+
In dolor sapien, pulvinar et odio quis, viverra dapibus justo. Fusce lacinia, dui a molestie iaculis, tortor ante vestibulum arcu, eu ultricies augue sapien in dolor. Integer posuere felis eget arcu dignissim maximus. Praesent vel mauris mattis, lacinia ipsum eget, vestibulum metus. Fusce tincidunt lorem vitae justo ultrices elementum. Quisque et rhoncus quam. Integer pretium pretium varius. Integer eget rhoncus risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis nibh quam, eleifend id vestibulum ac, finibus quis ligula. Duis placerat turpis volutpat euismod luctus. Aenean sed libero aliquet, gravida quam nec, elementum magna. Nullam convallis, ante in maximus pharetra, ipsum est efficitur magna, eget pellentesque turpis nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
140
|
+
</p>
|
|
141
|
+
<p>
|
|
142
|
+
Pellentesque accumsan urna in malesuada commodo. Curabitur hendrerit tincidunt enim, non sollicitudin elit tempus sit amet. Mauris id dui vulputate, fermentum felis sed, tincidunt orci. Suspendisse mollis in tortor non tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam pellentesque massa turpis, quis scelerisque eros placerat sed. Cras sollicitudin eget lorem id faucibus. Fusce sit amet consequat eros, quis aliquet nunc. Phasellus iaculis convallis magna, a egestas nulla egestas nec. Fusce quis elit vitae nisi lacinia pellentesque vitae vel sapien. Nullam rutrum fermentum sapien a interdum. Sed euismod ex risus, non interdum ipsum elementum sit amet. Nullam sed erat pretium, vehicula nibh in, semper libero. Nulla sem est, fringilla non velit id, laoreet ultricies dolor.
|
|
143
|
+
</p>
|
|
144
|
+
</section>
|
|
145
|
+
</article>
|
|
146
|
+
<article id="article-5">
|
|
147
|
+
<section id="section-5-1">
|
|
148
|
+
<p>
|
|
149
|
+
Sed vel purus vitae neque ornare commodo. Suspendisse interdum quis magna vel suscipit. Nullam id finibus massa. Nullam tincidunt at diam id pellentesque. Nulla vel mauris sollicitudin, aliquam urna quis, congue odio. Praesent rhoncus ante massa, eget vulputate diam finibus sit amet. Etiam sit amet felis vel libero sagittis venenatis at eget mi. Sed gravida augue eget odio lobortis feugiat. Donec tempor nec sapien eget laoreet. Proin at hendrerit odio. Nunc eget ipsum pharetra, suscipit risus sed, aliquam velit. Vestibulum egestas facilisis tortor ut sodales. Quisque vitae nisl sed ligula finibus dignissim.
|
|
150
|
+
</p>
|
|
151
|
+
</section>
|
|
152
|
+
<section id="section-5-2">
|
|
153
|
+
<p>
|
|
154
|
+
Maecenas a elementum augue. Pellentesque libero neque, gravida ac sem non, viverra interdum risus. Nulla facilisis tortor mi, eu imperdiet sapien venenatis hendrerit. Nam blandit a neque eget malesuada. Proin ac ultrices neque, eu dignissim enim. Duis massa lacus, ullamcorper dapibus quam eu, lacinia egestas ex. Donec justo ex, convallis non velit eget, viverra scelerisque leo. Duis lorem orci, imperdiet suscipit dolor at, lacinia efficitur augue. Vestibulum sed pellentesque ante. Phasellus placerat, lacus tristique vehicula mattis, nibh ligula vulputate diam, sed dignissim quam nulla vitae magna. Etiam consectetur rhoncus quam eget ultricies. Fusce ac orci quis ex posuere tempor. Aenean nec ligula in tortor rhoncus aliquet at id mi. Nam dignissim ante id ipsum sagittis, nec congue purus pharetra.
|
|
155
|
+
</p>
|
|
156
|
+
</section>
|
|
157
|
+
</article>
|
|
158
|
+
</main>
|
|
159
|
+
</body>
|
|
160
|
+
|
|
161
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: alex-brush;
|
|
3
|
+
src: url(https://fonts.cdnfonts.com/s/13498/AlexBrush-Regular.woff);
|
|
4
|
+
}
|
|
5
|
+
html {
|
|
6
|
+
--background: #efeff1;
|
|
7
|
+
--foreground: #fbfbfb;
|
|
8
|
+
--border: #dedde2;
|
|
9
|
+
|
|
10
|
+
--copy: #252329;
|
|
11
|
+
--copy-light: #645e6e;
|
|
12
|
+
--copy-lighter: #8a8495;
|
|
13
|
+
|
|
14
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
15
|
+
font-size:16px;
|
|
16
|
+
line-height:1.5;
|
|
17
|
+
color:var(--copy);
|
|
18
|
+
scroll-behavior:smooth;
|
|
19
|
+
background-color: var(--background);
|
|
20
|
+
}
|
|
21
|
+
h1 {
|
|
22
|
+
font-family: alex-brush, sans-serif;
|
|
23
|
+
font-size:4rem;
|
|
24
|
+
text-align:center;
|
|
25
|
+
}
|
|
26
|
+
a {
|
|
27
|
+
color:var(--copy);
|
|
28
|
+
}
|
|
29
|
+
nav {
|
|
30
|
+
padding:0px 30px;
|
|
31
|
+
border-radius:5px;
|
|
32
|
+
border:1px solid var(--border);
|
|
33
|
+
background-color: var(--foreground);
|
|
34
|
+
}
|
|
35
|
+
main {
|
|
36
|
+
margin:auto;
|
|
37
|
+
max-width:80ch;
|
|
38
|
+
}
|
|
39
|
+
p {
|
|
40
|
+
text-align:left;
|
|
41
|
+
text-indent:2rem;
|
|
42
|
+
padding:10px;
|
|
43
|
+
}
|
|
44
|
+
access-settings{
|
|
45
|
+
&:nth-of-type(1) {
|
|
46
|
+
left:20%;
|
|
47
|
+
}
|
|
48
|
+
&:nth-of-type(2) {
|
|
49
|
+
left:40%;
|
|
50
|
+
}
|
|
51
|
+
&:nth-of-type(3) {
|
|
52
|
+
left:60%;
|
|
53
|
+
&::part(icon) {
|
|
54
|
+
background-color: brown;
|
|
55
|
+
fill:white;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
&:nth-of-type(4) {
|
|
59
|
+
left:80%;
|
|
60
|
+
}
|
|
61
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "access-settings",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "web component for accessibility settings",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build-max": "esbuild src/index.js --bundle --outfile=dist/index.js",
|
|
8
|
+
"build-min": "esbuild src/index.js --bundle --minify --outfile=dist/index.min.js",
|
|
9
|
+
"build": "npm run build-max && npm run build-min",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/YannickBochatay/access-settings.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"accessiblity",
|
|
18
|
+
"webcomponent"
|
|
19
|
+
],
|
|
20
|
+
"author": "Yannick Bochatay",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/YannickBochatay/access-settings/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/YannickBochatay/access-settings#readme",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"esbuild": "0.27.2"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function createState(initialState) {
|
|
2
|
+
|
|
3
|
+
const listeners = [];
|
|
4
|
+
|
|
5
|
+
function createProxy(target) {
|
|
6
|
+
return new Proxy(target, {
|
|
7
|
+
|
|
8
|
+
set(target, prop, value) {
|
|
9
|
+
target[prop] = value;
|
|
10
|
+
listeners.forEach(callback => callback(String(prop), value));
|
|
11
|
+
return true;
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
get(target, prop) {
|
|
15
|
+
// from Chris Ferdinandi : https://gomakethings.com/guides/proxies/nesting/
|
|
16
|
+
if (prop === '_isProxy') return true;
|
|
17
|
+
if (target[prop]?._isProxy) return target[prop];
|
|
18
|
+
if (target[prop] && typeof target[prop] === 'object') return createProxy(target[prop]);
|
|
19
|
+
return target[prop];
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
state: createProxy(initialState),
|
|
26
|
+
onStateChange(callback) {
|
|
27
|
+
listeners.push(callback);
|
|
28
|
+
},
|
|
29
|
+
offStateChange(callback) {
|
|
30
|
+
const index = listeners.indexOf(callback);
|
|
31
|
+
if (index !== -1) listeners.splice(index, 1);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const globalStyles = document.createElement('style');
|
|
2
|
+
|
|
3
|
+
globalStyles.innerHTML = `
|
|
4
|
+
@font-face {
|
|
5
|
+
font-family: open-dyslexic;
|
|
6
|
+
src: url(https://fonts.cdnfonts.com/s/29616/open-dyslexic.woff);
|
|
7
|
+
}
|
|
8
|
+
:root.dyslexic {
|
|
9
|
+
font-family:open-dyslexic, sans-serif;
|
|
10
|
+
}
|
|
11
|
+
:root.invertedColors {
|
|
12
|
+
filter:invert(1);
|
|
13
|
+
}
|
|
14
|
+
@media (prefers-color-scheme: dark) {
|
|
15
|
+
:root:has(access-settings[invert-colors], access-settings[all]) {
|
|
16
|
+
filter:invert(1);
|
|
17
|
+
&.invertedColors {
|
|
18
|
+
filter:invert(0);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
document.head.append(globalStyles);
|
package/src/index.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026 Yannick Bochatay https://github.com/YannickBochatay
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
24
|
+
**/
|
|
25
|
+
|
|
26
|
+
import "./globalStyles.js"
|
|
27
|
+
import { preferences, resetPrefs, onStateChange, offStateChange } from "./preferences.js"
|
|
28
|
+
import { template } from "./template.js"
|
|
29
|
+
import languages from "./languages.json" with { type: "json" };
|
|
30
|
+
|
|
31
|
+
export class AccessSettings extends HTMLElement {
|
|
32
|
+
|
|
33
|
+
static languages = languages
|
|
34
|
+
|
|
35
|
+
#fontField
|
|
36
|
+
#colorsField
|
|
37
|
+
#fontSizeField
|
|
38
|
+
#lineHeightField
|
|
39
|
+
#observer
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
super();
|
|
43
|
+
const root = this.attachShadow({ mode : "open" });
|
|
44
|
+
root.append(template.content.cloneNode(true));
|
|
45
|
+
|
|
46
|
+
this.#fontField = root.querySelector("#dyslexic-font");
|
|
47
|
+
this.#colorsField = root.querySelector("#inverted-colors");
|
|
48
|
+
this.#fontSizeField = root.querySelector("#font-size");
|
|
49
|
+
this.#lineHeightField = root.querySelector("#line-height");
|
|
50
|
+
|
|
51
|
+
this.#fontField.addEventListener("change", e => preferences.dyslexicFont = e.target.checked);
|
|
52
|
+
this.#colorsField.addEventListener("change", e => preferences.invertedColors = e.target.checked);
|
|
53
|
+
this.#fontSizeField.addEventListener("change", e => preferences.fontSize = e.target.value);
|
|
54
|
+
this.#lineHeightField.addEventListener("change", e => preferences.lineHeight = e.target.value);
|
|
55
|
+
|
|
56
|
+
root.querySelector("#reset").addEventListener("click", resetPrefs);
|
|
57
|
+
root.querySelector("#close").addEventListener("click", () => {
|
|
58
|
+
root.querySelector("details").open = false;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.#observer = new MutationObserver((mutationList, observer) => {
|
|
62
|
+
for (const mutation of mutationList) {
|
|
63
|
+
if (mutation.attributeName === 'lang') this.#handleLangChange();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#handleStateChange = () => {
|
|
69
|
+
this.#fontField.checked = preferences.dyslexicFont;
|
|
70
|
+
this.#colorsField.checked = preferences.invertedColors;
|
|
71
|
+
this.#fontSizeField.value = preferences.fontSize;
|
|
72
|
+
this.#lineHeightField.value = preferences.lineHeight;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#handleLangChange() {
|
|
76
|
+
const lang = document.documentElement.lang
|
|
77
|
+
const locale = this.constructor.languages[lang]
|
|
78
|
+
const labels = this.shadowRoot.querySelectorAll("label")
|
|
79
|
+
|
|
80
|
+
for (let label of labels) {
|
|
81
|
+
let key = label.getAttribute("for")
|
|
82
|
+
if (locale[key]) label.textContent = locale[key]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (let id of ["close", "reset"]) {
|
|
86
|
+
this.shadowRoot.querySelector(`#${id}`).value = locale[id]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
connectedCallback() {
|
|
91
|
+
this.#handleStateChange();
|
|
92
|
+
this.#handleLangChange();
|
|
93
|
+
onStateChange(this.#handleStateChange);
|
|
94
|
+
this.#observer.observe( document.documentElement, { attributes: true });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
disconnectedCallback() {
|
|
98
|
+
offStateChange(this.#handleStateChange);
|
|
99
|
+
this.#observer.disconnect();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
customElements.define('access-settings', AccessSettings);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fr" : {
|
|
3
|
+
"dyslexic-font" : "Police dyslexie",
|
|
4
|
+
"inverted-colors" : "Couleurs inversées",
|
|
5
|
+
"font-size" : "Taille de police",
|
|
6
|
+
"line-height" : "Hauteur de ligne",
|
|
7
|
+
"reset" : "Réinitialiser",
|
|
8
|
+
"close" : "Terminer"
|
|
9
|
+
},
|
|
10
|
+
"en" : {
|
|
11
|
+
"dyslexic-font" : "Dyslexic font",
|
|
12
|
+
"inverted-colors" : "Inverted colors",
|
|
13
|
+
"font-size" : "Font size",
|
|
14
|
+
"line-height" : "Line height",
|
|
15
|
+
"reset" : "Reset",
|
|
16
|
+
"close" : "Close"
|
|
17
|
+
}
|
|
18
|
+
}
|