@hywax/cms 0.0.1 → 0.0.3
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/button-clear.ts +5 -0
- package/.nuxt/cms/index.ts +2 -0
- package/.nuxt/cms/prose/index.ts +1 -0
- package/.nuxt/cms/prose/uplora-image.ts +5 -0
- package/.nuxt/cms/uplora-image.ts +8 -0
- package/.nuxt/cms.css +1 -0
- package/cli/commands/make/component.mjs +75 -0
- package/cli/commands/make/index.mjs +12 -0
- package/cli/index.mjs +15 -0
- package/cli/package.json +13 -0
- package/cli/templates.mjs +101 -0
- package/cli/utils.mjs +31 -0
- package/dist/module.d.mts +26 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +185 -4
- package/dist/runtime/components/ButtonClear.vue +35 -0
- package/dist/runtime/components/ButtonClear.vue.d.ts +35 -0
- package/dist/runtime/components/UploraImage.vue +108 -0
- package/dist/runtime/components/UploraImage.vue.d.ts +34 -0
- package/dist/runtime/components/prose/UploraImage.vue +23 -0
- package/dist/runtime/components/prose/UploraImage.vue.d.ts +13 -0
- package/dist/runtime/composables/useApi.d.ts +14 -0
- package/dist/runtime/composables/useApi.js +16 -0
- package/dist/runtime/composables/useSeoStats.d.ts +12 -0
- package/dist/runtime/composables/useSeoStats.js +44 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/plugins/api.d.ts +6 -0
- package/dist/runtime/plugins/api.js +26 -0
- package/dist/runtime/types/app.config.d.ts +6 -0
- package/dist/runtime/types/image.d.ts +48 -0
- package/dist/runtime/types/image.js +0 -0
- package/dist/runtime/types/index.d.ts +5 -0
- package/dist/runtime/types/index.js +5 -0
- package/dist/runtime/types/seo.d.ts +4 -0
- package/dist/runtime/types/seo.js +0 -0
- package/dist/runtime/types/tv.d.ts +53 -0
- package/dist/runtime/types/tv.js +0 -0
- package/dist/runtime/types/utils.d.ts +3 -0
- package/dist/runtime/types/utils.js +1 -0
- package/dist/runtime/utils/image.d.ts +30 -0
- package/dist/runtime/utils/image.js +81 -0
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/tv.d.ts +1 -0
- package/dist/runtime/utils/tv.js +4 -0
- package/dist/types.d.mts +2 -0
- package/package.json +43 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as uploraImage } from './uplora-image'
|
package/.nuxt/cms.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@source "./cms";
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync, promises as fsp } from 'node:fs'
|
|
2
|
+
import process from 'node:process'
|
|
3
|
+
import { defineCommand } from 'citty'
|
|
4
|
+
import { consola } from 'consola'
|
|
5
|
+
import { resolve } from 'pathe'
|
|
6
|
+
import { camelCase, kebabCase, splitByCase, upperFirst } from 'scule'
|
|
7
|
+
import templates from '../../templates.mjs'
|
|
8
|
+
import { appendFile, sortFile } from '../../utils.mjs'
|
|
9
|
+
|
|
10
|
+
export default defineCommand({
|
|
11
|
+
meta: {
|
|
12
|
+
name: 'component',
|
|
13
|
+
description: 'Создать новый компонент',
|
|
14
|
+
},
|
|
15
|
+
args: {
|
|
16
|
+
name: {
|
|
17
|
+
type: 'positional',
|
|
18
|
+
required: true,
|
|
19
|
+
description: 'Имя компонента',
|
|
20
|
+
},
|
|
21
|
+
prose: {
|
|
22
|
+
type: 'boolean',
|
|
23
|
+
description: 'Создать компонент для контента',
|
|
24
|
+
},
|
|
25
|
+
template: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'Сгенерировать только шаблон',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
async setup({ args }) {
|
|
31
|
+
const name = args.name
|
|
32
|
+
if (!name) {
|
|
33
|
+
consola.error('`name` argument is missing!')
|
|
34
|
+
process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const path = resolve('.')
|
|
38
|
+
|
|
39
|
+
for (const template of Object.keys(templates)) {
|
|
40
|
+
if (args.template && template !== args.template) {
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const { filename, contents } = templates[template](args)
|
|
45
|
+
if (!contents) {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const filePath = resolve(path, filename)
|
|
50
|
+
|
|
51
|
+
if (existsSync(filePath)) {
|
|
52
|
+
consola.error(`🚨 ${filePath} уже существует!`)
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await fsp.writeFile(filePath, `${contents.trim()}\n`)
|
|
57
|
+
|
|
58
|
+
consola.success(`🪄 ${filePath} создан!`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (args.template) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const themePath = resolve(path, `src/theme/${args.prose ? 'prose/' : ''}index.ts`)
|
|
66
|
+
await appendFile(themePath, `export { default as ${camelCase(name)} } from './${kebabCase(name)}'`)
|
|
67
|
+
await sortFile(themePath)
|
|
68
|
+
|
|
69
|
+
if (!args.prose) {
|
|
70
|
+
const typesPath = resolve(path, 'src/runtime/types/index.ts')
|
|
71
|
+
await appendFile(typesPath, `export * from '../components/${splitByCase(name).map((p) => upperFirst(p)).join('')}.vue'`)
|
|
72
|
+
await sortFile(typesPath)
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
})
|
package/cli/index.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineCommand, runMain } from 'citty'
|
|
3
|
+
import make from './commands/make/index.mjs'
|
|
4
|
+
|
|
5
|
+
const main = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: 'cms',
|
|
8
|
+
description: 'Hywax CMS CLI',
|
|
9
|
+
},
|
|
10
|
+
subCommands: {
|
|
11
|
+
make,
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
runMain(main)
|
package/cli/package.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { camelCase, kebabCase, splitByCase, upperFirst } from 'scule'
|
|
2
|
+
|
|
3
|
+
function component({ name, prose }) {
|
|
4
|
+
const upperName = splitByCase(name).map((p) => upperFirst(p)).join('')
|
|
5
|
+
const camelName = camelCase(name)
|
|
6
|
+
const kebabName = kebabCase(name)
|
|
7
|
+
const path = 'cms'
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
filename: `src/runtime/components/${prose ? 'prose/' : ''}${upperName}.vue`,
|
|
11
|
+
contents: `
|
|
12
|
+
<template>
|
|
13
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
14
|
+
<slot />
|
|
15
|
+
</Primitive>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script lang="ts">
|
|
19
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
20
|
+
import type { ComponentConfig } from '${prose ? '../../types' : '../types'}'
|
|
21
|
+
import theme from '#build/${path}/${prose ? 'prose/' : ''}${kebabName}'
|
|
22
|
+
import { computed, useAppConfig } from '#imports'
|
|
23
|
+
import { Primitive } from 'reka-ui'
|
|
24
|
+
import { tv } from '${prose ? '../../utils/tv' : '../utils/tv'}'
|
|
25
|
+
|
|
26
|
+
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}>
|
|
27
|
+
|
|
28
|
+
export interface ${upperName}Props {
|
|
29
|
+
as?: any
|
|
30
|
+
class?: any
|
|
31
|
+
ui?: ${upperName}['slots']
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ${upperName}Emits {
|
|
35
|
+
// 'update:modelValue': [string]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ${upperName}Slots {
|
|
39
|
+
default?: () => any
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
const props = defineProps<${upperName}Props>()
|
|
45
|
+
const emit = defineEmits<${upperName}Emits>()
|
|
46
|
+
defineSlots<${upperName}Slots>()
|
|
47
|
+
|
|
48
|
+
const appConfig = useAppConfig() as ${upperName}['AppConfig']
|
|
49
|
+
|
|
50
|
+
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.cms?.${camelName} || {}) })())
|
|
51
|
+
</script>
|
|
52
|
+
`,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function test({ name, prose }) {
|
|
57
|
+
const upperName = splitByCase(name).map((p) => upperFirst(p)).join('')
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
filename: `test/runtime/components/${upperName}.spec.ts`,
|
|
61
|
+
contents: prose
|
|
62
|
+
? undefined
|
|
63
|
+
: `
|
|
64
|
+
import type { ${upperName}Props, ${upperName}Slots } from '../../../src/runtime/components/${upperName}.vue'
|
|
65
|
+
import { describe, it, expect } from 'vitest'
|
|
66
|
+
import ${upperName} from '../../../src/runtime/components/${upperName}.vue'
|
|
67
|
+
import ComponentRender from '../../component-render'
|
|
68
|
+
|
|
69
|
+
describe('${upperName}', () => {
|
|
70
|
+
it.each([
|
|
71
|
+
// Props
|
|
72
|
+
['с алиасом', { props: { as: 'section' } }],
|
|
73
|
+
['с class', { props: { class: '' } }],
|
|
74
|
+
['с ui', { props: { ui: {} } }],
|
|
75
|
+
// Slots
|
|
76
|
+
['с дефолтным слотом', { slots: { default: () => 'Default slot' } }]
|
|
77
|
+
])('рендерит %s корректно', async (nameOrHtml: string, options: { props?: ${upperName}Props, slots?: Partial<${upperName}Slots> }) => {
|
|
78
|
+
const html = await ComponentRender(nameOrHtml, options, ${upperName})
|
|
79
|
+
expect(html).toMatchSnapshot()
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
`,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function theme({ name, prose }) {
|
|
87
|
+
const kebabName = kebabCase(name)
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
filename: `src/theme/${prose ? 'prose/' : ''}${kebabName}.ts`,
|
|
91
|
+
contents: `
|
|
92
|
+
export default {
|
|
93
|
+
slots: {
|
|
94
|
+
root: '',
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
`,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default { component, test, theme }
|
package/cli/utils.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { promises as fsp } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
export async function sortFile(path) {
|
|
4
|
+
const file = await fsp.readFile(path, 'utf-8')
|
|
5
|
+
|
|
6
|
+
const lines = file.trim().split('\n').sort()
|
|
7
|
+
|
|
8
|
+
await fsp.writeFile(path, `${lines.join('\n')}\n`)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function appendFile(path, contents) {
|
|
12
|
+
const file = await fsp.readFile(path, 'utf-8')
|
|
13
|
+
|
|
14
|
+
if (!file.includes(contents)) {
|
|
15
|
+
await fsp.writeFile(path, `${file.trim()}\n${contents}\n`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function normalizeLocale(locale) {
|
|
20
|
+
if (!locale) {
|
|
21
|
+
return ''
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (locale.includes('_')) {
|
|
25
|
+
return locale.split('_')
|
|
26
|
+
.map((part, index) => index === 0 ? part.toLowerCase() : part.toUpperCase())
|
|
27
|
+
.join('-')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return locale.toLowerCase()
|
|
31
|
+
}
|
package/dist/module.d.mts
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
export * from '../dist/runtime/types/index.js';
|
|
3
|
+
|
|
4
|
+
declare module '@nuxt/schema' {
|
|
5
|
+
interface ConfigSchema {
|
|
6
|
+
public?: {
|
|
7
|
+
cms: {
|
|
8
|
+
fluxorUrl: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
2
13
|
|
|
3
14
|
interface ModuleOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Name of the module
|
|
17
|
+
* @defaultValue 'cms'
|
|
18
|
+
*/
|
|
19
|
+
name?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Prefix for the components
|
|
22
|
+
* @defaultValue 'C'
|
|
23
|
+
*/
|
|
24
|
+
prefix?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Fluxor URL
|
|
27
|
+
* @defaultValue 'https://fluxor.uplora.ru'
|
|
28
|
+
*/
|
|
29
|
+
fluxorUrl?: string;
|
|
4
30
|
}
|
|
5
31
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
6
32
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,7 +1,131 @@
|
|
|
1
|
-
import { defineNuxtModule } from '@nuxt/kit';
|
|
1
|
+
import { addTypeTemplate, addTemplate, defineNuxtModule, hasNuxtModule, installModule, createResolver, addComponentsDir, addImportsDir, addPlugin } from '@nuxt/kit';
|
|
2
|
+
import { defu } from 'defu';
|
|
3
|
+
import 'node:url';
|
|
4
|
+
import { kebabCase } from 'scule';
|
|
2
5
|
|
|
3
6
|
const name = "@hywax/cms";
|
|
4
|
-
const version = "0.0.
|
|
7
|
+
const version = "0.0.3";
|
|
8
|
+
|
|
9
|
+
const buttonClear = {
|
|
10
|
+
slots: {
|
|
11
|
+
base: "p-0"
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const uploraImage$1 = {
|
|
16
|
+
slots: {
|
|
17
|
+
root: "relative grid grid-cols-[100%] grid-rows-[100%] overflow-hidden",
|
|
18
|
+
lqip: "bg-cover bg-no-repeat bg-center col-[1] row-[1]",
|
|
19
|
+
picture: "aspect-3/2 col-[1] row-[1]",
|
|
20
|
+
img: "w-full h-full block object-cover"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const theme = {
|
|
25
|
+
__proto__: null,
|
|
26
|
+
buttonClear: buttonClear,
|
|
27
|
+
uploraImage: uploraImage$1
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const uploraImage = {
|
|
31
|
+
slots: {
|
|
32
|
+
base: ""
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const themeProse = {
|
|
37
|
+
__proto__: null,
|
|
38
|
+
uploraImage: uploraImage
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function getTemplates(options) {
|
|
42
|
+
const templates = [];
|
|
43
|
+
function writeThemeTemplate(theme2, path) {
|
|
44
|
+
for (const component in theme2) {
|
|
45
|
+
templates.push({
|
|
46
|
+
filename: `cms/${path ? `${path}/` : ""}${kebabCase(component)}.ts`,
|
|
47
|
+
write: true,
|
|
48
|
+
getContents: async () => {
|
|
49
|
+
const template = theme2[component];
|
|
50
|
+
const result = typeof template === "function" ? template(options) : template;
|
|
51
|
+
const variants = Object.entries(result.variants || {}).filter(([_, values]) => {
|
|
52
|
+
const keys = Object.keys(values);
|
|
53
|
+
return keys.some((key) => key !== "true" && key !== "false");
|
|
54
|
+
}).map(([key]) => key);
|
|
55
|
+
let json = JSON.stringify(result, null, 2);
|
|
56
|
+
for (const variant of variants) {
|
|
57
|
+
json = json.replace(new RegExp(`("${variant}": "[^"]+")`, "g"), `$1 as typeof ${variant}[number]`);
|
|
58
|
+
json = json.replace(new RegExp(`("${variant}": \\[\\s*)((?:"[^"]+",?\\s*)+)(\\])`, "g"), (_, before, match, after) => {
|
|
59
|
+
const replaced = match.replace(/("[^"]+")/g, `$1 as typeof ${variant}[number]`);
|
|
60
|
+
return `${before}${replaced}${after}`;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function generateVariantDeclarations(variants2) {
|
|
64
|
+
return variants2.filter((variant) => json.includes(`as typeof ${variant}`)).map((variant) => {
|
|
65
|
+
const keys = Object.keys(result.variants[variant]);
|
|
66
|
+
return `const ${variant} = ${JSON.stringify(keys, null, 2)} as const`;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return [
|
|
70
|
+
...generateVariantDeclarations(variants),
|
|
71
|
+
`export default ${json}`
|
|
72
|
+
].join("\n\n");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
writeThemeTemplate(themeProse, "prose");
|
|
78
|
+
writeThemeTemplate(theme);
|
|
79
|
+
templates.push({
|
|
80
|
+
filename: `cms/prose/index.ts`,
|
|
81
|
+
write: true,
|
|
82
|
+
getContents: () => Object.keys(themeProse).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n")
|
|
83
|
+
});
|
|
84
|
+
templates.push({
|
|
85
|
+
filename: "cms.css",
|
|
86
|
+
write: true,
|
|
87
|
+
getContents: () => `@source "./cms";`
|
|
88
|
+
});
|
|
89
|
+
templates.push({
|
|
90
|
+
filename: "cms/index.ts",
|
|
91
|
+
write: true,
|
|
92
|
+
getContents: () => {
|
|
93
|
+
return Object.keys(theme).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n");
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
templates.push({
|
|
97
|
+
filename: "types/cms.d.ts",
|
|
98
|
+
getContents: () => `import * as cms from '#build/cms'
|
|
99
|
+
import type { TVConfig } from '@nuxt/ui'
|
|
100
|
+
|
|
101
|
+
type AppConfigCMS = TVConfig<typeof cms>
|
|
102
|
+
|
|
103
|
+
declare module '@nuxt/schema' {
|
|
104
|
+
interface AppConfigInput {
|
|
105
|
+
/**
|
|
106
|
+
* CMS theme configuration
|
|
107
|
+
*/
|
|
108
|
+
cms?: AppConfigCMS
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export {}
|
|
113
|
+
`
|
|
114
|
+
});
|
|
115
|
+
return templates;
|
|
116
|
+
}
|
|
117
|
+
function addTemplates(options) {
|
|
118
|
+
const templates = getTemplates(options);
|
|
119
|
+
for (const template of templates) {
|
|
120
|
+
if (template.filename.endsWith(".d.ts")) {
|
|
121
|
+
addTypeTemplate(template);
|
|
122
|
+
} else {
|
|
123
|
+
addTemplate(template);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const icons = {};
|
|
5
129
|
|
|
6
130
|
const module = defineNuxtModule({
|
|
7
131
|
meta: {
|
|
@@ -9,8 +133,65 @@ const module = defineNuxtModule({
|
|
|
9
133
|
version,
|
|
10
134
|
configKey: "cms"
|
|
11
135
|
},
|
|
12
|
-
defaults: {
|
|
13
|
-
|
|
136
|
+
defaults: {
|
|
137
|
+
name: "cms",
|
|
138
|
+
prefix: "C",
|
|
139
|
+
fluxorUrl: "https://fluxor.uplora.ru"
|
|
140
|
+
},
|
|
141
|
+
async setup(options, nuxt) {
|
|
142
|
+
nuxt.options.runtimeConfig.public.cms = defu(nuxt.options.runtimeConfig.public.cms || {}, {
|
|
143
|
+
fluxorUrl: options.fluxorUrl
|
|
144
|
+
});
|
|
145
|
+
nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
|
|
146
|
+
icons
|
|
147
|
+
});
|
|
148
|
+
nuxt.options.ui = defu(nuxt.options.ui || {}, {
|
|
149
|
+
colorMode: true,
|
|
150
|
+
fonts: true
|
|
151
|
+
});
|
|
152
|
+
nuxt.options.colorMode = defu(nuxt.options.colorMode || {}, {
|
|
153
|
+
storageKey: `${options.name}-color-mode`
|
|
154
|
+
});
|
|
155
|
+
nuxt.options.mdc = defu(nuxt.options.mdc || {}, {
|
|
156
|
+
components: {
|
|
157
|
+
map: {
|
|
158
|
+
"uplora-image": "ProseUploraImage"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
nuxt.options.auth = defu(nuxt.options.auth || {}, {
|
|
163
|
+
name: `${options.name}-session`
|
|
164
|
+
});
|
|
165
|
+
if (!hasNuxtModule("@nuxt/ui-pro")) {
|
|
166
|
+
await installModule("@nuxt/ui-pro");
|
|
167
|
+
}
|
|
168
|
+
if (!hasNuxtModule("@nuxtjs/mdc")) {
|
|
169
|
+
await installModule("@nuxtjs/mdc");
|
|
170
|
+
}
|
|
171
|
+
if (!hasNuxtModule("@vueuse/nuxt")) {
|
|
172
|
+
await installModule("@vueuse/nuxt");
|
|
173
|
+
}
|
|
174
|
+
if (!hasNuxtModule("nuxt-auth-utils")) {
|
|
175
|
+
await installModule("nuxt-auth-utils");
|
|
176
|
+
}
|
|
177
|
+
const { resolve } = createResolver(import.meta.url);
|
|
178
|
+
nuxt.options.alias["#cms"] = resolve("./runtime");
|
|
179
|
+
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, {});
|
|
180
|
+
addComponentsDir({
|
|
181
|
+
path: resolve("./runtime/components"),
|
|
182
|
+
pathPrefix: false,
|
|
183
|
+
prefix: options?.prefix || "C",
|
|
184
|
+
ignore: ["prose/**"]
|
|
185
|
+
});
|
|
186
|
+
addComponentsDir({
|
|
187
|
+
path: resolve("./runtime/components/prose"),
|
|
188
|
+
prefix: "Prose",
|
|
189
|
+
pathPrefix: false,
|
|
190
|
+
global: true
|
|
191
|
+
});
|
|
192
|
+
addImportsDir(resolve("./runtime/composables"));
|
|
193
|
+
addTemplates(options);
|
|
194
|
+
addPlugin(resolve("./runtime/plugins/api.ts"));
|
|
14
195
|
}
|
|
15
196
|
});
|
|
16
197
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UButton
|
|
3
|
+
:class="ui.base({ class: [props.ui?.base, props.class] })"
|
|
4
|
+
:color="color"
|
|
5
|
+
:variant="variant"
|
|
6
|
+
:size="size"
|
|
7
|
+
:icon="icon || appConfig.ui.icons.close"
|
|
8
|
+
:aria-label="label"
|
|
9
|
+
:disabled="!modelValue"
|
|
10
|
+
@click.stop="emit('update:modelValue', resetValue)"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import theme from "#build/cms/button-clear";
|
|
16
|
+
import { computed, useAppConfig } from "#imports";
|
|
17
|
+
import { tv } from "../utils/tv";
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
icon: { type: String, required: false },
|
|
23
|
+
label: { type: String, required: false, default: "\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435" },
|
|
24
|
+
color: { type: null, required: false, default: "neutral" },
|
|
25
|
+
variant: { type: null, required: false, default: "link" },
|
|
26
|
+
size: { type: null, required: false, default: "sm" },
|
|
27
|
+
resetValue: { type: [String, Number, Boolean, null], required: false, skipCheck: true, default: void 0 },
|
|
28
|
+
class: { type: null, required: false },
|
|
29
|
+
ui: { type: null, required: false }
|
|
30
|
+
});
|
|
31
|
+
const emit = defineEmits(["update:modelValue"]);
|
|
32
|
+
const modelValue = defineModel({ type: [String, Number, Boolean, null], skipCheck: true });
|
|
33
|
+
const appConfig = useAppConfig();
|
|
34
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.buttonClear || {} })());
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
3
|
+
import type { ComponentConfig } from '../types';
|
|
4
|
+
import theme from '#build/cms/button-clear';
|
|
5
|
+
export type ButtonClear = ComponentConfig<typeof theme, AppConfig, 'buttonClear'>;
|
|
6
|
+
export type ResetValue = string | number | boolean | null | undefined;
|
|
7
|
+
export interface ButtonClearProps {
|
|
8
|
+
icon?: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
color?: ButtonProps['color'];
|
|
11
|
+
variant?: ButtonProps['variant'];
|
|
12
|
+
size?: ButtonProps['size'];
|
|
13
|
+
resetValue?: ResetValue;
|
|
14
|
+
class?: any;
|
|
15
|
+
ui?: ButtonClear['slots'];
|
|
16
|
+
}
|
|
17
|
+
export interface ButtonClearEmits {
|
|
18
|
+
'update:modelValue': [ResetValue];
|
|
19
|
+
}
|
|
20
|
+
declare const _default: import("vue").DefineComponent<ButtonClearProps & {
|
|
21
|
+
modelValue?: ResetValue;
|
|
22
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
|
+
"update:modelValue": (...args: unknown[]) => any;
|
|
24
|
+
}, string, import("vue").PublicProps, Readonly<ButtonClearProps & {
|
|
25
|
+
modelValue?: ResetValue;
|
|
26
|
+
}> & Readonly<{
|
|
27
|
+
"onUpdate:modelValue"?: ((...args: unknown[]) => any) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
size: "xs" | "sm" | "md" | "lg" | "xl";
|
|
30
|
+
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
31
|
+
variant: "solid" | "outline" | "soft" | "subtle" | "ghost" | "link";
|
|
32
|
+
label: string;
|
|
33
|
+
resetValue: string | number | boolean | null;
|
|
34
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
35
|
+
export default _default;
|