@globalbrain/sefirot 2.34.1 → 2.36.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 (34) hide show
  1. package/lib/components/SButton.vue +6 -5
  2. package/lib/components/SCard.vue +70 -0
  3. package/lib/components/SCardBlock.vue +33 -0
  4. package/lib/components/SCardFooter.vue +14 -0
  5. package/lib/components/SCardFooterAction.vue +31 -0
  6. package/lib/components/SCardFooterActions.vue +15 -0
  7. package/lib/components/SCardHeader.vue +15 -0
  8. package/lib/components/SCardHeaderAction.vue +28 -0
  9. package/lib/components/SCardHeaderActionClose.vue +27 -0
  10. package/lib/components/SCardHeaderActionCollapse.vue +47 -0
  11. package/lib/components/SCardHeaderActions.vue +13 -0
  12. package/lib/components/SCardHeaderTitle.vue +15 -0
  13. package/lib/components/SDropdown.vue +6 -11
  14. package/lib/components/SDropdownSection.vue +0 -25
  15. package/lib/components/SDropdownSectionActions.vue +3 -2
  16. package/lib/components/SDropdownSectionFilter.vue +60 -26
  17. package/lib/components/SDropdownSectionFilterItemAvatar.vue +1 -1
  18. package/lib/components/SDropdownSectionFilterItemText.vue +1 -2
  19. package/lib/components/SDropdownSectionMenu.vue +3 -2
  20. package/lib/components/SLink.vue +16 -3
  21. package/lib/components/SModal.vue +2 -2
  22. package/lib/components/STableCell.vue +1 -0
  23. package/lib/components/STableCellAvatar.vue +8 -2
  24. package/lib/components/STableColumn.vue +3 -3
  25. package/lib/components/STableHeader.vue +2 -0
  26. package/lib/composables/Card.ts +45 -0
  27. package/lib/composables/Flyout.ts +1 -1
  28. package/lib/composables/Form.ts +4 -4
  29. package/lib/composables/Table.ts +1 -0
  30. package/lib/composables/Tooltip.ts +9 -10
  31. package/lib/mixins/Card.ts +30 -0
  32. package/lib/styles/variables.css +214 -86
  33. package/lib/support/Num.ts +7 -0
  34. package/package.json +1 -1
@@ -86,12 +86,12 @@ function handleClick(): void {
86
86
  <template>
87
87
  <SFragment
88
88
  :is="hasTooltip && STooltip"
89
- :tag="tooltip?.tag"
90
- :text="unref(tooltip?.text)"
91
- :position="tooltip?.position"
89
+ :tag="props.tooltip?.tag"
90
+ :text="unref(props.tooltip?.text)"
91
+ :position="props.tooltip?.position"
92
92
  display="inline-block"
93
- :trigger="tooltip?.trigger ?? 'both'"
94
- :timeout="tooltip?.timeout"
93
+ :trigger="props.tooltip?.trigger ?? 'both'"
94
+ :timeout="props.tooltip?.timeout"
95
95
  :tabindex="-1"
96
96
  >
97
97
  <template v-if="$slots['tooltip-text']" #text><slot name="tooltip-text" /></template>
@@ -125,6 +125,7 @@ function handleClick(): void {
125
125
  .SButton {
126
126
  position: relative;
127
127
  display: inline-flex;
128
+ justify-content: center;
128
129
  align-items: center;
129
130
  letter-spacing: 0;
130
131
  text-align: center;
@@ -0,0 +1,70 @@
1
+ <script setup lang="ts">
2
+ import { provideCardState } from '../composables/Card'
3
+
4
+ export type Size = 'small' | 'medium'
5
+
6
+ defineProps<{
7
+ size?: Size
8
+ }>()
9
+
10
+ const { isCollapsed } = provideCardState()
11
+ </script>
12
+
13
+ <template>
14
+ <div class="SCard" :class="[size, { collapsed: isCollapsed }]">
15
+ <slot />
16
+ </div>
17
+ </template>
18
+
19
+ <style scoped lang="postcss">
20
+ .SCard {
21
+ display: grid;
22
+ gap: 1px;
23
+ border: 1px solid var(--c-divider-2);
24
+ border-radius: 6px;
25
+ background-color: var(--c-gutter);
26
+ }
27
+
28
+ .SCard.collapsed {
29
+ height: 48px;
30
+ overflow: hidden;
31
+ }
32
+
33
+ .SModal > .SCard {
34
+ margin: 12px 12px 128px;
35
+ box-shadow: var(--shadow-depth-3);
36
+ transition: opacity 0.25s, transform 0.25s;
37
+
38
+ @media (min-width: 512px) {
39
+ margin: 24px 24px 128px;
40
+ }
41
+
42
+ @media (min-width: 768px) {
43
+ margin: 48px 48px 128px;
44
+ }
45
+
46
+ &.small {
47
+ @media (min-width: 560px) {
48
+ margin: 24px auto 128px;
49
+ max-width: 512px;
50
+ }
51
+
52
+ @media (min-width: 768px) {
53
+ margin: 48px auto 128px;
54
+ }
55
+ }
56
+
57
+ &.medium {
58
+ @media (min-width: 864px) {
59
+ margin: 48px auto 128px;
60
+ max-width: 768px;
61
+ }
62
+ }
63
+ }
64
+
65
+ .SModal.fade-enter-from > .SCard,
66
+ .SModal.fade-leave-to > .SCard {
67
+ opacity: 0;
68
+ transform: translateY(8px);
69
+ }
70
+ </style>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ export type Space = 'compact' | 'wide'
3
+
4
+ defineProps<{
5
+ space?: Space
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <div class="SCardBlock" :class="[space]">
11
+ <slot />
12
+ </div>
13
+ </template>
14
+
15
+ <style scoped lang="postcss">
16
+ .SCardBlock {
17
+ padding: var(--card-padding, 0);
18
+ background-color: var(--c-bg-elv-3);
19
+
20
+ &.compact { padding: 24px; }
21
+ &.wide { padding: 48px; }
22
+ }
23
+
24
+ .SCard > .SCardBlock:first-child {
25
+ border-top-left-radius: 5px;
26
+ border-top-right-radius: 5px;
27
+ }
28
+
29
+ .SCard > .SCardBlock:last-child {
30
+ border-bottom-right-radius: 5px;
31
+ border-bottom-left-radius: 5px;
32
+ }
33
+ </style>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <div class="SCardFooter">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SCardFooter {
9
+ display: flex;
10
+ align-items: center;
11
+ border-radius: 0 0 5px 5px;
12
+ background-color: var(--c-bg-elv-3);
13
+ }
14
+ </style>
@@ -0,0 +1,31 @@
1
+ <script setup lang="ts">
2
+ import SButton, { type Mode, type Tooltip } from './SButton.vue'
3
+
4
+ defineProps<{
5
+ mode?: Mode
6
+ label?: string
7
+ labelMode?: Mode
8
+ loading?: boolean
9
+ disabled?: boolean
10
+ tooltip?: Tooltip
11
+ }>()
12
+
13
+ defineEmits<{
14
+ (e: 'click'): void
15
+ }>()
16
+ </script>
17
+
18
+ <template>
19
+ <div class="SCardFooterAction">
20
+ <SButton
21
+ size="medium"
22
+ :mode="mode"
23
+ :label="label"
24
+ :label-mode="labelMode"
25
+ :loading="loading"
26
+ :disabled="disabled"
27
+ :tooltip="tooltip"
28
+ @click="$emit('click')"
29
+ />
30
+ </div>
31
+ </template>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="SCardFooterActions">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SCardFooterActions {
9
+ display: flex;
10
+ justify-content: flex-end;
11
+ flex-grow: 1;
12
+ gap: 12px;
13
+ padding: 12px 24px;
14
+ }
15
+ </style>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="SCardHeader">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SCardHeader {
9
+ display: flex;
10
+ align-items: center;
11
+ border-radius: 5px 5px 0 0;
12
+ height: 48px;
13
+ background-color: var(--c-bg-soft);
14
+ }
15
+ </style>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import { type IconifyIcon } from '@iconify/vue/dist/offline'
3
+ import SButton, { type Tooltip } from './SButton.vue'
4
+
5
+ defineProps<{
6
+ icon: IconifyIcon
7
+ disabled?: boolean
8
+ tooltip?: Tooltip
9
+ }>()
10
+
11
+ defineEmits<{
12
+ (e: 'click'): void
13
+ }>()
14
+ </script>
15
+
16
+ <template>
17
+ <div class="SCardHeaderAction">
18
+ <SButton
19
+ type="text"
20
+ mode="mute"
21
+ size="small"
22
+ :icon="icon"
23
+ :disabled="disabled"
24
+ :tooltip="tooltip"
25
+ @click="$emit('click')"
26
+ />
27
+ </div>
28
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import IconX from '@iconify-icons/ph/x-bold'
3
+ import SButton, { type Tooltip } from './SButton.vue'
4
+
5
+ defineProps<{
6
+ disabled?: boolean
7
+ tooltip?: Tooltip
8
+ }>()
9
+
10
+ defineEmits<{
11
+ (e: 'click'): void
12
+ }>()
13
+ </script>
14
+
15
+ <template>
16
+ <div class="SCardHeaderActionClose">
17
+ <SButton
18
+ type="text"
19
+ mode="mute"
20
+ size="small"
21
+ :icon="IconX"
22
+ :disabled="disabled"
23
+ :tooltip="tooltip"
24
+ @click="$emit('click')"
25
+ />
26
+ </div>
27
+ </template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ import IconArrowsInLineVertical from '@iconify-icons/ph/arrows-in-line-vertical-bold'
3
+ import IconArrowsOutLineVertical from '@iconify-icons/ph/arrows-out-line-vertical-bold'
4
+ import { computed, shallowRef } from 'vue'
5
+ import { useCardState } from '../composables/Card'
6
+ import SButton, { type Tooltip } from './SButton.vue'
7
+
8
+ const props = defineProps<{
9
+ collapsed?: boolean
10
+ disabled?: boolean
11
+ tooltip?: Tooltip
12
+ }>()
13
+
14
+ defineEmits<{
15
+ (e: 'click'): void
16
+ }>()
17
+
18
+ const { isCollapsed, setCollapse, toggleCollapse } = useCardState()
19
+
20
+ setCollapse(props.collapsed)
21
+
22
+ const el = shallowRef<HTMLElement | null>(null)
23
+
24
+ const icon = computed(() => {
25
+ return isCollapsed.value
26
+ ? IconArrowsOutLineVertical
27
+ : IconArrowsInLineVertical
28
+ })
29
+ </script>
30
+
31
+ <template>
32
+ <div
33
+ class="SCardHeaderActionCollapse"
34
+ :class="{ collapsed: isCollapsed }"
35
+ ref="el"
36
+ >
37
+ <SButton
38
+ type="text"
39
+ mode="mute"
40
+ size="small"
41
+ :icon="icon"
42
+ :disabled="disabled"
43
+ :tooltip="tooltip"
44
+ @click="toggleCollapse"
45
+ />
46
+ </div>
47
+ </template>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div class="SCardHeaderActions">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SCardHeaderActions {
9
+ display: flex;
10
+ justify-content: flex-end;
11
+ padding-right: 8px;
12
+ }
13
+ </style>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <p class="SCardHeaderTitle">
3
+ <slot />
4
+ </p>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SCardHeaderTitle {
9
+ flex-grow: 1;
10
+ padding-left: 24px;
11
+ line-height: 32px;
12
+ font-size: 14px;
13
+ font-weight: 600;
14
+ }
15
+ </style>
@@ -19,25 +19,20 @@ defineProps<{
19
19
 
20
20
  <style scoped lang="postcss">
21
21
  .SDropdown {
22
- border: 1px solid var(--c-divider-light);
23
- border-radius: 12px;
22
+ border: 1px solid var(--c-divider-2);
23
+ border-radius: 6px;
24
24
  min-width: 256px;
25
25
  max-height: 384px;
26
- background-color: var(--c-bg);
27
26
  overflow-y: auto;
28
27
 
29
28
  &::-webkit-scrollbar {
30
29
  display: none;
31
30
  }
32
-
33
- .dark & {
34
- background-color: var(--c-bg-mute);
35
- }
36
31
  }
37
32
 
38
- .section {
39
- & + & {
40
- border-top: 1px solid var(--c-divider-light);
41
- }
33
+ .container {
34
+ display: grid;
35
+ gap: 1px;
36
+ background-color: var(--c-gutter);
42
37
  }
43
38
  </style>
@@ -31,28 +31,3 @@ defineProps<{
31
31
  :comp="section.component"
32
32
  />
33
33
  </template>
34
-
35
- <style scoped lang="postcss">
36
- .SDropdown {
37
- border: 1px solid var(--c-divider-light);
38
- border-radius: 12px;
39
- min-width: 256px;
40
- max-height: 384px;
41
- background-color: var(--c-bg);
42
- overflow-y: auto;
43
-
44
- &::-webkit-scrollbar {
45
- display: none;
46
- }
47
-
48
- .dark & {
49
- background-color: var(--c-bg-mute);
50
- }
51
- }
52
-
53
- .section {
54
- & + & {
55
- border-top: 1px solid var(--c-divider-light);
56
- }
57
- }
58
- </style>
@@ -20,7 +20,9 @@ defineProps<{
20
20
  .SDropdownSectionActions {
21
21
  display: flex;
22
22
  justify-content: flex-end;
23
+ gap: 4px;
23
24
  padding: 8px;
25
+ background-color: var(--c-bg-elv-3);
24
26
  }
25
27
 
26
28
  .button {
@@ -30,8 +32,7 @@ defineProps<{
30
32
  width: 100%;
31
33
  text-align: left;
32
34
  line-height: 32px;
33
- font-size: 12px;
34
- font-weight: 500;
35
+ font-size: 14px;
35
36
  transition: color 0.25s, background-color 0.25s;
36
37
 
37
38
  &.neutral { color: var(--button-text-neutral-text-color); }
@@ -74,11 +74,14 @@ function handleClick(option: DropdownSectionFilterOption, value: string | number
74
74
  @keyup.down.prevent="focusNext"
75
75
  @click="handleClick(option, option.value)"
76
76
  >
77
- <span class="checkbox">
77
+ <span v-if="isArray(unref(selected))" class="checkbox">
78
78
  <span class="checkbox-box">
79
79
  <SIcon :icon="IconCheck" class="checkbox-icon" />
80
80
  </span>
81
81
  </span>
82
+ <span v-else class="radio">
83
+ <span class="radio-dot" />
84
+ </span>
82
85
  <span class="option-item">
83
86
  <SDropdownSectionFilterItem :option="option" />
84
87
  </span>
@@ -93,33 +96,34 @@ function handleClick(option: DropdownSectionFilterOption, value: string | number
93
96
  </template>
94
97
 
95
98
  <style scoped lang="postcss">
99
+ .SDropdownSectionFilter {
100
+ background-color: var(--c-bg-elv-3);
101
+ }
102
+
96
103
  .search {
97
104
  position: sticky;
98
105
  top: 0;
99
- border-bottom: 1px solid var(--c-divider-light);
106
+ border-bottom: 1px solid var(--c-gutter);
100
107
  padding: 8px;
101
108
  background-color: var(--c-bg-elv-up);
102
109
  }
103
110
 
104
111
  .input {
105
- border: 1px solid var(--c-divider);
112
+ border: 1px solid var(--c-divider-1);
106
113
  border-radius: 6px;
107
114
  padding: 0 8px;
108
115
  width: 100%;
109
116
  font-size: 14px;
110
117
  line-height: 32px;
111
- background-color: var(--c-bg);
118
+ background-color: var(--input-bg-color);
112
119
  transition: border-color 0.25s;
113
120
 
114
121
  &::placeholder {
115
- color: var(--c-text-3);
122
+ color: var(--input-placeholder-color);
116
123
  }
117
124
 
118
- &:hover { border-color: var(--c-black); }
119
- &:focus { border-color: var(--c-info); }
120
-
121
- .dark &:hover { border-color: var(--c-gray); }
122
- .dark &:focus { border-color: var(--c-info); }
125
+ &:hover { border-color: var(--input-hover-border-color); }
126
+ &:focus { border-color: var(--input-focus-border-color); }
123
127
  }
124
128
 
125
129
  .list {
@@ -136,33 +140,29 @@ function handleClick(option: DropdownSectionFilterOption, value: string | number
136
140
 
137
141
  &:hover,
138
142
  &:focus {
139
- background-color: var(--c-bg-mute);
140
- }
141
-
142
- .dark &:hover,
143
- .dark &:focus {
144
- background-color: var(--c-bg);
143
+ background-color: var(--c-mute);
145
144
  }
146
145
  }
147
146
 
148
147
  .checkbox {
149
148
  display: block;
150
149
  padding-top: 8px;
150
+ padding-bottom: 8px;
151
151
  }
152
152
 
153
153
  .checkbox-box {
154
154
  display: flex;
155
155
  justify-content: center;
156
156
  align-items: center;
157
- border: 1px solid var(--c-divider);
157
+ border: 1px solid var(--c-divider-1);
158
158
  border-radius: 4px;
159
159
  width: 16px;
160
160
  height: 16px;
161
- background-color: var(--c-bg);
161
+ background-color: var(--input-bg-color);
162
162
  transition: border-color 0.1s, background-color 0.1s;
163
163
 
164
164
  .button.active & {
165
- border-color: var(--c-info);
165
+ border-color: var(--c-info-text);
166
166
  background-color: var(--c-info);
167
167
  }
168
168
  }
@@ -180,19 +180,53 @@ function handleClick(option: DropdownSectionFilterOption, value: string | number
180
180
  }
181
181
  }
182
182
 
183
+ .radio {
184
+ position: relative;
185
+ flex-shrink: 0;
186
+ border: 1px solid var(--c-divider-1);
187
+ border-radius: 50%;
188
+ margin-top: 8px;
189
+ margin-bottom: 8px;
190
+ width: 16px;
191
+ height: 16px;
192
+ background-color: var(--input-bg-color);
193
+ transition: border-color 0.25s;
194
+
195
+ .button.active & {
196
+ border-color: var(--c-info-light);
197
+ }
198
+ }
199
+
200
+ .radio-dot {
201
+ position: absolute;
202
+ top: 0;
203
+ right: 0;
204
+ bottom: 0;
205
+ left: 0;
206
+ display: flex;
207
+ justify-content: center;
208
+ align-items: center;
209
+ border-radius: 50%;
210
+ width: 100%;
211
+ background-color: var(--c-info-light);
212
+ opacity: 0;
213
+ transform: scale(0);
214
+ transition: opacity 0.25s, transform 0.1s;
215
+
216
+ .button.active & {
217
+ opacity: 1;
218
+ transform: scale(0.6);
219
+ }
220
+ }
221
+
183
222
  .option-item {
184
- padding-left: 8px;
223
+ padding-left: 12px;
185
224
  width: 100%;
186
225
  }
187
226
 
188
227
  .empty {
189
- padding: 16px;
228
+ padding: 14px 16px;
190
229
  font-size: 12px;
191
- font-weight: 500;
192
230
  color: var(--c-text-2);
193
-
194
- .search + & {
195
- border-top: 1px solid var(--c-divider-light);
196
- }
197
231
  }
198
232
  </style>
@@ -31,7 +31,7 @@ defineProps<{
31
31
  .name {
32
32
  display: inline-block;
33
33
  padding-left: 8px;
34
- font-size: 12px;
34
+ font-size: 14px;
35
35
  font-weight: 400;
36
36
  white-space: nowrap;
37
37
  overflow: hidden;
@@ -15,13 +15,12 @@ defineProps<{
15
15
  display: inline-block;
16
16
  padding: 6px 0;
17
17
  line-height: 20px;
18
- font-size: 12px;
19
18
  }
20
19
 
21
20
  .text {
22
21
  display: inline-block;
23
22
  line-height: 20px;
24
- font-size: 12px;
23
+ font-size: 14px;
25
24
  font-weight: 400;
26
25
  }
27
26
  </style>
@@ -19,6 +19,7 @@ defineProps<{
19
19
  <style scoped lang="postcss">
20
20
  .SDropdownSectionMenu {
21
21
  padding: 8px;
22
+ background-color: var(--c-bg-elv-3);
22
23
  }
23
24
 
24
25
  .button {
@@ -28,12 +29,12 @@ defineProps<{
28
29
  width: 100%;
29
30
  text-align: left;
30
31
  line-height: 32px;
31
- font-size: 12px;
32
+ font-size: 14px;
32
33
  font-weight: 400;
33
34
  transition: color 0.25s, background-color 0.25s;
34
35
 
35
36
  &:hover {
36
- background-color: var(--c-bg-elv-down);
37
+ background-color: var(--c-mute);
37
38
  }
38
39
  }
39
40
  </style>
@@ -1,13 +1,26 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
 
4
- const props = defineProps({
5
- href: { type: String, default: null }
4
+ const props = withDefaults(defineProps<{
5
+ href?: string | null
6
+ external?: boolean | null
7
+ }>(), {
8
+ external: null
6
9
  })
7
10
 
8
11
  const OUTBOUND_REGEX = /^[a-z]+:/i
9
12
 
10
- const isExternal = computed(() => OUTBOUND_REGEX.test(props.href))
13
+ const isExternal = computed(() => {
14
+ if (!props.href) {
15
+ return false
16
+ }
17
+
18
+ if (props.external !== null) {
19
+ return props.external
20
+ }
21
+
22
+ return OUTBOUND_REGEX.test(props.href)
23
+ })
11
24
 
12
25
  const component = computed(() => {
13
26
  if (!props.href) {
@@ -29,11 +29,11 @@ function onClick(e: MouseEvent) {
29
29
 
30
30
  <template>
31
31
  <Teleport to="#sefirot-modals">
32
- <transition name="fade">
32
+ <Transition name="fade">
33
33
  <div v-if="open" class="SModal" ref="el" @mousedown="onClick">
34
34
  <slot />
35
35
  </div>
36
- </transition>
36
+ </Transition>
37
37
  </Teleport>
38
38
  </template>
39
39
 
@@ -73,6 +73,7 @@ const computedCell = computed<TableCell | undefined>(() =>
73
73
  :name="computedCell.name"
74
74
  :link="computedCell.link"
75
75
  :color="computedCell.color"
76
+ :on-click="computedCell.onClick"
76
77
  />
77
78
  <STableCellAvatars
78
79
  v-else-if="computedCell.type === 'avatars'"
@@ -10,6 +10,7 @@ const props = defineProps<{
10
10
  name?: string | null | ((value: any, record: any) => string | null | undefined)
11
11
  link?: string | null | ((value: any, record: any) => string | null | undefined)
12
12
  color?: 'neutral' | 'soft' | 'mute'
13
+ onClick?(value: any, record: any): void
13
14
  }>()
14
15
 
15
16
  const _image = computed(() => resolve(props.image))
@@ -30,8 +31,13 @@ function resolve(
30
31
  </script>
31
32
 
32
33
  <template>
33
- <div class="STableCellAvatar" :class="[{ link }, color]">
34
- <SLink class="container" :href="_link ?? undefined">
34
+ <div class="STableCellAvatar" :class="[{ link: link || onClick }, color]">
35
+ <SLink
36
+ class="container"
37
+ :href="_link ?? undefined"
38
+ :role="onClick ? 'button' : null"
39
+ @click="() => onClick?.(value, record)"
40
+ >
35
41
  <div v-if="_image" class="avatar">
36
42
  <SAvatar size="mini" :avatar="_image" :name="_name" />
37
43
  </div>
@@ -90,14 +90,14 @@ function stopResizeListener() {
90
90
  }
91
91
 
92
92
  async function adjustDialogPosition() {
93
- if (!props.dropdown || !isOpen.value) {
93
+ const rect = container.value?.getBoundingClientRect()
94
+
95
+ if (!props.dropdown || !isOpen.value || !rect) {
94
96
  return
95
97
  }
96
98
 
97
99
  startDialogPositionListener()
98
100
 
99
- const rect = container.value.getBoundingClientRect()
100
-
101
101
  await nextTick()
102
102
 
103
103
  const dialogWidth = dialog.value?.offsetWidth ?? 0
@@ -28,8 +28,10 @@ defineProps<{
28
28
 
29
29
  <style scoped lang="postcss">
30
30
  .STableHeader {
31
+ border-radius: 6px 6px 0 0;
31
32
  padding-right: var(--table-padding-right);
32
33
  padding-left: var(--table-padding-left);
34
+ background-color: var(--c-bg-soft);
33
35
  }
34
36
 
35
37
  .container {
@@ -0,0 +1,45 @@
1
+ import { type InjectionKey, type Ref, inject, provide, ref } from 'vue'
2
+
3
+ export interface CardState {
4
+ isCollapsed: Ref<boolean>
5
+ setCollapse(value: boolean): void
6
+ toggleCollapse(): void
7
+ }
8
+
9
+ export const cardStateKey = Symbol('card-state') as InjectionKey<CardState>
10
+
11
+ export function provideCardState(): CardState {
12
+ const isCollapsed = ref(false)
13
+
14
+ function setCollapse(value: boolean): void {
15
+ isCollapsed.value = value
16
+ }
17
+
18
+ function toggleCollapse(): void {
19
+ isCollapsed.value = !isCollapsed.value
20
+ }
21
+
22
+ const cardState = {
23
+ isCollapsed,
24
+ setCollapse,
25
+ toggleCollapse
26
+ }
27
+
28
+ provide(cardStateKey, cardState)
29
+
30
+ return cardState
31
+ }
32
+
33
+ export function useCardState(): CardState {
34
+ const cardState = inject(cardStateKey)
35
+
36
+ if (!cardState) {
37
+ throw new Error(
38
+ '[sefirot] Unexpected call to `useCardState`. This probably means you'
39
+ + ' are using `<SCard>` child component outside of `<SCard>`. Make sure'
40
+ + ' to wrap the component within `<SCard>` component.'
41
+ )
42
+ }
43
+
44
+ return cardState
45
+ }
@@ -19,7 +19,7 @@ export function useFlyout(container?: Ref<any>) {
19
19
  }
20
20
 
21
21
  function closeOnClickOutside(event: any) {
22
- if (!el.value.contains(event.target) && isVisible(el.value)) {
22
+ if (!el.value?.contains(event.target) && isVisible(el.value)) {
23
23
  isOpen.value = false
24
24
  }
25
25
  }
@@ -1,5 +1,5 @@
1
1
  import { type Ref, computed, reactive, toRefs } from 'vue'
2
- import { useSnackbars } from '../stores/Snackbars'
2
+ import { type Snackbar, useSnackbars } from '../stores/Snackbars'
3
3
  import { type UseDataInput, useData } from './Data'
4
4
  import { type Validation, useValidation } from './Validation'
5
5
 
@@ -9,7 +9,7 @@ export interface Form<T extends Record<string, any>> {
9
9
  init(): void
10
10
  reset(): void
11
11
  validate(): Promise<boolean>
12
- validateAndNotify(): Promise<boolean>
12
+ validateAndNotify(message?: Snackbar): Promise<boolean>
13
13
  }
14
14
 
15
15
  export type ComputedData<T extends Record<string, () => any>> = {
@@ -69,11 +69,11 @@ export function useForm<
69
69
  return validation.value.$validate()
70
70
  }
71
71
 
72
- async function validateAndNotify(): Promise<boolean> {
72
+ async function validateAndNotify(message?: Snackbar): Promise<boolean> {
73
73
  const valid = await validate()
74
74
 
75
75
  if (!valid) {
76
- snackbars.push({
76
+ snackbars.push(message ?? {
77
77
  mode: 'danger',
78
78
  text: 'Form contains errors. Please correct them and try again.'
79
79
  })
@@ -122,6 +122,7 @@ export interface TableCellAvatar extends TableCellBase {
122
122
  name?: string | null | ((value: any, record: any) => string | null | undefined)
123
123
  link?: string | null | ((value: any, record: any) => string | null | undefined)
124
124
  color?: 'neutral' | 'soft' | 'mute'
125
+ onClick?(value: any, record: any): void
125
126
  }
126
127
 
127
128
  export interface TableCellAvatars extends TableCellBase {
@@ -8,8 +8,6 @@ export interface Tooltip {
8
8
 
9
9
  export type Position = 'top' | 'right' | 'bottom' | 'left'
10
10
 
11
- const SCREEN_PADDING = 16
12
-
13
11
  const globalHide = ref<() => void>()
14
12
 
15
13
  /**
@@ -61,31 +59,32 @@ export function useTooltip(
61
59
  // Temporally show tip to get its size.
62
60
  tip.value!.style.display = 'block'
63
61
 
62
+ const screenPadding = document.body.clientWidth >= 512 ? 24 : 8
64
63
  const contentRect = content.value!.getBoundingClientRect()
65
64
  const tipRect = tip.value!.getBoundingClientRect()
66
65
 
67
66
  const contentRightX = contentRect.x + contentRect.width
68
67
  const tipRightX = tipRect.x + tipRect.width
69
68
 
70
- if (tipRect.x < 0) {
71
- adjustLeftPosition(contentRect.x)
72
- } else if (tipRightX > window.outerWidth) {
73
- adjustRightPosition(contentRightX)
69
+ if (tipRect.x < screenPadding) {
70
+ adjustLeftPosition(screenPadding, contentRect.x)
71
+ } else if (tipRightX > (document.body.clientWidth - screenPadding)) {
72
+ adjustRightPosition(screenPadding, contentRightX)
74
73
  }
75
74
 
76
75
  tip.value!.style.display = 'none'
77
76
  }
78
77
 
79
- function adjustLeftPosition(contentRectX: number): void {
78
+ function adjustLeftPosition(screenPadding: number, contentRectX: number): void {
80
79
  tip.value!.style.left = '0'
81
80
  tip.value!.style.right = 'auto'
82
- setTransform(-contentRectX + SCREEN_PADDING)
81
+ setTransform(-contentRectX + screenPadding)
83
82
  }
84
83
 
85
- function adjustRightPosition(contentRightX: number): void {
84
+ function adjustRightPosition(screenPadding: number, contentRightX: number): void {
86
85
  tip.value!.style.left = 'auto'
87
86
  tip.value!.style.right = '0'
88
- setTransform((window.outerWidth - contentRightX) - SCREEN_PADDING)
87
+ setTransform((document.body.clientWidth - contentRightX) - screenPadding)
89
88
  }
90
89
 
91
90
  function resetPosition(): void {
@@ -0,0 +1,30 @@
1
+ import { type App } from 'vue'
2
+ import SCard from '../components/SCard.vue'
3
+ import SCardBlock from '../components/SCardBlock.vue'
4
+ import SCardFooter from '../components/SCardFooter.vue'
5
+ import SCardFooterAction from '../components/SCardFooterAction.vue'
6
+ import SCardFooterActions from '../components/SCardFooterActions.vue'
7
+ import SCardHeader from '../components/SCardHeader.vue'
8
+ import SCardHeaderAction from '../components/SCardHeaderAction.vue'
9
+ import SCardHeaderActionClose from '../components/SCardHeaderActionClose.vue'
10
+ import SCardHeaderActionCollapse from '../components/SCardHeaderActionCollapse.vue'
11
+ import SCardHeaderActions from '../components/SCardHeaderActions.vue'
12
+ import SCardHeaderTitle from '../components/SCardHeaderTitle.vue'
13
+
14
+ export function mixin(app: App): void {
15
+ app.mixin({
16
+ components: {
17
+ SCard,
18
+ SCardBlock,
19
+ SCardFooter,
20
+ SCardFooterAction,
21
+ SCardFooterActions,
22
+ SCardHeader,
23
+ SCardHeaderAction,
24
+ SCardHeaderActionClose,
25
+ SCardHeaderActionCollapse,
26
+ SCardHeaderActions,
27
+ SCardHeaderTitle
28
+ }
29
+ })
30
+ }
@@ -67,90 +67,6 @@
67
67
  --c-text-dark-1: rgba(235, 235, 245, 0.98);
68
68
  --c-text-dark-2: rgba(235, 235, 245, 0.6);
69
69
  --c-text-dark-3: rgba(235, 235, 245, 0.3);
70
-
71
- --c-info: #1668b6;
72
- --c-info-light: #2997ff;
73
- --c-info-lighter: #5bafff;
74
- --c-info-lghtest: #7dc0ff;
75
- --c-info-dark: #104c85;
76
- --c-info-darker: #0c3963;
77
- --c-info-darkest: #092e51;
78
- --c-info-dimm-1: rgba(22, 104, 182, 0.12);
79
- --c-info-dimm-2: rgba(22, 104, 182, 0.2);
80
- --c-info-dimm-3: rgba(22, 104, 182, 0.28);
81
- --c-info-text: var(--c-info-light);
82
- --c-info-text-light: var(--c-info-lighter);
83
- --c-info-text-lighter: var(--c-info-lightest);
84
- --c-info-text-dark: var(--c-info);
85
- --c-info-text-darker: var(--c-info-dark);
86
- --c-info-bg: var(--c-info);
87
- --c-info-bg-light: var(--c-info-light);
88
- --c-info-bg-lighter: var(--c-info-lighter);
89
- --c-info-bg-dark: var(--c-info-dark);
90
- --c-info-bg-darker: var(--c-info-darker);
91
-
92
- --c-success: #059669;
93
- --c-success-light: #10b981;
94
- --c-success-lighter: #34d399;
95
- --c-success-lghtest: #6ee7b7;
96
- --c-success-dark: #047857;
97
- --c-success-darker: #065f46;
98
- --c-success-darkest: #064e3b;
99
- --c-success-dimm-1: rgba(5, 150, 105, 0.12);
100
- --c-success-dimm-2: rgba(5, 150, 105, 0.2);
101
- --c-success-dimm-3: rgba(5, 150, 105, 0.28);
102
- --c-success-text: var(--c-success-light);
103
- --c-success-text-light: var(--c-success-lighter);
104
- --c-success-text-lighter: var(--c-success-lightest);
105
- --c-success-text-dark: var(--c-success);
106
- --c-success-text-darker: var(--c-success-dark);
107
- --c-success-bg: var(--c-success);
108
- --c-success-bg-light: var(--c-success-light);
109
- --c-success-bg-lighter: var(--c-success-lighter);
110
- --c-success-bg-dark: var(--c-success-dark);
111
- --c-success-bg-darker: var(--c-success-darker);
112
-
113
- --c-warning: #ca8a04;
114
- --c-warning-light: #eab308;
115
- --c-warning-lighter: #facc15;
116
- --c-warning-lghtest: #fde047;
117
- --c-warning-dark: #a16207;
118
- --c-warning-darker: #854d0e;
119
- --c-warning-darkest: #713f12;
120
- --c-warning-dimm-1: rgba(202, 138, 4, 0.12);
121
- --c-warning-dimm-2: rgba(202, 138, 4, 0.2);
122
- --c-warning-dimm-3: rgba(202, 138, 4, 0.28);
123
- --c-warning-text: var(--c-warning-light);
124
- --c-warning-text-light: var(--c-warning-lighter);
125
- --c-warning-text-lighter: var(--c-warning-lightest);
126
- --c-warning-text-dark: var(--c-warning);
127
- --c-warning-text-darker: var(--c-warning-dark);
128
- --c-warning-bg: var(--c-warning);
129
- --c-warning-bg-light: var(--c-warning-light);
130
- --c-warning-bg-lighter: var(--c-warning-lighter);
131
- --c-warning-bg-dark: var(--c-warning-dark);
132
- --c-warning-bg-darker: var(--c-warning-darker);
133
-
134
- --c-danger: #e11d48;
135
- --c-danger-light: #f43f5e;
136
- --c-danger-lighter: #fb7185;
137
- --c-danger-lghtest: #fda4af;
138
- --c-danger-dark: #be123c;
139
- --c-danger-darker: #9f1239;
140
- --c-danger-darkest: #881337;
141
- --c-danger-dimm-1: rgba(225, 29, 72, 0.12);
142
- --c-danger-dimm-2: rgba(225, 29, 72, 0.2);
143
- --c-danger-dimm-3: rgba(225, 29, 72, 0.28);
144
- --c-danger-text: var(--c-danger-light);
145
- --c-danger-text-light: var(--c-danger-lighter);
146
- --c-danger-text-lighter: var(--c-danger-lightest);
147
- --c-danger-text-dark: var(--c-danger);
148
- --c-danger-text-darker: var(--c-danger-dark);
149
- --c-danger-bg: var(--c-danger);
150
- --c-danger-bg-light: var(--c-danger-light);
151
- --c-danger-bg-lighter: var(--c-danger-lighter);
152
- --c-danger-bg-dark: var(--c-danger-dark);
153
- --c-danger-bg-darker: var(--c-danger-darker);
154
70
  }
155
71
 
156
72
  /**
@@ -183,6 +99,8 @@
183
99
  --c-divider-1: var(--c-divider-light-1);
184
100
  --c-divider-2: var(--c-divider-light-2);
185
101
 
102
+ --c-gutter: #e8e8e8;
103
+
186
104
  --c-neutral-1: var(--c-neutral-light-1);
187
105
  --c-neutral-2: var(--c-neutral-light-2);
188
106
  --c-neutral-3: var(--c-neutral-light-3);
@@ -210,6 +128,110 @@
210
128
  --c-mute-darker: #d1d1d1;
211
129
  --c-mute-dimm-1: #f1f1f1;
212
130
  --c-mute-dimm-2: #e3e3e3;
131
+
132
+ --c-info: #0969da;
133
+ --c-info-light: #218bff;
134
+ --c-info-lighter: #54aeff;
135
+ --c-info-lghtest: #80ccff;
136
+ --c-info-dark: #0550ae;
137
+ --c-info-darker: #033d8b;
138
+ --c-info-darkest: #0a3069;
139
+ --c-info-dimm-1: rgba(2, 132, 199, 0.12);
140
+ --c-info-dimm-2: rgba(2, 132, 199, 0.2);
141
+ --c-info-dimm-3: rgba(2, 132, 199, 0.28);
142
+ --c-info-text: var(--c-info-light);
143
+ --c-info-text-light: var(--c-info-lighter);
144
+ --c-info-text-lighter: var(--c-info-lightest);
145
+ --c-info-text-dark: var(--c-info);
146
+ --c-info-text-darker: var(--c-info-dark);
147
+ --c-info-border: var(--c-info-light);
148
+ --c-info-border-light: var(--c-info-lighter);
149
+ --c-info-border-lighter: var(--c-info-lightest);
150
+ --c-info-border-dark: var(--c-info);
151
+ --c-info-border-darker: var(--c-info-dark);
152
+ --c-info-bg: var(--c-info);
153
+ --c-info-bg-light: var(--c-info-light);
154
+ --c-info-bg-lighter: var(--c-info-lighter);
155
+ --c-info-bg-dark: var(--c-info-dark);
156
+ --c-info-bg-darker: var(--c-info-darker);
157
+
158
+ --c-success: #1a7f58;
159
+ --c-success-light: #2da476;
160
+ --c-success-lighter: #4ac294;
161
+ --c-success-lghtest: #6fddaf;
162
+ --c-success-dark: #116345;
163
+ --c-success-darker: #044f37;
164
+ --c-success-darkest: #003d2b;
165
+ --c-success-dimm-1: rgba(5, 150, 105, 0.12);
166
+ --c-success-dimm-2: rgba(5, 150, 105, 0.2);
167
+ --c-success-dimm-3: rgba(5, 150, 105, 0.28);
168
+ --c-success-text: var(--c-success-light);
169
+ --c-success-text-light: var(--c-success-lighter);
170
+ --c-success-text-lighter: var(--c-success-lightest);
171
+ --c-success-text-dark: var(--c-success);
172
+ --c-success-text-darker: var(--c-success-dark);
173
+ --c-success-border: var(--c-success-light);
174
+ --c-success-border-light: var(--c-success-lighter);
175
+ --c-success-border-lighter: var(--c-success-lightest);
176
+ --c-success-border-dark: var(--c-success);
177
+ --c-success-border-darker: var(--c-success-dark);
178
+ --c-success-bg: var(--c-success);
179
+ --c-success-bg-light: var(--c-success-light);
180
+ --c-success-bg-lighter: var(--c-success-lighter);
181
+ --c-success-bg-dark: var(--c-success-dark);
182
+ --c-success-bg-darker: var(--c-success-darker);
183
+
184
+ --c-warning: #bf8700;
185
+ --c-warning-light: #d4a72c;
186
+ --c-warning-lighter: #eac54f;
187
+ --c-warning-lghtest: #fae17d;
188
+ --c-warning-dark: #9a6700;
189
+ --c-warning-darker: #7d4e00;
190
+ --c-warning-darkest: #633c01;
191
+ --c-warning-dimm-1: rgba(202, 138, 4, 0.12);
192
+ --c-warning-dimm-2: rgba(202, 138, 4, 0.2);
193
+ --c-warning-dimm-3: rgba(202, 138, 4, 0.28);
194
+ --c-warning-text: var(--c-warning-light);
195
+ --c-warning-text-light: var(--c-warning-lighter);
196
+ --c-warning-text-lighter: var(--c-warning-lightest);
197
+ --c-warning-text-dark: var(--c-warning);
198
+ --c-warning-text-darker: var(--c-warning-dark);
199
+ --c-warning-border: var(--c-warning-light);
200
+ --c-warning-border-light: var(--c-warning-lighter);
201
+ --c-warning-border-lighter: var(--c-warning-lightest);
202
+ --c-warning-border-dark: var(--c-warning);
203
+ --c-warning-border-darker: var(--c-warning-dark);
204
+ --c-warning-bg: var(--c-warning);
205
+ --c-warning-bg-light: var(--c-warning-light);
206
+ --c-warning-bg-lighter: var(--c-warning-lighter);
207
+ --c-warning-bg-dark: var(--c-warning-dark);
208
+ --c-warning-bg-darker: var(--c-warning-darker);
209
+
210
+ --c-danger: #cf222e;
211
+ --c-danger-light: #fa4549;
212
+ --c-danger-lighter: #ff8182;
213
+ --c-danger-lghtest: #ffaba8;
214
+ --c-danger-dark: #a40e26;
215
+ --c-danger-darker: #82071e;
216
+ --c-danger-darkest: #660018;
217
+ --c-danger-dimm-1: rgba(225, 29, 72, 0.12);
218
+ --c-danger-dimm-2: rgba(225, 29, 72, 0.2);
219
+ --c-danger-dimm-3: rgba(225, 29, 72, 0.28);
220
+ --c-danger-text: var(--c-danger-light);
221
+ --c-danger-text-light: var(--c-danger-lighter);
222
+ --c-danger-text-lighter: var(--c-danger-lightest);
223
+ --c-danger-text-dark: var(--c-danger);
224
+ --c-danger-text-darker: var(--c-danger-dark);
225
+ --c-danger-border: var(--c-danger-light);
226
+ --c-danger-border-light: var(--c-danger-lighter);
227
+ --c-danger-border-lighter: var(--c-danger-lightest);
228
+ --c-danger-border-dark: var(--c-danger);
229
+ --c-danger-border-darker: var(--c-danger-dark);
230
+ --c-danger-bg: var(--c-danger);
231
+ --c-danger-bg-light: var(--c-danger-light);
232
+ --c-danger-bg-lighter: var(--c-danger-lighter);
233
+ --c-danger-bg-dark: var(--c-danger-dark);
234
+ --c-danger-bg-darker: var(--c-danger-darker);
213
235
  }
214
236
 
215
237
  .dark {
@@ -238,6 +260,8 @@
238
260
  --c-divider-1: var(--c-divider-dark-1);
239
261
  --c-divider-2: var(--c-divider-dark-2);
240
262
 
263
+ --c-gutter: #000000;
264
+
241
265
  --c-neutral-1: var(--c-neutral-dark-1);
242
266
  --c-neutral-2: var(--c-neutral-dark-2);
243
267
  --c-neutral-3: var(--c-neutral-dark-3);
@@ -265,6 +289,110 @@
265
289
  --c-mute-darker: #1c1c1e;
266
290
  --c-mute-dimm-1: #222226;
267
291
  --c-mute-dimm-2: #2c2c2e;
292
+
293
+ --c-info: #1f6feb;
294
+ --c-info-light: #388bfd;
295
+ --c-info-lighter: #58a6ff;
296
+ --c-info-lghtest: #79c0ff;
297
+ --c-info-dark: #1158c7;
298
+ --c-info-darker: #0d419d;
299
+ --c-info-darkest: #0c2d6b;
300
+ --c-info-dimm-1: rgba(2, 132, 199, 0.12);
301
+ --c-info-dimm-2: rgba(2, 132, 199, 0.2);
302
+ --c-info-dimm-3: rgba(2, 132, 199, 0.28);
303
+ --c-info-text: var(--c-info-light);
304
+ --c-info-text-light: var(--c-info-lighter);
305
+ --c-info-text-lighter: var(--c-info-lightest);
306
+ --c-info-text-dark: var(--c-info);
307
+ --c-info-text-darker: var(--c-info-dark);
308
+ --c-info-border: var(--c-info-light);
309
+ --c-info-border-light: var(--c-info-lighter);
310
+ --c-info-border-lighter: var(--c-info-lightest);
311
+ --c-info-border-dark: var(--c-info);
312
+ --c-info-border-darker: var(--c-info-dark);
313
+ --c-info-bg: var(--c-info);
314
+ --c-info-bg-light: var(--c-info-light);
315
+ --c-info-bg-lighter: var(--c-info-lighter);
316
+ --c-info-bg-dark: var(--c-info-dark);
317
+ --c-info-bg-darker: var(--c-info-darker);
318
+
319
+ --c-success: #238554;
320
+ --c-success-light: #2ea069;
321
+ --c-success-lighter: #3fb978;
322
+ --c-success-lghtest: #56d38e;
323
+ --c-success-dark: #196c49;
324
+ --c-success-darker: #0f533a;
325
+ --c-success-darkest: #033a29;
326
+ --c-success-dimm-1: rgba(5, 150, 105, 0.12);
327
+ --c-success-dimm-2: rgba(5, 150, 105, 0.2);
328
+ --c-success-dimm-3: rgba(5, 150, 105, 0.28);
329
+ --c-success-text: var(--c-success-light);
330
+ --c-success-text-light: var(--c-success-lighter);
331
+ --c-success-text-lighter: var(--c-success-lightest);
332
+ --c-success-text-dark: var(--c-success);
333
+ --c-success-text-darker: var(--c-success-dark);
334
+ --c-success-border: var(--c-success-light);
335
+ --c-success-border-light: var(--c-success-lighter);
336
+ --c-success-border-lighter: var(--c-success-lightest);
337
+ --c-success-border-dark: var(--c-success);
338
+ --c-success-border-darker: var(--c-success-dark);
339
+ --c-success-bg: var(--c-success);
340
+ --c-success-bg-light: var(--c-success-light);
341
+ --c-success-bg-lighter: var(--c-success-lighter);
342
+ --c-success-bg-dark: var(--c-success-dark);
343
+ --c-success-bg-darker: var(--c-success-darker);
344
+
345
+ --c-warning: #bb8009;
346
+ --c-warning-light: #d29922;
347
+ --c-warning-lighter: #e3b341;
348
+ --c-warning-lghtest: #f2cc60;
349
+ --c-warning-dark: #9e6a03;
350
+ --c-warning-darker: #845306;
351
+ --c-warning-darkest: #693e00;
352
+ --c-warning-dimm-1: rgba(202, 138, 4, 0.12);
353
+ --c-warning-dimm-2: rgba(202, 138, 4, 0.2);
354
+ --c-warning-dimm-3: rgba(202, 138, 4, 0.28);
355
+ --c-warning-text: var(--c-warning-light);
356
+ --c-warning-text-light: var(--c-warning-lighter);
357
+ --c-warning-text-lighter: var(--c-warning-lightest);
358
+ --c-warning-text-dark: var(--c-warning);
359
+ --c-warning-text-darker: var(--c-warning-dark);
360
+ --c-warning-border: var(--c-warning-light);
361
+ --c-warning-border-light: var(--c-warning-lighter);
362
+ --c-warning-border-lighter: var(--c-warning-lightest);
363
+ --c-warning-border-dark: var(--c-warning);
364
+ --c-warning-border-darker: var(--c-warning-dark);
365
+ --c-warning-bg: var(--c-warning);
366
+ --c-warning-bg-light: var(--c-warning-light);
367
+ --c-warning-bg-lighter: var(--c-warning-lighter);
368
+ --c-warning-bg-dark: var(--c-warning-dark);
369
+ --c-warning-bg-darker: var(--c-warning-darker);
370
+
371
+ --c-danger: #da3633;
372
+ --c-danger-light: #f85149;
373
+ --c-danger-lighter: #ff7b72;
374
+ --c-danger-lghtest: #ffaba8;
375
+ --c-danger-dark: #b62324;
376
+ --c-danger-darker: #8e1519;
377
+ --c-danger-darkest: #67060c;
378
+ --c-danger-dimm-1: rgba(225, 29, 72, 0.12);
379
+ --c-danger-dimm-2: rgba(225, 29, 72, 0.2);
380
+ --c-danger-dimm-3: rgba(225, 29, 72, 0.28);
381
+ --c-danger-text: var(--c-danger-light);
382
+ --c-danger-text-light: var(--c-danger-lighter);
383
+ --c-danger-text-lighter: var(--c-danger-lightest);
384
+ --c-danger-text-dark: var(--c-danger);
385
+ --c-danger-text-darker: var(--c-danger-dark);
386
+ --c-danger-border: var(--c-danger-light);
387
+ --c-danger-border-light: var(--c-danger-lighter);
388
+ --c-danger-border-lighter: var(--c-danger-lightest);
389
+ --c-danger-border-dark: var(--c-danger);
390
+ --c-danger-border-darker: var(--c-danger-dark);
391
+ --c-danger-bg: var(--c-danger);
392
+ --c-danger-bg-light: var(--c-danger-light);
393
+ --c-danger-bg-lighter: var(--c-danger-lighter);
394
+ --c-danger-bg-dark: var(--c-danger-dark);
395
+ --c-danger-bg-darker: var(--c-danger-darker);
268
396
  }
269
397
 
270
398
  /**
@@ -538,8 +666,8 @@
538
666
 
539
667
  --button-text-mute-text-color: var(--c-text-2);
540
668
  --button-text-mute-content-color: var(--c-text-2);
541
- --button-text-mute-hover-bg-color: var(--c-mute-dimm-1);
542
- --button-text-mute-active-bg-color: var(--c-mute-dimm-2);
669
+ --button-text-mute-hover-bg-color: var(--c-mute);
670
+ --button-text-mute-active-bg-color: var(--c-mute-light);
543
671
  --button-text-mute-disabled-text-color: var(--c-text-3);
544
672
  --button-text-mute-disabled-content-color: var(--c-text-3);
545
673
 
@@ -1,3 +1,10 @@
1
1
  export function format(value: number): string {
2
2
  return value.toLocaleString('en-US', { maximumFractionDigits: 20 })
3
3
  }
4
+
5
+ export function abbreviate(value: number, precision = 0): string {
6
+ return value.toLocaleString('en-US', {
7
+ notation: 'compact',
8
+ maximumFractionDigits: precision
9
+ })
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "2.34.1",
3
+ "version": "2.36.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>",