@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,54 @@
1
+ import { ref } from "vue";
2
+ import defaults from "./defaults.js";
3
+
4
+ export const options = {
5
+ plugin: { ...defaults.plugin },
6
+ popover: { ...defaults.popover },
7
+ tooltip: { ...defaults.tooltip, ...defaults.popover },
8
+ };
9
+
10
+ /**
11
+ * Whether or not the tooltip is active
12
+ */
13
+ export const active = ref(false);
14
+ /**
15
+ * Current tooltip config
16
+ */
17
+ export const activeConfig = ref(null);
18
+
19
+ /**
20
+ * Setup the store options
21
+ * @param {Object} userOptions
22
+ * @param {Object} options Resolved options
23
+ */
24
+ export function init(userOptions = {}) {
25
+ Object.assign(options.popover, userOptions.popover);
26
+ Object.assign(options.tooltip, userOptions.tooltip);
27
+ Object.assign(options.plugin, userOptions.plugin);
28
+ return options;
29
+ }
30
+
31
+ /**
32
+ * Config for a single tooltip instance
33
+ */
34
+ export function createConfig(userConfig) {
35
+ return Object.assign({}, options.tooltip, userConfig);
36
+ }
37
+
38
+ /**
39
+ * Show a tooltip
40
+ * - Set by directive
41
+ */
42
+ export function show(config) {
43
+ active.value = true;
44
+ activeConfig.value = config;
45
+ }
46
+
47
+ /**
48
+ * Hide a tooltip
49
+ * - Set by directive
50
+ */
51
+ export function hide() {
52
+ active.value = false;
53
+ activeConfig.value = null;
54
+ }
@@ -0,0 +1,80 @@
1
+ import { ref } from "vue";
2
+ import { show, hide, createConfig } from "./manager.js";
3
+
4
+ const defaults = {
5
+ content: null
6
+ };
7
+
8
+ export default function useFollowPoint(userOptions) {
9
+ if (!userOptions.content) {
10
+ console.warn("Missing content for 'useFollowPoint' tooltip", userOptions);
11
+ }
12
+ const options = Object.assign({}, defaults, userOptions);
13
+
14
+ let _update;
15
+
16
+ const x = ref(0);
17
+ const y = ref(0);
18
+
19
+ const config = createConfig({
20
+ trigger: ref({
21
+ getBoundingClientRect() {
22
+ const currentX = x.value;
23
+ const currentY = y.value;
24
+ return {
25
+ width: 0,
26
+ height: 0,
27
+ x: currentX,
28
+ left: currentX,
29
+ right: currentX,
30
+ y: currentY,
31
+ top: currentY,
32
+ bottom: currentY,
33
+ };
34
+ }
35
+ }),
36
+ content: options.content,
37
+ inline: false,
38
+ onReady({ update }) {
39
+ _update = update;
40
+ }
41
+ });
42
+
43
+ return {
44
+ /**
45
+ * Reactive X value
46
+ * @type {Object}
47
+ */
48
+ x,
49
+ /**
50
+ * Reactive Y value
51
+ * @type {Object}
52
+ */
53
+ y,
54
+ /**
55
+ * Show follow tooltip
56
+ */
57
+ show() {
58
+ show(config);
59
+ },
60
+ /**
61
+ * Hide follow tooltip
62
+ */
63
+ hide() {
64
+ hide(config);
65
+ },
66
+ /**
67
+ *
68
+ * @param {Object} changes Updates for virtual element
69
+ * @param {Object} changes.x New 'x' value
70
+ * @param {Object} changes.y New 'y' value
71
+ */
72
+ update(changes) {
73
+ x.value = changes.x;
74
+ y.value = changes.y;
75
+ if (_update) {
76
+ _update();
77
+ }
78
+ },
79
+ };
80
+ }
@@ -0,0 +1,5 @@
1
+ let uidCount = 0;
2
+
3
+ export function newUid() {
4
+ return `ulu-popovers-uid-${ ++uidCount }`;
5
+ }
@@ -0,0 +1,87 @@
1
+ <!--
2
+ Using slots so that user can wrap component for custom displays within default template (ie. to render a badge, etc)
3
+ -->
4
+ <template>
5
+ <div
6
+ class="toast"
7
+ :class="[
8
+ {
9
+ 'toast--persistent' : !toast.duration
10
+ },
11
+ toast?.class
12
+ ]"
13
+ >
14
+ <div v-if="toast.icon || $slots.icon" class="toast__icon" :class="classes.icon">
15
+ <slot name="icon" :toast="toast">
16
+ <FaIcon v-if="toast.icon" :icon="toast.icon"/>
17
+ </slot>
18
+ </div>
19
+ <div class="toast__content" :class="classes.content">
20
+ <slot name="content" :toast="toast">
21
+ <div v-if="toast.title" class="toast__header" :class="classes.header">
22
+ <strong class="toast__title" :class="classes.title">
23
+ {{ toast.title }}
24
+ </strong>
25
+ <span v-if="toast.date" class="toast__date" :class="classes.date">
26
+ {{ toast.date }}
27
+ </span>
28
+ </div>
29
+ <div v-if="toast.description" class="toast__body" :class="classes.body">
30
+ {{ toast.description }}
31
+ </div>
32
+ </slot>
33
+ </div>
34
+ <div v-if="toast.actions?.length" class="toast__actions" :class="classes.actions">
35
+ <button
36
+ v-for="(action, index) in toast.actions"
37
+ :key="index"
38
+ class="toast__action"
39
+ :class="classes.action"
40
+ @click="handleAction($event, action)"
41
+ >
42
+ {{ action.label }}
43
+ </button>
44
+ </div>
45
+ <button class="toast__close" :class="classes.closeButton" @click="toast.close">
46
+ <UluIcon type="close"/>
47
+ </button>
48
+ </div>
49
+ </template>
50
+
51
+ <script>
52
+ import UluIcon from "../../components/elements/UluIcon.vue";
53
+ export default {
54
+ name: 'UluToast',
55
+ components: {
56
+ UluIcon
57
+ },
58
+ props: {
59
+ /**
60
+ * Toast configuration
61
+ */
62
+ toast: Object,
63
+ /**
64
+ * Icons for each element { icon, header, content, date, actions, action, closeButton, title, body, closeButton }
65
+ */
66
+ classes: {
67
+ type: Object,
68
+ default: () => ({
69
+ content: "type-small",
70
+ date: "type-small-x",
71
+ actions: "type-small-x",
72
+ action: "button button--small button--outline",
73
+ closeButton: "button button--icon button--transparent"
74
+ })
75
+ }
76
+ },
77
+ methods: {
78
+ handleAction(event, action) {
79
+ const { toast } = this;
80
+ this.toast.close();
81
+ this.$nextTick(() => {
82
+ action(event, toast, action);
83
+ });
84
+ }
85
+ }
86
+ }
87
+ </script>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <Teleport :to="pluginOptions.teleportTo">
3
+ <TransitionGroup
4
+ class="toast-container"
5
+ :class="classes"
6
+ name="toast"
7
+ tag="div"
8
+ >
9
+ <component
10
+ v-for="toast in toasts"
11
+ :key="toast.uid"
12
+ :is="toast.component"
13
+ :toast="toast"
14
+ />
15
+ </TransitionGroup>
16
+ </Teleport>
17
+ </template>
18
+
19
+ <script>
20
+ import { store } from "./store.js";
21
+ export default {
22
+ name: 'UluTooltipDisplay',
23
+ data() {
24
+ const { toasts, pluginOptions } = store;
25
+ return { toasts, pluginOptions };
26
+ },
27
+ computed: {
28
+ classes() {
29
+ const { position } = this.pluginOptions;
30
+ const positionClasses = position.map(p => `toast-container--${ p }`);
31
+ return positionClasses;
32
+ }
33
+ }
34
+ }
35
+ </script>
@@ -0,0 +1,198 @@
1
+ ////
2
+ /// @group toast
3
+ /// Toast notifications
4
+ ////
5
+
6
+ @use "sass:map";
7
+ @use "sass:meta";
8
+
9
+ @use "@ulu/frontend/scss/selector";
10
+ @use "@ulu/frontend/scss/utils";
11
+ @use "@ulu/frontend/scss/color";
12
+ @use "@ulu/frontend/scss/element";
13
+ @use "@ulu/frontend/scss/layout";
14
+ @use "@ulu/frontend/scss/button";
15
+ @use "@ulu/frontend/scss/typography";
16
+ @use "@ulu/frontend/scss/cssvar";
17
+
18
+ // Used for function fallback
19
+ $-fallbacks: (
20
+ "box-shadow" : (
21
+ "function" : meta.get-function("get", false, "element"),
22
+ "property" : "box-shadow-above"
23
+ ),
24
+ "border-radius": (
25
+ "function": meta.get-function("get", false, "button"),
26
+ "property": "border-radius"
27
+ ),
28
+ "z-index": (
29
+ "function": meta.get-function("get", false, "layout"),
30
+ "property": "z-index-fixed"
31
+ ),
32
+ "date-font-weight": (
33
+ "function": meta.get-function("get", false, "typography"),
34
+ "property": "font-weight-light"
35
+ )
36
+ );
37
+
38
+ /// Module Settings
39
+ /// @type Map
40
+ /// @prop {CssValue} z-index [true] - Z-index of the toast container
41
+ /// @prop {CssValue} box-shadow [true] - Box shadow for the toast
42
+ /// @prop {Color} background-color [white] - Background color of the toast
43
+ /// @prop {CssValue} border-radius [true] - Border radius of the toast
44
+ /// @prop {CssValue} border-width [5px] - Border width of the toast
45
+ /// @prop {Color} border-color [transparent] - Border color of the toast
46
+ /// @prop {CssValue} padding [0 0 0 1rem] - Padding of the toast
47
+ /// @prop {CssValue} line-height [1] - Line height of the toast
48
+ /// @prop {CssValue} margin-bottom [0.5rem] - Margin bottom of the toast
49
+ /// @prop {CssValue} container-top [1rem] - Top position of the toast container
50
+ /// @prop {CssValue} container-right [1rem] - Right position of the toast container
51
+ /// @prop {CssValue} container-width [min(24rem, 100vw - 2rem)] - Width of the toast container
52
+ /// @prop {Color} date-color ["type-tertiary"] - Color of the date
53
+ /// @prop {CssValue} date-font-weight [true] - Font weight of the date
54
+ /// @prop {CssValue} icon-margin-right [0.7rem] - Margin right of the icon
55
+ /// @prop {CssValue} icon-font-size [1.2rem] - Font size of the icon
56
+ /// @prop {CssValue} actions-margin-right [3px] - Margin right of the actions container
57
+ /// @prop {CssValue} action-margin-top [3px] - Margin top of the action buttons
58
+ /// @prop {CssValue} content-padding [0.25rem 0.5rem 0.25rem 0] - Padding of the content
59
+ /// @prop {CssValue} persistent-animation [UluWiggle 4s infinite] - Animation for persistent toasts
60
+
61
+ $config: (
62
+ "z-index": true,
63
+ "box-shadow": true,
64
+ "background-color": white,
65
+ "border-radius": true,
66
+ "border-width": 5px,
67
+ "border-color": transparent,
68
+ "padding": 0 0 0 1rem,
69
+ "line-height": 1,
70
+ "margin-bottom": 0.5rem,
71
+ "container-top": 1rem,
72
+ "container-right": 1rem,
73
+ "container-width": min(24rem, 100vw - 2rem),
74
+ "date-color": "type-tertiary",
75
+ "date-font-weight": true,
76
+ "icon-margin-right": 0.7rem,
77
+ "icon-font-size": 1.2rem,
78
+ "actions-margin-right": 3px,
79
+ "action-margin-top": 3px,
80
+ "content-padding": (0.25rem 0.5rem 0.25rem 0),
81
+ "persistent-animation": (UluWiggle 4s infinite),
82
+ ) !default;
83
+
84
+ /// Change modules $config
85
+ /// @param {Map} $changes Map of changes
86
+ /// @example scss
87
+ /// @include ulu-vue.toast-set(( "property" : value ));
88
+
89
+ @mixin set($changes) {
90
+ $config: map.merge($config, $changes) !global;
91
+ }
92
+
93
+ /// Get a config option
94
+ /// @param {Map} $name Name of property
95
+ /// @example scss
96
+ /// @include ulu.toast-get("property");
97
+
98
+ @function get($name) {
99
+ $value: utils.require-map-get($config, $name, "toast [config]");
100
+ @return utils.function-fallback($name, $value, $-fallbacks);
101
+ }
102
+
103
+ /// Prints component styles
104
+ /// @demo toast
105
+ /// @example scss
106
+ /// @include ulu.toast-styles();
107
+
108
+ @mixin styles {
109
+ $prefix: selector.class("toast");
110
+
111
+ #{ $prefix }-container {
112
+ position: fixed;
113
+ top: get("container-top");
114
+ right: get("container-right");
115
+ width: get("container-width");
116
+ z-index: get("z-index");
117
+ }
118
+
119
+ #{ $prefix } {
120
+ box-shadow: get("box-shadow");
121
+ background-color: get("background-color");
122
+ border-radius: get("border-radius");
123
+ border: get("border-width") solid get("border-color");
124
+ padding: get("padding");
125
+ line-height: get("line-height");
126
+ margin-bottom: get("margin-bottom");
127
+ display: flex;
128
+ align-items: center;
129
+ }
130
+
131
+ #{ $prefix }__header {
132
+ display: flex;
133
+ justify-content: space-between;
134
+ align-items: baseline;
135
+ }
136
+
137
+ #{ $prefix }__date {
138
+ color: get("date-color");
139
+ font-weight: get("date-font-weight");
140
+ margin-left: 1em;
141
+ }
142
+
143
+ #{ $prefix }__icon {
144
+ margin-right: get("icon-margin-right");
145
+ font-size: get("icon-font-size");
146
+ }
147
+
148
+ #{ $prefix }__actions {
149
+ flex-basis: min-content;
150
+ display: flex;
151
+ flex-direction: column;
152
+ justify-content: center;
153
+ align-items: center;
154
+ margin-right: get("actions-margin-right");
155
+ }
156
+
157
+ #{ $prefix }__action {
158
+ width: 100%;
159
+ margin: 0;
160
+ & + & {
161
+ margin-top: get("action-margin-top");
162
+ }
163
+ }
164
+
165
+ #{ $prefix }__close {
166
+ margin: 0;
167
+ }
168
+
169
+ #{ $prefix }__content {
170
+ margin-right: auto;
171
+ flex-grow: 1;
172
+ padding: get("content-padding");
173
+ }
174
+
175
+ #{ $prefix }--persistent {
176
+ animation: get("persistent-animation");
177
+ &:hover,
178
+ &:focus-within {
179
+ animation: none;
180
+ }
181
+ }
182
+
183
+ // Vue animation
184
+ #{ $prefix }--animation-move,
185
+ #{ $prefix }--animation-enter-active,
186
+ #{ $prefix }--animation-leave-active {
187
+ transition: all 0.3s ease;
188
+ }
189
+ #{ $prefix }--animation-enter-from,
190
+ #{ $prefix }--animation-leave-to {
191
+ opacity: 0;
192
+ transform: translateX(30px);
193
+ }
194
+ #{ $prefix }--animation-leave-active {
195
+ position: absolute;
196
+ width: 100%;
197
+ }
198
+ }
@@ -0,0 +1,30 @@
1
+ import { markRaw } from "vue";
2
+ import ToastComponent from "./UluToast.vue";
3
+ /**
4
+ * Default plugin options
5
+ */
6
+ export default {
7
+ toastOptions: {
8
+ /**
9
+ * Component used to render the toast in the display
10
+ */
11
+ component: markRaw(ToastComponent),
12
+ /**
13
+ * Duration of toast
14
+ */
15
+ duration: 6000, // 8.5s
16
+ /**
17
+ * Array of actions { label, click }
18
+ */
19
+ actions: [],
20
+ },
21
+ pluginOptions: {
22
+ componentName: "UluToast",
23
+ componentNameDisplay: "UluToastDisplay",
24
+ teleportTo: "body",
25
+ /**
26
+ * Position of the toast container (holds toasts)
27
+ */
28
+ position: ["top", "right"],
29
+ }
30
+ };
@@ -0,0 +1,17 @@
1
+ import { store, api } from "./store.js";
2
+ import UluToast from "./UluToast.vue";
3
+ import UluToastDisplay from "./UluToastDisplay.vue";
4
+
5
+ /**
6
+ * Install plugin
7
+ */
8
+ export default function install(app, userOptions = {}) {
9
+ const options = store.setPluginOptions(userOptions?.plugin);
10
+ store.setToastOptions(userOptions?.toast);
11
+
12
+ app.component(options.componentName, UluToast);
13
+ app.component(options.componentNameDisplay, UluToastDisplay);
14
+
15
+ app.config.globalProperties.$uluToast = api;
16
+ app.provide('uluToast', api);
17
+ }
@@ -0,0 +1,71 @@
1
+ import { reactive } from "vue";
2
+ import defaults from "./defaults.js";
3
+
4
+ const { assign: merge } = Object;
5
+ let counter = 0;
6
+
7
+ /**
8
+ * Reactive State Object (used inside global components, and as API globally)
9
+ */
10
+ export const store = reactive({
11
+ toasts: [],
12
+ /**
13
+ * Saveable
14
+ */
15
+ pluginOptions: defaults.pluginOptions,
16
+ toastOptions: defaults.toastOptions,
17
+ setToastOptions(options) {
18
+ this.toastOptions = merge({}, this.toastOptions, options);
19
+ return this.pluginOptions;
20
+ },
21
+ setPluginOptions(options) {
22
+ this.pluginOptions = merge({}, this.pluginOptions, options);
23
+ return this.pluginOptions;
24
+ },
25
+ createToast(options) {
26
+ const uid = `toast-${ ++counter }`;
27
+ return merge({}, this.toastOptions, options, {
28
+ uid,
29
+ close() {
30
+ api.remove(uid);
31
+ }
32
+ });
33
+ }
34
+ });
35
+
36
+ /**
37
+ * Public API
38
+ */
39
+ export const api = {
40
+ /**
41
+ *
42
+ * @param {Object} options Toast options
43
+ * @returns Toast object (to be used to remove)
44
+ */
45
+ add(options) {
46
+ const toast = store.createToast(options);
47
+ store.toasts.unshift(toast);
48
+ if (toast.duration) {
49
+ setTimeout(() => {
50
+ this.remove(toast.uid);
51
+ }, toast.duration);
52
+ }
53
+ return toast;
54
+ },
55
+ /**
56
+ *
57
+ * @param {Object} toast Toast uid
58
+ */
59
+ remove(uid) {
60
+ const index = store.toasts.findIndex(t => t.uid === uid);
61
+ if (index > -1) {
62
+ store.toasts.splice(index, 1);
63
+ }
64
+ },
65
+ /**
66
+ * Remove all toasts
67
+ */
68
+ removeAll() {
69
+ store.toasts = [];
70
+ },
71
+ };
@@ -0,0 +1,18 @@
1
+ import { inject } from 'vue';
2
+
3
+ /**
4
+ * Composable for accessing the toast API.
5
+ * @returns {object} The toast API.
6
+ * @throws {Error} If the toast plugin is not installed.
7
+ * @example
8
+ * import { useToast } from './useToast';
9
+ * const toast = useToast();
10
+ * toast.add({ title: 'Hello World' });
11
+ */
12
+ export const useToast = () => {
13
+ const toast = inject('uluToast');
14
+ if (!toast) {
15
+ throw new Error('Toast plugin not installed');
16
+ }
17
+ return toast;
18
+ };