@teammodlr/ui-kit 2.1.67 → 2.1.69

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teammodlr/ui-kit",
3
- "version": "2.1.67",
3
+ "version": "2.1.69",
4
4
  "description": "",
5
5
  "main": "lib/index.cjs.js",
6
6
  "module": "lib/index.es.js",
@@ -1,38 +1,39 @@
1
1
  <template>
2
2
  <div ref="wrapper" class="m-color-picker">
3
3
  <div ref="referenceRef" @click="isOpen = !isOpen">
4
- <slot :r="finalColor.r" :g="finalColor.g" :b="finalColor.b" :a="finalColor.a" :hex="hexInput" :transparent="style.transparent">
4
+ <slot :r="finalColor.r" :g="finalColor.g" :b="finalColor.b" :a="finalColor.a" :hex="hexInput"
5
+ :transparent="style.transparent">
5
6
  <div>
6
7
  <div :class="style.referenceColor"
7
- :style="{ backgroundColor: `rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, ${finalColor.a})` }">
8
+ :style="{ backgroundColor: `rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, ${finalColor.a})` }">
8
9
  </div>
9
10
  </div>
10
11
  </slot>
11
12
  </div>
12
13
  <Teleport to="body">
13
14
  <transition :enter-active-class="scale.enterActive" :leave-active-class="scale.leaveActive"
14
- :enter-from-class="scale.enterFrom" :leave-to-class="scale.leaveTo">
15
+ :enter-from-class="scale.enterFrom" :leave-to-class="scale.leaveTo">
15
16
  <div :class="style.container" v-if="isOpen" ref="popper" :style="{ zIndex: zIndex }">
16
17
  <div ref="picker" @mousedown="handleMouseDown" :class="style.colours"
17
- :style="`background: rgb(${mainColor.r}, ${mainColor.g}, ${mainColor.b});`">
18
+ :style="`background: rgb(${mainColor.r}, ${mainColor.g}, ${mainColor.b});`">
18
19
  <div :class="style.whiteGradient"></div>
19
20
  <div :class="style.blackGradient"></div>
20
21
  <div :class="style.sliderThumb" @mousedown="handleMouseDown" @dragover.prevent=""
21
- :style="{ left: `${position.x * 100}%`, top: `${position.y * 100}%` }"></div>
22
+ :style="{ left: `${position.x * 100}%`, top: `${position.y * 100}%` }"></div>
22
23
  </div>
23
24
 
24
25
  <div :class="style.colorActions">
25
26
  <template v-if="canPickColor">
26
27
  <button role="button" :disabled="!canPickColor" :class="style.eyeDrop"
27
- @click="openEyeDropper">
28
+ @click="openEyeDropper">
28
29
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none"
29
- xmlns="http://www.w3.org/2000/svg">
30
+ xmlns="http://www.w3.org/2000/svg">
30
31
  <path
31
32
  d="M20.3847 2.87868C19.2132 1.70711 17.3137 1.70711 16.1421 2.87868L14.0202 5.00052L13.313 4.29332C12.9225 3.9028 12.2894 3.9028 11.8988 4.29332C11.5083 4.68385 11.5083 5.31701 11.8988 5.70754L17.5557 11.3644C17.9462 11.7549 18.5794 11.7549 18.9699 11.3644C19.3604 10.9739 19.3604 10.3407 18.9699 9.95018L18.2629 9.24316L20.3847 7.12132C21.5563 5.94975 21.5563 4.05025 20.3847 2.87868Z"
32
- fill="currentColor"/>
33
+ fill="currentColor" />
33
34
  <path fill-rule="evenodd" clip-rule="evenodd"
34
- d="M11.9297 7.09116L4.1515 14.8693C3.22786 15.793 3.03239 17.169 3.5651 18.2842L1.99994 19.8493L3.41415 21.2635L4.97931 19.6984C6.09444 20.2311 7.4705 20.0356 8.39414 19.112L16.1723 11.3338L11.9297 7.09116ZM13.3439 11.3338L11.9297 9.91959L5.56571 16.2835C5.17518 16.6741 5.17518 17.3072 5.56571 17.6978C5.95623 18.0883 6.5894 18.0883 6.97992 17.6978L13.3439 11.3338Z"
35
- fill="currentColor"/>
35
+ d="M11.9297 7.09116L4.1515 14.8693C3.22786 15.793 3.03239 17.169 3.5651 18.2842L1.99994 19.8493L3.41415 21.2635L4.97931 19.6984C6.09444 20.2311 7.4705 20.0356 8.39414 19.112L16.1723 11.3338L11.9297 7.09116ZM13.3439 11.3338L11.9297 9.91959L5.56571 16.2835C5.17518 16.6741 5.17518 17.3072 5.56571 17.6978C5.95623 18.0883 6.5894 18.0883 6.97992 17.6978L13.3439 11.3338Z"
36
+ fill="currentColor" />
36
37
  </svg>
37
38
  </button>
38
39
  </template>
@@ -44,12 +45,12 @@
44
45
  </div>
45
46
  </template>
46
47
  <div style="width: 100%; display: flex; flex-direction: column; gap: 10px;">
47
- <MSlider v-model="hueSlider"
48
- background="linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000)">
48
+ <MSlider v-model="hueSlider" @change="onSliderChangeComplete"
49
+ background="linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000)">
49
50
  </MSlider>
50
51
 
51
- <MSlider v-model="opacitySlider"
52
- :background="`linear-gradient(to right, rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, 0), rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, 1))`">
52
+ <MSlider v-model="opacitySlider" @change="onSliderChangeComplete"
53
+ :background="`linear-gradient(to right, rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, 0), rgba(${finalColor.r}, ${finalColor.g}, ${finalColor.b}, 1))`">
53
54
  </MSlider>
54
55
  </div>
55
56
  </div>
@@ -57,26 +58,26 @@
57
58
  <div :class="style.colorActions">
58
59
  <template v-if="rgbOrHex">
59
60
  <MInput @keyup.enter="updateFromRGB" @blur="updateFromRGB" block ref="rInputElement"
60
- v-model="rInput" name="r" placeholder="R"/>
61
+ v-model="rInput" name="r" placeholder="R" />
61
62
  <MInput @keyup.enter="updateFromRGB" @blur="updateFromRGB" block ref="gInputElement"
62
- v-model="gInput" name="g" placeholder="G"/>
63
+ v-model="gInput" name="g" placeholder="G" />
63
64
  <MInput @keyup.enter="updateFromRGB" @blur="updateFromRGB" block ref="bInputElement"
64
- v-model="bInput" name="b" placeholder="B"/>
65
+ v-model="bInput" name="b" placeholder="B" />
65
66
  <MInput @keyup.enter="updateFromRGB" @blur="updateFromRGB" block ref="aInputElement"
66
- v-model="aInput" name="a" placeholder="A"/>
67
+ v-model="aInput" name="a" placeholder="A" />
67
68
  </template>
68
69
  <template v-else>
69
70
  <MInput @keyup.enter="updateFromHex" @blur="updateFromHex" block ref="hexInputElement"
70
- v-model="hexInput" name="hex" placeholder="#00000000"/>
71
+ v-model="hexInput" name="hex" placeholder="#00000000" />
71
72
  </template>
72
73
 
73
74
  <MButton icon @click.prevent="rgbOrHex = !rgbOrHex">
74
75
 
75
76
  <svg style="width: 18px; height: 18px;" xmlns="http://www.w3.org/2000/svg"
76
- viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
77
+ viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
77
78
  <path fill-rule="evenodd"
78
- d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
79
- clip-rule="evenodd"/>
79
+ d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
80
+ clip-rule="evenodd" />
80
81
  </svg>
81
82
 
82
83
  </MButton>
@@ -88,14 +89,14 @@
88
89
  </template>
89
90
 
90
91
  <script lang="ts">
91
- import {onClickOutside, useEyeDropper, useMouseInElement, useMousePressed} from '@vueuse/core';
92
- import {computed, defineComponent, onMounted, type PropType, reactive, ref, toRef, watch} from "vue";
92
+ import { onClickOutside, useEyeDropper, useMouseInElement, useMousePressed } from '@vueuse/core';
93
+ import { computed, defineComponent, onMounted, type PropType, reactive, ref, toRef, watch } from "vue";
93
94
  import * as style from './style';
94
- import {scale} from "../../styles/transitions.css";
95
- import {hexToRGB, type HSV, HSVToRGBA, HueToRGBA, RGBAToHex, RGBToHSV} from './utils';
96
- import {usePopper} from "../../composables/usePopper";
97
- import type {Placement} from "@popperjs/core";
98
- import {useZIndex} from "../../composables/useZIndex";
95
+ import { scale } from "../../styles/transitions.css";
96
+ import { hexToRGB, type HSV, HSVToRGBA, HueToRGBA, RGBAToHex, RGBToHSV } from './utils';
97
+ import { usePopper } from "../../composables/usePopper";
98
+ import type { Placement } from "@popperjs/core";
99
+ import { useZIndex } from "../../composables/useZIndex";
99
100
  import MSlider from "../../components/slider/Slider.vue";
100
101
  import MButton from "../../components/button/Button.vue";
101
102
  import MInput from "../../components/input/Input.vue";
@@ -107,6 +108,10 @@ export default defineComponent({
107
108
  type: String,
108
109
  default: "#FFFFFF"
109
110
  },
111
+ modelModifiers: {
112
+ type: Object,
113
+ default: () => ({})
114
+ },
110
115
  transfer: {
111
116
  type: Boolean,
112
117
  default: false
@@ -129,9 +134,10 @@ export default defineComponent({
129
134
  MInput,
130
135
  MButton
131
136
  },
132
- setup(props, {emit}) {
133
- const {isSupported: canPickColor, open: openEyeDrop, sRGBHex: eyeDropColor} = useEyeDropper();
134
- const {nextZIndex} = useZIndex();
137
+ setup(props, { emit }) {
138
+ const modelModifiers = props.modelModifiers;
139
+ const { isSupported: canPickColor, open: openEyeDrop, sRGBHex: eyeDropColor } = useEyeDropper();
140
+ const { nextZIndex } = useZIndex();
135
141
  const isOpen = ref(false);
136
142
  const rgbOrHex = ref<boolean>(false);
137
143
  const hexInput = ref("");
@@ -139,6 +145,7 @@ export default defineComponent({
139
145
  const gInput = ref("");
140
146
  const bInput = ref("");
141
147
  const aInput = ref("");
148
+ const internalValue = ref(props.modelValue);
142
149
 
143
150
  const picker = ref<HTMLElement>();
144
151
  const wrapper = ref<HTMLElement>();
@@ -155,9 +162,9 @@ export default defineComponent({
155
162
  });
156
163
  const zIndex = ref(props.zIndex ?? nextZIndex());
157
164
 
158
- const {elementX, elementY} = useMouseInElement(picker);
159
- const {pressed} = useMousePressed();
160
- const {popper, transferTo, updatePopper} = usePopper({
165
+ const { elementX, elementY } = useMouseInElement(picker);
166
+ const { pressed } = useMousePressed();
167
+ const { popper, transferTo, updatePopper } = usePopper({
161
168
  reference: referenceRef,
162
169
  placement,
163
170
  transfer,
@@ -181,6 +188,10 @@ export default defineComponent({
181
188
  return HueToRGBA(hueSlider.value * 3.6, opacitySlider.value / 100);
182
189
  });
183
190
 
191
+ const emitModelValue = () => {
192
+ emit('update:modelValue', hexInput.value);
193
+ };
194
+
184
195
  const setInputs = () => {
185
196
  hexInput.value = RGBAToHex(finalColor.value.r, finalColor.value.g, finalColor.value.b, finalColor.value.a);
186
197
  rInput.value = finalColor.value.r.toString();
@@ -188,7 +199,9 @@ export default defineComponent({
188
199
  bInput.value = finalColor.value.b.toString();
189
200
  aInput.value = finalColor.value.a.toFixed(2).toString();
190
201
 
191
- emit('update:modelValue', hexInput.value);
202
+ if (!modelModifiers.lazy) {
203
+ emitModelValue();
204
+ }
192
205
  };
193
206
 
194
207
  watch(() => finalColor.value, () => {
@@ -206,6 +219,9 @@ export default defineComponent({
206
219
  const updateFromHex = () => {
207
220
  let color = hexToRGB(hexInput.value, finalColor.value.r, finalColor.value.g, finalColor.value.b, finalColor.value.a);
208
221
  updateFromHSV(RGBToHSV(color.r, color.g, color.b), color.a);
222
+ if (modelModifiers.lazy) {
223
+ emitModelValue();
224
+ }
209
225
  }
210
226
 
211
227
  const updateFromRGB = () => {
@@ -230,6 +246,9 @@ export default defineComponent({
230
246
  }
231
247
 
232
248
  updateFromHSV(RGBToHSV(red, green, blue), alpha);
249
+ if (modelModifiers.lazy) {
250
+ emitModelValue();
251
+ }
233
252
  };
234
253
 
235
254
  watch(() => pressed.value, () => {
@@ -238,6 +257,12 @@ export default defineComponent({
238
257
  }
239
258
  });
240
259
 
260
+ watch(() => dragging.value, (newVal, oldVal) => {
261
+ if (oldVal && !newVal && modelModifiers.lazy) {
262
+ emitModelValue();
263
+ }
264
+ });
265
+
241
266
  watch(() => [elementX.value, elementY.value], () => {
242
267
  if (!dragging.value) {
243
268
  return;
@@ -246,18 +271,13 @@ export default defineComponent({
246
271
  setThumbPosition();
247
272
  });
248
273
 
249
- const setDefaultColor = () => {
250
- hexInput.value
251
- }
252
-
253
- watch(() => props.modelValue, (newValue) => {
274
+ watch(() => props.modelValue, () => {
254
275
  let val = props.modelValue;
255
- if (!newValue || newValue.trim() === "") {
256
- val = props.defaultColor || "#FFFFFF"
276
+ if (!val || val.trim() === "") {
277
+ val = props.defaultColor ?? "#FFFFFF"
257
278
  }
258
279
  hexInput.value = val;
259
280
  updateFromHex();
260
-
261
281
  });
262
282
 
263
283
  const setThumbPosition = () => {
@@ -292,6 +312,12 @@ export default defineComponent({
292
312
  }
293
313
  }
294
314
 
315
+ const onSliderChangeComplete = () => {
316
+ if (modelModifiers.lazy) {
317
+ emitModelValue();
318
+ }
319
+ }
320
+
295
321
  return {
296
322
  isOpen,
297
323
  popper,
@@ -323,7 +349,8 @@ export default defineComponent({
323
349
  zIndex,
324
350
  canPickColor,
325
351
  openEyeDropper,
326
- scale
352
+ scale,
353
+ onSliderChangeComplete
327
354
  };
328
355
  }
329
356
  })
@@ -1,12 +1,23 @@
1
1
  <template>
2
- <MColorPicker style="display: inline-block;">
3
- <template #default="{r,g,b,hex, transparent}">
4
- <div :class="transparent"
5
- style="width: 100px; height: 100px; border: 1px solid black; position: relative; overflow: hidden;">
6
- <div style="position: absolute; inset: 0" :style="{backgroundColor: `${hex}`}">
7
-
2
+ <div>
3
+ <p>Selected Color: {{ colorValue }}</p>
4
+ <MColorPicker v-model.lazy="colorValue" style="display: inline-block;">
5
+ <template #default="{ r, g, b, hex, transparent }">
6
+ <div :class="transparent"
7
+ style="width: 100px; height: 100px; border: 1px solid black; position: relative; overflow: hidden;">
8
+ <div style="position: absolute; inset: 0" :style="{ backgroundColor: hex }"></div>
8
9
  </div>
9
- </div>
10
- </template>
11
- </MColorPicker>
10
+ </template>
11
+ </MColorPicker>
12
+ </div>
12
13
  </template>
14
+
15
+ <script>
16
+ export default {
17
+ data() {
18
+ return {
19
+ colorValue: '#FFFFFF' // Initial color value
20
+ };
21
+ }
22
+ };
23
+ </script>
@@ -5,8 +5,9 @@
5
5
  :enter-active-class="fade.enterActive"
6
6
  :leave-active-class="fade.leaveActive"
7
7
  :enter-from-class="fade.enterFrom"
8
- :leave-to-class="fade.leaveTo">
9
- <div :class="style.root" v-if="open">
8
+ :leave-to-class="fade.leaveTo"
9
+ >
10
+ <div :class="style.root" v-if="open" :style="{ zIndex: zIndex, position: 'fixed', inset: '0', pointerEvents: modal ? 'all' : 'none' }">
10
11
  <div :class="backdropClasses" v-if="modal"></div>
11
12
  <div ref="wrapper" :class="wrapperClasses">
12
13
  <Transition
@@ -27,7 +28,7 @@
27
28
  <div :class="style.header" ref="handle">
28
29
  <div :class="style.title">
29
30
  <slot name="title">
30
- {{ title }}
31
+ {{ resolvedTitle }}
31
32
  </slot>
32
33
  </div>
33
34
  </div>
@@ -48,26 +49,33 @@
48
49
  </TransitionGroup>
49
50
  </Teleport>
50
51
  </template>
51
-
52
52
  <script lang="ts">
53
- import { fade, modalScale } from '../../styles/transitions.css';
54
- import {computed, defineComponent, ref, watch, nextTick, type CSSProperties} from "vue";
55
- import type { ComputedRef } from "vue";
53
+ import {fade, modalScale} from '../../styles/transitions.css';
54
+ import {
55
+ computed,
56
+ defineComponent,
57
+ ref,
58
+ watch,
59
+ nextTick,
60
+ isRef,
61
+ type CSSProperties, type PropType, type Ref,
62
+ } from 'vue';
63
+ import type {ComputedRef} from 'vue';
56
64
 
57
- import { useZIndex } from "../../composables/useZIndex";
58
- import { useDraggable } from "@vueuse/core";
59
- import * as style from "./style";
65
+ import {useZIndex} from '../../composables/useZIndex';
66
+ import {useDraggable} from '@vueuse/core';
67
+ import * as style from './style';
60
68
 
61
69
  export default defineComponent({
62
- name: "Dialog",
70
+ name: 'Dialog',
63
71
  props: {
64
72
  title: {
65
- type: String,
66
- default: ""
73
+ type: [String, Object] as PropType<string | Ref<string>>,
74
+ default: '',
67
75
  },
68
76
  draggable: {
69
77
  type: Boolean,
70
- default: true
78
+ default: true,
71
79
  },
72
80
  modal: {
73
81
  type: Boolean,
@@ -75,32 +83,36 @@ export default defineComponent({
75
83
  },
76
84
  onClose: {
77
85
  type: Function,
78
- default: () => {}
86
+ default: () => {
87
+ },
79
88
  },
80
89
  zIndex: {
81
- type: Number
90
+ type: Number,
82
91
  },
83
92
  width: {
84
93
  type: [Number, String],
85
- default: "500px"
94
+ default: '500px',
86
95
  },
87
96
  focusTrap: {
88
97
  type: Boolean,
89
- default: true
98
+ default: true,
90
99
  },
91
100
  open: {
92
- type: Boolean
93
- }
101
+ type: Boolean,
102
+ default: false,
103
+ },
94
104
  },
95
105
  emits: ['onOpen', 'onClose', 'update:open'],
96
- setup(props, { slots, emit }) {
106
+ setup(props, {emit, expose}) {
97
107
  const wrapper = ref<HTMLElement | null>(null);
98
108
  const dialog = ref<HTMLElement | null>(null);
99
109
  const handle = ref<HTMLElement | null>(null);
100
- const { nextZIndex } = useZIndex();
110
+ const {nextZIndex} = useZIndex();
101
111
  const zIndex = ref(props.zIndex ?? nextZIndex());
102
112
 
103
- const { x, y } = useDraggable(dialog, {
113
+ const isOpen = ref<boolean>(props.open);
114
+
115
+ const {x, y} = useDraggable(dialog, {
104
116
  handle,
105
117
  preventDefault: true,
106
118
  containerElement: wrapper,
@@ -108,6 +120,10 @@ export default defineComponent({
108
120
  onStart: onDragStart,
109
121
  });
110
122
 
123
+ const resolvedTitle = computed(() =>
124
+ isRef(props.title) ? props.title.value : props.title
125
+ );
126
+
111
127
  const backdropClasses = computed(() => ({
112
128
  [style.backdrop]: true,
113
129
  [style.backdropColor]: props.modal === true,
@@ -118,21 +134,25 @@ export default defineComponent({
118
134
  [style.notModal]: !props.modal,
119
135
  }));
120
136
 
121
- const width = computed(() => (
122
- typeof props.width === "number" ? `${props.width}px` : props.width
123
- ));
137
+ const width = computed(() =>
138
+ typeof props.width === 'number' ? `${props.width}px` : props.width,
139
+ );
124
140
 
125
141
  const computedStyle: ComputedRef<CSSProperties> = computed(() => ({
126
142
  position: 'fixed',
127
143
  left: `${x.value}px`,
128
144
  top: `${y.value}px`,
129
145
  width: width.value,
130
- zIndex: zIndex.value
146
+ zIndex: zIndex.value,
131
147
  }));
132
148
 
133
149
  function close() {
150
+ isOpen.value = false;
134
151
  emit('update:open', false);
135
152
  emit('onClose');
153
+ if (props.onClose) {
154
+ props.onClose();
155
+ }
136
156
  }
137
157
 
138
158
  function onEnter() {
@@ -140,41 +160,51 @@ export default defineComponent({
140
160
  zIndex.value = nextZIndex();
141
161
  }
142
162
 
143
- function onDragStart() {
144
- zIndex.value = nextZIndex();
145
- }
163
+ function onDragStart() {
164
+ zIndex.value = nextZIndex();
165
+ }
166
+
167
+ function centerDialog() {
168
+ if (dialog.value) {
169
+ const boundingRect = dialog.value.getBoundingClientRect();
170
+ x.value = (window.innerWidth - boundingRect.width) / 2;
171
+ y.value = (window.innerHeight - boundingRect.height) / 2;
172
+ }
173
+ }
146
174
 
147
- function centerDialog() {
148
- if (dialog.value) {
149
- const boundingRect = dialog.value.getBoundingClientRect();
150
- x.value = (window.innerWidth - boundingRect.width) / 2;
151
- y.value = (window.innerHeight - boundingRect.height) / 2;
152
- }
175
+ watch(
176
+ () => props.open,
177
+ async (newVal) => {
178
+ isOpen.value = newVal;
179
+ if (newVal) {
180
+ await nextTick();
181
+ centerDialog();
153
182
  }
183
+ },
184
+ {immediate: true},
185
+ );
154
186
 
155
- watch(() => props.open, async (newVal) => {
156
- if (newVal) {
157
- await nextTick();
158
- centerDialog();
159
- }
160
- }, { immediate: true });
161
-
162
- return {
163
- slots,
164
- wrapper,
165
- dialog,
166
- handle,
167
- zIndex,
168
- fade,
169
- modalScale,
170
- style,
171
- computedStyle,
172
- backdropClasses,
173
- wrapperClasses,
174
- close,
175
- onEnter,
176
- };
177
- }
187
+ // Expose methods to parent components
188
+ expose({
189
+ close,
178
190
  });
179
- </script>
180
191
 
192
+ return {
193
+ wrapper,
194
+ dialog,
195
+ handle,
196
+ zIndex,
197
+ fade,
198
+ modalScale,
199
+ style,
200
+ computedStyle,
201
+ backdropClasses,
202
+ resolvedTitle,
203
+ wrapperClasses,
204
+ isOpen,
205
+ close,
206
+ onEnter,
207
+ };
208
+ },
209
+ });
210
+ </script>
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <slot/>
3
+ <template v-if="Object.keys(dialogMap).length > 0">
4
+ <Teleport to="body">
5
+ <MDialog
6
+ v-for="dialog in Object.values(dialogMap)"
7
+ :key="dialog.key"
8
+ v-bind="dialog.options"
9
+ ref="setDialogRef(dialog.key)"
10
+ @close="remove(dialog.key)"
11
+ >
12
+ <MRenderer v-if="dialog.options.render" :h="dialog.options.render" :props="dialog.options.props" />
13
+ </MDialog>
14
+ </Teleport>
15
+ </template>
16
+ </template>
17
+ <script lang="ts">
18
+ import {defineComponent, reactive, provide, ref} from 'vue';
19
+ import type {DialogApiInjection, DialogOptions, DialogReactive} from './types';
20
+ import MDialog from '../dialog/Dialog.vue';
21
+ import MRenderer from '../renderer/renderer';
22
+
23
+ export default defineComponent({
24
+ name: 'DialogProvider',
25
+ components: {
26
+ MDialog,
27
+ MRenderer,
28
+ },
29
+ setup() {
30
+ const dialogMap = reactive<Record<string, DialogReactive>>({});
31
+ const dialogRefs = ref<Record<string, any>>({});
32
+
33
+ function setDialogRef(key: string) {
34
+ return (el: any) => {
35
+ if (el) {
36
+ dialogRefs.value[key] = el;
37
+ } else {
38
+ delete dialogRefs.value[key];
39
+ }
40
+ };
41
+ }
42
+
43
+ function create(key: string, options: DialogOptions = {}): DialogReactive {
44
+ if (dialogMap[key]) {
45
+ // Merge new options into existing reactive options
46
+ Object.assign(dialogMap[key].options, options);
47
+ return dialogMap[key];
48
+ }
49
+
50
+ // Make options reactive
51
+ const reactiveOptions = reactive(options);
52
+
53
+ const dialog: DialogReactive = {
54
+ key,
55
+ options: reactiveOptions,
56
+ open: () => {
57
+ const dialogComponent = dialogRefs.value[key];
58
+ if (dialogComponent && dialogComponent.open) {
59
+ dialogComponent.open();
60
+ } else {
61
+ dialog.options.open = true;
62
+ }
63
+ },
64
+ close: () => {
65
+ const dialogComponent = dialogRefs.value[key];
66
+ if (dialogComponent && dialogComponent.close) {
67
+ dialogComponent.close();
68
+ } else {
69
+ remove(key);
70
+ }
71
+ },
72
+ };
73
+
74
+ dialogMap[key] = dialog;
75
+ return dialog;
76
+ }
77
+
78
+ function remove(key: string) {
79
+ delete dialogMap[key];
80
+ delete dialogRefs.value[key];
81
+ }
82
+
83
+ const api: DialogApiInjection = {
84
+ create,
85
+ remove,
86
+ };
87
+
88
+ provide('m-dialog', api);
89
+
90
+ return {
91
+ dialogMap,
92
+ remove,
93
+ setDialogRef,
94
+ };
95
+ },
96
+ });
97
+ </script>