@ulu/frontend 0.1.0-beta.6 → 0.1.0-beta.61

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 (290) hide show
  1. package/CHANGELOG.md +428 -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 +6236 -0
  9. package/docs-dev/changelog/updates-and-changes/index.html +5109 -0
  10. package/docs-dev/demos/accordion/index.html +904 -321
  11. package/docs-dev/demos/basic-hero/index.html +111 -0
  12. package/docs-dev/demos/breakpoints-manager/index.html +5246 -0
  13. package/docs-dev/demos/button/index.html +916 -323
  14. package/docs-dev/demos/button-verbose/index.html +5238 -0
  15. package/docs-dev/demos/callout/index.html +951 -328
  16. package/docs-dev/demos/captioned-figure/index.html +904 -321
  17. package/docs-dev/demos/card/index.html +970 -748
  18. package/docs-dev/demos/card-grid/index.html +5357 -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 +5224 -0
  24. package/docs-dev/demos/css-icons/index.html +904 -321
  25. package/docs-dev/demos/data-grid/index.html +1014 -511
  26. package/docs-dev/demos/data-table/index.html +1064 -348
  27. package/docs-dev/demos/details-group/index.html +5267 -0
  28. package/docs-dev/demos/file-save/index.html +904 -321
  29. package/docs-dev/demos/flipcard/index.html +904 -321
  30. package/docs-dev/demos/form-theme/index.html +922 -352
  31. package/docs-dev/demos/hero/index.html +12 -4
  32. package/docs-dev/demos/image-grid/index.html +12 -4
  33. package/docs-dev/demos/index.html +905 -322
  34. package/docs-dev/demos/list-inline/index.html +5220 -0
  35. package/docs-dev/demos/list-inline.1/index.html +4727 -0
  36. package/docs-dev/demos/list-lines/index.html +5210 -0
  37. package/docs-dev/demos/menu-stack/index.html +975 -377
  38. package/docs-dev/demos/modals/index.html +1010 -357
  39. package/docs-dev/demos/nav-strip/index.html +904 -321
  40. package/docs-dev/demos/overlay-section/index.html +979 -326
  41. package/docs-dev/demos/popovers/index.html +1152 -327
  42. package/docs-dev/demos/print/index.html +904 -321
  43. package/docs-dev/demos/pull-quote/index.html +904 -321
  44. package/docs-dev/demos/rule/index.html +952 -357
  45. package/docs-dev/demos/scroll-slider/index.html +72 -106
  46. package/docs-dev/demos/scrollpoints/index.html +905 -322
  47. package/docs-dev/demos/slider/index.html +12 -4
  48. package/docs-dev/demos/spoke-spinner/index.html +904 -321
  49. package/docs-dev/demos/sticky-list/index.html +5223 -0
  50. package/docs-dev/demos/tabs/index.html +944 -325
  51. package/docs-dev/demos/tag/index.html +904 -321
  52. package/docs-dev/demos/theme-toggle/index.html +5279 -0
  53. package/docs-dev/demos/tile-grid-overlay/index.html +12 -4
  54. package/docs-dev/demos/tiles/index.html +904 -321
  55. package/docs-dev/demos/tooltip/index.html +904 -321
  56. package/docs-dev/guide/building-stylesheet/index.html +904 -321
  57. package/docs-dev/guide/developing-ulu-scss-module/index.html +904 -321
  58. package/docs-dev/guide/index.html +904 -321
  59. package/docs-dev/guide/updates-and-changes/index.html +5033 -0
  60. package/docs-dev/index.html +904 -321
  61. package/docs-dev/javascript/events/index.html +901 -320
  62. package/docs-dev/javascript/index.html +904 -321
  63. package/docs-dev/javascript/settings/index.html +5400 -0
  64. package/docs-dev/javascript/ui-breakpoints/index.html +916 -335
  65. package/docs-dev/javascript/ui-collapsible/index.html +901 -320
  66. package/docs-dev/javascript/ui-details-group/index.html +5322 -0
  67. package/docs-dev/javascript/ui-dialog/index.html +967 -371
  68. package/docs-dev/javascript/ui-flipcard/index.html +964 -327
  69. package/docs-dev/javascript/ui-grid/index.html +913 -358
  70. package/docs-dev/javascript/ui-modal-builder/index.html +1067 -366
  71. package/docs-dev/javascript/ui-overflow-scroller/index.html +901 -320
  72. package/docs-dev/javascript/ui-overflow-scroller-pager/index.html +901 -320
  73. package/docs-dev/javascript/ui-page/index.html +901 -320
  74. package/docs-dev/javascript/ui-popover/index.html +911 -334
  75. package/docs-dev/javascript/ui-print/index.html +901 -328
  76. package/docs-dev/javascript/ui-print-details/index.html +901 -320
  77. package/docs-dev/javascript/ui-programmatic-modal/index.html +901 -320
  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 +941 -328
  81. package/docs-dev/javascript/ui-scrollpoint/index.html +907 -333
  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 +901 -320
  95. package/docs-dev/sass/base/elements/index.html +901 -320
  96. package/docs-dev/sass/base/index/index.html +901 -320
  97. package/docs-dev/sass/base/index.html +904 -321
  98. package/docs-dev/sass/base/keyframes/index.html +901 -320
  99. package/docs-dev/sass/base/layout/index.html +901 -320
  100. package/docs-dev/sass/base/normalize/index.html +901 -320
  101. package/docs-dev/sass/base/print/index.html +901 -320
  102. package/docs-dev/sass/base/root/index.html +901 -320
  103. package/docs-dev/sass/base/typography/index.html +901 -320
  104. package/docs-dev/sass/components/accordion/index.html +908 -327
  105. package/docs-dev/sass/components/adaptive-spacing/index.html +901 -320
  106. package/docs-dev/sass/components/badge/index.html +909 -328
  107. package/docs-dev/sass/components/basic-hero/index.html +5385 -0
  108. package/docs-dev/sass/components/button/index.html +901 -320
  109. package/docs-dev/sass/components/button-verbose/index.html +989 -333
  110. package/docs-dev/sass/components/callout/index.html +1018 -414
  111. package/docs-dev/sass/components/captioned-figure/index.html +1026 -330
  112. package/docs-dev/sass/components/card/index.html +1003 -350
  113. package/docs-dev/sass/components/card-grid/index.html +901 -320
  114. package/docs-dev/sass/components/counter-list/index.html +5458 -0
  115. package/docs-dev/sass/components/css-icon/index.html +918 -330
  116. package/docs-dev/sass/components/data-grid/index.html +922 -334
  117. package/docs-dev/sass/components/data-table/index.html +1106 -333
  118. package/docs-dev/sass/components/fill-context/index.html +901 -320
  119. package/docs-dev/sass/components/flipcard/index.html +939 -327
  120. package/docs-dev/sass/components/flipcard-grid/index.html +901 -320
  121. package/docs-dev/sass/components/form-theme/index.html +1110 -433
  122. package/docs-dev/sass/components/hero/index.html +995 -366
  123. package/docs-dev/sass/components/horizontal-rule/index.html +901 -320
  124. package/docs-dev/sass/components/image-grid/index.html +901 -320
  125. package/docs-dev/sass/components/index/index.html +915 -330
  126. package/docs-dev/sass/components/index.html +904 -321
  127. package/docs-dev/sass/components/links/index.html +901 -320
  128. package/docs-dev/sass/components/list-inline/index.html +5399 -0
  129. package/docs-dev/sass/components/list-lines/index.html +936 -359
  130. package/docs-dev/sass/components/list-ordered/index.html +903 -322
  131. package/docs-dev/sass/components/list-unordered/index.html +901 -320
  132. package/docs-dev/sass/components/menu-stack/index.html +973 -379
  133. package/docs-dev/sass/components/modal/index.html +953 -365
  134. package/docs-dev/sass/components/nav-strip/index.html +909 -328
  135. package/docs-dev/sass/components/overlay-section/index.html +909 -328
  136. package/docs-dev/sass/components/pager/index.html +901 -320
  137. package/docs-dev/sass/components/placeholder-block/index.html +901 -320
  138. package/docs-dev/sass/components/popover/index.html +996 -379
  139. package/docs-dev/sass/components/pull-quote/index.html +913 -332
  140. package/docs-dev/sass/components/ratio-box/index.html +909 -328
  141. package/docs-dev/sass/components/rule/index.html +909 -328
  142. package/docs-dev/sass/components/scroll-slider/index.html +944 -375
  143. package/docs-dev/sass/components/skip-link/index.html +909 -328
  144. package/docs-dev/sass/components/slider/index.html +989 -420
  145. package/docs-dev/sass/components/spoke-spinner/index.html +903 -322
  146. package/docs-dev/sass/components/sticky-list/index.html +5603 -0
  147. package/docs-dev/sass/components/tabs/index.html +910 -329
  148. package/docs-dev/sass/components/tag/index.html +903 -322
  149. package/docs-dev/sass/components/tile-button/index.html +901 -320
  150. package/docs-dev/sass/components/tile-grid/index.html +901 -320
  151. package/docs-dev/sass/components/tile-grid-overlay/index.html +901 -320
  152. package/docs-dev/sass/components/vignette/index.html +915 -328
  153. package/docs-dev/sass/components/wysiwyg/index.html +901 -320
  154. package/docs-dev/sass/core/breakpoint/index.html +947 -352
  155. package/docs-dev/sass/core/button/index.html +901 -320
  156. package/docs-dev/sass/core/color/index.html +1078 -364
  157. package/docs-dev/sass/core/cssvar/index.html +901 -320
  158. package/docs-dev/sass/core/element/index.html +1096 -368
  159. package/docs-dev/sass/core/index.html +901 -320
  160. package/docs-dev/sass/core/layout/index.html +961 -361
  161. package/docs-dev/sass/core/path/index.html +901 -320
  162. package/docs-dev/sass/core/selector/index.html +901 -320
  163. package/docs-dev/sass/core/typography/index.html +901 -320
  164. package/docs-dev/sass/core/units/index.html +911 -324
  165. package/docs-dev/sass/core/utils/index.html +1871 -430
  166. package/docs-dev/sass/helpers/color/index.html +901 -320
  167. package/docs-dev/sass/helpers/display/index.html +902 -321
  168. package/docs-dev/sass/helpers/index/index.html +901 -320
  169. package/docs-dev/sass/helpers/index.html +904 -321
  170. package/docs-dev/sass/helpers/print/index.html +843 -292
  171. package/docs-dev/sass/helpers/typography/index.html +901 -320
  172. package/docs-dev/sass/helpers/units/index.html +901 -320
  173. package/docs-dev/sass/helpers/utilities/index.html +903 -322
  174. package/docs-dev/sass/index.html +904 -321
  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 +76 -56
  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 +108 -63
  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 -7
  203. package/scss/_breakpoint.scss +16 -3
  204. package/scss/_color.scss +36 -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 +5 -7
  211. package/scss/components/_basic-hero.scss +112 -0
  212. package/scss/components/_button-verbose.scss +100 -18
  213. package/scss/components/_callout.scss +125 -78
  214. package/scss/components/_captioned-figure.scss +17 -0
  215. package/scss/components/_card-grid.scss +1 -1
  216. package/scss/components/_card.scss +246 -74
  217. package/scss/components/_counter-list.scss +137 -0
  218. package/scss/components/_css-icon.scss +25 -21
  219. package/scss/components/_data-grid.scss +38 -9
  220. package/scss/components/_data-table.scss +44 -4
  221. package/scss/components/_flipcard.scss +8 -3
  222. package/scss/components/_form-theme.scss +119 -108
  223. package/scss/components/_hero.scss +12 -10
  224. package/scss/components/_index.scss +24 -0
  225. package/scss/components/_list-inline.scss +80 -0
  226. package/scss/components/_list-lines.scss +44 -32
  227. package/scss/components/_menu-stack.scss +42 -26
  228. package/scss/components/_modal.scss +13 -6
  229. package/scss/components/_nav-strip.scss +2 -0
  230. package/scss/components/_overlay-section.scss +2 -5
  231. package/scss/components/_popover.scss +165 -64
  232. package/scss/components/_pull-quote.scss +13 -13
  233. package/scss/components/_ratio-box.scss +2 -5
  234. package/scss/components/_rule.scss +1 -0
  235. package/scss/components/_scroll-slider.scss +1 -5
  236. package/scss/components/_slider.scss +49 -72
  237. package/scss/components/_spoke-spinner.scss +2 -2
  238. package/scss/components/_sticky-list.scss +206 -0
  239. package/scss/components/_tabs.scss +3 -1
  240. package/scss/components/_vignette.scss +3 -5
  241. package/scss/helpers/_display.scss +15 -18
  242. package/scss/helpers/_print.scss +12 -7
  243. package/scss/helpers/_utilities.scss +42 -32
  244. package/types/index.d.ts +1 -0
  245. package/types/settings.d.ts +66 -0
  246. package/types/settings.d.ts.map +1 -0
  247. package/types/ui/breakpoints.d.ts +14 -14
  248. package/types/ui/breakpoints.d.ts.map +1 -1
  249. package/types/ui/collapsible.d.ts.map +1 -1
  250. package/types/ui/details-group.d.ts +38 -0
  251. package/types/ui/details-group.d.ts.map +1 -0
  252. package/types/ui/dialog.d.ts +20 -14
  253. package/types/ui/dialog.d.ts.map +1 -1
  254. package/types/ui/flipcard.d.ts +16 -10
  255. package/types/ui/flipcard.d.ts.map +1 -1
  256. package/types/ui/grid.d.ts +4 -6
  257. package/types/ui/grid.d.ts.map +1 -1
  258. package/types/ui/index.d.ts +1 -0
  259. package/types/ui/modal-builder.d.ts +93 -11
  260. package/types/ui/modal-builder.d.ts.map +1 -1
  261. package/types/ui/overflow-scroller.d.ts +2 -2
  262. package/types/ui/overflow-scroller.d.ts.map +1 -1
  263. package/types/ui/popover.d.ts +6 -7
  264. package/types/ui/popover.d.ts.map +1 -1
  265. package/types/ui/print.d.ts +0 -4
  266. package/types/ui/print.d.ts.map +1 -1
  267. package/types/ui/programmatic-modal.d.ts.map +1 -1
  268. package/types/ui/proxy-click.d.ts +19 -3
  269. package/types/ui/proxy-click.d.ts.map +1 -1
  270. package/types/ui/scroll-slider.d.ts +5 -7
  271. package/types/ui/scroll-slider.d.ts.map +1 -1
  272. package/types/ui/scrollpoint.d.ts +3 -8
  273. package/types/ui/scrollpoint.d.ts.map +1 -1
  274. package/types/ui/slider.d.ts +33 -14
  275. package/types/ui/slider.d.ts.map +1 -1
  276. package/types/ui/tabs.d.ts +6 -8
  277. package/types/ui/tabs.d.ts.map +1 -1
  278. package/types/ui/theme-toggle.d.ts +51 -7
  279. package/types/ui/theme-toggle.d.ts.map +1 -1
  280. package/types/ui/tooltip.d.ts +3 -5
  281. package/types/ui/tooltip.d.ts.map +1 -1
  282. package/types/utils/css.d.ts +11 -0
  283. package/types/utils/css.d.ts.map +1 -0
  284. package/types/utils/dom.d.ts +45 -6
  285. package/types/utils/dom.d.ts.map +1 -1
  286. package/types/utils/font-awesome.d.ts +5 -0
  287. package/types/utils/font-awesome.d.ts.map +1 -0
  288. package/types/utils/index.d.ts +1 -0
  289. package/types/utils/system.d.ts +113 -0
  290. 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.6",
3
+ "version": "0.1.0-beta.61",
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,15 @@
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.23",
87
94
  "ally.js": "^1.4.1",
88
95
  "aria-tablist": "^1.2.2",
89
- "@floating-ui/dom": "^1.6.5"
96
+ "swipe-listener" : "^1.3.0"
90
97
  }
91
98
  }
@@ -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
@@ -25,9 +25,15 @@ $palette: (
25
25
  "background" : white,
26
26
  "background-gray" : #F7F8F7,
27
27
  "focus" : blue,
28
- "error" : red,
29
- "warning" : orange,
30
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,
31
37
  "selected" : green,
32
38
  "box-shadow" : rgba(0, 0, 0, 0.349),
33
39
  "box-shadow-hover" : rgba(0, 0, 0, 0.5),
@@ -95,8 +101,11 @@ $color-classes: (
95
101
  @function get($name) {
96
102
  // Allow non lookup if the value is already a color (helps with code flow)
97
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;
98
107
  // Allow custom-properties and keyword inherit/transparent to pass through
99
- @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) {
100
109
  @return $name;
101
110
  // Else look up the color from the palette
102
111
  } @else {
@@ -172,7 +181,7 @@ $color-classes: (
172
181
  color: get-context-value($name, "color");
173
182
  }
174
183
 
175
- /// Lighten a color using the default white by a percentage
184
+ /// Tint (add white) a color using the default white by a percentage
176
185
  /// @param {Color, String} $color Color/palette color name to apply to tint
177
186
  /// @param {Number} $percentage Percentage
178
187
  /// @return {Color}
@@ -183,7 +192,18 @@ $color-classes: (
183
192
  @return color.mix(get("white"), get($color), $percentage);
184
193
  }
185
194
 
186
- /// 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
187
207
  /// @param {Color, String} $color Color/palette color name to shade
188
208
  /// @param {Number} $percentage Percentage to shade
189
209
  /// @return {Color}
@@ -194,6 +214,17 @@ $color-classes: (
194
214
  @return color.mix(get("black"), get($color), $percentage);
195
215
  }
196
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
+
197
228
  /// Prints all context styles
198
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)
199
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)