@globalbrain/sefirot 3.15.0 → 3.17.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 (37) hide show
  1. package/lib/components/SActionList.vue +1 -0
  2. package/lib/components/SActionListItem.vue +12 -3
  3. package/lib/components/SActionMenu.vue +84 -0
  4. package/lib/components/SButton.vue +41 -28
  5. package/lib/components/SCard.vue +2 -2
  6. package/lib/components/SCardBlock.vue +32 -6
  7. package/lib/components/SControl.vue +50 -0
  8. package/lib/components/SControlActionMenu.vue +43 -0
  9. package/lib/components/SControlButton.vue +45 -0
  10. package/lib/components/SControlCenter.vue +24 -0
  11. package/lib/components/SControlInputSearch.vue +68 -0
  12. package/lib/components/SControlLeft.vue +24 -0
  13. package/lib/components/SControlPagination.vue +26 -0
  14. package/lib/components/SControlRight.vue +24 -0
  15. package/lib/components/SControlText.vue +12 -0
  16. package/lib/components/SDropdown.vue +1 -1
  17. package/lib/components/SDropdownSection.vue +7 -1
  18. package/lib/components/SDropdownSectionDateRange.vue +126 -0
  19. package/lib/components/SDropdownSectionDateRangeDateFromTo.vue +88 -0
  20. package/lib/components/SDropdownSectionDateRangeYear.vue +73 -0
  21. package/lib/components/SDropdownSectionDateRangeYearHalf.vue +94 -0
  22. package/lib/components/SDropdownSectionDateRangeYearQuarter.vue +96 -0
  23. package/lib/components/SDropdownSectionMenu.vue +5 -34
  24. package/lib/components/SInputText.vue +9 -7
  25. package/lib/components/SPagination.vue +132 -0
  26. package/lib/components/STable.vue +6 -2
  27. package/lib/components/STableColumn.vue +1 -1
  28. package/lib/components/SW.vue +1 -1
  29. package/lib/composables/Card.ts +15 -3
  30. package/lib/composables/Control.ts +43 -0
  31. package/lib/composables/Dropdown.ts +47 -9
  32. package/lib/composables/Table.ts +11 -9
  33. package/lib/composables/V.ts +5 -5
  34. package/lib/mixins/Control.ts +33 -0
  35. package/lib/styles/utilities.css +113 -3
  36. package/lib/support/DateRange.ts +227 -0
  37. package/package.json +11 -11
@@ -15,6 +15,7 @@ defineProps<{
15
15
  v-for="item, index in list"
16
16
  :key="index"
17
17
  :lead-icon="item.leadIcon"
18
+ :label="item.label"
18
19
  :text="item.text"
19
20
  :link="item.link"
20
21
  :on-click="item.onClick"
@@ -1,16 +1,25 @@
1
1
  <script setup lang="ts">
2
2
  import { type IconifyIcon } from '@iconify/vue/dist/offline'
3
+ import { computed } from 'vue'
3
4
  import SIcon from './SIcon.vue'
4
5
  import SLink from './SLink.vue'
5
6
 
6
7
  export interface ActionListItem {
7
8
  leadIcon?: IconifyIcon
8
- text: string
9
9
  link?: string
10
+ label?: string
11
+ disabled?: boolean
10
12
  onClick?(): void
13
+
14
+ /** @deprecated Use `:label` instead. */
15
+ text?: string
11
16
  }
12
17
 
13
- defineProps<ActionListItem>()
18
+ const props = defineProps<ActionListItem>()
19
+
20
+ const _label = computed(() => {
21
+ return props.label ?? props.text
22
+ })
14
23
  </script>
15
24
 
16
25
  <template>
@@ -23,7 +32,7 @@ defineProps<ActionListItem>()
23
32
  <span v-if="leadIcon" class="lead-icon">
24
33
  <SIcon class="lead-icon-svg" :icon="leadIcon" />
25
34
  </span>
26
- <span class="text">{{ text }}</span>
35
+ <span class="text">{{ _label }}</span>
27
36
  </component>
28
37
  </template>
29
38
 
@@ -0,0 +1,84 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { type DropdownSection, useManualDropdownPosition } from '../composables/Dropdown'
4
+ import { useFlyout } from '../composables/Flyout'
5
+ import SButton, { type Mode, type Size, type Tooltip, type Type } from './SButton.vue'
6
+ import SDropdown from './SDropdown.vue'
7
+
8
+ export type { Mode, Size, Tooltip, Type }
9
+
10
+ const props = defineProps<{
11
+ tag?: string
12
+ size?: Size
13
+ type?: Type
14
+ mode?: Mode
15
+ icon?: any
16
+ iconMode?: Mode
17
+ label?: string
18
+ labelMode?: Mode
19
+ rounded?: boolean
20
+ block?: boolean
21
+ loading?: boolean
22
+ disabled?: boolean
23
+ tooltip?: Tooltip
24
+ options: DropdownSection[]
25
+ }>()
26
+
27
+ const container = ref<any>(null)
28
+
29
+ const { isOpen, toggle } = useFlyout(container)
30
+ const { position, update: updatePosition } = useManualDropdownPosition(container)
31
+
32
+ async function onOpen() {
33
+ if (!props.disabled) {
34
+ updatePosition()
35
+ toggle()
36
+ }
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <div class="SActionMenu" :class="[block]" ref="container">
42
+ <div class="button">
43
+ <SButton
44
+ :tag="tag"
45
+ :size="size"
46
+ :type="type"
47
+ :mode="mode"
48
+ :icon="icon"
49
+ :icon-mode="iconMode"
50
+ :label="label"
51
+ :label-mode="labelMode"
52
+ :rounded="rounded"
53
+ :block="block"
54
+ :loading="loading"
55
+ :disabled="disabled"
56
+ :tooltip="tooltip"
57
+ @click="onOpen"
58
+ />
59
+ </div>
60
+ <div v-if="isOpen" class="dropdown" :class="position">
61
+ <SDropdown :sections="options" />
62
+ </div>
63
+ </div>
64
+ </template>
65
+
66
+ <style scoped lang="postcss">
67
+ .SActionMenu {
68
+ position: relative;
69
+ display: inline-block;
70
+ }
71
+
72
+ .dropdown {
73
+ position: absolute;
74
+ left: 0;
75
+ z-index: var(--z-index-dropdown);
76
+
77
+ &.top { bottom: calc(100% + 8px); }
78
+ &.bottom { top: calc(100% + 8px); }
79
+ }
80
+
81
+ .SActionMenu.block {
82
+ display: block;
83
+ }
84
+ </style>
@@ -36,6 +36,8 @@ const props = defineProps<{
36
36
  type?: Type
37
37
  mode?: Mode
38
38
  icon?: any
39
+ leadIcon?: any
40
+ trailIcon?: any
39
41
  iconMode?: Mode
40
42
  label?: string
41
43
  labelMode?: Mode
@@ -52,12 +54,15 @@ const emit = defineEmits<{
52
54
  (e: 'disabled-click'): void
53
55
  }>()
54
56
 
57
+ const _leadIcon = computed(() => props.leadIcon ?? props.icon)
58
+
55
59
  const classes = computed(() => [
56
60
  props.size ?? 'medium',
57
61
  props.type ?? 'fill',
58
62
  props.mode ?? 'default',
59
63
  { 'has-label': props.label },
60
- { 'has-icon': props.icon },
64
+ { 'has-lead-icon': _leadIcon.value },
65
+ { 'has-trail-icon': props.trailIcon },
61
66
  { loading: props.loading },
62
67
  { rounded: props.rounded },
63
68
  { block: props.block },
@@ -104,12 +109,15 @@ function handleClick(): void {
104
109
  @click="handleClick"
105
110
  >
106
111
  <span class="content">
107
- <span v-if="icon" class="icon" :class="iconMode">
108
- <SIcon :icon="icon" class="icon-svg" />
112
+ <span v-if="_leadIcon" class="icon" :class="iconMode">
113
+ <SIcon :icon="_leadIcon" class="icon-svg" />
109
114
  </span>
110
115
  <span v-if="label" class="label" :class="labelMode">
111
116
  {{ label }}
112
117
  </span>
118
+ <span v-if="trailIcon" class="icon" :class="iconMode">
119
+ <SIcon :icon="trailIcon" class="icon-svg" />
120
+ </span>
113
121
  </span>
114
122
 
115
123
  <transition name="fade">
@@ -192,11 +200,12 @@ function handleClick(): void {
192
200
  min-height: 28px;
193
201
  font-size: var(--button-font-size, var(--button-mini-font-size));
194
202
 
195
- &.rounded { border-radius: 16px; }
196
- &.has-label { padding: var(--button-padding, 0 12px); }
197
- &.has-label.has-icon { padding: var(--button-padding, 0 10px 0 8px); }
198
- .content { gap: 4px; }
199
- .icon-svg { width: 16px; height: 16px; }
203
+ &.rounded { border-radius: 16px; }
204
+ &.has-label { padding: var(--button-padding, 0 12px); }
205
+ &.has-label.has-lead-icon { padding: var(--button-padding, 0 10px 0 8px); }
206
+ &.has-label.has-trail-icon { padding: var(--button-padding, 0 8px 0 10px); }
207
+ .content { gap: 4px; }
208
+ .icon-svg { width: 16px; height: 16px; }
200
209
  }
201
210
 
202
211
  .SButton.small {
@@ -204,11 +213,12 @@ function handleClick(): void {
204
213
  min-height: 32px;
205
214
  font-size: var(--button-font-size, var(--button-small-font-size));
206
215
 
207
- &.rounded { border-radius: 16px; }
208
- &.has-label { padding: var(--button-padding, 0 12px); }
209
- &.has-label.has-icon { padding: var(--button-padding, 0 10px 0 8px); }
210
- .content { gap: 6px; }
211
- .icon-svg { width: 16px; height: 16px; }
216
+ &.rounded { border-radius: 16px; }
217
+ &.has-label { padding: var(--button-padding, 0 12px); }
218
+ &.has-label.has-lead-icon { padding: var(--button-padding, 0 10px 0 8px); }
219
+ &.has-label.has-trail-icon { padding: var(--button-padding, 0 8px 0 10px); }
220
+ .content { gap: 6px; }
221
+ .icon-svg { width: 16px; height: 16px; }
212
222
  }
213
223
 
214
224
  .SButton.medium {
@@ -216,11 +226,12 @@ function handleClick(): void {
216
226
  min-height: 40px;
217
227
  font-size: var(--button-font-size, var(--button-medium-font-size));
218
228
 
219
- &.rounded { border-radius: 20px; }
220
- &.has-label { padding: var(--button-padding, 0 16px); }
221
- &.has-label.has-icon { padding: var(--button-padding, 0 12px 0 10px); }
222
- .content { gap: 6px; }
223
- .icon-svg { width: 18px; height: 18px; }
229
+ &.rounded { border-radius: 20px; }
230
+ &.has-label { padding: var(--button-padding, 0 16px); }
231
+ &.has-label.has-lead-icon { padding: var(--button-padding, 0 12px 0 10px); }
232
+ &.has-label.has-trail-icon { padding: var(--button-padding, 0 10px 0 12px); }
233
+ .content { gap: 6px; }
234
+ .icon-svg { width: 18px; height: 18px; }
224
235
  }
225
236
 
226
237
  .SButton.large {
@@ -228,11 +239,12 @@ function handleClick(): void {
228
239
  min-height: 48px;
229
240
  font-size: var(--button-font-size, var(--button-large-font-size));
230
241
 
231
- &.rounded { border-radius: 24px; }
232
- &.has-label { padding: var(--button-padding, 0 20px); }
233
- &.has-label.has-icon { padding: var(--button-padding, 0 14px 0 12px); }
234
- .content { gap: 6px; }
235
- .icon-svg { width: 18px; height: 18px; }
242
+ &.rounded { border-radius: 24px; }
243
+ &.has-label { padding: var(--button-padding, 0 20px); }
244
+ &.has-label.has-lead-icon { padding: var(--button-padding, 0 14px 0 12px); }
245
+ &.has-label.has-trail-icon { padding: var(--button-padding, 0 12px 0 14px); }
246
+ .content { gap: 6px; }
247
+ .icon-svg { width: 18px; height: 18px; }
236
248
  }
237
249
 
238
250
  .SButton.jumbo {
@@ -240,11 +252,12 @@ function handleClick(): void {
240
252
  min-height: 64px;
241
253
  font-size: var(--button-font-size, var(--button-jumbo-font-size));
242
254
 
243
- &.rounded { border-radius: 32px; }
244
- &.has-label { padding: var(--button-padding, 0 24px); }
245
- &.has-label.has-icon { padding: var(--button-padding, 0 20px 0 18px); }
246
- .content { gap: 8px; }
247
- .icon-svg { width: 20px; height: 20px; }
255
+ &.rounded { border-radius: 32px; }
256
+ &.has-label { padding: var(--button-padding, 0 24px); }
257
+ &.has-label.has-lead-icon { padding: var(--button-padding, 0 20px 0 18px); }
258
+ &.has-label.has-trail-icon { padding: var(--button-padding, 0 18px 0 20px); }
259
+ .content { gap: 8px; }
260
+ .icon-svg { width: 20px; height: 20px; }
248
261
  }
249
262
 
250
263
  .SButton.disabled {
@@ -10,13 +10,13 @@ const props = defineProps<{
10
10
  mode?: Mode
11
11
  }>()
12
12
 
13
- const { isCollapsed } = provideCardState()
14
-
15
13
  const classes = computed(() => [
16
14
  props.size,
17
15
  props.mode ?? 'neutral',
18
16
  { collapsed: isCollapsed.value }
19
17
  ])
18
+
19
+ const { isCollapsed } = provideCardState()
20
20
  </script>
21
21
 
22
22
  <template>
@@ -1,25 +1,35 @@
1
1
  <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { type CardBlockSize, provideCardBlockSize } from '../composables/Card'
4
+
5
+ export type { CardBlockSize as Size }
6
+
7
+ // @deprecated Use CSS utility classes instead.
2
8
  export type Space = 'compact' | 'wide' | 'xwide'
3
9
 
4
- defineProps<{
10
+ const props = defineProps<{
11
+ size?: CardBlockSize
12
+
13
+ // @deprecated Use CSS utility classes instead.
5
14
  space?: Space
6
15
  }>()
16
+
17
+ provideCardBlockSize(computed(() => props.size ?? null))
7
18
  </script>
8
19
 
9
20
  <template>
10
- <div class="SCardBlock" :class="[space]">
21
+ <div class="SCardBlock" :class="[size, space]">
11
22
  <slot />
12
23
  </div>
13
24
  </template>
14
25
 
15
26
  <style scoped lang="postcss">
16
27
  .SCardBlock {
17
- padding: var(--card-padding, 0);
18
28
  background-color: var(--c-bg-elv-3);
19
29
 
20
- &.compact { padding: 24px; }
21
- &.wide { padding: 32px; }
22
- &.xwide { padding: 48px; }
30
+ &.compact { padding: 12px; }
31
+ &.wide { padding: 16px; }
32
+ &.xwide { padding: 24px; }
23
33
  }
24
34
 
25
35
  .SCard > .SCardBlock:first-child {
@@ -31,4 +41,20 @@ defineProps<{
31
41
  border-bottom-right-radius: 5px;
32
42
  border-bottom-left-radius: 5px;
33
43
  }
44
+
45
+ .SCardBlock.xsmall,
46
+ .SCardBlock.small,
47
+ .SCardBlock.medium,
48
+ .SCardBlock.large,
49
+ .SCardBlock.xlarge {
50
+ display: flex;
51
+ align-items: center;
52
+ width: 100%;
53
+ }
54
+
55
+ .SCardBlock.xsmall { height: 40px; }
56
+ .SCardBlock.small { height: 48px; }
57
+ .SCardBlock.medium { height: 56px; }
58
+ .SCardBlock.large { height: 64px; }
59
+ .SCardBlock.xlarge { height: 80px; }
34
60
  </style>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { useCardBlockSize } from '../composables/Card'
4
+ import { type ControlSize, provideControlSize } from '../composables/Control'
5
+
6
+ export type { ControlSize as Size }
7
+
8
+ const props = defineProps<{
9
+ size?: ControlSize
10
+ }>()
11
+
12
+ const cardSize = useCardBlockSize()
13
+
14
+ const sizeDict = {
15
+ xsmall: 'small',
16
+ small: 'small',
17
+ medium: 'small',
18
+ large: 'medium',
19
+ xlarge: 'medium',
20
+ null: null
21
+ } as const
22
+
23
+ const _size = computed(() => {
24
+ return props.size ?? sizeDict[cardSize.value ?? 'null'] ?? 'small'
25
+ })
26
+
27
+ const classes = computed(() => [
28
+ _size.value,
29
+ cardSize.value ? `card-size-${cardSize.value}` : null
30
+ ])
31
+
32
+ provideControlSize(_size)
33
+ </script>
34
+
35
+ <template>
36
+ <div class="SControl" :class="classes">
37
+ <slot />
38
+ </div>
39
+ </template>
40
+
41
+ <style scoped lang="postcss">
42
+ .SControl {
43
+ display: flex;
44
+ align-items: center;
45
+ flex-grow: 1;
46
+ }
47
+
48
+ .SControl.small { gap: 8px; height: 32px; }
49
+ .SControl.medium { gap: 12px; height: 40px; }
50
+ </style>
@@ -0,0 +1,43 @@
1
+ <script setup lang="ts">
2
+ import { useControlSize } from '../composables/Control'
3
+ import { type DropdownSection } from '../composables/Dropdown'
4
+ import SActionMenu, { type Mode, type Tooltip, type Type } from './SActionMenu.vue'
5
+
6
+ defineProps<{
7
+ tag?: string
8
+ type?: Type
9
+ mode?: Mode
10
+ icon?: any
11
+ iconMode?: Mode
12
+ label?: string
13
+ labelMode?: Mode
14
+ href?: string
15
+ loading?: boolean
16
+ disabled?: boolean
17
+ tooltip?: Tooltip
18
+ options: DropdownSection[]
19
+ }>()
20
+
21
+ const size = useControlSize()
22
+ </script>
23
+
24
+ <template>
25
+ <div class="SControlActionMenu">
26
+ <SActionMenu
27
+ :tag="tag"
28
+ :size="size"
29
+ :type="type"
30
+ :mode="mode"
31
+ :icon="icon"
32
+ :icon-mode="iconMode"
33
+ :label="label"
34
+ :label-mode="labelMode"
35
+ :href="href"
36
+ :tooltip="tooltip"
37
+ :options="options"
38
+ block
39
+ :loading="loading"
40
+ :disabled="disabled"
41
+ />
42
+ </div>
43
+ </template>
@@ -0,0 +1,45 @@
1
+ <script setup lang="ts">
2
+ import { useControlSize } from '../composables/Control'
3
+ import SButton, { type Mode, type Tooltip, type Type } from './SButton.vue'
4
+
5
+ defineProps<{
6
+ tag?: string
7
+ type?: Type
8
+ mode?: Mode
9
+ icon?: any
10
+ iconMode?: Mode
11
+ label?: string
12
+ labelMode?: Mode
13
+ href?: string
14
+ loading?: boolean
15
+ disabled?: boolean
16
+ tooltip?: Tooltip
17
+ }>()
18
+
19
+ defineEmits<{
20
+ (e: 'click'): void
21
+ }>()
22
+
23
+ const size = useControlSize()
24
+ </script>
25
+
26
+ <template>
27
+ <div class="SControlButton">
28
+ <SButton
29
+ :tag="tag"
30
+ :size="size"
31
+ :type="type"
32
+ :mode="mode"
33
+ :icon="icon"
34
+ :icon-mode="iconMode"
35
+ :label="label"
36
+ :label-mode="labelMode"
37
+ :href="href"
38
+ :tooltip="tooltip"
39
+ block
40
+ :loading="loading"
41
+ :disabled="disabled"
42
+ @click="$emit('click')"
43
+ />
44
+ </div>
45
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { provideControlPosition } from '../composables/Control'
3
+
4
+ provideControlPosition('center')
5
+ </script>
6
+
7
+ <template>
8
+ <div class="SControlCenter">
9
+ <slot />
10
+ </div>
11
+ </template>
12
+
13
+ <style scoped lang="postcss">
14
+ .SControlCenter {
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ flex-grow: 1;
19
+ flex-shrink: 0;
20
+ }
21
+
22
+ .SControl.small .SControlCenter { gap: 8px; }
23
+ .SControl.medium .SControlCenter { gap: 12px; }
24
+ </style>
@@ -0,0 +1,68 @@
1
+ <script setup lang="ts">
2
+ import IconMagnifyingGlass from '@iconify-icons/ph/magnifying-glass-bold'
3
+ import { computed } from 'vue'
4
+ import { useControlSize } from '../composables/Control'
5
+ import { useTrans } from '../composables/Lang'
6
+ import { type Validatable } from '../composables/V'
7
+ import SInputText, { type Align, type TextColor } from './SInputText.vue'
8
+
9
+ const props = defineProps<{
10
+ placeholder?: string
11
+ unitAfter?: any
12
+ textColor?: TextColor | ((value: string | null) => TextColor)
13
+ align?: Align
14
+ disabled?: boolean
15
+ value?: string | null
16
+ modelValue?: string | null
17
+ displayValue?: string | null
18
+ validation?: Validatable
19
+ }>()
20
+
21
+ defineEmits<{
22
+ (e: 'update:model-value', value: string | null): void
23
+ (e: 'input', value: string | null): void
24
+ (e: 'blur', value: string | null): void
25
+ (e: 'enter', value: string | null): void
26
+ }>()
27
+
28
+ const { t } = useTrans({
29
+ en: { placeholder: 'Search items' },
30
+ ja: { placeholder: '検索する' }
31
+ })
32
+
33
+ const size = useControlSize()
34
+
35
+ const sizeDict = {
36
+ small: 'mini',
37
+ medium: 'small'
38
+ } as const
39
+
40
+ const _value = computed(() => {
41
+ return props.modelValue ?? props.value ?? null
42
+ })
43
+ </script>
44
+
45
+ <template>
46
+ <div class="SControlInputSearch">
47
+ <SInputText
48
+ :size="sizeDict[size]"
49
+ type="search"
50
+ :placeholder="placeholder ?? t.placeholder"
51
+ :unit-before="IconMagnifyingGlass"
52
+ :model-value="_value"
53
+ :validation="validation"
54
+ hide-error
55
+ @update:model-value="$emit('update:model-value', $event)"
56
+ @input="$emit('input', $event)"
57
+ @blur="$emit('blur', $event)"
58
+ @enter="$emit('enter', $event)"
59
+ />
60
+ </div>
61
+ </template>
62
+
63
+ <style scoped lang="postcss">
64
+ .SControlInputSearch {
65
+ flex-grow: 1;
66
+ flex-shrink: 0;
67
+ }
68
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { provideControlPosition } from '../composables/Control'
3
+
4
+ provideControlPosition('left')
5
+ </script>
6
+
7
+ <template>
8
+ <div class="SControlLeft">
9
+ <slot />
10
+ </div>
11
+ </template>
12
+
13
+ <style scoped lang="postcss">
14
+ .SControlLeft {
15
+ display: flex;
16
+ justify-content: flex-start;
17
+ align-items: center;
18
+ flex-grow: 1;
19
+ flex-shrink: 0;
20
+ }
21
+
22
+ .SControl.small .SControlLeft { gap: 8px; }
23
+ .SControl.medium .SControlLeft { gap: 12px; }
24
+ </style>
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ import { useControlPosition, useControlSize } from '../composables/Control'
3
+ import SPagination, { type Size } from './SPagination.vue'
4
+
5
+ defineProps<{
6
+ size?: Size
7
+ total: number
8
+ page: number
9
+ perPage: number
10
+ }>()
11
+
12
+ const size = useControlSize()
13
+ const position = useControlPosition()
14
+ </script>
15
+
16
+ <template>
17
+ <div class="SControlPagination">
18
+ <SPagination
19
+ :size="size"
20
+ :align="position"
21
+ :total="total"
22
+ :page="page"
23
+ :per-page="perPage"
24
+ />
25
+ </div>
26
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { provideControlPosition } from '../composables/Control'
3
+
4
+ provideControlPosition('right')
5
+ </script>
6
+
7
+ <template>
8
+ <div class="SControlRight">
9
+ <slot />
10
+ </div>
11
+ </template>
12
+
13
+ <style scoped lang="postcss">
14
+ .SControlRight {
15
+ display: flex;
16
+ justify-content: flex-end;
17
+ align-items: center;
18
+ flex-grow: 1;
19
+ flex-shrink: 0;
20
+ }
21
+
22
+ .SControl.small .SControlRight { gap: 8px; }
23
+ .SControl.medium .SControlRight { gap: 12px; }
24
+ </style>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div class="SControlText">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SControlText {
9
+ line-height: 24px;
10
+ font-size: 14px;
11
+ }
12
+ </style>
@@ -21,7 +21,7 @@ defineProps<{
21
21
  .SDropdown {
22
22
  border: 1px solid var(--c-divider);
23
23
  border-radius: 6px;
24
- min-width: 256px;
24
+ min-width: 288px;
25
25
  max-height: 384px;
26
26
  overflow-y: auto;
27
27
  white-space: normal;