@ulu/frontend-vue 0.1.0-beta.1

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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -0
  3. package/dist/breakpoints-ClT9bfZm.js +211 -0
  4. package/dist/frontend-vue.css +1 -0
  5. package/dist/frontend-vue.js +82 -0
  6. package/dist/frontend-vue.umd.cjs +561 -0
  7. package/dist/index-P5Rwl_Dl.js +7263 -0
  8. package/dist/index.es-HlG3u0J5.js +3134 -0
  9. package/lib/_index.scss +14 -0
  10. package/lib/components/_index.scss +6 -0
  11. package/lib/components/collapsible/UluAccordion.vue +82 -0
  12. package/lib/components/collapsible/UluCollapsibleRegion.vue +278 -0
  13. package/lib/components/collapsible/UluDropdown.vue +42 -0
  14. package/lib/components/collapsible/UluModal.vue +384 -0
  15. package/lib/components/collapsible/UluOverflowPopover.vue +52 -0
  16. package/lib/components/collapsible/UluTab.vue +9 -0
  17. package/lib/components/collapsible/UluTabGroup.vue +31 -0
  18. package/lib/components/collapsible/UluTabList.vue +9 -0
  19. package/lib/components/collapsible/UluTabPanel.vue +9 -0
  20. package/lib/components/collapsible/UluTabPanels.vue +9 -0
  21. package/lib/components/elements/UluAlert.vue +81 -0
  22. package/lib/components/elements/UluBadge.vue +58 -0
  23. package/lib/components/elements/UluBadgeStack.vue +27 -0
  24. package/lib/components/elements/UluButton.vue +161 -0
  25. package/lib/components/elements/UluCallout.vue +30 -0
  26. package/lib/components/elements/UluCard.vue +241 -0
  27. package/lib/components/elements/UluDefinitionList.vue +40 -0
  28. package/lib/components/elements/UluExternalLink.vue +47 -0
  29. package/lib/components/elements/UluIcon.vue +108 -0
  30. package/lib/components/elements/UluList.vue +87 -0
  31. package/lib/components/elements/UluMain.vue +5 -0
  32. package/lib/components/elements/UluSpokeSpinner.vue +25 -0
  33. package/lib/components/elements/UluTag.vue +53 -0
  34. package/lib/components/forms/UluCheckboxMenu.vue +36 -0
  35. package/lib/components/forms/UluFileDisplay.vue +39 -0
  36. package/lib/components/forms/UluFormDropzone.vue +62 -0
  37. package/lib/components/forms/UluFormFile.vue +47 -0
  38. package/lib/components/forms/UluFormMessage.vue +20 -0
  39. package/lib/components/forms/UluFormSelect.vue +37 -0
  40. package/lib/components/forms/UluFormText.vue +32 -0
  41. package/lib/components/forms/UluSearchForm.vue +31 -0
  42. package/lib/components/index.js +54 -0
  43. package/lib/components/layout/UluAdaptiveLayout.vue +11 -0
  44. package/lib/components/layout/UluDataGrid.vue +41 -0
  45. package/lib/components/layout/UluTitleRail.vue +56 -0
  46. package/lib/components/layout/UluWhenBreakpoint.vue +86 -0
  47. package/lib/components/navigation/UluBreadcrumb.vue +72 -0
  48. package/lib/components/navigation/UluMenu.vue +105 -0
  49. package/lib/components/navigation/UluMenuStack.vue +49 -0
  50. package/lib/components/navigation/UluNavStrip.vue +48 -0
  51. package/lib/components/navigation/UluSkipLink.vue +5 -0
  52. package/lib/components/systems/facets/UluFacets.vue +380 -0
  53. package/lib/components/systems/facets/UluFacetsList.vue +39 -0
  54. package/lib/components/systems/facets/UluFacetsSearch.vue +67 -0
  55. package/lib/components/systems/facets/_facets.scss +64 -0
  56. package/lib/components/systems/index.js +17 -0
  57. package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +152 -0
  58. package/lib/components/systems/scroll-anchors/UluScrollAnchorsNav.vue +37 -0
  59. package/lib/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue +124 -0
  60. package/lib/components/systems/scroll-anchors/UluScrollAnchorsSection.vue +63 -0
  61. package/lib/components/systems/scroll-anchors/symbols.js +6 -0
  62. package/lib/components/systems/skeleton/UluShowSkeleton.vue +13 -0
  63. package/lib/components/systems/skeleton/UluSkeletonContent.vue +60 -0
  64. package/lib/components/systems/skeleton/UluSkeletonMedia.vue +11 -0
  65. package/lib/components/systems/skeleton/UluSkeletonTextInline.vue +9 -0
  66. package/lib/components/systems/slider/UluImageSlideShow.vue +75 -0
  67. package/lib/components/systems/slider/UluSlideShow.vue +331 -0
  68. package/lib/components/systems/slider/UluSlideShowSlide.vue +25 -0
  69. package/lib/components/systems/table-sticky/UluTableSticky.vue +793 -0
  70. package/lib/components/systems/table-sticky/UluTableStickyRows.vue +73 -0
  71. package/lib/components/systems/table-sticky/UluTableStickyTable.vue +237 -0
  72. package/lib/components/systems/table-sticky/_table-sticky.scss +185 -0
  73. package/lib/components/utils/UluCondText.vue +28 -0
  74. package/lib/components/utils/UluEmpty.vue +3 -0
  75. package/lib/components/utils/UluEmptyView.vue +3 -0
  76. package/lib/components/utils/UluPlaceholderImage.vue +53 -0
  77. package/lib/components/utils/UluPlaceholderText.vue +25 -0
  78. package/lib/components/utils/UluRouteAnnouncer.vue +83 -0
  79. package/lib/components/visualizations/UluAnimateNumber.vue +32 -0
  80. package/lib/components/visualizations/UluProgressBar.vue +94 -0
  81. package/lib/components/visualizations/UluProgressDonut.vue +97 -0
  82. package/lib/composables/index.js +10 -0
  83. package/lib/composables/useBreakpointManager.js +68 -0
  84. package/lib/composables/useIcon.js +62 -0
  85. package/lib/composables/useModifiers.js +93 -0
  86. package/lib/composables/useWindowResize.js +64 -0
  87. package/lib/index.js +10 -0
  88. package/lib/plugins/_index.scss +7 -0
  89. package/lib/plugins/breakpoints/index.js +47 -0
  90. package/lib/plugins/index.js +11 -0
  91. package/lib/plugins/modals/UluModalsDisplay.vue +59 -0
  92. package/lib/plugins/modals/api.js +76 -0
  93. package/lib/plugins/modals/index.js +60 -0
  94. package/lib/plugins/modals/useModals.js +9 -0
  95. package/lib/plugins/popovers/UluPopover.vue +189 -0
  96. package/lib/plugins/popovers/UluTooltipDisplay.vue +15 -0
  97. package/lib/plugins/popovers/UluTooltipPopover.vue +83 -0
  98. package/lib/plugins/popovers/defaults.js +108 -0
  99. package/lib/plugins/popovers/directive.js +95 -0
  100. package/lib/plugins/popovers/index.js +18 -0
  101. package/lib/plugins/popovers/manager.js +54 -0
  102. package/lib/plugins/popovers/useFollow.js +80 -0
  103. package/lib/plugins/popovers/utils.js +5 -0
  104. package/lib/plugins/toast/UluToast.vue +87 -0
  105. package/lib/plugins/toast/UluToastDisplay.vue +35 -0
  106. package/lib/plugins/toast/_toast.scss +198 -0
  107. package/lib/plugins/toast/defaults.js +30 -0
  108. package/lib/plugins/toast/index.js +17 -0
  109. package/lib/plugins/toast/store.js +71 -0
  110. package/lib/plugins/toast/useToast.js +18 -0
  111. package/lib/settings.js +119 -0
  112. package/lib/utils/dom.js +14 -0
  113. package/lib/utils/placeholder.js +6 -0
  114. package/lib/utils/vue-router.js +219 -0
  115. package/package.json +75 -0
@@ -0,0 +1,331 @@
1
+ <!--
2
+ Notes:
3
+ - Could use anchor links instead of buttons for the nav?
4
+ - How to solve the scrollability with scroll snap
5
+ - Edge detection isn't reliable (scroll snap may prevent the element from reaching the edge of it's scroll)
6
+ - A better technique would be to check if there are any other items that could be scrolled to
7
+ - Could use active state to determine scrollability?
8
+ - This component is passed slide components in the #default slot
9
+ - It uses the default slot property as the reactive var for slides
10
+ - It renders the slides from the slot using <component> instead <slot>
11
+ - Since we know they are all component instances we can use <component> to render the vnode
12
+ - That way no hacks for getting slide DOM references, count, etc
13
+ - Allows us to collest a ref array of all slides
14
+ - Keeps the UX of the component simple, no need for hacks like passing props and asking user of component to set things like active
15
+ - TODO not sure if this is ok to do, what happens with props? User can pass props, we can pass props
16
+ - Should we debounce the scroll or throttle it
17
+ - Throttling would allow active items to happen during scroll
18
+ - Going to try this first
19
+ - Debounce would wait until scrolling ends
20
+ Todo:
21
+ [ ] - Setup active state in nav (need to think this through)
22
+
23
+ -->
24
+ <template>
25
+ <div class="slideshow">
26
+ <div class="slideshow__control-context" ref="context">
27
+ <div class="slideshow__track-crop" ref="crop">
28
+ <ul class="slideshow__track" ref="track">
29
+ <li
30
+ v-for="(slide, index) in slides"
31
+ class="slideshow__slide"
32
+ :class="{ 'is-active' : slide.active }"
33
+ :key="index"
34
+ :tabindex="slideFocusable ? '0' : '-1'"
35
+ :ref="el => { slide.element = el }"
36
+ >
37
+ <slot
38
+ name="slide"
39
+ :item="slide.item"
40
+ :index="index"
41
+ />
42
+ </li>
43
+ </ul>
44
+ </div>
45
+ <ul class="slideshow__controls">
46
+ <li class="slideshow__controls-item slideshow__controls-item--previous">
47
+ <button
48
+ class="slideshow__control-button slideshow__control-button--previous"
49
+ aria-label="Scroll Right"
50
+ @click="previous"
51
+ :disabled="!canScrollLeft"
52
+ >
53
+ <FaIcon class="slideshow__control-icon" icon="fas fa-chevron-left"/>
54
+ </button>
55
+ </li>
56
+ <li class="slideshow__controls-item slideshow__controls-item--next">
57
+ <button
58
+ class="slideshow__control-button slideshow__control-button--next"
59
+ aria-label="Scroll Left"
60
+ @click="next"
61
+ :disabled="!canScrollRight"
62
+ >
63
+ <FaIcon class="slideshow__control-icon" icon="fas fa-chevron-right"/>
64
+ </button>
65
+ </li>
66
+ </ul>
67
+ </div>
68
+ <ul
69
+ v-if="!noNav"
70
+ class="slideshow__nav"
71
+ ref="nav"
72
+ >
73
+ <li
74
+ class="slideshow__nav-item"
75
+ v-for="(slide, index) in slides"
76
+ :class="{ 'is-active' : slide.active }"
77
+ :ref="el => { slide.navElement = el }"
78
+ :key="index"
79
+ >
80
+ <button
81
+ class="slideshow__nav-button"
82
+ :class="{ 'is-active' : slide.active }"
83
+ @click="to(index)"
84
+ >
85
+ <slot
86
+ name="nav"
87
+ :item="slide.item"
88
+ :index="index"
89
+ :active="slide.active"
90
+ >
91
+ <span class="hidden-visually">Item {{ index + 1 }}</span>
92
+ </slot>
93
+ </button>
94
+ </li>
95
+ </ul>
96
+ </div>
97
+ </template>
98
+
99
+ <script>
100
+ export default {
101
+ name: 'SlideShow',
102
+ props: {
103
+ /**
104
+ * Should slides be focusable by tab key
105
+ */
106
+ slideFocusable: Boolean,
107
+ /**
108
+ * Setting for element.focus() when navigating to() a specific slide
109
+ */
110
+ focusOptions: {
111
+ type: Object,
112
+ default: () => ({
113
+ preventScroll: true,
114
+ focusVisible: false
115
+ })
116
+ },
117
+ /**
118
+ * Array of slide items (data)
119
+ * - Use slot (#slide) to template
120
+ */
121
+ items: Array,
122
+ /**
123
+ * Slideshow without a nav
124
+ */
125
+ noNav: Boolean,
126
+ /**
127
+ * Allow user to change the scroll behavior when a slide is navigated to()
128
+ */
129
+ scrollBehaviorNav: {
130
+ type: String,
131
+ default: "instant"
132
+ },
133
+ /**
134
+ * Allow user to change the scroll behavior when a slide is navigated via next/prev
135
+ */
136
+ scrollBehaviorControl: {
137
+ type: String,
138
+ default: "smooth"
139
+ },
140
+ /**
141
+ * Observe
142
+ */
143
+ observerOptions: {
144
+ type: Object,
145
+ default: () => ({
146
+ threshhold: 0,
147
+ rootMargin: "-50% 0px"
148
+ })
149
+ },
150
+ /**
151
+ * The intial slide index to use for active slide (zero based)
152
+ */
153
+ initialActive: {
154
+ type: Number,
155
+ default: 0
156
+ },
157
+ /**
158
+ * Allow user to control scroll amount (element.scrollTo) for prev/next controls
159
+ * - For future scroll implementations (like ulu scroll-slider for cards, etc)
160
+ * - Function is passed (direction, DomRefs)
161
+ * - Number is passed directly
162
+ */
163
+ scrollAmount: [Number, Function],
164
+ },
165
+ data() {
166
+ return {
167
+ slides: this.createSlides()
168
+ };
169
+ },
170
+ computed: {
171
+ canScrollRight() {
172
+ const { slides } = this;
173
+ return !slides[slides.length - 1].active;
174
+ },
175
+ canScrollLeft() {
176
+ const { slides } = this;
177
+ return !slides[0].active;
178
+ }
179
+ },
180
+ watch: {
181
+ 'items.length'() {
182
+ this.slides = this.createSlides();
183
+ this.$nextTick(() => {
184
+ this.observeSlides();
185
+ });
186
+ }
187
+ },
188
+ methods: {
189
+ /**
190
+ * Creates the internal array of slides based on user's passed items
191
+ */
192
+ createSlides() {
193
+ return this.items.map(item => ({
194
+ element: null,
195
+ active: false,
196
+ item
197
+ }));
198
+ },
199
+ /**
200
+ * Find the corresponding slide data by slide element
201
+ */
202
+ getSlideByElement(el) {
203
+ return this.slides.find(({ element }) => el === element);
204
+ },
205
+ /**
206
+ * Provides scroll measurements
207
+ */
208
+ getScrollData() {
209
+ const { scrollLeft, offsetWidth, scrollWidth } = this.$refs.track;
210
+ return { scrollLeft, offsetWidth, scrollWidth };
211
+ },
212
+ /**
213
+ * Determines the amount to scroll the track
214
+ */
215
+ resolveAmount(dir) {
216
+ const isNext = dir === "next";
217
+ const { scrollAmount: amount } = this;
218
+ const { scrollLeft, offsetWidth } = this.getScrollData();
219
+
220
+ if (typeof amount === "function") {
221
+ // Function can be setup by user (ie. scrolling by visible items for example)
222
+ return amount(dir, this.$refs);
223
+ } else if (typeof amount === "number") {
224
+ return isNext ? scrollLeft + amount : scrollLeft - amount;
225
+ } else {
226
+ // No amount set (default 100% scrollable area shift)
227
+ return isNext ? scrollLeft + offsetWidth : scrollLeft - offsetWidth;
228
+ }
229
+ },
230
+ /**
231
+ * Scroll the track to a specified point
232
+ */
233
+ scrollTo(left, behavior) {
234
+ this.$refs.track.scrollTo({ left, top: 0, behavior });
235
+ },
236
+ /**
237
+ * Scroll to specific index
238
+ * @param {Number} index Slide index
239
+ */
240
+ to(index) {
241
+ const slide = this.slides[index];
242
+ const { track } = this.$refs;
243
+ if (slide) {
244
+ let amount = slide.element.offsetLeft;
245
+ const end = () => {
246
+ slide.element.focus(this.focusOptions);
247
+ track.removeEventListener('scrollend', end);
248
+ }
249
+ track.addEventListener('scrollend', end);
250
+ this.scrollTo(amount, this.scrollBehaviorNav);
251
+ }
252
+ },
253
+ /**
254
+ * Goto to next slide
255
+ */
256
+ next() {
257
+ const amount = this.resolveAmount("next");
258
+ this.scrollTo(amount, this.scrollBehaviorControl);
259
+ },
260
+ /**
261
+ * Goto to previous slide
262
+ */
263
+ previous() {
264
+ const amount = this.resolveAmount("previous");
265
+ this.scrollTo(amount, this.scrollBehaviorControl);
266
+ },
267
+ /**
268
+ * Sets up a new observer to watch the slides visibility (within track)
269
+ */
270
+ createObserver() {
271
+ const { observerOptions } = this;
272
+ const { track, nav } = this.$refs;
273
+ // Observer callback, basically just sets active state for a given slide
274
+ // - isIntersecting will change when the element enters and leaves
275
+ const onObserve = (entries) => {
276
+ entries.forEach((entry) => {
277
+
278
+ this.$nextTick(() => {
279
+ const slide = this.getSlideByElement(entry.target);
280
+ slide.active = entry.isIntersecting;
281
+ this.$emit('slideChange', { slide, track, nav });
282
+ });
283
+ });
284
+ };
285
+ // Add non-reactive prop for removal and changes to targets
286
+ this.observer = new IntersectionObserver(onObserve, {
287
+ root: track,
288
+ ...observerOptions
289
+ });
290
+ },
291
+ /**
292
+ * Add all slide elements as targets in observer
293
+ */
294
+ observeSlides() {
295
+ const { observer, slides } = this;
296
+ observer.disconnect();
297
+ slides.forEach(({ element }) => {
298
+ if (element) {
299
+ observer.observe(element);
300
+ }
301
+ });
302
+ },
303
+ /**
304
+ * Remove observer and it's internal DOM references (GC)
305
+ */
306
+ destroyObserver() {
307
+ this.observer.disconnect();
308
+ this.observer = null;
309
+ },
310
+ },
311
+ mounted() {
312
+ this.createObserver();
313
+ this.observeSlides();
314
+ },
315
+ beforeUnmount() {
316
+ this.destroyObserver();
317
+ },
318
+ }
319
+ </script>
320
+
321
+ <!--
322
+ Old Notes:
323
+ - How to get around access the elements of the children in slots
324
+ - Component element is not available
325
+ - Hacks
326
+ - Add hidden element and use nextSibling (stack overflow suggestion)
327
+ - Don't like this. We could always traverse dom from the parent track ref anyways
328
+ but I'm trying to avoid that
329
+ - Ideas
330
+ - Watch the slot components and use
331
+ -->
@@ -0,0 +1,25 @@
1
+ <!--
2
+ Notes:
3
+ - This component is used in parent to identify slides in default slot
4
+ -->
5
+ <template>
6
+ <li class="slideshow__slide" :class="{ 'is-active' : active }">
7
+ <slot/>
8
+ </li>
9
+ </template>
10
+
11
+ <script>
12
+ export default {
13
+ name: 'SlideShowSlide',
14
+ props: {
15
+ /**
16
+ * Provided by grandparent, not user
17
+ */
18
+ active: Boolean,
19
+ someClassTest: String
20
+ },
21
+ mounted() {
22
+ console.log('slide mounted');
23
+ }
24
+ }
25
+ </script>