@globalbrain/sefirot 3.22.1 → 3.24.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.
- package/lib/components/SInputAddon.vue +3 -3
- package/lib/components/STableCellNumber.vue +1 -1
- package/lib/composables/Api.ts +1 -1
- package/lib/http/Http.ts +44 -22
- package/lib/support/Day.ts +43 -0
- package/lib/validation/Rule.ts +1 -1
- package/lib/validation/rules/checked.ts +11 -5
- package/lib/validation/rules/decimal.ts +11 -6
- package/lib/validation/rules/decimalOrHyphen.ts +11 -5
- package/lib/validation/rules/email.ts +11 -5
- package/lib/validation/rules/fileExtension.ts +11 -7
- package/lib/validation/rules/hms.ts +11 -8
- package/lib/validation/rules/maxFileSize.ts +11 -12
- package/lib/validation/rules/maxLength.ts +12 -7
- package/lib/validation/rules/maxTotalFileSize.ts +11 -12
- package/lib/validation/rules/maxValue.ts +12 -8
- package/lib/validation/rules/minLength.ts +12 -7
- package/lib/validation/rules/minValue.ts +12 -8
- package/lib/validation/rules/month.ts +12 -8
- package/lib/validation/rules/negativeInteger.ts +10 -5
- package/lib/validation/rules/positiveInteger.ts +10 -5
- package/lib/validation/rules/required.ts +1 -1
- package/lib/validation/rules/requiredHms.ts +10 -8
- package/lib/validation/rules/requiredIf.ts +12 -6
- package/lib/validation/rules/requiredYmd.ts +11 -8
- package/lib/validation/rules/rule.ts +12 -6
- package/lib/validation/rules/url.ts +11 -5
- package/lib/validation/rules/ymd.ts +11 -8
- package/lib/validation/rules/zeroOrNegativeInteger.ts +11 -6
- package/lib/validation/rules/zeroOrPositiveInteger.ts +11 -6
- package/lib/validation/validators/checked.ts +1 -1
- package/lib/validation/validators/decimal.ts +11 -0
- package/lib/validation/validators/email.ts +12 -0
- package/lib/validation/validators/fileExtension.ts +7 -2
- package/lib/validation/validators/hms.ts +8 -12
- package/lib/validation/validators/hyphen.ts +1 -1
- package/lib/validation/validators/index.ts +8 -0
- package/lib/validation/validators/maxFileSize.ts +9 -2
- package/lib/validation/validators/maxLength.ts +9 -0
- package/lib/validation/validators/maxTotalFileSize.ts +12 -2
- package/lib/validation/validators/maxValue.ts +7 -0
- package/lib/validation/validators/minLength.ts +9 -0
- package/lib/validation/validators/minValue.ts +7 -0
- package/lib/validation/validators/month.ts +7 -1
- package/lib/validation/validators/negativeInteger.ts +7 -1
- package/lib/validation/validators/positiveInteger.ts +7 -1
- package/lib/validation/validators/requiredHms.ts +6 -10
- package/lib/validation/validators/requiredIf.ts +19 -0
- package/lib/validation/validators/requiredYmd.ts +6 -10
- package/lib/validation/validators/url.ts +11 -0
- package/lib/validation/validators/ymd.ts +11 -15
- package/lib/validation/validators/zero.ts +1 -1
- package/package.json +11 -11
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import IconCaretDown from '@iconify-icons/ph/caret-down-bold'
|
|
3
|
+
import { computed, ref } from 'vue'
|
|
3
4
|
import {
|
|
4
5
|
type DropdownSection,
|
|
5
6
|
getSelectedOption,
|
|
6
7
|
useManualDropdownPosition
|
|
7
|
-
} from '
|
|
8
|
-
import { useFlyout } from '
|
|
9
|
-
import { computed, ref } from 'vue'
|
|
8
|
+
} from '../composables/Dropdown'
|
|
9
|
+
import { useFlyout } from '../composables/Flyout'
|
|
10
10
|
import { isString } from '../support/Utils'
|
|
11
11
|
import SDropdown from './SDropdown.vue'
|
|
12
12
|
import SIcon from './SIcon.vue'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { format } from 'sefirot/support/Num'
|
|
3
2
|
import { computed } from 'vue'
|
|
4
3
|
import { type TableCellValueColor } from '../composables/Table'
|
|
4
|
+
import { format } from '../support/Num'
|
|
5
5
|
import SIcon from './SIcon.vue'
|
|
6
6
|
import SLink from './SLink.vue'
|
|
7
7
|
|
package/lib/composables/Api.ts
CHANGED
package/lib/http/Http.ts
CHANGED
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
import { parse as parseContentDisposition } from '@tinyhttp/content-disposition'
|
|
2
2
|
import { parse as parseCookie } from '@tinyhttp/cookie'
|
|
3
3
|
import FileSaver from 'file-saver'
|
|
4
|
-
import {
|
|
4
|
+
import { type FetchOptions, type FetchRequest, type FetchResponse, ofetch } from 'ofetch'
|
|
5
5
|
import { stringify } from 'qs'
|
|
6
6
|
|
|
7
|
+
export interface HttpClient {
|
|
8
|
+
<T = any>(request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<T>
|
|
9
|
+
raw<T = any>(request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<FetchResponse<T>>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HttpOptions {
|
|
13
|
+
baseUrl?: string
|
|
14
|
+
xsrfUrl?: string | false
|
|
15
|
+
client?: HttpClient
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
export class Http {
|
|
8
|
-
static
|
|
9
|
-
static xsrfUrl: string | false = '/api/csrf-cookie'
|
|
19
|
+
private static baseUrl: string | undefined = undefined
|
|
20
|
+
private static xsrfUrl: string | false = '/api/csrf-cookie'
|
|
21
|
+
private static client: HttpClient = ofetch
|
|
22
|
+
|
|
23
|
+
static config(options: HttpOptions) {
|
|
24
|
+
if (options.baseUrl) {
|
|
25
|
+
Http.baseUrl = options.baseUrl
|
|
26
|
+
}
|
|
27
|
+
if (options.xsrfUrl !== undefined) {
|
|
28
|
+
Http.xsrfUrl = options.xsrfUrl
|
|
29
|
+
}
|
|
30
|
+
if (options.client) {
|
|
31
|
+
Http.client = options.client
|
|
32
|
+
}
|
|
33
|
+
}
|
|
10
34
|
|
|
11
35
|
private async ensureXsrfToken(): Promise<string | undefined> {
|
|
12
36
|
if (!Http.xsrfUrl) {
|
|
@@ -40,7 +64,7 @@ export class Http {
|
|
|
40
64
|
return [
|
|
41
65
|
`${url}${queryString ? `?${queryString}` : ''}`,
|
|
42
66
|
{
|
|
43
|
-
baseURL: Http.
|
|
67
|
+
baseURL: Http.baseUrl,
|
|
44
68
|
method,
|
|
45
69
|
credentials: 'include',
|
|
46
70
|
...options,
|
|
@@ -54,11 +78,11 @@ export class Http {
|
|
|
54
78
|
}
|
|
55
79
|
|
|
56
80
|
private async performRequest<T>(url: string, options: FetchOptions = {}) {
|
|
57
|
-
return
|
|
81
|
+
return Http.client<T>(...(await this.buildRequest(url, options)))
|
|
58
82
|
}
|
|
59
83
|
|
|
60
84
|
private async performRequestRaw<T>(url: string, options: FetchOptions = {}) {
|
|
61
|
-
return
|
|
85
|
+
return Http.client.raw<T>(...(await this.buildRequest(url, options)))
|
|
62
86
|
}
|
|
63
87
|
|
|
64
88
|
async get<T = any>(url: string, options?: FetchOptions): Promise<T> {
|
|
@@ -116,25 +140,23 @@ export class Http {
|
|
|
116
140
|
const fd = form || new FormData()
|
|
117
141
|
let formKey: string
|
|
118
142
|
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
143
|
+
Object.keys(obj).forEach((property) => {
|
|
144
|
+
if (namespace) {
|
|
145
|
+
formKey = `${namespace}[${property}]`
|
|
146
|
+
} else {
|
|
147
|
+
formKey = property
|
|
148
|
+
}
|
|
126
149
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
150
|
+
if (obj[property] === undefined) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
130
153
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
154
|
+
if (typeof obj[property] === 'object' && !(obj[property] instanceof Blob)) {
|
|
155
|
+
this.objectToFormData(obj[property], fd, property)
|
|
156
|
+
} else {
|
|
157
|
+
fd.append(formKey, obj[property])
|
|
136
158
|
}
|
|
137
|
-
}
|
|
159
|
+
})
|
|
138
160
|
|
|
139
161
|
return fd
|
|
140
162
|
}
|
package/lib/support/Day.ts
CHANGED
|
@@ -2,6 +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
6
|
|
|
6
7
|
dayjs.extend(PluginUtc)
|
|
7
8
|
dayjs.extend(PluginTimezone)
|
|
@@ -19,6 +20,14 @@ export interface Ymd {
|
|
|
19
20
|
date: number | null
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
export type YmdType = 'y' | 'm' | 'd'
|
|
24
|
+
|
|
25
|
+
export const YmdMap = {
|
|
26
|
+
y: 'year',
|
|
27
|
+
m: 'month',
|
|
28
|
+
d: 'date'
|
|
29
|
+
} as const
|
|
30
|
+
|
|
22
31
|
/**
|
|
23
32
|
* The hour, minute, and second object interface.
|
|
24
33
|
*/
|
|
@@ -28,6 +37,14 @@ export interface Hms {
|
|
|
28
37
|
second: string | null
|
|
29
38
|
}
|
|
30
39
|
|
|
40
|
+
export type HmsType = 'h' | 'm' | 's'
|
|
41
|
+
|
|
42
|
+
export const HmsMap = {
|
|
43
|
+
h: 'hour',
|
|
44
|
+
m: 'minute',
|
|
45
|
+
s: 'second'
|
|
46
|
+
} as const
|
|
47
|
+
|
|
31
48
|
export function day(input?: Input): Day {
|
|
32
49
|
return dayjs(input)
|
|
33
50
|
}
|
|
@@ -69,3 +86,29 @@ export function createHms(
|
|
|
69
86
|
second
|
|
70
87
|
}
|
|
71
88
|
}
|
|
89
|
+
|
|
90
|
+
export function isYmd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): value is Ymd {
|
|
91
|
+
if (!isObject(value)) {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return required
|
|
96
|
+
.reduce<string[]>((keys, type) => {
|
|
97
|
+
keys.push(YmdMap[type])
|
|
98
|
+
return keys
|
|
99
|
+
}, [])
|
|
100
|
+
.every((key) => value[key] === null || isNumber(value[key]))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function isHms(value: unknown, required: HmsType[] = ['h', 'm', 's']): value is Hms {
|
|
104
|
+
if (!isObject(value)) {
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return required
|
|
109
|
+
.reduce<string[]>((keys, type) => {
|
|
110
|
+
keys.push(HmsMap[type])
|
|
111
|
+
return keys
|
|
112
|
+
}, [])
|
|
113
|
+
.every((key) => value[key] === null || isString(value[key]))
|
|
114
|
+
}
|
package/lib/validation/Rule.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type Lang, useLang } from '../composables/Lang'
|
|
|
5
5
|
export interface RuleOptions {
|
|
6
6
|
optional?: boolean
|
|
7
7
|
message(params: MessageProps): string
|
|
8
|
-
validation(value: unknown): boolean
|
|
8
|
+
validation(value: unknown): boolean | Promise<boolean>
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface MessageProps extends VMessageProps {
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { checked as baseChecked } from '../validators/checked'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'You must check the field.',
|
|
6
|
+
ja: 'この項目は選択が必須です。'
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function checked(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: baseChecked
|
|
14
|
+
})
|
|
9
15
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { hyphen } from '../validators'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { decimal as baseDecimal, hyphen } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be valid decimal numbers.',
|
|
6
|
+
ja: 'この値は小数または10進数である必要があります。'
|
|
7
|
+
}
|
|
3
8
|
|
|
4
9
|
export function decimal(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: (value) => !hyphen(value) && baseDecimal(value)
|
|
13
|
+
})
|
|
9
14
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { decimal as baseDecimal, hyphen } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be valid decimal numbers or just a hyphen.',
|
|
6
|
+
ja: 'この値は小数、10進数、またはハイフンである必要があります。'
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function decimalOrHyphen(msg?: string) {
|
|
4
|
-
return
|
|
5
|
-
() => msg ??
|
|
6
|
-
baseDecimal
|
|
7
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: (value) => hyphen(value) || baseDecimal(value)
|
|
13
|
+
})
|
|
8
14
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { email as baseEmail } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The Email is invalid.',
|
|
6
|
+
ja: 'Emailの形式が正しくありません。'
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function email(msg?: string) {
|
|
4
|
-
return
|
|
5
|
-
() => msg ??
|
|
6
|
-
baseEmail
|
|
7
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: baseEmail
|
|
13
|
+
})
|
|
8
14
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { fileExtension as baseFileExtension } from '../validators/fileExtension'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The file extension is invalid.',
|
|
6
|
+
ja: 'ファイル拡張子が正しくありません。'
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function fileExtension(extensions: string[], msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: (value) => baseFileExtension(value, extensions)
|
|
14
|
+
})
|
|
11
15
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Hms } from '../../support/Day'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
3
2
|
import { hms as baseHms } from '../validators/hms'
|
|
4
3
|
|
|
5
4
|
type HmsType = 'h' | 'm' | 's'
|
|
6
5
|
|
|
6
|
+
export const message = {
|
|
7
|
+
en: 'The time is invalid.',
|
|
8
|
+
ja: '時間表記が正しくありません。'
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
export function hms(required?: HmsType[], msg?: string) {
|
|
8
|
-
return
|
|
9
|
-
() => msg ??
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
12
|
+
return createRule({
|
|
13
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
14
|
+
optional: true,
|
|
15
|
+
validation: (value) => baseHms(value, required)
|
|
16
|
+
})
|
|
14
17
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { maxFileSize as baseMaxFileSize } from '../validators/maxFileSize'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (size: string) => `The file must be smaller than or equal to ${size}.`,
|
|
6
|
+
ja: (size: string) => `ファイルは${size}よりも小さい必要があります。`
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function maxFileSize(size: string, msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
(value: File) => {
|
|
12
|
-
return !helpers.req(value) || baseMaxFileSize(value, size)
|
|
13
|
-
}
|
|
14
|
-
)
|
|
15
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](size),
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: (value) => baseMaxFileSize(value, size)
|
|
14
|
+
})
|
|
16
15
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { maxLength as baseMaxLength } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (length: number) => `The value must be less than or equal to ${length} characters.`,
|
|
6
|
+
ja: (length: number) => `この値は、最大${length}文字までです。`
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function maxLength(length: number, msg?: string) {
|
|
4
|
-
return
|
|
5
|
-
({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](length),
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: (value) => baseMaxLength(value, length)
|
|
14
|
+
})
|
|
10
15
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { maxTotalFileSize as baseMaxTotalFileSize } from '../validators/maxTotalFileSize'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (size: string) => `The total file size must be smaller than or equal to ${size}.`,
|
|
6
|
+
ja: (size: string) => `合計ファイルサイズは最大${size}までです。`
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function maxTotalFileSize(size: string, msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
(files: File[]) => {
|
|
12
|
-
return !helpers.req(files) || baseMaxTotalFileSize(files, size)
|
|
13
|
-
}
|
|
14
|
-
)
|
|
15
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](size),
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: (value) => baseMaxTotalFileSize(value, size)
|
|
14
|
+
})
|
|
16
15
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { maxValue as baseMaxValue } from '../validators'
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (max: number) => `The value must be less than or equal to ${max}.`,
|
|
6
|
+
ja: (max: number) => `この値は最大${max}です。`
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function maxValue(max: number, msg?: string) {
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](max),
|
|
12
|
+
validation: (value) => baseMaxValue(value, max)
|
|
13
|
+
})
|
|
10
14
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { minLength as baseMinLength } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (min: number) => `The value must be greater than or equal to ${min} characters.`,
|
|
6
|
+
ja: (min: number) => `この値は最小${min}文字です。`
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function minLength(length: number, msg?: string) {
|
|
4
|
-
return
|
|
5
|
-
({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](length),
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: (value) => baseMinLength(value, length)
|
|
14
|
+
})
|
|
10
15
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { minValue as baseMinValue } from '../validators'
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
export const message = {
|
|
5
|
+
en: (min: number) => `The value must be greater than or equal to ${min}.`,
|
|
6
|
+
ja: (min: number) => `この値は最大${min}です。`
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function minValue(min: number, msg?: string) {
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang](min),
|
|
12
|
+
validation: (value) => baseMinValue(value, min)
|
|
13
|
+
})
|
|
10
14
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { month as baseMonth } from '../validators
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { month as baseMonth } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The month is invalid.',
|
|
6
|
+
ja: '月が正しくありません。'
|
|
7
|
+
}
|
|
3
8
|
|
|
4
9
|
export function month(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: baseMonth
|
|
14
|
+
})
|
|
11
15
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { negativeInteger as baseNegativeInteger } from '../validators'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be valid negative integer.',
|
|
6
|
+
ja: 'この値は負の整数である必要があります。'
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function negativeInteger(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
baseNegativeInteger
|
|
8
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: baseNegativeInteger
|
|
13
|
+
})
|
|
9
14
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
import { positiveInteger as basePositiveInteger } from '../validators'
|
|
3
3
|
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be valid positive integer.',
|
|
6
|
+
ja: 'この値は正の整数である必要があります。'
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export function positiveInteger(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
basePositiveInteger
|
|
8
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: basePositiveInteger
|
|
13
|
+
})
|
|
9
14
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Hms } from '../../support/Day'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
3
2
|
import { requiredHms as baseRequiredHms } from '../validators/requiredHms'
|
|
4
3
|
|
|
5
4
|
type HmsType = 'h' | 'm' | 's'
|
|
6
5
|
|
|
6
|
+
export const message = {
|
|
7
|
+
en: 'The field is required.',
|
|
8
|
+
ja: 'この項目は必須です。'
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
export function requiredHms(required?: HmsType[], msg?: string) {
|
|
8
|
-
return
|
|
9
|
-
() => msg ??
|
|
10
|
-
(value
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
)
|
|
12
|
+
return createRule({
|
|
13
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
14
|
+
validation: (value) => baseRequiredHms(value, required)
|
|
15
|
+
})
|
|
14
16
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { type RequiredIfCondition, requiredIf as baseRequiredIf } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The field is required.',
|
|
6
|
+
ja: 'この項目は必須です。'
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function requiredIf(
|
|
4
|
-
|
|
10
|
+
condition: RequiredIfCondition,
|
|
5
11
|
msg?: string
|
|
6
12
|
) {
|
|
7
|
-
return
|
|
8
|
-
() => msg ??
|
|
9
|
-
baseRequiredIf(
|
|
10
|
-
)
|
|
13
|
+
return createRule({
|
|
14
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
15
|
+
validation: (value) => baseRequiredIf(value, condition)
|
|
16
|
+
})
|
|
11
17
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Ymd } from '../../support/Day'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
3
2
|
import { requiredYmd as baseRequiredYmd } from '../validators/requiredYmd'
|
|
4
3
|
|
|
5
4
|
type YmdType = 'y' | 'm' | 'd'
|
|
6
5
|
|
|
6
|
+
export const message = {
|
|
7
|
+
en: 'The field is required.',
|
|
8
|
+
ja: 'この項目は必須です。'
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
export function requiredYmd(required?: YmdType[], msg?: string) {
|
|
8
|
-
return
|
|
9
|
-
() => msg ??
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
12
|
+
return createRule({
|
|
13
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
14
|
+
optional: true,
|
|
15
|
+
validation: (value) => baseRequiredYmd(value, required)
|
|
16
|
+
})
|
|
14
17
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export const message = {
|
|
4
|
+
en: 'The value is invalid.',
|
|
5
|
+
ja: 'この値は正しくありません。'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function rule(validation: (value: unknown) => boolean, msg?: string) {
|
|
9
|
+
return createRule({
|
|
10
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
11
|
+
optional: true,
|
|
12
|
+
validation: (value) => validation(value)
|
|
13
|
+
})
|
|
8
14
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { url as baseUrl } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The URL is invalid.',
|
|
6
|
+
ja: 'URLの形式が正しくありません。'
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export function url(msg?: string) {
|
|
4
|
-
return
|
|
5
|
-
() => msg ??
|
|
6
|
-
baseUrl
|
|
7
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: baseUrl
|
|
13
|
+
})
|
|
8
14
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Ymd } from '../../support/Day'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
3
2
|
import { ymd as baseYmd } from '../validators/ymd'
|
|
4
3
|
|
|
5
4
|
type YmdType = 'y' | 'm' | 'd'
|
|
6
5
|
|
|
6
|
+
export const message = {
|
|
7
|
+
en: 'The field is required.',
|
|
8
|
+
ja: 'この項目は必須です。'
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
export function ymd(required?: YmdType[], msg?: string) {
|
|
8
|
-
return
|
|
9
|
-
() => msg ??
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
12
|
+
return createRule({
|
|
13
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
14
|
+
optional: true,
|
|
15
|
+
validation: (value) => baseYmd(value, required)
|
|
16
|
+
})
|
|
14
17
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { negativeInteger, zero } from '../validators'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { negativeInteger as baseNegativeInteger, zero } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be zero or valid negative integer.',
|
|
6
|
+
ja: 'この値はゼロまたは負の整数である必要があります。'
|
|
7
|
+
}
|
|
3
8
|
|
|
4
9
|
export function zeroOrNegativeInteger(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: (value) => zero(value) || baseNegativeInteger(value)
|
|
13
|
+
})
|
|
9
14
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { positiveInteger, zero } from '../validators'
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { positiveInteger as basePositiveInteger, zero } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The value must be zero or valid positive integer.',
|
|
6
|
+
ja: 'この値はゼロまたは正の整数である必要があります。'
|
|
7
|
+
}
|
|
3
8
|
|
|
4
9
|
export function zeroOrPositiveInteger(msg?: string) {
|
|
5
|
-
return
|
|
6
|
-
() => msg ??
|
|
7
|
-
|
|
8
|
-
)
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
validation: (value) => zero(value) || basePositiveInteger(value)
|
|
13
|
+
})
|
|
9
14
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isNumber, isString } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
const regExp = /^[-]?\d*(\.\d+)?$/
|
|
4
|
+
|
|
5
|
+
export function decimal(value: unknown): boolean {
|
|
6
|
+
if (!(isString(value) || isNumber(value))) {
|
|
7
|
+
return false
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return regExp.test(String(value))
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { isString } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
/* eslint-disable-next-line no-control-regex */
|
|
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
|
+
|
|
6
|
+
export function email(value: string): boolean {
|
|
7
|
+
if (!isString(value)) {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return regExp.test(value)
|
|
12
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { getExtension } from '../../support/File'
|
|
2
|
+
import { isFile } from '../../support/Utils'
|
|
2
3
|
|
|
3
|
-
export function fileExtension(
|
|
4
|
-
|
|
4
|
+
export function fileExtension(value: unknown, extensions: string[]): boolean {
|
|
5
|
+
if (!isFile(value)) {
|
|
6
|
+
return false
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const fileExtension = getExtension(value)
|
|
5
10
|
|
|
6
11
|
return extensions.some((extension) => {
|
|
7
12
|
// If the extention option is `jpg`, we'll consider other variants such as
|
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { HmsMap, type HmsType, isHms } from '../../support/Day'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export function hms(value: unknown, required: HmsType[] = ['h', 'm', 's']): boolean {
|
|
4
|
+
if (!isHms(value, required)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
4
7
|
|
|
5
|
-
const HmsMap = {
|
|
6
|
-
h: 'hour',
|
|
7
|
-
m: 'minute',
|
|
8
|
-
s: 'second'
|
|
9
|
-
} as const
|
|
10
|
-
|
|
11
|
-
export function hms(hms: Hms, required: HmsType[] = ['h', 'm', 's']): boolean {
|
|
12
8
|
return required.every((r) => {
|
|
13
|
-
const
|
|
9
|
+
const _value = value[HmsMap[r]]
|
|
14
10
|
|
|
15
|
-
if (
|
|
11
|
+
if (_value === null) {
|
|
16
12
|
return true
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
const valueAsNumber = Number(
|
|
15
|
+
const valueAsNumber = Number(_value)
|
|
20
16
|
|
|
21
17
|
return (r === 'h')
|
|
22
18
|
? (valueAsNumber >= 0 && valueAsNumber < 24)
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
export * from './checked'
|
|
2
|
+
export * from './decimal'
|
|
3
|
+
export * from './email'
|
|
2
4
|
export * from './fileExtension'
|
|
3
5
|
export * from './hms'
|
|
4
6
|
export * from './hyphen'
|
|
5
7
|
export * from './maxFileSize'
|
|
8
|
+
export * from './maxLength'
|
|
6
9
|
export * from './maxTotalFileSize'
|
|
10
|
+
export * from './maxValue'
|
|
11
|
+
export * from './minLength'
|
|
12
|
+
export * from './minValue'
|
|
7
13
|
export * from './month'
|
|
8
14
|
export * from './negativeInteger'
|
|
9
15
|
export * from './positiveInteger'
|
|
10
16
|
export * from './required'
|
|
11
17
|
export * from './requiredHms'
|
|
18
|
+
export * from './requiredIf'
|
|
12
19
|
export * from './requiredYmd'
|
|
20
|
+
export * from './url'
|
|
13
21
|
export * from './ymd'
|
|
14
22
|
export * from './zero'
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { isFile } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
export function maxFileSize(value: unknown, size: string): boolean {
|
|
4
|
+
if (!isFile(value)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
7
|
+
|
|
2
8
|
const factor = /gb/i.test(size)
|
|
3
9
|
? 1e9
|
|
4
10
|
: /mb/i.test(size)
|
|
@@ -6,5 +12,6 @@ export function maxFileSize(file: File, size: string): boolean {
|
|
|
6
12
|
: /kb/i.test(size)
|
|
7
13
|
? 1e3
|
|
8
14
|
: 1
|
|
9
|
-
|
|
15
|
+
|
|
16
|
+
return value.size <= factor * +size.replace(/[^\d\.]/g, '')
|
|
10
17
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { isFile } from '../../support/Utils'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Validates if the total size of the given files is smaller than the
|
|
3
5
|
* given size.
|
|
4
6
|
*/
|
|
5
|
-
export function maxTotalFileSize(
|
|
7
|
+
export function maxTotalFileSize(value: unknown, size: string): boolean {
|
|
8
|
+
if (!isArrayOfFiles(value)) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
const factor = /gb/i.test(size)
|
|
7
13
|
? 1e9
|
|
8
14
|
: /mb/i.test(size)
|
|
@@ -11,7 +17,11 @@ export function maxTotalFileSize(files: File[], size: string): boolean {
|
|
|
11
17
|
? 1e3
|
|
12
18
|
: 1
|
|
13
19
|
|
|
14
|
-
const total =
|
|
20
|
+
const total = value.reduce((total, file) => total + file.size, 0)
|
|
15
21
|
|
|
16
22
|
return total <= factor * +size.replace(/[^\d\.]/g, '')
|
|
17
23
|
}
|
|
24
|
+
|
|
25
|
+
function isArrayOfFiles(value: unknown): value is File[] {
|
|
26
|
+
return Array.isArray(value) && value.every((v) => isFile(v))
|
|
27
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { isNumber } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
export function negativeInteger(value: unknown): boolean {
|
|
4
|
+
if (!isNumber(value)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
7
|
+
|
|
2
8
|
return Number.isInteger(value) && value < 0
|
|
3
9
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { isNumber } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
export function positiveInteger(value: unknown): boolean {
|
|
4
|
+
if (!isNumber(value)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
7
|
+
|
|
2
8
|
return Number.isInteger(value) && value > 0
|
|
3
9
|
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { HmsMap, type HmsType, isHms } from '../../support/Day'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export function requiredHms(value: unknown, required: HmsType[] = ['h', 'm', 's']): boolean {
|
|
4
|
+
if (!isHms(value, required)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
h: 'hour',
|
|
7
|
-
m: 'minute',
|
|
8
|
-
s: 'second'
|
|
9
|
-
} as const
|
|
10
|
-
|
|
11
|
-
export function requiredHms(hms: Hms, required: HmsType[] = ['h', 'm', 's']): boolean {
|
|
12
|
-
return required.every((r) => hms[HmsMap[r]] != null)
|
|
8
|
+
return required.every((r) => value[HmsMap[r]] != null)
|
|
13
9
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { required } from './required'
|
|
2
|
+
|
|
3
|
+
export type RequiredIfCondition = boolean | string | (() => boolean) | (() => Promise<boolean>)
|
|
4
|
+
|
|
5
|
+
export async function requiredIf(value: unknown, condition: RequiredIfCondition): Promise<boolean> {
|
|
6
|
+
if (typeof condition === 'boolean' && condition) {
|
|
7
|
+
return required(value)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (typeof condition === 'string' && condition) {
|
|
11
|
+
return required(value)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (typeof condition === 'function' && (await condition())) {
|
|
15
|
+
return required(value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { YmdMap, type YmdType, isYmd } from '../../support/Day'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export function requiredYmd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): boolean {
|
|
4
|
+
if (!isYmd(value, required)) {
|
|
5
|
+
return false
|
|
6
|
+
}
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
y: 'year',
|
|
7
|
-
m: 'month',
|
|
8
|
-
d: 'date'
|
|
9
|
-
} as const
|
|
10
|
-
|
|
11
|
-
export function requiredYmd(ymd: Ymd, required: YmdType[] = ['y', 'm', 'd']): boolean {
|
|
12
|
-
return required.every((r) => ymd[YmdMap[r]] != null)
|
|
8
|
+
return required.every((r) => value[YmdMap[r]] != null)
|
|
13
9
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isString } from '../../support/Utils'
|
|
2
|
+
|
|
3
|
+
const regExp = /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00A1-\uFFFF][a-z0-9\u00A1-\uFFFF_-]{0,62})?[a-z0-9\u00A1-\uFFFF]\.)+(?:[a-z\u00A1-\uFFFF]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i
|
|
4
|
+
|
|
5
|
+
export function url(value: unknown): boolean {
|
|
6
|
+
if (!isString(value)) {
|
|
7
|
+
return false
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return regExp.test(value)
|
|
11
|
+
}
|
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
import day from 'dayjs'
|
|
2
|
-
import { type
|
|
2
|
+
import { YmdMap, type YmdType, isYmd } from '../../support/Day'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export function ymd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): boolean {
|
|
5
|
+
if (!isYmd(value, required)) {
|
|
6
|
+
return false
|
|
7
|
+
}
|
|
5
8
|
|
|
6
|
-
const YmdMap = {
|
|
7
|
-
y: 'year',
|
|
8
|
-
m: 'month',
|
|
9
|
-
d: 'date'
|
|
10
|
-
} as const
|
|
11
|
-
|
|
12
|
-
export function ymd(ymd: Ymd, required: YmdType[] = ['y', 'm', 'd']): boolean {
|
|
13
9
|
return required.every((r) => {
|
|
14
|
-
const
|
|
10
|
+
const _value = value[YmdMap[r]]
|
|
15
11
|
|
|
16
|
-
if (
|
|
12
|
+
if (_value === null) {
|
|
17
13
|
return true
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
if (r === 'y') {
|
|
21
|
-
return
|
|
17
|
+
return _value > 0 && _value <= 9999
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
if (r === 'm') {
|
|
25
|
-
return
|
|
21
|
+
return _value > 0 && _value <= 12
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
const d = day(new Date(2020,
|
|
24
|
+
const d = day(new Date(2020, value.month ? value.month - 1 : 1, _value))
|
|
29
25
|
|
|
30
|
-
if (d.month() + 1 !== (
|
|
26
|
+
if (d.month() + 1 !== (value.month ?? 1)) {
|
|
31
27
|
return false
|
|
32
28
|
}
|
|
33
29
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globalbrain/sefirot",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"packageManager": "pnpm@8.14.
|
|
3
|
+
"version": "3.24.0",
|
|
4
|
+
"packageManager": "pnpm@8.14.1",
|
|
5
5
|
"description": "Vue Components for Global Brain Design System.",
|
|
6
6
|
"author": "Kia Ishii <ka.ishii@globalbrains.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -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.
|
|
59
|
+
"vue": "^3.4.10",
|
|
60
60
|
"vue-router": "^4.2.5"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
@@ -80,9 +80,9 @@
|
|
|
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.
|
|
84
|
-
"@vitejs/plugin-vue": "^5.0.
|
|
85
|
-
"@vitest/coverage-v8": "^1.1.
|
|
83
|
+
"@types/node": "^20.11.0",
|
|
84
|
+
"@vitejs/plugin-vue": "^5.0.3",
|
|
85
|
+
"@vitest/coverage-v8": "^1.1.3",
|
|
86
86
|
"@vue/test-utils": "^2.4.3",
|
|
87
87
|
"@vuelidate/core": "^2.0.3",
|
|
88
88
|
"@vuelidate/validators": "^2.0.4",
|
|
@@ -90,7 +90,7 @@
|
|
|
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": "^
|
|
93
|
+
"happy-dom": "^13.0.2",
|
|
94
94
|
"histoire": "^0.17.6",
|
|
95
95
|
"lodash-es": "^4.17.21",
|
|
96
96
|
"markdown-it": "^14.0.0",
|
|
@@ -102,10 +102,10 @@
|
|
|
102
102
|
"release-it": "^17.0.1",
|
|
103
103
|
"typescript": "~5.3.3",
|
|
104
104
|
"v-calendar": "^3.1.2",
|
|
105
|
-
"vite": "^5.0.
|
|
106
|
-
"vitepress": "1.0.0-rc.
|
|
107
|
-
"vitest": "^1.1.
|
|
108
|
-
"vue": "^3.4.
|
|
105
|
+
"vite": "^5.0.11",
|
|
106
|
+
"vitepress": "1.0.0-rc.36",
|
|
107
|
+
"vitest": "^1.1.3",
|
|
108
|
+
"vue": "^3.4.10",
|
|
109
109
|
"vue-router": "^4.2.5",
|
|
110
110
|
"vue-tsc": "^1.8.27"
|
|
111
111
|
}
|