@geckou/ui-vue 0.3.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/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/assets/scss/functions.scss +6 -0
- package/dist/assets/scss/mixin.scss +33 -0
- package/dist/components/ArticleList/Card/Artistic.vue +310 -0
- package/dist/components/ArticleList/Card/Entertainment.vue +244 -0
- package/dist/components/ArticleList/Card/Gallery.vue +254 -0
- package/dist/components/ArticleList/Card/Grid.vue +247 -0
- package/dist/components/ArticleList/Card/News.vue +150 -0
- package/dist/components/ArticleList/Card/Rounded.vue +154 -0
- package/dist/components/ArticleList/Card/Row.vue +167 -0
- package/dist/components/ArticleList/Card/Simple.vue +232 -0
- package/dist/components/ArticleList/Card/Standard.vue +187 -0
- package/dist/components/ArticleList/Card/Tile.vue +171 -0
- package/dist/components/ArticleList/GenericArticleList.vue +143 -0
- package/dist/components/ArticleList/List/Artistic.vue +24 -0
- package/dist/components/ArticleList/List/Entertainment.vue +24 -0
- package/dist/components/ArticleList/List/Gallery.vue +24 -0
- package/dist/components/ArticleList/List/Grid.vue +216 -0
- package/dist/components/ArticleList/List/News.vue +24 -0
- package/dist/components/ArticleList/List/Rounded.vue +24 -0
- package/dist/components/ArticleList/List/Row.vue +24 -0
- package/dist/components/ArticleList/List/Simple.vue +24 -0
- package/dist/components/ArticleList/List/Standard.vue +24 -0
- package/dist/components/ArticleList/List/Tile.vue +24 -0
- package/dist/components/ArticleList/Parts/AuthorInfo.vue +100 -0
- package/dist/components/ArticleList/Parts/CardContainer.vue +23 -0
- package/dist/components/ArticleList/Parts/CardHeading.vue +43 -0
- package/dist/components/ArticleList/Parts/CategoryList.vue +41 -0
- package/dist/components/ArticleList/Parts/ExcerptText.vue +43 -0
- package/dist/components/ArticleList/Parts/MetadataList.vue +120 -0
- package/dist/components/ArticleList/Parts/NoImage.vue +36 -0
- package/dist/components/ArticleList/Parts/PostedDate.vue +41 -0
- package/dist/components/ArticleList/Parts/TagList.vue +41 -0
- package/dist/components/ArticleList/Parts/ThumbnailImage.vue +85 -0
- package/dist/components/BasicButton.vue +143 -0
- package/dist/components/CheckBox.vue +140 -0
- package/dist/components/CheckBoxes.vue +100 -0
- package/dist/components/CheckButton.vue +127 -0
- package/dist/components/DatePicker.vue +234 -0
- package/dist/components/DateRangePicker.vue +85 -0
- package/dist/components/DateSelector.vue +273 -0
- package/dist/components/DropdownUi.vue +118 -0
- package/dist/components/ErrorMessage.vue +61 -0
- package/dist/components/Icon/CalendarIcon.vue +8 -0
- package/dist/components/Icon/CheckIcon.vue +8 -0
- package/dist/components/Icon/CloseIcon.vue +8 -0
- package/dist/components/Icon/Folder.vue +8 -0
- package/dist/components/Icon/Image.vue +14 -0
- package/dist/components/Icon/KeyboardArrowDownIcon.vue +8 -0
- package/dist/components/Icon/Tag.vue +8 -0
- package/dist/components/InputBox.vue +134 -0
- package/dist/components/InputGroup.vue +41 -0
- package/dist/components/LabeledCheckbox.vue +82 -0
- package/dist/components/LabeledFieldset.vue +41 -0
- package/dist/components/LoadingSpinner.vue +56 -0
- package/dist/components/ModalBox.vue +192 -0
- package/dist/components/PopupBox.vue +93 -0
- package/dist/components/RadioButtons.vue +163 -0
- package/dist/components/SelectBox.vue +166 -0
- package/dist/components/SlideDownUi.vue +123 -0
- package/dist/components/TabUI.vue +123 -0
- package/dist/components/TextArea.vue +115 -0
- package/dist/components/TextBox.vue +111 -0
- package/dist/components/TextButton.vue +47 -0
- package/dist/components/ToggleButton.vue +179 -0
- package/dist/const/index.ts +2 -0
- package/dist/const/list-theme.ts +62 -0
- package/dist/index.ts +126 -0
- package/dist/scripts/form-validation-manager.ts +63 -0
- package/dist/scripts/utils.ts +36 -0
- package/dist/types/custom.d.ts +1 -0
- package/dist/types/index.d.ts +93 -0
- package/dist/types/vue-shim.d.ts +5 -0
- package/package.json +44 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type {
|
|
3
|
+
StateVariation,
|
|
4
|
+
BaseStyle,
|
|
5
|
+
} from '../types'
|
|
6
|
+
import { computed } from 'vue'
|
|
7
|
+
import { COLOR } from '../const'
|
|
8
|
+
|
|
9
|
+
const emit = defineEmits<{ (e: 'update:modelValue', newValue: boolean): void }>()
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<{
|
|
12
|
+
name: string
|
|
13
|
+
label?: Record<'on' | 'off', string>
|
|
14
|
+
modelValue?: boolean
|
|
15
|
+
isDisabled?: boolean
|
|
16
|
+
cssStyle?: Record<StateVariation, {
|
|
17
|
+
on: BaseStyle
|
|
18
|
+
off: BaseStyle
|
|
19
|
+
}>
|
|
20
|
+
}>(), {
|
|
21
|
+
label : () => ({ on: 'ON', off: 'OFF' }),
|
|
22
|
+
cssStyle: undefined,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const isChecked = computed<boolean>({
|
|
26
|
+
get: () => props.modelValue ?? false,
|
|
27
|
+
set: (newValue: boolean) => emit('update:modelValue', newValue),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const maxTextLength = computed<number>(() => {
|
|
31
|
+
const onLength = props.label.on.length
|
|
32
|
+
const offLength = props.label.off.length
|
|
33
|
+
|
|
34
|
+
return onLength > offLength ? onLength : offLength
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const currentCssStyle = computed(() => {
|
|
38
|
+
const cssStyle = props.isDisabled ? props.cssStyle?.disabled : props.cssStyle?.default
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
on: {
|
|
42
|
+
...{
|
|
43
|
+
textColor : props.isDisabled ? COLOR.lightGray : COLOR.white,
|
|
44
|
+
backgroundColor: props.isDisabled ? COLOR.gray : COLOR.blue,
|
|
45
|
+
border : {
|
|
46
|
+
color : props.isDisabled ? COLOR.gray : COLOR.blue,
|
|
47
|
+
size : '1px',
|
|
48
|
+
radius: '.25rem',
|
|
49
|
+
},
|
|
50
|
+
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)',
|
|
51
|
+
},
|
|
52
|
+
...cssStyle?.on,
|
|
53
|
+
},
|
|
54
|
+
off: {
|
|
55
|
+
...{
|
|
56
|
+
textColor : props.isDisabled ? COLOR.gray : COLOR.white,
|
|
57
|
+
backgroundColor: props.isDisabled ? COLOR.lightGray : COLOR.darkGray,
|
|
58
|
+
border : {
|
|
59
|
+
color : props.isDisabled ? COLOR.gray : COLOR.darkGray,
|
|
60
|
+
size : '1px',
|
|
61
|
+
radius: '.25rem',
|
|
62
|
+
},
|
|
63
|
+
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)',
|
|
64
|
+
},
|
|
65
|
+
...cssStyle?.off,
|
|
66
|
+
},
|
|
67
|
+
}[isChecked.value ? 'on' : 'off']
|
|
68
|
+
})
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<button
|
|
73
|
+
:class="$style.toggle_button"
|
|
74
|
+
:style="{
|
|
75
|
+
'--text-color': currentCssStyle?.textColor,
|
|
76
|
+
'--border-color': currentCssStyle?.border?.color,
|
|
77
|
+
'--border-size' : currentCssStyle?.border?.size,
|
|
78
|
+
'--radius-size': currentCssStyle?.border?.radius,
|
|
79
|
+
'--background-color': currentCssStyle?.backgroundColor,
|
|
80
|
+
'--box-shadow': currentCssStyle?.boxShadow,
|
|
81
|
+
'--inline-size': `${maxTextLength * 2}ch`,
|
|
82
|
+
}"
|
|
83
|
+
type="button"
|
|
84
|
+
:disabled="isDisabled"
|
|
85
|
+
@click.stop="!isDisabled ? isChecked = !isChecked : null"
|
|
86
|
+
>
|
|
87
|
+
<input
|
|
88
|
+
v-model="isChecked"
|
|
89
|
+
type="checkbox"
|
|
90
|
+
:name="name"
|
|
91
|
+
:disabled="isDisabled"
|
|
92
|
+
>
|
|
93
|
+
<div
|
|
94
|
+
:class="[$style.text, {[$style.on]: isChecked}]"
|
|
95
|
+
:data-on="label.on"
|
|
96
|
+
:data-off="label.off"
|
|
97
|
+
/>
|
|
98
|
+
<div :class="$style.handle" />
|
|
99
|
+
</button>
|
|
100
|
+
</template>
|
|
101
|
+
|
|
102
|
+
<style lang="scss" module>
|
|
103
|
+
:is(.toggle_button) {
|
|
104
|
+
--handle-size: 1.5rem;
|
|
105
|
+
--padding-size: calc(var(--border-size) + 2px);
|
|
106
|
+
--duration: .15s;
|
|
107
|
+
inline-size: calc(var(--inline-size) + var(--handle-size) + (var(--padding-size) * 2));
|
|
108
|
+
position: relative;
|
|
109
|
+
display: inline-block;
|
|
110
|
+
padding: var(--padding-size);
|
|
111
|
+
background-color: var(--background-color);
|
|
112
|
+
box-shadow:
|
|
113
|
+
0 0 0 var(--border-size) var(--border-color) inset,
|
|
114
|
+
var(--box-shadow)
|
|
115
|
+
;
|
|
116
|
+
border: none;
|
|
117
|
+
border-radius: var(--radius-size);
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
|
|
120
|
+
> input {
|
|
121
|
+
display: none;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
:is(.text) {
|
|
126
|
+
position: absolute;
|
|
127
|
+
inline-size: 100%;
|
|
128
|
+
block-size: 100%;
|
|
129
|
+
text-transform: uppercase;
|
|
130
|
+
color: var(--text-color);
|
|
131
|
+
top: 0;
|
|
132
|
+
left: 0;
|
|
133
|
+
|
|
134
|
+
&::before,
|
|
135
|
+
&::after {
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
align-items: center;
|
|
139
|
+
block-size: 100%;
|
|
140
|
+
inline-size: calc(100% - var(--handle-size) - var(--padding-size));
|
|
141
|
+
margin: auto;
|
|
142
|
+
line-height: 1;
|
|
143
|
+
position: absolute;
|
|
144
|
+
transition: opacity var(--duration) ease-out;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
&::before {
|
|
148
|
+
content: attr(data-off);
|
|
149
|
+
right: 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&::after {
|
|
153
|
+
content: attr(data-on);
|
|
154
|
+
left: 0;
|
|
155
|
+
opacity: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&.on {
|
|
159
|
+
&:before { opacity: 0; }
|
|
160
|
+
&:after { opacity: 1; }
|
|
161
|
+
|
|
162
|
+
+ .handle {
|
|
163
|
+
left: calc(100% - var(--handle-size));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
:is(.handle) {
|
|
169
|
+
inline-size: var(--handle-size);
|
|
170
|
+
aspect-ratio: 1 / 1;
|
|
171
|
+
margin: 0;
|
|
172
|
+
background-color: var(--text-color);
|
|
173
|
+
border-radius: calc(var(--radius-size) - (var(--padding-size) / 2));
|
|
174
|
+
box-shadow: var(--box-shadow);
|
|
175
|
+
position: relative;
|
|
176
|
+
left: 0;
|
|
177
|
+
transition: left var(--duration) ease-out;
|
|
178
|
+
}
|
|
179
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const LIST_THEME = {
|
|
2
|
+
standard: {
|
|
3
|
+
jaName : 'スタンダード',
|
|
4
|
+
enName : 'Standard',
|
|
5
|
+
columnNumber: 3,
|
|
6
|
+
name : 'Standard',
|
|
7
|
+
},
|
|
8
|
+
rounded: {
|
|
9
|
+
jaName : 'ポップ',
|
|
10
|
+
enName : 'Rounded',
|
|
11
|
+
columnNumber: 3,
|
|
12
|
+
name : 'Rounded',
|
|
13
|
+
},
|
|
14
|
+
artistic: {
|
|
15
|
+
jaName : 'アート',
|
|
16
|
+
enName : 'Artistic',
|
|
17
|
+
columnNumber: 3,
|
|
18
|
+
name : 'Artistic',
|
|
19
|
+
},
|
|
20
|
+
tile: {
|
|
21
|
+
jaName : 'タイル',
|
|
22
|
+
enName : 'Tile',
|
|
23
|
+
columnNumber: 3,
|
|
24
|
+
name : 'Tile',
|
|
25
|
+
},
|
|
26
|
+
simple: {
|
|
27
|
+
jaName : 'シンプル',
|
|
28
|
+
enName : 'Simple',
|
|
29
|
+
columnNumber: 3,
|
|
30
|
+
name : 'Simple',
|
|
31
|
+
},
|
|
32
|
+
row: {
|
|
33
|
+
jaName : 'ワイド',
|
|
34
|
+
enName : 'Row',
|
|
35
|
+
columnNumber: 1,
|
|
36
|
+
name : 'Row',
|
|
37
|
+
},
|
|
38
|
+
news: {
|
|
39
|
+
jaName : 'ニュース',
|
|
40
|
+
enName : 'News',
|
|
41
|
+
columnNumber: 1,
|
|
42
|
+
name : 'News',
|
|
43
|
+
},
|
|
44
|
+
grid: {
|
|
45
|
+
jaName : 'グリッド',
|
|
46
|
+
enName : 'Grid',
|
|
47
|
+
columnNumber: 4,
|
|
48
|
+
name : 'Grid',
|
|
49
|
+
},
|
|
50
|
+
gallery: {
|
|
51
|
+
jaName : 'ギャラリー',
|
|
52
|
+
enName : 'Gallery',
|
|
53
|
+
columnNumber: 3,
|
|
54
|
+
name : 'Gallery',
|
|
55
|
+
},
|
|
56
|
+
entertainment: {
|
|
57
|
+
jaName : 'エンタテインメント',
|
|
58
|
+
enName : 'Entertainment',
|
|
59
|
+
columnNumber: 3,
|
|
60
|
+
name : 'Entertainment',
|
|
61
|
+
},
|
|
62
|
+
}
|
package/dist/index.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { App } from 'vue'
|
|
2
|
+
|
|
3
|
+
// Form / UI components
|
|
4
|
+
import TextBox from './components/TextBox.vue'
|
|
5
|
+
import TextArea from './components/TextArea.vue'
|
|
6
|
+
import BasicButton from './components/BasicButton.vue'
|
|
7
|
+
import SelectBox from './components/SelectBox.vue'
|
|
8
|
+
import CheckBox from './components/CheckBox.vue'
|
|
9
|
+
import CheckBoxes from './components/CheckBoxes.vue'
|
|
10
|
+
import CheckButton from './components/CheckButton.vue'
|
|
11
|
+
import LabeledCheckbox from './components/LabeledCheckbox.vue'
|
|
12
|
+
import LabeledFieldset from './components/LabeledFieldset.vue'
|
|
13
|
+
import RadioButtons from './components/RadioButtons.vue'
|
|
14
|
+
import ToggleButton from './components/ToggleButton.vue'
|
|
15
|
+
import InputBox from './components/InputBox.vue'
|
|
16
|
+
import InputGroup from './components/InputGroup.vue'
|
|
17
|
+
import TextButton from './components/TextButton.vue'
|
|
18
|
+
import DatePicker from './components/DatePicker.vue'
|
|
19
|
+
import DateRangePicker from './components/DateRangePicker.vue'
|
|
20
|
+
import DateSelector from './components/DateSelector.vue'
|
|
21
|
+
import DropdownUi from './components/DropdownUi.vue'
|
|
22
|
+
import ModalBox from './components/ModalBox.vue'
|
|
23
|
+
import PopupBox from './components/PopupBox.vue'
|
|
24
|
+
import SlideDownUi from './components/SlideDownUi.vue'
|
|
25
|
+
import TabUI from './components/TabUI.vue'
|
|
26
|
+
import LoadingSpinner from './components/LoadingSpinner.vue'
|
|
27
|
+
import ErrorMessage from './components/ErrorMessage.vue'
|
|
28
|
+
|
|
29
|
+
// ArticleList components
|
|
30
|
+
import StandardList from './components/ArticleList/List/Standard.vue'
|
|
31
|
+
import RoundedList from './components/ArticleList/List/Rounded.vue'
|
|
32
|
+
import ArtisticList from './components/ArticleList/List/Artistic.vue'
|
|
33
|
+
import TileList from './components/ArticleList/List/Tile.vue'
|
|
34
|
+
import SimpleList from './components/ArticleList/List/Simple.vue'
|
|
35
|
+
import RowList from './components/ArticleList/List/Row.vue'
|
|
36
|
+
import NewsList from './components/ArticleList/List/News.vue'
|
|
37
|
+
import EntertainmentList from './components/ArticleList/List/Entertainment.vue'
|
|
38
|
+
import GalleryList from './components/ArticleList/List/Gallery.vue'
|
|
39
|
+
import GridList from './components/ArticleList/List/Grid.vue'
|
|
40
|
+
|
|
41
|
+
const components = {
|
|
42
|
+
TextBox,
|
|
43
|
+
TextArea,
|
|
44
|
+
BasicButton,
|
|
45
|
+
SelectBox,
|
|
46
|
+
CheckBox,
|
|
47
|
+
CheckBoxes,
|
|
48
|
+
CheckButton,
|
|
49
|
+
LabeledCheckbox,
|
|
50
|
+
LabeledFieldset,
|
|
51
|
+
RadioButtons,
|
|
52
|
+
ToggleButton,
|
|
53
|
+
InputBox,
|
|
54
|
+
InputGroup,
|
|
55
|
+
TextButton,
|
|
56
|
+
DatePicker,
|
|
57
|
+
DateRangePicker,
|
|
58
|
+
DateSelector,
|
|
59
|
+
DropdownUi,
|
|
60
|
+
ModalBox,
|
|
61
|
+
PopupBox,
|
|
62
|
+
SlideDownUi,
|
|
63
|
+
TabUI,
|
|
64
|
+
LoadingSpinner,
|
|
65
|
+
ErrorMessage,
|
|
66
|
+
|
|
67
|
+
StandardList,
|
|
68
|
+
RoundedList,
|
|
69
|
+
ArtisticList,
|
|
70
|
+
TileList,
|
|
71
|
+
SimpleList,
|
|
72
|
+
RowList,
|
|
73
|
+
NewsList,
|
|
74
|
+
EntertainmentList,
|
|
75
|
+
GalleryList,
|
|
76
|
+
GridList,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default {
|
|
80
|
+
install(app: App) {
|
|
81
|
+
Object.entries(components).forEach(([name, component]) => {
|
|
82
|
+
app.component(name, component)
|
|
83
|
+
})
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
TextBox,
|
|
89
|
+
TextArea,
|
|
90
|
+
BasicButton,
|
|
91
|
+
SelectBox,
|
|
92
|
+
CheckBox,
|
|
93
|
+
CheckBoxes,
|
|
94
|
+
CheckButton,
|
|
95
|
+
LabeledCheckbox,
|
|
96
|
+
LabeledFieldset,
|
|
97
|
+
RadioButtons,
|
|
98
|
+
ToggleButton,
|
|
99
|
+
InputBox,
|
|
100
|
+
InputGroup,
|
|
101
|
+
TextButton,
|
|
102
|
+
DatePicker,
|
|
103
|
+
DateRangePicker,
|
|
104
|
+
DateSelector,
|
|
105
|
+
DropdownUi,
|
|
106
|
+
ModalBox,
|
|
107
|
+
PopupBox,
|
|
108
|
+
SlideDownUi,
|
|
109
|
+
TabUI,
|
|
110
|
+
LoadingSpinner,
|
|
111
|
+
ErrorMessage,
|
|
112
|
+
|
|
113
|
+
StandardList,
|
|
114
|
+
RoundedList,
|
|
115
|
+
ArtisticList,
|
|
116
|
+
TileList,
|
|
117
|
+
SimpleList,
|
|
118
|
+
RowList,
|
|
119
|
+
NewsList,
|
|
120
|
+
EntertainmentList,
|
|
121
|
+
GalleryList,
|
|
122
|
+
GridList,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { LIST_THEME } from './const/list-theme'
|
|
126
|
+
export { FormValidationManager } from './scripts/form-validation-manager'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { computed, onScopeDispose, shallowRef } from 'vue'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { createFormValidationStore } from '@geckou/ui-core'
|
|
4
|
+
import type { FormValidationStore } from '@geckou/ui-core'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* フォーム内の各入力コンポーネントのバリデーション状態をまとめて管理する。
|
|
8
|
+
*
|
|
9
|
+
* 状態そのものは @geckou/ui-core の createFormValidationStore が持つ。
|
|
10
|
+
* このクラスは Vue のリアクティビティへ繋ぐ薄いラッパーで、
|
|
11
|
+
* 判定ロジックは React 実装(@geckou/ui-react)と共有される。
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const manager = new FormValidationManager()
|
|
15
|
+
* // <DatePicker name="startedOn" :formValidationManager="manager" />
|
|
16
|
+
* const canSubmit = manager.isAllValid
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export class FormValidationManager {
|
|
20
|
+
private readonly store: FormValidationStore
|
|
21
|
+
|
|
22
|
+
/** 登録済みの入力がすべて有効かどうか */
|
|
23
|
+
readonly isAllValid: ComputedRef<boolean>
|
|
24
|
+
|
|
25
|
+
/** 無効になっている入力の name 一覧 */
|
|
26
|
+
readonly invalidNames: ComputedRef<string[]>
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
this.store = createFormValidationStore()
|
|
30
|
+
|
|
31
|
+
const snapshot = shallowRef(this.store.getSnapshot())
|
|
32
|
+
const unsubscribe = this.store.subscribe(() => {
|
|
33
|
+
snapshot.value = this.store.getSnapshot()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// インスタンスを生成した effect scope の破棄時に購読を解除する
|
|
37
|
+
// (scope の外で生成された場合は何もしない)
|
|
38
|
+
onScopeDispose(unsubscribe, true)
|
|
39
|
+
|
|
40
|
+
this.isAllValid = computed(() => snapshot.value.isAllValid)
|
|
41
|
+
this.invalidNames = computed(() => snapshot.value.invalidNames)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 入力の状態を登録・更新する */
|
|
45
|
+
setValid(name: string, isValid: boolean): void {
|
|
46
|
+
this.store.setValid(name, isValid)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 個別の入力が有効かどうか(未登録なら true) */
|
|
50
|
+
isValid(name: string): boolean {
|
|
51
|
+
return this.store.isValid(name)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 管理対象から外す(コンポーネントのアンマウント時など) */
|
|
55
|
+
remove(name: string): void {
|
|
56
|
+
this.store.remove(name)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** すべての状態を破棄する */
|
|
60
|
+
reset(): void {
|
|
61
|
+
this.store.reset()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Article, PostConfig, WpTerm } from '../types'
|
|
2
|
+
|
|
3
|
+
export const generateQueryObject = (url: string): Record<string, string> => {
|
|
4
|
+
const regex = /[?&]([^=#]+)=([^&#]*)/g
|
|
5
|
+
const queryObject: Record<string, string> = {}
|
|
6
|
+
|
|
7
|
+
for (let match; (match = regex.exec(url)) !== null; ) {
|
|
8
|
+
queryObject[match[1]] = match[2]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return queryObject
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const returnTagList = (articleObject: Article): string[] => {
|
|
15
|
+
const terms = articleObject?.['_embedded']?.['wp:term']?.[1] ?? []
|
|
16
|
+
return terms.map((tag: WpTerm) => tag.name)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const returnArticlePath = (postConfig: PostConfig, domain: string, articleId: string) => {
|
|
20
|
+
// ドメイン末尾とパス先頭のスラッシュが重ならないようにする
|
|
21
|
+
const base = String(domain).replace(/\/+$/, '')
|
|
22
|
+
const path = String(postConfig.article_page_path ?? '').replace(/^\/+/, '')
|
|
23
|
+
|
|
24
|
+
return `https://${base}/${path}?${postConfig.query_key_name}=${articleId}`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 各カードは postConfig.author / category / tag を参照するが、
|
|
29
|
+
* 設定側では useAuthor / useCategory / useTag で渡すこともできるため両対応させる
|
|
30
|
+
*/
|
|
31
|
+
export const normalizePostConfig = (postConfig: PostConfig): PostConfig => ({
|
|
32
|
+
...postConfig,
|
|
33
|
+
author : postConfig?.author ?? postConfig?.useAuthor ?? false,
|
|
34
|
+
category: postConfig?.category ?? postConfig?.useCategory ?? false,
|
|
35
|
+
tag : postConfig?.tag ?? postConfig?.useTag ?? false,
|
|
36
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module '../*'
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// フォーム部品の型は @geckou/ui-core が正。Vue / React で共通のため、ここでは再エクスポートのみ行う
|
|
2
|
+
export type {
|
|
3
|
+
StateVariation,
|
|
4
|
+
BorderStyle,
|
|
5
|
+
BaseStyle,
|
|
6
|
+
StyleForEachStatus,
|
|
7
|
+
InputBoxStyle,
|
|
8
|
+
InputBoxStyleForEachStatus,
|
|
9
|
+
ButtonStyle,
|
|
10
|
+
ButtonStyleForEachStatus,
|
|
11
|
+
CheckBoxStyle,
|
|
12
|
+
CheckBoxStyleForEachStatus,
|
|
13
|
+
RadioButtonStyle,
|
|
14
|
+
RadioButtonStyleForEachStatus,
|
|
15
|
+
SelectValue,
|
|
16
|
+
Option,
|
|
17
|
+
Validate,
|
|
18
|
+
Validates,
|
|
19
|
+
InputValue,
|
|
20
|
+
DateObject,
|
|
21
|
+
DateType,
|
|
22
|
+
ValidationResult,
|
|
23
|
+
} from '@geckou/ui-core'
|
|
24
|
+
|
|
25
|
+
// ArticleList は Vue のみの機能のため、型もこのパッケージで持つ
|
|
26
|
+
export type Category = {
|
|
27
|
+
id: string
|
|
28
|
+
name: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type PostConfig = {
|
|
32
|
+
article_page_path: string
|
|
33
|
+
query_key_name: string
|
|
34
|
+
useAuthor?: boolean
|
|
35
|
+
useCategory?: boolean
|
|
36
|
+
useTag?: boolean
|
|
37
|
+
/** useAuthor のエイリアス(カード内部で参照される) */
|
|
38
|
+
author?: boolean
|
|
39
|
+
/** useCategory のエイリアス(カード内部で参照される) */
|
|
40
|
+
category?: boolean
|
|
41
|
+
/** useTag のエイリアス(カード内部で参照される) */
|
|
42
|
+
tag?: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type ListSettings = {
|
|
46
|
+
domainToUse: string
|
|
47
|
+
postConfig: PostConfig
|
|
48
|
+
isEnabledPickUp: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** WordPress REST API のレンダリング済みフィールド */
|
|
52
|
+
export type RenderedField = {
|
|
53
|
+
rendered: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** _embedded['wp:term'] の要素 */
|
|
57
|
+
export type WpTerm = {
|
|
58
|
+
id: string | number
|
|
59
|
+
name: string
|
|
60
|
+
taxonomy?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** _embedded['author'] の要素 */
|
|
64
|
+
export type WpAuthor = {
|
|
65
|
+
name: string
|
|
66
|
+
avatar_urls?: Record<string, string>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** _embedded['wp:featuredmedia'] の要素 */
|
|
70
|
+
export type WpMedia = {
|
|
71
|
+
alt_text?: string
|
|
72
|
+
media_details?: {
|
|
73
|
+
sizes?: Record<string, { source_url?: string }>
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* WordPress REST API(?_embed 付き)の投稿。
|
|
79
|
+
* 実際のレスポンスは環境ごとにフィールドが増減するため、既知のフィールドのみ定義する
|
|
80
|
+
*/
|
|
81
|
+
export type Article = {
|
|
82
|
+
id: string | number
|
|
83
|
+
date: string
|
|
84
|
+
title: RenderedField
|
|
85
|
+
excerpt: RenderedField
|
|
86
|
+
categories?: string[]
|
|
87
|
+
_embedded?: {
|
|
88
|
+
author?: WpAuthor[]
|
|
89
|
+
'wp:featuredmedia'?: WpMedia[]
|
|
90
|
+
'wp:term'?: WpTerm[][]
|
|
91
|
+
}
|
|
92
|
+
[key: string]: unknown
|
|
93
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@geckou/ui-vue",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "A set of reusable Vue UI components (forms & article lists) by Geckou",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/geckou/ui.git",
|
|
12
|
+
"directory": "packages/vue"
|
|
13
|
+
},
|
|
14
|
+
"author": "geckou-shogo <shogo.nojima@geckou.net>",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20.0.0"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"registry": "https://registry.npmjs.org/",
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"vue": "^3.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@geckou/ui-core": "^0.1.0",
|
|
33
|
+
"date-fns": "^4.4.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"clean": "rm -rf dist",
|
|
37
|
+
"convert-alias": "node scripts/convert-alias-to-relative.js",
|
|
38
|
+
"build": "yarn clean && rsync -av --exclude 'main.ts' --exclude 'App.vue' --exclude '.DS_Store' src/ dist/ && yarn convert-alias",
|
|
39
|
+
"type-check": "vue-tsc --noEmit",
|
|
40
|
+
"prepublishOnly": "yarn build",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest"
|
|
43
|
+
}
|
|
44
|
+
}
|