semantic-forms 5.1.2 → 5.1.4
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/CHANGELOG.md +11 -1
- package/dist/semantic-forms.cjs +6 -4
- package/dist/semantic-forms.cjs.map +1 -1
- package/dist/semantic-forms.css +1 -0
- package/dist/semantic-forms.css.map +1 -1
- package/dist/semantic-forms.js +6 -4
- package/dist/semantic-forms.js.map +1 -1
- package/dist/semantic-forms.min.js +1 -1
- package/dist/semantic-forms.min.js.map +1 -1
- package/dist/semantic-forms.min.mjs +1 -1
- package/dist/semantic-forms.min.mjs.map +1 -1
- package/dist/semantic-forms.mjs +8 -6
- package/dist/semantic-forms.mjs.map +1 -1
- package/docs/statics/js/semantic-forms-main.js +4 -0
- package/docs/statics/pages/fullDemo.html +11 -35
- package/docs/statics/pages/layouts/main.html +4 -4
- package/docs/statics/pages/usage.html +20 -0
- package/package.json +2 -2
- package/semanticForms.js +19 -9
- package/semanticForms.scss +10 -9
|
@@ -144,8 +144,11 @@
|
|
|
144
144
|
|
|
145
145
|
<dt><label for="range">Range field</label></dt>
|
|
146
146
|
<dd><input id="range" name="range" type="range"></dd>
|
|
147
|
+
|
|
148
|
+
<dt><label for="rangeValue">Range value</label></dt>
|
|
149
|
+
<dd><input id="rangeValue" name="rangeValue" type="range" class="displayValue"></dd>
|
|
147
150
|
</dl>
|
|
148
|
-
|
|
151
|
+
|
|
149
152
|
<h3>Selects</h3>
|
|
150
153
|
<dl>
|
|
151
154
|
<dt><label for="selectbox">Select box</label></dt>
|
|
@@ -236,15 +239,15 @@
|
|
|
236
239
|
<dd class="checkboxes">
|
|
237
240
|
<ul id="extra-text-checkboxes">
|
|
238
241
|
<li>
|
|
239
|
-
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_one" checked>
|
|
242
|
+
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_one" checked>
|
|
240
243
|
<label for="extra-text-checkboxes_one">One</label>
|
|
241
244
|
</li>
|
|
242
245
|
<li>
|
|
243
|
-
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_two">
|
|
246
|
+
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_two">
|
|
244
247
|
<label for="extra-text-checkboxes_two">Two</label>
|
|
245
248
|
</li>
|
|
246
249
|
<li>
|
|
247
|
-
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_three" checked>
|
|
250
|
+
<input type="checkbox" name="extra-text-field" id="extra-text-checkboxes_three" checked>
|
|
248
251
|
<label for="extra-text-checkboxes_three">Three</label></li>
|
|
249
252
|
</ul>
|
|
250
253
|
<label data-for="extra-text-checkboxes">This is some additional text.</label>
|
|
@@ -267,7 +270,7 @@
|
|
|
267
270
|
<label for="additional-text-checkbox">This is some additional text.</label>
|
|
268
271
|
</dd>
|
|
269
272
|
</dl>
|
|
270
|
-
|
|
273
|
+
|
|
271
274
|
|
|
272
275
|
<h3>Radios</h3>
|
|
273
276
|
<dl>
|
|
@@ -305,15 +308,15 @@
|
|
|
305
308
|
<dd class="radios">
|
|
306
309
|
<ul id="radios-with-additional-text">
|
|
307
310
|
<li>
|
|
308
|
-
<input type="radio" name="radios-with-additional-text" id="a_r_one">
|
|
311
|
+
<input type="radio" name="radios-with-additional-text" id="a_r_one">
|
|
309
312
|
<label for="a_r_one">One</label>
|
|
310
313
|
</li>
|
|
311
314
|
<li>
|
|
312
|
-
<input type="radio" name="radios-with-additional-text" id="a_r_two">
|
|
315
|
+
<input type="radio" name="radios-with-additional-text" id="a_r_two">
|
|
313
316
|
<label for="a_r_two">Two</label>
|
|
314
317
|
</li>
|
|
315
318
|
<li>
|
|
316
|
-
<input type="radio" name="radios-with-additional-text" id="a_r_three">
|
|
319
|
+
<input type="radio" name="radios-with-additional-text" id="a_r_three">
|
|
317
320
|
<label for="a_r_three">Three</label>
|
|
318
321
|
</li>
|
|
319
322
|
</ul>
|
|
@@ -1229,11 +1232,6 @@
|
|
|
1229
1232
|
</main>
|
|
1230
1233
|
<script>
|
|
1231
1234
|
document.addEventListener('DOMContentLoaded', () => {
|
|
1232
|
-
document.body.insertAdjacentHTML('afterbegin', '<p id="mode"><button></button></p>')
|
|
1233
|
-
document.querySelector('#mode button').addEventListener('click', (event) => toggleDarkMode())
|
|
1234
|
-
if (window.matchMedia('(prefers-color-scheme: dark)').matches) toggleDarkMode('dark')
|
|
1235
|
-
else toggleDarkMode('light')
|
|
1236
|
-
|
|
1237
1235
|
const forms = document.querySelectorAll('form')
|
|
1238
1236
|
for (const form of forms) {
|
|
1239
1237
|
form.addEventListener('submit', e => e.preventDefault())
|
|
@@ -1247,28 +1245,6 @@
|
|
|
1247
1245
|
})
|
|
1248
1246
|
}
|
|
1249
1247
|
})
|
|
1250
|
-
|
|
1251
|
-
function toggleDarkMode (mode) {
|
|
1252
|
-
if (mode === 'light' || document.body.className === 'dark') {
|
|
1253
|
-
document.documentElement.className = 'light'
|
|
1254
|
-
document.body.className = 'light'
|
|
1255
|
-
document.querySelector('#mode button').innerHTML = 'Switch to dark mode'
|
|
1256
|
-
const forms = document.querySelectorAll('form')
|
|
1257
|
-
for (const form of forms) {
|
|
1258
|
-
form.classList.add('light')
|
|
1259
|
-
form.classList.remove('dark')
|
|
1260
|
-
}
|
|
1261
|
-
} else {
|
|
1262
|
-
document.documentElement.className = 'dark'
|
|
1263
|
-
document.body.className = 'dark'
|
|
1264
|
-
document.querySelector('#mode button').innerHTML = 'Switch to light mode'
|
|
1265
|
-
const forms = document.querySelectorAll('form')
|
|
1266
|
-
for (const form of forms) {
|
|
1267
|
-
form.classList.add('dark')
|
|
1268
|
-
form.classList.remove('light')
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
1248
|
</script>
|
|
1273
1249
|
</body>
|
|
1274
1250
|
</html>
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
<meta name="description" content="Describe your website here">
|
|
9
9
|
<!--! this inline script makes it possible for check-if-CSS-is-disabled to listen for any CSS files that fail to load -->
|
|
10
10
|
<script>window.addEventListener('error', (event) => { if (event?.target?.tagName === 'LINK') { window.linkTagError = true } }, true)</script>
|
|
11
|
-
<link rel="preload" href="/css/styles.css" as="style">
|
|
12
|
-
<link rel="preload" href="/js/main.js" as="script">
|
|
13
|
-
<link rel="stylesheet" href="/css/styles.css">
|
|
11
|
+
<link rel="preload" href="/css/semantic-forms-styles.css" as="style">
|
|
12
|
+
<link rel="preload" href="/js/semantic-forms-main.js" as="script">
|
|
13
|
+
<link rel="stylesheet" href="/css/semantic-forms-styles.css">
|
|
14
14
|
<link rel="stylesheet" href="/css/highlight.js.light.css">
|
|
15
15
|
<link rel="stylesheet" href="/css/highlight.js.dark.css" media="(prefers-color-scheme: dark)">
|
|
16
|
-
<script src="/js/main.js" defer></script>
|
|
16
|
+
<script src="/js/semantic-forms-main.js" defer></script>
|
|
17
17
|
</head>
|
|
18
18
|
<body class="no-js" id="semantic-forms-usage">
|
|
19
19
|
<main>
|
|
@@ -503,6 +503,26 @@
|
|
|
503
503
|
</dl>
|
|
504
504
|
</form>
|
|
505
505
|
|
|
506
|
+
<h4 id="rangeInputsThatDisplayValues">Range inputs that display values</h4>
|
|
507
|
+
|
|
508
|
+
<p>Add a class of <code>displayValue</code> to any <code><!--#<input type="range">--></code> element to make its value display on the label:</p>
|
|
509
|
+
|
|
510
|
+
<pre><code class='language-html' lang='html'><escape>
|
|
511
|
+
<form class="semanticForms">
|
|
512
|
+
<dl>
|
|
513
|
+
<dt><label for="rangeValue">Range value</label></dt>
|
|
514
|
+
<dd><input id="rangeValue" name="rangeValue" type="range" class="displayValue"></dd>
|
|
515
|
+
</dl>
|
|
516
|
+
</form>
|
|
517
|
+
</escape></code></pre>
|
|
518
|
+
|
|
519
|
+
<form class="semanticForms">
|
|
520
|
+
<dl>
|
|
521
|
+
<dt><label for="rangeValue">Range value</label></dt>
|
|
522
|
+
<dd><input id="rangeValue" name="rangeValue" type="range" class="displayValue"></dd>
|
|
523
|
+
</dl>
|
|
524
|
+
</form>
|
|
525
|
+
|
|
506
526
|
<h3 id="lightanddarkmode">Light mode and dark mode</h3>
|
|
507
527
|
|
|
508
528
|
<p>Light mode and dark mode will be detected automatically based on operating system preference. To set it manually, you can apply an additional class of <code>light</code> or <code>dark</code> to your <code><!--#<form>--></code> elements to force the mode.</p>
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"url": "https://github.com/rooseveltframework/semantic-forms/graphs/contributors"
|
|
9
9
|
}
|
|
10
10
|
],
|
|
11
|
-
"version": "5.1.
|
|
11
|
+
"version": "5.1.4",
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
14
|
"semanticForms.scss",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@jsdevtools/coverage-istanbul-loader": "3.0.5",
|
|
24
24
|
"@playwright/test": "1.54.2",
|
|
25
|
-
"eslint": "9.
|
|
25
|
+
"eslint": "9.33.0",
|
|
26
26
|
"eslint-plugin-html": "8.1.3",
|
|
27
27
|
"express": "5.1.0",
|
|
28
28
|
"nodemon": "3.1.10",
|
package/semanticForms.js
CHANGED
|
@@ -7,7 +7,7 @@ const semanticForms = () => {
|
|
|
7
7
|
|
|
8
8
|
const passwordShow = '<svg fill="none" height="256" viewBox="0 0 24 24" width="256" xmlns="http://www.w3.org/2000/svg"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m1 12s4-8 11-8 11 8 11 8"/><path d="m1 12s4 8 11 8 11-8 11-8"/><circle cx="12" cy="12" r="3"/></g></svg>'
|
|
9
9
|
const passwordHide = '<svg fill="none" height="256" viewBox="0 0 24 24" width="256" xmlns="http://www.w3.org/2000/svg"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m2 2 20 20"/><path d="m6.71277 6.7226c-3.04798 2.07267-4.71277 5.2774-4.71277 5.2774s3.63636 7 10 7c2.0503 0 3.8174-.7266 5.2711-1.7116m-6.2711-12.23018c.3254-.03809.6588-.05822 1-.05822 6.3636 0 10 7 10 7s-.6918 1.3317-2 2.8335"/><path d="m14 14.2362c-.5308.475-1.2316.7639-2 .7639-1.6569 0-3-1.3431-3-3 0-.8237.33193-1.5698.86932-2.11192"/></g></svg>'
|
|
10
|
-
const helpTextIcon = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="
|
|
10
|
+
const helpTextIcon = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" version="1.1" style="overflow:visible;margin-top:1px;"><rect width="16" height="16" fill="none"/><path fill="currentColor" d="M8,10.5c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C9,10.948,8.552,10.5,8,10.5z M8,0 C3.582,0,0,3.582,0,8c0,4.418,3.582,8,8,8s8-3.582,8-8C16,3.582,12.418,0,8,0z M12.243,12.243C11.109,13.376,9.603,14,8,14 s-3.109-0.624-4.243-1.757C2.624,11.109,2,9.603,2,8s0.624-3.109,1.757-4.243C4.891,2.624,6.397,2,8,2s3.109,0.624,4.243,1.757 C13.376,4.891,14,6.397,14,8C14,9.603,13.376,11.109,12.243,12.243z M7.927,3.755c-2.248,0-2.76,1.695-2.802,2.906h1.571 c0.028-0.256,0.101-1.418,1.221-1.418c0.672,0,1.206,0.406,1.206,1.175c0,0.695-0.724,1.155-1.303,1.711 C7.241,8.685,7.168,9.325,7.168,9.824V10c0.146,0,1.615,0,1.615,0V9.824c0-1.256,1.967-1.594,1.967-3.541 C10.75,5.059,9.874,3.755,7.927,3.755z"/></svg>'
|
|
11
11
|
|
|
12
12
|
const nodeNameLookup = ['TEXTAREA', 'SELECT']
|
|
13
13
|
const inputTypeLookup = ['checkbox', 'color', 'date', 'datetime-local', 'email', 'file', 'image', 'month', 'number', 'password', 'radio', 'range', 'search', 'tel', 'text', 'time', 'url', 'week']
|
|
@@ -149,7 +149,7 @@ const semanticForms = () => {
|
|
|
149
149
|
clearBtn.innerHTML = '<svg viewBox="0 0 16 16" width="18" height="18"><path d="M 1 1 L 15 15 M 1 15 L 15 1" fill="none" stroke-width="2" stroke="currentColor" />'
|
|
150
150
|
clearBtn.classList.add('clear')
|
|
151
151
|
clearBtn.id = `semanticFormsClearButton_${input.id}`
|
|
152
|
-
clearBtn.addEventListener('click', (
|
|
152
|
+
clearBtn.addEventListener('click', () => {
|
|
153
153
|
input.previousValue = input.value
|
|
154
154
|
input.value = ''
|
|
155
155
|
input.focus()
|
|
@@ -157,7 +157,7 @@ const semanticForms = () => {
|
|
|
157
157
|
})
|
|
158
158
|
insertAfter(clearBtn, dd.querySelector('label'))
|
|
159
159
|
}
|
|
160
|
-
input.addEventListener('focus',
|
|
160
|
+
input.addEventListener('focus', event => {
|
|
161
161
|
if (event.target.nodeName === 'INPUT') lastFocusedInput = event.target
|
|
162
162
|
})
|
|
163
163
|
// #endregion
|
|
@@ -179,14 +179,24 @@ const semanticForms = () => {
|
|
|
179
179
|
// handle file input clear btn, cannot be handled with CSS
|
|
180
180
|
if (type === 'file') {
|
|
181
181
|
const clearBtn = input.parentElement.querySelector('.clear')
|
|
182
|
-
input.addEventListener('input',
|
|
183
|
-
clearBtn.style.display =
|
|
182
|
+
input.addEventListener('input', event => {
|
|
183
|
+
clearBtn.style.display = event.target.files.length ? 'flex' : 'none'
|
|
184
184
|
})
|
|
185
185
|
clearBtn.addEventListener('click', () => {
|
|
186
186
|
clearBtn.style.display = 'none'
|
|
187
187
|
})
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
// handle range inputs with a class to display the value
|
|
191
|
+
if (type === 'range' && input.classList.contains('displayValue')) {
|
|
192
|
+
const label = input.parentNode.parentNode.querySelector('dd label')
|
|
193
|
+
label.innerHTML += `<span class="seperator">: </span><output>${input.value}</output>`
|
|
194
|
+
input.addEventListener('input', event => {
|
|
195
|
+
const output = event.target.parentNode.parentNode.querySelector('output')
|
|
196
|
+
output.innerHTML = event.target.value
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
190
200
|
// #region show password button
|
|
191
201
|
if (type === 'password' && input.getAttribute('data-no-reveal') === null) {
|
|
192
202
|
const showBtn = document.createElement('button')
|
|
@@ -202,7 +212,7 @@ const semanticForms = () => {
|
|
|
202
212
|
console.error(`semantic-forms: Found an input (${input.id || input.getAttribute('name')}) that is not inside a <dd> element.`)
|
|
203
213
|
continue
|
|
204
214
|
}
|
|
205
|
-
showBtn.addEventListener('click', (
|
|
215
|
+
showBtn.addEventListener('click', () => {
|
|
206
216
|
if (input.type === 'password') {
|
|
207
217
|
showBtn.innerHTML = passwordHide
|
|
208
218
|
showBtn.title = input.getAttribute('data-hide-password-text') || 'Hide password'
|
|
@@ -248,7 +258,7 @@ const semanticForms = () => {
|
|
|
248
258
|
// handle undo/redo
|
|
249
259
|
let lastFocusedInput
|
|
250
260
|
let lastClearFieldPressed
|
|
251
|
-
document.addEventListener('keydown',
|
|
261
|
+
document.addEventListener('keydown', event => {
|
|
252
262
|
if ((event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey) {
|
|
253
263
|
// undo clearing a field
|
|
254
264
|
if (lastFocusedInput) {
|
|
@@ -274,7 +284,7 @@ const semanticForms = () => {
|
|
|
274
284
|
|
|
275
285
|
// monitor changes to the DOM and enhance new semanticForms forms that get added
|
|
276
286
|
if (!window.semanticFormsObserver) {
|
|
277
|
-
window.semanticFormsObserver = new window.MutationObserver(
|
|
287
|
+
window.semanticFormsObserver = new window.MutationObserver(mutations => {
|
|
278
288
|
let stop = false
|
|
279
289
|
for (const mutation of mutations) {
|
|
280
290
|
for (const node of mutation.addedNodes) {
|
|
@@ -289,7 +299,7 @@ const semanticForms = () => {
|
|
|
289
299
|
window.semanticFormsObserver.observe(document.body, { attributes: false, childList: true, characterData: false, subtree: true })
|
|
290
300
|
}
|
|
291
301
|
|
|
292
|
-
semanticForms.reinitialize =
|
|
302
|
+
semanticForms.reinitialize = form => {
|
|
293
303
|
form.classList.remove('semanticFormsActive')
|
|
294
304
|
semanticForms()
|
|
295
305
|
}
|
package/semanticForms.scss
CHANGED
|
@@ -81,9 +81,9 @@ html:not(.light) {
|
|
|
81
81
|
}
|
|
82
82
|
// #endregion
|
|
83
83
|
|
|
84
|
-
form.semanticForms,
|
|
85
|
-
form.semanticForms.light,
|
|
86
|
-
table.semanticForms,
|
|
84
|
+
form.semanticForms,
|
|
85
|
+
form.semanticForms.light,
|
|
86
|
+
table.semanticForms,
|
|
87
87
|
table.semanticForms.light {
|
|
88
88
|
font-family: var(--semanticFormsFontFamily);
|
|
89
89
|
width: 100%;
|
|
@@ -193,7 +193,7 @@ table.semanticForms.light {
|
|
|
193
193
|
|
|
194
194
|
select {
|
|
195
195
|
cursor: pointer;
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
&:not([multiple]) {
|
|
198
198
|
// custom dropdown graphic on select element
|
|
199
199
|
background-image: var(--semanticFormsSelectIcon);
|
|
@@ -240,7 +240,7 @@ table.semanticForms.light {
|
|
|
240
240
|
& + label.floatLabelFormAnimatedLabel {
|
|
241
241
|
left: 32px !important; // override float label
|
|
242
242
|
}
|
|
243
|
-
|
|
243
|
+
|
|
244
244
|
&:focus,
|
|
245
245
|
&:not(:placeholder-shown) {
|
|
246
246
|
& + label.floatLabelFormAnimatedLabel {
|
|
@@ -310,6 +310,7 @@ table.semanticForms.light {
|
|
|
310
310
|
padding: 5px 25px;
|
|
311
311
|
font-size: 100%;
|
|
312
312
|
line-height: 1;
|
|
313
|
+
user-select: none;
|
|
313
314
|
|
|
314
315
|
&:active {
|
|
315
316
|
background-image: linear-gradient(to bottom, var(--semanticFormsButtonGradientDark) 0%, var(--semanticFormsButtonGradientLight) 100%);
|
|
@@ -409,7 +410,7 @@ table.semanticForms.light {
|
|
|
409
410
|
@supports (scrollbar-color: auto) {
|
|
410
411
|
textarea {
|
|
411
412
|
scrollbar-color: var(--semanticFormsScrollbarColor) transparent;
|
|
412
|
-
|
|
413
|
+
|
|
413
414
|
&::-webkit-resizer {
|
|
414
415
|
border: none;
|
|
415
416
|
background-image: var(--semanticFormsCustomResizer);
|
|
@@ -419,7 +420,7 @@ table.semanticForms.light {
|
|
|
419
420
|
margin: 0 2px 2px 0;
|
|
420
421
|
}
|
|
421
422
|
}
|
|
422
|
-
|
|
423
|
+
|
|
423
424
|
select[multiple] {
|
|
424
425
|
scrollbar-color: var(--semanticFormsScrollbarColor) transparent;
|
|
425
426
|
}
|
|
@@ -1167,7 +1168,7 @@ table.semanticForms {
|
|
|
1167
1168
|
th:last-of-type, td:last-of-type {
|
|
1168
1169
|
border-right: none;
|
|
1169
1170
|
}
|
|
1170
|
-
|
|
1171
|
+
|
|
1171
1172
|
tbody {
|
|
1172
1173
|
tr:last-of-type {
|
|
1173
1174
|
th, td {
|
|
@@ -1180,6 +1181,6 @@ table.semanticForms {
|
|
|
1180
1181
|
menu:has(li > input, li > label, li > button, li > select, li > textarea) {
|
|
1181
1182
|
width: max-content;
|
|
1182
1183
|
}
|
|
1183
|
-
|
|
1184
|
+
|
|
1184
1185
|
}
|
|
1185
1186
|
// #endregion
|