goodteditor-ui 1.0.26 → 1.0.28

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 (116) hide show
  1. package/.eslintrc.js +7 -7
  2. package/.prettierrc +14 -14
  3. package/README.md +35 -35
  4. package/babel.config.js +5 -5
  5. package/index.js +53 -53
  6. package/jsconfig.json +13 -13
  7. package/package.json +67 -67
  8. package/src/App.vue +36 -36
  9. package/src/components/ui/Avatar.md +68 -68
  10. package/src/components/ui/Avatar.vue +180 -180
  11. package/src/components/ui/Badge.md +20 -20
  12. package/src/components/ui/Badge.vue +75 -75
  13. package/src/components/ui/Collapse.md +90 -90
  14. package/src/components/ui/Collapse.vue +86 -86
  15. package/src/components/ui/ColorPicker/Alpha.vue +114 -114
  16. package/src/components/ui/ColorPicker/Colors.vue +117 -117
  17. package/src/components/ui/ColorPicker/Hue.vue +113 -113
  18. package/src/components/ui/ColorPicker/Preview.vue +55 -55
  19. package/src/components/ui/ColorPicker/Saturation.vue +123 -123
  20. package/src/components/ui/ColorPicker/mixin.js +105 -105
  21. package/src/components/ui/ColorPicker.md +17 -17
  22. package/src/components/ui/ColorPicker.vue +314 -314
  23. package/src/components/ui/Datalist.md +41 -41
  24. package/src/components/ui/Datalist.vue +164 -164
  25. package/src/components/ui/DatePicker.md +168 -168
  26. package/src/components/ui/DatePicker.vue +527 -527
  27. package/src/components/ui/FileSelector.md +105 -105
  28. package/src/components/ui/FileSelector.vue +82 -82
  29. package/src/components/ui/Grid.md +130 -130
  30. package/src/components/ui/Grid.vue +92 -92
  31. package/src/components/ui/Image.md +59 -59
  32. package/src/components/ui/Image.vue +57 -57
  33. package/src/components/ui/InputAutocomplete.md +115 -115
  34. package/src/components/ui/InputAutocomplete.vue +374 -349
  35. package/src/components/ui/InputColorPicker.md +51 -51
  36. package/src/components/ui/InputColorPicker.vue +151 -151
  37. package/src/components/ui/InputDatePicker.md +121 -121
  38. package/src/components/ui/InputDatePicker.vue +326 -326
  39. package/src/components/ui/InputTags.md +51 -51
  40. package/src/components/ui/InputTags.vue +184 -184
  41. package/src/components/ui/InputTimePicker.md +25 -25
  42. package/src/components/ui/InputTimePicker.vue +253 -253
  43. package/src/components/ui/InputUnits.md +20 -20
  44. package/src/components/ui/InputUnits.vue +257 -257
  45. package/src/components/ui/Lazy.md +37 -37
  46. package/src/components/ui/Lazy.vue +92 -92
  47. package/src/components/ui/Pagination.md +74 -74
  48. package/src/components/ui/Pagination.vue +138 -138
  49. package/src/components/ui/Paginator.md +34 -34
  50. package/src/components/ui/Paginator.vue +83 -83
  51. package/src/components/ui/Popover.md +34 -34
  52. package/src/components/ui/Popover.vue +274 -274
  53. package/src/components/ui/Popup.md +59 -59
  54. package/src/components/ui/Popup.vue +150 -150
  55. package/src/components/ui/ResponsiveContainer.md +58 -58
  56. package/src/components/ui/ResponsiveContainer.vue +99 -99
  57. package/src/components/ui/Select.md +187 -187
  58. package/src/components/ui/Select.vue +421 -421
  59. package/src/components/ui/TimePicker.md +50 -50
  60. package/src/components/ui/TimePicker.vue +252 -252
  61. package/src/components/ui/Tooltip.md +54 -54
  62. package/src/components/ui/Tooltip.vue +113 -113
  63. package/src/components/ui/WysiwygEditor/WysiwygEditor.d.ts +128 -128
  64. package/src/components/ui/WysiwygEditor/constants.js +273 -273
  65. package/src/components/ui/WysiwygEditor/extensions/blockquote.js +15 -15
  66. package/src/components/ui/WysiwygEditor/extensions/bold.js +15 -15
  67. package/src/components/ui/WysiwygEditor/extensions/bullet-list.js +15 -15
  68. package/src/components/ui/WysiwygEditor/extensions/code-block.js +13 -13
  69. package/src/components/ui/WysiwygEditor/extensions/code.js +13 -13
  70. package/src/components/ui/WysiwygEditor/extensions/font-size.js +34 -34
  71. package/src/components/ui/WysiwygEditor/extensions/formatting.js +14 -14
  72. package/src/components/ui/WysiwygEditor/extensions/heading.js +13 -13
  73. package/src/components/ui/WysiwygEditor/extensions/horizontal-rule.js +15 -15
  74. package/src/components/ui/WysiwygEditor/extensions/image.js +37 -33
  75. package/src/components/ui/WysiwygEditor/extensions/index.d.ts +32 -32
  76. package/src/components/ui/WysiwygEditor/extensions/index.js +32 -32
  77. package/src/components/ui/WysiwygEditor/extensions/italic.js +15 -15
  78. package/src/components/ui/WysiwygEditor/extensions/link.js +16 -16
  79. package/src/components/ui/WysiwygEditor/extensions/list-item.js +15 -15
  80. package/src/components/ui/WysiwygEditor/extensions/ordered-list.js +15 -15
  81. package/src/components/ui/WysiwygEditor/extensions/paragraph.js +23 -23
  82. package/src/components/ui/WysiwygEditor/extensions/strike.js +15 -15
  83. package/src/components/ui/WysiwygEditor/extensions/table-cell.js +13 -13
  84. package/src/components/ui/WysiwygEditor/extensions/table-header.js +15 -15
  85. package/src/components/ui/WysiwygEditor/extensions/table-row.js +15 -15
  86. package/src/components/ui/WysiwygEditor/extensions/table.js +29 -29
  87. package/src/components/ui/WysiwygEditor/extensions/text-align.js +6 -6
  88. package/src/components/ui/WysiwygEditor/extensions/text-style.js +12 -12
  89. package/src/components/ui/WysiwygEditor/extensions/underline.js +15 -15
  90. package/src/components/ui/WysiwygEditor/index.d.ts +4 -4
  91. package/src/components/ui/WysiwygEditor/index.js +4 -4
  92. package/src/components/ui/WysiwygEditor/renders/Button.vue +28 -28
  93. package/src/components/ui/WysiwygEditor/renders/ColorPicker.vue +41 -41
  94. package/src/components/ui/WysiwygEditor/renders/Image.vue +200 -162
  95. package/src/components/ui/WysiwygEditor/renders/InputAuto.vue +34 -34
  96. package/src/components/ui/WysiwygEditor/renders/InputUnits.vue +37 -37
  97. package/src/components/ui/WysiwygEditor/renders/Link.vue +82 -82
  98. package/src/components/ui/WysiwygEditor/renders/Select.vue +47 -47
  99. package/src/components/ui/WysiwygEditor/renders/ToolbarPopover.vue +49 -49
  100. package/src/components/ui/WysiwygEditor/renders/components/Popover.vue +15 -0
  101. package/src/components/ui/WysiwygEditor/renders/components/WithPopover.vue +35 -35
  102. package/src/components/ui/WysiwygEditor/renders/index.d.ts +8 -8
  103. package/src/components/ui/WysiwygEditor/renders/index.js +8 -8
  104. package/src/components/ui/WysiwygEditor/renders/mixins/RenderMixin.js +39 -39
  105. package/src/components/ui/WysiwygEditor/renders/mixins/index.js +1 -1
  106. package/src/components/ui/WysiwygEditor/tools-and-commands.js +709 -702
  107. package/src/components/ui/WysiwygEditor/utils.js +72 -72
  108. package/src/components/ui/WysiwygEditor.md +18 -18
  109. package/src/components/ui/WysiwygEditor.vue +266 -266
  110. package/src/components/ui/utils/FormComponent.js +107 -107
  111. package/src/components/ui/utils/Helpers.js +84 -84
  112. package/src/components/ui/utils/WithPopover.js +81 -81
  113. package/src/main.js +8 -8
  114. package/styleguide.config.js +37 -37
  115. package/vue.config.js +8 -8
  116. package/dist/js.png +0 -0
@@ -1,150 +1,150 @@
1
- <template>
2
- <div
3
- class="ui-popup popup popup-fixed"
4
- :class="{ fullscreen: fullscreen }"
5
- @click="onClick"
6
- v-if="visible"
7
- >
8
- <div class="popup-dialog" v-bind="dialog">
9
- <!--
10
- @slot Custom close slot
11
- @binding {Function} close closes the popup
12
- -->
13
- <slot name="close" v-bind="{ close }" v-if="showCloseButton">
14
- <div class="icon close" @click="close">
15
- <i class="mdi mdi-close" style="font-size: 1.25rem"></i>
16
- </div>
17
- </slot>
18
- <div class="popup-dialog-body" :class="{ 'pad-none': !usePadding }">
19
- <!--
20
- @slot Custom body slot
21
- @binding {Function} close closes the popup
22
- -->
23
- <slot name="body" v-bind="{ close }"></slot>
24
- </div>
25
- <div
26
- class="popup-dialog-footer"
27
- :class="{ 'pad-none': !usePadding }"
28
- v-if="$scopedSlots.footer"
29
- >
30
- <!--
31
- @slot Custom footer slot
32
- @binding {Function} close closes the popup
33
- -->
34
- <slot name="footer" v-bind="{ close }"></slot>
35
- </div>
36
- </div>
37
- </div>
38
- </template>
39
- <style lang="less" scoped>
40
- .ui-popup {
41
- &.fullscreen {
42
- .popup-dialog {
43
- display: flex;
44
- flex-direction: column;
45
- width: 100%;
46
- height: 100%;
47
- min-height: 100%;
48
- border-radius: 0;
49
- overflow: auto;
50
- &-body {
51
- flex: 1;
52
- height: 0;
53
- }
54
- }
55
- }
56
- }
57
- </style>
58
- <script>
59
- export default {
60
- props: {
61
- /**
62
- * Whether the popup is visible (.sync supported)
63
- */
64
- visible: {
65
- type: Boolean,
66
- default: false,
67
- },
68
- /**
69
- * Whether the popup is modal (clicking outside closes the popup)
70
- */
71
- modal: {
72
- type: Boolean,
73
- default: false,
74
- },
75
- /**
76
- * Whether the popup is fullscreen
77
- */
78
- fullscreen: {
79
- type: Boolean,
80
- default: false,
81
- },
82
- /**
83
- * Popup dialog options for styling css/style
84
- * { class:any style:any }
85
- */
86
- dialog: {
87
- type: Object,
88
- default() {
89
- return { class: {}, style: {} };
90
- },
91
- },
92
- /**
93
- * Whether to show the close button
94
- */
95
- showCloseButton: {
96
- type: Boolean,
97
- default: true,
98
- },
99
- /**
100
- * Whether the popup body/footer should have padding
101
- */
102
- usePadding: {
103
- type: Boolean,
104
- default: true,
105
- },
106
- /**
107
- * Css class which applies on 'body' node when the popup is visible
108
- */
109
- visibleBodyClass: {
110
- type: String,
111
- default: 'scroll-hide',
112
- },
113
- },
114
- watch: {
115
- visible: {
116
- handler(val) {
117
- if (!this.visibleBodyClass) {
118
- return;
119
- }
120
- let m = val ? 'add' : 'remove';
121
- document.body.classList[m](this.visibleBodyClass);
122
- },
123
- immediate: true,
124
- },
125
- },
126
- beforeDestroy() {
127
- if (this.visibleBodyClass) {
128
- document.body.classList.remove(this.visibleBodyClass);
129
- }
130
- },
131
- methods: {
132
- close() {
133
- /**
134
- * Close event
135
- */
136
- this.$emit('close');
137
- /**
138
- * Visibility update event (visible.sync compatibility)
139
- * @property {Boolean} visible
140
- */
141
- this.$emit('update:visible', false);
142
- },
143
- onClick(e) {
144
- if (!this.modal && e.target == this.$el) {
145
- this.close();
146
- }
147
- },
148
- },
149
- };
150
- </script>
1
+ <template>
2
+ <div
3
+ class="ui-popup popup popup-fixed"
4
+ :class="{ fullscreen: fullscreen }"
5
+ @click="onClick"
6
+ v-if="visible"
7
+ >
8
+ <div class="popup-dialog" v-bind="dialog">
9
+ <!--
10
+ @slot Custom close slot
11
+ @binding {Function} close closes the popup
12
+ -->
13
+ <slot name="close" v-bind="{ close }" v-if="showCloseButton">
14
+ <div class="icon close" @click="close">
15
+ <i class="mdi mdi-close" style="font-size: 1.25rem"></i>
16
+ </div>
17
+ </slot>
18
+ <div class="popup-dialog-body" :class="{ 'pad-none': !usePadding }">
19
+ <!--
20
+ @slot Custom body slot
21
+ @binding {Function} close closes the popup
22
+ -->
23
+ <slot name="body" v-bind="{ close }"></slot>
24
+ </div>
25
+ <div
26
+ class="popup-dialog-footer"
27
+ :class="{ 'pad-none': !usePadding }"
28
+ v-if="$scopedSlots.footer"
29
+ >
30
+ <!--
31
+ @slot Custom footer slot
32
+ @binding {Function} close closes the popup
33
+ -->
34
+ <slot name="footer" v-bind="{ close }"></slot>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </template>
39
+ <style lang="less" scoped>
40
+ .ui-popup {
41
+ &.fullscreen {
42
+ .popup-dialog {
43
+ display: flex;
44
+ flex-direction: column;
45
+ width: 100%;
46
+ height: 100%;
47
+ min-height: 100%;
48
+ border-radius: 0;
49
+ overflow: auto;
50
+ &-body {
51
+ flex: 1;
52
+ height: 0;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ </style>
58
+ <script>
59
+ export default {
60
+ props: {
61
+ /**
62
+ * Whether the popup is visible (.sync supported)
63
+ */
64
+ visible: {
65
+ type: Boolean,
66
+ default: false,
67
+ },
68
+ /**
69
+ * Whether the popup is modal (clicking outside closes the popup)
70
+ */
71
+ modal: {
72
+ type: Boolean,
73
+ default: false,
74
+ },
75
+ /**
76
+ * Whether the popup is fullscreen
77
+ */
78
+ fullscreen: {
79
+ type: Boolean,
80
+ default: false,
81
+ },
82
+ /**
83
+ * Popup dialog options for styling css/style
84
+ * { class:any style:any }
85
+ */
86
+ dialog: {
87
+ type: Object,
88
+ default() {
89
+ return { class: {}, style: {} };
90
+ },
91
+ },
92
+ /**
93
+ * Whether to show the close button
94
+ */
95
+ showCloseButton: {
96
+ type: Boolean,
97
+ default: true,
98
+ },
99
+ /**
100
+ * Whether the popup body/footer should have padding
101
+ */
102
+ usePadding: {
103
+ type: Boolean,
104
+ default: true,
105
+ },
106
+ /**
107
+ * Css class which applies on 'body' node when the popup is visible
108
+ */
109
+ visibleBodyClass: {
110
+ type: String,
111
+ default: 'scroll-hide',
112
+ },
113
+ },
114
+ watch: {
115
+ visible: {
116
+ handler(val) {
117
+ if (!this.visibleBodyClass) {
118
+ return;
119
+ }
120
+ let m = val ? 'add' : 'remove';
121
+ document.body.classList[m](this.visibleBodyClass);
122
+ },
123
+ immediate: true,
124
+ },
125
+ },
126
+ beforeDestroy() {
127
+ if (this.visibleBodyClass) {
128
+ document.body.classList.remove(this.visibleBodyClass);
129
+ }
130
+ },
131
+ methods: {
132
+ close() {
133
+ /**
134
+ * Close event
135
+ */
136
+ this.$emit('close');
137
+ /**
138
+ * Visibility update event (visible.sync compatibility)
139
+ * @property {Boolean} visible
140
+ */
141
+ this.$emit('update:visible', false);
142
+ },
143
+ onClick(e) {
144
+ if (!this.modal && e.target == this.$el) {
145
+ this.close();
146
+ }
147
+ },
148
+ },
149
+ };
150
+ </script>
@@ -1,58 +1,58 @@
1
- ```vue
2
- <template>
3
- <div class="pad-l5">
4
- <div class="p">
5
- <div class="form-label form-label-small">Tile width:</div>
6
- <input class="input input-small" type="number" min="0" step="10" v-model.number="tileWidth">
7
- </div>
8
-
9
- <ui-responsive-container v-bind="binds" v-slot="{ breakpoint, width, height }">
10
- <!-- {demo-tile} -->
11
- <div class="tile" :class="[`tile--${breakpoint}`]" :style="tileStyle">
12
- <div class="tile-body">
13
- <div class="row">
14
- <div class="col col-auto tile__avatar">
15
- <img class="avatar avatar-4 round" src="https://picsum.photos/150/150" >
16
- </div>
17
- <div class="col">
18
- <div class="text-bold">John Wick</div>
19
- <div class="text-xsmall">john.wick@site.com</div>
20
- <code>{{breakpoint}}</code> | <code>{{width}}&times;{{height}}</code>
21
- </div>
22
- </div>
23
- </div>
24
- <!-- {/demo-tile} -->
25
- </div>
26
- </ui-responsive-container>
27
- </div>
28
- </template>
29
- <script>
30
- import UiResponsiveContainer from './ResponsiveContainer.vue';
31
-
32
- export default {
33
- components: { UiResponsiveContainer },
34
- data: () => ({
35
- binds: {
36
- breakpoints: {
37
- 's': 450,
38
- 'm': 550,
39
- 'l': 650,
40
- }
41
- },
42
- tileWidth: ''
43
- }),
44
- computed: {
45
- tileStyle() {
46
- return { width: `${this.tileWidth}px` }
47
- }
48
- }
49
- };
50
- </script>
51
- <style scoped>
52
- .tile { min-width: 150px; }
53
- .tile--s { color: red; }
54
- .tile--s .tile__avatar { display:none; }
55
- .tile--m { color: orange; }
56
- .tile--l { color: green; }
57
- </style>
58
- ```
1
+ ```vue
2
+ <template>
3
+ <div class="pad-l5">
4
+ <div class="p">
5
+ <div class="form-label form-label-small">Tile width:</div>
6
+ <input class="input input-small" type="number" min="0" step="10" v-model.number="tileWidth">
7
+ </div>
8
+
9
+ <ui-responsive-container v-bind="binds" v-slot="{ breakpoint, width, height }">
10
+ <!-- {demo-tile} -->
11
+ <div class="tile" :class="[`tile--${breakpoint}`]" :style="tileStyle">
12
+ <div class="tile-body">
13
+ <div class="row">
14
+ <div class="col col-auto tile__avatar">
15
+ <img class="avatar avatar-4 round" src="https://picsum.photos/150/150" >
16
+ </div>
17
+ <div class="col">
18
+ <div class="text-bold">John Wick</div>
19
+ <div class="text-xsmall">john.wick@site.com</div>
20
+ <code>{{breakpoint}}</code> | <code>{{width}}&times;{{height}}</code>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ <!-- {/demo-tile} -->
25
+ </div>
26
+ </ui-responsive-container>
27
+ </div>
28
+ </template>
29
+ <script>
30
+ import UiResponsiveContainer from './ResponsiveContainer.vue';
31
+
32
+ export default {
33
+ components: { UiResponsiveContainer },
34
+ data: () => ({
35
+ binds: {
36
+ breakpoints: {
37
+ 's': 450,
38
+ 'm': 550,
39
+ 'l': 650,
40
+ }
41
+ },
42
+ tileWidth: ''
43
+ }),
44
+ computed: {
45
+ tileStyle() {
46
+ return { width: `${this.tileWidth}px` }
47
+ }
48
+ }
49
+ };
50
+ </script>
51
+ <style scoped>
52
+ .tile { min-width: 150px; }
53
+ .tile--s { color: red; }
54
+ .tile--s .tile__avatar { display:none; }
55
+ .tile--m { color: orange; }
56
+ .tile--l { color: green; }
57
+ </style>
58
+ ```
@@ -1,99 +1,99 @@
1
- <script>
2
- import { debounce } from './utils/Helpers';
3
-
4
- const ObserverManager = {
5
- observer: null,
6
- records: new Map(),
7
- register({ fn, el }) {
8
- const { records } = this;
9
- if (!records.size) {
10
- this.createObserver();
11
- }
12
- records.set(el, fn);
13
- this.observer.observe(el);
14
- },
15
- unregister(el) {
16
- const { records } = this;
17
- records.delete(el);
18
- this.observer.unobserve(el);
19
- if (!records.size) {
20
- this.destroyObserver();
21
- }
22
- },
23
- createObserver() {
24
- const { records } = this;
25
- const callback = entries => {
26
- entries.forEach(entry => {
27
- const fn = records.get(entry.target);
28
- fn && fn(entry);
29
- });
30
- };
31
- this.observer = new ResizeObserver(debounce(callback, 50));
32
- },
33
- destroyObserver() {
34
- this.observer.disconnect();
35
- this.observer = null;
36
- },
37
- };
38
-
39
- export default {
40
- props: {
41
- /**
42
- * Breakpoints hash { '<name>': '<max-width-in-px>' }<br>
43
- * example:
44
- * <pre>{ 'mobile': 400, 'tablet': 800 }</pre>
45
- */
46
- breakpoints: {
47
- type: Object,
48
- default: () => ({}),
49
- },
50
- },
51
- data: () => ({ width: 0, height: 0 }),
52
- computed: {
53
- /**
54
- * @return {[string, number][]}
55
- */
56
- breakpointEntries() {
57
- return Object.entries(this.breakpoints).sort(([, aVal], [, bVal]) => aVal - bVal);
58
- },
59
- /**
60
- * @return {string}
61
- */
62
- breakpoint() {
63
- const { breakpointEntries, width } = this;
64
- if (width === 0) {
65
- return null;
66
- }
67
- const match = breakpointEntries.find(([, value]) => width < value);
68
- return match?.[0] ?? null;
69
- },
70
- },
71
- mounted() {
72
- const { $el: el } = this;
73
- const fn = ({ contentRect }) => {
74
- this.width = contentRect.width | 0;
75
- this.height = contentRect.height | 0;
76
- };
77
- ObserverManager.register({ fn, el });
78
- },
79
- beforeDestroy() {
80
- ObserverManager.unregister(this.$el);
81
- },
82
- render(h) {
83
- const { breakpoint, width, height } = this;
84
- /*
85
- @slot Page data slot
86
- @binding {string} breakpoint breakpoint name
87
- @binding {number} width current container width (px)
88
- @binding {number} height current container height (px)
89
- */
90
- const content = this.$scopedSlots.default
91
- ? this.$scopedSlots.default({ breakpoint, width, height })
92
- : null;
93
- if (content.length > 1) {
94
- return h('div', 'Slot content should have one child');
95
- }
96
- return content;
97
- },
98
- };
99
- </script>
1
+ <script>
2
+ import { debounce } from './utils/Helpers';
3
+
4
+ const ObserverManager = {
5
+ observer: null,
6
+ records: new Map(),
7
+ register({ fn, el }) {
8
+ const { records } = this;
9
+ if (!records.size) {
10
+ this.createObserver();
11
+ }
12
+ records.set(el, fn);
13
+ this.observer.observe(el);
14
+ },
15
+ unregister(el) {
16
+ const { records } = this;
17
+ records.delete(el);
18
+ this.observer.unobserve(el);
19
+ if (!records.size) {
20
+ this.destroyObserver();
21
+ }
22
+ },
23
+ createObserver() {
24
+ const { records } = this;
25
+ const callback = entries => {
26
+ entries.forEach(entry => {
27
+ const fn = records.get(entry.target);
28
+ fn && fn(entry);
29
+ });
30
+ };
31
+ this.observer = new ResizeObserver(debounce(callback, 50));
32
+ },
33
+ destroyObserver() {
34
+ this.observer.disconnect();
35
+ this.observer = null;
36
+ },
37
+ };
38
+
39
+ export default {
40
+ props: {
41
+ /**
42
+ * Breakpoints hash { '<name>': '<max-width-in-px>' }<br>
43
+ * example:
44
+ * <pre>{ 'mobile': 400, 'tablet': 800 }</pre>
45
+ */
46
+ breakpoints: {
47
+ type: Object,
48
+ default: () => ({}),
49
+ },
50
+ },
51
+ data: () => ({ width: 0, height: 0 }),
52
+ computed: {
53
+ /**
54
+ * @return {[string, number][]}
55
+ */
56
+ breakpointEntries() {
57
+ return Object.entries(this.breakpoints).sort(([, aVal], [, bVal]) => aVal - bVal);
58
+ },
59
+ /**
60
+ * @return {string}
61
+ */
62
+ breakpoint() {
63
+ const { breakpointEntries, width } = this;
64
+ if (width === 0) {
65
+ return null;
66
+ }
67
+ const match = breakpointEntries.find(([, value]) => width < value);
68
+ return match?.[0] ?? null;
69
+ },
70
+ },
71
+ mounted() {
72
+ const { $el: el } = this;
73
+ const fn = ({ contentRect }) => {
74
+ this.width = contentRect.width | 0;
75
+ this.height = contentRect.height | 0;
76
+ };
77
+ ObserverManager.register({ fn, el });
78
+ },
79
+ beforeDestroy() {
80
+ ObserverManager.unregister(this.$el);
81
+ },
82
+ render(h) {
83
+ const { breakpoint, width, height } = this;
84
+ /*
85
+ @slot Page data slot
86
+ @binding {string} breakpoint breakpoint name
87
+ @binding {number} width current container width (px)
88
+ @binding {number} height current container height (px)
89
+ */
90
+ const content = this.$scopedSlots.default
91
+ ? this.$scopedSlots.default({ breakpoint, width, height })
92
+ : null;
93
+ if (content.length > 1) {
94
+ return h('div', 'Slot content should have one child');
95
+ }
96
+ return content;
97
+ },
98
+ };
99
+ </script>