@radio-garden/ditojs-admin 2.85.2-0.5067ad799

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 (153) hide show
  1. package/README.md +180 -0
  2. package/dist/dito-admin.css +1 -0
  3. package/dist/dito-admin.es.js +12106 -0
  4. package/dist/dito-admin.umd.js +7 -0
  5. package/package.json +96 -0
  6. package/src/DitoAdmin.js +293 -0
  7. package/src/DitoComponent.js +34 -0
  8. package/src/DitoContext.js +318 -0
  9. package/src/DitoTypeComponent.js +42 -0
  10. package/src/DitoUser.js +12 -0
  11. package/src/appState.js +12 -0
  12. package/src/components/DitoAccount.vue +60 -0
  13. package/src/components/DitoAffix.vue +68 -0
  14. package/src/components/DitoAffixes.vue +200 -0
  15. package/src/components/DitoButtons.vue +80 -0
  16. package/src/components/DitoClipboard.vue +186 -0
  17. package/src/components/DitoContainer.vue +374 -0
  18. package/src/components/DitoCreateButton.vue +146 -0
  19. package/src/components/DitoDialog.vue +242 -0
  20. package/src/components/DitoDraggable.vue +117 -0
  21. package/src/components/DitoEditButtons.vue +135 -0
  22. package/src/components/DitoErrors.vue +83 -0
  23. package/src/components/DitoForm.vue +521 -0
  24. package/src/components/DitoFormInner.vue +26 -0
  25. package/src/components/DitoFormNested.vue +17 -0
  26. package/src/components/DitoHeader.vue +84 -0
  27. package/src/components/DitoLabel.vue +200 -0
  28. package/src/components/DitoMenu.vue +186 -0
  29. package/src/components/DitoNavigation.vue +40 -0
  30. package/src/components/DitoNotifications.vue +170 -0
  31. package/src/components/DitoPagination.vue +42 -0
  32. package/src/components/DitoPane.vue +334 -0
  33. package/src/components/DitoPanel.vue +256 -0
  34. package/src/components/DitoPanels.vue +61 -0
  35. package/src/components/DitoRoot.vue +524 -0
  36. package/src/components/DitoSchema.vue +846 -0
  37. package/src/components/DitoSchemaInlined.vue +97 -0
  38. package/src/components/DitoScopes.vue +76 -0
  39. package/src/components/DitoSidebar.vue +50 -0
  40. package/src/components/DitoSpinner.vue +95 -0
  41. package/src/components/DitoTableCell.vue +64 -0
  42. package/src/components/DitoTableHead.vue +121 -0
  43. package/src/components/DitoTabs.vue +103 -0
  44. package/src/components/DitoTrail.vue +124 -0
  45. package/src/components/DitoTreeItem.vue +420 -0
  46. package/src/components/DitoUploadFile.vue +199 -0
  47. package/src/components/DitoVNode.vue +14 -0
  48. package/src/components/DitoView.vue +143 -0
  49. package/src/components/index.js +42 -0
  50. package/src/directives/resize.js +83 -0
  51. package/src/index.js +1 -0
  52. package/src/mixins/ContextMixin.js +68 -0
  53. package/src/mixins/DataMixin.js +131 -0
  54. package/src/mixins/DitoMixin.js +591 -0
  55. package/src/mixins/DomMixin.js +29 -0
  56. package/src/mixins/EmitterMixin.js +158 -0
  57. package/src/mixins/ItemMixin.js +144 -0
  58. package/src/mixins/LoadingMixin.js +23 -0
  59. package/src/mixins/NumberMixin.js +118 -0
  60. package/src/mixins/OptionsMixin.js +304 -0
  61. package/src/mixins/PulldownMixin.js +63 -0
  62. package/src/mixins/ResourceMixin.js +398 -0
  63. package/src/mixins/RouteMixin.js +190 -0
  64. package/src/mixins/SchemaParentMixin.js +33 -0
  65. package/src/mixins/SortableMixin.js +49 -0
  66. package/src/mixins/SourceMixin.js +734 -0
  67. package/src/mixins/TextMixin.js +26 -0
  68. package/src/mixins/TypeMixin.js +280 -0
  69. package/src/mixins/ValidationMixin.js +119 -0
  70. package/src/mixins/ValidatorMixin.js +57 -0
  71. package/src/mixins/ValueMixin.js +31 -0
  72. package/src/styles/_base.scss +17 -0
  73. package/src/styles/_button.scss +191 -0
  74. package/src/styles/_imports.scss +3 -0
  75. package/src/styles/_info.scss +19 -0
  76. package/src/styles/_layout.scss +19 -0
  77. package/src/styles/_pulldown.scss +38 -0
  78. package/src/styles/_scroll.scss +13 -0
  79. package/src/styles/_settings.scss +88 -0
  80. package/src/styles/_table.scss +223 -0
  81. package/src/styles/_tippy.scss +45 -0
  82. package/src/styles/style.scss +9 -0
  83. package/src/types/DitoTypeButton.vue +143 -0
  84. package/src/types/DitoTypeCheckbox.vue +27 -0
  85. package/src/types/DitoTypeCheckboxes.vue +65 -0
  86. package/src/types/DitoTypeCode.vue +199 -0
  87. package/src/types/DitoTypeColor.vue +272 -0
  88. package/src/types/DitoTypeComponent.vue +31 -0
  89. package/src/types/DitoTypeComputed.vue +50 -0
  90. package/src/types/DitoTypeDate.vue +99 -0
  91. package/src/types/DitoTypeLabel.vue +23 -0
  92. package/src/types/DitoTypeList.vue +364 -0
  93. package/src/types/DitoTypeMarkup.vue +700 -0
  94. package/src/types/DitoTypeMultiselect.vue +522 -0
  95. package/src/types/DitoTypeNumber.vue +66 -0
  96. package/src/types/DitoTypeObject.vue +136 -0
  97. package/src/types/DitoTypePanel.vue +18 -0
  98. package/src/types/DitoTypeProgress.vue +40 -0
  99. package/src/types/DitoTypeRadio.vue +45 -0
  100. package/src/types/DitoTypeSection.vue +80 -0
  101. package/src/types/DitoTypeSelect.vue +133 -0
  102. package/src/types/DitoTypeSlider.vue +66 -0
  103. package/src/types/DitoTypeSpacer.vue +11 -0
  104. package/src/types/DitoTypeSwitch.vue +40 -0
  105. package/src/types/DitoTypeText.vue +101 -0
  106. package/src/types/DitoTypeTextarea.vue +48 -0
  107. package/src/types/DitoTypeTreeList.vue +193 -0
  108. package/src/types/DitoTypeUpload.vue +503 -0
  109. package/src/types/index.js +30 -0
  110. package/src/utils/SchemaGraph.js +147 -0
  111. package/src/utils/accessor.js +75 -0
  112. package/src/utils/agent.js +47 -0
  113. package/src/utils/data.js +92 -0
  114. package/src/utils/filter.js +266 -0
  115. package/src/utils/math.js +14 -0
  116. package/src/utils/options.js +48 -0
  117. package/src/utils/path.js +5 -0
  118. package/src/utils/resource.js +44 -0
  119. package/src/utils/route.js +53 -0
  120. package/src/utils/schema.js +1121 -0
  121. package/src/utils/type.js +81 -0
  122. package/src/utils/uid.js +15 -0
  123. package/src/utils/units.js +5 -0
  124. package/src/validators/_creditcard.js +6 -0
  125. package/src/validators/_decimals.js +11 -0
  126. package/src/validators/_domain.js +6 -0
  127. package/src/validators/_email.js +6 -0
  128. package/src/validators/_hostname.js +6 -0
  129. package/src/validators/_integer.js +6 -0
  130. package/src/validators/_max.js +6 -0
  131. package/src/validators/_min.js +6 -0
  132. package/src/validators/_password.js +5 -0
  133. package/src/validators/_range.js +6 -0
  134. package/src/validators/_required.js +9 -0
  135. package/src/validators/_url.js +6 -0
  136. package/src/validators/index.js +12 -0
  137. package/src/verbs.js +17 -0
  138. package/types/index.d.ts +3298 -0
  139. package/types/tests/admin.test-d.ts +27 -0
  140. package/types/tests/component-buttons.test-d.ts +44 -0
  141. package/types/tests/component-list.test-d.ts +159 -0
  142. package/types/tests/component-misc.test-d.ts +137 -0
  143. package/types/tests/component-object.test-d.ts +69 -0
  144. package/types/tests/component-section.test-d.ts +174 -0
  145. package/types/tests/component-select.test-d.ts +107 -0
  146. package/types/tests/components.test-d.ts +81 -0
  147. package/types/tests/context.test-d.ts +31 -0
  148. package/types/tests/fixtures.ts +24 -0
  149. package/types/tests/form.test-d.ts +109 -0
  150. package/types/tests/instance.test-d.ts +20 -0
  151. package/types/tests/schema-features.test-d.ts +402 -0
  152. package/types/tests/variance.test-d.ts +125 -0
  153. package/types/tests/view.test-d.ts +146 -0
@@ -0,0 +1,200 @@
1
+ <template lang="pug">
2
+ component.dito-label(
3
+ v-if="text || collapsible"
4
+ :is="collapsible ? 'button' : 'div'"
5
+ :type="collapsible ? 'button' : null"
6
+ v-bind="attributes"
7
+ :class="{ 'dito-label--active': isActive }"
8
+ )
9
+ .dito-chevron(
10
+ v-if="collapsible"
11
+ :class="{ 'dito-chevron--open': !collapsed }"
12
+ )
13
+ .dito-label__inner(
14
+ v-if="text || prefixes.length > 0 || suffixes.length > 0"
15
+ )
16
+ DitoAffixes(
17
+ :items="prefixes"
18
+ position="prefix"
19
+ :parentContext="context"
20
+ )
21
+ label(
22
+ v-if="text"
23
+ :for="dataPath"
24
+ v-html="text"
25
+ )
26
+ DitoAffixes(
27
+ :items="suffixes"
28
+ mode="ellipsis"
29
+ position="suffix"
30
+ :parentContext="context"
31
+ )
32
+ .dito-info(
33
+ v-if="info"
34
+ :data-info="info"
35
+ )
36
+ </template>
37
+
38
+ <script>
39
+ import DitoComponent from '../DitoComponent.js'
40
+ import DitoAffixes from './DitoAffixes.vue'
41
+ import { isObject, asArray } from '@ditojs/utils'
42
+
43
+ // @vue/component
44
+ export default DitoComponent.component('DitoLabel', {
45
+ components: { DitoAffixes },
46
+
47
+ emits: ['open'],
48
+
49
+ props: {
50
+ label: { type: [String, Object], default: null },
51
+ dataPath: { type: String, default: null },
52
+ collapsed: { type: Boolean, default: false },
53
+ collapsible: { type: Boolean, default: false },
54
+ info: { type: String, default: null }
55
+ },
56
+
57
+ computed: {
58
+ text() {
59
+ const { label } = this
60
+ return isObject(label) ? label?.text : label
61
+ },
62
+
63
+ prefixes() {
64
+ return asArray(this.label?.prefix)
65
+ },
66
+
67
+ suffixes() {
68
+ return asArray(this.label?.suffix)
69
+ },
70
+
71
+ attributes() {
72
+ return this.collapsible ? { onClick: this.onClick } : {}
73
+ },
74
+
75
+ isActive() {
76
+ return this.appState.activeLabel === this
77
+ }
78
+ },
79
+
80
+ methods: {
81
+ onClick() {
82
+ this.appState.activeLabel = this
83
+ this.$emit('open', this.collapsed)
84
+ }
85
+ }
86
+ })
87
+ </script>
88
+
89
+ <style lang="scss">
90
+ @import '../styles/_imports';
91
+
92
+ .dito-label {
93
+ $self: &;
94
+
95
+ // For buttons and chevron to align right:
96
+ display: flex;
97
+ position: relative;
98
+ // Vertically center all items in the label, e.g. chevron, edit-buttons.
99
+ align-items: center;
100
+ min-height: $input-height;
101
+ margin-right: $form-spacing-half; // When inlined.
102
+
103
+ &:has(.dito-schema-header) {
104
+ // The container's label is used as teleport for a nested section or object
105
+ // label. Hide `&__inner`, as it is be duplicated inside the nested label.
106
+ > #{$self}__inner {
107
+ display: none;
108
+ }
109
+ }
110
+
111
+ &:not(:has(+ .dito-tabs)) {
112
+ // Take full width but only if there aren't also tabs to be centered.
113
+ flex: 1;
114
+ }
115
+
116
+ &__inner {
117
+ flex: 1 0 0%;
118
+ display: flex;
119
+ align-items: center;
120
+ overflow: hidden;
121
+ gap: $input-padding-hor;
122
+ }
123
+
124
+ label {
125
+ @include ellipsis;
126
+
127
+ cursor: inherit;
128
+ font-weight: bold;
129
+ line-height: $input-height;
130
+ }
131
+
132
+ // Fix alignment of sub and sup elements in label content.
133
+ sub,
134
+ sup {
135
+ display: inline-block;
136
+ vertical-align: baseline;
137
+ }
138
+
139
+ sub {
140
+ transform: translateY(4px);
141
+ }
142
+
143
+ sup {
144
+ transform: translateY(-4px);
145
+ }
146
+
147
+ .dito-buttons {
148
+ // Move the label padding inside .dito-buttons, so that it captures all
149
+ // near mouse events:
150
+ margin: calc(-1 * var(--label-padding));
151
+ margin-left: 0;
152
+ padding: var(--label-padding);
153
+ }
154
+
155
+ &--fill {
156
+ width: 100%;
157
+
158
+ // In order for ellipsis to work on labels without affecting other layout,
159
+ // we need to position it absolutely inside its container. But we can only
160
+ // do so if there is't also a chevron or other UX elements besides it.
161
+ &:has(> #{$self}__inner:only-child) {
162
+ flex: 1; // When in `.dito-schema-header`.
163
+
164
+ > #{$self}__inner {
165
+ position: absolute;
166
+ inset: 0;
167
+ }
168
+ }
169
+
170
+ &::after {
171
+ // Since <label> uses `position: absolute`, set content to a zero-width
172
+ // space on its parent to enforce the right text height in the container
173
+ content: '\200b'; // zero-width space;
174
+ }
175
+ }
176
+
177
+ .dito-info {
178
+ margin-left: 0.35em;
179
+ }
180
+
181
+ @at-root button#{&} {
182
+ border: 0;
183
+ padding: 0;
184
+ background: none;
185
+ text-align: start;
186
+
187
+ &:hover {
188
+ .dito-chevron {
189
+ color: $color-darker;
190
+ }
191
+ }
192
+
193
+ &:focus:not(:active, &--active) {
194
+ .dito-chevron {
195
+ -webkit-text-stroke: $border-width $color-active;
196
+ }
197
+ }
198
+ }
199
+ }
200
+ </style>
@@ -0,0 +1,186 @@
1
+ <template lang="pug">
2
+ ul.dito-menu(
3
+ v-resize="onResize"
4
+ :style="{ '--width': width ? `${width}px` : null }"
5
+ )
6
+ li.dito-menu__item(
7
+ v-for="item in items"
8
+ )
9
+ template(
10
+ v-if="shouldShowItem(item)"
11
+ )
12
+ a.dito-menu__link(
13
+ :href="getItemHref(item)"
14
+ :class="{ 'dito-menu__link--active': isActiveItem(item) }"
15
+ @click.prevent.stop="onClickItem(item)"
16
+ ) {{ getLabel(item) }}
17
+ DitoMenu.dito-menu__sub(
18
+ v-if="item.items"
19
+ :items="item.items"
20
+ :path="getItemPath(item, false)"
21
+ )
22
+ </template>
23
+
24
+ <script>
25
+ import DitoComponent from '../DitoComponent.js'
26
+
27
+ // @vue/component
28
+ export default DitoComponent.component('DitoMenu', {
29
+ props: {
30
+ items: {
31
+ type: [Object, Array],
32
+ default: () => []
33
+ },
34
+ path: {
35
+ type: String,
36
+ default: ''
37
+ }
38
+ },
39
+
40
+ data() {
41
+ return {
42
+ width: 0
43
+ }
44
+ },
45
+
46
+ methods: {
47
+ shouldShowItem(item) {
48
+ return (
49
+ this.shouldRenderSchema(item) && (
50
+ !item.items ||
51
+ Object.values(item.items).some(this.shouldRenderSchema)
52
+ )
53
+ )
54
+ },
55
+
56
+ onResize({ contentRect: { width } }) {
57
+ if (width) {
58
+ this.width = width
59
+ }
60
+ },
61
+
62
+ getItemPath(item, firstChild) {
63
+ const path = item.path ? `${this.path}/${item.path}` : null
64
+ return firstChild && path && item.items
65
+ ? `${path}${this.getItemPath(Object.values(item.items)[0], false)}`
66
+ : path
67
+ },
68
+
69
+ getItemHref(item) {
70
+ const path = this.getItemPath(item, true)
71
+ return path ? this.$router.resolve(path).href : null
72
+ },
73
+
74
+ isActiveItem(item) {
75
+ return (
76
+ this.$route.path.startsWith(this.getItemPath(item, false)) ||
77
+ item.items && Object.values(item.items).some(this.isActiveItem)
78
+ )
79
+ },
80
+
81
+ onClickItem(item) {
82
+ const path = this.getItemPath(item, true)
83
+ if (path) {
84
+ this.$router.push({ path, force: true })
85
+ }
86
+ }
87
+ }
88
+ })
89
+ </script>
90
+
91
+ <style lang="scss">
92
+ @use 'sass:color';
93
+ @import '../styles/_imports';
94
+
95
+ .dito-menu {
96
+ $self: &;
97
+ $item-height: $menu-font-size + 2 * $menu-padding-ver;
98
+
99
+ --menu-active-color: #{$color-white};
100
+ --menu-active-background: #{$color-active};
101
+
102
+ border-right: $border-style;
103
+ padding: 0 $menu-spacing;
104
+
105
+ &__item {
106
+ &:has(#{$self}__sub):not(:has(#{$self}__link--active)) {
107
+ // Pop-out sub-menus on hover:
108
+ &:hover {
109
+ > #{$self}__link {
110
+ background: $color-lightest;
111
+ }
112
+
113
+ #{$self}__sub {
114
+ display: block;
115
+ position: absolute;
116
+ width: var(--width);
117
+ z-index: $z-index-header;
118
+ transform: translateX(calc(var(--width) + 2 * $menu-spacing))
119
+ translateY(-$item-height);
120
+
121
+ #{$self}__item:first-child {
122
+ #{$self}__link {
123
+ margin-top: 0;
124
+ }
125
+ }
126
+
127
+ &::before {
128
+ // Fill the gap to not loose the hover when moving over it.
129
+ content: '';
130
+ position: absolute;
131
+ top: 0;
132
+ left: -2 * $menu-spacing;
133
+ width: 2 * $menu-spacing;
134
+ height: $item-height;
135
+ opacity: 0;
136
+ }
137
+ }
138
+
139
+ #{$self}__sub {
140
+ box-shadow: $shadow-window;
141
+ }
142
+ }
143
+ }
144
+ }
145
+
146
+ &__link {
147
+ display: block;
148
+ padding: $menu-padding;
149
+ line-height: $menu-line-height;
150
+ border-radius: $border-radius;
151
+ margin-top: $menu-spacing;
152
+
153
+ &:focus:not(:active, &--active) {
154
+ box-shadow: $shadow-focus;
155
+ }
156
+
157
+ &:hover {
158
+ background: rgb(255, 255, 255, 0.5);
159
+ }
160
+
161
+ &--active {
162
+ &,
163
+ &:hover {
164
+ color: var(--menu-active-color);
165
+ background: var(--menu-active-background);
166
+ }
167
+
168
+ &:has(+ #{$self}__sub) {
169
+ --menu-active-background: #{color.adjust($color-active, $alpha: -0.3)};
170
+ }
171
+ }
172
+ }
173
+
174
+ &__sub {
175
+ display: none;
176
+ border-right: 0;
177
+ padding: 0;
178
+ border-radius: $border-radius;
179
+ background: $color-lightest;
180
+ }
181
+
182
+ &__link--active + &__sub {
183
+ display: block;
184
+ }
185
+ }
186
+ </style>
@@ -0,0 +1,40 @@
1
+ <template lang="pug">
2
+ nav.dito-navigation.dito-scroll-parent
3
+ h1
4
+ RouterLink.dito-link(to="/") {{ appState.title }}
5
+ DitoMenu.dito-scroll(:items="views")
6
+ </template>
7
+
8
+ <script>
9
+ import DitoComponent from '../DitoComponent.js'
10
+
11
+ // @vue/component
12
+ export default DitoComponent.component('DitoNavigation', {})
13
+ </script>
14
+
15
+ <style lang="scss">
16
+ @import '../styles/_imports';
17
+
18
+ .dito-navigation {
19
+ @include user-select(none);
20
+
21
+ flex: 0 0 min-content;
22
+ font-size: $menu-font-size;
23
+ white-space: nowrap;
24
+ background: $color-lighter;
25
+
26
+ h1 {
27
+ display: block;
28
+ line-height: $header-line-height;
29
+ font-weight: bold;
30
+ background: $color-darker;
31
+ border-right: $border-width solid $color-darkest;
32
+ color: $color-white;
33
+
34
+ .dito-link {
35
+ display: block;
36
+ padding: $header-padding;
37
+ }
38
+ }
39
+ }
40
+ </style>
@@ -0,0 +1,170 @@
1
+ <template lang="pug">
2
+ .dito-notifications
3
+ .dito-header
4
+ span
5
+ .dito-notifications__inner
6
+ VueNotifications(
7
+ ref="notifications"
8
+ classes="dito-notification"
9
+ :dangerouslySetInnerHtml="true"
10
+ position=""
11
+ width=""
12
+ )
13
+ </template>
14
+
15
+ <script>
16
+ import DitoComponent from '../DitoComponent.js'
17
+ import { asArray, stripHtml } from '@ditojs/utils'
18
+
19
+ // @vue/component
20
+ export default DitoComponent.component('DitoNotifications', {
21
+ notifications() {
22
+ return this.isMounted && this.$refs.notifications
23
+ },
24
+
25
+ methods: {
26
+ notify({ type = 'info', title, text, error, duration } = {}) {
27
+ title ||= (
28
+ {
29
+ warning: 'Warning',
30
+ error: 'Error',
31
+ info: 'Information',
32
+ success: 'Success'
33
+ }[type] ||
34
+ 'Notification'
35
+ )
36
+ text = `<p>${
37
+ asArray(text).join('</p> <p>')
38
+ }</p>`.replace(/\n|\r\n|\r/g, '<br>')
39
+ const log = (
40
+ {
41
+ warning: 'warn',
42
+ error: 'error',
43
+ info: 'log',
44
+ success: 'log'
45
+ }[type] ||
46
+ 'error'
47
+ )
48
+ // eslint-disable-next-line no-console
49
+ console[log](
50
+ ...[
51
+ stripHtml(text),
52
+ ...(type === 'error' && error ? [error] : [])
53
+ ]
54
+ )
55
+ const { notifications = true } = this.api
56
+ if (notifications) {
57
+ // Calculate display-duration for the notification based on its content
58
+ // and the setting of the `durationFactor` configuration. It defines the
59
+ // amount of milliseconds multiplied with the amount of characters
60
+ // displayed in the notification, plus 40 (40 + title + message):
61
+ const { durationFactor = 20 } = notifications
62
+ duration ??= (40 + text.length + title.length) * durationFactor
63
+ this.$notify({
64
+ type,
65
+ title,
66
+ text,
67
+ duration: duration === 0 ? -1 : duration // < 0 -> <= 0 = sticky
68
+ })
69
+ }
70
+ },
71
+
72
+ destroyAll() {
73
+ this.notifications.destroyAll()
74
+ }
75
+ }
76
+ })
77
+ </script>
78
+
79
+ <style lang="scss">
80
+ @use 'sass:color';
81
+ @import '../styles/_imports';
82
+
83
+ @mixin type($background) {
84
+ background: color.adjust($background, $lightness: 5%);
85
+ color: $color-white;
86
+ border-left: 12px solid color.adjust($background, $lightness: -10%);
87
+ }
88
+
89
+ .dito-notifications {
90
+ $notification-width: 300px;
91
+
92
+ flex: 1;
93
+ z-index: $z-index-notifications;
94
+ box-sizing: border-box;
95
+ margin-left: $form-spacing;
96
+ // For the `@container` rule to work:
97
+ container-type: inline-size;
98
+
99
+ .dito-header {
100
+ span {
101
+ padding-left: 0;
102
+ padding-right: 0;
103
+ }
104
+ }
105
+
106
+ &__inner {
107
+ position: relative;
108
+ }
109
+
110
+ .vue-notification-group {
111
+ position: absolute;
112
+ left: 0;
113
+ top: 0;
114
+ width: $notification-width;
115
+
116
+ @container (width < #{$notification-width + $content-padding}) {
117
+ left: unset;
118
+ right: $content-padding;
119
+ }
120
+ }
121
+
122
+ .vue-notification-wrapper {
123
+ overflow: visible;
124
+ }
125
+
126
+ .dito-notification {
127
+ padding: 8px;
128
+ margin: $content-padding 0;
129
+ font-size: inherit;
130
+ color: $color-white;
131
+ border-radius: $border-radius;
132
+ box-shadow: $shadow-window;
133
+
134
+ .notification-title {
135
+ font-weight: bold;
136
+ padding-bottom: 8px;
137
+ }
138
+
139
+ .notification-content {
140
+ overflow: hidden;
141
+ word-break: break-all;
142
+
143
+ p {
144
+ margin: 0;
145
+
146
+ & + p {
147
+ margin-top: 8px;
148
+ }
149
+ }
150
+ }
151
+
152
+ &,
153
+ &.info {
154
+ @include type($color-active);
155
+ }
156
+
157
+ &.success {
158
+ @include type($color-success);
159
+ }
160
+
161
+ &.warning {
162
+ @include type($color-warning);
163
+ }
164
+
165
+ &.error {
166
+ @include type($color-error);
167
+ }
168
+ }
169
+ }
170
+ </style>
@@ -0,0 +1,42 @@
1
+ <template lang="pug">
2
+ Pagination(
3
+ v-model:page="page"
4
+ :pageSize="limit"
5
+ :total="total"
6
+ )
7
+ </template>
8
+
9
+ <script>
10
+ import { DitoPagination as Pagination } from '@ditojs/ui/src'
11
+ import DitoComponent from '../DitoComponent.js'
12
+
13
+ // @vue/component
14
+ export default DitoComponent.component('DitoPagination', {
15
+ components: { Pagination },
16
+
17
+ props: {
18
+ query: { type: Object, required: true },
19
+ limit: { type: Number, required: true },
20
+ total: { type: Number, required: true }
21
+ },
22
+
23
+ computed: {
24
+ page: {
25
+ get() {
26
+ return (+this.query.page || 0) + 1
27
+ },
28
+
29
+ set(page) {
30
+ if (this.page !== page) {
31
+ this.$router.push(
32
+ this.getQueryLink({
33
+ ...this.query,
34
+ page: page - 1
35
+ })
36
+ )
37
+ }
38
+ }
39
+ }
40
+ }
41
+ })
42
+ </script>