@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
@@ -2,6 +2,7 @@
2
2
  import { type DropdownSection } from '../composables/Dropdown'
3
3
  import SDropdownSectionActions from './SDropdownSectionActions.vue'
4
4
  import SDropdownSectionComponent from './SDropdownSectionComponent.vue'
5
+ import SDropdownSectionDateRange from './SDropdownSectionDateRange.vue'
5
6
  import SDropdownSectionFilter from './SDropdownSectionFilter.vue'
6
7
  import SDropdownSectionMenu from './SDropdownSectionMenu.vue'
7
8
 
@@ -22,8 +23,13 @@ defineProps<{
22
23
  :options="section.options"
23
24
  :on-click="section.onClick"
24
25
  />
26
+ <SDropdownSectionDateRange
27
+ v-else-if="section.type === 'date-range'"
28
+ :range="section.range"
29
+ :on-apply="section.onApply"
30
+ />
25
31
  <SDropdownSectionActions
26
- v-if="section.type === 'actions'"
32
+ v-else-if="section.type === 'actions'"
27
33
  :options="section.options"
28
34
  />
29
35
  <SDropdownSectionComponent
@@ -0,0 +1,126 @@
1
+ <script setup lang="ts">
2
+ import { type MaybeRefOrGetter, computed, shallowRef, toValue } from 'vue'
3
+ import { type DropdownSectionActionsOption } from '../composables/Dropdown'
4
+ import { useTrans } from '../composables/Lang'
5
+ import { useV } from '../composables/V'
6
+ import { DateRange, type DateRangePreset, type DateRangePresetType } from '../support/DateRange'
7
+ import SDropdownSectionActions from './SDropdownSectionActions.vue'
8
+ import SDropdownSectionDateRangeDateFromTo from './SDropdownSectionDateRangeDateFromTo.vue'
9
+ import SDropdownSectionDateRangeYear from './SDropdownSectionDateRangeYear.vue'
10
+ import SDropdownSectionDateRangeYearHalf from './SDropdownSectionDateRangeYearHalf.vue'
11
+ import SDropdownSectionDateRangeYearQuarter from './SDropdownSectionDateRangeYearQuarter.vue'
12
+ import SInputSelect from './SInputSelect.vue'
13
+
14
+ const props = defineProps<{
15
+ range: MaybeRefOrGetter<DateRange>
16
+ onApply: (range: DateRange) => void
17
+ }>()
18
+
19
+ const { t } = useTrans({
20
+ en: {
21
+ p_date_from_to: 'Custom period',
22
+ p_year: 'Year',
23
+ p_year_half: 'Year half',
24
+ p_year_quarter: 'Year quarter',
25
+ a_apply: 'Apply'
26
+ },
27
+ ja: {
28
+ p_date_from_to: '日付指定',
29
+ p_year: '年',
30
+ p_year_half: '半期',
31
+ p_year_quarter: '四半期',
32
+ a_apply: '適用する'
33
+ }
34
+ })
35
+
36
+ const _range = shallowRef(toValue(props.range))
37
+
38
+ const presetValue = computed(() => {
39
+ return _range.value.preset.type
40
+ })
41
+
42
+ const presetOptions = [
43
+ { label: t.p_date_from_to, value: 'date-from-to' },
44
+ { label: t.p_year, value: 'year' },
45
+ { label: t.p_year_half, value: 'year-half' },
46
+ { label: t.p_year_quarter, value: 'year-quarter' }
47
+ ]
48
+
49
+ const actions: DropdownSectionActionsOption[] = [
50
+ { label: t.a_apply, mode: 'info', onClick: onApply }
51
+ ]
52
+
53
+ const { validate } = useV()
54
+
55
+ function onPresetChange(value: any) {
56
+ _range.value = new DateRange().setPreset(value as DateRangePresetType)
57
+ }
58
+
59
+ function onValueChange(value: DateRangePreset) {
60
+ _range.value = new DateRange().setPreset(value)
61
+ }
62
+
63
+ async function onApply() {
64
+ if (await validate()) {
65
+ props.onApply(_range.value)
66
+ }
67
+ }
68
+ </script>
69
+
70
+ <template>
71
+ <div class="SDropdownSectionDateRange">
72
+ <div class="preset">
73
+ <SInputSelect
74
+ size="mini"
75
+ :options="presetOptions"
76
+ :value="presetValue"
77
+ @change="onPresetChange"
78
+ />
79
+ </div>
80
+ <div class="control">
81
+ <SDropdownSectionDateRangeDateFromTo
82
+ v-if="_range.preset.type === 'date-from-to'"
83
+ :preset="_range.preset"
84
+ @change="onValueChange"
85
+ />
86
+ <SDropdownSectionDateRangeYear
87
+ v-else-if="_range.preset.type === 'year'"
88
+ :preset="_range.preset"
89
+ @change="onValueChange"
90
+ />
91
+ <SDropdownSectionDateRangeYearHalf
92
+ v-else-if="_range.preset.type === 'year-half'"
93
+ :preset="_range.preset"
94
+ @change="onValueChange"
95
+ />
96
+ <SDropdownSectionDateRangeYearQuarter
97
+ v-else-if="_range.preset.type === 'year-quarter'"
98
+ :preset="_range.preset"
99
+ @change="onValueChange"
100
+ />
101
+ </div>
102
+ <div class="actions">
103
+ <SDropdownSectionActions
104
+ :options="actions"
105
+ />
106
+ </div>
107
+ </div>
108
+ </template>
109
+
110
+ <style scoped lang="postcss">
111
+ .SDropdownSectionDateRange {
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: 1px;
115
+ background-color: var(--c-bg-elv-1);
116
+ }
117
+
118
+ .preset {
119
+ padding: 8px;
120
+ background-color: var(--c-bg-elv-3);
121
+ }
122
+
123
+ .control {
124
+ background-color: var(--c-bg-elv-3);
125
+ }
126
+ </style>
@@ -0,0 +1,88 @@
1
+ <script setup lang="ts">
2
+ import { useV } from '../composables/V'
3
+ import { DateFromTo } from '../support/DateRange'
4
+ import { type Day } from '../support/Day'
5
+ import { required } from '../validation/rules'
6
+ import SInputDate from './SInputDate.vue'
7
+
8
+ const props = defineProps<{
9
+ preset: DateFromTo
10
+ }>()
11
+
12
+ const emit = defineEmits<{
13
+ (e: 'change', value: DateFromTo): void
14
+ }>()
15
+
16
+ const { validation } = useV(() => ({
17
+ from: props.preset.from,
18
+ to: props.preset.to
19
+ }), {
20
+ from: { required: required() },
21
+ to: { required: required() }
22
+ })
23
+
24
+ function onFromChange(value: Day | null) {
25
+ emit('change', new DateFromTo().setFrom(value).setTo(props.preset.to))
26
+ }
27
+
28
+ function onToChange(value: Day | null) {
29
+ emit('change', new DateFromTo().setFrom(props.preset.from).setTo(value))
30
+ }
31
+ </script>
32
+
33
+ <template>
34
+ <div class="SDropdownSectionDateRangeDateFromTo">
35
+ <div class="group">
36
+ <div class="label">From</div>
37
+ <div class="input">
38
+ <SInputDate
39
+ size="mini"
40
+ block
41
+ :model-value="preset.from"
42
+ :validation="validation.from"
43
+ hide-error
44
+ @change="onFromChange"
45
+ />
46
+ </div>
47
+ </div>
48
+ <div class="group">
49
+ <div class="label">To</div>
50
+ <div class="input">
51
+ <SInputDate
52
+ size="mini"
53
+ block
54
+ :model-value="preset.to"
55
+ :validation="validation.to"
56
+ hide-error
57
+ @change="onToChange"
58
+ />
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </template>
63
+
64
+ <style scoped lang="postcss">
65
+ .SDropdownSectionDateRangeDateFromTo {
66
+ display: flex;
67
+ flex-direction: column;
68
+ gap: 8px;
69
+ padding: 8px 0;
70
+ }
71
+
72
+ .group {
73
+ display: flex;
74
+ align-items: center;
75
+ padding: 0 8px 0 16px;
76
+ }
77
+
78
+ .label {
79
+ flex-shrink: 0;
80
+ width: 64px;
81
+ font-size: 12px;
82
+ color: var(--c-text-2);
83
+ }
84
+
85
+ .input {
86
+ flex-grow: 1;
87
+ }
88
+ </style>
@@ -0,0 +1,73 @@
1
+ <script setup lang="ts">
2
+ import { useV } from '../composables/V'
3
+ import { Year } from '../support/DateRange'
4
+ import { maxValue, minValue, required } from '../validation/rules'
5
+ import SInputNumber from './SInputNumber.vue'
6
+
7
+ const props = defineProps<{
8
+ preset: Year
9
+ }>()
10
+
11
+ const emit = defineEmits<{
12
+ (e: 'change', value: Year): void
13
+ }>()
14
+
15
+ const { validation } = useV(() => ({
16
+ year: props.preset.year
17
+ }), {
18
+ year: {
19
+ required: required(),
20
+ minValue: minValue(1),
21
+ maxValue: maxValue(9999)
22
+ }
23
+ })
24
+
25
+ function onInput(value: number | null) {
26
+ emit('change', new Year().setYear(value))
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <div class="SDropdownSectionDateRangeYear">
32
+ <div class="group">
33
+ <div class="label">Year</div>
34
+ <div class="input">
35
+ <SInputNumber
36
+ size="mini"
37
+ placeholder="YYYY"
38
+ block
39
+ :model-value="preset.year"
40
+ :validation="validation.year"
41
+ hide-error
42
+ @input="onInput"
43
+ />
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </template>
48
+
49
+ <style scoped lang="postcss">
50
+ .SDropdownSectionDateRangeYear {
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 8px;
54
+ padding: 8px 0;
55
+ }
56
+
57
+ .group {
58
+ display: flex;
59
+ align-items: center;
60
+ padding: 0 8px 0 16px;
61
+ }
62
+
63
+ .label {
64
+ flex-shrink: 0;
65
+ width: 64px;
66
+ font-size: 12px;
67
+ color: var(--c-text-2);
68
+ }
69
+
70
+ .input {
71
+ flex-grow: 1;
72
+ }
73
+ </style>
@@ -0,0 +1,94 @@
1
+ <script setup lang="ts">
2
+ import { useV } from '../composables/V'
3
+ import { YearHalf } from '../support/DateRange'
4
+ import { maxValue, minValue, required } from '../validation/rules'
5
+ import SInputNumber from './SInputNumber.vue'
6
+ import SInputSelect from './SInputSelect.vue'
7
+
8
+ const props = defineProps<{
9
+ preset: YearHalf
10
+ }>()
11
+
12
+ const emit = defineEmits<{
13
+ (e: 'change', value: YearHalf): void
14
+ }>()
15
+
16
+ const { validation } = useV(() => ({
17
+ year: props.preset.year
18
+ }), {
19
+ year: {
20
+ required: required(),
21
+ minValue: minValue(1),
22
+ maxValue: maxValue(9999)
23
+ }
24
+ })
25
+
26
+ const halfOptions = [
27
+ { label: 'H1', value: 1 },
28
+ { label: 'H2', value: 2 }
29
+ ]
30
+
31
+ function onYearInput(value: number | null) {
32
+ emit('change', new YearHalf().setYear(value).setHalf(props.preset.half))
33
+ }
34
+
35
+ function onHalfChange(value: any) {
36
+ emit('change', new YearHalf().setYear(props.preset.year).setHalf(value))
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <div class="SDropdownSectionDateRangeYearHalf">
42
+ <div class="group">
43
+ <div class="label">Year</div>
44
+ <div class="input">
45
+ <SInputNumber
46
+ size="mini"
47
+ placeholder="YYYY"
48
+ block
49
+ :model-value="preset.year"
50
+ :validation="validation.year"
51
+ hide-error
52
+ @input="onYearInput"
53
+ />
54
+ </div>
55
+ </div>
56
+ <div class="group">
57
+ <div class="label">Half</div>
58
+ <div class="input">
59
+ <SInputSelect
60
+ size="mini"
61
+ :options="halfOptions"
62
+ :model-value="preset.half"
63
+ @change="onHalfChange"
64
+ />
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </template>
69
+
70
+ <style scoped lang="postcss">
71
+ .SDropdownSectionDateRangeYearHalf {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: 8px;
75
+ padding: 8px 0;
76
+ }
77
+
78
+ .group {
79
+ display: flex;
80
+ align-items: center;
81
+ padding: 0 8px 0 16px;
82
+ }
83
+
84
+ .label {
85
+ flex-shrink: 0;
86
+ width: 64px;
87
+ font-size: 12px;
88
+ color: var(--c-text-2);
89
+ }
90
+
91
+ .input {
92
+ flex-grow: 1;
93
+ }
94
+ </style>
@@ -0,0 +1,96 @@
1
+ <script setup lang="ts">
2
+ import { useV } from '../composables/V'
3
+ import { YearQuarter } from '../support/DateRange'
4
+ import { maxValue, minValue, required } from '../validation/rules'
5
+ import SInputNumber from './SInputNumber.vue'
6
+ import SInputSelect from './SInputSelect.vue'
7
+
8
+ const props = defineProps<{
9
+ preset: YearQuarter
10
+ }>()
11
+
12
+ const emit = defineEmits<{
13
+ (e: 'change', value: YearQuarter): void
14
+ }>()
15
+
16
+ const { validation } = useV(() => ({
17
+ year: props.preset.year
18
+ }), {
19
+ year: {
20
+ required: required(),
21
+ minValue: minValue(1),
22
+ maxValue: maxValue(9999)
23
+ }
24
+ })
25
+
26
+ const quarterOptions = [
27
+ { label: 'Q1', value: 1 },
28
+ { label: 'Q2', value: 2 },
29
+ { label: 'Q3', value: 3 },
30
+ { label: 'Q4', value: 4 }
31
+ ]
32
+
33
+ function onYearInput(value: number | null) {
34
+ emit('change', new YearQuarter().setYear(value).setQuarter(props.preset.quarter))
35
+ }
36
+
37
+ function onQuarterChange(value: any) {
38
+ emit('change', new YearQuarter().setYear(props.preset.year).setQuarter(value))
39
+ }
40
+ </script>
41
+
42
+ <template>
43
+ <div class="SDropdownSectionDateRangeYearQuarter">
44
+ <div class="group">
45
+ <div class="label">Year</div>
46
+ <div class="input">
47
+ <SInputNumber
48
+ size="mini"
49
+ placeholder="YYYY"
50
+ block
51
+ :model-value="preset.year"
52
+ :validation="validation.year"
53
+ hide-error
54
+ @input="onYearInput"
55
+ />
56
+ </div>
57
+ </div>
58
+ <div class="group">
59
+ <div class="label">Quarter</div>
60
+ <div class="input">
61
+ <SInputSelect
62
+ size="mini"
63
+ :options="quarterOptions"
64
+ :model-value="preset.quarter"
65
+ @change="onQuarterChange"
66
+ />
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </template>
71
+
72
+ <style scoped lang="postcss">
73
+ .SDropdownSectionDateRangeYearQuarter {
74
+ display: flex;
75
+ flex-direction: column;
76
+ gap: 8px;
77
+ padding: 8px 0;
78
+ }
79
+
80
+ .group {
81
+ display: flex;
82
+ align-items: center;
83
+ padding: 0 8px 0 16px;
84
+ }
85
+
86
+ .label {
87
+ flex-shrink: 0;
88
+ width: 64px;
89
+ font-size: 12px;
90
+ color: var(--c-text-2);
91
+ }
92
+
93
+ .input {
94
+ flex-grow: 1;
95
+ }
96
+ </style>
@@ -1,23 +1,15 @@
1
1
  <script setup lang="ts">
2
- import { type DropdownSectionMenuOption } from '../composables/Dropdown'
2
+ import SActionList, { type ActionList } from './SActionList.vue'
3
3
 
4
4
  defineProps<{
5
- options: DropdownSectionMenuOption[]
5
+ options: ActionList
6
6
  }>()
7
7
  </script>
8
8
 
9
9
  <template>
10
- <ul class="SDropdownSectionMenu">
11
- <li v-for="option in options" :key="option.label" class="item">
12
- <button
13
- class="button"
14
- @click="option.onClick"
15
- :disabled="option.disabled"
16
- >
17
- {{ option.label }}
18
- </button>
19
- </li>
20
- </ul>
10
+ <div class="SDropdownSectionMenu">
11
+ <SActionList :list="options" />
12
+ </div>
21
13
  </template>
22
14
 
23
15
  <style scoped lang="postcss">
@@ -25,25 +17,4 @@ defineProps<{
25
17
  padding: 8px;
26
18
  background-color: var(--c-bg-elv-3);
27
19
  }
28
-
29
- .button {
30
- display: block;
31
- border-radius: 6px;
32
- padding: 0 8px;
33
- width: 100%;
34
- text-align: left;
35
- line-height: 32px;
36
- font-size: 14px;
37
- font-weight: 400;
38
- transition: color 0.25s, background-color 0.25s;
39
-
40
- &:hover:not(:disabled) {
41
- background-color: var(--c-bg-mute-1);
42
- }
43
-
44
- &:disabled {
45
- color: var(--c-text-3);
46
- cursor: not-allowed;
47
- }
48
- }
49
20
  </style>
@@ -6,12 +6,7 @@ import { isString } from '../support/Utils'
6
6
  import SIcon from './SIcon.vue'
7
7
  import SInputBase from './SInputBase.vue'
8
8
 
9
- export type Size = 'mini' | 'small' | 'medium'
10
- export type Align = 'left' | 'center' | 'right'
11
- export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
12
- export type TextColor = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
13
-
14
- const props = defineProps<{
9
+ export interface Props {
15
10
  size?: Size
16
11
  name?: string
17
12
  label?: string
@@ -32,7 +27,14 @@ const props = defineProps<{
32
27
  displayValue?: string | null
33
28
  hideError?: boolean
34
29
  validation?: Validatable
35
- }>()
30
+ }
31
+
32
+ export type Size = 'mini' | 'small' | 'medium'
33
+ export type Align = 'left' | 'center' | 'right'
34
+ export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
35
+ export type TextColor = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
36
+
37
+ const props = defineProps<Props>()
36
38
 
37
39
  const emit = defineEmits<{
38
40
  (e: 'update:model-value', value: string | null): void