@globalbrain/sefirot 2.20.0 → 2.21.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.
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { DropdownSection } from '../composables/Dropdown'
3
+ import SDropdownSectionActions from './SDropdownSectionActions.vue'
4
+ import SDropdownSectionComponent from './SDropdownSectionComponent.vue'
3
5
  import SDropdownSectionFilter from './SDropdownSectionFilter.vue'
4
6
  import SDropdownSectionMenu from './SDropdownSectionMenu.vue'
5
7
 
@@ -20,6 +22,14 @@ defineProps<{
20
22
  :options="section.options"
21
23
  :on-click="section.onClick"
22
24
  />
25
+ <SDropdownSectionActions
26
+ v-if="section.type === 'actions'"
27
+ :options="section.options"
28
+ />
29
+ <SDropdownSectionComponent
30
+ v-else-if="section.type === 'component'"
31
+ :comp="section.component"
32
+ />
23
33
  </template>
24
34
 
25
35
  <style scoped lang="postcss">
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ import { DropdownSectionActionsOption } from '../composables/Dropdown'
3
+
4
+ defineProps<{
5
+ options: DropdownSectionActionsOption[]
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <div class="SDropdownSectionActions">
11
+ <div v-for="option in options" :key="option.label" class="item">
12
+ <button class="button" :class="[option.mode ?? 'neutral']" @click="option.onClick">
13
+ {{ option.label }}
14
+ </button>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <style scoped lang="postcss">
20
+ .SDropdownSectionActions {
21
+ display: flex;
22
+ justify-content: flex-end;
23
+ padding: 8px;
24
+ }
25
+
26
+ .button {
27
+ display: block;
28
+ border-radius: 6px;
29
+ padding: 0 8px;
30
+ width: 100%;
31
+ text-align: left;
32
+ line-height: 32px;
33
+ font-size: 12px;
34
+ font-weight: 500;
35
+ transition: color 0.25s, background-color 0.25s;
36
+
37
+ &.neutral { color: var(--button-text-neutral-text-color); }
38
+ &.neutral:hover { background-color: var(--button-text-neutral-hover-bg-color); }
39
+ &.neutral:active { background-color: var(--button-text-neutral-active-bg-color); }
40
+
41
+ &.mute { color: var(--button-text-mute-text-color); }
42
+ &.mute:hover { background-color: var(--button-text-mute-hover-bg-color); }
43
+ &.mute:active { background-color: var(--button-text-mute-active-bg-color); }
44
+
45
+ &.info { color: var(--button-text-info-text-color); }
46
+ &.info:hover { background-color: var(--button-text-info-hover-bg-color); }
47
+ &.info:active { background-color: var(--button-text-info-active-bg-color); }
48
+
49
+ &.success { color: var(--button-text-success-text-color); }
50
+ &.success:hover { background-color: var(--button-text-success-hover-bg-color); }
51
+ &.success:active { background-color: var(--button-text-success-active-bg-color); }
52
+
53
+ &.warning { color: var(--button-text-warning-text-color); }
54
+ &.warning:hover { background-color: var(--button-text-warning-hover-bg-color); }
55
+ &.warning:active { background-color: var(--button-text-warning-active-bg-color); }
56
+
57
+ &.danger { color: var(--button-text-danger-text-color); }
58
+ &.danger:hover { background-color: var(--button-text-danger-hover-bg-color); }
59
+ &.danger:active { background-color: var(--button-text-danger-active-bg-color); }
60
+ }
61
+ </style>
@@ -0,0 +1,11 @@
1
+ <script setup lang="ts">
2
+ import { DefineComponent } from 'vue'
3
+
4
+ defineProps<{
5
+ comp: DefineComponent
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <Component :is="comp" />
11
+ </template>
@@ -5,36 +5,53 @@ import { Validatable } from '../composables/Validation'
5
5
  import SInputBase from './SInputBase.vue'
6
6
 
7
7
  export type Size = 'mini' | 'small' | 'medium'
8
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
8
+ export type ActiveColor = 'info' | 'success' | 'warning' | 'danger'
9
+ export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
9
10
 
10
- const props = defineProps<{
11
+ const props = withDefaults(defineProps<{
11
12
  size?: Size
12
13
  name?: string
13
14
  label?: string
14
15
  info?: string
15
16
  note?: string
16
17
  text?: string
18
+ color?: ActiveColor
17
19
  help?: string
18
20
  checkIcon?: IconifyIcon | DefineComponent
19
21
  checkText?: string
20
- checkColor?: Color
22
+ checkColor?: CheckColor
21
23
  disabled?: boolean
22
- modelValue: boolean
24
+ value?: boolean
25
+ modelValue?: boolean
23
26
  hideError?: boolean
24
27
  validation?: Validatable
25
- }>()
28
+ }>(), {
29
+ value: undefined,
30
+ modelValue: undefined
31
+ })
26
32
 
27
33
  const emit = defineEmits<{
28
- (e: 'update:modelValue', value: boolean): void
34
+ (e: 'update:model-value', value: boolean): void
35
+ (e: 'change', value: boolean): void
29
36
  }>()
30
37
 
38
+ const _value = computed(() => {
39
+ return props.modelValue !== undefined
40
+ ? props.modelValue
41
+ : props.value !== undefined ? props.value : false
42
+ })
43
+
31
44
  const classes = computed(() => [
32
- [props.size ?? 'small'],
45
+ props.size ?? 'small',
46
+ props.color ?? 'info',
33
47
  { disabled: props.disabled }
34
48
  ])
35
49
 
36
50
  function emitChange(): void {
37
- !props.disabled && emit('update:modelValue', !props.modelValue)
51
+ if (!props.disabled) {
52
+ emit('update:model-value', !_value.value)
53
+ emit('change', !_value.value)
54
+ }
38
55
  }
39
56
  </script>
40
57
 
@@ -53,11 +70,10 @@ function emitChange(): void {
53
70
  :hide-error="hideError"
54
71
  >
55
72
  <div class="container">
56
- <div class="input" :class="{ on: modelValue }" role="button" @click="emitChange">
73
+ <div class="input" :class="{ on: _value }" role="button" @click="emitChange">
57
74
  <p v-if="text" class="text">{{ text }}</p>
58
-
59
75
  <div class="box">
60
- <div class="check" />
76
+ <div class="toggle" />
61
77
  </div>
62
78
  </div>
63
79
  </div>
@@ -65,7 +81,185 @@ function emitChange(): void {
65
81
  </SInputBase>
66
82
  </template>
67
83
 
68
- <style lang="postcss" scoped>
84
+ <style scoped lang="postcss">
85
+ .SInputSwitch.mini {
86
+ .input {
87
+ height: 32px;
88
+ }
89
+
90
+ .text {
91
+ line-height: 20px;
92
+ font-size: 14px;
93
+ }
94
+
95
+ .box {
96
+ border-radius: 9px;
97
+ width: 32px;
98
+ height: 18px;
99
+ }
100
+
101
+ .toggle {
102
+ top: 1px;
103
+ left: 1px;
104
+ width: 14px;
105
+ height: 14px;
106
+ }
107
+
108
+ .input.on .toggle {
109
+ transform: translateX(14px);
110
+ }
111
+ }
112
+
113
+ .SInputSwitch.small {
114
+ .input {
115
+ height: 32px;
116
+ }
117
+
118
+ .text {
119
+ line-height: 20px;
120
+ font-size: 14px;
121
+ }
122
+
123
+ .box {
124
+ border-radius: 11px;
125
+ width: 40px;
126
+ height: 22px;
127
+ }
128
+
129
+ .toggle {
130
+ top: 2px;
131
+ left: 2px;
132
+ width: 16px;
133
+ height: 16px;
134
+ }
135
+
136
+ .input.on .toggle {
137
+ transform: translateX(18px);
138
+ }
139
+ }
140
+
141
+ .SInputSwitch.medium {
142
+ .input {
143
+ height: 32px;
144
+ }
145
+
146
+ .text {
147
+ line-height: 20px;
148
+ font-size: 14px;
149
+ }
150
+
151
+ .box {
152
+ border-radius: 13px;
153
+ width: 46px;
154
+ height: 26px;
155
+ }
156
+
157
+ .toggle {
158
+ top: 3px;
159
+ left: 3px;
160
+ width: 18px;
161
+ height: 18px;
162
+ }
163
+
164
+ .input.on .toggle {
165
+ transform: translateX(20px);
166
+ }
167
+ }
168
+
169
+ .SInputSwitch.info {
170
+ .box:hover {
171
+ border-color: var(--c-info-light);
172
+ }
173
+
174
+ .input.on .box {
175
+ border-color: var(--c-info-light);
176
+ background-color: var(--c-info);
177
+ }
178
+ }
179
+
180
+ .SInputSwitch.success {
181
+ .box:hover {
182
+ border-color: var(--c-success-light);
183
+ }
184
+
185
+ .input.on .box {
186
+ border-color: var(--c-success-light);
187
+ background-color: var(--c-success);
188
+ }
189
+ }
190
+
191
+ .SInputSwitch.warning {
192
+ .box:hover {
193
+ border-color: var(--c-warning-light);
194
+ }
195
+
196
+ .input.on .box {
197
+ border-color: var(--c-warning-light);
198
+ background-color: var(--c-warning);
199
+ }
200
+ }
201
+
202
+ .SInputSwitch.danger {
203
+ .box:hover {
204
+ border-color: var(--c-danger-light);
205
+ }
206
+
207
+ .input.on .box {
208
+ border-color: var(--c-danger-light);
209
+ background-color: var(--c-danger);
210
+ }
211
+ }
212
+
213
+ .SInputSwitch.disabled {
214
+ .input {
215
+ cursor: not-allowed;
216
+ }
217
+
218
+ .box {
219
+ background-color: var(--input-switch-disabled-bg-color);
220
+ }
221
+
222
+ .box:hover {
223
+ border-color: var(--c-divider-1);
224
+ }
225
+
226
+ .toggle {
227
+ background-color: var(--input-switch-disabled-toggle-color);
228
+ }
229
+
230
+ .input.on .toggle {
231
+ opacity: 0.5;
232
+ }
233
+
234
+ &.info {
235
+ .input.on .box {
236
+ border-color: var(--c-info);
237
+ background-color: var(--c-info-dark);
238
+ }
239
+ }
240
+
241
+ &.success {
242
+ .input.on .box {
243
+ border-color: var(--c-success);
244
+ background-color: var(--c-success-dark);
245
+ }
246
+ }
247
+
248
+ &.warning {
249
+ .input.on .box {
250
+ border-color: var(--c-warning);
251
+ background-color: var(--c-warning-dark);
252
+ }
253
+ }
254
+
255
+ &.danger {
256
+ .input.on .box {
257
+ border-color: var(--c-danger);
258
+ background-color: var(--c-danger-dark);
259
+ }
260
+ }
261
+ }
262
+
69
263
  .container {
70
264
  display: flex;
71
265
  }
@@ -76,11 +270,7 @@ function emitChange(): void {
76
270
  justify-content: space-between;
77
271
  align-items: center;
78
272
  width: 100%;
79
- height: 32px;
80
-
81
- &:hover {
82
- .box { border-color: var(--c-info); }
83
- }
273
+ cursor: pointer;
84
274
  }
85
275
 
86
276
  .input.on .box {
@@ -88,43 +278,28 @@ function emitChange(): void {
88
278
  background-color: var(--c-info);
89
279
  }
90
280
 
91
- .input.on .check {
281
+ .input.on .toggle {
92
282
  background-color: var(--c-white);
93
- transform: translateX(18px);
94
283
  }
95
284
 
96
285
  .text {
97
286
  flex-grow: 1;
98
287
  margin: 0;
99
288
  padding-right: 16px;
100
- line-height: 20px;
101
- font-size: 14px;
102
- font-weight: 500;
103
289
  }
104
290
 
105
291
  .box {
106
292
  position: relative;
107
293
  flex-shrink: 0;
108
- border: 1px solid var(--c-divider);
109
- border-radius: 11px;
110
- width: 40px;
111
- height: 22px;
112
- background-color: var(--c-bg-elv-down);
294
+ border: 1px solid var(--c-divider-1);
295
+ background-color: var(--input-switch-bg-color);
113
296
  transition: border-color 0.25s, background-color 0.25s, box-shadow 0.25s;
114
297
  }
115
298
 
116
- .check {
299
+ .toggle {
117
300
  position: absolute;
118
301
  border-radius: 50%;
119
- background-color: var(--c-black);
120
- top: 2px;
121
- left: 2px;
122
- width: 16px;
123
- height: 16px;
124
- transition: background-color .25s, transform .25s;
125
-
126
- .dark & {
127
- background-color: var(--c-white);
128
- }
302
+ background-color: var(--input-switch-toggle-color);
303
+ transition: background-color 0.25s, transform 0.25s;
129
304
  }
130
305
  </style>
@@ -6,7 +6,7 @@ import SInputBase from './SInputBase.vue'
6
6
  import SInputSwitch from './SInputSwitch.vue'
7
7
 
8
8
  export type Size = 'mini' | 'small' | 'medium'
9
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
9
+ export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
10
10
 
11
11
  export interface Option {
12
12
  label: string
@@ -22,7 +22,7 @@ const props = defineProps<{
22
22
  help?: string
23
23
  checkIcon?: IconifyIcon | DefineComponent
24
24
  checkText?: string
25
- checkColor?: Color
25
+ checkColor?: CheckColor
26
26
  options: Option[]
27
27
  disabled?: boolean
28
28
  modelValue: (string | number | boolean)[]
@@ -4,8 +4,10 @@ import { Ref, ref, unref } from 'vue'
4
4
  export type DropdownSection =
5
5
  | DropdownSectionMenu
6
6
  | DropdownSectionFilter
7
+ | DropdownSectionComponent
8
+ | DropdownSectionActions
7
9
 
8
- export type DropdownSectionType = 'menu' | 'filter'
10
+ export type DropdownSectionType = 'menu' | 'filter' | 'actions' | 'component'
9
11
 
10
12
  export interface DropdownSectionBase {
11
13
  type: DropdownSectionType
@@ -56,6 +58,22 @@ export interface DropdownSectionFilterOptionAvatar extends DropdownSectionFilter
56
58
  image?: string | null
57
59
  }
58
60
 
61
+ export interface DropdownSectionActions extends DropdownSectionBase {
62
+ type: 'actions'
63
+ options: DropdownSectionActionsOption[]
64
+ }
65
+
66
+ export interface DropdownSectionActionsOption {
67
+ mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
68
+ label: string
69
+ onClick(): void
70
+ }
71
+
72
+ export interface DropdownSectionComponent extends DropdownSectionBase {
73
+ type: 'component'
74
+ component: any
75
+ }
76
+
59
77
  export interface ManualDropdownPosition {
60
78
  container: Ref<any>
61
79
  position: Ref<'top' | 'bottom'>
@@ -666,4 +666,14 @@
666
666
  --input-mini-label-font-size: 12px;
667
667
  --input-small-label-font-size: 14px;
668
668
  --input-medium-label-font-size: 14px;
669
+
670
+ --input-switch-toggle-color: var(--c-neutral-1);
671
+ --input-switch-bg-color: var(--c-mute);
672
+ --input-switch-disabled-toggle-color: var(--c-gray);
673
+ --input-switch-disabled-bg-color: var(--c-mute);
674
+ }
675
+
676
+ .dark {
677
+ --input-switch-bg-color: var(--c-bg-elv-1);
678
+ --input-switch-disabled-bg-color: var(--c-mute);
669
679
  }
@@ -1,7 +1,7 @@
1
1
  export interface Hms {
2
- hour?: string
3
- minute?: string
4
- second?: string
2
+ hour?: string | null
3
+ minute?: string | null
4
+ second?: string | null
5
5
  }
6
6
 
7
7
  export type HmsType = 'h' | 'm' | 's'
@@ -1,7 +1,7 @@
1
1
  export interface Hms {
2
- hour?: string
3
- minute?: string
4
- second?: string
2
+ hour?: string | null
3
+ minute?: string | null
4
+ second?: string | null
5
5
  }
6
6
 
7
7
  export type HmsType = 'h' | 'm' | 's'
@@ -13,5 +13,5 @@ export const HmsMap = {
13
13
  } as const
14
14
 
15
15
  export function requiredHms(hms: Hms, required: HmsType[] = ['h', 'm', 's']): boolean {
16
- return required.every((r) => hms[HmsMap[r]] !== undefined)
16
+ return required.every((r) => hms[HmsMap[r]] != null)
17
17
  }
@@ -3,5 +3,5 @@ import { Ymd, YmdMap, YmdType } from './ymd'
3
3
  export type { Ymd, YmdType, YmdMap }
4
4
 
5
5
  export function requiredYmd(ymd: Ymd, required: YmdType[] = ['y', 'm', 'd']): boolean {
6
- return required.every((r) => ymd[YmdMap[r]] !== null)
6
+ return required.every((r) => ymd[YmdMap[r]] != null)
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "2.20.0",
3
+ "version": "2.21.0",
4
4
  "packageManager": "pnpm@7.26.2",
5
5
  "description": "Vue Components for Global Brain Design System.",
6
6
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",