@globalbrain/sefirot 2.36.0 → 2.37.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.
@@ -103,6 +103,7 @@ function handleClick(option: DropdownSectionFilterOption, value: string | number
103
103
  .search {
104
104
  position: sticky;
105
105
  top: 0;
106
+ z-index: 10;
106
107
  border-bottom: 1px solid var(--c-gutter);
107
108
  padding: 8px;
108
109
  background-color: var(--c-bg-elv-up);
@@ -60,7 +60,11 @@ const showHeader = computed(() => {
60
60
  return header
61
61
  }
62
62
 
63
- return unref(props.options.total) != null || !!unref(props.options.reset)
63
+ return (
64
+ unref(props.options.total) != null
65
+ || !!unref(props.options.reset)
66
+ || !!unref(props.options.menu)
67
+ )
64
68
  })
65
69
 
66
70
  const showFooter = computed(() => {
@@ -216,6 +220,7 @@ function getCell(key: string, index: number) {
216
220
  v-if="showHeader"
217
221
  :total="unref(options.total)"
218
222
  :reset="unref(options.reset)"
223
+ :menu="unref(options.menu)"
219
224
  :borderless="unref(options.borderless)"
220
225
  :on-reset="options.onReset"
221
226
  />
@@ -5,6 +5,7 @@ import STableCellAvatar from './STableCellAvatar.vue'
5
5
  import STableCellAvatars from './STableCellAvatars.vue'
6
6
  import STableCellDay from './STableCellDay.vue'
7
7
  import STableCellEmpty from './STableCellEmpty.vue'
8
+ import STableCellNumber from './STableCellNumber.vue'
8
9
  import STableCellPill from './STableCellPill.vue'
9
10
  import STableCellPills from './STableCellPills.vue'
10
11
  import STableCellState from './STableCellState.vue'
@@ -32,6 +33,7 @@ const computedCell = computed<TableCell | undefined>(() =>
32
33
  v-if="!computedCell || computedCell.type === 'text'"
33
34
  :value="value"
34
35
  :record="record"
36
+ :align="computedCell?.align"
35
37
  :icon="computedCell?.icon"
36
38
  :getter="computedCell?.value"
37
39
  :link="computedCell?.link"
@@ -39,10 +41,24 @@ const computedCell = computed<TableCell | undefined>(() =>
39
41
  :icon-color="computedCell?.iconColor"
40
42
  :on-click="computedCell?.onClick"
41
43
  />
44
+ <STableCellNumber
45
+ v-else-if="computedCell.type === 'number'"
46
+ :value="value"
47
+ :record="record"
48
+ :align="computedCell.align"
49
+ :icon="computedCell.icon"
50
+ :getter="computedCell.value"
51
+ :separator="computedCell.separator"
52
+ :link="computedCell.link"
53
+ :color="computedCell.color"
54
+ :icon-color="computedCell.iconColor"
55
+ :on-click="computedCell.onClick"
56
+ />
42
57
  <STableCellDay
43
58
  v-else-if="computedCell.type === 'day'"
44
59
  :value="value"
45
60
  :record="record"
61
+ :align="computedCell.align"
46
62
  :getter="computedCell.value"
47
63
  :format="computedCell.format"
48
64
  :color="computedCell.color"
@@ -5,6 +5,7 @@ import { type Day } from '../support/Day'
5
5
  const props = defineProps<{
6
6
  value?: Day | null
7
7
  record: any
8
+ align?: 'left' | 'center' | 'right'
8
9
  getter?: Day | null
9
10
  format?: string
10
11
  color?: 'neutral' | 'soft' | 'mute'
@@ -16,9 +17,9 @@ const _value = computed(() => {
16
17
  </script>
17
18
 
18
19
  <template>
19
- <div class="STableCellDay" :class="[color ?? 'neutral']">
20
+ <div class="STableCellDay" :class="[align ?? 'left', color ?? 'neutral']">
20
21
  <div v-if="_value" class="value">
21
- {{ _value.format(format ?? 'YYYY / MM / DD HH:mm:ss') }}
22
+ {{ _value.format(format ?? 'YYYY-MM-DD HH:mm:ss') }}
22
23
  </div>
23
24
  </div>
24
25
  </template>
@@ -31,14 +32,18 @@ const _value = computed(() => {
31
32
 
32
33
  .value {
33
34
  line-height: 24px;
34
- font-family: var(--font-family-number);
35
35
  font-size: var(--table-cell-font-size);
36
36
  font-weight: var(--table-cell-font-weight);
37
+ font-feature-settings: "tnum";
37
38
  white-space: nowrap;
38
39
  overflow: hidden;
39
40
  text-overflow: ellipsis;
40
41
  transition: color 0.25s;
41
42
 
43
+ .STableCellDay.left & { text-align: left; }
44
+ .STableCellDay.center & { text-align: center; }
45
+ .STableCellDay.right & { text-align: right; }
46
+
42
47
  .STableCellDay.neutral & { color: var(--c-text-1); }
43
48
  .STableCellDay.soft & { color: var(--c-text-2); }
44
49
  .STableCellDay.mute & { color: var(--c-text-3); }
@@ -0,0 +1,145 @@
1
+ <script setup lang="ts">
2
+ import { format } from 'sefirot/support/Num'
3
+ import { computed } from 'vue'
4
+ import { type TableCellValueColor } from '../composables/Table'
5
+ import SIcon from './SIcon.vue'
6
+ import SLink from './SLink.vue'
7
+
8
+ const props = defineProps<{
9
+ value?: any
10
+ record: any
11
+ align?: 'left' | 'center' | 'right'
12
+ icon?: any
13
+ getter?: number | null
14
+ separator?: boolean
15
+ color?: TableCellValueColor
16
+ iconColor?: TableCellValueColor
17
+ link?: string | null
18
+ onClick?(value: any, record: any): void
19
+ }>()
20
+
21
+ const _value = computed(() => props.getter ?? props.value)
22
+ const _color = computed(() => props.color ?? 'neutral')
23
+ const _iconColor = computed(() => props.iconColor ?? _color.value)
24
+
25
+ const classes = computed(() => [
26
+ props.align ?? 'left',
27
+ _color,
28
+ { link: props.link || props.onClick }
29
+ ])
30
+ </script>
31
+
32
+ <template>
33
+ <div class="STableCellNumber" :class="classes">
34
+ <SLink
35
+ v-if="_value"
36
+ class="container"
37
+ :href="link"
38
+ :role="onClick ? 'button' : null"
39
+ @click="() => onClick?.(value, record)"
40
+ >
41
+ <div v-if="icon" class="icon" :class="[_iconColor]">
42
+ <SIcon :icon="icon" class="svg" />
43
+ </div>
44
+ <div class="value" :class="[_color ?? 'neutral']">
45
+ {{ separator ? format(_value) : _value }}
46
+ </div>
47
+ </SLink>
48
+ </div>
49
+ </template>
50
+
51
+ <style scoped lang="postcss">
52
+ .STableCellNumber {
53
+ min-height: 40px;
54
+ }
55
+
56
+ .container {
57
+ display: flex;
58
+ gap: 4px;
59
+ padding: 8px 16px;
60
+
61
+ .STableCellNumber.left & { justify-content: flex-start; }
62
+ .STableCellNumber.center & { justify-content: center; }
63
+ .STableCellNumber.right & { justify-content: flex-end; }
64
+ }
65
+
66
+ .value {
67
+ line-height: 24px;
68
+ font-size: var(--table-cell-font-size);
69
+ font-weight: var(--table-cell-font-weight);
70
+ font-feature-settings: "tnum";
71
+ white-space: nowrap;
72
+ overflow: hidden;
73
+ text-overflow: ellipsis;
74
+ transition: color 0.25s;
75
+
76
+ &.neutral { color: var(--c-text-1); }
77
+ &.soft { color: var(--c-text-2); }
78
+ &.mute { color: var(--c-text-3); }
79
+ &.info { color: var(--c-info-text); }
80
+ &.success { color: var(--c-success-text); }
81
+ &.warning { color: var(--c-warning-text); }
82
+ &.danger { color: var(--c-danger-text); }
83
+
84
+ .STableCellNumber.link & { color: var(--c-info-text); }
85
+ .STableCellNumber.link:hover & { color: var(--c-info-text-dark); }
86
+
87
+ .STableCellNumber.link &.neutral { color: var(--c-text-1); }
88
+ .STableCellNumber.link:hover &.neutral { color: var(--c-info-text); }
89
+ .STableCellNumber.link &.soft { color: var(--c-text-2); }
90
+ .STableCellNumber.link:hover &.soft { color: var(--c-info-text); }
91
+ .STableCellNumber.link &.mute { color: var(--c-text-3); }
92
+ .STableCellNumber.link:hover &.mute { color: var(--c-text-3); }
93
+ .STableCellNumber.link &.info { color: var(--c-info-text); }
94
+ .STableCellNumber.link:hover &.info { color: var(--c-info-text-dark); }
95
+ .STableCellNumber.link &.success { color: var(--c-success-text); }
96
+ .STableCellNumber.link:hover &.success { color: var(--c-success-text-dark); }
97
+ .STableCellNumber.link &.warning { color: var(--c-warning-text); }
98
+ .STableCellNumber.link:hover &.warning { color: var(--c-warning-text-darker); }
99
+ .STableCellNumber.link &.danger { color: var(--c-danger-text); }
100
+ .STableCellNumber.link:hover &.danger { color: var(--c-danger-text-dark); }
101
+
102
+ .STableCell.summary & {
103
+ font-weight: var(--table-cell-summary-font-weight);
104
+ }
105
+ }
106
+
107
+ .icon {
108
+ display: flex;
109
+ justify-content: center;
110
+ align-items: center;
111
+ flex-shrink: 0;
112
+ margin-left: -3px;
113
+ width: 24px;
114
+ height: 24px;
115
+ transition: color 0.25s;
116
+
117
+ &.neutral { color: var(--c-text-1); }
118
+ &.soft { color: var(--c-text-2); }
119
+ &.mute { color: var(--c-text-3); }
120
+
121
+ .STableCellNumber.link & { color: var(--c-info-text); }
122
+ .STableCellNumber.link:hover & { color: var(--c-info-text-dark); }
123
+
124
+ .STableCellNumber.link &.neutral { color: var(--c-text-1); }
125
+ .STableCellNumber.link:hover &.neutral { color: var(--c-info-text); }
126
+ .STableCellNumber.link &.soft { color: var(--c-text-2); }
127
+ .STableCellNumber.link:hover &.soft { color: var(--c-info-text); }
128
+ .STableCellNumber.link &.mute { color: var(--c-text-3); }
129
+ .STableCellNumber.link:hover &.mute { color: var(--c-info-text); }
130
+ .STableCellNumber.link &.info { color: var(--c-info-text); }
131
+ .STableCellNumber.link:hover &.info { color: var(--c-info-text-dark); }
132
+ .STableCellNumber.link &.success { color: var(--c-success-text); }
133
+ .STableCellNumber.link:hover &.success { color: var(--c-success-text-dark); }
134
+ .STableCellNumber.link &.warning { color: var(--c-warning-text); }
135
+ .STableCellNumber.link:hover &.warning { color: var(--c-warning-text-dark); }
136
+ .STableCellNumber.link &.danger { color: var(--c-danger-text); }
137
+ .STableCellNumber.link:hover &.danger { color: var(--c-danger-text-dark); }
138
+ }
139
+
140
+ .svg {
141
+ width: 18px;
142
+ height: 18px;
143
+ fill: currentColor;
144
+ }
145
+ </style>
@@ -33,6 +33,7 @@ const items = computed(() => props.pills(props.value, props.record))
33
33
  .STableCellPills {
34
34
  display: flex;
35
35
  padding: 0 14px;
36
+ min-height: 40px;
36
37
 
37
38
  :deep(.STableCellPill) {
38
39
  padding-right: 2px;
@@ -15,6 +15,7 @@ export type Color =
15
15
  const props = defineProps<{
16
16
  value?: any
17
17
  record: any
18
+ align?: 'left' | 'center' | 'right'
18
19
  icon?: any
19
20
  getter?: string | null | ((value: any, record: any) => string | null)
20
21
  color?: Color | ((value: any, record: any) => Color)
@@ -42,12 +43,12 @@ const _color = computed(() => {
42
43
  const _iconColor = computed(() => {
43
44
  return typeof props.iconColor === 'function'
44
45
  ? props.iconColor(props.value, props.record)
45
- : props.iconColor ?? 'neutral'
46
+ : props.iconColor ?? _color.value
46
47
  })
47
48
  </script>
48
49
 
49
50
  <template>
50
- <div class="STableCellText" :class="[{ link: link || onClick }, _color]">
51
+ <div class="STableCellText" :class="[align ?? 'left', { link: link || onClick }, _color]">
51
52
  <SLink
52
53
  v-if="_value"
53
54
  class="container"
@@ -74,6 +75,10 @@ const _iconColor = computed(() => {
74
75
  display: flex;
75
76
  gap: 4px;
76
77
  padding: 8px 16px;
78
+
79
+ .STableCellText.left & { justify-content: flex-start; }
80
+ .STableCellText.center & { justify-content: center; }
81
+ .STableCellText.right & { justify-content: flex-end; }
77
82
  }
78
83
 
79
84
  .text {
@@ -88,28 +93,28 @@ const _iconColor = computed(() => {
88
93
  &.neutral { color: var(--c-text-1); }
89
94
  &.soft { color: var(--c-text-2); }
90
95
  &.mute { color: var(--c-text-3); }
91
- &.info { color: var(--c-info); }
92
- &.success { color: var(--c-success); }
93
- &.warning { color: var(--c-warning); }
94
- &.danger { color: var(--c-danger); }
96
+ &.info { color: var(--c-info-text); }
97
+ &.success { color: var(--c-success-text); }
98
+ &.warning { color: var(--c-warning-text); }
99
+ &.danger { color: var(--c-danger-text); }
95
100
 
96
- .STableCellText.link & { color: var(--c-info); }
97
- .STableCellText.link:hover & { color: var(--c-info-dark); }
101
+ .STableCellText.link & { color: var(--c-info-text); }
102
+ .STableCellText.link:hover & { color: var(--c-info-text-dark); }
98
103
 
99
104
  .STableCellText.link &.neutral { color: var(--c-text-1); }
100
- .STableCellText.link:hover &.neutral { color: var(--c-info); }
105
+ .STableCellText.link:hover &.neutral { color: var(--c-info-text); }
101
106
  .STableCellText.link &.soft { color: var(--c-text-2); }
102
- .STableCellText.link:hover &.soft { color: var(--c-info); }
107
+ .STableCellText.link:hover &.soft { color: var(--c-info-text); }
103
108
  .STableCellText.link &.mute { color: var(--c-text-3); }
104
109
  .STableCellText.link:hover &.mute { color: var(--c-text-3); }
105
- .STableCellText.link &.info { color: var(--c-info); }
106
- .STableCellText.link:hover &.info { color: var(--c-info-dark); }
107
- .STableCellText.link &.success { color: var(--c-success); }
108
- .STableCellText.link:hover &.success { color: var(--c-success-dark); }
109
- .STableCellText.link &.warning { color: var(--c-warning); }
110
- .STableCellText.link:hover &.warning { color: var(--c-warning-darker); }
111
- .STableCellText.link &.danger { color: var(--c-danger); }
112
- .STableCellText.link:hover &.danger { color: var(--c-danger-dark); }
110
+ .STableCellText.link &.info { color: var(--c-info-text); }
111
+ .STableCellText.link:hover &.info { color: var(--c-info-text-dark); }
112
+ .STableCellText.link &.success { color: var(--c-success-text); }
113
+ .STableCellText.link:hover &.success { color: var(--c-success-text-dark); }
114
+ .STableCellText.link &.warning { color: var(--c-warning-text); }
115
+ .STableCellText.link:hover &.warning { color: var(--c-warning-text-darker); }
116
+ .STableCellText.link &.danger { color: var(--c-danger-text); }
117
+ .STableCellText.link:hover &.danger { color: var(--c-danger-text-dark); }
113
118
 
114
119
  .STableCell.summary & {
115
120
  font-weight: var(--table-cell-summary-font-weight);
@@ -130,23 +135,23 @@ const _iconColor = computed(() => {
130
135
  &.soft { color: var(--c-text-2); }
131
136
  &.mute { color: var(--c-text-3); }
132
137
 
133
- .STableCellText.link & { color: var(--c-info); }
134
- .STableCellText.link:hover & { color: var(--c-info-dark); }
138
+ .STableCellText.link & { color: var(--c-info-text); }
139
+ .STableCellText.link:hover & { color: var(--c-info-text-dark); }
135
140
 
136
141
  .STableCellText.link &.neutral { color: var(--c-text-1); }
137
- .STableCellText.link:hover &.neutral { color: var(--c-info); }
142
+ .STableCellText.link:hover &.neutral { color: var(--c-info-text); }
138
143
  .STableCellText.link &.soft { color: var(--c-text-2); }
139
- .STableCellText.link:hover &.soft { color: var(--c-info); }
144
+ .STableCellText.link:hover &.soft { color: var(--c-info-text); }
140
145
  .STableCellText.link &.mute { color: var(--c-text-3); }
141
- .STableCellText.link:hover &.mute { color: var(--c-info); }
142
- .STableCellText.link &.info { color: var(--c-info); }
146
+ .STableCellText.link:hover &.mute { color: var(--c-info-text); }
147
+ .STableCellText.link &.info { color: var(--c-info-text); }
143
148
  .STableCellText.link:hover &.info { color: var(--c-info-dark); }
144
- .STableCellText.link &.success { color: var(--c-success); }
145
- .STableCellText.link:hover &.success { color: var(--c-success-dark); }
146
- .STableCellText.link &.warning { color: var(--c-warning); }
147
- .STableCellText.link:hover &.warning { color: var(--c-warning-dark); }
148
- .STableCellText.link &.danger { color: var(--c-danger); }
149
- .STableCellText.link:hover &.danger { color: var(--c-danger-dark); }
149
+ .STableCellText.link &.success { color: var(--c-success-text); }
150
+ .STableCellText.link:hover &.success { color: var(--c-success-text-dark); }
151
+ .STableCellText.link &.warning { color: var(--c-warning-text); }
152
+ .STableCellText.link:hover &.warning { color: var(--c-warning-text-dark); }
153
+ .STableCellText.link &.danger { color: var(--c-danger-text); }
154
+ .STableCellText.link:hover &.danger { color: var(--c-danger-text-dark); }
150
155
  }
151
156
 
152
157
  .svg {
@@ -1,10 +1,13 @@
1
1
  <script setup lang="ts">
2
+ import { type TableMenu } from '../composables/Table'
2
3
  import { format } from '../support/Num'
3
4
  import { isNullish } from '../support/Utils'
5
+ import STableHeaderMenu from './STableHeaderMenu.vue'
4
6
 
5
7
  defineProps<{
6
8
  total?: number | null
7
9
  reset?: boolean
10
+ menu?: TableMenu[] | TableMenu[][]
8
11
  borderless?: boolean
9
12
  onReset?(): void
10
13
  }>()
@@ -13,14 +16,18 @@ defineProps<{
13
16
  <template>
14
17
  <div class="STableHeader" :class="{ borderless }">
15
18
  <div class="container">
16
- <p v-if="!isNullish(total)" class="total">
17
- {{ format(total) }} {{ (total) > 1 ? 'records' : 'record' }}
18
- </p>
19
-
20
- <div v-if="reset" class="reset">
21
- <button class="button" @click="onReset">
22
- Reset filters
23
- </button>
19
+ <div class="stat">
20
+ <p v-if="!isNullish(total)" class="total">
21
+ {{ format(total) }} {{ (total) > 1 ? 'records' : 'record' }}
22
+ </p>
23
+ <div v-if="reset" class="reset">
24
+ <button class="button" @click="onReset">
25
+ Reset filters
26
+ </button>
27
+ </div>
28
+ </div>
29
+ <div v-if="menu && menu.length" class="menu">
30
+ <STableHeaderMenu :menu="menu" />
24
31
  </div>
25
32
  </div>
26
33
  </div>
@@ -36,13 +43,18 @@ defineProps<{
36
43
 
37
44
  .container {
38
45
  display: flex;
39
- padding: 0 16px;
40
46
  min-height: 48px;
41
47
  }
42
48
 
49
+ .stat {
50
+ display: flex;
51
+ flex-grow: 1;
52
+ padding: 0 16px;
53
+ }
54
+
43
55
  .total {
44
56
  margin: 0;
45
- padding: 13px 0 11px;
57
+ padding: 12px 0;
46
58
  line-height: 24px;
47
59
  font-size: 12px;
48
60
  font-weight: 500;
@@ -68,7 +80,7 @@ defineProps<{
68
80
  }
69
81
 
70
82
  .button {
71
- padding: 13px 0 11px;
83
+ padding: 12px 0;
72
84
  line-height: 24px;
73
85
  font-size: 12px;
74
86
  font-weight: 500;
@@ -79,4 +91,9 @@ defineProps<{
79
91
  color: var(--c-info-text-dark);
80
92
  }
81
93
  }
94
+
95
+ .menu {
96
+ flex-shrink: 0;
97
+ padding-right: 8px;
98
+ }
82
99
  </style>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { type TableMenu } from '../composables/Table'
4
+ import { isArray } from '../support/Utils'
5
+ import STableHeaderMenuItem from './STableHeaderMenuItem.vue'
6
+
7
+ const props = defineProps<{
8
+ menu: TableMenu[] | TableMenu[][]
9
+ }>()
10
+
11
+ const normalizedMenu = computed(() => {
12
+ return isArray(props.menu[0])
13
+ ? props.menu as TableMenu[][]
14
+ : [props.menu] as TableMenu[][]
15
+ })
16
+ </script>
17
+
18
+ <template>
19
+ <div class="STableHeaderMenu">
20
+ <div v-for="items, index in normalizedMenu" :key="index" class="group">
21
+ <div v-if="index > 0" class="divider" />
22
+ <div v-for="item in items" :key="item.label" class="item">
23
+ <STableHeaderMenuItem
24
+ :label="item.label"
25
+ :state="item.state"
26
+ :dropdown="item.dropdown"
27
+ />
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </template>
32
+
33
+ <style scoped lang="postcss">
34
+ .STableHeaderMenu {
35
+ display: flex;
36
+ align-items: center;
37
+ height: 48px;
38
+ }
39
+
40
+ .group {
41
+ display: flex;
42
+ align-items: center;
43
+ height: 48px;
44
+ }
45
+
46
+ .divider {
47
+ margin: 0 8px;
48
+ width: 1px;
49
+ height: 16px;
50
+ background-color: var(--c-divider-2);
51
+ }
52
+ </style>
@@ -0,0 +1,109 @@
1
+ <script setup lang="ts">
2
+ import IconCaretDown from '@iconify-icons/ph/caret-down-bold'
3
+ import { type DropdownSection } from '../composables/Dropdown'
4
+ import { useFlyout } from '../composables/Flyout'
5
+ import SDropdown from './SDropdown.vue'
6
+ import SIcon from './SIcon.vue'
7
+
8
+ defineProps<{
9
+ label: string
10
+ state?: 'inactive' | 'active' | 'indicate'
11
+ dropdown: DropdownSection[]
12
+ }>()
13
+
14
+ const { container, isOpen, toggle } = useFlyout()
15
+ </script>
16
+
17
+ <template>
18
+ <div class="STableHeaderMenuItem" ref="container">
19
+ <button class="button" :class="[state]" @click="toggle">
20
+ <span class="label">{{ label }}</span>
21
+ <span v-if="state !== 'indicate'" class="caret">
22
+ <SIcon class="caret-svg" :icon="IconCaretDown" />
23
+ </span>
24
+ <span v-else class="indicator">
25
+ <span class="indicator-dot" />
26
+ </span>
27
+ </button>
28
+ <Transition name="fade">
29
+ <div v-if="isOpen" class="dialog">
30
+ <SDropdown :sections="dropdown" />
31
+ </div>
32
+ </Transition>
33
+ </div>
34
+ </template>
35
+
36
+ <style scoped lang="postcss">
37
+ .STableHeaderMenuItem {
38
+ position: relative;
39
+ }
40
+
41
+ .button {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 6px;
45
+ border-radius: 6px;
46
+ padding: 6px 7px 6px 9px;
47
+ transition: background-color 0.25s;
48
+
49
+ &:hover {
50
+ background-color: var(--c-mute);
51
+ }
52
+ }
53
+
54
+ .label {
55
+ font-size: 12px;
56
+ color: var(--c-text-2);
57
+ transition: color 0.25s;
58
+
59
+ .button:hover & {
60
+ color: var(--c-text-1);
61
+ }
62
+
63
+ .button.active &,
64
+ .button.indicate & {
65
+ color: var(--c-text-1);
66
+ }
67
+ }
68
+
69
+ .caret-svg {
70
+ width: 12px;
71
+ height: 12px;
72
+ color: var(--c-text-2);
73
+ transition: color 0.25s;
74
+
75
+ .button:hover & {
76
+ color: var(--c-text-1);
77
+ }
78
+ }
79
+
80
+ .indicator {
81
+ display: flex;
82
+ justify-content: center;
83
+ align-items: center;
84
+ width: 12px;
85
+ height: 12px;
86
+ }
87
+
88
+ .indicator-dot {
89
+ display: block;
90
+ border-radius: 6px;
91
+ width: 6px;
92
+ height: 6px;
93
+ background-color: var(--c-info-text);
94
+ }
95
+
96
+ .dialog {
97
+ position: absolute;
98
+ top: 32px;
99
+ right: 0;
100
+ z-index: var(--z-index-dropdown);
101
+ transition: opacity 0.25s, transform 0.25s;
102
+ }
103
+
104
+ .dialog.fade-enter-from,
105
+ .dialog.fade-leave-to {
106
+ opacity: 0;
107
+ transform: translateY(-4px);
108
+ }
109
+ </style>
@@ -1,7 +1,6 @@
1
1
  import { watchOnce } from '@vueuse/core'
2
2
  import cloneDeep from 'lodash-es/cloneDeep'
3
- import { type WatchSource } from 'vue'
4
- import { reactive } from 'vue'
3
+ import { type WatchSource, reactive } from 'vue'
5
4
  import { isNullish, isObject } from '../support/Utils'
6
5
 
7
6
  export interface Data<T extends Record<string, any>> {
@@ -1,5 +1,4 @@
1
- import { type MaybeRef } from '@vueuse/core'
2
- import { useElementBounding, useWindowSize } from '@vueuse/core'
1
+ import { type MaybeRef, useElementBounding, useWindowSize } from '@vueuse/core'
3
2
  import { type Ref } from 'vue'
4
3
  import { ref, unref } from 'vue'
5
4
 
@@ -1,5 +1,4 @@
1
- import { type Ref } from 'vue'
2
- import { ref, watch } from 'vue'
1
+ import { type Ref, ref, watch } from 'vue'
3
2
 
4
3
  export function useFlyout(container?: Ref<any>) {
5
4
  const el = container ?? ref<any>(null)
@@ -1,5 +1,4 @@
1
- import { type Ref } from 'vue'
2
- import { onMounted, onUnmounted, ref, watchEffect } from 'vue'
1
+ import { type Ref, onMounted, onUnmounted, ref, watchEffect } from 'vue'
3
2
 
4
3
  export interface Grid {
5
4
  container: Ref<HTMLElement | null>
@@ -1,9 +1,7 @@
1
1
  import MarkdownIt from 'markdown-it'
2
- import { type Ref } from 'vue'
3
- import { onUnmounted } from 'vue'
2
+ import { type Ref, onUnmounted } from 'vue'
4
3
  import { useRouter } from 'vue-router'
5
- import { type LinkAttrs } from './markdown/LinkPlugin'
6
- import { isCallbackUrl, isExternalUrl, linkPlugin } from './markdown/LinkPlugin'
4
+ import { type LinkAttrs, isCallbackUrl, isExternalUrl, linkPlugin } from './markdown/LinkPlugin'
7
5
 
8
6
  export type UseMarkdown = (source: string, inline: boolean) => string
9
7
 
@@ -10,6 +10,7 @@ export interface Table<
10
10
  > {
11
11
  orders: MaybeRef<O[]>
12
12
  columns: MaybeRef<TableColumns<O, R, SR>>
13
+ menu?: MaybeRef<TableMenu[] | TableMenu[][]>
13
14
  records?: MaybeRef<R[] | null | undefined>
14
15
  header?: MaybeRef<boolean | undefined>
15
16
  footer?: MaybeRef<boolean | undefined>
@@ -48,6 +49,7 @@ export type TableColumnCellFn<V, R> = (value: V, record: R) => TableCell
48
49
 
49
50
  export type TableCell =
50
51
  | TableCellText
52
+ | TableCellNumber
51
53
  | TableCellDay
52
54
  | TableCellPill
53
55
  | TableCellPills
@@ -59,6 +61,7 @@ export type TableCell =
59
61
 
60
62
  export type TableCellType =
61
63
  | 'text'
64
+ | 'number'
62
65
  | 'day'
63
66
  | 'pill'
64
67
  | 'pills'
@@ -74,15 +77,28 @@ export interface TableCellBase {
74
77
 
75
78
  export interface TableCellText extends TableCellBase {
76
79
  type: 'text'
80
+ align?: 'left' | 'center' | 'right'
77
81
  icon?: any
78
82
  value?: string | null | ((value: any, record: any) => string | null)
79
83
  link?(value: any, record: any): string
80
- color?: TableCellTextColor | ((value: any, record: any) => TableCellTextColor)
81
- iconColor?: TableCellTextColor | ((value: any, record: any) => TableCellTextColor)
84
+ color?: TableCellValueColor | ((value: any, record: any) => TableCellValueColor)
85
+ iconColor?: TableCellValueColor | ((value: any, record: any) => TableCellValueColor)
82
86
  onClick?(value: any, record: any): void
83
87
  }
84
88
 
85
- export type TableCellTextColor =
89
+ export interface TableCellNumber extends TableCellBase {
90
+ type: 'number'
91
+ align?: 'left' | 'center' | 'right'
92
+ icon?: any
93
+ value?: number | null
94
+ separator?: boolean
95
+ link?: string | null
96
+ color?: TableCellValueColor
97
+ iconColor?: TableCellValueColor
98
+ onClick?(value: any, record: any): void
99
+ }
100
+
101
+ export type TableCellValueColor =
86
102
  | 'neutral'
87
103
  | 'soft'
88
104
  | 'mute'
@@ -93,6 +109,7 @@ export type TableCellTextColor =
93
109
 
94
110
  export interface TableCellDay extends TableCellBase {
95
111
  type: 'day'
112
+ align?: 'left' | 'center' | 'right'
96
113
  value?: Day | null
97
114
  format?: string
98
115
  color?: 'neutral' | 'soft' | 'mute'
@@ -152,6 +169,12 @@ export interface TableCellState extends TableCellBase {
152
169
  mode?: 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
153
170
  }
154
171
 
172
+ export interface TableMenu {
173
+ label: string
174
+ state?: 'inactive' | 'active' | 'indicate'
175
+ dropdown: DropdownSection[]
176
+ }
177
+
155
178
  export function useTable<
156
179
  O extends string,
157
180
  R extends Record<string, any>,
@@ -1,7 +1,5 @@
1
- import { type MaybeRefOrGetter } from '@vueuse/core'
2
- import { resolveUnref } from '@vueuse/core'
3
- import { type ComputedRef } from 'vue'
4
- import { computed } from 'vue'
1
+ import { type MaybeRefOrGetter, resolveUnref } from '@vueuse/core'
2
+ import { type ComputedRef, computed } from 'vue'
5
3
 
6
4
  export type WhenCondition<T> = MaybeRefOrGetter<T>
7
5
 
@@ -1,9 +1,7 @@
1
1
  import {
2
2
  type GlobalConfig,
3
3
  type Validation,
4
- type ValidationArgs
5
- } from '@vuelidate/core'
6
- import {
4
+ type ValidationArgs,
7
5
  useVuelidate
8
6
  } from '@vuelidate/core'
9
7
  import { type Ref, type ToRefs } from 'vue'
@@ -1,5 +1,4 @@
1
- import { type ConfigType, type Dayjs } from 'dayjs'
2
- import dayjs from 'dayjs'
1
+ import dayjs, { type ConfigType, type Dayjs } from 'dayjs'
3
2
  import PluginRelativeTime from 'dayjs/plugin/relativeTime'
4
3
  import PluginTimezone from 'dayjs/plugin/timezone'
5
4
  import PluginUtc from 'dayjs/plugin/utc'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "2.36.0",
3
+ "version": "2.37.0",
4
4
  "packageManager": "pnpm@8.5.0",
5
5
  "description": "Vue Components for Global Brain Design System.",
6
6
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",