@oscarpalmer/oui 0.17.0 → 0.19.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.
Files changed (72) hide show
  1. package/dist/css/badge.css +13 -13
  2. package/dist/css/button.css +9 -9
  3. package/dist/css/color.css +99 -99
  4. package/dist/css/content.css +10 -12
  5. package/dist/css/flex.css +39 -39
  6. package/dist/css/form.css +47 -60
  7. package/dist/css/message.css +10 -6
  8. package/dist/css/reset.css +178 -57
  9. package/dist/css/table.css +4 -4
  10. package/dist/css/tooltip.css +26 -1
  11. package/dist/js/attributable.full.js +36 -0
  12. package/dist/js/attributable.js +30 -45
  13. package/dist/js/floatable.full.js +398 -0
  14. package/dist/js/floatable.js +254 -169
  15. package/dist/js/focus-trap/embedded.full.js +408 -0
  16. package/dist/js/focus-trap/embedded.js +131 -131
  17. package/dist/js/focus-trap/standalone.full.js +447 -0
  18. package/dist/js/focus-trap/standalone.js +4 -4
  19. package/dist/js/index.js +3 -4
  20. package/dist/js/oui.full.js +1573 -0
  21. package/dist/js/popover.full.js +760 -0
  22. package/dist/js/popover.js +84 -163
  23. package/dist/js/splitter.full.js +769 -0
  24. package/dist/js/splitter.js +264 -246
  25. package/dist/js/tooltip.full.js +613 -0
  26. package/dist/js/tooltip.js +160 -151
  27. package/package.json +35 -63
  28. package/src/css/a11y.scss +1 -1
  29. package/src/css/badge.scss +23 -19
  30. package/src/css/button.scss +9 -9
  31. package/src/css/color.scss +99 -99
  32. package/src/css/content.scss +6 -9
  33. package/src/css/flex.scss +21 -20
  34. package/src/css/form.scss +47 -62
  35. package/src/css/message.scss +11 -12
  36. package/src/css/mixins.scss +16 -10
  37. package/src/css/popover.scss +2 -2
  38. package/src/css/reset.scss +181 -55
  39. package/src/css/splitter.scss +15 -13
  40. package/src/css/table.scss +11 -11
  41. package/src/css/tooltip.scss +31 -2
  42. package/src/js/attributable.ts +3 -10
  43. package/src/js/floatable.ts +370 -141
  44. package/src/js/focus-trap/embedded.ts +141 -74
  45. package/src/js/focus-trap/standalone.ts +4 -4
  46. package/src/js/index.ts +1 -0
  47. package/src/js/popover.ts +52 -122
  48. package/src/js/splitter.ts +248 -131
  49. package/src/js/tooltip.ts +143 -68
  50. package/types/floatable.d.ts +17 -10
  51. package/types/focus-trap/embedded.d.ts +18 -5
  52. package/types/index.d.ts +1 -0
  53. package/types/popover.d.ts +2 -0
  54. package/types/splitter.d.ts +13 -1
  55. package/types/tooltip.d.ts +2 -1
  56. package/dist/css/value.css +0 -1
  57. package/dist/js/attributable.cjs +0 -51
  58. package/dist/js/floatable.cjs +0 -176
  59. package/dist/js/focus-trap/embedded.cjs +0 -150
  60. package/dist/js/focus-trap/standalone.cjs +0 -8
  61. package/dist/js/index.cjs +0 -6
  62. package/dist/js/popover.cjs +0 -166
  63. package/dist/js/splitter.cjs +0 -272
  64. package/dist/js/tooltip.cjs +0 -166
  65. package/types/attributable.d.cts +0 -5
  66. package/types/floatable.d.cts +0 -20
  67. package/types/focus-trap/embedded.d.cts +0 -15
  68. package/types/focus-trap/standalone.d.cts +0 -3
  69. package/types/index.d.cts +0 -14
  70. package/types/popover.d.cts +0 -14
  71. package/types/splitter.d.cts +0 -10
  72. package/types/tooltip.d.cts +0 -3
@@ -13,9 +13,15 @@
13
13
  * - Andy Bell's "A (more) Modern CSS Reset" [AB]
14
14
  * https://andy-bell.co.uk/a-more-modern-css-reset/
15
15
  *
16
+ * - Chris Coyier's "The Coyier CSS Starter" [CC]
17
+ * https://frontendmasters.com/blog/the-coyier-css-starter/
18
+ *
16
19
  * - CSS Remedy [CR]
17
20
  * https://github.com/jensimmons/cssremedy
18
21
  *
22
+ * - Harry Roberts [HR]
23
+ * - https://github.com/csswizardry
24
+ *
19
25
  * - RESS [RS]
20
26
  * https://github.com/filipelinhares/ress
21
27
  *
@@ -43,12 +49,14 @@
43
49
  font-family: system-ui, sans-serif;
44
50
  font-size: 100%;
45
51
  line-height: 1.5;
52
+ /** Prevent text size inflation (e.g., after orientation change) [AB][RE][SE] */
46
53
  -webkit-text-size-adjust: none;
47
54
  -moz-text-size-adjust: none;
48
- text-size-adjust: none; /* Prevent text size inflation (e.g., after orientation change) [AB][RE][SE]*/
55
+ text-size-adjust: none;
49
56
  -moz-tab-size: 4;
50
57
  -o-tab-size: 4;
51
58
  tab-size: 4;
59
+ word-break: break-word;
52
60
  }
53
61
 
54
62
  :where(body) {
@@ -65,50 +73,85 @@
65
73
  text-underline-offset: 0.125em;
66
74
  }
67
75
 
76
+ :where(abbr[title], dfn[title]) {
77
+ cursor: help;
78
+ }
79
+
68
80
  :where(abbr[title]) {
69
- text-decoration: underline; /* Add the correct text decoration in Safari [RS][SE]*/
81
+ /** Add the correct text decoration in Safari [RS][SE] */
82
+ text-decoration: underline;
83
+ /** Ditto */
70
84
  -webkit-text-decoration: underline dotted;
71
- text-decoration: underline dotted; /* ditto*/
85
+ text-decoration: underline dotted;
72
86
  }
73
87
 
74
88
  :where(b, strong) {
75
- font-weight: bolder; /* Add the correct font weight in Chrome, Edge, and Safari [RS][SE]*/
89
+ /** Add the correct font weight in Chrome, Edge, and Safari [RS][SE], without compounding [HR] */
90
+ font-weight: bold;
76
91
  }
77
92
 
78
93
  :where(button, h1, h2, h3, h4, h5, h6, input, label, legend) {
79
- line-height: 1.125; /* Set shorter line heights on headings and interactive elements [AB]*/
80
- }
81
-
82
- :where(button, [type=button i], [type=reset i], [type=submit i]) {
94
+ /** Set shorter line heights on headings and interactive elements [AB] */
95
+ line-height: 1.125;
96
+ }
97
+
98
+ :where(button,
99
+ input[type=button i],
100
+ input[type=checkbox i],
101
+ input[type=file i],
102
+ input[type=image i],
103
+ input[type=radio i],
104
+ input[type=reset i],
105
+ input[type=submit i],
106
+ summary) {
107
+ /** Correct the inability to style clickable types in iOS [HR][RS][SE] */
83
108
  -webkit-appearance: button;
84
109
  -moz-appearance: button;
85
- appearance: button; /* Correct the inability to style clickable types in iOS [RS][SE]*/
110
+ appearance: button;
111
+ /** Ditto */
86
112
  cursor: pointer;
87
113
  }
88
114
 
89
- :where(code, kbd, pre, samp) {
90
- font-family: monospace, monospace; /* Specify the font family of code elements [RS][SE]*/
91
- font-size: 1em; /* Correct the odd 'em' font sizing in all browsers [RS][SE]*/
115
+ :where(code, kbd, output, pre, samp) {
116
+ /** Specify the font family of code elements [HR][RS][SE] */
117
+ font-family: monospace, monospace;
118
+ /** Correct the odd 'em' font sizing in all browsers [HR][RS][SE] */
119
+ font-size: inherit;
92
120
  }
93
121
 
94
122
  :where(details > summary:first-of-type) {
95
- display: list-item; /* Add the correct display in Safari [SE]*/
123
+ /** Add the correct display in Safari [SE] */
124
+ display: list-item;
96
125
  }
97
126
 
98
127
  :where(dl, ol, ul) :where(dl, ol, ul) {
99
- margin: 0; /* Remove the margin on nested lists in Chrome, Edge, and Safari [SE]*/
128
+ /** Remove the margin on nested lists in Chrome, Edge, and Safari [SE] */
129
+ margin: 0;
100
130
  }
101
131
 
102
132
  :where(h1, h2, h3, h4, h5, h6) {
103
133
  text-wrap: balance;
104
134
  }
105
135
 
136
+ :where(h1) {
137
+ /** Consistent sizing across browsers [HR] */
138
+ font-size: 2em;
139
+ }
140
+
106
141
  :where(hr) {
107
- height: 0; /* Add the correct box sizing in Firefox [CR][RS][SE]*/
108
- overflow: visible; /* Show the overflow in Edge and IE [CR][RS]*/
142
+ /** Add the correct box sizing in Firefox [CR][RS][SE] */
143
+ height: 0;
144
+ /** Show the overflow in Edge and IE [CR][RS] */
145
+ overflow: visible;
109
146
  border-style: solid;
110
147
  border-width: 1px 0 0;
111
- color: inherit; /* Correct the inheritance of border colour in Firefox [CR][RS][SE]*/
148
+ /** // Correct the inheritance of border colour in Firefox [CR][RS][SE] */
149
+ color: inherit;
150
+ }
151
+
152
+ :where(ins, u) {
153
+ /** Prevent link styling [HR] */
154
+ text-decoration: none;
112
155
  }
113
156
 
114
157
  :where(nav) :where(ol, ul),
@@ -118,22 +161,24 @@
118
161
  }
119
162
 
120
163
  :where(nav li)::before {
121
- content: "​"; /* Prevent VoiceOver from ignoring list semantics in Safari [SE]*/
164
+ /** Prevent VoiceOver from ignoring list semantics in Safari [SE] */
165
+ content: "​";
122
166
  float: left;
123
167
  }
124
168
 
125
169
  :where(pre) {
126
- overflow: auto; /* Prevent overflow of the container in all browsers [SE]*/
127
- white-space: pre-wrap; /* Overflow by default is bad… [CR]*/
170
+ /** Prevent overflow of the container in all browsers [SE] */
171
+ overflow: auto;
172
+ /** Overflow by default is bad… [CR] */
173
+ white-space: pre-wrap;
128
174
  }
129
175
 
130
- :where(small) {
176
+ :where(small, sub, sup) {
131
177
  font-size: 0.875rem;
132
178
  }
133
179
 
134
180
  :where(sub, sup) {
135
181
  vertical-align: baseline;
136
- font-size: 0.75rem;
137
182
  line-height: 0;
138
183
  position: relative;
139
184
  }
@@ -148,101 +193,129 @@
148
193
 
149
194
  :where(table) {
150
195
  border-collapse: collapse;
151
- border-color: currentColor; /* Correct table border colour in Chrome, Edge, and Safari [SE]*/
152
- text-indent: 0; /* Remove text indentation from table contents in Chrome, Edge, and Safari [RS][SE]*/
196
+ /** Correct table border colour in Chrome, Edge, and Safari [SE] */
197
+ border-color: currentcolor;
198
+ /** Modernized border spacing [HR] */
199
+ border-spacing: 0;
200
+ /** More legible numbers [HR] */
201
+ font-variant-numeric: tabular-nums;
202
+ /** Remove text indentation from table contents in Chrome, Edge, and Safari [RS][SE] */
203
+ text-indent: 0;
153
204
  }
154
205
 
155
206
  /**
156
207
  * Form-related
157
208
  */
158
209
  :where(button, input, optgroup, select, textarea) {
159
- font: inherit; /* Correct the font inheritance in Firefox, Edge, and Safari [RS][SE]*/
210
+ /** Correct the font inheritance in Firefox, Edge, and Safari [HR][RS][SE] */
211
+ font: inherit;
160
212
  }
161
213
 
162
214
  :where(button, input, select, textarea) {
163
- padding: 0.25em 0.5em; /* Change the inconsistent appearance in all browsers [SE]*/
164
- background-color: transparent; /* ditto*/
165
- border: 1px solid WindowFrame; /* ditto*/
166
- color: inherit; /* ditto*/
167
- letter-spacing: inherit; /* ditto*/
215
+ /** Change the inconsistent appearance in all browsers [SE] */
216
+ padding: 0.25em 0.5em;
217
+ /** Ditto for all */
218
+ background-color: transparent;
219
+ border: 1px solid WindowFrame;
220
+ color: inherit;
221
+ letter-spacing: inherit;
168
222
  }
169
223
 
170
224
  :where(fieldset) {
171
- border: 1px solid darkgrey; /* Change the inconsistent appearance in all browsers [SE]*/
225
+ /** Change the inconsistent appearance in all browsers [SE] */
226
+ border: 1px solid darkgrey;
172
227
  }
173
228
 
174
229
  :where(optgroup) {
175
- font-weight: bold; /* Restore the font weight unset by previous rules [RS]*/
230
+ /** Restore the font weight unset by previous rules [RS] */
231
+ font-weight: bold;
176
232
  }
177
233
 
178
234
  :where(progress) {
179
- vertical-align: baseline; /* Add the correct vertical alignment in Chrome, Edge, and Firefox [RS][SE]*/
235
+ /** Add the correct vertical alignment in Chrome, Edge, and Firefox [RS][SE] */
236
+ vertical-align: baseline;
180
237
  }
181
238
 
182
239
  :where(select, input[list]) {
240
+ /** Change the inconsistent appearance in all browsers [SE] */
183
241
  -webkit-appearance: none;
184
242
  -moz-appearance: none;
185
- appearance: none; /* Change the inconsistent appearance in all browsers [SE]*/
186
- padding-right: 1em; /* ditto*/
243
+ appearance: none;
244
+ /** Ditto for all */
245
+ padding-right: 1em;
187
246
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='4'%3E%3Cpath d='M4 0h6L7 4'/%3E%3C/svg%3E");
188
- background-position: right center/1em; /* ditto*/
189
- background-repeat: no-repeat; /* ditto*/
190
- border-radius: 0; /* ditto*/
247
+ background-position: right center/1em;
248
+ background-repeat: no-repeat;
249
+ border-radius: 0;
191
250
  }
192
251
 
193
252
  :where(select[multiple]) {
194
- background-image: none; /* Don't show the arrow for multiple choice selects [SE]*/
253
+ /** Don't show the arrow for multiple choice selects [SE] */
254
+ background-image: none;
195
255
  }
196
256
 
197
257
  :where(textarea) {
198
- resize: vertical; /* Change the resize direction in all browsers [RS][SE]*/
258
+ /** Change the resize direction in all browsers [RS][SE] */
259
+ resize: vertical;
199
260
  }
200
261
 
201
262
  :where([type=color i], [type=range i]) {
202
- padding: 0; /* Remove the padding in all browsers [SE]*/
203
- border-width: 0; /* Remove the border in all browsers [SE]*/
263
+ /** Remove the padding in all browsers [SE] */
264
+ padding: 0;
265
+ /** Remove the border in all browsers [SE] */
266
+ border-width: 0;
204
267
  }
205
268
 
206
269
  :where([type=search i]) {
270
+ /** Correct the odd appearance in Chrome, Edge, and Safari [RS][SE] */
207
271
  -webkit-appearance: textfield;
208
272
  -moz-appearance: textfield;
209
- appearance: textfield; /* Correct the odd appearance in Chrome, Edge, and Safari [RS][SE]*/
210
- outline-offset: -2px; /* Correct the outline style in Safari [RS][SE]*/
273
+ appearance: textfield;
274
+ /** Correct the outline style in Safari [RS][SE] */
275
+ outline-offset: -2px;
211
276
  }
212
277
 
213
278
  ::file-selector-button {
279
+ /** Correct the inability to style upload buttons in iOS and Safari [RS][SE] */
214
280
  -webkit-appearance: button;
215
281
  -moz-appearance: button;
216
- appearance: button; /* Correct the inability to style upload buttons in iOS and Safari [RS][SE]*/
282
+ appearance: button;
217
283
  color: inherit;
218
284
  font: inherit;
219
285
  line-height: 1.25;
220
286
  }
221
287
 
222
288
  ::-moz-placeholder {
223
- opacity: 0.54; /* Correct the text style of placeholders in Chrome, Edge, and Safari. [SE]*/
224
- color: inherit; /* Correct the text style of placeholders in Chrome, Edge, and Safari. [SE]*/
289
+ /** Better default text opacity [OP] */
290
+ opacity: 0.67;
291
+ /** Better default text color [HR][SE] */
292
+ color: inherit;
225
293
  }
226
294
 
227
295
  ::placeholder {
228
- opacity: 0.54; /* Correct the text style of placeholders in Chrome, Edge, and Safari. [SE]*/
229
- color: inherit; /* Correct the text style of placeholders in Chrome, Edge, and Safari. [SE]*/
296
+ /** Better default text opacity [OP] */
297
+ opacity: 0.67;
298
+ /** Better default text color [HR][SE] */
299
+ color: inherit;
230
300
  }
231
301
 
232
302
  ::-webkit-inner-spin-button,
233
303
  ::-webkit-outer-spin-button {
234
- height: auto; /* Correct the cursor style of increment and decrement buttons in Safari [RS][SE]*/
304
+ /** Correct the cursor style of increment and decrement buttons in Safari [RS][SE] */
305
+ height: auto;
235
306
  }
236
307
 
237
308
  ::-webkit-search-decoration {
238
- -webkit-appearance: none; /* Remove the inner padding in Chrome, Edge, and Safari on macOS [SE]*/
309
+ /** Remove the inner padding in Chrome, Edge, and Safari on macOS [SE] */
310
+ -webkit-appearance: none;
311
+ appearance: none;
239
312
  }
240
313
 
241
314
  /**
242
315
  * Media-related
243
316
  */
244
317
  :where(audio, canvas, embed, iframe, img, object, picture, svg, video) {
245
- max-width: 100%;
318
+ max-inline-size: 100%;
246
319
  vertical-align: middle;
247
320
  }
248
321
 
@@ -251,7 +324,8 @@
251
324
  }
252
325
 
253
326
  :where(audio) {
254
- width: 100%; /* Better default width [CR]*/
327
+ /** Better default width [CR] */
328
+ width: 100%;
255
329
  }
256
330
 
257
331
  :where(audio:not([controls])) {
@@ -259,23 +333,35 @@
259
333
  }
260
334
 
261
335
  :where(canvas, img, svg, video) {
262
- height: auto; /* Maintain aspect ratios [CR]*/
336
+ /** Proportional height based on width [HR] */
337
+ block-size: auto;
263
338
  }
264
339
 
265
340
  :where(iframe) {
266
341
  border-style: none;
267
342
  }
268
343
 
344
+ :where(img) {
345
+ /** CSS magic! [HR] */
346
+ background-repeat: no-repeat;
347
+ /** Ditto */
348
+ background-size: cover;
349
+ /** Offset alt-text if image does not load [HR] */
350
+ font-style: italic;
351
+ }
352
+
269
353
  :where(picture) {
270
- display: contents; /* Remove the unnecessary wrapping 'picture', while maintaining contents [CR]*/
354
+ /** Remove the unnecessary wrapping 'picture', while maintaining contents [CR] */
355
+ display: contents;
271
356
  }
272
357
 
273
358
  :where(source) {
274
- display: none; /* Source elements have nothing to display, so we hide them entirely [CR]*/
359
+ /** Source elements have nothing to display, so we hide them entirely [CR] */
360
+ display: none;
275
361
  }
276
362
 
277
363
  :where(svg:not([fill])) {
278
- fill: currentColor;
364
+ fill: currentcolor;
279
365
  }
280
366
 
281
367
  /**
@@ -297,4 +383,39 @@
297
383
  cursor: pointer;
298
384
  }
299
385
 
386
+ /**
387
+ * Pseudo-classes
388
+ */
389
+ :where(:target) {
390
+ scroll-margin: 2rlh;
391
+ }
392
+
393
+ /**
394
+ * Media queries
395
+ */
396
+ @media (prefers-reduced-motion: no-preference) {
397
+ :where(:root) {
398
+ /** Allow for animations on auto-sizes [CC] */
399
+ interpolate-size: allow-keywords;
400
+ }
401
+ :where(:root:focus-within) {
402
+ /** Allow for smooth scrolling to focused elements */
403
+ scroll-behavior: smooth;
404
+ }
405
+ }
406
+ @media (prefers-reduced-motion: reduce) {
407
+ :where(:root:focus-within) {
408
+ /** Disable smooth scrolling, when requested */
409
+ scroll-behavior: auto;
410
+ }
411
+ /** Disable animations and transitions, when requested */
412
+ :where(*),
413
+ ::after,
414
+ ::before {
415
+ animation-duration: 0.01ms !important;
416
+ animation-iteration-count: 1 !important;
417
+ transition-duration: 0.01ms !important;
418
+ scroll-behavior: auto !important;
419
+ }
420
+ }
300
421
 
@@ -3,7 +3,7 @@
3
3
  width: 100%;
4
4
  background-color: var(--oui-absolute);
5
5
  }
6
- :where(.oui-table-wrapper) {
6
+ :where(.oui-table_wrapper) {
7
7
  max-height: 32em;
8
8
  overflow: auto;
9
9
  border: 1px solid var(--oui-gray-3);
@@ -16,7 +16,7 @@
16
16
  align-content: center;
17
17
  background-color: var(--oui-gray-1);
18
18
  border: solid var(--oui-gray-3);
19
- border-width: 0 0 1px 0;
19
+ border-width: 0 0 1px;
20
20
  font-size: 0.875rem;
21
21
  text-align: left;
22
22
  text-indent: 0.5rem;
@@ -58,7 +58,7 @@
58
58
  :where(.oui-table thead th)::after {
59
59
  --oui-shadow-direction: bottom;
60
60
  border-top: 1px solid var(--oui-gray-3);
61
- inset: 100% 0 0 0;
61
+ inset: 100%;
62
62
  }
63
63
  :where(.oui-table:has(caption) thead th) {
64
64
  top: 2rem;
@@ -69,7 +69,7 @@
69
69
  :where(.oui-table tfoot td)::after {
70
70
  --oui-shadow-direction: top;
71
71
  border-bottom: 1px solid var(--oui-gray-3);
72
- inset: -4px 0 0 0;
72
+ inset: -4px;
73
73
  }
74
74
  :where(.oui-table tbody td) {
75
75
  border: solid var(--oui-gray-3);
@@ -1,5 +1,22 @@
1
1
 
2
- :where([oui-tooltip]:is(abbr, b, cite, dfn, code, em, i, kbd, mark, q, samp, small, span, strong, sub, sup, time, var)) {
2
+ :where([oui-tooltip]:is(abbr,
3
+ b,
4
+ cite,
5
+ dfn,
6
+ code,
7
+ em,
8
+ i,
9
+ kbd,
10
+ mark,
11
+ q,
12
+ samp,
13
+ small,
14
+ span,
15
+ strong,
16
+ sub,
17
+ sup,
18
+ time,
19
+ var)) {
3
20
  -webkit-text-decoration: underline dotted;
4
21
  text-decoration: underline dotted;
5
22
  -webkit-text-decoration-skip: ink;
@@ -12,9 +29,17 @@
12
29
  box-shadow: inset 0 1px 0 0 transparent, 0 0 0 1px rgba(0, 0, 0, 0.05), 0 1px 2px -0.5px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.05), 0 4px 8px -2px rgba(0, 0, 0, 0.05), 0 8px 16px -4px rgba(0, 0, 0, 0.05), 0 16px 32px -8px rgba(0, 0, 0, 0.05), 0 32px 64px -16px rgba(0, 0, 0, 0.05), 0 64px 128px -32px rgba(0, 0, 0, 0.05);
13
30
  max-width: 48ch;
14
31
  padding: 0.75em 1em;
32
+ opacity: 0;
15
33
  background-color: var(--oui-absolute);
16
34
  border-radius: 0.25rem;
17
35
  font-size: 0.875rem;
36
+ transition: opacity 0.125s ease-in-out;
37
+ transition-delay: 0s;
38
+ }
39
+
40
+ :where([oui-tooltip-content][oui-tooltip-content-active]) {
41
+ opacity: 1;
42
+ transition-delay: 0.25s;
18
43
  }
19
44
 
20
45
 
@@ -0,0 +1,36 @@
1
+ function attributable(attribute, add, remove) {
2
+ new MutationObserver((entries) => {
3
+ const { length } = entries;
4
+ for (let index = 0; index < length; index += 1) {
5
+ const entry = entries[index];
6
+ if (entry.type === "attributes" && entry.target instanceof HTMLElement) if (entry.target.hasAttribute(attribute)) handleAdded(attribute, [entry.target], add);
7
+ else handleRemoved([entry.target], remove);
8
+ else if (entry.type === "childList") {
9
+ handleAdded(attribute, entry.addedNodes, add);
10
+ handleRemoved(entry.removedNodes, remove);
11
+ }
12
+ }
13
+ }).observe(document, {
14
+ attributeFilter: [attribute],
15
+ attributes: true,
16
+ childList: true,
17
+ subtree: true
18
+ });
19
+ requestAnimationFrame(() => {
20
+ handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
21
+ });
22
+ }
23
+ function handleAdded(attribute, nodes, add) {
24
+ const elements = [...nodes].filter((node) => node instanceof HTMLElement);
25
+ const { length } = elements;
26
+ for (let index = 0; index < length; index += 1) {
27
+ const element = elements[index];
28
+ if (element.hasAttribute(attribute)) add(element);
29
+ }
30
+ }
31
+ function handleRemoved(nodes, remove) {
32
+ const elements = [...nodes].filter((node) => node instanceof HTMLElement);
33
+ const { length } = elements;
34
+ for (let index = 0; index < length; index += 1) remove(elements[index]);
35
+ }
36
+ export { attributable };
@@ -1,51 +1,36 @@
1
1
  function attributable(attribute, add, remove) {
2
- const observer = new MutationObserver((entries) => {
3
- const { length } = entries;
4
- for (let index = 0; index < length; index += 1) {
5
- const entry = entries[index];
6
- if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
7
- if (entry.target.hasAttribute(attribute)) {
8
- handleAdded(attribute, [entry.target], add);
9
- } else {
10
- handleRemoved([entry.target], remove);
11
- }
12
- } else if (entry.type === "childList") {
13
- handleAdded(attribute, entry.addedNodes, add);
14
- handleRemoved(entry.removedNodes, remove);
15
- }
16
- }
17
- });
18
- observer.observe(document, {
19
- attributeFilter: [attribute],
20
- attributes: true,
21
- childList: true,
22
- subtree: true
23
- });
24
- requestAnimationFrame(() => {
25
- handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
26
- });
2
+ new MutationObserver((entries) => {
3
+ const { length } = entries;
4
+ for (let index = 0; index < length; index += 1) {
5
+ const entry = entries[index];
6
+ if (entry.type === "attributes" && entry.target instanceof HTMLElement) if (entry.target.hasAttribute(attribute)) handleAdded(attribute, [entry.target], add);
7
+ else handleRemoved([entry.target], remove);
8
+ else if (entry.type === "childList") {
9
+ handleAdded(attribute, entry.addedNodes, add);
10
+ handleRemoved(entry.removedNodes, remove);
11
+ }
12
+ }
13
+ }).observe(document, {
14
+ attributeFilter: [attribute],
15
+ attributes: true,
16
+ childList: true,
17
+ subtree: true
18
+ });
19
+ requestAnimationFrame(() => {
20
+ handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
21
+ });
27
22
  }
28
23
  function handleAdded(attribute, nodes, add) {
29
- const elements = [...nodes].filter(
30
- (node) => node instanceof HTMLElement
31
- );
32
- const { length } = elements;
33
- for (let index = 0; index < length; index += 1) {
34
- const element = elements[index];
35
- if (element.hasAttribute(attribute)) {
36
- add(element);
37
- }
38
- }
24
+ const elements = [...nodes].filter((node) => node instanceof HTMLElement);
25
+ const { length } = elements;
26
+ for (let index = 0; index < length; index += 1) {
27
+ const element = elements[index];
28
+ if (element.hasAttribute(attribute)) add(element);
29
+ }
39
30
  }
40
31
  function handleRemoved(nodes, remove) {
41
- const elements = [...nodes].filter(
42
- (node) => node instanceof HTMLElement
43
- );
44
- const { length } = elements;
45
- for (let index = 0; index < length; index += 1) {
46
- remove(elements[index]);
47
- }
32
+ const elements = [...nodes].filter((node) => node instanceof HTMLElement);
33
+ const { length } = elements;
34
+ for (let index = 0; index < length; index += 1) remove(elements[index]);
48
35
  }
49
- export {
50
- attributable
51
- };
36
+ export { attributable };