vanilla-vue-ui 0.0.0
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/README.md +45 -0
- package/basic/range/WRange.stories.ts +61 -0
- package/basic/range/WRange.vue +93 -0
- package/package.json +73 -0
- package/types/ClassObject.ts +21 -0
- package/util/deepMergeClassObject.ts +13 -0
- package/util/index.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# vanilla-vue-ui
|
|
2
|
+
|
|
3
|
+
This template should help get you started developing with Vue 3 in Vite.
|
|
4
|
+
|
|
5
|
+
## Recommended IDE Setup
|
|
6
|
+
|
|
7
|
+
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
8
|
+
|
|
9
|
+
## Type Support for `.vue` Imports in TS
|
|
10
|
+
|
|
11
|
+
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
12
|
+
|
|
13
|
+
## Customize configuration
|
|
14
|
+
|
|
15
|
+
See [Vite Configuration Reference](https://vite.dev/config/).
|
|
16
|
+
|
|
17
|
+
## Project Setup
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Compile and Hot-Reload for Development
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm run dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Type-Check, Compile and Minify for Production
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm run build
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Run Unit Tests with [Vitest](https://vitest.dev/)
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npm run test:unit
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Lint with [ESLint](https://eslint.org/)
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
npm run lint
|
|
45
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Replace vue3 with vue if you are using Storybook for Vue 2
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
3
|
+
import WRange from './WRange.vue';
|
|
4
|
+
import { ref, watchEffect } from 'vue';
|
|
5
|
+
|
|
6
|
+
type WRangeProps = InstanceType<typeof WRange>['$props']
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof WRange> = {
|
|
9
|
+
component: WRange,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof WRange>;
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
|
|
17
|
+
* See https://storybook.js.org/docs/api/csf
|
|
18
|
+
* to learn how to use render functions.
|
|
19
|
+
*/
|
|
20
|
+
export const Primary: Story = {
|
|
21
|
+
render: () => ({
|
|
22
|
+
components: { WRange },
|
|
23
|
+
template: '<w-range @customInput="(value) => console.log(`Received customInput event with value:`, value)"></w-range>',
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const PrimaryDataBinding: Story = {
|
|
28
|
+
render: (args: WRangeProps) => ({
|
|
29
|
+
setup() {
|
|
30
|
+
const modelValue = ref(args.modelValue)
|
|
31
|
+
|
|
32
|
+
// `update:modelValue`イベントをリッスンして、内部状態を更新
|
|
33
|
+
watchEffect(() => {
|
|
34
|
+
modelValue.value = args.modelValue;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
...args,
|
|
39
|
+
modelValue,
|
|
40
|
+
updateModelValue: (newValue: number) => {
|
|
41
|
+
modelValue.value = newValue;
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
components: { WRange },
|
|
46
|
+
template: `
|
|
47
|
+
<w-range
|
|
48
|
+
:max="max"
|
|
49
|
+
:min="min"
|
|
50
|
+
:step="step"
|
|
51
|
+
v-model="modelValue"
|
|
52
|
+
></w-range>
|
|
53
|
+
`,
|
|
54
|
+
}),
|
|
55
|
+
args: {
|
|
56
|
+
max: 100,
|
|
57
|
+
min: 0,
|
|
58
|
+
step: 10,
|
|
59
|
+
modelValue: 0
|
|
60
|
+
}
|
|
61
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<input
|
|
3
|
+
type="range"
|
|
4
|
+
class="w-full"
|
|
5
|
+
:class="[
|
|
6
|
+
mergedClasses.content?.base,
|
|
7
|
+
mergedClasses.content?.backgroundColor,
|
|
8
|
+
mergedClasses.content?.rounded,
|
|
9
|
+
mergedClasses.content?.size,
|
|
10
|
+
]"
|
|
11
|
+
:min="min"
|
|
12
|
+
:max="max"
|
|
13
|
+
:step="step"
|
|
14
|
+
:value="modelValue"
|
|
15
|
+
@input="inputValue"
|
|
16
|
+
>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import { defineProps, type PropType, ref } from 'vue'
|
|
21
|
+
import type { ClassObject } from '../../types/ClassObject';
|
|
22
|
+
import { deepMergeClassObject } from '../../util';
|
|
23
|
+
|
|
24
|
+
const props = defineProps({
|
|
25
|
+
min: {
|
|
26
|
+
type: Number as PropType<number>,
|
|
27
|
+
default() {
|
|
28
|
+
return 0
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
max: {
|
|
32
|
+
type: Number as PropType<number>,
|
|
33
|
+
default() {
|
|
34
|
+
return 100
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
step: {
|
|
38
|
+
type: Number as PropType<number>,
|
|
39
|
+
default() {
|
|
40
|
+
return 1
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
modelValue: {
|
|
44
|
+
type: Number as PropType<number>,
|
|
45
|
+
default() {
|
|
46
|
+
return 0
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
classes: {
|
|
50
|
+
type: Object as PropType<ClassObject>,
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const defaultClasses: ClassObject = {
|
|
55
|
+
icon: {
|
|
56
|
+
color: 'text-gray-500'
|
|
57
|
+
},
|
|
58
|
+
content: {
|
|
59
|
+
base: 'appearance-none [-webkit-appearance: none]',
|
|
60
|
+
backgroundColor: 'bg-gray-400',
|
|
61
|
+
rounded: 'rounded-full',
|
|
62
|
+
size: 'h-2'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// props.classesが渡されていない場合、defaultClassesを使用する
|
|
67
|
+
const mergedClasses = props.classes ? deepMergeClassObject(defaultClasses, props.classes) : defaultClasses;
|
|
68
|
+
|
|
69
|
+
const modelValue = ref<string>(props.modelValue.toString())
|
|
70
|
+
|
|
71
|
+
const emit = defineEmits<{
|
|
72
|
+
customInput: [value: Event],
|
|
73
|
+
'update:modelValue': [value: number]
|
|
74
|
+
}>()
|
|
75
|
+
|
|
76
|
+
function inputValue(e: Event) {
|
|
77
|
+
const target = e.target as HTMLInputElement | null
|
|
78
|
+
|
|
79
|
+
if (target) {
|
|
80
|
+
emitCustomEvent(target.value)
|
|
81
|
+
modelValue.value = target.value
|
|
82
|
+
|
|
83
|
+
emit('update:modelValue', Number(target.value))
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function emitCustomEvent(value: string) {
|
|
88
|
+
const event = new CustomEvent('input', {
|
|
89
|
+
detail: value
|
|
90
|
+
})
|
|
91
|
+
emit('customInput', event)
|
|
92
|
+
}
|
|
93
|
+
</script>
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vanilla-vue-ui",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"basic",
|
|
8
|
+
"template",
|
|
9
|
+
"custom",
|
|
10
|
+
"icon",
|
|
11
|
+
"types",
|
|
12
|
+
"util"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "vite",
|
|
16
|
+
"build": "npm run copy",
|
|
17
|
+
"preview": "vite preview",
|
|
18
|
+
"test:unit": "vitest",
|
|
19
|
+
"build-only": "vite build",
|
|
20
|
+
"type-check": "vue-tsc --build",
|
|
21
|
+
"lint": "eslint . --fix",
|
|
22
|
+
"format": "prettier --write src/",
|
|
23
|
+
"storybook": "storybook dev -p 6006",
|
|
24
|
+
"build-storybook": "storybook build",
|
|
25
|
+
"copy-template": "copyfiles -u 1 src/template/**/* .",
|
|
26
|
+
"copy-basic": "copyfiles -u 1 src/basic/**/* .",
|
|
27
|
+
"copy-custom": "copyfiles -u 1 src/custom/**/* .",
|
|
28
|
+
"copy-icon": "copyfiles -u 1 src/icon/**/* .",
|
|
29
|
+
"copy-types": "copyfiles -u 1 src/types/**/* .",
|
|
30
|
+
"copy-util": "copyfiles -u 1 src/util/**/* .",
|
|
31
|
+
"copy": "npm run copy-template && npm run copy-basic && npm run copy-custom && npm run copy-icon && npm run copy-types && npm run copy-util"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"vue": "^3.5.13"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@chromatic-com/storybook": "^3.2.4",
|
|
38
|
+
"@storybook/addon-essentials": "^8.5.5",
|
|
39
|
+
"@storybook/addon-interactions": "^8.5.5",
|
|
40
|
+
"@storybook/addon-onboarding": "^8.5.5",
|
|
41
|
+
"@storybook/blocks": "^8.5.5",
|
|
42
|
+
"@storybook/test": "^8.5.5",
|
|
43
|
+
"@storybook/vue3": "^8.5.5",
|
|
44
|
+
"@storybook/vue3-vite": "^8.5.5",
|
|
45
|
+
"@tsconfig/node22": "^22.0.0",
|
|
46
|
+
"@types/jsdom": "^21.1.7",
|
|
47
|
+
"@types/node": "^22.9.3",
|
|
48
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
49
|
+
"@vitest/eslint-plugin": "1.1.10",
|
|
50
|
+
"@vue/eslint-config-prettier": "^10.1.0",
|
|
51
|
+
"@vue/eslint-config-typescript": "^14.1.3",
|
|
52
|
+
"@vue/test-utils": "^2.4.6",
|
|
53
|
+
"@vue/tsconfig": "^0.7.0",
|
|
54
|
+
"copyfiles": "^2.4.1",
|
|
55
|
+
"eslint": "^9.14.0",
|
|
56
|
+
"eslint-plugin-storybook": "^0.11.2",
|
|
57
|
+
"eslint-plugin-vue": "^9.30.0",
|
|
58
|
+
"jsdom": "^25.0.1",
|
|
59
|
+
"npm-run-all2": "^7.0.1",
|
|
60
|
+
"prettier": "^3.3.3",
|
|
61
|
+
"storybook": "^8.5.5",
|
|
62
|
+
"typescript": "~5.6.3",
|
|
63
|
+
"vite": "^6.0.1",
|
|
64
|
+
"vite-plugin-vue-devtools": "^7.6.5",
|
|
65
|
+
"vitest": "^2.1.5",
|
|
66
|
+
"vue-tsc": "^2.1.10"
|
|
67
|
+
},
|
|
68
|
+
"eslintConfig": {
|
|
69
|
+
"extends": [
|
|
70
|
+
"plugin:storybook/recommended"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ClassObject = {
|
|
2
|
+
base?: string;
|
|
3
|
+
backgroundColor?: string;
|
|
4
|
+
spacing?: string;
|
|
5
|
+
size?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
shadow?: string;
|
|
8
|
+
rounded?: string;
|
|
9
|
+
border?: string;
|
|
10
|
+
layout?: string;
|
|
11
|
+
text?: ClassObject;
|
|
12
|
+
outline?: ClassObject;
|
|
13
|
+
label?: ClassObject;
|
|
14
|
+
errorMessage?: ClassObject;
|
|
15
|
+
title?: ClassObject;
|
|
16
|
+
content?: ClassObject;
|
|
17
|
+
icon?: ClassObject;
|
|
18
|
+
button?: ClassObject;
|
|
19
|
+
input?: ClassObject;
|
|
20
|
+
[key: string]: any; // インデックスシグネチャの追加
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ClassObject } from "../types/ClassObject";
|
|
2
|
+
|
|
3
|
+
// 深くマージする関数
|
|
4
|
+
export function deepMergeClassObject(target: ClassObject, source: ClassObject): ClassObject {
|
|
5
|
+
for (const key in source) {
|
|
6
|
+
if (source[key] instanceof Object && key in target) {
|
|
7
|
+
target[key] = deepMergeClassObject(target[key], source[key]);
|
|
8
|
+
} else {
|
|
9
|
+
target[key] = source[key];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return target;
|
|
13
|
+
}
|
package/util/index.ts
ADDED