@ulu/frontend-vue 0.2.0-beta.8 → 0.3.0
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.
- package/dist/components/collapsible/UluAccordionGroup.vue.d.ts +2 -2
- package/dist/components/collapsible/UluAccordionGroup.vue.d.ts.map +1 -1
- package/dist/components/collapsible/UluAccordionGroup.vue.js +22 -19
- package/dist/components/collapsible/UluDropdown.vue.d.ts +1 -1
- package/dist/components/collapsible/UluDropdown.vue.d.ts.map +1 -1
- package/dist/components/collapsible/UluDropdown.vue.js +22 -15
- package/dist/components/collapsible/UluModal.vue.d.ts +43 -248
- package/dist/components/collapsible/UluModal.vue.d.ts.map +1 -1
- package/dist/components/collapsible/UluModal.vue.js +139 -191
- package/dist/components/collapsible/UluTabGroup.vue.d.ts +2 -0
- package/dist/components/collapsible/UluTabGroup.vue.d.ts.map +1 -1
- package/dist/components/collapsible/UluTabGroup.vue.js +23 -14
- package/dist/components/elements/UluAlert.vue.d.ts +29 -144
- package/dist/components/elements/UluAlert.vue.d.ts.map +1 -1
- package/dist/components/elements/UluAlert.vue.js +39 -50
- package/dist/components/elements/UluBadge.vue.d.ts +6 -6
- package/dist/components/elements/UluBadgeStack.vue.d.ts +1 -1
- package/dist/components/elements/UluBadgeStack.vue.d.ts.map +1 -1
- package/dist/components/elements/UluBadgeStack.vue.js +12 -9
- package/dist/components/elements/UluButton.vue.d.ts +47 -177
- package/dist/components/elements/UluButton.vue.d.ts.map +1 -1
- package/dist/components/elements/UluButton.vue.js +59 -72
- package/dist/components/elements/UluButtonVerbose.vue.d.ts +38 -123
- package/dist/components/elements/UluButtonVerbose.vue.d.ts.map +1 -1
- package/dist/components/elements/UluButtonVerbose.vue.js +52 -65
- package/dist/components/elements/UluCallout.vue.d.ts +20 -25
- package/dist/components/elements/UluCallout.vue.d.ts.map +1 -1
- package/dist/components/elements/UluCallout.vue.js +11 -16
- package/dist/components/elements/UluCaptionedFigure.vue.d.ts +25 -0
- package/dist/components/elements/UluCaptionedFigure.vue.d.ts.map +1 -0
- package/dist/components/elements/UluCaptionedFigure.vue.js +48 -0
- package/dist/components/elements/UluCard.vue.d.ts +2 -2
- package/dist/components/elements/UluDefinitionList.vue.d.ts +4 -2
- package/dist/components/elements/UluDefinitionList.vue.d.ts.map +1 -1
- package/dist/components/elements/UluDefinitionList.vue.js +32 -28
- package/dist/components/elements/UluExternalLink.vue.d.ts +2 -2
- package/dist/components/elements/UluImage.vue.d.ts +14 -0
- package/dist/components/elements/UluImage.vue.d.ts.map +1 -0
- package/dist/components/elements/UluImage.vue.js +53 -0
- package/dist/components/elements/UluList.vue.d.ts.map +1 -1
- package/dist/components/elements/UluList.vue.js +14 -13
- package/dist/components/elements/UluOverflowScroller.vue.d.ts +49 -0
- package/dist/components/elements/UluOverflowScroller.vue.d.ts.map +1 -0
- package/dist/components/elements/UluOverflowScroller.vue.js +138 -0
- package/dist/components/elements/UluScrollSlider.vue.d.ts +38 -0
- package/dist/components/elements/UluScrollSlider.vue.d.ts.map +1 -0
- package/dist/components/elements/UluScrollSlider.vue.js +146 -0
- package/dist/components/elements/UluSlider.vue.d.ts +57 -0
- package/dist/components/elements/UluSlider.vue.d.ts.map +1 -0
- package/dist/components/elements/UluSlider.vue.js +277 -0
- package/dist/components/forms/UluFormFile.vue.d.ts +2 -2
- package/dist/components/forms/UluFormRadio.vue.d.ts +4 -4
- package/dist/components/index.d.ts +6 -0
- package/dist/components/layout/UluTitleRail.vue.d.ts +29 -87
- package/dist/components/layout/UluTitleRail.vue.d.ts.map +1 -1
- package/dist/components/layout/UluTitleRail.vue.js +51 -46
- package/dist/components/navigation/UluBreadcrumb.vue.d.ts +27 -68
- package/dist/components/navigation/UluBreadcrumb.vue.d.ts.map +1 -1
- package/dist/components/navigation/UluBreadcrumb.vue.js +51 -54
- package/dist/components/navigation/UluMenu.vue.d.ts +30 -138
- package/dist/components/navigation/UluMenu.vue.d.ts.map +1 -1
- package/dist/components/navigation/UluMenu.vue.js +85 -84
- package/dist/components/navigation/UluMenuStack.vue.d.ts +12 -2
- package/dist/components/navigation/UluMenuStack.vue.d.ts.map +1 -1
- package/dist/components/navigation/UluMenuStack.vue.js +26 -18
- package/dist/components/navigation/UluNavStrip.vue.d.ts +22 -134
- package/dist/components/navigation/UluNavStrip.vue.d.ts.map +1 -1
- package/dist/components/navigation/UluNavStrip.vue.js +43 -31
- package/dist/components/systems/facets/UluFacetsSidebarLayout.vue.js +10 -10
- package/dist/components/systems/facets/useFacets.d.ts +3 -0
- package/dist/components/systems/facets/useFacets.d.ts.map +1 -1
- package/dist/components/systems/facets/useFacets.js +124 -112
- package/dist/components/systems/index.d.ts +0 -3
- package/dist/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts +2 -2
- package/dist/components/systems/table-sticky/UluTableSticky.vue.d.ts +504 -432
- package/dist/components/systems/table-sticky/UluTableSticky.vue.d.ts.map +1 -1
- package/dist/components/systems/table-sticky/UluTableSticky.vue.js +313 -456
- package/dist/components/systems/table-sticky/UluTableStickyRows.vue.d.ts +40 -31
- package/dist/components/systems/table-sticky/UluTableStickyRows.vue.d.ts.map +1 -1
- package/dist/components/systems/table-sticky/UluTableStickyRows.vue.js +43 -45
- package/dist/components/systems/table-sticky/UluTableStickyTable.vue.d.ts +60 -146
- package/dist/components/systems/table-sticky/UluTableStickyTable.vue.d.ts.map +1 -1
- package/dist/components/systems/table-sticky/UluTableStickyTable.vue.js +156 -175
- package/dist/components/utils/UluAction.vue.d.ts +36 -0
- package/dist/components/utils/UluAction.vue.d.ts.map +1 -0
- package/dist/components/utils/UluAction.vue.js +59 -0
- package/dist/components/utils/UluConditionalText.vue.d.ts +7 -26
- package/dist/components/utils/UluConditionalText.vue.d.ts.map +1 -1
- package/dist/components/utils/UluConditionalText.vue.js +12 -14
- package/dist/components/utils/UluConditionalWrapper.vue.d.ts.map +1 -1
- package/dist/components/utils/UluConditionalWrapper.vue.js +11 -9
- package/dist/components/utils/UluPlaceholderImage.vue.d.ts +12 -57
- package/dist/components/utils/UluPlaceholderImage.vue.d.ts.map +1 -1
- package/dist/components/utils/UluPlaceholderImage.vue.js +18 -26
- package/dist/components/utils/UluPlaceholderText.vue.d.ts +6 -20
- package/dist/components/utils/UluPlaceholderText.vue.js +12 -14
- package/dist/components/utils/UluRouteAnnouncer.vue.d.ts +9 -58
- package/dist/components/utils/UluRouteAnnouncer.vue.d.ts.map +1 -1
- package/dist/components/utils/UluRouteAnnouncer.vue.js +28 -28
- package/dist/components/visualizations/UluAnimateNumber.vue.d.ts +20 -14
- package/dist/components/visualizations/UluAnimateNumber.vue.d.ts.map +1 -1
- package/dist/components/visualizations/UluAnimateNumber.vue.js +18 -26
- package/dist/components/visualizations/UluProgressCircle.vue.d.ts +2 -2
- package/dist/composables/useModifiers.d.ts +20 -25
- package/dist/composables/useModifiers.d.ts.map +1 -1
- package/dist/index.js +206 -200
- package/dist/plugins/modals/UluModalsDisplay.vue.d.ts +3 -12
- package/dist/plugins/modals/UluModalsDisplay.vue.js +24 -45
- package/dist/plugins/modals/index.js +6 -6
- package/dist/plugins/toast/UluToast.vue.d.ts +24 -49
- package/dist/plugins/toast/UluToast.vue.d.ts.map +1 -1
- package/dist/plugins/toast/UluToast.vue.js +68 -77
- package/dist/plugins/toast/UluToastDisplay.vue.d.ts +1 -9
- package/dist/plugins/toast/UluToastDisplay.vue.js +27 -35
- package/dist/plugins/toast/defaults.d.ts +40 -35
- package/dist/plugins/toast/defaults.js +2 -2
- package/dist/plugins/toast/index.js +4 -4
- package/dist/plugins/toast/store.d.ts +40 -35
- package/dist/plugins/toast/store.d.ts.map +1 -1
- package/dist/utils/props.d.ts +7 -0
- package/dist/utils/props.d.ts.map +1 -0
- package/dist/utils/props.js +6 -0
- package/lib/components/collapsible/UluAccordionGroup.vue +4 -1
- package/lib/components/collapsible/UluDropdown.vue +5 -1
- package/lib/components/collapsible/UluModal.vue +278 -298
- package/lib/components/collapsible/UluTabGroup.vue +21 -6
- package/lib/components/elements/UluAlert.vue +38 -51
- package/lib/components/elements/UluBadgeStack.vue +4 -1
- package/lib/components/elements/UluButton.vue +105 -129
- package/lib/components/elements/UluButtonVerbose.vue +67 -89
- package/lib/components/elements/UluCallout.vue +15 -19
- package/lib/components/elements/UluCaptionedFigure.vue +40 -0
- package/lib/components/elements/UluDefinitionList.vue +27 -6
- package/lib/components/elements/UluImage.vue +56 -0
- package/lib/components/elements/UluList.vue +1 -0
- package/lib/components/elements/UluOverflowScroller.vue +140 -0
- package/lib/components/elements/UluScrollSlider.vue +150 -0
- package/lib/components/elements/UluSlider.vue +488 -0
- package/lib/components/index.js +10 -0
- package/lib/components/layout/UluTitleRail.vue +55 -48
- package/lib/components/navigation/UluBreadcrumb.vue +29 -34
- package/lib/components/navigation/UluMenu.vue +60 -71
- package/lib/components/navigation/UluMenuStack.vue +6 -1
- package/lib/components/navigation/UluNavStrip.vue +43 -31
- package/lib/components/systems/facets/useFacets.js +33 -17
- package/lib/components/systems/index.js +0 -4
- package/lib/components/systems/table-sticky/UluTableSticky.vue +602 -576
- package/lib/components/systems/table-sticky/UluTableStickyRows.vue +16 -27
- package/lib/components/systems/table-sticky/UluTableStickyTable.vue +95 -96
- package/lib/components/utils/UluAction.vue +81 -0
- package/lib/components/utils/UluConditionalText.vue +13 -16
- package/lib/components/utils/UluConditionalWrapper.vue +5 -1
- package/lib/components/utils/UluPlaceholderImage.vue +44 -46
- package/lib/components/utils/UluPlaceholderText.vue +10 -13
- package/lib/components/utils/UluRouteAnnouncer.vue +59 -47
- package/lib/components/visualizations/UluAnimateNumber.vue +23 -30
- package/lib/composables/useModifiers.js +21 -26
- package/lib/plugins/modals/UluModalsDisplay.vue +44 -45
- package/lib/plugins/toast/UluToast.vue +28 -34
- package/lib/plugins/toast/UluToastDisplay.vue +9 -15
- package/lib/utils/props.js +8 -0
- package/package.json +9 -5
- package/dist/components/systems/slider/UluImageSlideShow.vue.d.ts +0 -130
- package/dist/components/systems/slider/UluImageSlideShow.vue.d.ts.map +0 -1
- package/dist/components/systems/slider/UluImageSlideShow.vue.js +0 -73
- package/dist/components/systems/slider/UluSlideShow.vue.d.ts +0 -205
- package/dist/components/systems/slider/UluSlideShow.vue.d.ts.map +0 -1
- package/dist/components/systems/slider/UluSlideShow.vue.js +0 -292
- package/dist/components/systems/slider/UluSlideShowSlide.vue.d.ts +0 -17
- package/dist/components/systems/slider/UluSlideShowSlide.vue.d.ts.map +0 -1
- package/dist/components/systems/slider/UluSlideShowSlide.vue.js +0 -26
- package/lib/components/systems/slider/UluImageSlideShow.vue +0 -75
- package/lib/components/systems/slider/UluSlideShow.vue +0 -336
- package/lib/components/systems/slider/UluSlideShowSlide.vue +0 -25
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
@cancel.prevent="close"
|
|
15
15
|
@close="handleDialogCloseEvent"
|
|
16
16
|
@click="handleClick"
|
|
17
|
-
@toggle="handleToggle"
|
|
18
17
|
>
|
|
19
18
|
<header
|
|
20
19
|
v-if="hasHeader"
|
|
@@ -68,321 +67,302 @@
|
|
|
68
67
|
</Teleport>
|
|
69
68
|
</template>
|
|
70
69
|
|
|
71
|
-
<script>
|
|
72
|
-
import { useSlots, computed } from "vue";
|
|
70
|
+
<script setup>
|
|
71
|
+
import { useSlots, computed, ref, onMounted, onBeforeUnmount, watch, nextTick } from "vue";
|
|
73
72
|
import UluIcon from "../elements/UluIcon.vue";
|
|
74
73
|
import { useModifiers } from "../../composables/useModifiers.js";
|
|
75
74
|
import { wasClickOutside, preventScroll as setupPreventScroll } from "@ulu/utils/browser/dom.js";
|
|
76
|
-
import { Resizer } from "@ulu/frontend";
|
|
75
|
+
import { Resizer, observeDialogToggle } from "@ulu/frontend";
|
|
77
76
|
import { newId } from "../../utils/dom.js";
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
const emit = defineEmits(["update:modelValue", "close", "open"]);
|
|
79
|
+
|
|
80
|
+
const props = defineProps({
|
|
81
|
+
/**
|
|
82
|
+
* Controls the visibility of the modal (for v-model).
|
|
83
|
+
*/
|
|
84
|
+
modelValue: Boolean,
|
|
85
|
+
/**
|
|
86
|
+
* Target for Vue's Teleport. Defaults to 'body'.
|
|
87
|
+
* Set to `false` to disable teleporting (modal renders inline).
|
|
88
|
+
* Set to `null` or `undefined` for `body` fallback with disabled as false.
|
|
89
|
+
*/
|
|
90
|
+
teleport: {
|
|
91
|
+
type: [String, Boolean, Object], // Allow string for target selector, or false to disable, or object (Dome node)
|
|
92
|
+
default: "body"
|
|
83
93
|
},
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Target for Vue's Teleport. Defaults to 'body'.
|
|
92
|
-
* Set to `false` to disable teleporting (modal renders inline).
|
|
93
|
-
* Set to `null` or `undefined` for `body` fallback with disabled as false.
|
|
94
|
-
*/
|
|
95
|
-
teleport: {
|
|
96
|
-
type: [String, Boolean, Object], // Allow string for target selector, or false to disable, or object (Dome node)
|
|
97
|
-
default: 'body'
|
|
98
|
-
},
|
|
99
|
-
/**
|
|
100
|
-
* When open and not non-modal, the body is prevented from scrolling (defaults to true).
|
|
101
|
-
*/
|
|
102
|
-
preventScroll: {
|
|
103
|
-
type: Boolean,
|
|
104
|
-
default: true
|
|
105
|
-
},
|
|
106
|
-
/**
|
|
107
|
-
* Compensate for layout shift when preventing scroll. Which adds padding equal to scrollbars
|
|
108
|
-
* width while dialog is open
|
|
109
|
-
*/
|
|
110
|
-
preventScrollShift: {
|
|
111
|
-
type: Boolean,
|
|
112
|
-
default: true
|
|
113
|
-
},
|
|
114
|
-
/**
|
|
115
|
-
* Use non-modal interface for dialog
|
|
116
|
-
*/
|
|
117
|
-
nonModal: Boolean,
|
|
118
|
-
/**
|
|
119
|
-
* Close modal on click outside
|
|
120
|
-
*/
|
|
121
|
-
clickOutsideCloses: {
|
|
122
|
-
type: Boolean,
|
|
123
|
-
default: true
|
|
124
|
-
},
|
|
125
|
-
/**
|
|
126
|
-
* Enable resizer
|
|
127
|
-
*/
|
|
128
|
-
allowResize: Boolean,
|
|
129
|
-
/**
|
|
130
|
-
* Position (any position that modal.scss supports)
|
|
131
|
-
*/
|
|
132
|
-
position: {
|
|
133
|
-
type: String,
|
|
134
|
-
default: "center"
|
|
135
|
-
},
|
|
136
|
-
/**
|
|
137
|
-
* If `true`, the modal body will fill the available space.
|
|
138
|
-
*/
|
|
139
|
-
bodyFills: Boolean,
|
|
140
|
-
/**
|
|
141
|
-
* If `true`, no backdrop will be displayed behind the modal
|
|
142
|
-
*/
|
|
143
|
-
noBackdrop: Boolean,
|
|
144
|
-
/**
|
|
145
|
-
* If `true`, the modal will not have a minimum height
|
|
146
|
-
*/
|
|
147
|
-
noMinHeight: Boolean,
|
|
148
|
-
/**
|
|
149
|
-
* Set aria-labelledby by element id (to add accessible label)
|
|
150
|
-
* - Use this if you are not using the default modal title (custom titles)
|
|
151
|
-
*/
|
|
152
|
-
labelledby: String,
|
|
153
|
-
/**
|
|
154
|
-
* Set aria-describedby by element id (to add accessible description)
|
|
155
|
-
* - This is usually content you passed into the modal body (paragraph/etc)
|
|
156
|
-
*/
|
|
157
|
-
describedby: String,
|
|
158
|
-
/**
|
|
159
|
-
* Text for modal title in header (can use title slot as well for complex markup), if not passed the header will be omitted
|
|
160
|
-
*/
|
|
161
|
-
title: String,
|
|
162
|
-
/**
|
|
163
|
-
* Optional icon for before title (uses UluIcon interface)
|
|
164
|
-
*/
|
|
165
|
-
titleIcon: String,
|
|
166
|
-
/**
|
|
167
|
-
* Default icon for resizer
|
|
168
|
-
*/
|
|
169
|
-
resizerIcon: String,
|
|
170
|
-
/**
|
|
171
|
-
* Default icon for close button (uses UluIcon interface)
|
|
172
|
-
*/
|
|
173
|
-
closeIcon: String,
|
|
174
|
-
/**
|
|
175
|
-
* Classes for elements ({ container, header, title, body, footer })
|
|
176
|
-
* - Any valid class binding value per element
|
|
177
|
-
*/
|
|
178
|
-
classes: {
|
|
179
|
-
type: Object,
|
|
180
|
-
default: () => ({
|
|
181
|
-
close: "button button--icon"
|
|
182
|
-
})
|
|
183
|
-
},
|
|
184
|
-
/**
|
|
185
|
-
* Modifiers (to add any modifier classes based on base class [ie. 'tertiary'])
|
|
186
|
-
*/
|
|
187
|
-
modifiers: [String, Array]
|
|
94
|
+
/**
|
|
95
|
+
* When open and not non-modal, the body is prevented from scrolling (defaults to true).
|
|
96
|
+
*/
|
|
97
|
+
preventScroll: {
|
|
98
|
+
type: Boolean,
|
|
99
|
+
default: true
|
|
188
100
|
},
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Compensate for layout shift when preventing scroll. Which adds padding equal to scrollbars
|
|
103
|
+
* width while dialog is open
|
|
104
|
+
*/
|
|
105
|
+
preventScrollShift: {
|
|
106
|
+
type: Boolean,
|
|
107
|
+
default: true
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Use non-modal interface for dialog
|
|
111
|
+
*/
|
|
112
|
+
nonModal: Boolean,
|
|
113
|
+
/**
|
|
114
|
+
* Close modal on click outside
|
|
115
|
+
*/
|
|
116
|
+
clickOutsideCloses: {
|
|
117
|
+
type: Boolean,
|
|
118
|
+
default: true
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Enable resizer
|
|
122
|
+
*/
|
|
123
|
+
allowResize: Boolean,
|
|
124
|
+
/**
|
|
125
|
+
* Position (any position that modal.scss supports)
|
|
126
|
+
*/
|
|
127
|
+
position: {
|
|
128
|
+
type: String,
|
|
129
|
+
default: "center"
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* If `true`, the modal body will fill the available space.
|
|
133
|
+
*/
|
|
134
|
+
bodyFills: Boolean,
|
|
135
|
+
/**
|
|
136
|
+
* If `true`, no backdrop will be displayed behind the modal
|
|
137
|
+
*/
|
|
138
|
+
noBackdrop: Boolean,
|
|
139
|
+
/**
|
|
140
|
+
* If `true`, the modal will not have a minimum height
|
|
141
|
+
*/
|
|
142
|
+
noMinHeight: Boolean,
|
|
143
|
+
/**
|
|
144
|
+
* Set aria-labelledby by element id (to add accessible label)
|
|
145
|
+
* - Use this if you are not using the default modal title (custom titles)
|
|
146
|
+
*/
|
|
147
|
+
labelledby: String,
|
|
148
|
+
/**
|
|
149
|
+
* Set aria-describedby by element id (to add accessible description)
|
|
150
|
+
* - This is usually content you passed into the modal body (paragraph/etc)
|
|
151
|
+
*/
|
|
152
|
+
describedby: String,
|
|
153
|
+
/**
|
|
154
|
+
* Text for modal title in header (can use title slot as well for complex markup), if not passed the header will be omitted
|
|
155
|
+
*/
|
|
156
|
+
title: String,
|
|
157
|
+
/**
|
|
158
|
+
* Optional icon for before title (uses UluIcon interface)
|
|
159
|
+
*/
|
|
160
|
+
titleIcon: String,
|
|
161
|
+
/**
|
|
162
|
+
* Default icon for resizer
|
|
163
|
+
*/
|
|
164
|
+
resizerIcon: String,
|
|
165
|
+
/**
|
|
166
|
+
* Default icon for close button (uses UluIcon interface)
|
|
167
|
+
*/
|
|
168
|
+
closeIcon: String,
|
|
169
|
+
/**
|
|
170
|
+
* Classes for elements ({ container, header, title, body, footer })
|
|
171
|
+
* - Any valid class binding value per element
|
|
172
|
+
*/
|
|
173
|
+
classes: {
|
|
174
|
+
type: Object,
|
|
175
|
+
default: () => ({
|
|
176
|
+
close: "button button--icon"
|
|
177
|
+
})
|
|
197
178
|
},
|
|
198
|
-
|
|
199
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Modifiers (to add any modifier classes based on base class [ie. 'tertiary'])
|
|
181
|
+
*/
|
|
182
|
+
modifiers: [String, Array],
|
|
183
|
+
/**
|
|
184
|
+
* If true, modal is forced to fullscreen on mobile viewports
|
|
185
|
+
*/
|
|
186
|
+
fullscreenMobile: Boolean
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const slots = useSlots();
|
|
190
|
+
|
|
191
|
+
const containerWidth = ref(null);
|
|
192
|
+
const titleId = newId("ulu-modal-title");
|
|
193
|
+
const isResizing = ref(false);
|
|
194
|
+
|
|
195
|
+
const container = ref(null);
|
|
196
|
+
const resizer = ref(null);
|
|
197
|
+
|
|
198
|
+
const hasHeader = computed(() => props.title || slots.title);
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
* Flag for if resizer script should be enabled
|
|
205
|
-
* - Resizer only available for left and right
|
|
206
|
-
*/
|
|
207
|
-
const resizerEnabled = computed(() => {
|
|
208
|
-
const { allowResize, position } = props;
|
|
209
|
-
if (!allowResize || !position) return;
|
|
200
|
+
const resizerEnabled = computed(() => {
|
|
201
|
+
const { allowResize, position } = props;
|
|
202
|
+
if (!allowResize || !position) return false;
|
|
210
203
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
204
|
+
const resizablePositions = ["left", "right", "center"];
|
|
205
|
+
if (resizablePositions.includes(position)) {
|
|
206
|
+
return true;
|
|
207
|
+
} else {
|
|
208
|
+
console.warn(`Passed invalid position for resize (${ position }), use ${ resizablePositions.join(", ") }`);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const resizerIconType = computed(() => {
|
|
214
|
+
return props.position === "center" ? "type:resizeBoth" : "type:resizeHorizontal";
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const internalModifiers = computed(() => ({
|
|
218
|
+
[props.position]: props.position,
|
|
219
|
+
"resize": props.allowResize,
|
|
220
|
+
"no-resize": !props.allowResize,
|
|
221
|
+
"no-header": !hasHeader.value,
|
|
222
|
+
"body-fills": props.bodyFills,
|
|
223
|
+
"no-backdrop": props.noBackdrop,
|
|
224
|
+
"no-min-height": props.noMinHeight,
|
|
225
|
+
"non-modal": props.nonModal,
|
|
226
|
+
"resizer-active": resizerEnabled.value,
|
|
227
|
+
"fullscreen-mobile": props.fullscreenMobile,
|
|
228
|
+
}));
|
|
229
|
+
|
|
230
|
+
const { resolvedModifiers } = useModifiers({
|
|
231
|
+
props: props,
|
|
232
|
+
baseClass: "modal",
|
|
233
|
+
internal: internalModifiers
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const resolvedLabelledby = computed(() => {
|
|
237
|
+
return props.labelledby ? props.labelledby : titleId;
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const close = () => {
|
|
241
|
+
emit("update:modelValue", false);
|
|
242
|
+
emit("close");
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const handleDialogCloseEvent = () => {
|
|
246
|
+
if (props.modelValue) {
|
|
247
|
+
emit("update:modelValue", false);
|
|
248
|
+
emit("close");
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const handleClick = (event) => {
|
|
253
|
+
if (props.clickOutsideCloses && !isResizing.value) {
|
|
254
|
+
const { target } = event;
|
|
255
|
+
if (target === container.value && wasClickOutside(container.value, event)) {
|
|
256
|
+
close();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
let toggleObserver = null;
|
|
262
|
+
let restoreScroll = null;
|
|
263
|
+
let resizerInstance = null;
|
|
264
|
+
let handleResizerStart = null;
|
|
265
|
+
let handleResizerEnd = null;
|
|
266
|
+
|
|
267
|
+
const setupToggleObserver = () => {
|
|
268
|
+
if (!props.nonModal && props.preventScroll) {
|
|
269
|
+
toggleObserver = observeDialogToggle(container.value, (isOpen) => {
|
|
270
|
+
if (isOpen) {
|
|
271
|
+
restoreScroll = setupPreventScroll({ preventShift: props.preventScrollShift });
|
|
214
272
|
} else {
|
|
215
|
-
|
|
216
|
-
return false;
|
|
273
|
+
destroyPreventScroll();
|
|
217
274
|
}
|
|
218
275
|
});
|
|
276
|
+
}
|
|
277
|
+
};
|
|
219
278
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
[props.position]: props.position,
|
|
227
|
-
"resize" : props.allowResize,
|
|
228
|
-
"no-resize" : !props.allowResize,
|
|
229
|
-
"no-header" : !hasHeader.value,
|
|
230
|
-
"body-fills" : props.bodyFills,
|
|
231
|
-
"no-backdrop" : props.noBackdrop,
|
|
232
|
-
"no-min-height" : props.noMinHeight,
|
|
233
|
-
"non-modal" : props.nonModal,
|
|
234
|
-
"resizer-active" : resizerEnabled.value,
|
|
235
|
-
}));
|
|
279
|
+
const destroyToggleObserver = () => {
|
|
280
|
+
if (toggleObserver) {
|
|
281
|
+
toggleObserver.destroy();
|
|
282
|
+
toggleObserver = null;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
236
285
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
286
|
+
const destroyPreventScroll = () => {
|
|
287
|
+
if (restoreScroll) {
|
|
288
|
+
restoreScroll();
|
|
289
|
+
restoreScroll = null;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
242
292
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
293
|
+
const setupResizer = () => {
|
|
294
|
+
if (resizerEnabled.value) {
|
|
295
|
+
const options = props.position === "center" ?
|
|
296
|
+
{ fromX: "right", fromY: "bottom", multiplier: 2 } :
|
|
297
|
+
{ fromX: props.position === "right" ? "left" : "right" };
|
|
298
|
+
resizerInstance = new Resizer(container.value, resizer.value, options);
|
|
299
|
+
handleResizerStart = () => {
|
|
300
|
+
isResizing.value = true;
|
|
248
301
|
};
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
this.setupResizer();
|
|
279
|
-
});
|
|
280
|
-
} else {
|
|
281
|
-
this.destroyResizer();
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
position(newValue, oldValue) {
|
|
286
|
-
if (newValue !== oldValue) {
|
|
287
|
-
this.destroyResizer();
|
|
288
|
-
this.$nextTick(() => {
|
|
289
|
-
this.setupResizer();
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
methods: {
|
|
295
|
-
close() {
|
|
296
|
-
// Emit 'update:modelValue' to inform parent to set modelValue to false
|
|
297
|
-
// This will trigger the watch handler above to call this.$refs.container.close()
|
|
298
|
-
this.$emit("update:modelValue", false);
|
|
299
|
-
this.$emit("close"); // Also emit a generic 'close' event for convenience
|
|
300
|
-
},
|
|
301
|
-
handleDialogCloseEvent() {
|
|
302
|
-
// Ensure modelValue is false, primarily for scenarios where dialog is closed
|
|
303
|
-
// by user agent (e.g., form submission within dialog) or direct native API call
|
|
304
|
-
// that bypasses `this.close()` or Escape key.
|
|
305
|
-
if (this.modelValue) { // Only emit if it was open based on modelValue
|
|
306
|
-
this.$emit("update:modelValue", false);
|
|
307
|
-
this.$emit("close");
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
handleClick(event) {
|
|
311
|
-
if (this.clickOutsideCloses && !this.isResizing) {
|
|
312
|
-
const { target } = event;
|
|
313
|
-
const { container } = this.$refs;
|
|
314
|
-
if (target === container && wasClickOutside(container, event)) {
|
|
315
|
-
this.close();
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
setupPreventScroll() {
|
|
320
|
-
const { body } = document;
|
|
321
|
-
this.bodyOverflowValue = body.style.overflow;
|
|
322
|
-
this.bodyPaddingRightValue = body.style.paddingRight;
|
|
323
|
-
},
|
|
324
|
-
destroyPreventScroll() {
|
|
325
|
-
if (this.restoreScroll) {
|
|
326
|
-
this.restoreScroll();
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
handleToggle(event) {
|
|
330
|
-
if (!this.nonModal && this.preventScroll) {
|
|
331
|
-
const { preventScrollShift: preventShift } = this;
|
|
332
|
-
const isOpen = event.newState === "open";
|
|
333
|
-
if (isOpen) {
|
|
334
|
-
this.restoreScroll = setupPreventScroll({ preventShift });
|
|
335
|
-
} else {
|
|
336
|
-
this.destroyPreventScroll();
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
setupResizer() {
|
|
341
|
-
const { position, resizerEnabled } = this;
|
|
342
|
-
if (resizerEnabled) {
|
|
343
|
-
const { container, resizer } = this.$refs;
|
|
344
|
-
const options = position === "center" ?
|
|
345
|
-
{ fromX: "right", fromY: "bottom", multiplier: 2 } :
|
|
346
|
-
{ fromX: position === "right" ? "left" : "right" };
|
|
347
|
-
this.resizerInstance = new Resizer(container, resizer, options);
|
|
348
|
-
this.handleResizerStart = () => {
|
|
349
|
-
this.isResizing = true;
|
|
350
|
-
};
|
|
351
|
-
this.handleResizerEnd = () => {
|
|
352
|
-
// After click has ended (next in event loop)
|
|
353
|
-
setTimeout(() => { this.isResizing = false; }, 0)
|
|
354
|
-
};
|
|
355
|
-
container.addEventListener("ulu:resizer:start", this.handleResizerStart);
|
|
356
|
-
container.addEventListener("ulu:resizer:end", this.handleResizerEnd);
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
destroyResizer() {
|
|
360
|
-
const { container } = this.$refs;
|
|
361
|
-
if (this.resizerInstance) {
|
|
362
|
-
this.resizerInstance.destroy();
|
|
363
|
-
this.resizerInstance = null;
|
|
364
|
-
}
|
|
365
|
-
if (this.handleResizerStart) {
|
|
366
|
-
container.removeEventListener("ulu:resizer:start", this.handleResizerStart);
|
|
367
|
-
}
|
|
368
|
-
if (this.handleResizerEnd) {
|
|
369
|
-
container.removeEventListener("ulu:resizer:end", this.handleResizerEnd);
|
|
302
|
+
handleResizerEnd = () => {
|
|
303
|
+
setTimeout(() => { isResizing.value = false; }, 0);
|
|
304
|
+
};
|
|
305
|
+
container.value.addEventListener("ulu:resizer:start", handleResizerStart);
|
|
306
|
+
container.value.addEventListener("ulu:resizer:end", handleResizerEnd);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const destroyResizer = () => {
|
|
311
|
+
if (resizerInstance) {
|
|
312
|
+
resizerInstance.destroy();
|
|
313
|
+
resizerInstance = null;
|
|
314
|
+
}
|
|
315
|
+
if (handleResizerStart && container.value) {
|
|
316
|
+
container.value.removeEventListener("ulu:resizer:start", handleResizerStart);
|
|
317
|
+
}
|
|
318
|
+
if (handleResizerEnd && container.value) {
|
|
319
|
+
container.value.removeEventListener("ulu:resizer:end", handleResizerEnd);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
watch(() => props.modelValue, (newValue) => {
|
|
324
|
+
nextTick(() => {
|
|
325
|
+
if (container.value) {
|
|
326
|
+
if (newValue) {
|
|
327
|
+
container.value[props.nonModal ? "show" : "showModal"]();
|
|
328
|
+
emit("open");
|
|
329
|
+
} else {
|
|
330
|
+
container.value.close();
|
|
370
331
|
}
|
|
371
332
|
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
container.close();
|
|
383
|
-
}
|
|
384
|
-
this.destroyPreventScroll();
|
|
385
|
-
this.destroyResizer();
|
|
333
|
+
});
|
|
334
|
+
}, { immediate: true });
|
|
335
|
+
|
|
336
|
+
watch(resizerEnabled, (newValue) => {
|
|
337
|
+
if (newValue) {
|
|
338
|
+
nextTick(() => {
|
|
339
|
+
setupResizer();
|
|
340
|
+
});
|
|
341
|
+
} else {
|
|
342
|
+
destroyResizer();
|
|
386
343
|
}
|
|
387
|
-
};
|
|
344
|
+
}, { immediate: false });
|
|
345
|
+
|
|
346
|
+
watch(() => props.position, (newValue, oldValue) => {
|
|
347
|
+
if (newValue !== oldValue) {
|
|
348
|
+
destroyResizer();
|
|
349
|
+
nextTick(() => {
|
|
350
|
+
setupResizer();
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
onMounted(() => {
|
|
356
|
+
setupToggleObserver();
|
|
357
|
+
setupResizer();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
onBeforeUnmount(() => {
|
|
361
|
+
if (container.value && container.value.open) {
|
|
362
|
+
container.value.close();
|
|
363
|
+
}
|
|
364
|
+
destroyToggleObserver();
|
|
365
|
+
destroyPreventScroll();
|
|
366
|
+
destroyResizer();
|
|
367
|
+
});
|
|
388
368
|
</script>
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TabGroup
|
|
2
|
+
<TabGroup
|
|
3
|
+
v-slot="slotProps"
|
|
4
|
+
:defaultIndex="defaultIndex"
|
|
5
|
+
:vertical="vertical"
|
|
6
|
+
>
|
|
3
7
|
<div
|
|
8
|
+
v-bind="$attrs"
|
|
4
9
|
class="tabs"
|
|
5
|
-
:class="
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
:class="[
|
|
11
|
+
resolvedModifiers,
|
|
12
|
+
{
|
|
13
|
+
'tabs--vertical' : vertical
|
|
14
|
+
}
|
|
15
|
+
]"
|
|
8
16
|
>
|
|
9
17
|
<slot v-bind="slotProps"/>
|
|
10
18
|
</div>
|
|
@@ -13,12 +21,13 @@
|
|
|
13
21
|
|
|
14
22
|
<script setup>
|
|
15
23
|
import { TabGroup } from "@headlessui/vue";
|
|
24
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
16
25
|
|
|
17
26
|
defineOptions({
|
|
18
27
|
inheritAttrs: false
|
|
19
28
|
});
|
|
20
29
|
|
|
21
|
-
defineProps({
|
|
30
|
+
const props = defineProps({
|
|
22
31
|
/**
|
|
23
32
|
* Active tab index by default
|
|
24
33
|
*/
|
|
@@ -26,6 +35,12 @@
|
|
|
26
35
|
/**
|
|
27
36
|
* Whether or not to use vertical layout
|
|
28
37
|
*/
|
|
29
|
-
vertical: Boolean
|
|
38
|
+
vertical: Boolean,
|
|
39
|
+
/**
|
|
40
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
41
|
+
*/
|
|
42
|
+
modifiers: [String, Array]
|
|
30
43
|
});
|
|
44
|
+
|
|
45
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "tabs" });
|
|
31
46
|
</script>
|