@ulu/frontend 0.1.0-beta.5 → 0.1.0-beta.50

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 (296) hide show
  1. package/CHANGELOG.md +382 -0
  2. package/dist/ulu-frontend.min.css +1 -1
  3. package/dist/ulu-frontend.min.js +28 -27
  4. package/docs-dev/assets/main.js +832 -421
  5. package/docs-dev/assets/placeholder/icon-calendar.svg +1 -0
  6. package/docs-dev/assets/placeholder/icon-check.svg +1 -0
  7. package/docs-dev/assets/style.css +629 -233
  8. package/docs-dev/changelog/index.html +0 -0
  9. package/docs-dev/changelog/updates-and-changes/index.html +5109 -0
  10. package/docs-dev/demos/accordion/index.html +0 -4809
  11. package/docs-dev/demos/basic-hero/index.html +0 -0
  12. package/docs-dev/demos/breakpoints-manager/index.html +0 -0
  13. package/docs-dev/demos/button/index.html +0 -4621
  14. package/docs-dev/demos/button-verbose/index.html +0 -0
  15. package/docs-dev/demos/callout/index.html +0 -4661
  16. package/docs-dev/demos/captioned-figure/index.html +0 -4683
  17. package/docs-dev/demos/card/index.html +0 -5040
  18. package/docs-dev/demos/card-grid/index.html +0 -0
  19. package/docs-dev/demos/card-new/index.html +5088 -0
  20. package/docs-dev/demos/card-old/index.html +5223 -0
  21. package/docs-dev/demos/card.1/index.html +5223 -0
  22. package/docs-dev/demos/card.TRASH/index.html +5541 -0
  23. package/docs-dev/demos/counter-list/index.html +0 -0
  24. package/docs-dev/demos/css-icons/index.html +0 -5272
  25. package/docs-dev/demos/data-grid/index.html +0 -5606
  26. package/docs-dev/demos/data-table/index.html +0 -4697
  27. package/docs-dev/demos/details-group/index.html +0 -0
  28. package/docs-dev/demos/file-save/index.html +0 -4672
  29. package/docs-dev/demos/flipcard/index.html +0 -5221
  30. package/docs-dev/demos/form-theme/index.html +0 -4852
  31. package/docs-dev/demos/hero/index.html +0 -301
  32. package/docs-dev/demos/image-grid/index.html +0 -157
  33. package/docs-dev/demos/index.html +0 -4610
  34. package/docs-dev/demos/list-inline/index.html +0 -0
  35. package/docs-dev/demos/list-inline.1/index.html +4727 -0
  36. package/docs-dev/demos/list-lines/index.html +0 -0
  37. package/docs-dev/demos/menu-stack/index.html +0 -4751
  38. package/docs-dev/demos/modals/index.html +0 -4718
  39. package/docs-dev/demos/nav-strip/index.html +0 -4722
  40. package/docs-dev/demos/overlay-section/index.html +0 -4628
  41. package/docs-dev/demos/popovers/index.html +0 -4628
  42. package/docs-dev/demos/print/index.html +0 -4630
  43. package/docs-dev/demos/pull-quote/index.html +0 -4629
  44. package/docs-dev/demos/rule/index.html +0 -4679
  45. package/docs-dev/demos/scroll-slider/index.html +0 -204
  46. package/docs-dev/demos/scrollpoints/index.html +0 -4648
  47. package/docs-dev/demos/slider/index.html +0 -164
  48. package/docs-dev/demos/spoke-spinner/index.html +0 -4625
  49. package/docs-dev/demos/sticky-list/index.html +0 -0
  50. package/docs-dev/demos/tabs/index.html +0 -4714
  51. package/docs-dev/demos/tag/index.html +0 -4630
  52. package/docs-dev/demos/theme-toggle/index.html +0 -0
  53. package/docs-dev/demos/tile-grid-overlay/index.html +0 -382
  54. package/docs-dev/demos/tiles/index.html +0 -4879
  55. package/docs-dev/demos/tooltip/index.html +0 -4658
  56. package/docs-dev/guide/building-stylesheet/index.html +0 -4679
  57. package/docs-dev/guide/developing-ulu-scss-module/index.html +0 -4731
  58. package/docs-dev/guide/index.html +0 -4612
  59. package/docs-dev/guide/updates-and-changes/index.html +5033 -0
  60. package/docs-dev/index.html +0 -4659
  61. package/docs-dev/javascript/events/index.html +0 -4770
  62. package/docs-dev/javascript/index.html +0 -4625
  63. package/docs-dev/javascript/settings/index.html +0 -0
  64. package/docs-dev/javascript/ui-breakpoints/index.html +0 -5070
  65. package/docs-dev/javascript/ui-collapsible/index.html +0 -4737
  66. package/docs-dev/javascript/ui-details-group/index.html +0 -0
  67. package/docs-dev/javascript/ui-dialog/index.html +0 -4771
  68. package/docs-dev/javascript/ui-flipcard/index.html +0 -4621
  69. package/docs-dev/javascript/ui-grid/index.html +0 -4678
  70. package/docs-dev/javascript/ui-modal-builder/index.html +0 -4760
  71. package/docs-dev/javascript/ui-overflow-scroller/index.html +0 -4610
  72. package/docs-dev/javascript/ui-overflow-scroller-pager/index.html +0 -4628
  73. package/docs-dev/javascript/ui-page/index.html +0 -4625
  74. package/docs-dev/javascript/ui-popover/index.html +0 -4664
  75. package/docs-dev/javascript/ui-print/index.html +0 -4677
  76. package/docs-dev/javascript/ui-print-details/index.html +0 -4640
  77. package/docs-dev/javascript/ui-programmatic-modal/index.html +0 -4610
  78. package/docs-dev/javascript/ui-proxy-click/index.html +990 -324
  79. package/docs-dev/javascript/ui-resizer/index.html +901 -320
  80. package/docs-dev/javascript/ui-scroll-slider/index.html +0 -4639
  81. package/docs-dev/javascript/ui-scrollpoint/index.html +0 -4857
  82. package/docs-dev/javascript/ui-slider/index.html +1099 -327
  83. package/docs-dev/javascript/ui-tabs/index.html +914 -370
  84. package/docs-dev/javascript/ui-theme-toggle/index.html +5410 -0
  85. package/docs-dev/javascript/ui-tooltip/index.html +940 -363
  86. package/docs-dev/javascript/utils-class-logger/index.html +901 -320
  87. package/docs-dev/javascript/utils-css/index.html +5224 -0
  88. package/docs-dev/javascript/utils-dom/index.html +1054 -339
  89. package/docs-dev/javascript/utils-file-save/index.html +901 -320
  90. package/docs-dev/javascript/utils-floating-ui/index.html +901 -320
  91. package/docs-dev/javascript/utils-id/index.html +901 -320
  92. package/docs-dev/javascript/utils-pause-youtube-video/index.html +901 -320
  93. package/docs-dev/javascript/utils-system/index.html +5527 -0
  94. package/docs-dev/sass/base/color/index.html +0 -4643
  95. package/docs-dev/sass/base/elements/index.html +0 -4814
  96. package/docs-dev/sass/base/index/index.html +0 -4813
  97. package/docs-dev/sass/base/index.html +0 -4619
  98. package/docs-dev/sass/base/keyframes/index.html +0 -4645
  99. package/docs-dev/sass/base/layout/index.html +0 -4805
  100. package/docs-dev/sass/base/normalize/index.html +0 -4653
  101. package/docs-dev/sass/base/print/index.html +0 -4649
  102. package/docs-dev/sass/base/root/index.html +0 -4669
  103. package/docs-dev/sass/base/typography/index.html +0 -4669
  104. package/docs-dev/sass/components/accordion/index.html +0 -4971
  105. package/docs-dev/sass/components/adaptive-spacing/index.html +0 -4914
  106. package/docs-dev/sass/components/badge/index.html +0 -4862
  107. package/docs-dev/sass/components/basic-hero/index.html +0 -0
  108. package/docs-dev/sass/components/button/index.html +0 -4798
  109. package/docs-dev/sass/components/button-verbose/index.html +0 -4910
  110. package/docs-dev/sass/components/callout/index.html +0 -4937
  111. package/docs-dev/sass/components/captioned-figure/index.html +0 -4788
  112. package/docs-dev/sass/components/card/index.html +0 -5146
  113. package/docs-dev/sass/components/card-grid/index.html +0 -4812
  114. package/docs-dev/sass/components/counter-list/index.html +0 -0
  115. package/docs-dev/sass/components/css-icon/index.html +0 -4909
  116. package/docs-dev/sass/components/data-grid/index.html +0 -5044
  117. package/docs-dev/sass/components/data-table/index.html +0 -4795
  118. package/docs-dev/sass/components/fill-context/index.html +0 -4678
  119. package/docs-dev/sass/components/flipcard/index.html +0 -4948
  120. package/docs-dev/sass/components/flipcard-grid/index.html +0 -4799
  121. package/docs-dev/sass/components/form-theme/index.html +0 -5428
  122. package/docs-dev/sass/components/hero/index.html +0 -4800
  123. package/docs-dev/sass/components/horizontal-rule/index.html +0 -4797
  124. package/docs-dev/sass/components/image-grid/index.html +0 -4804
  125. package/docs-dev/sass/components/index/index.html +0 -4848
  126. package/docs-dev/sass/components/index.html +0 -4619
  127. package/docs-dev/sass/components/links/index.html +0 -4648
  128. package/docs-dev/sass/components/list-inline/index.html +0 -0
  129. package/docs-dev/sass/components/list-lines/index.html +0 -4843
  130. package/docs-dev/sass/components/list-ordered/index.html +0 -4644
  131. package/docs-dev/sass/components/list-unordered/index.html +0 -4648
  132. package/docs-dev/sass/components/menu-stack/index.html +0 -4978
  133. package/docs-dev/sass/components/modal/index.html +0 -5025
  134. package/docs-dev/sass/components/nav-strip/index.html +0 -4898
  135. package/docs-dev/sass/components/overlay-section/index.html +0 -4842
  136. package/docs-dev/sass/components/pager/index.html +0 -4960
  137. package/docs-dev/sass/components/placeholder-block/index.html +0 -4882
  138. package/docs-dev/sass/components/popover/index.html +0 -4957
  139. package/docs-dev/sass/components/pull-quote/index.html +0 -4856
  140. package/docs-dev/sass/components/ratio-box/index.html +0 -4802
  141. package/docs-dev/sass/components/rule/index.html +0 -4804
  142. package/docs-dev/sass/components/scroll-slider/index.html +0 -4915
  143. package/docs-dev/sass/components/skip-link/index.html +0 -4788
  144. package/docs-dev/sass/components/slider/index.html +0 -4924
  145. package/docs-dev/sass/components/spoke-spinner/index.html +0 -4862
  146. package/docs-dev/sass/components/sticky-list/index.html +0 -0
  147. package/docs-dev/sass/components/tabs/index.html +0 -4938
  148. package/docs-dev/sass/components/tag/index.html +0 -4963
  149. package/docs-dev/sass/components/tile-button/index.html +0 -4843
  150. package/docs-dev/sass/components/tile-grid/index.html +0 -4978
  151. package/docs-dev/sass/components/tile-grid-overlay/index.html +0 -4779
  152. package/docs-dev/sass/components/vignette/index.html +0 -4792
  153. package/docs-dev/sass/components/wysiwyg/index.html +0 -4808
  154. package/docs-dev/sass/core/breakpoint/index.html +0 -5401
  155. package/docs-dev/sass/core/button/index.html +0 -5535
  156. package/docs-dev/sass/core/color/index.html +0 -5385
  157. package/docs-dev/sass/core/cssvar/index.html +0 -5410
  158. package/docs-dev/sass/core/element/index.html +0 -5533
  159. package/docs-dev/sass/core/index.html +0 -4608
  160. package/docs-dev/sass/core/layout/index.html +0 -5368
  161. package/docs-dev/sass/core/path/index.html +0 -4777
  162. package/docs-dev/sass/core/selector/index.html +0 -4856
  163. package/docs-dev/sass/core/typography/index.html +0 -5782
  164. package/docs-dev/sass/core/units/index.html +0 -4815
  165. package/docs-dev/sass/core/utils/index.html +0 -6256
  166. package/docs-dev/sass/helpers/color/index.html +0 -4643
  167. package/docs-dev/sass/helpers/display/index.html +0 -4648
  168. package/docs-dev/sass/helpers/index/index.html +0 -4810
  169. package/docs-dev/sass/helpers/index.html +0 -4619
  170. package/docs-dev/sass/helpers/print/index.html +843 -292
  171. package/docs-dev/sass/helpers/typography/index.html +0 -4671
  172. package/docs-dev/sass/helpers/units/index.html +0 -4817
  173. package/docs-dev/sass/helpers/utilities/index.html +0 -4648
  174. package/docs-dev/sass/index.html +0 -4670
  175. package/js/index.js +1 -0
  176. package/js/settings.js +95 -0
  177. package/js/ui/breakpoints.js +19 -16
  178. package/js/ui/collapsible.js +8 -1
  179. package/js/ui/details-group.js +112 -0
  180. package/js/ui/dialog.js +90 -42
  181. package/js/ui/dialog.todo +2 -36
  182. package/js/ui/flipcard.js +37 -57
  183. package/js/ui/grid.js +15 -13
  184. package/js/ui/index.js +1 -0
  185. package/js/ui/modal-builder.js +45 -54
  186. package/js/ui/overflow-scroller.js +6 -4
  187. package/js/ui/popover.js +38 -38
  188. package/js/ui/print.js +16 -25
  189. package/js/ui/programmatic-modal.js +9 -3
  190. package/js/ui/proxy-click.js +50 -36
  191. package/js/ui/scroll-slider.js +24 -30
  192. package/js/ui/scrollpoint.js +28 -64
  193. package/js/ui/slider.js +61 -62
  194. package/js/ui/tabs.js +23 -36
  195. package/js/ui/theme-toggle.js +331 -94
  196. package/js/ui/tooltip.js +27 -32
  197. package/js/utils/css.js +13 -0
  198. package/js/utils/dom.js +85 -8
  199. package/js/utils/font-awesome.js +18 -0
  200. package/js/utils/index.js +2 -1
  201. package/js/utils/system.js +154 -0
  202. package/package.json +14 -8
  203. package/scss/_breakpoint.scss +16 -3
  204. package/scss/_color.scss +37 -5
  205. package/scss/_element.scss +94 -2
  206. package/scss/_layout.scss +7 -8
  207. package/scss/_units.scss +3 -2
  208. package/scss/_utils.scss +248 -13
  209. package/scss/components/README.todos +14 -0
  210. package/scss/components/_accordion.scss +18 -20
  211. package/scss/components/_badge.scss +3 -2
  212. package/scss/components/_basic-hero.scss +112 -0
  213. package/scss/components/_button-verbose.scss +102 -20
  214. package/scss/components/_callout.scss +127 -79
  215. package/scss/components/_captioned-figure.scss +23 -5
  216. package/scss/components/_card-grid.scss +1 -1
  217. package/scss/components/_card.scss +261 -88
  218. package/scss/components/_counter-list.scss +133 -0
  219. package/scss/components/_css-icon.scss +33 -28
  220. package/scss/components/_data-grid.scss +38 -9
  221. package/scss/components/_data-table.scss +44 -4
  222. package/scss/components/_flipcard.scss +21 -15
  223. package/scss/components/_form-theme.scss +146 -135
  224. package/scss/components/_hero.scss +12 -10
  225. package/scss/components/_index.scss +24 -0
  226. package/scss/components/_list-inline.scss +80 -0
  227. package/scss/components/_list-lines.scss +44 -33
  228. package/scss/components/_list-ordered.scss +0 -1
  229. package/scss/components/_menu-stack.scss +42 -26
  230. package/scss/components/_modal.scss +29 -19
  231. package/scss/components/_nav-strip.scss +5 -1
  232. package/scss/components/_overlay-section.scss +4 -6
  233. package/scss/components/_pager.scss +6 -6
  234. package/scss/components/_placeholder-block.scss +4 -4
  235. package/scss/components/_popover.scss +174 -73
  236. package/scss/components/_pull-quote.scss +13 -13
  237. package/scss/components/_ratio-box.scss +2 -5
  238. package/scss/components/_rule.scss +1 -1
  239. package/scss/components/_scroll-slider.scss +2 -6
  240. package/scss/components/_skip-link.scss +2 -1
  241. package/scss/components/_slider.scss +18 -38
  242. package/scss/components/_spoke-spinner.scss +2 -2
  243. package/scss/components/_sticky-list.scss +206 -0
  244. package/scss/components/_tabs.scss +4 -2
  245. package/scss/components/_tag.scss +1 -1
  246. package/scss/components/_vignette.scss +3 -5
  247. package/scss/helpers/_display.scss +15 -18
  248. package/scss/helpers/_print.scss +12 -7
  249. package/scss/helpers/_utilities.scss +42 -32
  250. package/types/index.d.ts +1 -0
  251. package/types/settings.d.ts +66 -0
  252. package/types/settings.d.ts.map +1 -0
  253. package/types/ui/breakpoints.d.ts +14 -14
  254. package/types/ui/breakpoints.d.ts.map +1 -1
  255. package/types/ui/collapsible.d.ts.map +1 -1
  256. package/types/ui/details-group.d.ts +38 -0
  257. package/types/ui/details-group.d.ts.map +1 -0
  258. package/types/ui/dialog.d.ts +20 -14
  259. package/types/ui/dialog.d.ts.map +1 -1
  260. package/types/ui/flipcard.d.ts +16 -10
  261. package/types/ui/flipcard.d.ts.map +1 -1
  262. package/types/ui/grid.d.ts +4 -6
  263. package/types/ui/grid.d.ts.map +1 -1
  264. package/types/ui/index.d.ts +1 -0
  265. package/types/ui/modal-builder.d.ts +8 -11
  266. package/types/ui/modal-builder.d.ts.map +1 -1
  267. package/types/ui/overflow-scroller.d.ts +2 -2
  268. package/types/ui/overflow-scroller.d.ts.map +1 -1
  269. package/types/ui/popover.d.ts +6 -7
  270. package/types/ui/popover.d.ts.map +1 -1
  271. package/types/ui/print.d.ts +0 -4
  272. package/types/ui/print.d.ts.map +1 -1
  273. package/types/ui/programmatic-modal.d.ts.map +1 -1
  274. package/types/ui/proxy-click.d.ts +19 -3
  275. package/types/ui/proxy-click.d.ts.map +1 -1
  276. package/types/ui/scroll-slider.d.ts +5 -7
  277. package/types/ui/scroll-slider.d.ts.map +1 -1
  278. package/types/ui/scrollpoint.d.ts +3 -8
  279. package/types/ui/scrollpoint.d.ts.map +1 -1
  280. package/types/ui/slider.d.ts +24 -14
  281. package/types/ui/slider.d.ts.map +1 -1
  282. package/types/ui/tabs.d.ts +6 -8
  283. package/types/ui/tabs.d.ts.map +1 -1
  284. package/types/ui/theme-toggle.d.ts +51 -7
  285. package/types/ui/theme-toggle.d.ts.map +1 -1
  286. package/types/ui/tooltip.d.ts +3 -5
  287. package/types/ui/tooltip.d.ts.map +1 -1
  288. package/types/utils/css.d.ts +11 -0
  289. package/types/utils/css.d.ts.map +1 -0
  290. package/types/utils/dom.d.ts +45 -6
  291. package/types/utils/dom.d.ts.map +1 -1
  292. package/types/utils/font-awesome.d.ts +5 -0
  293. package/types/utils/font-awesome.d.ts.map +1 -0
  294. package/types/utils/index.d.ts +1 -0
  295. package/types/utils/system.d.ts +113 -0
  296. package/types/utils/system.d.ts.map +1 -0
package/js/utils/dom.js CHANGED
@@ -5,6 +5,18 @@
5
5
 
6
6
  export const regexJsonString = /^[{\[][\s\S]*[}\]]$/;
7
7
 
8
+ /**
9
+ * Converts a data attribute name to its corresponding dataset property name.
10
+ * @param {string} dataAttribute - The data attribute name (e.g., "data-ulu-dialog").
11
+ * @returns {string} - The dataset property name (e.g., "uluDialog").
12
+ */
13
+ export function dataAttributeToDatasetKey(attribute) {
14
+ // Remove "data-" prefix then convert kebab-case to camelCase
15
+ return attribute
16
+ .replace(/^data-/, "")
17
+ .replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
18
+ }
19
+
8
20
  /**
9
21
  * Get an elements JSON dataset value
10
22
  * @param {Node} element
@@ -98,6 +110,7 @@ export function setPositionClasses(parent, classes = {
98
110
  * Resolve a target to Element
99
111
  * @param {String|Node} target The selector or node/element
100
112
  * @param {Object} context [document] The context to query possible selectors from
113
+ * @return {HTMLElement} The element or null if not found
101
114
  */
102
115
  export function getElement(target, context = document) {
103
116
  if (typeof target === "string") {
@@ -105,18 +118,82 @@ export function getElement(target, context = document) {
105
118
  } else if (target instanceof Element) {
106
119
  return target;
107
120
  } else {
108
- console.warn("Unable to getElement()", target);
121
+ console.warn("getElement: Invalid target type (expected String/Node)", target);
109
122
  return null;
110
123
  }
111
124
  }
112
125
 
113
126
  /**
114
- * Sets a CSS custom property equal to the scrollbar width
115
- * @param {Node} element The element that is the child of a scrollabel container
116
- * @param {Node} container The container that can be scrolled
117
- * @param {Stirng} propName Custom property to set
127
+ * Resolve a target to Elements
128
+ * @param {String|Node} target The selector or node/element
129
+ * @param {Object} context [document] The context to query possible selectors from
130
+ * @return {Array} The elements or null if not found
131
+ */
132
+ export function getElements(target, context = document) {
133
+ if (typeof target === "string") {
134
+ return [...context.querySelectorAll(target)];
135
+ } else if (target instanceof Element) {
136
+ return [target];
137
+ } else if (Array.isArray(target) || target instanceof NodeList) {
138
+ return [...target];
139
+ } else {
140
+ console.warn("getElement: Invalid target type (expected String/Node/Array/Node List)", target);
141
+ return null;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Resolves a class input (string or array) into a consistent array of class names.
147
+ * @param {string|string[]} input - The class input, which can be a string, an array of strings, or any other value.
148
+ * @returns {string[]} An array of class names. Returns an empty array for invalid or falsy input.
149
+ * @example
150
+ * resolveClassArray("fas fa-check my-class"); // Returns ["fas", "fa-check", "my-class"]
151
+ * resolveClassArray(["another-class", "yet-another-class"]); // Returns ["another-class", "yet-another-class"]
152
+ * resolveClassArray("single-class"); // Returns ["single-class"]
153
+ */
154
+ export function resolveClasses(classes) {
155
+ if (typeof classes === "string") {
156
+ return classes.split(" ").filter(c => c !== ""); // Split and remove empty strings
157
+ } else if (Array.isArray(classes)) {
158
+ return classes;
159
+ } else if (!classes) {
160
+ return [];
161
+ } else {
162
+ console.warn("resolveClassArray: Invalid class input type.", classes);
163
+ return [];
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Sets a CSS custom property equal to the scrollbar width.
169
+ * @param {object} options - Configuration options.
170
+ * @param {HTMLElement} [options.scrollableChild=document.body] - An element that is a child of a scrollable container (used for width calculation).
171
+ * @param {Window|HTMLElement} [options.container=window] - The container that can be scrolled (used for width calculation).
172
+ * @param {HTMLElement} [options.propertyElement=document.documentElement] - The element to which the custom property will be added. Defaults to document.documentElement for :root access.
173
+ * @param {string} [options.propName="--ulu-scrollbar-width"] - The name of the custom property to set.
174
+ */
175
+ export function addScrollbarProperty(options) {
176
+ const defaults = {
177
+ scrollableChild: document.body,
178
+ container: window,
179
+ propertyElement: document.documentElement,
180
+ propName: "--ulu-scrollbar-width",
181
+ };
182
+
183
+ const config = { ...defaults, ...options };
184
+ const { scrollableChild, container, propertyElement, propName } = config;
185
+
186
+ const scrollbarWidth = getScrollbarWidth(scrollableChild, container);
187
+ propertyElement.style.setProperty(propName, `${ scrollbarWidth }px`);
188
+ }
189
+
190
+ /**
191
+ * Calculates the width of the scrollbar.
192
+ *
193
+ * @param {HTMLElement} [element=document.body] -The element that is the child of a scrollable container
194
+ * @param {Window|HTMLElement} [container=window] - The container that can be scrolled
195
+ * @returns {number} The width of the scrollbar in pixels.
118
196
  */
119
- export function addScrollbarProperty(element = document.body, container = window, propName = "--ulu-scrollbar-width") {
120
- const scrollbarWidth = container.innerWidth - element.clientWidth;
121
- element.style.setProperty(propName, `${ scrollbarWidth }px`);
197
+ export function getScrollbarWidth(element = document.body, container = window) {
198
+ return container.innerWidth - element.clientWidth;
122
199
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @module settings
3
+ * @description Utility module for setting up Font Awesome
4
+ */
5
+
6
+ import { updateSettings } from "../settings.js";
7
+
8
+ /**
9
+ * Sets icon settings to Font Awesome icons
10
+ */
11
+ export function configureIcons() {
12
+ updateSettings({
13
+ iconClassClose: "fas fa-xmark",
14
+ iconClassDragX: "fas fa-solid fa-grip-lines-vertical",
15
+ iconClassPrevious: "fas fa-solid fa-chevron-left",
16
+ iconClassNext: "fas fa-solid fa-chevron-right"
17
+ });
18
+ }
package/js/utils/index.js CHANGED
@@ -4,4 +4,5 @@ export * as floatingUi from "./floating-ui.js";
4
4
  export * as id from "./id.js";
5
5
  export * as index from "./index.js";
6
6
  export * as pauseYoutubeVideo from "./pause-youtube-video.js";
7
- export * as fileSave from "./file-save.js";
7
+ export * as fileSave from "./file-save.js";
8
+ export * as fontAwesome from "./font-awesome.js";
@@ -0,0 +1,154 @@
1
+ /**
2
+ * @module utils/system
3
+ * @description Core classes and mechanisms that define how UI components are created and managed within the library
4
+ */
5
+
6
+ import { hasRequiredProps } from "@ulu/utils/object.js";
7
+ import { getDatasetOptionalJson, dataAttributeToDatasetKey } from "./dom.js";
8
+ import { getName } from "../events/index.js";
9
+
10
+ /**
11
+ * Class serves as a utility for UI modules, handling the selection of elements and the initialization of corresponding component instances, ensuring consistent setup within the module
12
+ */
13
+ export class ComponentInitializer {
14
+ static defaults = {
15
+ type: null,
16
+ baseAttribute: null
17
+ };
18
+ static requiredOptions = [
19
+ "type",
20
+ "baseAttribute"
21
+ ];
22
+ static hasRequiredOptions = hasRequiredProps(
23
+ ComponentInitializer.requiredOptions
24
+ );
25
+
26
+ /**
27
+ * Create a new instance of ComponentInitializer
28
+ * @param {Object} options Options for configuring the component initializer.
29
+ * @param {String} options.type Type of component (used for logs).
30
+ * @param {String} options.baseAttribute Prefix and base attribute name (used for base attribute and further element attribute names).
31
+ */
32
+ constructor(options) {
33
+ if (!ComponentInitializer.hasRequiredOptions(options)) {
34
+ throw new Error(
35
+ `Missing a required options: ${ ComponentInitializer.requiredOptions.join(", ") }`
36
+ );
37
+ }
38
+ this.options = Object.assign({}, ComponentInitializer.defaults, options);
39
+ this.logTitle = `ULU: ${ this.options.type }:\n`;
40
+ }
41
+ /**
42
+ * Initializes the component based on the provided configuration.
43
+ * @param {Object} config The initialization configuration.
44
+ * @param {Function} config.setup The setup function to call for each element.
45
+ * @param {String} config.key [null] The optional key to use with attribute selector.
46
+ * @param {Boolean} config.withData [null] Whether to retrieve element data.
47
+ * @param {Array} config.events [null] Ulu events that should call setup when dispatched (ie. pageModified, pageResized)
48
+ * @param {Boolean} config.onPageResized [null] Whether to bind event listener for page resize end
49
+ * @param {HTMLElement} config.context [document] The context to query within.
50
+ */
51
+ init(config) {
52
+ this.setupElements(config);
53
+ // Attach Handler to reinitialize if page is updated
54
+ // Specifically checking entire document incase element that dispatched
55
+ // event made alterations outside of itself
56
+ if (config.events?.length) {
57
+ config.events.forEach(name => {
58
+ document.addEventListener(getName(name), () => this.setupElements(config));
59
+ });
60
+ }
61
+ }
62
+ /**
63
+ * Processes the elements based on the provided configuration.
64
+ * @param {object} config The initialization configuration.
65
+ * @param {function} config.setup The setup function to call for each element.
66
+ * @param {string} config.key The optional key to use with attribute selector.
67
+ * @param {boolean} config.withData [false] Whether to retrieve element data.
68
+ * @param {boolean} config.onPageModified [true] Whether to bind event listener for page modifications.
69
+ * @param {HTMLElement} config.context [document] The context to query within.
70
+ */
71
+ setupElements(config) {
72
+ const { setup, key, withData, context } = config;
73
+ const elementsWithData = this.queryAllInitial(key, withData, context);
74
+ elementsWithData.forEach(elementWithData => setup(elementWithData, this));
75
+ }
76
+ /**
77
+ * Get an attribute name
78
+ * @param {String} key Optional key, if no key will return baseAttribute if key will return key added to base
79
+ * @returns {String} String like data-ulu-dialog or data-ulu-dialog-element
80
+ */
81
+ getAttribute(key) {
82
+ const { baseAttribute } = this.options;
83
+ return key ? `${ baseAttribute }-${ key }` : `${ baseAttribute }`;
84
+ }
85
+ /**
86
+ * Create an attribute selector
87
+ * @param {String} key Optional key (see getAttribute)
88
+ */
89
+ attributeSelector(key) {
90
+ return `[${ this.getAttribute(key) }]`;
91
+ }
92
+ /**
93
+ * Create an attribute selector for initial
94
+ * @return {String}
95
+ */
96
+ attributeSelectorInitial(key) {
97
+ return `${ this.attributeSelector(key) }:not([${ this.getAttribute("init") }])`
98
+ }
99
+ /**
100
+ * Queries all main elements of a component that have not been initialized and extracts their data attributes.
101
+ * @param {HTMLElement} context The context to query within.
102
+ * @param {Boolean} withData Include dataset from element (as optional JSON)
103
+ * @param {Node} context Element to query elements from
104
+ * @returns {Array<{element: HTMLElement, data: object, initialize: Function}>} An array of objects containing the elements, their data, and convenience function initialize() which when called will set the init attribute on the element
105
+ */
106
+ queryAllInitial(key, withData, context = document) {
107
+ const elements = [ ...context.querySelectorAll(this.attributeSelectorInitial(key)) ];
108
+ return elements.map((element) => ({
109
+ element,
110
+ data: withData ? this.getData(element, key) : null,
111
+ initialize: () => this.initializeElement(element)
112
+ }));
113
+ }
114
+ /**
115
+ * Sets the init attribute on an element, marking it as initialized.
116
+ * @param {HTMLElement} element The element to initialize.
117
+ */
118
+ initializeElement(element) {
119
+ element.setAttribute(this.getAttribute("init"), "");
120
+ }
121
+ /**
122
+ * Get an elements dataset value as JSON or other value
123
+ * @return {*} The value of the dataset, if JSON will return object else will return string value or undefined
124
+ */
125
+ getData(element, key) {
126
+ const datasetKey = dataAttributeToDatasetKey(this.getAttribute(key));
127
+ return getDatasetOptionalJson(element, datasetKey);
128
+ }
129
+ /**
130
+ * Will output namespaced console logs for the given initializer
131
+ */
132
+ log(...msgs) {
133
+ console.log(this.logTitle, ...msgs);
134
+ }
135
+ /**
136
+ * Will output namespaced console warnings for the given initializer
137
+ */
138
+ warn(...msgs) {
139
+ console.warn(this.logTitle, ...msgs);
140
+ }
141
+ /**
142
+ * Will output namespaced console error for the given initializer
143
+ */
144
+ logError(...msgs) {
145
+ console.error(this.logTitle, ...msgs);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Class serves as a base for representing individual occurrences of a UI component, providing a consistent structure for each
151
+ */
152
+ export class ComponentInstance {
153
+
154
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulu/frontend",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.0-beta.50",
4
4
  "description": "Modular Sass Theming Library",
5
5
  "browser": "js/index.js",
6
6
  "main": "index.js",
@@ -30,7 +30,9 @@
30
30
  "docs:build:prod": "IS_PRODUCTION=true npx @11ty/eleventy --config=docs.eleventy.js",
31
31
  "docs:assets": "vite --config docs.vite.config.js --force",
32
32
  "docs:assets:build": "vite build --config docs.vite.config.js",
33
- "docs:assets:build:prod": "IS_PRODUCTION=true vite build --config docs.vite.config.js"
33
+ "docs:assets:build:prod": "IS_PRODUCTION=true vite build --config docs.vite.config.js",
34
+ "deploy": "npm run build && npm run types && npm run docs:build:prod && npm run docs:assets:build:prod",
35
+ "deploy:docs": "npm run docs:build:prod && npm run docs:assets:build:prod"
34
36
  },
35
37
  "repository": {
36
38
  "type": "git",
@@ -44,7 +46,10 @@
44
46
  "modules",
45
47
  "javascript",
46
48
  "framework",
47
- "mixin"
49
+ "mixin",
50
+ "components",
51
+ "HTML",
52
+ "frontend framework"
48
53
  ],
49
54
  "authors": {
50
55
  "name": "Joe Scherben, Informatics Studio",
@@ -61,11 +66,12 @@
61
66
  "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
62
67
  "@fortawesome/fontawesome-free": "^6.5.2",
63
68
  "@ulu/markdown-output-utils": "^0.0.6",
64
- "@ulu/sassdoc-to-markdown": "^0.0.15",
69
+ "@ulu/sassdoc-to-markdown": "^0.0.16",
65
70
  "@ulu/vite-config-cms-theme": "^0.0.10",
66
71
  "@ulu/vitepress-auto-menus": "^0.0.3",
67
72
  "@ulu/vitepress-sassdoc": "^0.0.9",
68
73
  "algoliasearch": "^4.23.3",
74
+ "autoprefixer": "^10.4.16",
69
75
  "chokidar": "^3.6.0",
70
76
  "eleventy-plugin-nesting-toc": "^1.3.0",
71
77
  "fs-extra": "^11.2.0",
@@ -78,14 +84,14 @@
78
84
  "sass-embedded": "^1.81.0",
79
85
  "sharp": "^0.33.4",
80
86
  "svgo": "^3.3.2",
87
+ "twig": "^1.17.1",
81
88
  "typescript": "^5.3.3",
82
- "autoprefixer": "^10.4.16",
83
89
  "vite": "^5.4.11"
84
90
  },
85
91
  "dependencies": {
86
- "@ulu/utils": "^0.0.17",
92
+ "@floating-ui/dom": "^1.6.5",
93
+ "@ulu/utils": "^0.0.20",
87
94
  "ally.js": "^1.4.1",
88
- "aria-tablist": "^1.2.2",
89
- "@floating-ui/dom": "^1.6.5"
95
+ "aria-tablist": "^1.2.2"
90
96
  }
91
97
  }
@@ -4,6 +4,7 @@
4
4
  ////
5
5
 
6
6
  @use "sass:map";
7
+ @use "sass:list";
7
8
  @use "utils";
8
9
 
9
10
  /// Module Settings
@@ -30,8 +31,12 @@ $config: (
30
31
  }
31
32
 
32
33
  /// Get a config option
33
- /// @example scss Get default breakpoint name
34
- /// $default: ulu.breakpoint-get("default");
34
+ /// @compiler
35
+ /// @use "index" as ulu;
36
+ /// @example scss {compile} Example usage
37
+ /// .test-get {
38
+ /// font-size: ulu.breakpoint-get("base");
39
+ /// }
35
40
  /// @param {Map} $name Name of property
36
41
  /// @return {*} Property Value
37
42
 
@@ -66,6 +71,14 @@ $sizes: (
66
71
 
67
72
  /// Get all breakpoint sizes
68
73
  /// @return {Map} Map of breakpoints (equivalent to $sizes)
74
+ /// @compiler
75
+ /// @use "index" as ulu;
76
+ /// @use "sass:map";
77
+ /// @example scss {compile} Example usage
78
+ /// .test-get {
79
+ /// $sizes: ulu.breakpoint-get-sizes();
80
+ /// height: map.get($sizes, "medium");
81
+ /// }
69
82
 
70
83
  @function get-sizes() {
71
84
  @return $sizes;
@@ -220,7 +233,7 @@ $sizes: (
220
233
  /// - Breakpoints always min-width (upwards) for javascript setup
221
234
 
222
235
  @mixin embed-for-scripts() {
223
- &:before {
236
+ &::before {
224
237
  display: none;
225
238
  content: get("null-name");
226
239
  @each $size, $breakpoint in $sizes {
package/scss/_color.scss CHANGED
@@ -23,10 +23,17 @@ $palette: (
23
23
  "type-tertiary" : rgb(157, 157, 157),
24
24
  "headline" : inherit,
25
25
  "background" : white,
26
+ "background-gray" : #F7F8F7,
26
27
  "focus" : blue,
27
- "error" : red,
28
- "warning" : orange,
29
28
  "accent" : orange,
29
+ "info" : #00bde3,
30
+ "success" : #00a91c,
31
+ "warning" : #ffbe2e,
32
+ "danger" : #d54309,
33
+ "info-background" : #e7f6f8,
34
+ "success-background" : #ecf3ec,
35
+ "warning-background" : #faf3d1,
36
+ "danger-background" : #f4e3db,
30
37
  "selected" : green,
31
38
  "box-shadow" : rgba(0, 0, 0, 0.349),
32
39
  "box-shadow-hover" : rgba(0, 0, 0, 0.5),
@@ -94,8 +101,11 @@ $color-classes: (
94
101
  @function get($name) {
95
102
  // Allow non lookup if the value is already a color (helps with code flow)
96
103
  @if (meta.type-of($name) == "string") {
104
+ $is-keyword: $name == "inherit" or $name == "transparent" or $name == "currentColor";
105
+ $is-cssvar: string.index($name, "var(") == 1;
106
+ $is-color-mix: string.index($name, "color-mix(") == 1;
97
107
  // Allow custom-properties and keyword inherit/transparent to pass through
98
- @if ($name == "inherit" or $name == "transparent" or $name == "currentColor" or string.index($name, "var(") == 1) {
108
+ @if ($is-keyword or $is-cssvar or $is-color-mix) {
99
109
  @return $name;
100
110
  // Else look up the color from the palette
101
111
  } @else {
@@ -171,7 +181,7 @@ $color-classes: (
171
181
  color: get-context-value($name, "color");
172
182
  }
173
183
 
174
- /// Lighten a color using the default white by a percentage
184
+ /// Tint (add white) a color using the default white by a percentage
175
185
  /// @param {Color, String} $color Color/palette color name to apply to tint
176
186
  /// @param {Number} $percentage Percentage
177
187
  /// @return {Color}
@@ -182,7 +192,18 @@ $color-classes: (
182
192
  @return color.mix(get("white"), get($color), $percentage);
183
193
  }
184
194
 
185
- /// Darken a color with the default black by a percentage
195
+ /// Tint (add white) a color using the default white by a percentage (Using color-mix)
196
+ /// - This only works in modern browsers (as of June 2025)
197
+ /// - These match ulu.color-tint() and are designed to accept the same arguments with the same results
198
+ /// @param {Color, String} $color Color or custom property to apply mix to
199
+ /// @param {Number} $percentage Percentage
200
+ /// @return {Color}
201
+
202
+ @function css-tint($color, $percentage) {
203
+ @return color-mix(in srgb, get("white") $percentage, get($color) calc(100% - $percentage));
204
+ }
205
+
206
+ /// Shade (add black) a color with the default black by a percentage
186
207
  /// @param {Color, String} $color Color/palette color name to shade
187
208
  /// @param {Number} $percentage Percentage to shade
188
209
  /// @return {Color}
@@ -193,6 +214,17 @@ $color-classes: (
193
214
  @return color.mix(get("black"), get($color), $percentage);
194
215
  }
195
216
 
217
+ /// Shade (add black) a color using the default white by a percentage (Using color-mix)
218
+ /// - This only works in modern browsers (as of June 2025)
219
+ /// - These match ulu.color-shade() and are designed to accept the same arguments with the same results
220
+ /// @param {Color, String} $color Color or custom property to apply mix to
221
+ /// @param {Number} $percentage Percentage
222
+ /// @return {Color}
223
+
224
+ @function css-shade($color, $percentage) {
225
+ @return color-mix(in srgb, get("black") $percentage, get($color) calc(100% - $percentage));
226
+ }
227
+
196
228
  /// Prints all context styles
197
229
  /// @param {String} $with-prop Checks the specific context for a certain prop (has to be truthy)(used for output in helper/base color modules)
198
230
  /// @example scss
@@ -69,6 +69,8 @@ $config: (
69
69
  "ul-list-style-type": disc,
70
70
  "ul-list-style-type-2": circle,
71
71
  "ul-list-style-type-3": square,
72
+ "cap-color" : "accent",
73
+ "cap-size" : 5px
72
74
  ) !default;
73
75
 
74
76
  /// Rule style map, redefine defaults or add to
@@ -114,9 +116,10 @@ $rule-margins: (
114
116
 
115
117
  /// Sets rule margins
116
118
  /// @param {Map} $changes Map of changes
119
+ /// @param {String} $merge-mode Merge mode see utils.map-merge() [null|"deep"|"overwrite"]
117
120
 
118
- @mixin set-rule-margins($changes) {
119
- $rule-margins: map.merge($rule-margins, $changes) !global;
121
+ @mixin set-rule-margins($changes, $merge-mode: null) {
122
+ $rule-margins: utils.map-merge($rule-margins, $changes, $merge-mode) !global;
120
123
  }
121
124
 
122
125
  /// Get a rule style
@@ -290,4 +293,93 @@ $rule-margins: (
290
293
  white-space: normal;
291
294
  width: auto;
292
295
  }
296
+ }
297
+
298
+
299
+ /// Layout utility to add a colored bar (cap) to an element's edge, positioned over the element and its border
300
+ /// - You need to set position (relative, fixed) on parent
301
+ /// @param {String} $side The side to place the cap (top, bottom, left, right)
302
+ /// @param {Map} $options Options for the appearance of the cap
303
+ /// @param {Color} $options.color [$config.cap-color] The color for the end cap
304
+ /// @param {Number} $options.size [$config.cap-size] The width/height of the cap
305
+ /// @param {Number} $options.offset [0] A positive number of the amount the cap should extend outside the box (to account for border-width)
306
+ /// @param {Number} $options.border-radius [null] An optional border-radius to apply to the outward-facing edges of the cap (used to match parent)
307
+ /// @param {Boolean} $before [true] Whether or not to use the ::before element (if not uses :after)
308
+
309
+ @mixin cap(
310
+ $side,
311
+ $options: (),
312
+ $before: true,
313
+ ) {
314
+ $defaults: (
315
+ "color" : get("cap-color"),
316
+ "size" : get("cap-size"),
317
+ "offset" : 0,
318
+ "color-hover" : null,
319
+ "border-radius" : null,
320
+ "padding-adjust" : null,
321
+ );
322
+ $config: map.merge($defaults, $options);
323
+ $element: if($before, "::before", "::after");
324
+
325
+ &#{ $element } {
326
+ content: "";
327
+ position: absolute;
328
+ display: block;
329
+ }
330
+
331
+ @include cap-appearance($side, $config, $before);
332
+ }
333
+
334
+
335
+
336
+ /// Provides the appearance styles for a given cap
337
+ /// - If an option is not provided it won't be output
338
+ /// - This is used to update the caps styling (states, modifiers, etc)
339
+ /// @param {String} $side The side to place the cap (top, bottom, left, right)
340
+ /// @param {Map} $options Options for the appearance of the cap (see options from element.cap)
341
+ /// @param {Boolean} $before Whether or not to use the ::before element (if not uses :after)
342
+
343
+ @mixin cap-appearance(
344
+ $side,
345
+ $options: (),
346
+ $before: true
347
+ ) {
348
+ $element: if($before, "::before", "::after");
349
+ $size: map.get($options, "size");
350
+ $offset: map.get($options, "offset");
351
+ $border-radius: map.get($options, "border-radius");
352
+ $padding-adjust: map.get($options, "padding-adjust");
353
+
354
+ $end: $side == "top" or $side == "bottom";
355
+ $position: if($offset, 0 - $offset, null);
356
+
357
+ @if ($padding-adjust and $size) {
358
+ padding-#{ $side }: calc($padding-adjust + $size);
359
+ }
360
+
361
+ &#{ $element } {
362
+ background-color: color.get(map.get($options, "color"));
363
+ #{ $side }: $position;
364
+
365
+ @if $end {
366
+ left: $position;
367
+ right: $position;
368
+ height: $size;
369
+ } @else {
370
+ top: $position;
371
+ bottom: $position;
372
+ width: $size;
373
+ }
374
+
375
+ @if $border-radius {
376
+ @if $end {
377
+ border-#{ $side }-left-radius: $border-radius;
378
+ border-#{ $side }-right-radius: $border-radius;
379
+ } @else {
380
+ border-top-#{ $side }-radius: $border-radius;
381
+ border-bottom-#{ $side }-radius: $border-radius;
382
+ }
383
+ }
384
+ }
293
385
  }
package/scss/_layout.scss CHANGED
@@ -7,6 +7,7 @@
7
7
  @use "sass:meta";
8
8
  @use "utils";
9
9
  @use "breakpoint";
10
+ @use "color";
10
11
 
11
12
  /// Module Settings
12
13
  /// @type Map
@@ -215,10 +216,7 @@ $containers: (
215
216
  $breakpoints: map.get($container, "breakpoints");
216
217
 
217
218
  $width: map.get($container, "width");
218
- // @debug $specific-breakpoint;
219
- // @if $specific-breakpoint {
220
- // @debug $container;
221
- // }
219
+
222
220
  @if ($width == null) {
223
221
  $width: 100%;
224
222
  }
@@ -243,14 +241,14 @@ $containers: (
243
241
  /// Prints clearfix styles
244
242
 
245
243
  @mixin clearfix() {
246
- &:before,
247
- &:after {
244
+ &::before,
245
+ &::after {
248
246
  content: "";
249
247
  display: table;
250
248
  flex-basis: 0; // Flexbox, clear fix for pseudo elements in Safari
251
249
  order: 1;
252
250
  }
253
- &:after {
251
+ &::after {
254
252
  clear: both;
255
253
  }
256
254
  }
@@ -267,6 +265,7 @@ $containers: (
267
265
  /// Layout utility for absolute (zero on all sides)
268
266
  /// - Probably helpful for gzip if we use this when these exact styles are needed
269
267
  /// so they are identical for compression
268
+ /// @param {Boolean} $set-size [false] Whether or not to use sizes to fill the space (height/width 100%) versus setting bottom and right to 0)
270
269
  @mixin absolute-fill($set-size: false) {
271
270
  position: absolute;
272
271
  top: 0;
@@ -278,4 +277,4 @@ $containers: (
278
277
  width: 100%;
279
278
  height: 100%;
280
279
  }
281
- }
280
+ }
package/scss/_units.scss CHANGED
@@ -27,13 +27,14 @@ $config: (
27
27
 
28
28
  /// Update the units config
29
29
  /// @param {Map} $changes A map to merge into the color palette
30
+ /// @param {String} $merge-mode Merge mode see utils.map-merge() [null|"deep"|"overwrite"]
30
31
  /// @example scss Setting the error and type color
31
32
  /// @include ulu.units-set((
32
33
  /// "default" : 1.5em
33
34
  /// ));
34
35
 
35
- @mixin set($changes) {
36
- $config: map.merge($config, $changes) !global;
36
+ @mixin set($changes, $merge-mode: null) {
37
+ $config: utils.map-merge($config, $changes, $merge-mode) !global;
37
38
  }
38
39
 
39
40
  /// Get a unit by name (preset) or number (multiplier of base)