@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
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@radio-garden/ditojs-admin",
3
+ "version": "2.85.2-0.5067ad799",
4
+ "type": "module",
5
+ "description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
6
+ "repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
7
+ "author": "Jürg Lehni <juerg@scratchdisk.com> (http://scratchdisk.com)",
8
+ "license": "MIT",
9
+ "module": "./dist/dito-admin.es.js",
10
+ "main": "./dist/dito-admin.umd.js",
11
+ "types": "./types/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./types/index.d.ts",
15
+ "import": "./dist/dito-admin.es.js",
16
+ "require": "./dist/dito-admin.umd.js"
17
+ },
18
+ "./style.css": "./dist/dito-admin.css",
19
+ "./src": "./src/index.js",
20
+ "./imports.scss": "./src/styles/_imports.scss"
21
+ },
22
+ "files": [
23
+ "src/",
24
+ "dist/",
25
+ "types/"
26
+ ],
27
+ "scripts": {
28
+ "build": "vite build",
29
+ "watch": "pnpm run build --mode 'development' --watch",
30
+ "prepare": "pnpm run build",
31
+ "types": "tsc --noEmit types/index.d.ts"
32
+ },
33
+ "engines": {
34
+ "node": ">= 20.0.0"
35
+ },
36
+ "browserslist": [
37
+ "> 1%",
38
+ "last 2 versions",
39
+ "not ie > 0",
40
+ "not ie_mob > 0"
41
+ ],
42
+ "dependencies": {
43
+ "@ditojs/ui": "workspace:^",
44
+ "@ditojs/utils": "workspace:^",
45
+ "@kyvg/vue3-notification": "^3.4.2",
46
+ "@lk77/vue3-color": "^3.0.6",
47
+ "@tiptap/core": "^3.20.1",
48
+ "@tiptap/extension-blockquote": "^3.20.1",
49
+ "@tiptap/extension-bold": "^3.20.1",
50
+ "@tiptap/extension-bullet-list": "^3.20.1",
51
+ "@tiptap/extension-code": "^3.20.1",
52
+ "@tiptap/extension-code-block": "^3.20.1",
53
+ "@tiptap/extension-document": "^3.20.1",
54
+ "@tiptap/extension-hard-break": "^3.20.1",
55
+ "@tiptap/extension-heading": "^3.20.1",
56
+ "@tiptap/extension-history": "^3.20.1",
57
+ "@tiptap/extension-horizontal-rule": "^3.20.1",
58
+ "@tiptap/extension-italic": "^3.20.1",
59
+ "@tiptap/extension-link": "^3.20.1",
60
+ "@tiptap/extension-list": "^3.20.1",
61
+ "@tiptap/extension-list-item": "^3.20.1",
62
+ "@tiptap/extension-ordered-list": "^3.20.1",
63
+ "@tiptap/extension-paragraph": "^3.20.1",
64
+ "@tiptap/extension-strike": "^3.20.1",
65
+ "@tiptap/extension-subscript": "^3.20.1",
66
+ "@tiptap/extension-superscript": "^3.20.1",
67
+ "@tiptap/extension-text": "^3.20.1",
68
+ "@tiptap/extension-text-style": "^3.20.1",
69
+ "@tiptap/extension-underline": "^3.20.1",
70
+ "@tiptap/extensions": "^3.20.1",
71
+ "@tiptap/pm": "^3.20.1",
72
+ "@tiptap/vue-3": "^3.20.1",
73
+ "@vueuse/integrations": "^14.2.1",
74
+ "codeflask": "^1.4.1",
75
+ "filesize": "^11.0.13",
76
+ "filesize-parser": "^1.5.1",
77
+ "focus-trap": "^8.0.0",
78
+ "nanoid": "^5.1.6",
79
+ "sortablejs": "^1.15.7",
80
+ "tinycolor2": "^1.6.0",
81
+ "tippy.js": "^6.3.7",
82
+ "tiptap-footnotes": "^3.0.1",
83
+ "type-fest": "^5.4.4",
84
+ "vue": "^3.5.30",
85
+ "vue-multiselect": "^3.4.0",
86
+ "vue-router": "^5.0.3",
87
+ "vue-upload-component": "^3.1.17"
88
+ },
89
+ "devDependencies": {
90
+ "@ditojs/build": "workspace:^",
91
+ "typescript": "^5.9.3",
92
+ "vite": "^7.3.1"
93
+ },
94
+ "gitHead": "5067ad799",
95
+ "gitBranch": "chore/improve-ts-types"
96
+ }
@@ -0,0 +1,293 @@
1
+ import { createApp, h as createElement } from 'vue'
2
+ import { createRouter, createWebHistory } from 'vue-router'
3
+ import VueNotifications from '@kyvg/vue3-notification'
4
+ import {
5
+ isString,
6
+ isAbsoluteUrl,
7
+ assignDeeply,
8
+ hyphenate,
9
+ camelize,
10
+ defaultFormats
11
+ } from '@ditojs/utils'
12
+ import * as components from './components/index.js'
13
+ import * as types from './types/index.js'
14
+ import DitoRoot from './components/DitoRoot.vue'
15
+ import DitoTypeComponent from './DitoTypeComponent.js'
16
+ import ResizeDirective from './directives/resize.js'
17
+ import { getResource } from './utils/resource.js'
18
+ import { formatQuery } from './utils/route.js'
19
+ import verbs from './verbs.js'
20
+
21
+ export default class DitoAdmin {
22
+ constructor(el, {
23
+ // `dito` contains the base and api settings passed from `AdminController`
24
+ dito = {},
25
+ api,
26
+ views = {},
27
+ ...options
28
+ } = {}) {
29
+ this.el = el
30
+ // Merge in `api` settings as passed from `config.admin` and through the
31
+ // `AdminController` with `api` values from from 'admin/index.js'
32
+ // NOTE: `AdminController` provides `dito.api.base`
33
+ this.api = api = assignDeeply({ base: '/' }, dito.api, api)
34
+ this.options = options
35
+
36
+ // Setup default api settings:
37
+ api.locale ||= 'en-US'
38
+ api.formats = assignDeeply({}, defaultFormats, api.formats)
39
+ api.request ||= options => request(api, options)
40
+ api.getApiUrl ||= options => getApiUrl(api, options)
41
+ api.isApiUrl ||= url => isApiUrl(api, url)
42
+ // Setting `api.normalizePaths = true (plural) sets both:
43
+ // `api.normalizePath = hyphenate` and `api.denormalizePath = camelize`
44
+ api.normalizePath ||= api.normalizePaths ? hyphenate : val => val
45
+ api.denormalizePath ||= api.normalizePaths ? camelize : val => val
46
+
47
+ // Allow definition of defaults for admin component types, nested per type:
48
+ // api.defaults = {
49
+ // 'multiselect': {
50
+ // selectable: true
51
+ // },
52
+ // 'fake-type': schema => {
53
+ // // Return defaults, or directly modify the schema:
54
+ // Object.assign(schema, {
55
+ // type: 'real-type',
56
+ // format: ({ value }) => `Formatted ${value}`,
57
+ // process: ({ value }) => `Processed ${value}`
58
+ // })
59
+ // }
60
+ // }
61
+
62
+ api.defaults ||= {}
63
+
64
+ // Allow the configuration of all auth resources, like so:
65
+ // api.users = {
66
+ // path: '/admins',
67
+ // // These are the defaults:
68
+ // login: {
69
+ // path: 'login',
70
+ // method: 'post'
71
+ // },
72
+ // logout: {
73
+ // path: 'logout',
74
+ // method: 'post'
75
+ // },
76
+ // session: {
77
+ // path: 'session',
78
+ // method: 'get'
79
+ // }
80
+ // }
81
+ const users = getResource(api.users, {
82
+ type: 'collection'
83
+ }) || {}
84
+ users.login = getResource(users.login || 'login', {
85
+ method: 'post',
86
+ parent: users
87
+ })
88
+ users.logout = getResource(users.logout || 'logout', {
89
+ method: 'post',
90
+ parent: users
91
+ })
92
+ users.session = getResource(users.session || 'session', {
93
+ method: 'get',
94
+ parent: users
95
+ })
96
+ api.users = users
97
+
98
+ // Allow overriding of resource path handlers:
99
+ // api.resources = {
100
+ // collection(resource) {
101
+ // return resource.parent
102
+ // ? `${resource.path}?${resource.parent.path}_id=${
103
+ // resource.parent.id}`
104
+ // : resource.path
105
+ // }
106
+ // }
107
+
108
+ api.resources = {
109
+ any(resource) {
110
+ const handler = this[resource?.type] || this.default
111
+ return resource && handler.call(this, resource)
112
+ },
113
+
114
+ default(resource) {
115
+ const parentPath = this.any(resource.parent)
116
+ return parentPath
117
+ ? `${parentPath}/${resource.path}`
118
+ : resource.path
119
+ },
120
+
121
+ collection(resource) {
122
+ return this.default(resource)
123
+ },
124
+
125
+ member(resource) {
126
+ return `${this.default(resource)}/${resource.id}`
127
+ },
128
+
129
+ upload(resource) {
130
+ // Dito.js Server handles upload routes on the collection resource:
131
+ return `${this.collection(resource.parent)}/upload/${resource.path}`
132
+ },
133
+
134
+ ...api.resources
135
+ }
136
+
137
+ // Allow overriding / extending of headers:
138
+ // api.headers = {
139
+ // 'Content-Type': 'application/json'
140
+ // }
141
+ api.headers = {
142
+ 'Content-Type': 'application/json',
143
+ ...api.headers
144
+ }
145
+
146
+ if (isString(el)) {
147
+ el = document.querySelector(el)
148
+ }
149
+
150
+ const app = (this.app = createApp({
151
+ components: {
152
+ DitoRoot,
153
+ VueNotifications,
154
+ // This may only be needed to avoid tree-shacking of these components,
155
+ // since they actually handle registry internally already.
156
+ // TODO: Remove this once we have a better solution.
157
+ ...components,
158
+ ...types
159
+ },
160
+
161
+ // Most injects are defined as functions, to preserve reactiveness across
162
+ // provide/inject, see:
163
+ // https://github.com/vuejs/vue/issues/7017#issuecomment-480906691
164
+ provide: {
165
+ api,
166
+ // A default list of verbs are provided by $verbs() and can be
167
+ // overridden at any point in the component hierarchy.
168
+ $verbs: () => verbs,
169
+ // Provide defaults so DitoMixin can inject them for all components:
170
+ // inject: [ '$isPopulated', '$schemaComponent', '$routeComponent' ]
171
+ $views: () => {},
172
+ $isPopulated: () => true,
173
+ $parentComponent: () => null,
174
+ $schemaComponent: () => null,
175
+ $schemaParentComponent: () => null,
176
+ $routeComponent: () => null,
177
+ $dataComponent: () => null,
178
+ $sourceComponent: () => null,
179
+ $resourceComponent: () => null,
180
+ $dialogComponent: () => null,
181
+ $panelComponent: () => null,
182
+ $tabComponent: () => null
183
+ },
184
+
185
+ render: () =>
186
+ createElement(DitoRoot, {
187
+ ref: 'root',
188
+ class: dito.settings.rootClass,
189
+ unresolvedViews: views,
190
+ options
191
+ })
192
+ }))
193
+
194
+ // Prevent endless loops of error messages during render functions by
195
+ // setting a custom error handler.
196
+ app.config.errorHandler = console.error
197
+
198
+ app.use(VueNotifications, {
199
+ componentName: 'VueNotifications',
200
+ name: 'notify'
201
+ })
202
+
203
+ app.directive('resize', ResizeDirective)
204
+
205
+ app.use(
206
+ createRouter({
207
+ // Start with a catch-all route, to be replaced by the actual routes
208
+ // once the schemas are loaded, to prevent vue-router from complaining,
209
+ // see: `resolveViews()` in `DitoRoot` for the actual route setup.
210
+ routes: [
211
+ {
212
+ name: 'catch-all',
213
+ path: '/:_(.*)',
214
+ components: {}
215
+ }
216
+ ],
217
+ history: createWebHistory(dito.base),
218
+ linkActiveClass: '',
219
+ linkExactActiveClass: ''
220
+ })
221
+ )
222
+
223
+ el.classList.add('dito-app')
224
+ app.mount(el)
225
+ }
226
+
227
+ register(type, options) {
228
+ return DitoTypeComponent.register(type, options)
229
+ }
230
+ }
231
+
232
+ class RequestError extends Error {
233
+ constructor(response) {
234
+ super(
235
+ `Request failed with status code: ${response.status} (${
236
+ response.statusText
237
+ })`
238
+ )
239
+ this.response = response
240
+ }
241
+ }
242
+
243
+ async function request(api, {
244
+ url,
245
+ method = 'get',
246
+ query = null,
247
+ headers = null,
248
+ data = null,
249
+ signal = null
250
+ }) {
251
+ const isApiUrl = api.isApiUrl(url)
252
+
253
+ const response = await fetch(api.getApiUrl({ url, query }), {
254
+ method: method.toUpperCase(),
255
+ ...(data && { body: JSON.stringify(data) }),
256
+ headers: {
257
+ ...(isApiUrl && api.headers),
258
+ ...headers
259
+ },
260
+ credentials:
261
+ isApiUrl && api.cors?.credentials
262
+ ? 'include'
263
+ : 'same-origin',
264
+ signal
265
+ })
266
+
267
+ if (response.headers.get('Content-Type')?.includes('application/json')) {
268
+ response.data = await response.json()
269
+ }
270
+
271
+ if (!response.ok) {
272
+ throw new RequestError(response)
273
+ }
274
+ return response
275
+ }
276
+
277
+ function isApiUrl(api, url) {
278
+ return !isAbsoluteUrl(url) || url.startsWith(api.url)
279
+ }
280
+
281
+ function getApiUrl(api, { url, query }) {
282
+ if (!url.startsWith(api.url) && !isAbsoluteUrl(url)) {
283
+ url = combineUrls(api.url, url)
284
+ }
285
+ // Support optional query parameters, to be are added to the URL.
286
+ const search = formatQuery(query)
287
+ return search ? `${url}${url.includes('?') ? '&' : '?'}${search}` : url
288
+ }
289
+
290
+ function combineUrls(baseUrl, relativeUrl) {
291
+ // Use same approach as axios `combineURLs()` to join baseUrl & relativeUrl:
292
+ return `${baseUrl.replace(/\/+$/, '')}/${relativeUrl.replace(/^\/+/, '')}`
293
+ }
@@ -0,0 +1,34 @@
1
+ import DitoMixin from './mixins/DitoMixin.js'
2
+ import { getTypeComponent } from './utils/schema.js'
3
+ import { resolveMergedOptions } from './utils/options.js'
4
+ import { isPlainObject } from '@ditojs/utils'
5
+
6
+ const components = {}
7
+
8
+ // @vue/component
9
+ export default {
10
+ mixins: [DitoMixin],
11
+ // Make sure that registered components are present in all DitoComponent.
12
+ components,
13
+
14
+ component(name, definition) {
15
+ if (definition) {
16
+ if (isPlainObject(definition)) {
17
+ definition = resolveMergedOptions({
18
+ extends: this,
19
+ name,
20
+ ...definition
21
+ })
22
+ }
23
+ components[name] = definition
24
+ }
25
+ if (!(name in components)) {
26
+ throw new Error(`Component "${name}" not registered`)
27
+ }
28
+ return components[name]
29
+ },
30
+
31
+ methods: {
32
+ getTypeComponent
33
+ }
34
+ }