@globalbrain/sefirot 4.29.1 → 4.30.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.
@@ -3,10 +3,9 @@ import IconCheck from '~icons/ph/check-bold'
3
3
  import IconMinus from '~icons/ph/minus-bold'
4
4
  import { type Component, computed } from 'vue'
5
5
  import { type Validatable } from '../composables/Validation'
6
- import SInputBase from './SInputBase.vue'
6
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
7
7
 
8
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
9
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
8
+ export type { Color, Size }
10
9
 
11
10
  const props = withDefaults(defineProps<{
12
11
  size?: Size
@@ -1,11 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
  import SInputCheckbox from './SInputCheckbox.vue'
6
6
 
7
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
8
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
7
+ export type { Color, Size }
9
8
 
10
9
  export type Value = any
11
10
 
@@ -3,10 +3,9 @@ import { DatePicker } from 'v-calendar'
3
3
  import { type Component, computed } from 'vue'
4
4
  import { type Validatable } from '../composables/Validation'
5
5
  import { type Day, day } from '../support/Day'
6
- import SInputBase from './SInputBase.vue'
6
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
7
7
 
8
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
9
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
8
+ export type { Color, Size }
10
9
 
11
10
  const props = defineProps<{
12
11
  size?: Size
@@ -20,6 +19,7 @@ const props = defineProps<{
20
19
  checkColor?: Color
21
20
  block?: boolean
22
21
  disabled?: boolean
22
+ tabindex?: -1 | 0 | number
23
23
  modelValue: Day | null
24
24
  validation?: Validatable
25
25
  hideError?: boolean
@@ -86,6 +86,7 @@ function emitBlur() {
86
86
  autocomplete="off"
87
87
  :value="inputValue"
88
88
  :disabled
89
+ :tabindex
89
90
  v-on="disabled ? {} : inputEvents"
90
91
  @blur="emitBlur"
91
92
  >
@@ -10,6 +10,7 @@ import SDropdown from './SDropdown.vue'
10
10
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
11
11
  import SInputDropdownItem from './SInputDropdownItem.vue'
12
12
 
13
+ export type { Color, Size } from './SInputBase.vue'
13
14
  export interface Props extends BaseProps {
14
15
  placeholder?: string
15
16
  options: Option[]
@@ -1,6 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import IconX from '~icons/ph/x'
3
3
  import SAvatar from './SAvatar.vue'
4
+ import { type Size } from './SInputBase.vue'
5
+
6
+ export type { Size }
4
7
 
5
8
  export type Item = ItemText | ItemAvatar
6
9
 
@@ -20,8 +23,6 @@ export interface ItemAvatar extends ItemBase {
20
23
  image?: string | null
21
24
  }
22
25
 
23
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
24
-
25
26
  defineProps<{
26
27
  item: Item | Item[]
27
28
  size: Size
@@ -1,10 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed, ref } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
 
6
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
7
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
6
+ export type { Color, Size }
8
7
 
9
8
  const props = defineProps<{
10
9
  size?: Size
@@ -16,6 +15,7 @@ const props = defineProps<{
16
15
  placeholder?: string
17
16
  accept?: string
18
17
  multiple?: boolean
18
+ tabindex?: -1 | 0 | number
19
19
  checkIcon?: Component
20
20
  checkText?: string
21
21
  checkColor?: Color
@@ -82,12 +82,13 @@ function onChange(e: Event) {
82
82
  type="file"
83
83
  :accept
84
84
  :multiple
85
+ :tabindex
85
86
  @change="onChange"
86
87
  >
87
88
 
88
89
  <div class="box" role="button" @click="open">
89
90
  <div class="action">
90
- <button class="button">
91
+ <button class="button" :tabindex>
91
92
  {{ text ?? 'Choose File' }}
92
93
  </button>
93
94
  </div>
@@ -9,12 +9,12 @@ import SButton, { type Mode as ButtonMode } from './SButton.vue'
9
9
  import SCard from './SCard.vue'
10
10
  import SCardBlock from './SCardBlock.vue'
11
11
  import { type State as IndicatorState } from './SIndicator.vue'
12
- import SInputBase from './SInputBase.vue'
12
+ import SInputBase, { type Color } from './SInputBase.vue'
13
13
  import SInputFileUploadItem from './SInputFileUploadItem.vue'
14
14
  import STrans from './STrans.vue'
15
15
 
16
16
  export type Size = 'mini' | 'small' | 'medium'
17
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
17
+ export type { Color }
18
18
 
19
19
  export type ModelType = 'file' | 'object'
20
20
  export type ModelValue<T extends ModelType> = T extends 'file' ? File : FileObject
@@ -2,6 +2,7 @@
2
2
  import { computed, ref } from 'vue'
3
3
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
4
4
 
5
+ export type { Color, Size } from './SInputBase.vue'
5
6
  export interface Props extends BaseProps {
6
7
  placeholder?: Placeholder
7
8
  noHour?: boolean
@@ -4,10 +4,10 @@ import { type Component, computed, ref } from 'vue'
4
4
  import { useImageSrcFromFile } from '../composables/Image'
5
5
  import { type Validatable } from '../composables/Validation'
6
6
  import SButton from './SButton.vue'
7
- import SInputBase from './SInputBase.vue'
7
+ import SInputBase, { type Color } from './SInputBase.vue'
8
8
 
9
9
  export type Size = 'mini' | 'small' | 'medium'
10
- export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
10
+ export type { Color }
11
11
  export type ImageType = 'rectangle' | 'circle'
12
12
 
13
13
  const props = withDefaults(defineProps<{
@@ -18,7 +18,7 @@ const props = withDefaults(defineProps<{
18
18
  help?: string
19
19
  checkIcon?: Component
20
20
  checkText?: string
21
- checkColor?: CheckColor
21
+ checkColor?: Color
22
22
  imageType?: ImageType
23
23
  imageWidth?: string
24
24
  imageAspectRatio?: string
@@ -12,6 +12,7 @@ export interface Props extends BaseProps {
12
12
  separator?: boolean
13
13
  align?: Align
14
14
  disabled?: boolean
15
+ tabindex?: -1 | 0 | number
15
16
  value?: number | null
16
17
  modelValue?: number | null
17
18
  displayValue?: string | null
@@ -91,6 +92,7 @@ function emitUpdate(value: string | null) {
91
92
  :text-color="_textColor"
92
93
  :align
93
94
  :disabled
95
+ :tabindex
94
96
  :display-value
95
97
  :model-value="_value == null ? null : String(_value)"
96
98
  :validation
@@ -1,10 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
 
6
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
7
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
6
+ export type { Color, Size }
8
7
 
9
8
  const props = defineProps<{
10
9
  size?: Size
@@ -8,11 +8,10 @@
8
8
  >
9
9
  import { type Component, computed } from 'vue'
10
10
  import { type Validatable } from '../composables/Validation'
11
- import SInputBase from './SInputBase.vue'
11
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
12
12
  import SInputRadio from './SInputRadio.vue'
13
13
 
14
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
15
- export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
14
+ export type { Color, Size }
16
15
 
17
16
  export interface Option<
18
17
  ValueType extends string | number | boolean = string | number | boolean
@@ -1,12 +1,10 @@
1
1
  <script setup lang="ts" generic="T extends string | number | boolean">
2
2
  import { type Component, computed } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
  import SInputSegmentsOption, { type Mode } from './SInputSegmentsOption.vue'
6
6
 
7
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
8
- export type Color = 'default' | 'mute' | 'neutral' | 'info' | 'success' | 'warning' | 'danger'
9
- export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
7
+ export type { Color, Size }
10
8
 
11
9
  export interface Option<T extends string | number | boolean> {
12
10
  label: string
@@ -24,7 +22,7 @@ const props = defineProps<{
24
22
  help?: string
25
23
  checkIcon?: Component
26
24
  checkText?: string
27
- checkColor?: CheckColor
25
+ checkColor?: Color
28
26
  options: Option<T>[]
29
27
  block?: boolean
30
28
  disabled?: boolean
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts" generic="T extends string | number | boolean">
2
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
2
+ import { type Size } from './SInputBase.vue'
3
+
4
+ export type { Size }
3
5
  export type Mode = 'default' | 'mute' | 'neutral' | 'info' | 'success' | 'warning' | 'danger'
4
6
 
5
7
  const props = defineProps<{
@@ -4,11 +4,13 @@ import IconCaretUp from '~icons/ph/caret-up'
4
4
  import { computed, ref } from 'vue'
5
5
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
6
6
 
7
+ export type { Color, Size } from './SInputBase.vue'
7
8
  export interface Props extends BaseProps {
8
9
  placeholder?: string
9
10
  options: Option[]
10
11
  nullable?: boolean
11
12
  disabled?: boolean
13
+ tabindex?: -1 | 0 | number
12
14
  value?: Value
13
15
  modelValue?: Value
14
16
  }
@@ -85,6 +87,7 @@ function emitChange(e: any): void {
85
87
  class="select"
86
88
  :class="{ 'is-not-selected': isNotSelected }"
87
89
  :disabled
90
+ :tabindex
88
91
  @focus="isFocused = true"
89
92
  @blur="isFocused = false"
90
93
  @change="emitChange"
@@ -1,11 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
 
6
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
6
+ export type { Color, Size }
7
7
  export type ActiveColor = 'info' | 'success' | 'warning' | 'danger'
8
- export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
9
8
 
10
9
  const props = withDefaults(defineProps<{
11
10
  size?: Size
@@ -18,7 +17,7 @@ const props = withDefaults(defineProps<{
18
17
  help?: string
19
18
  checkIcon?: Component
20
19
  checkText?: string
21
- checkColor?: CheckColor
20
+ checkColor?: Color
22
21
  disabled?: boolean
23
22
  value?: boolean
24
23
  modelValue?: boolean
@@ -1,11 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed } from 'vue'
3
3
  import { type Validatable } from '../composables/Validation'
4
- import SInputBase from './SInputBase.vue'
4
+ import SInputBase, { type Color, type Size } from './SInputBase.vue'
5
5
  import SInputSwitch from './SInputSwitch.vue'
6
6
 
7
- export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
8
- export type CheckColor = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
7
+ export type { Color, Size }
9
8
 
10
9
  export interface Option {
11
10
  label: string
@@ -21,7 +20,7 @@ const props = defineProps<{
21
20
  help?: string
22
21
  checkIcon?: Component
23
22
  checkText?: string
24
- checkColor?: CheckColor
23
+ checkColor?: Color
25
24
  options: Option[]
26
25
  disabled?: boolean
27
26
  modelValue: any[]
@@ -3,6 +3,7 @@ import { type Component, computed, ref } from 'vue'
3
3
  import { isString } from '../support/Utils'
4
4
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
5
5
 
6
+ export type { Color, Size } from './SInputBase.vue'
6
7
  export interface Props extends BaseProps {
7
8
  type?: string
8
9
  placeholder?: string
@@ -11,6 +12,7 @@ export interface Props extends BaseProps {
11
12
  textColor?: TextColor | ((value: string | null) => TextColor)
12
13
  align?: Align
13
14
  disabled?: boolean
15
+ tabindex?: -1 | 0 | number
14
16
  modelValue: string | null
15
17
  displayValue?: string | null
16
18
  }
@@ -134,6 +136,7 @@ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
134
136
  :type="type ?? 'text'"
135
137
  :placeholder
136
138
  :disabled
139
+ :tabindex
137
140
  :value="modelValue"
138
141
  ref="input"
139
142
  @focus="onFocus"
@@ -3,9 +3,11 @@ import { computed, ref } from 'vue'
3
3
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
4
4
  import SInputSegments from './SInputSegments.vue'
5
5
 
6
+ export type { Color, Size } from './SInputBase.vue'
6
7
  export interface Props extends BaseProps {
7
8
  placeholder?: string
8
9
  disabled?: boolean
10
+ tabindex?: 0 | -1 | number
9
11
  rows?: number | 'fill'
10
12
  autoResize?: boolean | number
11
13
  value?: string | null
@@ -115,6 +117,7 @@ const isPreview = ref(false)
115
117
  :placeholder
116
118
  :rows="rows === 'fill' ? 3 : rows"
117
119
  :disabled
120
+ :tabindex
118
121
  :value="_value ?? undefined"
119
122
  @input="emitInput"
120
123
  @blur="emitBlur"
@@ -2,6 +2,7 @@
2
2
  import { computed, ref } from 'vue'
3
3
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
4
4
 
5
+ export type { Color, Size } from './SInputBase.vue'
5
6
  export interface Props extends BaseProps {
6
7
  placeholder?: Placeholder
7
8
  noYear?: boolean
@@ -11,7 +11,7 @@ const props = withDefaults(defineProps<{
11
11
  display?: 'inline' | 'inline-block' | 'block'
12
12
  trigger?: 'hover' | 'focus' | 'both'
13
13
  timeout?: number
14
- tabindex?: number
14
+ tabindex?: -1 | 0 | number
15
15
  }>(), {
16
16
  tag: 'span',
17
17
  triggerTag: 'span',
@@ -1,3 +1,4 @@
1
+ import { useHttpConfig } from 'sefirot/stores/HttpConfig'
1
2
  import { type Ref, type WatchSource, ref, watch } from 'vue'
2
3
  import { Http } from '../http/Http'
3
4
  import { tryOnMounted } from './Utils'
@@ -45,6 +46,7 @@ export function useQuery<Data = any>(
45
46
  ): Query<Data> {
46
47
  const loading = ref(false)
47
48
  const data = ref<Data | undefined>()
49
+ const httpConfig = useHttpConfig()
48
50
 
49
51
  if (options.immediate !== false) {
50
52
  tryOnMounted(execute)
@@ -57,7 +59,7 @@ export function useQuery<Data = any>(
57
59
  async function execute({ assign = true, silent = false } = {}): Promise<Data> {
58
60
  if (!silent) { loading.value = true }
59
61
 
60
- const res: Data = await req(new Http())
62
+ const res: Data = await req(new Http(httpConfig))
61
63
  if (assign) { data.value = res }
62
64
 
63
65
  loading.value = false
@@ -72,11 +74,12 @@ export function useMutation<Data = any, Args extends any[] = any[]>(
72
74
  ): Mutation<Data, Args> {
73
75
  const loading = ref(false)
74
76
  const data = ref<Data | undefined>()
77
+ const httpConfig = useHttpConfig()
75
78
 
76
79
  async function execute(...args: Args): Promise<Data> {
77
80
  loading.value = true
78
81
 
79
- const res: Data = await req(new Http(), ...args)
82
+ const res: Data = await req(new Http(httpConfig), ...args)
80
83
  data.value = res
81
84
 
82
85
  loading.value = false
@@ -1,4 +1,4 @@
1
- import { type HttpOptions } from '../http/Http'
1
+ import { type HttpOptions } from 'sefirot/stores/HttpConfig'
2
2
  import { useSetupHttp } from './Http'
3
3
  import { type HasLang, useSetupLang } from './Lang'
4
4
  import { type HasTheme, useSetupTheme } from './Theme'
@@ -1,5 +1,5 @@
1
1
  import { type Lang, useBrowserLang } from 'sefirot/composables/Lang'
2
- import { Http, type HttpOptions } from 'sefirot/http/Http'
2
+ import { type HttpOptions, useHttpConfig } from 'sefirot/stores/HttpConfig'
3
3
 
4
4
  export interface HasLang {
5
5
  lang: Lang
@@ -7,9 +7,10 @@ export interface HasLang {
7
7
 
8
8
  export function useSetupHttp(): (user?: HasLang | null, options?: HttpOptions) => void {
9
9
  const browserLang = useBrowserLang()
10
+ const httpConfig = useHttpConfig()
10
11
 
11
12
  return (user, options = {}) => {
12
- Http.config({
13
+ httpConfig.apply({
13
14
  lang: user?.lang ?? browserLang,
14
15
  ...options
15
16
  })
package/lib/http/Http.ts CHANGED
@@ -1,70 +1,28 @@
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 { FetchError, type FetchOptions, type FetchRequest, type FetchResponse, ofetch } from 'ofetch'
5
- import { type IStringifyOptions, stringify } from 'qs'
6
- import { type Lang } from '../composables/Lang'
4
+ import { FetchError, type FetchOptions, type FetchResponse } from 'ofetch'
5
+ import { stringify } from 'qs'
7
6
  import { isBlob, isError, isFormData, isRequest, isResponse, isString } from '../support/Utils'
8
7
 
9
- type Awaitable<T> = T | PromiseLike<T>
10
-
11
- export interface HttpClient {
12
- (request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<any>
13
- raw(request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<FetchResponse<any>>
14
- }
15
-
16
- export interface HttpOptions {
17
- baseUrl?: string
18
- xsrfUrl?: string | false
19
- client?: HttpClient
20
- lang?: Lang
21
- payloadKey?: string
22
- headers?: () => Awaitable<Record<string, string>>
23
- stringifyOptions?: IStringifyOptions
24
- }
8
+ type Config = ReturnType<typeof import('../stores/HttpConfig').useHttpConfig>
25
9
 
26
10
  export class Http {
27
- private static baseUrl: string | undefined = undefined
28
- private static xsrfUrl: string | false = '/api/csrf-cookie'
29
- private static client: HttpClient = ofetch
30
- private static lang: Lang | undefined = undefined
31
- private static payloadKey = '__payload__'
32
- private static headers: () => Awaitable<Record<string, string>> = async () => ({})
33
- private static stringifyOptions: IStringifyOptions = {}
34
-
35
- static config(options: HttpOptions): void {
36
- if (options.baseUrl) {
37
- Http.baseUrl = options.baseUrl
38
- }
39
- if (options.xsrfUrl !== undefined) {
40
- Http.xsrfUrl = options.xsrfUrl
41
- }
42
- if (options.client) {
43
- Http.client = options.client
44
- }
45
- if (options.lang) {
46
- Http.lang = options.lang
47
- }
48
- if (options.payloadKey) {
49
- Http.payloadKey = options.payloadKey
50
- }
51
- if (options.headers) {
52
- Http.headers = options.headers
53
- }
54
- if (options.stringifyOptions) {
55
- Http.stringifyOptions = options.stringifyOptions
56
- }
11
+ private config: Config
12
+
13
+ constructor(options: Config) {
14
+ this.config = options
57
15
  }
58
16
 
59
17
  private async ensureXsrfToken(): Promise<string | undefined> {
60
- if (!Http.xsrfUrl) {
18
+ if (!this.config.xsrfUrl) {
61
19
  return undefined
62
20
  }
63
21
 
64
22
  let xsrfToken = parseCookie(document.cookie)['XSRF-TOKEN']
65
23
 
66
24
  if (!xsrfToken) {
67
- await this.head(Http.xsrfUrl)
25
+ await this.head(this.config.xsrfUrl)
68
26
  xsrfToken = parseCookie(document.cookie)['XSRF-TOKEN']
69
27
  }
70
28
 
@@ -75,20 +33,20 @@ export class Http {
75
33
  const { method, params, query, ...options } = _options
76
34
  const xsrfToken = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method || '') && (await this.ensureXsrfToken())
77
35
 
78
- const queryString = stringify({ ...params, ...query }, { encodeValuesOnly: true, ...Http.stringifyOptions })
36
+ const queryString = stringify({ ...params, ...query }, { encodeValuesOnly: true, ...this.config.stringifyOptions })
79
37
 
80
38
  return [
81
39
  `${url}${queryString ? `?${queryString}` : ''}`,
82
40
  {
83
- baseURL: Http.baseUrl,
41
+ baseURL: this.config.baseUrl,
84
42
  method,
85
43
  credentials: 'include',
86
44
  ...options,
87
45
  headers: {
88
46
  Accept: 'application/json',
89
- ...(await Http.headers()),
47
+ ...(await this.config.headers()),
90
48
  ...(xsrfToken && { 'X-Xsrf-Token': xsrfToken }),
91
- ...(Http.lang && { 'Accept-Language': Http.lang }),
49
+ ...(this.config.lang && { 'Accept-Language': this.config.lang }),
92
50
  ...options.headers
93
51
  }
94
52
  }
@@ -96,11 +54,11 @@ export class Http {
96
54
  }
97
55
 
98
56
  private async performRequest<T>(url: string, options: FetchOptions = {}): Promise<T> {
99
- return Http.client(...(await this.buildRequest(url, options)))
57
+ return this.config.client(...(await this.buildRequest(url, options)))
100
58
  }
101
59
 
102
60
  private async performRequestRaw<T>(url: string, options: FetchOptions = {}): Promise<FetchResponse<T>> {
103
- return Http.client.raw(...(await this.buildRequest(url, options)))
61
+ return this.config.client.raw(...(await this.buildRequest(url, options)))
104
62
  }
105
63
 
106
64
  async get<T = any>(url: string, options?: FetchOptions): Promise<T> {
@@ -125,7 +83,7 @@ export class Http {
125
83
 
126
84
  if (hasFile) {
127
85
  const formData = this.objectToFormData(body, undefined, undefined, true)
128
- formData.append(Http.payloadKey, payload)
86
+ formData.append(this.config.payloadKey, payload)
129
87
  body = formData
130
88
  } else {
131
89
  body = payload
@@ -0,0 +1,53 @@
1
+ import { type FetchOptions, type FetchRequest, type FetchResponse, ofetch } from 'ofetch'
2
+ import { defineStore } from 'pinia'
3
+ import { type IStringifyOptions } from 'qs'
4
+ import { computed, ref } from 'vue'
5
+ import { type Lang } from '../composables/Lang'
6
+
7
+ type Awaitable<T> = T | PromiseLike<T>
8
+
9
+ export interface HttpClient {
10
+ (request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<any>
11
+ raw(request: FetchRequest, options?: Omit<FetchOptions, 'method'>): Promise<FetchResponse<any>>
12
+ }
13
+
14
+ export interface HttpOptions {
15
+ baseUrl?: string
16
+ xsrfUrl?: string | false
17
+ client?: HttpClient
18
+ lang?: Lang
19
+ payloadKey?: string
20
+ headers?: () => Awaitable<Record<string, string>>
21
+ stringifyOptions?: IStringifyOptions
22
+ }
23
+
24
+ export const useHttpConfig = defineStore('sefirot-http-config', () => {
25
+ const baseUrl = ref<string | undefined>(undefined)
26
+ const xsrfUrl = ref<string | false>('/api/csrf-cookie')
27
+ const client = ref<HttpClient>(ofetch)
28
+ const lang = ref<Lang | undefined>(undefined)
29
+ const payloadKey = ref<string>('__payload__')
30
+ const headers = ref<() => Awaitable<Record<string, string>>>(async () => ({}))
31
+ const stringifyOptions = ref<IStringifyOptions>({})
32
+
33
+ function apply(options: HttpOptions): void {
34
+ if (options.baseUrl != null) { baseUrl.value = options.baseUrl }
35
+ if (options.xsrfUrl != null) { xsrfUrl.value = options.xsrfUrl }
36
+ if (options.client != null) { client.value = options.client }
37
+ if (options.lang != null) { lang.value = options.lang }
38
+ if (options.payloadKey != null) { payloadKey.value = options.payloadKey }
39
+ if (options.headers != null) { headers.value = options.headers }
40
+ if (options.stringifyOptions != null) { stringifyOptions.value = options.stringifyOptions }
41
+ }
42
+
43
+ return {
44
+ baseUrl: computed(() => baseUrl.value),
45
+ xsrfUrl: computed(() => xsrfUrl.value),
46
+ client: computed(() => client.value),
47
+ lang: computed(() => lang.value),
48
+ payloadKey: computed(() => payloadKey.value),
49
+ headers: computed(() => headers.value),
50
+ stringifyOptions: computed(() => stringifyOptions.value),
51
+ apply
52
+ }
53
+ })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
3
  "type": "module",
4
- "version": "4.29.1",
4
+ "version": "4.30.0",
5
5
  "packageManager": "pnpm@9.15.4",
6
6
  "description": "Vue Components for Global Brain Design System.",
7
7
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",
@@ -121,6 +121,6 @@
121
121
  "vitest": "^3.2.3",
122
122
  "vue": "^3.5.16",
123
123
  "vue-router": "^4.5.1",
124
- "vue-tsc": "^2.2.10"
124
+ "vue-tsc": "^3.0.4"
125
125
  }
126
126
  }