@globalbrain/sefirot 4.30.1 → 4.32.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 (134) hide show
  1. package/client.d.ts +5 -0
  2. package/config/nuxt.d.ts +1 -0
  3. package/config/nuxt.js +8 -5
  4. package/config/vite.js +4 -13
  5. package/lib/components/SActionList.vue +2 -2
  6. package/lib/components/SActionMenu.vue +43 -7
  7. package/lib/components/SAvatar.vue +1 -1
  8. package/lib/components/SAvatarStack.vue +12 -12
  9. package/lib/components/SButton.vue +5 -7
  10. package/lib/components/SCard.vue +2 -2
  11. package/lib/components/SChartBar.vue +37 -12
  12. package/lib/components/SChartPie.vue +13 -7
  13. package/lib/components/SControlActionBarCollapse.vue +2 -4
  14. package/lib/components/SControlInputSearch.vue +7 -2
  15. package/lib/components/SDataListItem.vue +1 -3
  16. package/lib/components/SDescAvatar.vue +1 -1
  17. package/lib/components/SDescDay.vue +2 -2
  18. package/lib/components/SDescFile.vue +2 -4
  19. package/lib/components/SDescItem.vue +2 -1
  20. package/lib/components/SDescLabel.vue +1 -1
  21. package/lib/components/SDescLink.vue +2 -7
  22. package/lib/components/SDescPill.vue +2 -4
  23. package/lib/components/SDescText.vue +3 -3
  24. package/lib/components/SDropdown.vue +1 -1
  25. package/lib/components/SDropdownSectionFilter.vue +11 -11
  26. package/lib/components/SFragment.vue +1 -1
  27. package/lib/components/SInputAddon.vue +13 -11
  28. package/lib/components/SInputBase.vue +11 -11
  29. package/lib/components/SInputCheckbox.vue +6 -3
  30. package/lib/components/SInputCheckboxes.vue +7 -3
  31. package/lib/components/SInputDate.vue +3 -5
  32. package/lib/components/SInputDropdown.vue +26 -28
  33. package/lib/components/SInputDropdownItem.vue +21 -11
  34. package/lib/components/SInputFile.vue +9 -6
  35. package/lib/components/SInputFileUpload.vue +9 -11
  36. package/lib/components/SInputFileUploadItem.vue +8 -4
  37. package/lib/components/SInputHMS.vue +3 -1
  38. package/lib/components/SInputImage.vue +4 -2
  39. package/lib/components/SInputNumber.vue +9 -10
  40. package/lib/components/SInputRadio.vue +3 -2
  41. package/lib/components/SInputRadios.vue +6 -5
  42. package/lib/components/SInputSegments.vue +5 -7
  43. package/lib/components/SInputSegmentsOption.vue +1 -2
  44. package/lib/components/SInputSelect.vue +6 -4
  45. package/lib/components/SInputSwitch.vue +4 -1
  46. package/lib/components/SInputSwitches.vue +5 -3
  47. package/lib/components/SInputText.vue +16 -16
  48. package/lib/components/SInputTextarea.vue +7 -3
  49. package/lib/components/SInputYMD.vue +3 -1
  50. package/lib/components/SLink.vue +2 -2
  51. package/lib/components/SLocalNav.vue +1 -1
  52. package/lib/components/SLocalNavActions.vue +1 -1
  53. package/lib/components/SLocalNavMenu.vue +2 -2
  54. package/lib/components/SLoginPagePasswordDialog.vue +2 -2
  55. package/lib/components/SM.vue +1 -1
  56. package/lib/components/SMFade.vue +1 -1
  57. package/lib/components/SMarkdown.vue +3 -2
  58. package/lib/components/SModal.vue +2 -2
  59. package/lib/components/SSnackbar.vue +2 -2
  60. package/lib/components/SSteps.vue +6 -6
  61. package/lib/components/STable.vue +70 -27
  62. package/lib/components/STableCell.vue +14 -17
  63. package/lib/components/STableCellAvatars.vue +1 -1
  64. package/lib/components/STableCellDay.vue +12 -5
  65. package/lib/components/STableCellNumber.vue +2 -3
  66. package/lib/components/STableCellPath.vue +2 -2
  67. package/lib/components/STableCellText.vue +2 -3
  68. package/lib/components/STableColumn.vue +38 -16
  69. package/lib/components/STableFooter.vue +10 -2
  70. package/lib/components/STableHeader.vue +0 -1
  71. package/lib/components/STableHeaderMenu.vue +4 -4
  72. package/lib/components/STableHeaderMenuItem.vue +1 -1
  73. package/lib/components/STooltip.vue +3 -3
  74. package/lib/composables/Api.ts +1 -1
  75. package/lib/composables/App.ts +13 -11
  76. package/lib/composables/Dropdown.ts +10 -1
  77. package/lib/composables/Error.ts +37 -37
  78. package/lib/composables/Grid.ts +1 -4
  79. package/lib/composables/Image.ts +2 -3
  80. package/lib/composables/Lang.ts +8 -16
  81. package/lib/composables/Markdown.ts +1 -1
  82. package/lib/composables/Table.ts +0 -2
  83. package/lib/composables/Theme.ts +1 -13
  84. package/lib/composables/Utils.ts +11 -4
  85. package/lib/composables/Validation.ts +1 -4
  86. package/lib/http/Http.ts +23 -17
  87. package/lib/styles/variables-deprecated.css +0 -1
  88. package/lib/styles/variables.css +16 -16
  89. package/lib/support/Chart.ts +0 -1
  90. package/lib/support/DateRange.ts +1 -1
  91. package/lib/support/Day.ts +12 -65
  92. package/lib/support/File.ts +7 -16
  93. package/lib/support/Utils.ts +7 -40
  94. package/lib/validation/Rule.ts +6 -21
  95. package/lib/validation/rules/decimal.ts +3 -3
  96. package/lib/validation/rules/email.ts +1 -1
  97. package/lib/validation/rules/index.ts +1 -1
  98. package/lib/validation/rules/negativeInteger.ts +1 -1
  99. package/lib/validation/rules/positiveInteger.ts +1 -1
  100. package/lib/validation/rules/requiredHms.ts +2 -2
  101. package/lib/validation/rules/requiredIf.ts +1 -4
  102. package/lib/validation/rules/requiredYmd.ts +2 -2
  103. package/lib/validation/rules/slackChannelName.ts +4 -1
  104. package/lib/validation/rules/zeroOrNegativeInteger.ts +1 -1
  105. package/lib/validation/rules/zeroOrPositiveInteger.ts +1 -1
  106. package/lib/validation/validators/after.ts +1 -5
  107. package/lib/validation/validators/afterOrEqual.ts +1 -5
  108. package/lib/validation/validators/before.ts +1 -4
  109. package/lib/validation/validators/beforeOrEqual.ts +1 -5
  110. package/lib/validation/validators/decimal.ts +7 -9
  111. package/lib/validation/validators/email.ts +4 -8
  112. package/lib/validation/validators/fileExtension.ts +7 -15
  113. package/lib/validation/validators/hms.ts +26 -15
  114. package/lib/validation/validators/index.ts +0 -2
  115. package/lib/validation/validators/maxFileSize.ts +3 -13
  116. package/lib/validation/validators/maxLength.ts +1 -7
  117. package/lib/validation/validators/maxTotalFileSize.ts +3 -26
  118. package/lib/validation/validators/maxValue.ts +2 -6
  119. package/lib/validation/validators/minLength.ts +1 -7
  120. package/lib/validation/validators/minValue.ts +2 -6
  121. package/lib/validation/validators/month.ts +1 -7
  122. package/lib/validation/validators/negativeInteger.ts +1 -7
  123. package/lib/validation/validators/positiveInteger.ts +1 -7
  124. package/lib/validation/validators/required.ts +5 -28
  125. package/lib/validation/validators/requiredHmsIf.ts +11 -13
  126. package/lib/validation/validators/requiredIf.ts +5 -11
  127. package/lib/validation/validators/requiredYmdIf.ts +11 -13
  128. package/lib/validation/validators/slackChannelName.ts +11 -11
  129. package/lib/validation/validators/url.ts +7 -5
  130. package/lib/validation/validators/ymd.ts +36 -30
  131. package/package.json +44 -42
  132. package/lib/composables/Http.ts +0 -18
  133. package/lib/validation/validators/requiredHms.ts +0 -9
  134. package/lib/validation/validators/requiredYmd.ts +0 -9
@@ -1,5 +1,14 @@
1
1
  import { useElementBounding, useWindowSize } from '@vueuse/core'
2
- import { type Component, type MaybeRef, type MaybeRefOrGetter, type Ref, computed, ref, toValue, unref } from 'vue'
2
+ import {
3
+ type Component,
4
+ type MaybeRef,
5
+ type MaybeRefOrGetter,
6
+ type Ref,
7
+ computed,
8
+ ref,
9
+ toValue,
10
+ unref
11
+ } from 'vue'
3
12
  import { type ActionList } from '../components/SActionList.vue'
4
13
  import { type DateRange } from '../support/DateRange'
5
14
 
@@ -1,20 +1,16 @@
1
1
  /**
2
2
  * Adapted from
3
- * @see https://github.com/vuejs/core/blob/1755ac0a108ba3486bd8397e56d3bdcd69196594/packages/runtime-core/src/component.ts
3
+ * @see https://github.com/vuejs/core/blob/b50eb68c50f3b94dca2e96f706c3e96ab864df24/packages/runtime-core/src/component.ts
4
4
  * @see https://github.com/vuejs/core/blob/ac9e7e8bfa55432a73a10864805fdf48bda2ff73/packages/runtime-core/src/warning.ts
5
- * @see https://github.com/getsentry/sentry-javascript/blob/04711c20246f7cdaac2305286fec783ab1859a18/packages/vue/src/errorhandler.ts
6
- * @see https://github.com/vercel/ai/blob/d544886d4f61440bacd6e44c86144bfac7c98282/packages/provider-utils/src/get-error-message.ts
5
+ * @see https://github.com/getsentry/sentry-javascript/blob/fbadeb81d23c03c3d852531c2deef59a3a992def/packages/vue/src/errorhandler.ts
7
6
  *
8
7
  * Original licenses:
9
8
  *
10
- * (c) 2018-present Yuxi (Evan) You and Vue contributors
9
+ * Copyright (c) 2018-present, Yuxi (Evan) You
11
10
  * @license MIT
12
11
  *
13
- * (c) 2012-2024 Functional Software, Inc. dba Sentry
12
+ * Copyright (c) 2019 Functional Software, Inc. dba Sentry
14
13
  * @license MIT
15
- *
16
- * (c) 2023 Vercel, Inc.
17
- * @license Apache-2.0
18
14
  */
19
15
 
20
16
  import * as Sentry from '@sentry/browser'
@@ -22,8 +18,8 @@ import { createSentryPiniaPlugin } from '@sentry/vue'
22
18
  import { pauseTracking, resetTracking } from '@vue/reactivity'
23
19
  import { getActivePinia } from 'pinia'
24
20
  import {
21
+ type Component,
25
22
  type ComponentInternalInstance,
26
- type ComponentOptions,
27
23
  type ComponentPublicInstance,
28
24
  type ConcreteComponent,
29
25
  type MaybeRefOrGetter,
@@ -31,7 +27,6 @@ import {
31
27
  toValue
32
28
  } from 'vue'
33
29
  import { useError } from '../stores/Error'
34
- import { isError } from '../support/Utils'
35
30
 
36
31
  export interface User {
37
32
  id?: string | number
@@ -43,7 +38,7 @@ type TraceEntry = { vnode: VNode; recurseCount: number }
43
38
 
44
39
  type ComponentTraceStack = TraceEntry[]
45
40
 
46
- const classifyRE = /(?:^|[-_])(\w)/g
41
+ const classifyRE = /(?:^|[-_])\w/g
47
42
  function classify(str: string): string {
48
43
  return str.replace(classifyRE, (c) => c.toUpperCase()).replace(/[-_]/g, '')
49
44
  }
@@ -70,19 +65,20 @@ function formatComponentName(instance: ComponentInternalInstance | null): string
70
65
  }
71
66
  }
72
67
 
73
- if (!name && instance && instance.parent) {
74
- const inferFromRegistry = (registry: Record<string, unknown> | undefined) => {
68
+ if (!name && instance) {
69
+ const inferFromRegistry = (registry?: Record<string, Component>) => {
75
70
  for (const key in registry) {
76
71
  if (registry[key] === Component) {
77
72
  return key
78
73
  }
79
74
  }
80
75
  }
81
- name
82
- = inferFromRegistry(
83
- // @ts-expect-error internal api
84
- instance.components || (instance.parent.type as ComponentOptions).components
85
- ) || inferFromRegistry(instance.appContext.components)
76
+ name =
77
+ // @ts-expect-error internal API
78
+ inferFromRegistry(instance.components)
79
+ // @ts-expect-error internal API
80
+ || inferFromRegistry(instance.parent?.type.components)
81
+ || inferFromRegistry(instance.appContext.components)
86
82
  }
87
83
 
88
84
  return name ? classify(name) : isRoot ? 'App' : 'Anonymous'
@@ -102,8 +98,8 @@ function getComponentTrace(currentVNode: VNode | null): ComponentTraceStack {
102
98
  } else {
103
99
  normalizedStack.push({ vnode: currentVNode, recurseCount: 0 })
104
100
  }
105
- const parentInstance: ComponentInternalInstance | null
106
- = currentVNode.component && currentVNode.component.parent
101
+ const parentInstance: ComponentInternalInstance | null =
102
+ currentVNode.component && currentVNode.component.parent
107
103
  currentVNode = parentInstance && parentInstance.vnode
108
104
  }
109
105
 
@@ -147,6 +143,26 @@ const ignoreErrors = [
147
143
  /\[Cloudflare Turnstile\] Error: (?:10[2-46]|1106[02]|[36]00)/
148
144
  ]
149
145
 
146
+ const stringifiers: readonly ((e: unknown) => string | false)[] = [
147
+ (e) => typeof e === 'string' && e,
148
+ (e) => e instanceof Error && (e.message || e.name),
149
+ (e) => {
150
+ const json = JSON.stringify(e)
151
+ return json !== '{}' && json
152
+ },
153
+ (e) => String(e)
154
+ ]
155
+
156
+ function getErrorMessage(error: unknown | undefined): string {
157
+ for (const stringify of stringifiers) {
158
+ try {
159
+ const s = stringify(error)
160
+ if (s) { return s }
161
+ } catch { /* continue */ }
162
+ }
163
+ return 'unknown error'
164
+ }
165
+
150
166
  export function useErrorHandler({
151
167
  dsn,
152
168
  environment,
@@ -204,7 +220,7 @@ export function useErrorHandler({
204
220
  componentName: formatComponentName($),
205
221
  lifecycleHook: info,
206
222
  trace: formatTrace($),
207
- propsData: $ && $.props
223
+ propsData: $.props
208
224
  }
209
225
 
210
226
  setTimeout(() => {
@@ -224,19 +240,3 @@ export function useErrorHandler({
224
240
  set(e)
225
241
  }
226
242
  }
227
-
228
- function getErrorMessage(error: unknown | undefined) {
229
- if (error == null) {
230
- return 'unknown error'
231
- }
232
-
233
- if (typeof error === 'string') {
234
- return error
235
- }
236
-
237
- if (isError(error)) {
238
- return error.message
239
- }
240
-
241
- return JSON.stringify(error)
242
- }
@@ -45,9 +45,7 @@ export function useGrid(options: UseGridOptions = {}): Grid {
45
45
  })
46
46
 
47
47
  function adjustSpacer() {
48
- container.value?.querySelectorAll(`${toClassSelector(spacerClass)}`)
49
- .forEach((n) => n.remove())
50
-
48
+ container.value?.querySelectorAll(`${toClassSelector(spacerClass)}`).forEach((n) => n.remove())
51
49
  const track = container.value?.firstElementChild
52
50
 
53
51
  const containerWidth = container.value?.clientWidth ?? 0
@@ -59,7 +57,6 @@ export function useGrid(options: UseGridOptions = {}): Grid {
59
57
  const lack = mod !== 0 ? perRow - mod : 0
60
58
 
61
59
  const fragment = createSpacers(lack, spacerTag, spacerClass, type)
62
-
63
60
  container.value?.appendChild(fragment)
64
61
  }
65
62
 
@@ -1,6 +1,5 @@
1
1
  import { isClient } from '@vueuse/core'
2
2
  import { type MaybeRefOrGetter, type Ref, ref, toValue, watchEffect } from 'vue'
3
- import { isFile, isString } from '../support/Utils'
4
3
 
5
4
  export interface ImageSrcFromFile {
6
5
  src: Ref<string | null>
@@ -34,12 +33,12 @@ export function useImageSrcFromFile(
34
33
  function read(): void {
35
34
  const f = toValue(file)
36
35
 
37
- if (isFile(f)) {
36
+ if (f instanceof Blob) {
38
37
  reader.readAsDataURL(f)
39
38
  return
40
39
  }
41
40
 
42
- if (isString(f)) {
41
+ if (typeof f === 'string') {
43
42
  src.value = f
44
43
  return
45
44
  }
@@ -8,23 +8,11 @@ export interface Trans<T> {
8
8
 
9
9
  export interface TransMessages<T> {
10
10
  en: T
11
- ja: T
12
- }
13
-
14
- export interface HasLang {
15
- lang: Lang
11
+ ja: NoInfer<T>
16
12
  }
17
13
 
18
14
  export const SefirotLangKey: InjectionKey<Lang> = Symbol.for('sefirot-lang-key')
19
15
 
20
- export function useSetupLang(): (user?: HasLang | null) => void {
21
- const browserLang = useBrowserLang()
22
-
23
- return (user) => {
24
- provideLang(user?.lang ?? browserLang)
25
- }
26
- }
27
-
28
16
  export function provideLang(lang: Lang) {
29
17
  getCurrentInstance()!.appContext.app._context.provides[SefirotLangKey] = lang
30
18
  }
@@ -33,12 +21,16 @@ export function useLang(): Lang {
33
21
  return inject(SefirotLangKey, 'en')
34
22
  }
35
23
 
36
- export function useBrowserLang(): Lang {
37
- const lang = navigator.language
38
-
24
+ export function getBrowserLang(): Lang {
25
+ const lang = String(globalThis.navigator?.language || 'en')
39
26
  return lang.split('-')[0] === 'ja' ? 'ja' : 'en'
40
27
  }
41
28
 
29
+ /** @deprecated use `getBrowserLang` instead */
30
+ export function useBrowserLang(): Lang {
31
+ return getBrowserLang()
32
+ }
33
+
42
34
  export function useTrans<T>(messages: TransMessages<T>): Trans<T> {
43
35
  const lang = useLang()
44
36
 
@@ -1,4 +1,4 @@
1
- import DOMPurify, { type Config } from 'dompurify'
1
+ import DOMPurify, { type Config } from 'isomorphic-dompurify'
2
2
  import MarkdownIt from 'markdown-it'
3
3
 
4
4
  export type UseMarkdown = (source: string, inline?: boolean) => string
@@ -25,11 +25,9 @@ export interface Table<
25
25
  total?: MaybeRef<number | null | undefined>
26
26
  page?: MaybeRef<number | null | undefined>
27
27
  perPage?: MaybeRef<number | null | undefined>
28
- reset?: MaybeRef<boolean | undefined>
29
28
  borderSize?: MaybeRef<number | undefined>
30
29
  onPrev?(): void
31
30
  onNext?(): void
32
- onReset?(): void
33
31
  }
34
32
 
35
33
  export type TableColumns<
@@ -3,23 +3,11 @@ import { type WritableComputedRef, computed } from 'vue'
3
3
 
4
4
  export type Theme = 'light' | 'dark'
5
5
 
6
- export interface HasTheme {
7
- theme: Theme
8
- }
9
-
10
- export function useSetupTheme(): (user?: HasTheme | null) => void {
11
- const theme = useTheme()
12
-
13
- return (user) => {
14
- theme.value = user?.theme ?? 'light'
15
- }
16
- }
17
-
18
6
  export function useTheme(): WritableComputedRef<Theme> {
19
7
  const _isDark = useDark()
20
8
 
21
9
  return computed({
22
- get: () => _isDark.value ? 'dark' : 'light',
10
+ get: () => (_isDark.value ? 'dark' : 'light'),
23
11
  set: (v) => { _isDark.value = v === 'dark' }
24
12
  })
25
13
  }
@@ -1,5 +1,12 @@
1
- import { type ComputedRef, type MaybeRefOrGetter, computed, getCurrentInstance, onMounted, toValue, useSlots } from 'vue'
2
- import { isString } from '../support/Utils'
1
+ import {
2
+ type ComputedRef,
3
+ type MaybeRefOrGetter,
4
+ computed,
5
+ getCurrentInstance,
6
+ onMounted,
7
+ toValue,
8
+ useSlots
9
+ } from 'vue'
3
10
 
4
11
  export type WhenCondition<T> = MaybeRefOrGetter<T>
5
12
 
@@ -22,7 +29,7 @@ export function computedWhen<T, C, D>(
22
29
  return computed(() => {
23
30
  const c = toValue(condition)
24
31
 
25
- return c ? fn(c) : whenFalse as D
32
+ return c ? fn(c) : (whenFalse as D)
26
33
  })
27
34
  }
28
35
 
@@ -68,7 +75,7 @@ export function useSlotValue(name = 'default'): ComputedRef<string | null> {
68
75
 
69
76
  return computed(() => {
70
77
  const c = slots[name]?.()[0]?.children
71
- const v = isString(c) ? c.trim() : null
78
+ const v = typeof c === 'string' ? c.trim() : null
72
79
  return v !== '' ? v : null
73
80
  })
74
81
  }
@@ -85,10 +85,7 @@ export function useVNotification(): VNotification {
85
85
  const snackbars = useSnackbars()
86
86
 
87
87
  function notify(message?: Snackbar): void {
88
- snackbars.push(message ?? {
89
- mode: 'danger',
90
- text: t.notify
91
- })
88
+ snackbars.push(message ?? { mode: 'danger', text: t.notify })
92
89
  }
93
90
 
94
91
  return {
package/lib/http/Http.ts CHANGED
@@ -3,7 +3,6 @@ import { parse as parseCookie } from '@tinyhttp/cookie'
3
3
  import FileSaver from 'file-saver'
4
4
  import { FetchError, type FetchOptions, type FetchResponse } from 'ofetch'
5
5
  import { stringify } from 'qs'
6
- import { isBlob, isError, isFormData, isRequest, isResponse, isString } from '../support/Utils'
7
6
 
8
7
  type Config = ReturnType<typeof import('../stores/HttpConfig').useHttpConfig>
9
8
 
@@ -31,9 +30,13 @@ export class Http {
31
30
 
32
31
  private async buildRequest(url: string, _options: FetchOptions = {}): Promise<[string, FetchOptions]> {
33
32
  const { method, params, query, ...options } = _options
34
- const xsrfToken = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method || '') && (await this.ensureXsrfToken())
33
+ const xsrfToken = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method || '')
34
+ && (await this.ensureXsrfToken())
35
35
 
36
- const queryString = stringify({ ...params, ...query }, { encodeValuesOnly: true, ...this.config.stringifyOptions })
36
+ const queryString = stringify(
37
+ { ...params, ...query },
38
+ { encodeValuesOnly: true, ...this.config.stringifyOptions }
39
+ )
37
40
 
38
41
  return [
39
42
  `${url}${queryString ? `?${queryString}` : ''}`,
@@ -70,11 +73,11 @@ export class Http {
70
73
  }
71
74
 
72
75
  async post<T = any>(url: string, body?: any, options?: FetchOptions): Promise<T> {
73
- if (body && !isFormData(body)) {
76
+ if (body && !(body instanceof FormData)) {
74
77
  let hasFile = false
75
78
 
76
79
  const payload = JSON.stringify(body, (_, value) => {
77
- if (isBlob(value)) {
80
+ if (value instanceof Blob) {
78
81
  hasFile = true
79
82
  return undefined
80
83
  }
@@ -120,13 +123,18 @@ export class Http {
120
123
  throw new Error('No blob')
121
124
  }
122
125
 
123
- const { filename = 'download' }
124
- = parseContentDisposition(headers.get('Content-Disposition') || '')?.parameters || {}
126
+ const { filename = 'download' } =
127
+ parseContentDisposition(headers.get('Content-Disposition') || '')?.parameters || {}
125
128
 
126
129
  FileSaver.saveAs(blob, filename as string)
127
130
  }
128
131
 
129
- private objectToFormData(obj: any, form?: FormData, namespace?: string, onlyFiles = false): FormData {
132
+ private objectToFormData(
133
+ obj: any,
134
+ form?: FormData,
135
+ namespace?: string,
136
+ onlyFiles = false
137
+ ): FormData {
130
138
  const fd = form || new FormData()
131
139
  let formKey: string
132
140
 
@@ -141,11 +149,15 @@ export class Http {
141
149
  return
142
150
  }
143
151
 
144
- if (typeof obj[property] === 'object' && !isBlob(obj[property]) && obj[property] !== null) {
152
+ if (
153
+ typeof obj[property] === 'object'
154
+ && !(obj[property] instanceof Blob)
155
+ && obj[property] !== null
156
+ ) {
145
157
  this.objectToFormData(obj[property], fd, property, onlyFiles)
146
158
  } else {
147
159
  const value = obj[property] === null ? '' : obj[property]
148
- if (onlyFiles && !isBlob(value)) {
160
+ if (onlyFiles && !(value instanceof Blob)) {
149
161
  return
150
162
  }
151
163
  fd.append(formKey, value)
@@ -157,13 +169,7 @@ export class Http {
157
169
  }
158
170
 
159
171
  export function isFetchError(e: unknown): e is FetchError {
160
- return (
161
- e instanceof FetchError
162
- || (isError<FetchError>(e)
163
- && (e.response === undefined || isResponse(e.response))
164
- && ((isString(e.request) && e.message.startsWith(`[${e.options?.method || 'GET'}] ${JSON.stringify(e.request || '/')}: `))
165
- || (isRequest(e.request) && e.message.startsWith(`[${e.request.method}] ${JSON.stringify(e.request.url)}: `))))
166
- )
172
+ return e instanceof FetchError || (e instanceof Error && e.name === 'FetchError')
167
173
  }
168
174
 
169
175
  export { FetchError, type FetchOptions, type FetchRequest, type FetchResponse } from 'ofetch'
@@ -110,7 +110,6 @@
110
110
  */
111
111
  :root {
112
112
  --c-soft: var(--c-white-soft);
113
-
114
113
  }
115
114
 
116
115
  .dark {
@@ -154,7 +154,7 @@
154
154
  * Color: Divider and Gutter
155
155
  * -------------------------------------------------------------------------- */
156
156
 
157
- :root {
157
+ :root {
158
158
  --c-divider: #e0e0e1;
159
159
  --c-gutter: #e2e2e3;
160
160
  }
@@ -290,7 +290,7 @@
290
290
  * Color: Border
291
291
  * -------------------------------------------------------------------------- */
292
292
 
293
- :root {
293
+ :root {
294
294
  --c-border-mute-1: var(--c-gray-6);
295
295
  --c-border-mute-2: var(--c-gray-7);
296
296
  --c-border-mute-3: var(--c-gray-8);
@@ -316,7 +316,7 @@
316
316
  * Color: Text
317
317
  * -------------------------------------------------------------------------- */
318
318
 
319
- :root {
319
+ :root {
320
320
  --c-text-1: var(--c-text-light-1);
321
321
  --c-text-2: var(--c-text-light-2);
322
322
  --c-text-3: var(--c-text-light-3);
@@ -367,11 +367,11 @@
367
367
  * -------------------------------------------------------------------------- */
368
368
 
369
369
  :root {
370
- --shadow-depth-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);
371
- --shadow-depth-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);
372
- --shadow-depth-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);
373
- --shadow-depth-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);
374
- --shadow-depth-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16);
370
+ --shadow-depth-1: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06);
371
+ --shadow-depth-2: 0 3px 12px rgba(0, 0, 0, 0.07), 0 1px 4px rgba(0, 0, 0, 0.07);
372
+ --shadow-depth-3: 0 12px 32px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08);
373
+ --shadow-depth-4: 0 14px 44px rgba(0, 0, 0, 0.12), 0 3px 9px rgba(0, 0, 0, 0.12);
374
+ --shadow-depth-5: 0 18px 56px rgba(0, 0, 0, 0.16), 0 4px 12px rgba(0, 0, 0, 0.16);
375
375
  }
376
376
 
377
377
  /**
@@ -389,15 +389,15 @@
389
389
  * -------------------------------------------------------------------------- */
390
390
 
391
391
  :root {
392
- --ease-in-quint: cubic-bezier(.755, .05, .855, .06);
393
- --ease-in-back: cubic-bezier(1, -.75, 1, 1);
392
+ --ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
393
+ --ease-in-back: cubic-bezier(1, -0.75, 1, 1);
394
394
 
395
- --ease-out-quint: cubic-bezier(.23, 1, .32, 1);
396
- --ease-out-expo: cubic-bezier(.19, 1, .22, 1);
397
- --ease-out-back: cubic-bezier(.175, .885, .320, 1.275);
398
- --ease-out-back-quint: cubic-bezier(.175, .885, .280, 1.5);
395
+ --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
396
+ --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
397
+ --ease-out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275);
398
+ --ease-out-back-quint: cubic-bezier(0.175, 0.885, 0.28, 1.5);
399
399
 
400
- --ease-in-out-quint: cubic-bezier(.86, 0, .07, 1);
400
+ --ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
401
401
  --ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
402
402
  }
403
403
 
@@ -503,7 +503,7 @@
503
503
  --button-fill-black-hover-text-color: var(--c-text-dark-1);
504
504
  --button-fill-black-hover-bg-color: var(--c-neutral-light-2);
505
505
  --button-fill-black-active-border-color: transparent;
506
- --button-fill-black-active-text-color:var(--c-text-dark-1);
506
+ --button-fill-black-active-text-color: var(--c-text-dark-1);
507
507
  --button-fill-black-active-bg-color: var(--c-neutral-light-3);
508
508
  --button-fill-black-disabled-border-color: transparent;
509
509
  --button-fill-black-disabled-text-color: var(--c-text-dark-2);
@@ -37,7 +37,6 @@ export const chartColors = {
37
37
  gray: 'light-dark(#8d8d8d, #7b7b7b)'
38
38
  } as const
39
39
 
40
- // eslint-disable-next-line @typescript-eslint/ban-types
41
40
  export type ChartColor = keyof typeof chartColors | (string & {})
42
41
  export type KV = { key: string; value: number; color?: ChartColor }
43
42
  export type Margins = Partial<{ top: number; right: number; bottom: number; left: number }>
@@ -93,7 +93,7 @@ export class DateFromTo extends DateRangePresetBase {
93
93
  const f = this.getFrom()?.format('YYYY-MM-DD')
94
94
  const t = this.getTo()?.format('YYYY-MM-DD')
95
95
 
96
- return (f && t) ? `${f} – ${t}` : 'Error'
96
+ return f && t ? `${f} – ${t}` : 'Error'
97
97
  }
98
98
 
99
99
  setFrom(from: Day | null): this {
@@ -2,7 +2,6 @@ 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'
6
5
 
7
6
  dayjs.extend(PluginUtc)
8
7
  dayjs.extend(PluginTimezone)
@@ -22,12 +21,6 @@ export interface Ymd {
22
21
 
23
22
  export type YmdType = 'y' | 'm' | 'd'
24
23
 
25
- export const YmdMap = {
26
- y: 'year',
27
- m: 'month',
28
- d: 'date'
29
- } as const
30
-
31
24
  /**
32
25
  * The hour, minute, and second object interface.
33
26
  */
@@ -39,13 +32,13 @@ export interface Hms {
39
32
 
40
33
  export type HmsType = 'h' | 'm' | 's'
41
34
 
42
- export const HmsMap = {
43
- h: 'hour',
44
- m: 'minute',
45
- s: 'second'
46
- } as const
47
-
48
35
  export function day(input?: Input): Day {
36
+ // hack for histoire
37
+ if (input && typeof input === 'object' && !(input instanceof Date)) {
38
+ const { $D, $H, $M, $m, $ms, $s, $y } = input as any
39
+ input = new Date($y, $M, $D, $H, $m, $s, $ms)
40
+ }
41
+
49
42
  return dayjs(input)
50
43
  }
51
44
 
@@ -67,19 +60,9 @@ export function createYmd(
67
60
  month: number | null = null,
68
61
  date: number | null = null
69
62
  ): Ymd {
70
- if (isNumber(yearOrDay) || yearOrDay == null) {
71
- return {
72
- year: yearOrDay,
73
- month,
74
- date
75
- }
76
- }
77
-
78
- return {
79
- year: yearOrDay.year(),
80
- month: yearOrDay.month() + 1,
81
- date: yearOrDay.date()
82
- }
63
+ return isDay(yearOrDay)
64
+ ? { year: yearOrDay.year(), month: yearOrDay.month() + 1, date: yearOrDay.date() }
65
+ : { year: yearOrDay, month, date }
83
66
  }
84
67
 
85
68
  /**
@@ -92,45 +75,9 @@ export function createHms(
92
75
  minute: string | null = null,
93
76
  second: string | null = null
94
77
  ): Hms {
95
- if (isString(hourOrDay) || hourOrDay == null) {
96
- return {
97
- hour: hourOrDay,
98
- minute,
99
- second
100
- }
101
- }
102
-
103
- return {
104
- hour: hourOrDay.format('HH'),
105
- minute: hourOrDay.format('mm'),
106
- second: hourOrDay.format('ss')
107
- }
108
- }
109
-
110
- export function isYmd(value: unknown, required: YmdType[] = ['y', 'm', 'd']): value is Ymd {
111
- if (value == null || !isObject(value)) {
112
- return false
113
- }
114
-
115
- return required
116
- .reduce<string[]>((keys, type) => {
117
- keys.push(YmdMap[type])
118
- return keys
119
- }, [])
120
- .every((key) => value[key] === null || isNumber(value[key]))
121
- }
122
-
123
- export function isHms(value: unknown, required: HmsType[] = ['h', 'm', 's']): value is Hms {
124
- if (value == null || !isObject(value)) {
125
- return false
126
- }
127
-
128
- return required
129
- .reduce<string[]>((keys, type) => {
130
- keys.push(HmsMap[type])
131
- return keys
132
- }, [])
133
- .every((key) => value[key] === null || isString(value[key]))
78
+ return isDay(hourOrDay)
79
+ ? { hour: hourOrDay.format('HH'), minute: hourOrDay.format('mm'), second: hourOrDay.format('ss') }
80
+ : { hour: hourOrDay, minute, second }
134
81
  }
135
82
 
136
83
  export function isDay(value: unknown): value is Day {
@@ -1,24 +1,15 @@
1
- /**
2
- * Get extension of the given file.
3
- */
4
- export function getExtension(file: File): string {
5
- const name = file.name
6
-
7
- return name.slice((name.lastIndexOf('.') - 1 >>> 0) + 2)
8
- }
1
+ const units = ['B', 'kB', 'MB', 'GB'] as const
9
2
 
10
3
  /**
11
4
  * Formats the file size in bytes to a human-readable format. It also accepts
12
5
  * array of files and returns the total size.
13
6
  */
14
7
  export function formatSize(files: File | File[]): string {
15
- const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
16
8
  files = Array.isArray(files) ? files : [files]
17
- let size = files.reduce((previous, file) => previous + file.size, 0)
18
- let index = 0
19
- while (size >= 1024 && index < units.length) {
20
- size /= 1024
21
- index++
22
- }
23
- return `${size.toFixed(2)}${units[index]}`
9
+
10
+ const size = files.reduce((sum, file) => sum + file.size, 0)
11
+ if (size === 0) { return `0 ${units[0]}` }
12
+
13
+ const i = Math.min(Math.floor(Math.log(size) / Math.log(1000)), units.length - 1)
14
+ return `${(size / 1000 ** i).toFixed(2)} ${units[i]}`
24
15
  }