message.vue 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <template>
  2. <div class="message modal-content" :class="{ multiline: /\n/.test(message.text) }">
  3. <div class="mb-1" v-if="message.text" v-text="message.text"></div>
  4. <form v-if="message.buttons" @submit.prevent>
  5. <!-- eslint-disable-next-line vue/no-mutating-props -->
  6. <input class="mb-1" type="text" v-if="message.input !== false" v-model="message.input">
  7. <div class="mr-1c">
  8. <button
  9. v-for="(button, index) in message.buttons"
  10. :key="index"
  11. :type="button.type || 'button'"
  12. v-text="button.text"
  13. @click="onButtonClick(button)"
  14. />
  15. </div>
  16. </form>
  17. </div>
  18. </template>
  19. <script>
  20. const dismissers = [];
  21. window.addEventListener('keydown', (e) => {
  22. if (e.keyCode === 27 && dismissers.length) {
  23. e.stopImmediatePropagation();
  24. dismissers.pop()();
  25. }
  26. }, true);
  27. export default {
  28. props: ['message'],
  29. created() {
  30. dismissers.push(this.dismiss);
  31. },
  32. mounted() {
  33. const input = this.$el.querySelector('input');
  34. if (input) {
  35. setTimeout(() => {
  36. input.focus();
  37. });
  38. }
  39. },
  40. beforeUnmount() {
  41. const i = dismissers.indexOf(this.dismiss);
  42. if (i >= 0) dismissers.splice(i, 1);
  43. },
  44. methods: {
  45. onButtonClick(button) {
  46. const { onClick } = button;
  47. if (onClick) {
  48. if (onClick(this.message.input) !== false) this.dismiss();
  49. }
  50. },
  51. onBackdropClick() {
  52. const { onBackdropClick } = this.message;
  53. if (onBackdropClick) {
  54. if (onBackdropClick() !== false) this.dismiss();
  55. }
  56. },
  57. dismiss() {
  58. this.$emit('dismiss');
  59. },
  60. },
  61. };
  62. </script>
  63. <style>
  64. .message {
  65. width: 18rem;
  66. white-space: pre-wrap;
  67. overflow-wrap: break-word;
  68. border-bottom-left-radius: .2rem;
  69. border-bottom-right-radius: .2rem;
  70. box-shadow: 0 0 .2rem rgba(0,0,0,.2);
  71. &.multiline {
  72. width: auto;
  73. max-width: 50vw;
  74. &::first-line {
  75. font-weight: bold;
  76. text-decoration: underline;
  77. }
  78. }
  79. input {
  80. width: 100%;
  81. }
  82. }
  83. </style>