@geckou/ui-vue 0.3.1 → 0.4.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.
Files changed (145) hide show
  1. package/README.md +8 -1
  2. package/dist/components/ArticleList/Card/Artistic.vue.d.ts +10 -0
  3. package/dist/components/ArticleList/Card/Entertainment.vue.d.ts +10 -0
  4. package/dist/components/ArticleList/Card/Gallery.vue.d.ts +10 -0
  5. package/dist/components/ArticleList/Card/Grid.vue.d.ts +11 -0
  6. package/dist/components/ArticleList/Card/News.vue.d.ts +9 -0
  7. package/dist/components/ArticleList/Card/Rounded.vue.d.ts +10 -0
  8. package/dist/components/ArticleList/Card/Row.vue.d.ts +9 -0
  9. package/dist/components/ArticleList/Card/Simple.vue.d.ts +10 -0
  10. package/dist/components/ArticleList/Card/Standard.vue.d.ts +10 -0
  11. package/dist/components/ArticleList/Card/Tile.vue.d.ts +10 -0
  12. package/dist/components/ArticleList/GenericArticleList.vue.d.ts +11 -0
  13. package/dist/components/ArticleList/List/Artistic.vue.d.ts +8 -0
  14. package/dist/components/ArticleList/List/Entertainment.vue.d.ts +8 -0
  15. package/dist/components/ArticleList/List/Gallery.vue.d.ts +8 -0
  16. package/dist/components/ArticleList/List/Grid.vue.d.ts +11 -0
  17. package/dist/components/ArticleList/List/News.vue.d.ts +8 -0
  18. package/dist/components/ArticleList/List/Rounded.vue.d.ts +8 -0
  19. package/dist/components/ArticleList/List/Row.vue.d.ts +8 -0
  20. package/dist/components/ArticleList/List/Simple.vue.d.ts +8 -0
  21. package/dist/components/ArticleList/List/Standard.vue.d.ts +8 -0
  22. package/dist/components/ArticleList/List/Tile.vue.d.ts +8 -0
  23. package/dist/components/ArticleList/Parts/AuthorInfo.vue.d.ts +31 -0
  24. package/dist/components/ArticleList/Parts/CardContainer.vue.d.ts +20 -0
  25. package/dist/components/ArticleList/Parts/CardHeading.vue.d.ts +12 -0
  26. package/dist/components/ArticleList/Parts/CategoryList.vue.d.ts +19 -0
  27. package/dist/components/ArticleList/Parts/ExcerptText.vue.d.ts +12 -0
  28. package/dist/components/ArticleList/Parts/MetadataList.vue.d.ts +32 -0
  29. package/dist/components/ArticleList/Parts/NoImage.vue.d.ts +2 -0
  30. package/dist/components/ArticleList/Parts/PostedDate.vue.d.ts +14 -0
  31. package/dist/components/ArticleList/Parts/TagList.vue.d.ts +18 -0
  32. package/dist/components/ArticleList/Parts/ThumbnailImage.vue.d.ts +17 -0
  33. package/dist/components/BasicButton.vue.d.ts +26 -0
  34. package/dist/components/CheckBox.vue.d.ts +34 -0
  35. package/dist/components/CheckBoxes.vue.d.ts +18 -0
  36. package/dist/components/CheckButton.vue.d.ts +31 -0
  37. package/dist/components/DatePicker.vue.d.ts +27 -0
  38. package/dist/components/DateRangePicker.vue.d.ts +31 -0
  39. package/dist/components/DateSelector.vue.d.ts +17 -0
  40. package/dist/components/DropdownUi.vue.d.ts +37 -0
  41. package/dist/components/ErrorMessage.vue.d.ts +9 -0
  42. package/dist/components/Icon/CalendarIcon.vue.d.ts +2 -0
  43. package/dist/components/Icon/CheckIcon.vue.d.ts +2 -0
  44. package/dist/components/Icon/CloseIcon.vue.d.ts +2 -0
  45. package/dist/components/Icon/Folder.vue.d.ts +2 -0
  46. package/dist/components/Icon/Image.vue.d.ts +2 -0
  47. package/dist/components/Icon/KeyboardArrowDownIcon.vue.d.ts +2 -0
  48. package/dist/components/Icon/Tag.vue.d.ts +2 -0
  49. package/dist/components/InputBox.vue.d.ts +27 -0
  50. package/dist/components/InputGroup.vue.d.ts +17 -0
  51. package/dist/components/LabeledCheckbox.vue.d.ts +20 -0
  52. package/dist/components/LabeledFieldset.vue.d.ts +21 -0
  53. package/dist/components/LoadingSpinner.vue.d.ts +2 -0
  54. package/dist/components/ModalBox.vue.d.ts +27 -0
  55. package/dist/components/PopupBox.vue.d.ts +30 -0
  56. package/dist/components/RadioButtons.vue.d.ts +20 -0
  57. package/dist/components/SelectBox.vue.d.ts +37 -0
  58. package/dist/components/SlideDownUi.vue.d.ts +37 -0
  59. package/dist/components/TabUI.vue.d.ts +54 -0
  60. package/dist/components/TextArea.vue.d.ts +33 -0
  61. package/dist/components/TextBox.vue.d.ts +44 -0
  62. package/dist/components/TextButton.vue.d.ts +10 -0
  63. package/dist/components/ToggleButton.vue.d.ts +23 -0
  64. package/dist/const/index.d.ts +1 -0
  65. package/dist/const/list-theme.d.ts +62 -0
  66. package/dist/index.d.ts +43 -0
  67. package/dist/index.js +3519 -0
  68. package/dist/scripts/form-validation-manager.d.ts +30 -0
  69. package/dist/scripts/unique-id.d.ts +1 -0
  70. package/dist/scripts/use-click-outside.d.ts +13 -0
  71. package/dist/scripts/utils.d.ts +15 -0
  72. package/dist/style.css +1 -0
  73. package/dist/types/index.d.ts +48 -77
  74. package/package.json +16 -8
  75. package/dist/assets/scss/functions.scss +0 -6
  76. package/dist/assets/scss/mixin.scss +0 -33
  77. package/dist/components/ArticleList/Card/Artistic.vue +0 -311
  78. package/dist/components/ArticleList/Card/Entertainment.vue +0 -245
  79. package/dist/components/ArticleList/Card/Gallery.vue +0 -255
  80. package/dist/components/ArticleList/Card/Grid.vue +0 -248
  81. package/dist/components/ArticleList/Card/News.vue +0 -151
  82. package/dist/components/ArticleList/Card/Rounded.vue +0 -155
  83. package/dist/components/ArticleList/Card/Row.vue +0 -168
  84. package/dist/components/ArticleList/Card/Simple.vue +0 -233
  85. package/dist/components/ArticleList/Card/Standard.vue +0 -188
  86. package/dist/components/ArticleList/Card/Tile.vue +0 -172
  87. package/dist/components/ArticleList/GenericArticleList.vue +0 -143
  88. package/dist/components/ArticleList/List/Artistic.vue +0 -24
  89. package/dist/components/ArticleList/List/Entertainment.vue +0 -24
  90. package/dist/components/ArticleList/List/Gallery.vue +0 -24
  91. package/dist/components/ArticleList/List/Grid.vue +0 -216
  92. package/dist/components/ArticleList/List/News.vue +0 -24
  93. package/dist/components/ArticleList/List/Rounded.vue +0 -24
  94. package/dist/components/ArticleList/List/Row.vue +0 -24
  95. package/dist/components/ArticleList/List/Simple.vue +0 -24
  96. package/dist/components/ArticleList/List/Standard.vue +0 -24
  97. package/dist/components/ArticleList/List/Tile.vue +0 -24
  98. package/dist/components/ArticleList/Parts/AuthorInfo.vue +0 -100
  99. package/dist/components/ArticleList/Parts/CardContainer.vue +0 -23
  100. package/dist/components/ArticleList/Parts/CardHeading.vue +0 -43
  101. package/dist/components/ArticleList/Parts/CategoryList.vue +0 -41
  102. package/dist/components/ArticleList/Parts/ExcerptText.vue +0 -43
  103. package/dist/components/ArticleList/Parts/MetadataList.vue +0 -120
  104. package/dist/components/ArticleList/Parts/NoImage.vue +0 -36
  105. package/dist/components/ArticleList/Parts/PostedDate.vue +0 -41
  106. package/dist/components/ArticleList/Parts/TagList.vue +0 -41
  107. package/dist/components/ArticleList/Parts/ThumbnailImage.vue +0 -85
  108. package/dist/components/BasicButton.vue +0 -143
  109. package/dist/components/CheckBox.vue +0 -140
  110. package/dist/components/CheckBoxes.vue +0 -101
  111. package/dist/components/CheckButton.vue +0 -127
  112. package/dist/components/DatePicker.vue +0 -234
  113. package/dist/components/DateRangePicker.vue +0 -85
  114. package/dist/components/DateSelector.vue +0 -273
  115. package/dist/components/DropdownUi.vue +0 -118
  116. package/dist/components/ErrorMessage.vue +0 -61
  117. package/dist/components/Icon/CalendarIcon.vue +0 -8
  118. package/dist/components/Icon/CheckIcon.vue +0 -8
  119. package/dist/components/Icon/CloseIcon.vue +0 -8
  120. package/dist/components/Icon/Folder.vue +0 -8
  121. package/dist/components/Icon/Image.vue +0 -14
  122. package/dist/components/Icon/KeyboardArrowDownIcon.vue +0 -8
  123. package/dist/components/Icon/Tag.vue +0 -8
  124. package/dist/components/InputBox.vue +0 -134
  125. package/dist/components/InputGroup.vue +0 -41
  126. package/dist/components/LabeledCheckbox.vue +0 -82
  127. package/dist/components/LabeledFieldset.vue +0 -41
  128. package/dist/components/LoadingSpinner.vue +0 -56
  129. package/dist/components/ModalBox.vue +0 -192
  130. package/dist/components/PopupBox.vue +0 -93
  131. package/dist/components/RadioButtons.vue +0 -163
  132. package/dist/components/SelectBox.vue +0 -166
  133. package/dist/components/SlideDownUi.vue +0 -123
  134. package/dist/components/TabUI.vue +0 -123
  135. package/dist/components/TextArea.vue +0 -115
  136. package/dist/components/TextBox.vue +0 -111
  137. package/dist/components/TextButton.vue +0 -47
  138. package/dist/components/ToggleButton.vue +0 -179
  139. package/dist/const/index.ts +0 -2
  140. package/dist/const/list-theme.ts +0 -62
  141. package/dist/index.ts +0 -126
  142. package/dist/scripts/form-validation-manager.ts +0 -63
  143. package/dist/scripts/utils.ts +0 -44
  144. package/dist/types/custom.d.ts +0 -1
  145. package/dist/types/vue-shim.d.ts +0 -5
@@ -1,192 +0,0 @@
1
- <script lang="ts">
2
- // スクロールロックはページ全体で 1 つの状態として扱う
3
- let lockCount = 0
4
- let previousOverflow = ''
5
- </script>
6
-
7
- <script setup lang="ts">
8
- import { onMounted, onBeforeUnmount, watch } from 'vue'
9
- import IconClose from '../components/Icon/CloseIcon.vue'
10
-
11
- const props = defineProps<{
12
- isShown: boolean,
13
- size?: 'small' | 'medium' | 'large',
14
- }>()
15
-
16
- const emit = defineEmits<{ (e: 'closeModal', state: boolean): void }>()
17
- const bodyElement = document.querySelector('body') as HTMLElement
18
- // 複数のモーダルが重なっても解除順で壊れないよう、ロック数をカウントする
19
- let isLocked = false
20
-
21
- const toggleScrollLock = (shouldLock: boolean) => {
22
- if (!bodyElement || isLocked === shouldLock) return
23
-
24
- isLocked = shouldLock
25
- lockCount += shouldLock ? 1 : -1
26
-
27
- if (lockCount === 1 && shouldLock) {
28
- previousOverflow = bodyElement.style.overflow
29
- bodyElement.style.overflow = 'hidden'
30
- } else if (lockCount <= 0) {
31
- lockCount = 0
32
- bodyElement.style.overflow = previousOverflow
33
- }
34
- }
35
-
36
- const closeModal = () => {
37
- toggleScrollLock(false)
38
- emit('closeModal', false)
39
- }
40
-
41
- watch(() => props.isShown, newVal => {
42
- if (newVal) toggleScrollLock(true)
43
- else closeModal()
44
- })
45
-
46
- onMounted(() => toggleScrollLock(props.isShown))
47
- onBeforeUnmount(() => closeModal())
48
- </script>
49
-
50
- <template>
51
- <div
52
- :class="[$style.overlay, {[$style.display]: isShown}]"
53
- @click.self="closeModal"
54
- >
55
- <div :class="[$style.container, $style[size ?? 'medium'],]">
56
- <header
57
- v-if="$slots.header"
58
- :class="$style.header"
59
- >
60
- <slot name="header" />
61
- </header>
62
- <div :class="$style.contents">
63
- <slot />
64
- </div>
65
- <footer
66
- v-if="$slots.footer"
67
- :class="$style.footer"
68
- >
69
- <slot name="footer" />
70
- </footer>
71
- <button
72
- type="button"
73
- :class="$style.close_button"
74
- @click="closeModal"
75
- >
76
- <IconClose />
77
- </button>
78
- </div>
79
- </div>
80
- </template>
81
-
82
- <style lang="scss" module>
83
- @use '../assets/scss/mixin' as *;
84
-
85
- .container {
86
- display : flex;
87
- flex-direction : column;
88
- inline-size : 100%;
89
- max-inline-size : var(--desktop-lower-width);
90
- max-block-size : 100%;
91
- background-color: var(--white);
92
- border-radius : var(--radius-small);
93
- cursor : auto;
94
- filter : drop-shadow(0 0 6px var(--shadow-color));
95
- position : relative;
96
-
97
- &.small {
98
- max-inline-size: var(--mobile-lower-width);
99
- }
100
-
101
- &.large {
102
- max-inline-size: var(--contents-max-width);
103
- }
104
- }
105
-
106
- .header {
107
- padding: var(--sp-medium) var(--sp-large);
108
- border-block-end: 1px solid var(--light-border-color);
109
-
110
- > h2 {
111
- font-size : var(--fs-large);
112
- font-weight: bold;
113
- }
114
-
115
- @include media('mobile') {
116
- padding: var(--sp-medium);
117
- }
118
- }
119
-
120
- .contents {
121
- flex : 1 1 auto;
122
- overflow: auto;
123
- padding : var(--sp-large);
124
-
125
- @include media('mobile') {
126
- padding: var(--sp-medium);
127
- }
128
- }
129
-
130
- .footer {
131
- display : flex;
132
- justify-content : center;
133
- gap : var(--sp-large);
134
- padding : var(--sp-medium) var(--sp-large);
135
- border-block-start: 1px solid var(--light-border-color);
136
-
137
- @include media('mobile') {
138
- gap : var(--sp-medium);
139
- padding: var(--sp-medium);
140
-
141
- > * {
142
- flex: 1 1 auto;
143
- }
144
- }
145
- }
146
-
147
- .close_button {
148
- inline-size: var(--icon-medium);
149
- block-size : var(--icon-medium);
150
- color : var(--white);
151
- line-height: 1;
152
- cursor : pointer;
153
- position : absolute;
154
- bottom : 100%;
155
- left : 100%;
156
-
157
- > * {
158
- @include icon();
159
- }
160
- }
161
-
162
- .overlay {
163
- display : flex;
164
- justify-content : center;
165
- align-items : center;
166
- inline-size : 100dvw;
167
- block-size : 100dvh;
168
- padding : var(--sp-larger);
169
- background : var(--overlay-color);
170
- background-blend-mode: multiply;
171
- backdrop-filter : blur(4px);
172
- opacity : 0;
173
- transition : opacity .1s linear;
174
- pointer-events : none;
175
- position : fixed;
176
- z-index : var(--z-index-overlay);
177
- top : 0;
178
- left : 0;
179
- cursor : pointer;
180
- overflow : hidden;
181
-
182
- @include media('mobile') {
183
- padding-inline: var(--sp-large);
184
- }
185
-
186
- &.display {
187
- opacity : 1;
188
- pointer-events: auto;
189
- z-index : calc(var(--z-index-nav) + 1);
190
- }
191
- }
192
- </style>
@@ -1,93 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Ref } from 'vue'
3
- import { ref } from 'vue'
4
- withDefaults(defineProps<{
5
- position?: {
6
- x: 'left' | 'right' | 'center'
7
- y: 'top' | 'bottom' | 'center'
8
- },
9
- }>(), {
10
- position: () => ({ x: 'right', y: 'top' }),
11
- })
12
-
13
- const isShown: Ref<boolean> = ref(false)
14
-
15
- const showPopup = () => {
16
- isShown.value = true
17
-
18
- setTimeout(() => {
19
- isShown.value = false
20
- }, 3000)
21
- }
22
-
23
- defineExpose({
24
- showPopup,
25
- })
26
- </script>
27
-
28
- <template>
29
- <teleport to="body">
30
- <div
31
- :class="[
32
- $style.popup,
33
- $style[`x-${position.x}`],
34
- $style[`y-${position.y}`],
35
- { [$style.show]: isShown },
36
- ]"
37
- >
38
- <slot />
39
- </div>
40
- </teleport>
41
- </template>
42
-
43
- <style lang="scss" module>
44
- .x {
45
- &-left {
46
- left: max(calc((100vw - var(--contents-max-width)) / 2), var(--sp-medium));
47
- }
48
-
49
- &-right {
50
- right: max(calc((100vw - var(--contents-max-width)) / 2), var(--sp-medium));
51
- }
52
-
53
- &-center {
54
- inset: 0;
55
- margin: auto;
56
- }
57
- }
58
-
59
- .y {
60
- &-top {
61
- top: calc(var(--global-header-height) - var(--sp-small));
62
- }
63
-
64
- &-bottom {
65
- bottom: var(--sp-medium);
66
- }
67
-
68
- &-center {
69
- inset : 0;
70
- margin: auto;
71
- }
72
- }
73
-
74
- .popup {
75
- position : fixed;
76
- background-color : var(--white);
77
- border : 1px solid var(--primary-color);
78
- padding : var(--sp-medium);
79
- border-radius : var(--radius-small);
80
- inline-size : max-content;
81
- max-inline-size : calc(var(--lower-mobile-size) / 2);
82
- block-size : max-content;
83
- opacity : 0;
84
- transition : transform, opacity;
85
- transition-duration: var(--transition-duration);
86
- pointer-events : none;
87
- z-index : var(--z-index-overlay);
88
-
89
- &.show {
90
- opacity: 1;
91
- }
92
- }
93
- </style>
@@ -1,163 +0,0 @@
1
- <script lang="ts">
2
- // name を省略したときの既定値に使う連番。
3
- // <script setup> の中はインスタンスごとに実行されるため、モジュールスコープはこちらに置く
4
- let groupSequence = 0
5
- </script>
6
-
7
- <script setup lang="ts">
8
- import type {
9
- Option,
10
- RadioButtonStyleForEachStatus,
11
- } from '../types'
12
- import {
13
- ref,
14
- watch,
15
- computed,
16
- } from 'vue'
17
- import { COLOR } from '../const'
18
-
19
- type SelectValue = string | number
20
-
21
- const emit = defineEmits<{(e: 'update:modelValue', newValue: SelectValue): void}>()
22
-
23
- const props = withDefaults(defineProps<{
24
- modelValue: SelectValue
25
- options: Array<Option>
26
- name?: string
27
- isDisabled? : boolean
28
- isRequired?: boolean
29
- cssStyle?: RadioButtonStyleForEachStatus
30
- isDisableAnimation?: boolean
31
- }>(), {
32
- name : undefined,
33
- cssStyle: undefined,
34
- })
35
-
36
- // name を省略したときの一意な既定値。
37
- // vue 3.5 の useId は peerDependencies(^3.0.0)を満たさないため使わない
38
- const groupName = props.name ?? `radio_group_${++groupSequence}`
39
-
40
- const errorMessages = ref<Array<string>>([])
41
-
42
- const selectedValue = computed({
43
- get: () => props.modelValue ?? '',
44
- set: (newValue: SelectValue) => emit('update:modelValue', newValue),
45
- })
46
-
47
- const currentCssStyle = computed(() => {
48
- const cssStyle = props.isDisabled ? props.cssStyle?.disabled : props.cssStyle?.default
49
-
50
- return {
51
- ...{
52
- textColor : props.isDisabled ? COLOR.darkGray : COLOR.black,
53
- backgroundColor: props.isDisabled ? COLOR.lightGray : COLOR.white,
54
- border : {
55
- color: props.isDisabled ? COLOR.darkGray : COLOR.blue,
56
- size : '1px',
57
- },
58
- },
59
- ...(cssStyle ?? {}),
60
- }
61
- })
62
-
63
- const validateValue = () => {
64
- errorMessages.value = []
65
- if (!selectedValue.value && props.isRequired) errorMessages.value.push('必須項目です')
66
- }
67
-
68
- watch(() => selectedValue.value, () => validateValue(), { immediate: !!props.modelValue })
69
- </script>
70
-
71
- <template>
72
- <div :class="$style.radios">
73
- <label
74
- v-for="option in options"
75
- :key="option.value"
76
- :class="$style.radio"
77
- :style="{
78
- '--border-color': currentCssStyle?.border?.color,
79
- '--border-size' : currentCssStyle?.border?.size,
80
- '--background-color': currentCssStyle?.backgroundColor,
81
- '--duration': isDisableAnimation ? '0s' : '.3s',
82
- }"
83
- >
84
- <input
85
- v-model="selectedValue"
86
- type="radio"
87
- :name="groupName"
88
- :value="option.value"
89
- :disabled="isDisabled"
90
- :required="isRequired"
91
- :checked="option.value === selectedValue"
92
- >
93
- <span>
94
- {{ option.label }}
95
- </span>
96
- </label>
97
- </div>
98
- </template>
99
-
100
- <style lang="scss" module>
101
- @keyframes pop {
102
- 0% {
103
- scale : 1;
104
- }
105
-
106
- 10% {
107
- scale : .8;
108
- }
109
-
110
- 50% {
111
- scale : 1.2;
112
- }
113
-
114
- 100% {
115
- scale: 1;
116
- }
117
- }
118
-
119
- :is(.radios) {
120
- display : flex;
121
- align-items: center;
122
- flex-wrap : wrap;
123
- gap : 1rem;
124
- }
125
-
126
- :is(.radio) {
127
- display : grid;
128
- grid-template-columns: auto 1fr;
129
- align-items : center;
130
- gap : .5rem;
131
- color : var(--border-color);
132
- cursor : pointer;
133
-
134
- &::before {
135
- content : '';
136
- display : inline-block;
137
- aspect-ratio : 1 / 1;
138
- width : 1rem;
139
- box-shadow : 0 0 0 1px var(--border-color) inset;
140
- background-color: var(--background-color);
141
- border-radius : 50%;
142
- transition : all var(--duration) linear;
143
- }
144
-
145
- &:has(input:checked) {
146
- color: var(--text-color);
147
-
148
- &::before {
149
- box-shadow : 0 0 0 2px var(--background-color) inset, 0 0 0 1px var(--border-color);
150
- background-color: var(--border-color);
151
- animation : pop var(--duration) ease-out;
152
- }
153
- }
154
-
155
- &:has(input:disabled) {
156
- cursor: not-allowed !important;
157
- }
158
-
159
- > input {
160
- display: none;
161
- }
162
- }
163
- </style>
@@ -1,166 +0,0 @@
1
- <script setup lang="ts">
2
- import type {
3
- Option,
4
- InputBoxStyleForEachStatus,
5
- } from '../types'
6
- import {
7
- ref,
8
- computed,
9
- watch,
10
- } from 'vue'
11
- import InputBox from '../components/InputBox.vue'
12
- import ErrorMessage from '../components/ErrorMessage.vue'
13
- import KeyboardArrowDownIcon from '../components/Icon/KeyboardArrowDownIcon.vue'
14
-
15
- type SelectValue = string | number
16
-
17
- const emit = defineEmits<{ (e: 'update:modelValue', newValue: SelectValue): void }>()
18
-
19
- const props = withDefaults(defineProps<{
20
- options : Array<Option | Record<string, Option[]>>
21
- name: string
22
- modelValue?: SelectValue
23
- cssStyle?: InputBoxStyleForEachStatus | undefined
24
- placeholder?: string
25
- canOmitSelect?: boolean
26
- isDisabled? : boolean
27
- isRequired?: boolean
28
- }>(), {
29
- modelValue : undefined,
30
- cssStyle : undefined,
31
- placeholder: '選択してください',
32
- })
33
-
34
- const errorMessages = ref<Array<string>>([])
35
-
36
- const selectedValue = computed<SelectValue>({
37
- get: () => props.modelValue ?? '',
38
- set: (newValue: SelectValue) => emit('update:modelValue', newValue),
39
- })
40
-
41
- const isOption = (obj: unknown): obj is Option => {
42
- return (
43
- typeof obj === 'object' &&
44
- obj !== null &&
45
- 'label' in obj && typeof obj.label === 'string' &&
46
- 'value' in obj
47
- )
48
- }
49
-
50
- const validateValue = () => {
51
- errorMessages.value = []
52
- if (!selectedValue.value && props.isRequired) errorMessages.value.push('必須項目です')
53
- }
54
-
55
- watch(() => selectedValue.value, () => validateValue(), { immediate: !!props.modelValue, flush: 'post' })
56
- </script>
57
-
58
- <template>
59
- <InputBox
60
- :cssStyle="cssStyle"
61
- :class="$style.select_box"
62
- :isDisabled="isDisabled"
63
- >
64
- <select
65
- v-model="selectedValue"
66
- :disabled="isDisabled"
67
- :required="isRequired"
68
- :class="$style.select"
69
- @blur="validateValue()"
70
- >
71
- <option
72
- v-if="canOmitSelect"
73
- value=""
74
- >
75
- {{ placeholder || '選択しない' }}
76
- </option>
77
- <option
78
- v-else
79
- disabled
80
- selected
81
- value=""
82
- >
83
- {{ placeholder || '選択してください' }}
84
- </option>
85
- <option
86
- v-if="['0', 'NA'].includes(selectedValue.toString()) && isDisabled"
87
- disabled
88
- selected
89
- :value="selectedValue"
90
- >
91
- {{ placeholder || '選択してください' }}
92
- </option>
93
- <template
94
- v-for="option in options"
95
- :key="isOption(option) ? option.value : Object.keys(option)[0]"
96
- >
97
- <option
98
- v-if="isOption(option)"
99
- :value="option.value"
100
- :disabled="option.isDisabled"
101
- >
102
- {{ option.label }}
103
- </option>
104
- <template v-else>
105
- <optgroup
106
- v-for="(opt, key) in option"
107
- :key="key"
108
- :label="key"
109
- >
110
- <option
111
- v-for="o in opt"
112
- :key="o.value"
113
- :value="o.value"
114
- :disabled="o.isDisabled"
115
- >
116
- {{ o.label }}
117
- </option>
118
- </optgroup>
119
- <hr>
120
- </template>
121
- </template>
122
- </select>
123
- <div :class="$style.arrow_container">
124
- <slot name="arrow" />
125
- <KeyboardArrowDownIcon
126
- v-if="!$slots.arrow"
127
- :class="$style.arrow"
128
- />
129
- </div>
130
- <ErrorMessage
131
- :errorMessages="errorMessages"
132
- :cssStyle="{
133
- textColor: cssStyle?.error?.backgroundColor,
134
- backgroundColor: cssStyle?.error?.textColor,
135
- }"
136
- />
137
- </InputBox>
138
- </template>
139
-
140
- <style lang="scss" module>
141
- :is(.select_box) {
142
- display: inline-flex;
143
-
144
- > select {
145
- flex : 1 1 auto;
146
- padding-inline-end: 2rem;
147
- cursor : pointer;
148
- }
149
- }
150
-
151
- :is(.arrow_container) {
152
- display : flex;
153
- align-items : center;
154
- position : absolute;
155
- margin : auto;
156
- inset-inline-end: .5rem;
157
- inset-block : 0;
158
- pointer-events : none;
159
-
160
- > * {
161
- color : currentColor;
162
- fill : currentColor;
163
- block-size: 1rem;
164
- }
165
- }
166
- </style>