@globalbrain/sefirot 3.49.0 → 4.0.0-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 (106) hide show
  1. package/config/nuxt.d.ts +4 -0
  2. package/config/nuxt.js +31 -0
  3. package/config/vite.d.ts +8 -0
  4. package/config/vite.js +69 -0
  5. package/lib/components/SActionList.vue +0 -1
  6. package/lib/components/SActionListItem.vue +3 -11
  7. package/lib/components/SAlert.vue +8 -13
  8. package/lib/components/SButton.vue +9 -10
  9. package/lib/components/SCardBlock.vue +0 -6
  10. package/lib/components/SControlActionBarClose.vue +1 -1
  11. package/lib/components/SControlActionBarCollapse.vue +2 -2
  12. package/lib/components/SControlInputSearch.vue +2 -2
  13. package/lib/components/SDescAvatar.vue +1 -2
  14. package/lib/components/SDescFile.vue +4 -6
  15. package/lib/components/SDescPill.vue +1 -2
  16. package/lib/components/SDescText.vue +1 -1
  17. package/lib/components/SDropdownSectionDateRange.vue +2 -2
  18. package/lib/components/SDropdownSectionDateRangeDateFromTo.vue +2 -2
  19. package/lib/components/SDropdownSectionDateRangeYear.vue +2 -2
  20. package/lib/components/SDropdownSectionDateRangeYearHalf.vue +2 -2
  21. package/lib/components/SDropdownSectionDateRangeYearQuarter.vue +2 -2
  22. package/lib/components/SDropdownSectionFilter.vue +4 -6
  23. package/lib/components/SIndicator.vue +10 -16
  24. package/lib/components/SInputAddon.vue +6 -8
  25. package/lib/components/SInputBase.vue +6 -8
  26. package/lib/components/SInputCheckbox.vue +7 -11
  27. package/lib/components/SInputCheckboxes.vue +3 -4
  28. package/lib/components/SInputDate.vue +3 -4
  29. package/lib/components/SInputDropdown.vue +10 -13
  30. package/lib/components/SInputDropdownItemAvatar.vue +2 -3
  31. package/lib/components/SInputDropdownItemText.vue +2 -3
  32. package/lib/components/SInputFile.vue +3 -4
  33. package/lib/components/SInputHMS.vue +4 -5
  34. package/lib/components/SInputImage.vue +5 -7
  35. package/lib/components/SInputNumber.vue +10 -11
  36. package/lib/components/SInputRadio.vue +3 -4
  37. package/lib/components/SInputRadios.vue +3 -4
  38. package/lib/components/SInputSegments.vue +3 -4
  39. package/lib/components/SInputSelect.vue +7 -9
  40. package/lib/components/SInputSwitch.vue +3 -4
  41. package/lib/components/SInputSwitches.vue +3 -4
  42. package/lib/components/SInputText.vue +7 -9
  43. package/lib/components/SInputTextarea.vue +3 -4
  44. package/lib/components/SInputYMD.vue +4 -5
  45. package/lib/components/SLink.vue +1 -1
  46. package/lib/components/SLocalNavMenu.vue +3 -4
  47. package/lib/components/SLoginPage.vue +79 -22
  48. package/lib/components/SLoginPagePasswordDialog.vue +95 -0
  49. package/lib/components/SPagination.vue +2 -2
  50. package/lib/components/SPill.vue +1 -5
  51. package/lib/components/SSnackbar.vue +2 -3
  52. package/lib/components/SStep.vue +4 -5
  53. package/lib/components/STable.vue +1 -2
  54. package/lib/components/STableCell.vue +5 -13
  55. package/lib/components/STableCellAvatar.vue +10 -27
  56. package/lib/components/STableCellAvatars.vue +6 -19
  57. package/lib/components/STableCellDay.vue +4 -11
  58. package/lib/components/STableCellNumber.vue +8 -9
  59. package/lib/components/STableCellPill.vue +5 -33
  60. package/lib/components/STableCellPills.vue +4 -14
  61. package/lib/components/STableCellState.vue +3 -3
  62. package/lib/components/STableCellText.vue +22 -50
  63. package/lib/components/STableColumn.vue +4 -6
  64. package/lib/components/STableFooter.vue +4 -5
  65. package/lib/components/STableHeader.vue +2 -19
  66. package/lib/components/STableHeaderMenu.vue +1 -2
  67. package/lib/components/STableHeaderMenuItem.vue +2 -3
  68. package/lib/components/STableItem.vue +1 -1
  69. package/lib/composables/Data.ts +8 -102
  70. package/lib/composables/Error.ts +3 -3
  71. package/lib/composables/Table.ts +17 -22
  72. package/lib/composables/Utils.ts +2 -2
  73. package/lib/composables/Validation.ts +76 -14
  74. package/lib/http/Http.ts +27 -10
  75. package/lib/mixins/Card.ts +0 -27
  76. package/lib/mixins/Fundamental.ts +0 -3
  77. package/lib/support/Day.ts +5 -5
  78. package/lib/support/Utils.ts +35 -14
  79. package/lib/validation/validators/maxLength.ts +2 -2
  80. package/lib/validation/validators/maxValue.ts +2 -2
  81. package/lib/validation/validators/minLength.ts +2 -2
  82. package/lib/validation/validators/minValue.ts +2 -2
  83. package/lib/validation/validators/required.ts +4 -4
  84. package/package.json +40 -40
  85. package/lib/components/SCardFooter.vue +0 -22
  86. package/lib/components/SCardFooterAction.vue +0 -31
  87. package/lib/components/SCardFooterActions.vue +0 -18
  88. package/lib/components/SCardHeader.vue +0 -15
  89. package/lib/components/SCardHeaderAction.vue +0 -28
  90. package/lib/components/SCardHeaderActionClose.vue +0 -27
  91. package/lib/components/SCardHeaderActionCollapse.vue +0 -47
  92. package/lib/components/SCardHeaderActions.vue +0 -13
  93. package/lib/components/SCardHeaderTitle.vue +0 -29
  94. package/lib/components/SIcon.vue +0 -13
  95. package/lib/components/SSheet.vue +0 -87
  96. package/lib/components/SSheetFooter.vue +0 -16
  97. package/lib/components/SSheetFooterAction.vue +0 -34
  98. package/lib/components/SSheetFooterActions.vue +0 -14
  99. package/lib/components/SSheetForm.vue +0 -15
  100. package/lib/components/SSheetMedium.vue +0 -72
  101. package/lib/components/SSheetTitle.vue +0 -13
  102. package/lib/components/STableHeaderActions.vue +0 -20
  103. package/lib/composables/D.ts +0 -21
  104. package/lib/composables/Form.ts +0 -109
  105. package/lib/composables/V.ts +0 -97
  106. package/lib/mixins/Sheet.ts +0 -30
@@ -1,28 +1,18 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
2
  import { type TableCellPillItem } from '../composables/Table'
4
3
  import STableCellPill from './STableCellPill.vue'
5
4
 
6
- const props = defineProps<{
7
- value?: any
8
- record?: any
9
- pills: TableCellPillItem[] | ((value: any, record: any) => TableCellPillItem[])
5
+ defineProps<{
6
+ pills: TableCellPillItem[]
10
7
  }>()
11
-
12
- const items = computed(() => {
13
- return Array.isArray(props.pills)
14
- ? props.pills
15
- : props.pills(props.value, props.record)
16
- })
17
8
  </script>
18
9
 
19
10
  <template>
20
11
  <div class="STableCellPills">
21
12
  <STableCellPill
22
- v-for="item in items"
13
+ v-for="item in pills"
23
14
  :key="item.label"
24
- :value="item.label"
25
- :record="record"
15
+ :pill="item.label"
26
16
  :color="item.color"
27
17
  />
28
18
  </div>
@@ -2,7 +2,7 @@
2
2
  import SState, { type Mode } from './SState.vue'
3
3
 
4
4
  defineProps<{
5
- value?: string
5
+ state?: string
6
6
  mode?: Mode
7
7
  }>()
8
8
  </script>
@@ -10,10 +10,10 @@ defineProps<{
10
10
  <template>
11
11
  <div class="STableCellState" :class="[mode ?? 'neutral']">
12
12
  <SState
13
- v-if="value"
13
+ v-if="state"
14
14
  size="mini"
15
15
  :mode="mode"
16
- :label="value"
16
+ :label="state"
17
17
  />
18
18
  </div>
19
19
  </template>
@@ -1,72 +1,44 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import SIcon from './SIcon.vue'
2
+ import { type Component, computed } from 'vue'
3
+ import { type TableCellValueColor } from '../composables/Table'
4
4
  import SLink from './SLink.vue'
5
5
 
6
- export type Color =
7
- | 'default'
8
- | 'mute'
9
- | 'neutral'
10
- | 'info'
11
- | 'success'
12
- | 'warning'
13
- | 'danger'
14
- | 'soft'
15
-
16
6
  const props = defineProps<{
17
7
  value?: any
18
- record: any
8
+ record?: any
19
9
  align?: 'left' | 'center' | 'right'
20
- icon?: any
21
- getter?: string | null | ((value: any, record: any) => string | null)
22
- color?: Color | ((value: any, record: any) => Color)
23
- iconColor?: Color | ((value: any, record: any) => Color)
24
- link?: string | null | ((value: any, record: any) => string)
10
+ icon?: Component
11
+ text?: string | null
12
+ color?: TableCellValueColor
13
+ iconColor?: TableCellValueColor
14
+ link?: string | null
25
15
  onClick?(value: any, record: any): void
26
16
  }>()
27
17
 
28
- const _value = computed(() => {
29
- if (props.getter === undefined) {
30
- return props.value
31
- }
18
+ const _value = computed(() => props.text ?? props.value)
19
+ const _color = computed(() => props.color ?? 'neutral')
20
+ const _iconColor = computed(() => props.iconColor ?? _color.value)
32
21
 
33
- return typeof props.getter === 'function'
34
- ? props.getter(props.value, props.record)
35
- : props.getter
36
- })
37
-
38
- const _link = computed(() => {
39
- return typeof props.link === 'function'
40
- ? props.link(props.value, props.record)
41
- : props.link
42
- })
43
-
44
- const _color = computed(() => {
45
- return typeof props.color === 'function'
46
- ? props.color(props.value, props.record)
47
- : props.color ?? 'neutral'
48
- })
49
-
50
- const _iconColor = computed(() => {
51
- return typeof props.iconColor === 'function'
52
- ? props.iconColor(props.value, props.record)
53
- : props.iconColor ?? _color.value
54
- })
22
+ const classes = computed(() => [
23
+ props.align ?? 'left',
24
+ _color,
25
+ { link: !!(props.link || props.onClick) }
26
+ ])
55
27
  </script>
56
28
 
57
29
  <template>
58
- <div class="STableCellText" :class="[align ?? 'left', { link: link || onClick }, _color]">
30
+ <div class="STableCellText" :class="classes">
59
31
  <SLink
60
- v-if="_value"
32
+ v-if="_value != null"
61
33
  class="container"
62
- :href="_link"
34
+ :href="link"
63
35
  :role="onClick ? 'button' : null"
64
36
  @click="() => onClick?.(value, record)"
65
37
  >
66
- <div v-if="icon" class="icon" :class="[_iconColor ?? _color]">
67
- <SIcon :icon="icon" class="svg" />
38
+ <div v-if="icon" class="icon" :class="_iconColor">
39
+ <component :is="icon" class="svg" />
68
40
  </div>
69
- <div class="text" :class="[_color]">
41
+ <div class="text" :class="_color">
70
42
  {{ _value }}
71
43
  </div>
72
44
  </SLink>
@@ -1,11 +1,9 @@
1
1
  <script setup lang="ts">
2
- import IconDotsThree from '@iconify-icons/ph/dots-three'
3
2
  import { computed, nextTick, ref, unref, watch } from 'vue'
4
3
  import { type DropdownSection } from '../composables/Dropdown'
5
4
  import { useFlyout } from '../composables/Flyout'
6
- import { isArray } from '../support/Utils'
7
5
  import SDropdown from './SDropdown.vue'
8
- import SIcon from './SIcon.vue'
6
+ import IconDotsThree from '~icons/ph/dots-three'
9
7
 
10
8
  const props = withDefaults(defineProps<{
11
9
  name: string
@@ -40,8 +38,8 @@ const active = computed(() => {
40
38
 
41
39
  const selected = unref(item.selected)
42
40
 
43
- if (!isArray(selected)) {
44
- return selected !== null
41
+ if (!Array.isArray(selected)) {
42
+ return selected != null
45
43
  }
46
44
 
47
45
  if (!selected.length) {
@@ -130,7 +128,7 @@ function stopDialogPositionListener() {
130
128
 
131
129
  <div v-if="dropdown" class="action" ref="container">
132
130
  <button class="button" :class="{ active: buttonActive }" @click="toggle">
133
- <SIcon :icon="IconDotsThree" class="icon" />
131
+ <IconDotsThree class="icon" />
134
132
  </button>
135
133
 
136
134
  <transition name="fade">
@@ -1,9 +1,8 @@
1
1
  <script setup lang="ts">
2
- import IconCaretLeft from '@iconify-icons/ph/caret-left-bold'
3
- import IconCaretRight from '@iconify-icons/ph/caret-right-bold'
4
2
  import { computed } from 'vue'
5
3
  import { format } from '../support/Num'
6
- import SIcon from './SIcon.vue'
4
+ import IconCaretLeft from '~icons/ph/caret-left-bold'
5
+ import IconCaretRight from '~icons/ph/caret-right-bold'
7
6
 
8
7
  const props = defineProps<{
9
8
  total?: number | null
@@ -44,10 +43,10 @@ const hasNext = computed(() => {
44
43
 
45
44
  <div v-if="onPrev && onNext" class="actions">
46
45
  <button class="button prev" :class="{ active: hasPrev }" @click="() => hasPrev && onPrev?.()">
47
- <SIcon :icon="IconCaretLeft" class="icon" />
46
+ <IconCaretLeft class="icon" />
48
47
  </button>
49
48
  <button class="button next" :class="{ active: hasNext }" @click="() => hasNext && onNext?.()">
50
- <SIcon :icon="IconCaretRight" class="icon" />
49
+ <IconCaretRight class="icon" />
51
50
  </button>
52
51
  </div>
53
52
  </div>
@@ -1,23 +1,19 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
- import { type TableHeaderAction, type TableMenu } from '../composables/Table'
3
+ import { type TableMenu } from '../composables/Table'
4
4
  import { format } from '../support/Num'
5
- import { isNullish } from '../support/Utils'
6
- import STableHeaderActions from './STableHeaderActions.vue'
7
5
  import STableHeaderMenu from './STableHeaderMenu.vue'
8
6
 
9
7
  const props = defineProps<{
10
8
  total?: number | null
11
- reset?: boolean
12
9
  menu?: TableMenu[] | TableMenu[][]
13
- actions?: TableHeaderAction[]
14
10
  borderless?: boolean
15
11
  onReset?(): void
16
12
  selected?: unknown[]
17
13
  }>()
18
14
 
19
15
  const stats = computed(() => {
20
- if (isNullish(props.total)) {
16
+ if (props.total == null) {
21
17
  return null
22
18
  }
23
19
 
@@ -25,13 +21,6 @@ const stats = computed(() => {
25
21
  ? `${format(props.selected.length)} of ${props.total} selected`
26
22
  : `${format(props.total)} ${props.total > 1 ? 'records' : 'record'}`
27
23
  })
28
-
29
- // deprecated `reset` prop in favor of `actions`, remove this in next major version
30
- const resetAction = computed(() => {
31
- return props.reset
32
- ? [{ label: 'Reset filters', onClick: props.onReset!, type: 'info' }] // onReset is required when reset is true
33
- : []
34
- })
35
24
  </script>
36
25
 
37
26
  <template>
@@ -41,12 +30,6 @@ const resetAction = computed(() => {
41
30
  <div v-if="stats" class="stats">
42
31
  {{ stats }}
43
32
  </div>
44
- <div v-if="actions?.length" class="actions">
45
- <STableHeaderActions :actions="actions" />
46
- </div>
47
- <div v-else-if="resetAction.length">
48
- <STableHeaderActions :actions="resetAction" />
49
- </div>
50
33
  </div>
51
34
  <div v-if="menu && menu.length" class="menu">
52
35
  <STableHeaderMenu :menu="menu" />
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
  import { type TableMenu } from '../composables/Table'
4
- import { isArray } from '../support/Utils'
5
4
  import STableHeaderMenuItem from './STableHeaderMenuItem.vue'
6
5
 
7
6
  const props = defineProps<{
@@ -9,7 +8,7 @@ const props = defineProps<{
9
8
  }>()
10
9
 
11
10
  const normalizedMenu = computed(() => {
12
- return isArray(props.menu[0])
11
+ return Array.isArray(props.menu[0])
13
12
  ? props.menu as TableMenu[][]
14
13
  : [props.menu] as TableMenu[][]
15
14
  })
@@ -1,9 +1,8 @@
1
1
  <script setup lang="ts">
2
- import IconCaretDown from '@iconify-icons/ph/caret-down-bold'
3
2
  import { type DropdownSection } from '../composables/Dropdown'
4
3
  import { useFlyout } from '../composables/Flyout'
5
4
  import SDropdown from './SDropdown.vue'
6
- import SIcon from './SIcon.vue'
5
+ import IconCaretDown from '~icons/ph/caret-down-bold'
7
6
 
8
7
  defineProps<{
9
8
  label: string
@@ -19,7 +18,7 @@ const { container, isOpen, toggle } = useFlyout()
19
18
  <button class="button" :class="[state]" @click="toggle">
20
19
  <span class="label">{{ label }}</span>
21
20
  <span v-if="state !== 'indicate'" class="caret">
22
- <SIcon class="caret-svg" :icon="IconCaretDown" />
21
+ <IconCaretDown class="caret-svg" />
23
22
  </span>
24
23
  <span v-else class="indicator">
25
24
  <span class="indicator-dot" />
@@ -11,7 +11,7 @@ const classes = computed(() => [
11
11
  'STableItem',
12
12
  props.className,
13
13
  `col-${props.name}`,
14
- { adjusted: props.width },
14
+ { adjusted: !!props.width },
15
15
  { auto: props.width === 'auto' }
16
16
  ])
17
17
  </script>
@@ -1,115 +1,21 @@
1
- /**
2
- * @deprecated Use `composables/D` module instead.
3
- */
1
+ import { type Ref, ref } from 'vue'
4
2
 
5
- import { watchOnce } from '@vueuse/core'
6
- import cloneDeep from 'lodash-es/cloneDeep'
7
- import { type WatchSource, reactive } from 'vue'
8
- import { isNullish, isObject } from '../support/Utils'
9
-
10
- export interface Data<T extends Record<string, any>> {
11
- state: T
3
+ export interface D<T extends Record<string, any>> {
4
+ data: Ref<T>
12
5
  init(): void
13
6
  }
14
7
 
15
- export type DataWithDef = Record<string, any>
16
-
17
- export interface Def<T = any> {
18
- __isDef: true
19
- value: any
20
- source: WatchSource<T>
21
- cb: (value: Exclude<T, undefined>) => void
22
- }
23
-
24
- export type UseDataInput<
25
- T extends Record<string, any>
26
- > = T | ((utils: UseDataInputUtils) => DataWithDef)
27
-
28
- export interface UseDataInputUtils {
29
- def<T>(
30
- value: any,
31
- source: WatchSource<T>,
32
- cb: (value: Exclude<T, null | undefined>) => void
33
- ): Def<T>
34
- }
35
-
36
- export function useData<T extends Record<string, any>>(
37
- data: UseDataInput<T>
38
- ): Data<T> {
39
- const { state, defs } = createState(data)
40
-
41
- const initialState = cloneDeep(state)
42
- const reactiveState = reactive(state)
8
+ export function useData<T extends Record<string, any>>(data: T): D<T> {
9
+ const initialData = JSON.stringify(data)
43
10
 
44
- handleDefs(defs, reactiveState)
11
+ const refData = ref(data) as Ref<T>
45
12
 
46
13
  function init(): void {
47
- Object.assign(reactiveState, initialState)
14
+ refData.value = JSON.parse(initialData) as T
48
15
  }
49
16
 
50
17
  return {
51
- state: reactiveState as T,
18
+ data: refData,
52
19
  init
53
20
  }
54
21
  }
55
-
56
- function createState<T extends Record<string, any>>(
57
- data: UseDataInput<T>
58
- ): { state: T; defs: [string, Def][] } {
59
- if (typeof data !== 'function') {
60
- return { state: data, defs: [] }
61
- }
62
-
63
- const dataWithDef = data({ def })
64
-
65
- const state = {} as T
66
- const defs = [] as [string, Def][]
67
-
68
- for (const key in dataWithDef) {
69
- const maybeDef = dataWithDef[key]
70
-
71
- if (!isDef(maybeDef)) {
72
- (state as any)[key] = maybeDef
73
- continue
74
- }
75
-
76
- (state as any)[key] = maybeDef.value
77
-
78
- defs.push([key, maybeDef])
79
- }
80
-
81
- return {
82
- state,
83
- defs
84
- }
85
- }
86
-
87
- function handleDefs<T extends Record<string, any>>(
88
- defs: [string, Def][],
89
- state: T
90
- ): void {
91
- defs.forEach(([key, def]) => {
92
- watchOnce(def.source, (value: any) => {
93
- if (!isNullish(value)) {
94
- (state as any)[key] = def.cb(value)
95
- }
96
- })
97
- })
98
- }
99
-
100
- function def<T>(
101
- value: any,
102
- source: WatchSource<T>,
103
- cb: (value: Exclude<T, null | undefined>) => void
104
- ): Def {
105
- return {
106
- __isDef: true,
107
- value,
108
- source,
109
- cb
110
- }
111
- }
112
-
113
- function isDef(value: any): boolean {
114
- return isObject(value) ? !!value.__isDef : false
115
- }
@@ -29,7 +29,7 @@ import {
29
29
  toValue
30
30
  } from 'vue'
31
31
  import { useError } from '../stores/Error'
32
- import { isFunction } from '../support/Utils'
32
+ import { isError } from '../support/Utils'
33
33
 
34
34
  export interface User {
35
35
  id?: string | number
@@ -47,7 +47,7 @@ function classify(str: string): string {
47
47
  }
48
48
 
49
49
  function getComponentName(Component: ConcreteComponent): string | undefined {
50
- return isFunction(Component)
50
+ return typeof Component === 'function'
51
51
  ? Component.displayName || Component.name
52
52
  : Component.name || Component.__name
53
53
  }
@@ -232,7 +232,7 @@ function getErrorMessage(error: unknown | undefined) {
232
232
  return error
233
233
  }
234
234
 
235
- if (error instanceof Error) {
235
+ if (isError(error)) {
236
236
  return error.message
237
237
  }
238
238
 
@@ -18,11 +18,6 @@ export interface Table<
18
18
  rowSize?: MaybeRef<number | undefined>
19
19
  borderless?: MaybeRef<boolean>
20
20
  disableSelection?: (record: R) => boolean
21
-
22
- /**
23
- * @deprecated Use `<SControl>` to add equivalent features.
24
- */
25
- actions?: MaybeRef<TableHeaderAction[]>
26
21
  menu?: MaybeRef<TableMenu[] | TableMenu[][]>
27
22
  header?: MaybeRef<boolean | undefined>
28
23
  footer?: MaybeRef<boolean | undefined>
@@ -61,11 +56,11 @@ export type TableCell<V = any, R = any> =
61
56
  | TableCellText<V, R>
62
57
  | TableCellNumber<V, R>
63
58
  | TableCellDay
64
- | TableCellPill<V, R>
65
- | TableCellPills<V, R>
59
+ | TableCellPill
60
+ | TableCellPills
66
61
  | TableCellState
67
62
  | TableCellAvatar<V, R>
68
- | TableCellAvatars<V, R>
63
+ | TableCellAvatars
69
64
  | TableCellCustom
70
65
  | TableCellEmpty
71
66
  | TableCellComponent
@@ -102,10 +97,10 @@ export interface TableCellText<V = any, R = any> extends TableCellBase {
102
97
  type: 'text'
103
98
  align?: 'left' | 'center' | 'right'
104
99
  icon?: any
105
- value?: string | null | ((value: V, record: R) => string | null)
106
- link?: string | null | ((value: V, record: R) => string)
107
- color?: TableCellValueColor | ((value: V, record: R) => TableCellValueColor)
108
- iconColor?: TableCellValueColor | ((value: V, record: R) => TableCellValueColor)
100
+ value?: string | null
101
+ link?: string | null
102
+ color?: TableCellValueColor
103
+ iconColor?: TableCellValueColor
109
104
  onClick?(value: V, record: R): void
110
105
  }
111
106
 
@@ -131,17 +126,17 @@ export interface TableCellDay extends TableCellBase {
131
126
  color?: 'neutral' | 'soft' | 'mute'
132
127
  }
133
128
 
134
- export interface TableCellPill<V = any, R = any> extends TableCellBase {
129
+ export interface TableCellPill extends TableCellBase {
135
130
  type: 'pill'
136
- value?: string | ((value: V, record: R) => string)
137
- color?: TableCellPillColor | ((value: V, record: R) => TableCellPillColor)
131
+ value?: string
132
+ color?: TableCellPillColor
138
133
  }
139
134
 
140
135
  export type TableCellPillColor = ColorModes
141
136
 
142
- export interface TableCellPills<V = any, R = any> extends TableCellBase {
137
+ export interface TableCellPills extends TableCellBase {
143
138
  type: 'pills'
144
- pills: TableCellPillItem[] | ((value: V, record: R) => TableCellPillItem[])
139
+ pills: TableCellPillItem[]
145
140
  }
146
141
 
147
142
  export interface TableCellPillItem {
@@ -151,16 +146,16 @@ export interface TableCellPillItem {
151
146
 
152
147
  export interface TableCellAvatar<V = any, R = any> extends TableCellBase {
153
148
  type: 'avatar'
154
- image?: string | null | ((value: V, record: R) => string | null | undefined)
155
- name?: string | null | ((value: V, record: R) => string | null | undefined)
156
- link?: string | null | ((value: V, record: R) => string | null | undefined)
149
+ image?: string | null
150
+ name?: string | null
151
+ link?: string | null
157
152
  color?: 'neutral' | 'soft' | 'mute'
158
153
  onClick?(value: V, record: R): void
159
154
  }
160
155
 
161
- export interface TableCellAvatars<V = any, R = any> extends TableCellBase {
156
+ export interface TableCellAvatars extends TableCellBase {
162
157
  type: 'avatars'
163
- avatars: TableCellAvatarsOption[] | ((value: V, record: R) => TableCellAvatarsOption[])
158
+ avatars: TableCellAvatarsOption[]
164
159
  color?: 'neutral' | 'soft' | 'mute'
165
160
  avatarCount?: number
166
161
  nameCount?: number
@@ -1,5 +1,5 @@
1
1
  import { type ComputedRef, type MaybeRefOrGetter, computed, getCurrentInstance, onMounted, toValue, useSlots } from 'vue'
2
- import { isArray, isString } from '../support/Utils'
2
+ import { isString } from '../support/Utils'
3
3
 
4
4
  export type WhenCondition<T> = MaybeRefOrGetter<T>
5
5
 
@@ -42,7 +42,7 @@ export function useHasSlotContent(name = 'default'): ComputedRef<boolean> {
42
42
 
43
43
  return computed(() => {
44
44
  return !!slots[name]?.().some((s) => {
45
- return isArray(s.children) ? true : !!(s.children as string).trim()
45
+ return Array.isArray(s.children) ? true : !!(s.children as string).trim()
46
46
  })
47
47
  })
48
48
  }
@@ -1,16 +1,23 @@
1
- /**
2
- * @deprecated Use `composables/V` module instead.
3
- */
4
-
5
1
  import {
6
- type GlobalConfig,
7
2
  type Validation,
8
3
  type ValidationArgs,
4
+ type GlobalConfig as VuelidateConfig,
9
5
  useVuelidate
10
6
  } from '@vuelidate/core'
11
- import { type Ref, type ToRefs } from 'vue'
7
+ import { type MaybeRefOrGetter, type Ref, computed, toValue } from 'vue'
8
+ import { type Snackbar, useSnackbars } from '../stores/Snackbars'
9
+ import { useTrans } from './Lang'
12
10
 
13
- export type { Validation, ValidationArgs, GlobalConfig }
11
+ export interface V<
12
+ Data extends { [key in keyof Rules]: any },
13
+ Rules extends ValidationArgs = ValidationArgs
14
+ > {
15
+ validation: Ref<Validation<Rules, Data>>
16
+ validate(): Promise<boolean>
17
+ validateAndNotify(message?: Snackbar): Promise<boolean>
18
+ notify(message?: Snackbar): void
19
+ reset(): void
20
+ }
14
21
 
15
22
  export interface Validatable {
16
23
  readonly $dirty: boolean
@@ -23,13 +30,68 @@ export interface ValidatableError {
23
30
  readonly $message: string | Ref<string>
24
31
  }
25
32
 
33
+ export interface VNotification {
34
+ notify(message?: Snackbar): void
35
+ }
36
+
26
37
  export function useValidation<
27
- T extends { [key in keyof R]: any },
28
- R extends ValidationArgs = ValidationArgs
38
+ Data extends { [key in keyof Rules]: any },
39
+ Rules extends ValidationArgs = ValidationArgs
29
40
  >(
30
- state: T | Ref<T> | ToRefs<T>,
31
- rules: Ref<R> | R,
32
- config?: GlobalConfig
33
- ): Ref<Validation<R, T>> {
34
- return useVuelidate(rules, state, config)
41
+ data?: MaybeRefOrGetter<Data>,
42
+ rules?: MaybeRefOrGetter<Rules>,
43
+ config?: VuelidateConfig
44
+ ): V<Data, Rules> {
45
+ const { notify } = useVNotification()
46
+
47
+ const d = computed(() => toValue(data) ?? {})
48
+ const r = computed(() => toValue(rules) ?? {})
49
+
50
+ const validation = useVuelidate(r, d, config) as any
51
+
52
+ function reset(): void {
53
+ validation.value.$reset()
54
+ }
55
+
56
+ function validate(): Promise<boolean> {
57
+ return validation.value.$validate()
58
+ }
59
+
60
+ async function validateAndNotify(message?: Snackbar): Promise<boolean> {
61
+ const valid = await validate()
62
+
63
+ if (!valid) {
64
+ notify(message)
65
+ }
66
+
67
+ return valid
68
+ }
69
+
70
+ return {
71
+ validation,
72
+ validate,
73
+ validateAndNotify,
74
+ notify,
75
+ reset
76
+ }
77
+ }
78
+
79
+ export function useVNotification(): VNotification {
80
+ const { t } = useTrans({
81
+ en: { notify: 'Form contains errors. Please correct them and try again.' },
82
+ ja: { notify: 'フォームにエラーがあります。内容を確認し、再度お試しください。' }
83
+ })
84
+
85
+ const snackbars = useSnackbars()
86
+
87
+ function notify(message?: Snackbar): void {
88
+ snackbars.push(message ?? {
89
+ mode: 'danger',
90
+ text: t.notify
91
+ })
92
+ }
93
+
94
+ return {
95
+ notify
96
+ }
35
97
  }