@hywax/cms 0.0.6 → 0.0.8
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/.nuxt/cms/editor/uplora-image.ts +1 -1
- package/.nuxt/cms/editor-content-full.ts +6 -0
- package/.nuxt/cms/editor-content-light.ts +6 -0
- package/.nuxt/cms/index.ts +3 -0
- package/.nuxt/cms/input-uplora-image.ts +15 -0
- package/cli/templates.mjs +6 -6
- package/dist/module.d.mts +7 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +141 -54
- package/dist/runtime/components/AutocompleteSelect.vue +1 -2
- package/dist/runtime/components/ButtonDelete.vue +3 -2
- package/dist/runtime/components/ButtonDelete.vue.d.ts +1 -0
- package/dist/runtime/components/EditorContentFull.vue +53 -0
- package/dist/runtime/components/EditorContentFull.vue.d.ts +20 -0
- package/dist/runtime/components/EditorContentLight.vue +46 -0
- package/dist/runtime/components/EditorContentLight.vue.d.ts +20 -0
- package/dist/runtime/components/InputUploraImage.vue +136 -0
- package/dist/runtime/components/InputUploraImage.vue.d.ts +35 -0
- package/dist/runtime/components/ModalConfirm.vue +2 -1
- package/dist/runtime/components/TablePanel.vue +1 -1
- package/dist/runtime/components/TablePanelColumnSorting.vue +1 -1
- package/dist/runtime/components/TablePanelFilters.vue.d.ts +1 -1
- package/dist/runtime/components/UploraImage.vue +2 -2
- package/dist/runtime/components/UploraImage.vue.d.ts +1 -1
- package/dist/runtime/components/prose/UploraImage.vue +1 -1
- package/dist/runtime/composables/useAdmin.d.ts +1 -1
- package/dist/runtime/composables/useAdmin.js +1 -2
- package/dist/runtime/composables/useAsyncHandler.d.ts +12 -0
- package/dist/runtime/composables/useAsyncHandler.js +30 -0
- package/dist/runtime/composables/useLogout.d.ts +8 -0
- package/dist/runtime/composables/useLogout.js +21 -0
- package/dist/runtime/composables/useUplora.d.ts +20 -0
- package/dist/runtime/composables/useUplora.js +52 -0
- package/dist/runtime/editor/components/BlockMenu.vue +43 -0
- package/dist/runtime/editor/components/BlockMenu.vue.d.ts +2 -0
- package/dist/runtime/editor/components/SlashCommand.vue +92 -0
- package/dist/runtime/editor/components/SlashCommand.vue.d.ts +7 -0
- package/dist/runtime/editor/components/TooltipLink.vue +81 -0
- package/dist/runtime/editor/components/TooltipLink.vue.d.ts +9 -0
- package/dist/runtime/editor/components/TooltipMenu.vue +75 -0
- package/dist/runtime/editor/components/TooltipMenu.vue.d.ts +9 -0
- package/dist/runtime/editor/extensions/callout/CalloutView.vue +7 -1
- package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue +7 -4
- package/dist/runtime/index.css +1 -1
- package/dist/runtime/server/api/uplora/[id].delete.d.ts +9 -1
- package/dist/runtime/server/api/uplora/[id].delete.js +13 -2
- package/dist/runtime/server/api/uplora/index.post.d.ts +7 -1
- package/dist/runtime/server/api/uplora/index.post.js +31 -2
- package/dist/runtime/server/errors/InternalHttpError.d.ts +5 -1
- package/dist/runtime/server/errors/InternalHttpError.js +2 -1
- package/dist/runtime/server/utils/errors.js +1 -1
- package/dist/runtime/server/utils/validation.d.ts +6 -2
- package/dist/runtime/server/utils/validation.js +28 -0
- package/dist/runtime/types/index.d.ts +4 -0
- package/dist/runtime/types/index.js +3 -0
- package/dist/runtime/types/query.d.ts +0 -3
- package/dist/runtime/types/tv.d.ts +2 -2
- package/package.json +1 -1
package/.nuxt/cms/index.ts
CHANGED
|
@@ -2,11 +2,14 @@ export { default as autocompleteSelect } from './autocomplete-select'
|
|
|
2
2
|
export { default as buttonClear } from './button-clear'
|
|
3
3
|
export { default as buttonCopy } from './button-copy'
|
|
4
4
|
export { default as buttonDelete } from './button-delete'
|
|
5
|
+
export { default as editorContentFull } from './editor-content-full'
|
|
6
|
+
export { default as editorContentLight } from './editor-content-light'
|
|
5
7
|
export { default as formPanel } from './form-panel'
|
|
6
8
|
export { default as formPanelAsideSection } from './form-panel-aside-section'
|
|
7
9
|
export { default as formPanelSection } from './form-panel-section'
|
|
8
10
|
export { default as inputSeo } from './input-seo'
|
|
9
11
|
export { default as inputSlug } from './input-slug'
|
|
12
|
+
export { default as inputUploraImage } from './input-uplora-image'
|
|
10
13
|
export { default as modalConfirm } from './modal-confirm'
|
|
11
14
|
export { default as tableCellPreview } from './table-cell-preview'
|
|
12
15
|
export { default as tableCellSeo } from './table-cell-seo'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"slots": {
|
|
3
|
+
"root": "relative w-full rounded-md overflow-hidden border border-default aspect-3/2 text-sm",
|
|
4
|
+
"image": "",
|
|
5
|
+
"imageActions": "absolute top-4 right-4 flex gap-2",
|
|
6
|
+
"uploader": "flex flex-col items-center justify-center w-full h-full p-4",
|
|
7
|
+
"uploaderPendingIcon": "size-6 animate-spin",
|
|
8
|
+
"uploaderIdleButton": "cursor-pointer bg-muted/50 border border-default border-dashed rounded-md h-full w-full",
|
|
9
|
+
"uploaderIdleIcon": "size-10 text-primary",
|
|
10
|
+
"uploaderIdleText": "mt-2 font-medium",
|
|
11
|
+
"uploaderIdleExtensions": "mt-2 text-xs text-muted uppercase",
|
|
12
|
+
"uploaderErrorText": "text-center font-medium",
|
|
13
|
+
"uploaderErrorActions": "flex gap-2 mt-4"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/cli/templates.mjs
CHANGED
|
@@ -69,13 +69,13 @@ import ComponentRender from '../../component-render'
|
|
|
69
69
|
describe('${upperName}.vue', () => {
|
|
70
70
|
it.each([
|
|
71
71
|
// Props
|
|
72
|
-
['
|
|
73
|
-
['
|
|
74
|
-
['
|
|
75
|
-
['
|
|
72
|
+
['base component', { props: {} }],
|
|
73
|
+
['with as', { props: { as: 'section' } }],
|
|
74
|
+
['with class', { props: { class: '' } }],
|
|
75
|
+
['with ui', { props: { ui: {} } }],
|
|
76
76
|
// Slots
|
|
77
|
-
['
|
|
78
|
-
])('
|
|
77
|
+
['with default slot', { slots: { default: () => 'Default slot' } }],
|
|
78
|
+
])('renders %s correctly', async (nameOrHtml: string, options: { props?: ${upperName}Props, slots?: Partial<${upperName}Slots> }) => {
|
|
79
79
|
const html = await ComponentRender(nameOrHtml, options, ${upperName})
|
|
80
80
|
expect(html).toMatchSnapshot()
|
|
81
81
|
})
|
package/dist/module.d.mts
CHANGED
|
@@ -17,6 +17,11 @@ interface CMSOptions {
|
|
|
17
17
|
* @defaultValue 'https://fluxor.uplora.ru'
|
|
18
18
|
*/
|
|
19
19
|
fluxorUrl?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Uplora URL
|
|
22
|
+
* @defaultValue 'http://uplora.ru'
|
|
23
|
+
*/
|
|
24
|
+
uploraUrl?: string;
|
|
20
25
|
/**
|
|
21
26
|
* Prefix for the environment variables
|
|
22
27
|
* @defaultValue 'APP_'
|
|
@@ -35,6 +40,8 @@ declare module '@nuxt/schema' {
|
|
|
35
40
|
fluxorUrl: string;
|
|
36
41
|
version: string;
|
|
37
42
|
};
|
|
43
|
+
uploraUrl: string;
|
|
44
|
+
uploraApiKey: string;
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, addServerHandler, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule
|
|
2
|
-
import { defu } from 'defu';
|
|
1
|
+
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, hasNuxtModule, installModule, addServerHandler, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule } from '@nuxt/kit';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { dirname } from 'pathe';
|
|
3
|
+
import { dirname, join } from 'pathe';
|
|
4
|
+
import { defu } from 'defu';
|
|
5
5
|
import { snakeCase, kebabCase } from 'scule';
|
|
6
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
7
|
|
|
7
8
|
const name = "@hywax/cms";
|
|
8
|
-
const version = "0.0.
|
|
9
|
+
const version = "0.0.8";
|
|
9
10
|
|
|
10
11
|
function createContext(options, nuxt) {
|
|
11
12
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -24,6 +25,7 @@ const defaultCMSConfig = {};
|
|
|
24
25
|
const defaultModuleOptions = {
|
|
25
26
|
name: "cms",
|
|
26
27
|
prefix: "C",
|
|
28
|
+
uploraUrl: "http://uplora.ru",
|
|
27
29
|
fluxorUrl: "https://fluxor.uplora.ru",
|
|
28
30
|
envPrefix: "APP_",
|
|
29
31
|
httpCodes: {
|
|
@@ -52,7 +54,7 @@ function prepareAutoImports({ resolve, options, nuxt }) {
|
|
|
52
54
|
path: resolve("./runtime/components"),
|
|
53
55
|
pathPrefix: false,
|
|
54
56
|
prefix: options?.prefix,
|
|
55
|
-
ignore: ["prose/**"
|
|
57
|
+
ignore: ["prose/**"]
|
|
56
58
|
});
|
|
57
59
|
addComponentsDir({
|
|
58
60
|
path: resolve("./runtime/components/prose"),
|
|
@@ -75,6 +77,103 @@ function prepareAutoImports({ resolve, options, nuxt }) {
|
|
|
75
77
|
addServerImportsDir(resolve("./runtime/server/utils"));
|
|
76
78
|
nuxt.options.nitro.alias ||= {};
|
|
77
79
|
nuxt.options.nitro.alias["#cms/http-codes"] = httpCodesPath;
|
|
80
|
+
nuxt.options.alias["#cms"] = resolve("./runtime");
|
|
81
|
+
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, defaultCMSConfig);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function prepareGenerateEnv({ nuxt }) {
|
|
85
|
+
const runtimeConfig = nuxt.options.runtimeConfig;
|
|
86
|
+
if (nuxt.options.dev && !runtimeConfig.uploraApiKey) {
|
|
87
|
+
const envPath = join(nuxt.options.rootDir, ".env");
|
|
88
|
+
const envContent = await readFile(envPath, "utf-8").catch(() => "");
|
|
89
|
+
const envKey = `${runtimeConfig.nitro?.envPrefix || "NUXT_"}UPLORA_API_KEY`;
|
|
90
|
+
if (!envContent.includes(envKey)) {
|
|
91
|
+
await writeFile(
|
|
92
|
+
envPath,
|
|
93
|
+
`${envContent ? `${envContent}
|
|
94
|
+
` : envContent}${envKey}=put-your-api-key-here`,
|
|
95
|
+
"utf-8"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function prepareInstallModules(_context) {
|
|
102
|
+
if (!hasNuxtModule("@nuxt/ui-pro")) {
|
|
103
|
+
await installModule("@nuxt/ui-pro");
|
|
104
|
+
}
|
|
105
|
+
if (!hasNuxtModule("@nuxtjs/mdc")) {
|
|
106
|
+
await installModule("@nuxtjs/mdc");
|
|
107
|
+
}
|
|
108
|
+
if (!hasNuxtModule("@vueuse/nuxt")) {
|
|
109
|
+
await installModule("@vueuse/nuxt");
|
|
110
|
+
}
|
|
111
|
+
if (!hasNuxtModule("nuxt-auth-utils")) {
|
|
112
|
+
await installModule("nuxt-auth-utils");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const icons = {
|
|
117
|
+
edit: "lucide:pencil",
|
|
118
|
+
trash: "lucide:trash-2",
|
|
119
|
+
imageUp: "lucide:image-up",
|
|
120
|
+
arrowDownUp: "lucide:arrow-down-up",
|
|
121
|
+
sortAsc: "lucide:arrow-up-wide-narrow",
|
|
122
|
+
sortDesc: "lucide:arrow-down-wide-narrow",
|
|
123
|
+
columns: "lucide:columns-3-cog",
|
|
124
|
+
filter: "lucide:filter",
|
|
125
|
+
link: "lucide:link-2",
|
|
126
|
+
linkOff: "lucide:link-2-off",
|
|
127
|
+
ellipsisVertical: "lucide:ellipsis-vertical",
|
|
128
|
+
heading2: "lucide:heading-2",
|
|
129
|
+
heading3: "lucide:heading-3",
|
|
130
|
+
heading4: "lucide:heading-4",
|
|
131
|
+
list: "lucide:list",
|
|
132
|
+
listOrdered: "lucide:list-ordered",
|
|
133
|
+
checkSquare: "lucide:check-square",
|
|
134
|
+
image: "lucide:image",
|
|
135
|
+
quote: "lucide:quote",
|
|
136
|
+
code: "lucide:code",
|
|
137
|
+
paragraph: "lucide:paragraph",
|
|
138
|
+
pilcrow: "lucide:pilcrow",
|
|
139
|
+
info: "lucide:info",
|
|
140
|
+
bold: "lucide:bold",
|
|
141
|
+
italic: "lucide:italic",
|
|
142
|
+
underline: "lucide:underline",
|
|
143
|
+
strike: "lucide:strikethrough"
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
function prepareMergeConfigs({ nuxt, options }) {
|
|
147
|
+
nuxt.options.runtimeConfig.public = defu(nuxt.options.runtimeConfig.public || {}, {
|
|
148
|
+
fluxorUrl: options.fluxorUrl,
|
|
149
|
+
version: ""
|
|
150
|
+
});
|
|
151
|
+
nuxt.options.runtimeConfig.nitro ||= {};
|
|
152
|
+
nuxt.options.runtimeConfig.nitro.envPrefix = options.envPrefix;
|
|
153
|
+
nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
|
|
154
|
+
icons
|
|
155
|
+
});
|
|
156
|
+
nuxt.options.ui = defu(nuxt.options.ui || {}, {
|
|
157
|
+
colorMode: true,
|
|
158
|
+
fonts: true
|
|
159
|
+
});
|
|
160
|
+
nuxt.options.colorMode = defu(nuxt.options.colorMode || {}, {
|
|
161
|
+
storageKey: `${options.name}-color-mode`
|
|
162
|
+
});
|
|
163
|
+
nuxt.options.mdc = defu(nuxt.options.mdc || {}, {
|
|
164
|
+
components: {
|
|
165
|
+
map: {
|
|
166
|
+
"uplora-image": "ProseUploraImage"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
nuxt.options.auth = defu(nuxt.options.auth || {}, {
|
|
171
|
+
name: `${options.name}-session`
|
|
172
|
+
});
|
|
173
|
+
nuxt.options.runtimeConfig.uplora = defu(nuxt.options.runtimeConfig.uplora || {}, {
|
|
174
|
+
url: options.uploraUrl,
|
|
175
|
+
apiKey: ""
|
|
176
|
+
});
|
|
78
177
|
}
|
|
79
178
|
|
|
80
179
|
function prepareServerRoutes({ resolve }) {
|
|
@@ -114,6 +213,20 @@ const buttonDelete = {
|
|
|
114
213
|
}
|
|
115
214
|
};
|
|
116
215
|
|
|
216
|
+
const editorContentFull = {
|
|
217
|
+
slots: {
|
|
218
|
+
root: "h-full w-full relative",
|
|
219
|
+
editor: "min-h-full w-full focus:outline-none editor-content-full relative"
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const editorContentLight = {
|
|
224
|
+
slots: {
|
|
225
|
+
root: "relative",
|
|
226
|
+
editor: "w-full focus:outline-none editor-content-light relative"
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
117
230
|
const formPanel = {
|
|
118
231
|
slots: {
|
|
119
232
|
root: "",
|
|
@@ -161,6 +274,22 @@ const inputSlug = {
|
|
|
161
274
|
}
|
|
162
275
|
};
|
|
163
276
|
|
|
277
|
+
const inputUploraImage = {
|
|
278
|
+
slots: {
|
|
279
|
+
root: "relative w-full rounded-md overflow-hidden border border-default aspect-3/2 text-sm",
|
|
280
|
+
image: "",
|
|
281
|
+
imageActions: "absolute top-4 right-4 flex gap-2",
|
|
282
|
+
uploader: "flex flex-col items-center justify-center w-full h-full p-4",
|
|
283
|
+
uploaderPendingIcon: "size-6 animate-spin",
|
|
284
|
+
uploaderIdleButton: "cursor-pointer bg-muted/50 border border-default border-dashed rounded-md h-full w-full",
|
|
285
|
+
uploaderIdleIcon: "size-10 text-primary",
|
|
286
|
+
uploaderIdleText: "mt-2 font-medium",
|
|
287
|
+
uploaderIdleExtensions: "mt-2 text-xs text-muted uppercase",
|
|
288
|
+
uploaderErrorText: "text-center font-medium",
|
|
289
|
+
uploaderErrorActions: "flex gap-2 mt-4"
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
164
293
|
const modalConfirm = {
|
|
165
294
|
slots: {
|
|
166
295
|
root: ""
|
|
@@ -231,11 +360,14 @@ const theme = {
|
|
|
231
360
|
buttonClear: buttonClear,
|
|
232
361
|
buttonCopy: buttonCopy,
|
|
233
362
|
buttonDelete: buttonDelete,
|
|
363
|
+
editorContentFull: editorContentFull,
|
|
364
|
+
editorContentLight: editorContentLight,
|
|
234
365
|
formPanel: formPanel,
|
|
235
366
|
formPanelAsideSection: formPanelAsideSection,
|
|
236
367
|
formPanelSection: formPanelSection,
|
|
237
368
|
inputSeo: inputSeo,
|
|
238
369
|
inputSlug: inputSlug,
|
|
370
|
+
inputUploraImage: inputUploraImage,
|
|
239
371
|
modalConfirm: modalConfirm,
|
|
240
372
|
tableCellPreview: tableCellPreview,
|
|
241
373
|
tableCellSeo: tableCellSeo,
|
|
@@ -271,7 +403,7 @@ const callout = {
|
|
|
271
403
|
|
|
272
404
|
const uploraImage$1 = {
|
|
273
405
|
slots: {
|
|
274
|
-
root: "
|
|
406
|
+
root: ""
|
|
275
407
|
}
|
|
276
408
|
};
|
|
277
409
|
|
|
@@ -410,14 +542,6 @@ function prepareTemplates(context) {
|
|
|
410
542
|
}
|
|
411
543
|
}
|
|
412
544
|
|
|
413
|
-
const icons = {
|
|
414
|
-
sortAsc: "lucide:arrow-up-wide-narrow",
|
|
415
|
-
sortDesc: "lucide:arrow-down-wide-narrow",
|
|
416
|
-
columns: "lucide:columns-3-cog",
|
|
417
|
-
filter: "lucide:filter",
|
|
418
|
-
link: "lucide:link-2"
|
|
419
|
-
};
|
|
420
|
-
|
|
421
545
|
const module = defineNuxtModule({
|
|
422
546
|
meta: {
|
|
423
547
|
name,
|
|
@@ -427,49 +551,12 @@ const module = defineNuxtModule({
|
|
|
427
551
|
defaults: defaultModuleOptions,
|
|
428
552
|
async setup(options, nuxt) {
|
|
429
553
|
const context = createContext(options, nuxt);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
version: ""
|
|
433
|
-
});
|
|
434
|
-
nuxt.options.runtimeConfig.nitro ||= {};
|
|
435
|
-
nuxt.options.runtimeConfig.nitro.envPrefix = options.envPrefix;
|
|
436
|
-
nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
|
|
437
|
-
icons
|
|
438
|
-
});
|
|
439
|
-
nuxt.options.ui = defu(nuxt.options.ui || {}, {
|
|
440
|
-
colorMode: true,
|
|
441
|
-
fonts: true
|
|
442
|
-
});
|
|
443
|
-
nuxt.options.colorMode = defu(nuxt.options.colorMode || {}, {
|
|
444
|
-
storageKey: `${options.name}-color-mode`
|
|
445
|
-
});
|
|
446
|
-
nuxt.options.mdc = defu(nuxt.options.mdc || {}, {
|
|
447
|
-
components: {
|
|
448
|
-
map: {
|
|
449
|
-
"uplora-image": "ProseUploraImage"
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
nuxt.options.auth = defu(nuxt.options.auth || {}, {
|
|
454
|
-
name: `${options.name}-session`
|
|
455
|
-
});
|
|
456
|
-
if (!hasNuxtModule("@nuxt/ui-pro")) {
|
|
457
|
-
await installModule("@nuxt/ui-pro");
|
|
458
|
-
}
|
|
459
|
-
if (!hasNuxtModule("@nuxtjs/mdc")) {
|
|
460
|
-
await installModule("@nuxtjs/mdc");
|
|
461
|
-
}
|
|
462
|
-
if (!hasNuxtModule("@vueuse/nuxt")) {
|
|
463
|
-
await installModule("@vueuse/nuxt");
|
|
464
|
-
}
|
|
465
|
-
if (!hasNuxtModule("nuxt-auth-utils")) {
|
|
466
|
-
await installModule("nuxt-auth-utils");
|
|
467
|
-
}
|
|
468
|
-
nuxt.options.alias["#cms"] = context.resolve("./runtime");
|
|
469
|
-
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, defaultCMSConfig);
|
|
554
|
+
prepareMergeConfigs(context);
|
|
555
|
+
await prepareInstallModules();
|
|
470
556
|
prepareAutoImports(context);
|
|
471
557
|
prepareTemplates(context);
|
|
472
558
|
prepareServerRoutes(context);
|
|
559
|
+
await prepareGenerateEnv(context);
|
|
473
560
|
}
|
|
474
561
|
});
|
|
475
562
|
|
|
@@ -31,8 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
<script>
|
|
33
33
|
import theme from "#build/cms/autocomplete-select";
|
|
34
|
-
import { computed, ref, refDebounced, shallowRef, toRaw, triggerRef, useAppConfig, useAsyncData, useId, useNuxtData, watch } from "#imports";
|
|
35
|
-
import { useInfiniteScroll, useOffsetPagination } from "@vueuse/core";
|
|
34
|
+
import { computed, ref, refDebounced, shallowRef, toRaw, triggerRef, useAppConfig, useAsyncData, useId, useInfiniteScroll, useNuxtData, useOffsetPagination, watch } from "#imports";
|
|
36
35
|
import { tv } from "../utils/tv";
|
|
37
36
|
</script>
|
|
38
37
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
:color="color"
|
|
11
11
|
:variant="variant"
|
|
12
12
|
:size="size"
|
|
13
|
+
:icon="icon"
|
|
13
14
|
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
14
15
|
auto-loading
|
|
15
16
|
@click="handleDeleteClick()"
|
|
@@ -34,6 +35,7 @@ const props = defineProps({
|
|
|
34
35
|
tooltipText: { type: String, required: false },
|
|
35
36
|
color: { type: null, required: false, default: "error" },
|
|
36
37
|
variant: { type: null, required: false },
|
|
38
|
+
icon: { type: null, required: false },
|
|
37
39
|
size: { type: null, required: false },
|
|
38
40
|
class: { type: null, required: false },
|
|
39
41
|
ui: { type: null, required: false },
|
|
@@ -47,9 +49,8 @@ function handleDeleteClick() {
|
|
|
47
49
|
...props.modalProps,
|
|
48
50
|
title: props.title ?? "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435",
|
|
49
51
|
message: props.message ?? "\u0412\u044B \u0434\u0435\u0438\u0306\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043B\u0438\u0442\u044C?",
|
|
50
|
-
color:
|
|
52
|
+
color: "error",
|
|
51
53
|
variant: props.variant,
|
|
52
|
-
size: props.size,
|
|
53
54
|
confirmLabel: props.confirmLabel,
|
|
54
55
|
confirmText: props.confirmText,
|
|
55
56
|
onConfirm: props.onConfirm
|
|
@@ -15,6 +15,7 @@ export interface ButtonDeleteProps extends Pick<ModalConfirmProps, 'onConfirm'>
|
|
|
15
15
|
tooltipText?: string;
|
|
16
16
|
color?: ButtonProps['color'];
|
|
17
17
|
variant?: ButtonProps['variant'];
|
|
18
|
+
icon?: ButtonProps['icon'];
|
|
18
19
|
size?: ButtonProps['size'];
|
|
19
20
|
class?: any;
|
|
20
21
|
ui?: ButtonDelete['slots'];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<ProseKit :editor="editor">
|
|
4
|
+
<div ref="editorRef" :class="ui.editor({ class: [props.ui?.editor, 'pl-14'] })" />
|
|
5
|
+
|
|
6
|
+
<BlockMenu />
|
|
7
|
+
<SlashCommand />
|
|
8
|
+
<TooltipMenu />
|
|
9
|
+
</ProseKit>
|
|
10
|
+
</Primitive>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import theme from "#build/cms/editor-content-full";
|
|
15
|
+
import { computed, useAppConfig, useTemplateRef, watchPostEffect } from "#imports";
|
|
16
|
+
import { createEditor } from "prosekit/core";
|
|
17
|
+
import { ProseKit, useDocChange } from "prosekit/vue";
|
|
18
|
+
import { Primitive } from "reka-ui";
|
|
19
|
+
import BlockMenu from "../editor/components/BlockMenu.vue";
|
|
20
|
+
import SlashCommand from "../editor/components/SlashCommand.vue";
|
|
21
|
+
import TooltipMenu from "../editor/components/TooltipMenu.vue";
|
|
22
|
+
import { defineFullExtension } from "../editor/extensions";
|
|
23
|
+
import { docToMarkdown, markdownToDoc } from "../editor/markdown";
|
|
24
|
+
import { tv } from "../utils/tv";
|
|
25
|
+
import "prosekit/basic/style.css";
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<script setup>
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
as: { type: null, required: false },
|
|
31
|
+
class: { type: null, required: false },
|
|
32
|
+
ui: { type: null, required: false }
|
|
33
|
+
});
|
|
34
|
+
const modelValue = defineModel({ type: String, ...{ default: "" } });
|
|
35
|
+
const appConfig = useAppConfig();
|
|
36
|
+
const editor = createEditor({
|
|
37
|
+
extension: defineFullExtension(),
|
|
38
|
+
defaultContent: await markdownToDoc(modelValue.value)
|
|
39
|
+
});
|
|
40
|
+
const editorRef = useTemplateRef("editorRef");
|
|
41
|
+
useDocChange(async () => {
|
|
42
|
+
modelValue.value = await docToMarkdown(editor.getDocJSON());
|
|
43
|
+
}, { editor });
|
|
44
|
+
watchPostEffect((onCleanup) => {
|
|
45
|
+
editor.mount(editorRef.value);
|
|
46
|
+
onCleanup(() => editor.unmount());
|
|
47
|
+
});
|
|
48
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editorContentFull || {} })());
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<style scoped>
|
|
52
|
+
::v-deep(.editor-content-full){line-height:calc(var(--spacing)*7)}::v-deep(.editor-content-full) [data-placeholder]:before{color:var(--ui-text-dimmed);content:attr(data-placeholder);height:0;pointer-events:none;position:absolute}::v-deep(.editor-content-full) h2,::v-deep(.editor-content-full) h3,::v-deep(.editor-content-full) h4{font-weight:600;margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) h2{font-size:var(--text-2xl)}::v-deep(.editor-content-full) h3{font-size:var(--text-xl)}::v-deep(.editor-content-full) h4{font-size:var(--text-lg)}::v-deep(.editor-content-full) blockquote{border-left:4px solid var(--ui-border-accented);margin-block:calc(var(--spacing)*4);padding-inline-start:calc(var(--spacing)*4)}::v-deep(.editor-content-full) [data-node-view-root=true],::v-deep(.editor-content-full)>p{margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) hr{border-block-start:1px solid var(--ui-border);margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) pre{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);line-height:calc(var(--spacing)*6);overflow-x:auto;padding-block:calc(var(--spacing)*3);padding-inline:calc(var(--spacing)*4)}::v-deep(.editor-content-full) p>code{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);padding-inline:var(--spacing)}::v-deep(.editor-content-full) a{color:var(--ui-primary);cursor:pointer;text-decoration:underline;-webkit-user-select:all;-moz-user-select:all;user-select:all}
|
|
53
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ComponentConfig } from '../types';
|
|
3
|
+
import theme from '#build/cms/editor-content-full';
|
|
4
|
+
import 'prosekit/basic/style.css';
|
|
5
|
+
type EditorContentFull = ComponentConfig<typeof theme, AppConfig, 'editorContentFull'>;
|
|
6
|
+
export interface EditorContentFullProps {
|
|
7
|
+
as?: any;
|
|
8
|
+
class?: any;
|
|
9
|
+
ui?: EditorContentFull['slots'];
|
|
10
|
+
}
|
|
11
|
+
declare const _default: import("vue").DefineComponent<EditorContentFullProps & {
|
|
12
|
+
modelValue?: string;
|
|
13
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
+
"update:modelValue": (value: string) => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<EditorContentFullProps & {
|
|
16
|
+
modelValue?: string;
|
|
17
|
+
}> & Readonly<{
|
|
18
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<ProseKit :editor="editor">
|
|
4
|
+
<div ref="editorRef" :class="ui.editor({ class: props.ui?.editor })" />
|
|
5
|
+
</ProseKit>
|
|
6
|
+
</Primitive>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import theme from "#build/cms/editor-content-light";
|
|
11
|
+
import { computed, useAppConfig, useTemplateRef, watchPostEffect } from "#imports";
|
|
12
|
+
import { createEditor } from "prosekit/core";
|
|
13
|
+
import { ProseKit, useDocChange } from "prosekit/vue";
|
|
14
|
+
import { Primitive } from "reka-ui";
|
|
15
|
+
import { defineLightExtension } from "../editor/extensions";
|
|
16
|
+
import { docToMarkdown, markdownToDoc } from "../editor/markdown";
|
|
17
|
+
import { tv } from "../utils/tv";
|
|
18
|
+
import "prosekit/basic/style.css";
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<script setup>
|
|
22
|
+
const props = defineProps({
|
|
23
|
+
as: { type: null, required: false },
|
|
24
|
+
class: { type: null, required: false },
|
|
25
|
+
ui: { type: null, required: false }
|
|
26
|
+
});
|
|
27
|
+
const modelValue = defineModel({ type: String, ...{ default: "" } });
|
|
28
|
+
const appConfig = useAppConfig();
|
|
29
|
+
const editor = createEditor({
|
|
30
|
+
extension: defineLightExtension(),
|
|
31
|
+
defaultContent: await markdownToDoc(modelValue.value)
|
|
32
|
+
});
|
|
33
|
+
const editorRef = useTemplateRef("editorRef");
|
|
34
|
+
useDocChange(async () => {
|
|
35
|
+
modelValue.value = await docToMarkdown(editor.getDocJSON());
|
|
36
|
+
}, { editor });
|
|
37
|
+
watchPostEffect((onCleanup) => {
|
|
38
|
+
editor.mount(editorRef.value);
|
|
39
|
+
onCleanup(() => editor.unmount());
|
|
40
|
+
});
|
|
41
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editorContentLight || {} })());
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
::v-deep(.editor-content-light){line-height:calc(var(--spacing)*7)}::v-deep(.editor-content-light) [data-placeholder]:before{color:var(--ui-text-dimmed);content:attr(data-placeholder);height:0;pointer-events:none;position:absolute}::v-deep(.editor-content-light) blockquote{border-left:4px solid var(--ui-border-accented);margin-block:calc(var(--spacing)*4);padding-inline-start:calc(var(--spacing)*4)}::v-deep(.editor-content-light) [data-node-view-root=true],::v-deep(.editor-content-light)>p{margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-light) pre{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);line-height:calc(var(--spacing)*6);overflow-x:auto;padding-block:calc(var(--spacing)*3);padding-inline:calc(var(--spacing)*4)}::v-deep(.editor-content-light) p>code{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);padding-inline:var(--spacing)}::v-deep(.editor-content-light) a{color:var(--ui-primary);cursor:pointer;text-decoration:underline;-webkit-user-select:all;-moz-user-select:all;user-select:all}
|
|
46
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ComponentConfig } from '../types';
|
|
3
|
+
import theme from '#build/cms/editor-content-light';
|
|
4
|
+
import 'prosekit/basic/style.css';
|
|
5
|
+
type EditorContentLight = ComponentConfig<typeof theme, AppConfig, 'editorContentLight'>;
|
|
6
|
+
export interface EditorContentLightProps {
|
|
7
|
+
as?: any;
|
|
8
|
+
class?: any;
|
|
9
|
+
ui?: EditorContentLight['slots'];
|
|
10
|
+
}
|
|
11
|
+
declare const _default: import("vue").DefineComponent<EditorContentLightProps & {
|
|
12
|
+
modelValue?: string;
|
|
13
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
+
"update:modelValue": (value: string) => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<EditorContentLightProps & {
|
|
16
|
+
modelValue?: string;
|
|
17
|
+
}> & Readonly<{
|
|
18
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
export default _default;
|