@globalbrain/sefirot 2.47.4 → 2.49.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.
@@ -0,0 +1,132 @@
1
+ <script setup lang="ts" generic="T extends string | number | boolean">
2
+ import { type IconifyIcon } from '@iconify/vue/dist/offline'
3
+ import { computed } from 'vue'
4
+ import { type Validatable } from '../composables/Validation'
5
+ import SInputBase from './SInputBase.vue'
6
+ import SInputSegmentsOption, { type Mode } from './SInputSegmentsOption.vue'
7
+
8
+ export type Size = 'mini' | 'small' | 'medium'
9
+ export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
10
+
11
+ export interface Option<T extends string | number | boolean> {
12
+ label: string
13
+ value: T
14
+ mode?: Mode
15
+ disabled?: boolean
16
+ }
17
+
18
+ const props = defineProps<{
19
+ size?: Size
20
+ name?: string
21
+ label?: string
22
+ info?: string
23
+ note?: string
24
+ help?: string
25
+ checkIcon?: IconifyIcon
26
+ checkText?: string
27
+ checkColor?: Color
28
+ options: Option<T>[]
29
+ block?: boolean
30
+ disabled?: boolean
31
+ value?: T
32
+ modelValue?: T
33
+ validation?: Validatable
34
+ hideError?: boolean
35
+ }>()
36
+
37
+ const emit = defineEmits<{
38
+ (e: 'update:model-value', value: T): void
39
+ (e: 'change', value: T): void
40
+ }>()
41
+
42
+ const _value = computed(() => {
43
+ const v = props.modelValue !== undefined
44
+ ? props.modelValue
45
+ : props.value
46
+
47
+ if (v === undefined) {
48
+ throw new Error('[sefirot] SInputSegments: `value` or `modelValue` is required.')
49
+ }
50
+
51
+ return v
52
+ })
53
+
54
+ function onSelect(value: T) {
55
+ emit('update:model-value', value)
56
+ emit('change', value)
57
+ }
58
+ </script>
59
+
60
+ <template>
61
+ <SInputBase
62
+ class="SInputSegments"
63
+ :class="[size ?? 'small', { block }]"
64
+ :label="label"
65
+ :note="note"
66
+ :info="info"
67
+ :help="help"
68
+ :check-icon="checkIcon"
69
+ :check-text="checkText"
70
+ :check-color="checkColor"
71
+ :hide-error="hideError"
72
+ :validation="validation"
73
+ >
74
+ <div class="box">
75
+ <SInputSegmentsOption
76
+ v-for="option, index in options"
77
+ :key="index"
78
+ :size="size ?? 'small'"
79
+ :label="option.label"
80
+ :value="option.value"
81
+ :mode="option.mode ?? 'neutral'"
82
+ :active="_value === option.value"
83
+ :disabled="disabled ? true : option.disabled ?? false"
84
+ @click="onSelect(option.value)"
85
+ />
86
+ </div>
87
+ <template v-if="$slots.info" #info><slot name="info" /></template>
88
+ </SInputBase>
89
+ </template>
90
+
91
+ <style scoped lang="postcss">
92
+ .SInputSegments.mini {
93
+ .box {
94
+ padding: 2px;
95
+ height: 32px;
96
+ }
97
+ }
98
+
99
+ .SInputSegments.small {
100
+ .box {
101
+ padding: 4px;
102
+ height: 40px;
103
+ }
104
+ }
105
+
106
+ .SInputSegments.medium {
107
+ .box {
108
+ padding: 4px;
109
+ height: 48px;
110
+ }
111
+ }
112
+
113
+ .SInputSegments.block {
114
+ .box {
115
+ display: flex;
116
+ }
117
+ }
118
+
119
+ .SInputSegments.has-error {
120
+ .box {
121
+ border-color: var(--input-error-border-color);
122
+ }
123
+ }
124
+
125
+ .box {
126
+ display: inline-flex;
127
+ border: 1px solid var(--input-border-color);
128
+ border-radius: 6px;
129
+ background-color: var(--input-bg-color);
130
+ transition: border-color 0.25s;
131
+ }
132
+ </style>
@@ -0,0 +1,150 @@
1
+ <script setup lang="ts" generic="T extends string | number | boolean">
2
+ export type Size = 'mini' | 'small' | 'medium'
3
+ export type Mode = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
4
+
5
+ const props = defineProps<{
6
+ size: Size
7
+ label: string
8
+ value: T
9
+ mode: Mode
10
+ active: boolean
11
+ disabled: boolean
12
+ }>()
13
+
14
+ const emit = defineEmits<{
15
+ (e: 'click'): void
16
+ }>()
17
+
18
+ function onClick() {
19
+ if (!props.disabled) {
20
+ emit('click')
21
+ }
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <button
27
+ class="SInputSegmentsOption"
28
+ :class="[size, mode, { active }, { disabled }]"
29
+ @click="onClick"
30
+ >
31
+ <span class="label">
32
+ {{ label }}
33
+ </span>
34
+ </button>
35
+ </template>
36
+
37
+ <style scoped lang="postcss">
38
+ .SInputSegmentsOption {
39
+ position: relative;
40
+ display: block;
41
+ flex-grow: 1;
42
+ justify-content: center;
43
+ align-items: center;
44
+ border: 1px solid transparent;
45
+ border-radius: 3px;
46
+ width: 100%;
47
+ height: 100%;
48
+ text-align: center;
49
+ font-size: 14px;
50
+ color: var(--c-text-2);
51
+ white-space: nowrap;
52
+ transition: border-color 0.25s, color 0.25s, background-color 0.25s;
53
+
54
+ &:hover {
55
+ color: var(--c-text-1);
56
+ }
57
+
58
+ &.disabled {
59
+ color: var(--c-text-3);
60
+ cursor: not-allowed;
61
+ }
62
+
63
+ .SInputSegmentsOption + &::before {
64
+ position: absolute;
65
+ left: -1px;
66
+ display: block;
67
+ width: 1px;
68
+ height: 16px;
69
+ border-radius: 4px;
70
+ background-color: var(--c-divider-2);
71
+ content: "";
72
+ transition: opacity 0.25s;
73
+ }
74
+
75
+ .SInputSegmentsOption.active + &::before,
76
+ &.active::before {
77
+ opacity: 0;
78
+ }
79
+ }
80
+
81
+ .SInputSegmentsOption.mini {
82
+ .SInputSegmentsOption + &::before {
83
+ top: 4px;
84
+ }
85
+
86
+ .label {
87
+ padding: 0 12px;
88
+ }
89
+ }
90
+
91
+ .SInputSegmentsOption.small {
92
+ .SInputSegmentsOption + &::before {
93
+ top: 7px;
94
+ }
95
+
96
+ .label {
97
+ padding: 0 12px;
98
+ }
99
+ }
100
+
101
+ .SInputSegmentsOption.medium {
102
+ .SInputSegmentsOption + &::before {
103
+ top: 10px;
104
+ }
105
+
106
+ .label {
107
+ padding: 0 16px;
108
+ }
109
+ }
110
+
111
+ .SInputSegmentsOption.neutral.active {
112
+ border-color: var(--button-fill-mute-border-color);
113
+ color: var(--button-fill-mute-text-color);
114
+ background-color: var(--button-fill-mute-bg-color);
115
+ }
116
+
117
+ .SInputSegmentsOption.mute.active {
118
+ border-color: var(--button-fill-mute-border-color);
119
+ color: var(--c-text-2);
120
+ background-color: var(--button-fill-mute-bg-color);
121
+ }
122
+
123
+ .SInputSegmentsOption.info.active {
124
+ border-color: var(--button-fill-info-border-color);
125
+ color: var(--button-fill-info-text-color);
126
+ background-color: var(--button-fill-info-bg-color);
127
+ }
128
+
129
+ .SInputSegmentsOption.success.active {
130
+ border-color: var(--button-fill-success-border-color);
131
+ color: var(--button-fill-success-text-color);
132
+ background-color: var(--button-fill-success-bg-color);
133
+ }
134
+
135
+ .SInputSegmentsOption.warning.active {
136
+ border-color: var(--button-fill-warning-border-color);
137
+ color: var(--button-fill-warning-text-color);
138
+ background-color: var(--button-fill-warning-bg-color);
139
+ }
140
+
141
+ .SInputSegmentsOption.danger.active {
142
+ border-color: var(--button-fill-danger-border-color);
143
+ color: var(--button-fill-danger-text-color);
144
+ background-color: var(--button-fill-danger-bg-color);
145
+ }
146
+
147
+ .label {
148
+ display: inline-block;
149
+ }
150
+ </style>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
  import { type TableCell } from '../composables/Table'
4
+ import STableCellActions from './STableCellActions.vue'
4
5
  import STableCellAvatar from './STableCellAvatar.vue'
5
6
  import STableCellAvatars from './STableCellAvatars.vue'
6
7
  import STableCellCustom from './STableCellCustom.vue'
@@ -99,6 +100,12 @@ const computedCell = computed<TableCell | undefined>(() =>
99
100
  :avatars="computedCell.avatars"
100
101
  :color="computedCell.color"
101
102
  />
103
+ <STableCellActions
104
+ v-else-if="computedCell.type === 'actions'"
105
+ :value="value"
106
+ :record="record"
107
+ :actions="computedCell.actions"
108
+ />
102
109
  <STableCellCustom
103
110
  v-else-if="computedCell.type === 'custom'"
104
111
  >
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ import { type TableCellAction } from '../composables/Table'
3
+ import SButton from './SButton.vue'
4
+
5
+ defineProps<{
6
+ value: any
7
+ record: any
8
+ actions: TableCellAction[]
9
+ }>()
10
+ </script>
11
+
12
+ <template>
13
+ <div class="STableCellActions">
14
+ <SButton
15
+ v-for="(action, i) in actions"
16
+ :key="i"
17
+ size="mini"
18
+ type="text"
19
+ :mode="action.mode ?? 'mute'"
20
+ :icon="action.icon"
21
+ :icon-mode="action.iconMode"
22
+ :label="action.label"
23
+ :label-mode="action.labelMode"
24
+ @click="action.onClick(value, record)"
25
+ />
26
+ </div>
27
+ </template>
28
+
29
+ <style scoped lang="postcss">
30
+ .STableCellActions {
31
+ min-height: 40px;
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ flex-wrap: nowrap;
36
+ flex-direction: row;
37
+ }
38
+ </style>
@@ -33,7 +33,7 @@ const names = computed(() => {
33
33
  return `${_avatars.value[0].name}, ${_avatars.value[1].name}`
34
34
  }
35
35
 
36
- return `${_avatars.value[0].name}, ${_avatars.value[1].name} +${_avatars.value.length - 1}`
36
+ return `${_avatars.value[0].name}, ${_avatars.value[1].name} +${_avatars.value.length - 2}`
37
37
  })
38
38
  </script>
39
39
 
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
- import { type TableAction, type TableMenu } from '../composables/Table'
3
+ import { type TableHeaderAction, type TableMenu } from '../composables/Table'
4
4
  import { format } from '../support/Num'
5
5
  import { isNullish } from '../support/Utils'
6
6
  import STableHeaderActions from './STableHeaderActions.vue'
@@ -10,7 +10,7 @@ const props = defineProps<{
10
10
  total?: number | null
11
11
  reset?: boolean
12
12
  menu?: TableMenu[] | TableMenu[][]
13
- actions?: TableAction[]
13
+ actions?: TableHeaderAction[]
14
14
  borderless?: boolean
15
15
  onReset?(): void
16
16
  selected?: unknown[]
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
- import { type TableAction } from '../composables/Table'
2
+ import { type TableHeaderAction } from '../composables/Table'
3
3
  import SButton from './SButton.vue'
4
4
 
5
- withDefaults(defineProps<TableAction>(), {
5
+ withDefaults(defineProps<TableHeaderAction>(), {
6
6
  show: true,
7
7
  mode: 'mute',
8
8
  labelMode: 'neutral'
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
- import { type TableAction } from '../composables/Table'
2
+ import { type TableHeaderAction } from '../composables/Table'
3
3
  import STableHeaderActionItem from './STableHeaderActionItem.vue'
4
4
 
5
- defineProps<{ actions: TableAction[] }>()
5
+ defineProps<{ actions: TableHeaderAction[] }>()
6
6
  </script>
7
7
 
8
8
  <template>
@@ -10,7 +10,7 @@ export interface Table<
10
10
  orders: MaybeRef<O[]>
11
11
  columns: MaybeRef<TableColumns<O, R, SR>>
12
12
  menu?: MaybeRef<TableMenu[] | TableMenu[][]>
13
- actions?: MaybeRef<TableAction[]>
13
+ actions?: MaybeRef<TableHeaderAction[]>
14
14
  records?: MaybeRef<R[] | null | undefined>
15
15
  header?: MaybeRef<boolean | undefined>
16
16
  footer?: MaybeRef<boolean | undefined>
@@ -64,6 +64,7 @@ export type TableCell =
64
64
  | TableCellCustom
65
65
  | TableCellEmpty
66
66
  | TableCellComponent
67
+ | TableCellActions
67
68
 
68
69
  export type TableCellType =
69
70
  | 'text'
@@ -77,6 +78,9 @@ export type TableCellType =
77
78
  | 'custom'
78
79
  | 'empty'
79
80
  | 'component'
81
+ | 'actions'
82
+
83
+ export type ColorModes = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
80
84
 
81
85
  export interface TableCellBase {
82
86
  type: TableCellType
@@ -105,14 +109,7 @@ export interface TableCellNumber extends TableCellBase {
105
109
  onClick?(value: any, record: any): void
106
110
  }
107
111
 
108
- export type TableCellValueColor =
109
- | 'neutral'
110
- | 'soft'
111
- | 'mute'
112
- | 'info'
113
- | 'success'
114
- | 'warning'
115
- | 'danger'
112
+ export type TableCellValueColor = ColorModes | 'soft'
116
113
 
117
114
  export interface TableCellDay extends TableCellBase {
118
115
  type: 'day'
@@ -128,7 +125,7 @@ export interface TableCellPill extends TableCellBase {
128
125
  color?: TableCellPillColor | ((value: any, record: any) => TableCellPillColor)
129
126
  }
130
127
 
131
- export type TableCellPillColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
128
+ export type TableCellPillColor = ColorModes
132
129
 
133
130
  export interface TableCellPills extends TableCellBase {
134
131
  type: 'pills'
@@ -177,7 +174,21 @@ export interface TableCellComponent extends TableCellBase {
177
174
  export interface TableCellState extends TableCellBase {
178
175
  type: 'state'
179
176
  label: string
180
- mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
177
+ mode?: ColorModes
178
+ }
179
+
180
+ export interface TableCellActions extends TableCellBase {
181
+ type: 'actions'
182
+ actions: TableCellAction[]
183
+ }
184
+
185
+ export interface TableCellAction {
186
+ mode?: ColorModes
187
+ icon?: any
188
+ iconMode?: ColorModes
189
+ label?: string
190
+ labelMode?: ColorModes
191
+ onClick(value: any, record: any): void
181
192
  }
182
193
 
183
194
  export interface TableMenu {
@@ -186,11 +197,11 @@ export interface TableMenu {
186
197
  dropdown: DropdownSection[]
187
198
  }
188
199
 
189
- export interface TableAction {
200
+ export interface TableHeaderAction {
190
201
  show?: boolean
191
- mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
202
+ mode?: ColorModes
192
203
  label: string
193
- labelMode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
204
+ labelMode?: ColorModes
194
205
  onClick(): void
195
206
  }
196
207
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "2.47.4",
3
+ "version": "2.49.0",
4
4
  "packageManager": "pnpm@8.8.0",
5
5
  "description": "Vue Components for Global Brain Design System.",
6
6
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",