@globalbrain/sefirot 3.24.1 → 3.25.1

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.
@@ -34,6 +34,7 @@ const props = withDefaults(defineProps<{
34
34
  hideError?: boolean
35
35
  validation?: Validatable
36
36
  }>(), {
37
+ size: 'small',
37
38
  imageType: 'rectangle',
38
39
  imageWidth: '96px',
39
40
  imageAspectRatio: '1 / 1',
@@ -1,4 +1,11 @@
1
- <script setup lang="ts">
1
+ <script
2
+ setup
3
+ lang="ts"
4
+ generic="
5
+ T extends string | number | boolean = string | number | boolean,
6
+ Nullable extends boolean = false
7
+ "
8
+ >
2
9
  import { type IconifyIcon } from '@iconify/vue/dist/offline'
3
10
  import { type DefineComponent, computed } from 'vue'
4
11
  import { type Validatable } from '../composables/V'
@@ -8,12 +15,19 @@ import SInputRadio from './SInputRadio.vue'
8
15
  export type Size = 'mini' | 'small' | 'medium'
9
16
  export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
10
17
 
11
- export interface Option {
18
+ export interface Option<
19
+ T extends string | number | boolean = string | number | boolean,
20
+ Nullable extends boolean = false
21
+ > {
12
22
  label: string
13
- value: any
23
+ value: Nullable extends true ? T : T
14
24
  disabled?: boolean
15
25
  }
16
26
 
27
+ type ValueType = Nullable extends true ? T : T
28
+ type ValueOrNull = Nullable extends true ? T | null : T
29
+ type NullValue = Nullable extends true ? null : never
30
+
17
31
  const props = withDefaults(defineProps<{
18
32
  size?: Size
19
33
  name?: string
@@ -24,11 +38,11 @@ const props = withDefaults(defineProps<{
24
38
  checkIcon?: IconifyIcon | DefineComponent
25
39
  checkText?: string
26
40
  checkColor?: Color
27
- options: Option[]
28
- nullable?: boolean
41
+ options: Option<T, Nullable>[]
42
+ nullable?: Nullable
29
43
  disabled?: boolean
30
- value?: any
31
- modelValue?: any
44
+ value?: ValueType | null
45
+ modelValue?: ValueType | null
32
46
  validation?: Validatable
33
47
  hideError?: boolean
34
48
  }>(), {
@@ -37,8 +51,8 @@ const props = withDefaults(defineProps<{
37
51
  })
38
52
 
39
53
  const emit = defineEmits<{
40
- (e: 'update:model-value', value: any): void
41
- (e: 'change', value: any): void
54
+ (e: 'update:model-value', value: ValueOrNull): void
55
+ (e: 'change', value: ValueOrNull): void
42
56
  }>()
43
57
 
44
58
  const _value = computed(() => {
@@ -47,29 +61,29 @@ const _value = computed(() => {
47
61
  : props.value !== undefined ? props.value : null
48
62
  })
49
63
 
50
- function isChecked(value: any) {
64
+ function isChecked(value: ValueType) {
51
65
  return value === _value.value
52
66
  }
53
67
 
54
- function onUpdate(value: any) {
68
+ function onUpdate(value: ValueType) {
55
69
  if (value !== _value.value) {
56
70
  emit('update:model-value', value)
57
71
  return
58
72
  }
59
73
 
60
74
  if (props.nullable) {
61
- emit('update:model-value', null)
75
+ emit('update:model-value', null as NullValue)
62
76
  }
63
77
  }
64
78
 
65
- function onChange(value: any) {
79
+ function onChange(value: ValueType) {
66
80
  if (value !== _value.value) {
67
81
  emit('change', value)
68
82
  return
69
83
  }
70
84
 
71
85
  if (props.nullable) {
72
- emit('change', null)
86
+ emit('change', null as NullValue)
73
87
  }
74
88
  }
75
89
  </script>
@@ -46,6 +46,7 @@
46
46
  .s-shrink { flex-shrink: 1; }
47
47
  .s-shrink-0 { flex-shrink: 0; }
48
48
 
49
+ .s-gap-1 { gap: 1px; }
49
50
  .s-gap-4 { gap: 4px; }
50
51
  .s-gap-8 { gap: 8px; }
51
52
  .s-gap-12 { gap: 12px; }
@@ -2,7 +2,7 @@ import dayjs, { type ConfigType, type Dayjs } from 'dayjs'
2
2
  import PluginRelativeTime from 'dayjs/plugin/relativeTime'
3
3
  import PluginTimezone from 'dayjs/plugin/timezone'
4
4
  import PluginUtc from 'dayjs/plugin/utc'
5
- import { isNumber, isObject, isString } from './Utils'
5
+ import { isNullish, isNumber, isObject, isString } from './Utils'
6
6
 
7
7
  dayjs.extend(PluginUtc)
8
8
  dayjs.extend(PluginTimezone)
@@ -60,35 +60,55 @@ export function tz(input?: Input, timezone?: string): Day {
60
60
  /**
61
61
  * Creates a new `Ymd` object.
62
62
  */
63
+ export function createYmd(year?: number | null, month?: number | null, date?: number | null): Ymd
64
+ export function createYmd(day?: Day | null): Ymd
63
65
  export function createYmd(
64
- year: number | null = null,
66
+ yearOrDay: number | Day | null = null,
65
67
  month: number | null = null,
66
68
  date: number | null = null
67
69
  ): Ymd {
70
+ if (isNumber(yearOrDay) || isNullish(yearOrDay)) {
71
+ return {
72
+ year: yearOrDay,
73
+ month,
74
+ date
75
+ }
76
+ }
77
+
68
78
  return {
69
- year,
70
- month,
71
- date
79
+ year: yearOrDay.year(),
80
+ month: yearOrDay.month() + 1,
81
+ date: yearOrDay.date()
72
82
  }
73
83
  }
74
84
 
75
85
  /**
76
86
  * Creates a new `Hms` object.
77
87
  */
88
+ export function createHms(hour?: string | null, minute?: string | null, second?: string | null): Hms
89
+ export function createHms(day?: Day | null): Hms
78
90
  export function createHms(
79
- hour: string | null = null,
91
+ hourOrDay: string | Day | null = null,
80
92
  minute: string | null = null,
81
93
  second: string | null = null
82
94
  ): Hms {
95
+ if (isString(hourOrDay) || isNullish(hourOrDay)) {
96
+ return {
97
+ hour: hourOrDay,
98
+ minute,
99
+ second
100
+ }
101
+ }
102
+
83
103
  return {
84
- hour,
85
- minute,
86
- second
104
+ hour: hourOrDay.format('HH'),
105
+ minute: hourOrDay.format('mm'),
106
+ second: hourOrDay.format('ss')
87
107
  }
88
108
  }
89
109
 
90
110
  export function isYmd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): value is Ymd {
91
- if (!isObject(value)) {
111
+ if (isNullish(value) || !isObject(value)) {
92
112
  return false
93
113
  }
94
114
 
@@ -101,7 +121,7 @@ export function isYmd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): va
101
121
  }
102
122
 
103
123
  export function isHms(value: unknown, required: HmsType[] = ['h', 'm', 's']): value is Hms {
104
- if (!isObject(value)) {
124
+ if (isNullish(value) || !isObject(value)) {
105
125
  return false
106
126
  }
107
127
 
@@ -1,5 +1,5 @@
1
1
  export function isNullish(value: unknown): value is undefined | null {
2
- return value === null || value === undefined
2
+ return value == null
3
3
  }
4
4
 
5
5
  export function isString(value: unknown): value is string {
@@ -1,6 +1,7 @@
1
1
  import { type ValidationRuleWithParams } from '@vuelidate/core'
2
2
  import { type MessageProps as VMessageProps, helpers } from '@vuelidate/validators'
3
3
  import { type Lang, useLang } from '../composables/Lang'
4
+ import { _required } from './validators'
4
5
 
5
6
  export interface RuleOptions {
6
7
  optional?: boolean
@@ -22,7 +23,7 @@ export function createRule(
22
23
  return options.message({ ...params, lang })
23
24
  },
24
25
  (value) => {
25
- return options.optional && !helpers.req(value)
26
+ return options.optional && !_required(value)
26
27
  ? true
27
28
  : options.validation(value)
28
29
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function decimal(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: (value) => !hyphen(value) && baseDecimal(value)
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function decimalOrHyphen(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: (value) => hyphen(value) || baseDecimal(value)
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function email(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: baseEmail
13
14
  })
14
15
  }
@@ -3,7 +3,7 @@ import { maxLength as baseMaxLength } from '../validators'
3
3
 
4
4
  export const message = {
5
5
  en: (length: number) => `The value must be less than or equal to ${length} characters.`,
6
- ja: (length: number) => `この値は、最大${length}文字までです。`
6
+ ja: (length: number) => `この値は最大${length}文字までです。`
7
7
  }
8
8
 
9
9
  export function maxLength(length: number, msg?: string) {
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function maxValue(max: number, msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang](max),
12
+ optional: true,
12
13
  validation: (value) => baseMaxValue(value, max)
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function minValue(min: number, msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang](min),
12
+ optional: true,
12
13
  validation: (value) => baseMinValue(value, min)
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function negativeInteger(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: baseNegativeInteger
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function positiveInteger(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: basePositiveInteger
13
14
  })
14
15
  }
@@ -11,7 +11,6 @@ export const message = {
11
11
  export function requiredYmd(required?: YmdType[], msg?: string) {
12
12
  return createRule({
13
13
  message: ({ lang }) => msg ?? message[lang],
14
- optional: true,
15
14
  validation: (value) => baseRequiredYmd(value, required)
16
15
  })
17
16
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function url(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: baseUrl
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function zeroOrNegativeInteger(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: (value) => zero(value) || baseNegativeInteger(value)
13
14
  })
14
15
  }
@@ -9,6 +9,7 @@ export const message = {
9
9
  export function zeroOrPositiveInteger(msg?: string) {
10
10
  return createRule({
11
11
  message: ({ lang }) => msg ?? message[lang],
12
+ optional: true,
12
13
  validation: (value) => zero(value) || basePositiveInteger(value)
13
14
  })
14
15
  }
@@ -3,7 +3,7 @@ import { isString } from '../../support/Utils'
3
3
  /* eslint-disable-next-line no-control-regex */
4
4
  const regExp = /^(?:[A-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]{2,}(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)\])$/i
5
5
 
6
- export function email(value: string): boolean {
6
+ export function email(value: unknown): boolean {
7
7
  if (!isString(value)) {
8
8
  return false
9
9
  }
@@ -9,6 +9,10 @@ export function maxTotalFileSize(value: unknown, size: string): boolean {
9
9
  return false
10
10
  }
11
11
 
12
+ if (value.length === 0) {
13
+ return true
14
+ }
15
+
12
16
  const factor = /gb/i.test(size)
13
17
  ? 1e9
14
18
  : /mb/i.test(size)
@@ -1,5 +1,7 @@
1
+ import { isNumber, isString } from '../../support/Utils'
2
+
1
3
  export function maxValue(value: unknown, max: number) {
2
- if (typeof value === 'string' || value instanceof Date) {
4
+ if (isNumber(value) || isString(value) || value instanceof Date) {
3
5
  return +value <= max
4
6
  }
5
7
 
@@ -1,5 +1,7 @@
1
+ import { isNumber, isString } from '../../support/Utils'
2
+
1
3
  export function minValue(value: unknown, min: number) {
2
- if (typeof value === 'string' || value instanceof Date) {
4
+ if (isNumber(value) || isString(value) || value instanceof Date) {
3
5
  return +value >= min
4
6
  }
5
7
 
@@ -1,6 +1,14 @@
1
1
  import { isArray, isNullish, isString } from '../../support/Utils'
2
2
 
3
3
  export function required(value: unknown): boolean {
4
+ if (isString(value)) {
5
+ value = value.trim()
6
+ }
7
+
8
+ return _required(value)
9
+ }
10
+
11
+ export function _required(value: unknown): boolean {
4
12
  if (isArray(value)) {
5
13
  return !!value.length
6
14
  }
@@ -17,9 +25,5 @@ export function required(value: unknown): boolean {
17
25
  return !Number.isNaN(value.getTime())
18
26
  }
19
27
 
20
- if (isString(value)) {
21
- value = value.trim()
22
- }
23
-
24
28
  return !!String(value).length
25
29
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "3.24.1",
4
- "packageManager": "pnpm@8.14.1",
3
+ "version": "3.25.1",
4
+ "packageManager": "pnpm@8.14.3",
5
5
  "description": "Vue Components for Global Brain Design System.",
6
6
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",
7
7
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "@types/markdown-it": "^13.0.7",
47
47
  "@vuelidate/core": "^2.0.3",
48
48
  "@vuelidate/validators": "^2.0.4",
49
- "@vueuse/core": "^10.7.1",
49
+ "@vueuse/core": "^10.7.2",
50
50
  "body-scroll-lock": "4.0.0-beta.0",
51
51
  "fuse.js": "^7.0.0",
52
52
  "lodash-es": "^4.17.21",
@@ -56,7 +56,7 @@
56
56
  "postcss": "^8.4.33",
57
57
  "postcss-nested": "^6.0.1",
58
58
  "v-calendar": "^3.1.2",
59
- "vue": "^3.4.10",
59
+ "vue": "^3.4.15",
60
60
  "vue-router": "^4.2.5"
61
61
  },
62
62
  "dependencies": {
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "devDependencies": {
74
74
  "@globalbrain/eslint-config": "^1.5.2",
75
- "@histoire/plugin-vue": "^0.17.6",
75
+ "@histoire/plugin-vue": "^0.17.8",
76
76
  "@iconify-icons/ph": "^1.2.5",
77
77
  "@iconify-icons/ri": "^1.2.10",
78
78
  "@iconify/vue": "^4.1.1",
@@ -80,18 +80,18 @@
80
80
  "@types/body-scroll-lock": "^3.1.2",
81
81
  "@types/lodash-es": "^4.17.12",
82
82
  "@types/markdown-it": "^13.0.7",
83
- "@types/node": "^20.11.0",
83
+ "@types/node": "^20.11.6",
84
84
  "@vitejs/plugin-vue": "^5.0.3",
85
- "@vitest/coverage-v8": "^1.1.3",
85
+ "@vitest/coverage-v8": "^1.2.1",
86
86
  "@vue/test-utils": "^2.4.3",
87
87
  "@vuelidate/core": "^2.0.3",
88
88
  "@vuelidate/validators": "^2.0.4",
89
- "@vueuse/core": "^10.7.1",
89
+ "@vueuse/core": "^10.7.2",
90
90
  "body-scroll-lock": "4.0.0-beta.0",
91
91
  "eslint": "^8.56.0",
92
92
  "fuse.js": "^7.0.0",
93
- "happy-dom": "^13.0.2",
94
- "histoire": "^0.17.6",
93
+ "happy-dom": "^13.3.1",
94
+ "histoire": "^0.17.8",
95
95
  "lodash-es": "^4.17.21",
96
96
  "markdown-it": "^14.0.0",
97
97
  "normalize.css": "^8.0.1",
@@ -99,13 +99,13 @@
99
99
  "postcss": "^8.4.33",
100
100
  "postcss-nested": "^6.0.1",
101
101
  "punycode": "^2.3.1",
102
- "release-it": "^17.0.1",
102
+ "release-it": "^17.0.3",
103
103
  "typescript": "~5.3.3",
104
104
  "v-calendar": "^3.1.2",
105
- "vite": "^5.0.11",
106
- "vitepress": "1.0.0-rc.36",
107
- "vitest": "^1.1.3",
108
- "vue": "^3.4.10",
105
+ "vite": "^5.0.12",
106
+ "vitepress": "1.0.0-rc.40",
107
+ "vitest": "^1.2.1",
108
+ "vue": "^3.4.15",
109
109
  "vue-router": "^4.2.5",
110
110
  "vue-tsc": "^1.8.27"
111
111
  }