@splendidlabz/utils 1.11.2 → 1.11.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.
Files changed (228) hide show
  1. package/dist/cjs/dom/accessibility.cjs +2 -0
  2. package/dist/cjs/dom/actions/index.cjs +392 -7
  3. package/dist/cjs/dom/actions/masonry.cjs +97 -6
  4. package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +58 -14
  5. package/dist/cjs/dom/actions/sticky.cjs +126 -6
  6. package/dist/cjs/dom/bounding-box.cjs +2 -0
  7. package/dist/cjs/dom/clipboard.cjs +2 -0
  8. package/dist/cjs/dom/cookie.cjs +3 -1
  9. package/dist/cjs/dom/css-vars.cjs +13 -3
  10. package/dist/cjs/dom/events.cjs +2 -0
  11. package/dist/cjs/dom/focusable.cjs +2 -0
  12. package/dist/cjs/dom/font-size.cjs +15 -3
  13. package/dist/cjs/dom/get-element.cjs +3 -1
  14. package/dist/cjs/dom/hash.cjs +2 -0
  15. package/dist/cjs/dom/index.cjs +1249 -47
  16. package/dist/cjs/dom/keyboard.cjs +2 -0
  17. package/dist/cjs/dom/local-store.cjs +3 -1
  18. package/dist/cjs/dom/media.cjs +2 -0
  19. package/dist/cjs/dom/observers/index.cjs +235 -9
  20. package/dist/cjs/dom/observers/intersection-observer.cjs +38 -6
  21. package/dist/cjs/dom/observers/mutation-observer.cjs +38 -6
  22. package/dist/cjs/dom/observers/observer.cjs +12 -2
  23. package/dist/cjs/dom/observers/resize-observer.cjs +38 -6
  24. package/dist/cjs/dom/observers/scroll-observer.cjs +62 -3
  25. package/dist/cjs/dom/pkce.cjs +13 -3
  26. package/dist/cjs/dom/query-params.cjs +3 -1
  27. package/dist/cjs/dom/random-string.cjs +2 -0
  28. package/dist/cjs/dom/sanitize.cjs +27 -3
  29. package/dist/cjs/dom/session-store.cjs +3 -1
  30. package/dist/cjs/dom/spam-prevention.cjs +2 -0
  31. package/dist/cjs/dom/trap-focus.cjs +131 -9
  32. package/dist/cjs/dom/ui/aria-current.cjs +2 -0
  33. package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +2 -0
  34. package/dist/cjs/dom/ui/index.cjs +87 -9
  35. package/dist/cjs/dom/ui/scroll-container.cjs +2 -0
  36. package/dist/cjs/dom/ui/traverse-and-scramble.cjs +2 -0
  37. package/dist/cjs/lib/arrays/index.cjs +121 -13
  38. package/dist/cjs/lib/arrays/item-position.cjs +2 -0
  39. package/dist/cjs/lib/arrays/join.cjs +10 -2
  40. package/dist/cjs/lib/arrays/shuffle.cjs +2 -0
  41. package/dist/cjs/lib/arrays/sort.cjs +11 -3
  42. package/dist/cjs/lib/arrays/split-array.cjs +2 -0
  43. package/dist/cjs/lib/arrays/unique.cjs +2 -0
  44. package/dist/cjs/lib/auth/index.cjs +35 -3
  45. package/dist/cjs/lib/auth/route-manager.cjs +2 -0
  46. package/dist/cjs/lib/checks.cjs +2 -0
  47. package/dist/cjs/lib/date/days.cjs +3 -1
  48. package/dist/cjs/lib/date/index.cjs +190 -7
  49. package/dist/cjs/lib/date/months.cjs +3 -1
  50. package/dist/cjs/lib/date/time.cjs +14 -2
  51. package/dist/cjs/lib/form/form-data.cjs +2 -0
  52. package/dist/cjs/lib/form/index.cjs +104 -5
  53. package/dist/cjs/lib/form/sanitize.cjs +2 -0
  54. package/dist/cjs/lib/functions/callback.cjs +2 -0
  55. package/dist/cjs/lib/functions/debounce.cjs +2 -0
  56. package/dist/cjs/lib/functions/env.cjs +2 -0
  57. package/dist/cjs/lib/functions/functional.cjs +2 -0
  58. package/dist/cjs/lib/functions/index.cjs +124 -11
  59. package/dist/cjs/lib/functions/throttle.cjs +2 -0
  60. package/dist/cjs/lib/functions/timeout.cjs +2 -0
  61. package/dist/cjs/lib/hash.cjs +2 -0
  62. package/dist/cjs/lib/index.cjs +1160 -29
  63. package/dist/cjs/lib/numbers/index.cjs +17 -4
  64. package/dist/cjs/lib/numbers/math.cjs +2 -0
  65. package/dist/cjs/lib/objects/camelcase-keys.cjs +45 -4
  66. package/dist/cjs/lib/objects/empty.cjs +2 -0
  67. package/dist/cjs/lib/objects/equal.cjs +2 -0
  68. package/dist/cjs/lib/objects/extend.cjs +117 -6
  69. package/dist/cjs/lib/objects/flatten.cjs +11 -3
  70. package/dist/cjs/lib/objects/index.cjs +360 -27
  71. package/dist/cjs/lib/objects/json.cjs +2 -0
  72. package/dist/cjs/lib/objects/loop.cjs +2 -0
  73. package/dist/cjs/lib/objects/mix/mix.cjs +5 -3
  74. package/dist/cjs/lib/objects/nested-property.cjs +2 -0
  75. package/dist/cjs/lib/objects/normalize-object.cjs +78 -4
  76. package/dist/cjs/lib/objects/omit-empty.cjs +2 -0
  77. package/dist/cjs/lib/objects/size.cjs +2 -0
  78. package/dist/cjs/lib/objects/split.cjs +2 -0
  79. package/dist/cjs/lib/promises/index.cjs +51 -3
  80. package/dist/cjs/lib/promises/reject.cjs +19 -2
  81. package/dist/cjs/lib/sse.cjs +29 -4
  82. package/dist/cjs/lib/strings/convert-case/convert-case.cjs +2 -0
  83. package/dist/cjs/lib/strings/index.cjs +179 -11
  84. package/dist/cjs/lib/strings/markdown.cjs +3 -1
  85. package/dist/cjs/lib/strings/name.cjs +2 -0
  86. package/dist/cjs/lib/strings/pluralize.cjs +3 -1
  87. package/dist/cjs/lib/strings/query-string.cjs +2 -0
  88. package/dist/cjs/lib/style/index.cjs +31 -2
  89. package/dist/cjs/lib/symbols/index.cjs +22 -3
  90. package/dist/cjs/lib/symbols/symbols.cjs +2 -0
  91. package/dist/cjs/node/context.cjs +0 -0
  92. package/dist/cjs/node/dirname.cjs +4 -2
  93. package/dist/cjs/node/file-cache.cjs +45 -3
  94. package/dist/cjs/node/file.cjs +4 -2
  95. package/dist/cjs/node/hash.cjs +3 -1
  96. package/dist/cjs/node/index.cjs +278 -15
  97. package/dist/cjs/node/pkce.cjs +20 -8
  98. package/dist/cjs/node/random-string.cjs +3 -1
  99. package/dist/cjs/node/sanitize.cjs +27 -3
  100. package/dist/cjs/node/uuid.cjs +2 -0
  101. package/dist/esm/node/context.js +0 -0
  102. package/dist/esm/node/file-cache.js +1 -1
  103. package/dist/esm/node/pkce.js +3 -2
  104. package/dist/types/node/context.d.cts +2 -0
  105. package/dist/types/node/index.d.cts +1 -1
  106. package/dist/types/node/pkce.d.cts +7 -1
  107. package/package.json +5 -2
  108. package/CHANGELOG.md +0 -231
  109. package/eslint.config.js +0 -2
  110. package/src/dom/accessibility.js +0 -58
  111. package/src/dom/actions/index.js +0 -3
  112. package/src/dom/actions/masonry.js +0 -43
  113. package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
  114. package/src/dom/actions/sticky.js +0 -85
  115. package/src/dom/bounding-box.js +0 -82
  116. package/src/dom/clipboard.js +0 -14
  117. package/src/dom/cookie.js +0 -32
  118. package/src/dom/css-vars.js +0 -19
  119. package/src/dom/events.js +0 -71
  120. package/src/dom/focusable.js +0 -165
  121. package/src/dom/font-size.js +0 -40
  122. package/src/dom/get-element.js +0 -176
  123. package/src/dom/hash.js +0 -9
  124. package/src/dom/index.js +0 -23
  125. package/src/dom/keyboard.js +0 -44
  126. package/src/dom/local-store.js +0 -66
  127. package/src/dom/media.js +0 -30
  128. package/src/dom/observers/index.js +0 -4
  129. package/src/dom/observers/intersection-observer.js +0 -43
  130. package/src/dom/observers/mutation-observer.js +0 -51
  131. package/src/dom/observers/observer.js +0 -18
  132. package/src/dom/observers/resize-observer.js +0 -66
  133. package/src/dom/observers/scroll-observer.js +0 -146
  134. package/src/dom/pkce.js +0 -34
  135. package/src/dom/query-params.js +0 -14
  136. package/src/dom/random-string.js +0 -18
  137. package/src/dom/random-string.test.js +0 -13
  138. package/src/dom/sanitize.js +0 -16
  139. package/src/dom/session-store.js +0 -29
  140. package/src/dom/spam-prevention.js +0 -40
  141. package/src/dom/trap-focus.js +0 -70
  142. package/src/dom/ui/aria-current.js +0 -20
  143. package/src/dom/ui/inconsistent-button-fix.js +0 -20
  144. package/src/dom/ui/index.js +0 -4
  145. package/src/dom/ui/scroll-container.js +0 -25
  146. package/src/dom/ui/traverse-and-scramble.js +0 -61
  147. package/src/lib/arrays/index.js +0 -6
  148. package/src/lib/arrays/item-position.js +0 -23
  149. package/src/lib/arrays/join.js +0 -20
  150. package/src/lib/arrays/shuffle.js +0 -21
  151. package/src/lib/arrays/sort.js +0 -88
  152. package/src/lib/arrays/sort.spec.js +0 -123
  153. package/src/lib/arrays/split-array.js +0 -15
  154. package/src/lib/arrays/unique.js +0 -3
  155. package/src/lib/auth/index.js +0 -1
  156. package/src/lib/auth/route-manager.js +0 -45
  157. package/src/lib/checks.js +0 -57
  158. package/src/lib/date/days.js +0 -9
  159. package/src/lib/date/index.js +0 -3
  160. package/src/lib/date/months.js +0 -74
  161. package/src/lib/date/time.js +0 -83
  162. package/src/lib/form/form-data.js +0 -73
  163. package/src/lib/form/index.js +0 -2
  164. package/src/lib/form/sanitize.js +0 -80
  165. package/src/lib/form/sanitize.spec.js +0 -126
  166. package/src/lib/functions/callback.js +0 -8
  167. package/src/lib/functions/debounce.js +0 -18
  168. package/src/lib/functions/env.js +0 -5
  169. package/src/lib/functions/functional.js +0 -113
  170. package/src/lib/functions/functional.test.js +0 -196
  171. package/src/lib/functions/index.js +0 -5
  172. package/src/lib/functions/throttle.js +0 -11
  173. package/src/lib/functions/timeout.js +0 -15
  174. package/src/lib/hash.js +0 -18
  175. package/src/lib/hash.spec.js +0 -163
  176. package/src/lib/index.js +0 -14
  177. package/src/lib/numbers/index.js +0 -12
  178. package/src/lib/numbers/math.js +0 -9
  179. package/src/lib/numbers/split-unit.test.js +0 -45
  180. package/src/lib/objects/camelcase-keys.js +0 -17
  181. package/src/lib/objects/camelcase-keys.test.js +0 -72
  182. package/src/lib/objects/empty.js +0 -10
  183. package/src/lib/objects/equal.js +0 -9
  184. package/src/lib/objects/extend.js +0 -16
  185. package/src/lib/objects/extend.test.js +0 -35
  186. package/src/lib/objects/flatten.js +0 -19
  187. package/src/lib/objects/index.js +0 -13
  188. package/src/lib/objects/json.js +0 -7
  189. package/src/lib/objects/loop.js +0 -11
  190. package/src/lib/objects/loop.test.js +0 -31
  191. package/src/lib/objects/mix/mix.js +0 -191
  192. package/src/lib/objects/mix/mix.md +0 -78
  193. package/src/lib/objects/mix/mix.test.js +0 -445
  194. package/src/lib/objects/nested-property.js +0 -41
  195. package/src/lib/objects/normalize-object.js +0 -10
  196. package/src/lib/objects/omit-empty.js +0 -23
  197. package/src/lib/objects/omit-empty.test.js +0 -85
  198. package/src/lib/objects/size.js +0 -41
  199. package/src/lib/objects/split.js +0 -19
  200. package/src/lib/promises/index.js +0 -1
  201. package/src/lib/promises/reject.js +0 -17
  202. package/src/lib/sse.js +0 -61
  203. package/src/lib/strings/convert-case/convert-case.js +0 -86
  204. package/src/lib/strings/convert-case/convert-case.md +0 -44
  205. package/src/lib/strings/convert-case/convert-case.test.js +0 -50
  206. package/src/lib/strings/index.js +0 -5
  207. package/src/lib/strings/markdown.js +0 -71
  208. package/src/lib/strings/name.js +0 -24
  209. package/src/lib/strings/name.test.js +0 -67
  210. package/src/lib/strings/pluralize.js +0 -2
  211. package/src/lib/strings/query-string.js +0 -18
  212. package/src/lib/style/index.js +0 -13
  213. package/src/lib/symbols/index.js +0 -1
  214. package/src/lib/symbols/symbols.js +0 -9
  215. package/src/node/dirname.js +0 -17
  216. package/src/node/file-cache.js +0 -184
  217. package/src/node/file.js +0 -13
  218. package/src/node/hash.js +0 -5
  219. package/src/node/index.js +0 -7
  220. package/src/node/pkce.js +0 -33
  221. package/src/node/random-string.js +0 -10
  222. package/src/node/random-string.test.js +0 -15
  223. package/src/node/sanitize.js +0 -13
  224. package/src/node/sanitize.spec.js +0 -142
  225. package/src/node/uuid.js +0 -5
  226. package/tsconfig.json +0 -23
  227. package/tsup.config.js +0 -38
  228. package/tsup.config.mjs +0 -45
package/src/dom/events.js DELETED
@@ -1,71 +0,0 @@
1
- /**
2
- * @typedef {Object} EventListener
3
- * @property {Element} node - The DOM element to attach the event listener to
4
- * @property {string} event - The event type (e.g., 'click', 'keydown')
5
- * @property {EventListenerOrEventListenerObject} handler - The event handler function
6
- */
7
-
8
- /**
9
- * @typedef {Object} ListenerManager
10
- * @property {EventListener[]} list - Array of current event listeners
11
- * @property {function(EventListener): void} add - Add a new event listener
12
- * @property {function(EventListener): void} remove - Remove an event listener
13
- * @property {function(): void} clear - Remove all event listeners
14
- */
15
-
16
- /**
17
- * @typedef {Object} CustomEventOptions
18
- * @property {boolean} [bubbles=false] - Whether the event bubbles up through the DOM
19
- * @property {boolean} [cancelable=false] - Whether the event can be canceled
20
- * @property {boolean} [composed=false] - Whether the event will trigger listeners outside of a shadow root
21
- */
22
-
23
- /**
24
- * Adds multiple event listeners to their respective DOM elements
25
- * @param {EventListener[]} listeners - Array of listener objects
26
- */
27
- export function addListeners(listeners) {
28
- listeners.forEach(({ node, event, handler }) => {
29
- node.addEventListener(event, handler)
30
- })
31
- }
32
-
33
- /**
34
- * Removes multiple event listeners from their respective DOM elements
35
- * @param {EventListener[]} listeners - Array of listener objects
36
- */
37
- export function removeListeners(listeners) {
38
- listeners.forEach(({ node, event, handler }) => {
39
- node.removeEventListener(event, handler)
40
- })
41
- }
42
-
43
- /**
44
- * Dispatches a custom event from a DOM node
45
- * @param {Element} node - The DOM element to dispatch the event from
46
- * @param {string} eventName - The name of the custom event
47
- * @param {*} detail - The detail data to include with the event
48
- * @param {CustomEventOptions} [options={}] - Additional event options
49
- */
50
- export function dispatchEvent(node, eventName, detail, options = {}) {
51
- node.dispatchEvent(
52
- new CustomEvent(eventName, {
53
- ...options,
54
- detail,
55
- }),
56
- )
57
- }
58
-
59
- /**
60
- * Creates a new CustomEvent with updated properties from an existing event
61
- * @param {Event} event - The original event object
62
- * @param {Object} updates - Properties to update in the new event
63
- * @return {CustomEvent} A new CustomEvent with updated properties
64
- */
65
- export function updateEvent(event, updates) {
66
- const { type, ...rest } = event
67
- return new CustomEvent(event.type, {
68
- ...rest,
69
- ...updates,
70
- })
71
- }
@@ -1,165 +0,0 @@
1
- /**
2
- * @typedef {Object} Focusables
3
- * @property {number} length - Number of keyboard focusable elements
4
- * @property {Array} all - All focusable elements that are visible and enabled
5
- * @property {Array} keyboard - Elements that can be focused via keyboard (tabIndex > -1)
6
- * @property {Array} keyboardOnly - Alias for keyboard focusable elements
7
- * @property {HTMLElement|null} first - First keyboard focusable element
8
- * @property {HTMLElement|null} last - Last keyboard focusable element
9
- * @property {function(number): HTMLElement|null} next - Get next focusable element after the given index
10
- * @property {function(number): HTMLElement|null} prev - Get previous focusable element before the given index
11
- */
12
-
13
- /**
14
- * Gets all focusable elements within a container and provides methods to navigate between them.
15
- * This is useful for implementing keyboard navigation, focus trapping, and accessibility features.
16
- *
17
- * @param {HTMLElement} [container=document.body] - The container element to search within. Only elements inside this container will be included.
18
- * @returns {Focusables} Object containing focusable elements and navigation methods
19
- * @example
20
- * // Get focusable elements in a modal
21
- * const modal = document.querySelector('.modal')
22
- * const focusable = getFocusableElements(modal)
23
- *
24
- * // Get all focusable elements in document
25
- * const allFocusable = getFocusableElements()
26
- *
27
- * // Focus the first element when modal opens
28
- * focusable.first?.focus()
29
- *
30
- * // Handle tab key to trap focus
31
- * modal.addEventListener('keydown', e => {
32
- * if (e.key === 'Tab') {
33
- * e.preventDefault()
34
- * const currentIndex = focusable.keyboard.indexOf(document.activeElement)
35
- * const nextElement = e.shiftKey
36
- * ? focusable.prev(currentIndex)
37
- * : focusable.next(currentIndex)
38
- * nextElement?.focus()
39
- * }
40
- * })
41
- */
42
- export function getFocusableElements(container = document.body) {
43
- return {
44
- /**
45
- * Gets the number of keyboard focusable elements.
46
- * This is useful for checking if there are any focusable elements
47
- * before attempting to focus them.
48
- *
49
- * @returns {number} The number of keyboard focusable elements
50
- */
51
- get length() {
52
- return this.keyboard.length
53
- },
54
-
55
- /**
56
- * Gets all focusable elements within the container that are visible and enabled.
57
- * This includes elements that can be focused via mouse or programmatically,
58
- * but may not be keyboard focusable.
59
- *
60
- * Elements are considered focusable if they:
61
- * - Are not disabled
62
- * - Are not hidden
63
- * - Are not display:none
64
- *
65
- * @returns {HTMLElement[]} Array of focusable elements that are visible and enabled
66
- */
67
- get all() {
68
- const elements = Array.from(
69
- container.querySelectorAll(
70
- `a,
71
- button,
72
- input,
73
- textarea,
74
- select,
75
- details,
76
- iframe,
77
- embed,
78
- object,
79
- summary,
80
- dialog,
81
- audio[controls],
82
- video[controls],
83
- [contenteditable],
84
- [tabindex]
85
- `,
86
- ),
87
- )
88
-
89
- // @ts-ignore - we check instanceof HTMLElement at runtime
90
- return elements.filter(el => {
91
- if (el.hasAttribute('disabled')) return false
92
- if (el.hasAttribute('hidden')) return false
93
- if (window.getComputedStyle(el).display === 'none') return false
94
- return true
95
- })
96
- },
97
-
98
- /**
99
- * Gets elements that can be focused via keyboard (tabIndex > -1).
100
- * These are the elements that will be focused when using the Tab key.
101
- *
102
- * @returns {HTMLElement[]} Array of keyboard focusable elements
103
- */
104
- get keyboard() {
105
- return this.all.filter(el => el instanceof HTMLElement && el.tabIndex > -1)
106
- },
107
-
108
- /**
109
- * Alias for keyboard focusable elements.
110
- * This is provided for semantic clarity in certain contexts.
111
- *
112
- * @returns {HTMLElement[]} Array of keyboard focusable elements
113
- */
114
- get keyboardOnly() {
115
- return this.keyboard
116
- },
117
-
118
- /**
119
- * Gets the first keyboard focusable element.
120
- * This is useful for setting initial focus when opening a modal or dialog.
121
- *
122
- * @returns {HTMLElement|null} The first focusable element or null if none exist
123
- */
124
- get first() {
125
- return this.keyboard[0] || null
126
- },
127
-
128
- /**
129
- * Gets the last keyboard focusable element.
130
- * This is useful for focus trapping when using Shift+Tab.
131
- *
132
- * @returns {HTMLElement|null} The last focusable element or null if none exist
133
- */
134
- get last() {
135
- return this.keyboard[this.length - 1] || null
136
- },
137
-
138
- /**
139
- * Gets the next focusable element after the given index.
140
- * This is useful for implementing custom tab order or focus management.
141
- *
142
- * @param {number} index - The current element's index in the keyboard focusable array
143
- * @returns {HTMLElement|null} The next focusable element or null if none exists
144
- */
145
- next(index) {
146
- return this.keyboard[index + 1] || null
147
- },
148
-
149
- /**
150
- * Gets the previous focusable element before the given index.
151
- * This is useful for implementing custom tab order or focus management.
152
- *
153
- * @param {number} index - The current element's index in the keyboard focusable array
154
- * @returns {HTMLElement|null} The previous focusable element or null if none exists
155
- */
156
- prev(index) {
157
- return this.keyboard[index - 1] || null
158
- },
159
- }
160
- }
161
-
162
- // Alias of getFocusableElements
163
- export function Focusable(container = document.body) {
164
- return getFocusableElements(container)
165
- }
@@ -1,40 +0,0 @@
1
- import { splitUnit } from '../lib/numbers/index.js'
2
-
3
- export function getUnit(value) {
4
- const [, unit] = splitUnit(value)
5
- return unit
6
- }
7
-
8
- export function rem(multiple = 1) {
9
- const value = parseFloat(getComputedStyle(document.body)['font-size'])
10
- return Math.round(value * multiple)
11
- }
12
-
13
- export function em(element = document.body, multiple = 1) {
14
- const value = parseFloat(getComputedStyle(element)['font-size'])
15
- return Math.round(value * multiple)
16
- }
17
-
18
- export function rlh(multiple = 1) {
19
- const lineHeight = parseFloat(getComputedStyle(document.body)['line-height'])
20
- return Math.round(lineHeight * multiple)
21
- }
22
-
23
- export function lh(element = document.body, multiple = 1) {
24
- const lineHeight = getComputedStyle(element)['line-height']
25
- const value = parseFloat(lineHeight)
26
- return Math.round(value * multiple)
27
- }
28
-
29
- export function toPx(value, element = null) {
30
- const [numeric, unit] = splitUnit(value)
31
- let finalValue = 0
32
-
33
- if (unit === 'rem') finalValue = rem(numeric)
34
- if (unit === 'em') finalValue = em(element, numeric)
35
- if (unit === 'lh') finalValue = lh(element, numeric)
36
- if (unit === 'px') finalValue = numeric
37
- if (!unit) finalValue = numeric // Default to px offsets
38
-
39
- return finalValue
40
- }
@@ -1,176 +0,0 @@
1
- // Returns the target HTMLElement.
2
- // If the selector is already an HTMLElement, it will return the selector itself.
3
- // Otherwise, it will return the first element that matches the selector.
4
-
5
- /**
6
- * List of Astro-specific node names that need special handling
7
- * @type {string[]}
8
- */
9
- const astroNodes = ['ASTRO-SLOT', 'ASTRO-ISLAND']
10
-
11
- /**
12
- * Gets the type of a DOM node
13
- * @param {Node|NodeList|Array} node - The node to check
14
- * @returns {'element'|'nodelist'|'array'|undefined} The type of the node
15
- */
16
- export function getNodeType(node) {
17
- if (node instanceof Element) return 'element'
18
- if (node instanceof NodeList) return 'nodelist'
19
- if (Array.isArray(node)) return 'array'
20
- }
21
-
22
- /**
23
- * Gets an element from a selector or returns the element if it's already an Element
24
- * @param {string|Element} selector - CSS selector or Element
25
- * @returns {Element|undefined} The matching element or undefined if not found
26
- *
27
- * @example
28
- * // Get element by selector
29
- * const button = getElement('.button')
30
- *
31
- * // Pass through Element
32
- * const element = document.querySelector('.button')
33
- * const sameElement = getElement(element) // Returns element directly
34
- */
35
- export function getElement(selector) {
36
- if (!selector) return
37
- if (selector instanceof Element) return selector
38
- return document.querySelector(selector)
39
- }
40
-
41
- /**
42
- * Gets all child elements of a node, handling Astro slots
43
- * @param {Element} node - The parent node
44
- * @returns {Element[]} Array of child elements
45
- *
46
- * @example
47
- * // Get children of a div
48
- * const children = getChildrenElements(div)
49
- *
50
- * // Works with Astro slots
51
- * const slotChildren = getChildrenElements(astroSlot)
52
- */
53
- export function getChildrenElements(node) {
54
- let children = node.children
55
-
56
- // Compensate for Astro Slots
57
- if (children[0]?.nodeName === 'ASTRO-SLOT') children = children[0].children
58
- return Array.from(children)
59
- }
60
-
61
- /**
62
- * Gets the parent element, skipping Astro-specific nodes
63
- * @param {Element} element - The element to get the parent of
64
- * @returns {Element|null} The parent element, or null if no parent exists
65
- *
66
- * @example
67
- * // Get parent, skipping Astro slots
68
- * const parent = getParentElement(element)
69
- */
70
- export function getParentElement(element) {
71
- const parent = element.parentElement
72
- if (astroNodes.includes(parent.nodeName)) return getParentElement(parent)
73
- return parent
74
- }
75
-
76
- /**
77
- * Gets all sibling elements of an element (excluding the element itself)
78
- * @param {Element} element - The element to get siblings of
79
- * @returns {Element[]} Array of sibling elements
80
- *
81
- * @example
82
- * // Get all siblings of an element
83
- * const siblings = getSiblingElements(element)
84
- */
85
- export function getSiblingElements(element) {
86
- return Array.from(element.parentElement.children).filter(
87
- child => child !== element
88
- )
89
- }
90
-
91
- /**
92
- * Gets the index of an element among its siblings
93
- * @param {Element} element - The element to get the index of
94
- * @returns {number} The index of the element (0-based)
95
- *
96
- * @example
97
- * // Get position of element among siblings
98
- * const index = getSelfIndex(element)
99
- */
100
- export function getSelfIndex(element) {
101
- return Array.from(element.parentElement.children).indexOf(element)
102
- }
103
-
104
- /**
105
- * Checks if an element is an ancestor of another element
106
- * @param {Element} ancestor - The potential ancestor element
107
- * @param {Element} element - The element to check
108
- * @param {Object} [options] - Options for the search
109
- * @param {number} [options.searchLevels=0] - Number of levels to search up, 0 for unlimited
110
- * @returns {boolean} True if ancestor is an ancestor of element
111
- *
112
- * @example
113
- * // Check if div is an ancestor of button
114
- * const isParent = isAncestor(div, button)
115
- *
116
- * // Check if div is an ancestor within 2 levels
117
- * const isCloseAncestor = isAncestor(div, button, { searchLevels: 2 })
118
- */
119
- export function isAncestor(ancestor, element, { searchLevels = 0 } = {}) {
120
- if (ancestor === element) return true
121
-
122
- let parent = element.parentElement
123
- // Infinite Search
124
- if (searchLevels === 0) {
125
- while (parent) {
126
- if (ancestor === parent) return true
127
- parent = parent.parentElement
128
- }
129
- } else {
130
- // Search X levels upwards
131
- for (let i = 0; i < searchLevels; i++) {
132
- if (ancestor === parent) return true
133
- parent = parent.parentElement
134
- }
135
- }
136
-
137
- return false
138
- }
139
-
140
- /**
141
- * Gets ancestor elements with their siblings, optionally limiting the search depth.
142
- * Useful for finding the nearest ancestor that has siblings.
143
- *
144
- * @param {Element} element - The element to start searching from
145
- * @param {Object} [options] - Options for the search
146
- * @param {number|boolean} [options.limit=false] - Number of levels to search up, or false for unlimited
147
- * @returns {Element[]|null} Array of sibling elements, or null if none found
148
- *
149
- * @example
150
- * // Get siblings of nearest ancestor that has siblings
151
- * const ancestorSiblings = getAncestorWithSiblings(element)
152
- *
153
- * // Search up to 2 levels
154
- * const limitedSiblings = getAncestorWithSiblings(element, { limit: 2 })
155
- */
156
- export function getAncestorWithSiblings(element, { limit = false } = {}) {
157
- const ancestor = element.parentElement
158
- const siblings = getSiblingElements(ancestor)
159
-
160
- // Found
161
- if (siblings.length) return siblings
162
-
163
- // No more ancestors
164
- if (!ancestor) return null
165
-
166
- // Unlimited upwards search
167
- if (limit === false) return getAncestorWithSiblings(ancestor)
168
-
169
- // Limited search
170
- if (typeof limit === 'number' && limit > 0) {
171
- return getAncestorWithSiblings(ancestor, { limit: limit - 1 })
172
- }
173
-
174
- // Limit reached, end search
175
- if (limit === 0) return null
176
- }
package/src/dom/hash.js DELETED
@@ -1,9 +0,0 @@
1
- export async function sha256Hash(string) {
2
- const utf8 = new TextEncoder().encode(string)
3
- const hashBuffer = await crypto.subtle.digest('SHA-256', utf8)
4
- const hashArray = Array.from(new Uint8Array(hashBuffer))
5
- const hashHex = hashArray
6
- .map(bytes => bytes.toString(16).padStart(2, '0'))
7
- .join('')
8
- return hashHex
9
- }
package/src/dom/index.js DELETED
@@ -1,23 +0,0 @@
1
- export * from './accessibility.js'
2
- export * from './actions/index.js'
3
- export * from './bounding-box.js'
4
- export * from './clipboard.js'
5
- export * from './cookie.js'
6
- export * from './css-vars.js'
7
- export * from './events.js'
8
- export * from './focusable.js'
9
- export * from './font-size.js'
10
- export * from './get-element.js'
11
- export * from './hash.js'
12
- export * from './keyboard.js'
13
- export * from './local-store.js'
14
- export * from './media.js'
15
- export * from './observers/index.js'
16
- export * from './pkce.js'
17
- export * from './query-params.js'
18
- export * from './random-string.js'
19
- export * from './sanitize.js'
20
- export * from './session-store.js'
21
- export * from './spam-prevention.js'
22
- export * from './trap-focus.js'
23
- export * from './ui/index.js'
@@ -1,44 +0,0 @@
1
- /**
2
- * Event is Tab (without shift)
3
- * @param {KeyboardEvent} event - The keyboard event object
4
- * @returns {boolean}
5
- */
6
- export function isTab(event) {
7
- return !event.shiftKey && event.key === 'Tab'
8
- }
9
-
10
- /**
11
- * Event is shift + Tab
12
- * @param {KeyboardEvent} event - The keyboard event object
13
- * @returns {boolean}
14
- */
15
- export function isShiftTab(event) {
16
- return event.shiftKey && event.key === 'Tab'
17
- }
18
-
19
- /**
20
- * Matches both Tab and Shift+Tab
21
- * @param {string} key - The keyboard key to check
22
- * @returns {boolean} Whether the key is Tab
23
- */
24
- export function isTabKey(key) {
25
- return key === 'Tab'
26
- }
27
-
28
- /**
29
- * Event is an arrow key
30
- * @param {string} key - The keyboard key to check
31
- * @returns {boolean} Whether the key is an arrow key (Up, Down, Left, Right)
32
- */
33
- export function isArrowKey(key) {
34
- return ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)
35
- }
36
-
37
- /**
38
- * Event is Escape key
39
- * @param {string} key - The keyboard key to check
40
- * @returns {boolean} Whether the key is Escape
41
- */
42
- export function isEscapeKey(key) {
43
- return key === 'Escape'
44
- }
@@ -1,66 +0,0 @@
1
- // ========================
2
- // Local Storage
3
- // ========================
4
-
5
- /**
6
- * Utility object for managing localStorage operations with JSON support
7
- * @namespace localStore
8
- */
9
- export const localStore = {
10
- /**
11
- * Retrieves a value from localStorage
12
- * @param {string} key - The key to retrieve from localStorage
13
- * @returns {any} The stored value. Returns parsed JSON if the value was stored as JSON. Returns the original string if not JSON, or undefined if key doesn't exist
14
- */
15
- get(key) {
16
- const value = localStorage.getItem(key)
17
- if (!value) return
18
-
19
- try {
20
- // Returns an object if stored value is JSON
21
- return JSON.parse(value)
22
- } catch (error) {
23
- // Returns plain string if stored value is not JSON
24
- return value
25
- }
26
- },
27
-
28
- /**
29
- * Stores a value in localStorage
30
- * @param {string} key - The key to store the value under
31
- * @param {any} value - The value to store. Objects will be stringified to JSON
32
- */
33
- set(key, value) {
34
- if (typeof value === 'string') {
35
- localStorage.setItem(key, value)
36
- } else {
37
- localStorage.setItem(key, JSON.stringify(value))
38
- }
39
- },
40
-
41
- /**
42
- * Stores multiple key-value pairs in localStorage
43
- * @param {Object|Map} data - An object or Map containing key-value pairs to store
44
- */
45
- setMultiple(data) {
46
- for (const [key, value] of Object.entries(data)) {
47
- this.set(key, value)
48
- }
49
- },
50
-
51
- /**
52
- * Removes a value from localStorage
53
- * @param {string} key - The key to remove from localStorage
54
- */
55
- remove(key) {
56
- localStorage.removeItem(key)
57
- },
58
-
59
- /**
60
- * Removes multiple keys from localStorage
61
- * @param {string[]} keys - Array of keys to remove from localStorage
62
- */
63
- removeMultiple(keys) {
64
- keys.forEach(key => this.remove(key))
65
- },
66
- }
package/src/dom/media.js DELETED
@@ -1,30 +0,0 @@
1
- export async function imagesLoaded(node) {
2
- const images = Array.from(node.querySelectorAll('img'))
3
- const promises = images.map(img => {
4
- return new Promise((resolve, reject) => {
5
- if (img.complete) return resolve()
6
- img.onload = resolve
7
- img.onerror = e => {
8
- // eslint-disable-next-line prefer-promise-reject-errors
9
- reject('Image failed to load')
10
- }
11
- })
12
- })
13
- return Promise.all(promises)
14
- }
15
-
16
- export async function videosLoaded(node) {
17
- const videos = Array.from(node.querySelectorAll('video'))
18
- const promises = videos.map(video => {
19
- return new Promise((resolve, reject) => {
20
- if (video.readyState === 4) return resolve() // HAVE_ENOUGH_DATA
21
- video.onloadedmetadata = resolve
22
- video.onerror = reject
23
- })
24
- })
25
- return Promise.all(promises)
26
- }
27
-
28
- export async function mediaLoaded(node) {
29
- return Promise.all([imagesLoaded(node), videosLoaded(node)])
30
- }
@@ -1,4 +0,0 @@
1
- export * from './intersection-observer.js'
2
- export * from './mutation-observer.js'
3
- export * from './resize-observer.js'
4
- export * from './scroll-observer.js'
@@ -1,43 +0,0 @@
1
- import { dispatchEvent } from '../events.js'
2
- import { useObserverMethodOnTarget } from './observer.js'
3
-
4
- // See https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options for options
5
- export function intersectionObserver(target, options = {}) {
6
- const { callback, ...opts } = options
7
- const observer = new IntersectionObserver(observerFn, opts)
8
-
9
- useObserverMethodOnTarget(target, observer, 'observe')
10
-
11
- function observerFn(entries) {
12
- for (const entry of entries) {
13
- if (callback) callback({ entry, entries, observer })
14
- else dispatchEvent(target, 'intersect', { entry, entries, observer })
15
- }
16
- }
17
-
18
- return {
19
- observer,
20
- observe(target) {
21
- useObserverMethodOnTarget(target, observer, 'observe', options)
22
- },
23
-
24
- unobserve(target) {
25
- useObserverMethodOnTarget(target, observer, 'unobserve')
26
- },
27
-
28
- takeRecords() {
29
- return observer.takeRecords()
30
- },
31
-
32
- disconnect() {
33
- // Take records before disconnecting.
34
- const records = observer.takeRecords()
35
- observer.disconnect()
36
- if (records.length > 0) observerFn(records)
37
- },
38
-
39
- destroy() {
40
- observer.disconnect()
41
- },
42
- }
43
- }