@globalbrain/sefirot 4.43.5 → 4.45.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/README.md +5 -5
- package/config/vite.js +1 -24
- package/lib/blocks/lens/FieldData.ts +46 -0
- package/lib/blocks/lens/Rule.ts +6 -0
- package/lib/blocks/lens/components/LensCatalog.vue +57 -2
- package/lib/blocks/lens/components/LensCatalogControl.vue +9 -0
- package/lib/blocks/lens/components/LensCatalogStateFilterCondition.vue +13 -7
- package/lib/blocks/lens/components/LensFormFilter.vue +22 -3
- package/lib/blocks/lens/components/LensFormFilterCondition.vue +6 -0
- package/lib/blocks/lens/components/LensFormOverrideBase.vue +6 -0
- package/lib/blocks/lens/components/LensFormOverrideNumber.vue +166 -0
- package/lib/blocks/lens/components/LensFormView.vue +31 -4
- package/lib/blocks/lens/components/LensTable.vue +18 -5
- package/lib/blocks/lens/composables/SetupLens.ts +6 -0
- package/lib/blocks/lens/fields/BooleanField.ts +76 -0
- package/lib/blocks/lens/fields/DateField.ts +9 -1
- package/lib/blocks/lens/fields/DatetimeField.ts +8 -1
- package/lib/blocks/lens/fields/DecimalField.ts +60 -0
- package/lib/blocks/lens/fields/Field.ts +24 -1
- package/lib/blocks/lens/fields/NumberField.ts +25 -4
- package/lib/blocks/lens/fields/RelatedManyField.ts +29 -5
- package/lib/blocks/lens/fields/RelatedOneField.ts +119 -0
- package/lib/blocks/lens/fields/TextField.ts +2 -0
- package/lib/blocks/lens/fields/support/Renderers.ts +78 -0
- package/lib/blocks/lens/filter-inputs/SelectFilterInput.ts +5 -1
- package/lib/blocks/lens/validation/RuleMapper.ts +3 -1
- package/lib/components/SInputFileUpload.vue +17 -2
- package/lib/components/SInputFileUploadItem.vue +57 -16
- package/lib/components/STableCell.vue +1 -0
- package/lib/components/STableCellNumber.vue +25 -2
- package/lib/composables/Table.ts +6 -0
- package/lib/http/Http.ts +8 -13
- package/lib/support/Chart.ts +7 -3
- package/lib/support/Day.ts +5 -4
- package/lib/support/File.ts +25 -0
- package/lib/support/Num.ts +3 -2
- package/lib/support/Utils.ts +13 -0
- package/lib/validation/validators/maxLength.ts +3 -1
- package/lib/validation/validators/maxTotalFileSize.ts +10 -2
- package/lib/validation/validators/minLength.ts +3 -1
- package/package.json +34 -35
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import IconFileText from '~icons/ph/file-text'
|
|
3
3
|
import IconTrash from '~icons/ph/trash'
|
|
4
4
|
import { type ValidationRuleWithParams } from '@vuelidate/core'
|
|
5
|
-
import { type Component, computed } from 'vue'
|
|
5
|
+
import { type Component, computed, watch } from 'vue'
|
|
6
6
|
import { useValidation } from '../composables/Validation'
|
|
7
7
|
import { formatSize } from '../support/File'
|
|
8
8
|
import SButton, { type Mode as ButtonMode } from './SButton.vue'
|
|
@@ -27,7 +27,7 @@ export interface Action {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const props = defineProps<{
|
|
30
|
-
file: File | FileObject
|
|
30
|
+
file: File | FileObject | string
|
|
31
31
|
rules?: Record<string, ValidationRuleWithParams>
|
|
32
32
|
}>()
|
|
33
33
|
|
|
@@ -35,23 +35,64 @@ defineEmits<{
|
|
|
35
35
|
remove: []
|
|
36
36
|
}>()
|
|
37
37
|
|
|
38
|
-
const _file = computed(() =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
const _file = computed(() => {
|
|
39
|
+
const value = props.file
|
|
40
|
+
|
|
41
|
+
if (value instanceof File) {
|
|
42
|
+
return {
|
|
43
|
+
name: value.name,
|
|
44
|
+
file: value as File | null,
|
|
45
|
+
size: formatSize(value) as string | null,
|
|
46
|
+
indicatorState: null as IndicatorState | null,
|
|
47
|
+
canRemove: true,
|
|
48
|
+
action: null as Action | null,
|
|
49
|
+
errorMessage: null as string | null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// A plain string references an already-uploaded file: show its basename
|
|
54
|
+
// and skip the size (unknown for server-side files).
|
|
55
|
+
if (typeof value === 'string') {
|
|
56
|
+
return {
|
|
57
|
+
name: value.split('/').pop() || value,
|
|
58
|
+
file: null,
|
|
59
|
+
size: null,
|
|
60
|
+
indicatorState: null,
|
|
61
|
+
canRemove: true,
|
|
62
|
+
action: null,
|
|
63
|
+
errorMessage: null
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
name: value.file.name,
|
|
69
|
+
file: value.file as File | null,
|
|
70
|
+
size: formatSize(value.file) as string | null,
|
|
71
|
+
indicatorState: value.indicatorState ?? null,
|
|
72
|
+
canRemove: value.canRemove ?? true,
|
|
73
|
+
action: value.action ?? null,
|
|
74
|
+
errorMessage: value.errorMessage ?? null
|
|
75
|
+
}
|
|
76
|
+
})
|
|
47
77
|
|
|
78
|
+
// Rules are passed as a getter so validation reacts when the item's
|
|
79
|
+
// identity changes — the parent keys items by index, so a single instance
|
|
80
|
+
// can be reused for a different item after a removal. Per-file rules apply
|
|
81
|
+
// to newly selected `File`s only; an already-uploaded `string` reference
|
|
82
|
+
// has no local file to validate, so it's skipped (the server validates it).
|
|
48
83
|
const { validation } = useValidation(() => ({
|
|
49
84
|
file: _file.value.file
|
|
50
|
-
}), {
|
|
51
|
-
file: props.rules ?? {}
|
|
52
|
-
})
|
|
85
|
+
}), () => ({
|
|
86
|
+
file: typeof props.file === 'string' ? {} : (props.rules ?? {})
|
|
87
|
+
}))
|
|
53
88
|
|
|
54
|
-
validation
|
|
89
|
+
// Surface validation immediately, and re-touch whenever the item changes:
|
|
90
|
+
// when an index-keyed instance is reused for a different item, switching
|
|
91
|
+
// rules resets the dirty state, so a post-flush re-touch is needed to keep
|
|
92
|
+
// the new item's errors visible.
|
|
93
|
+
watch(() => props.file, () => {
|
|
94
|
+
validation.value.$touch()
|
|
95
|
+
}, { immediate: true, flush: 'post' })
|
|
55
96
|
</script>
|
|
56
97
|
|
|
57
98
|
<template>
|
|
@@ -84,7 +125,7 @@ validation.value.$touch()
|
|
|
84
125
|
/>
|
|
85
126
|
</div>
|
|
86
127
|
<div class="meta">
|
|
87
|
-
<div class="size">
|
|
128
|
+
<div v-if="_file.size" class="size">
|
|
88
129
|
{{ _file.size }}
|
|
89
130
|
</div>
|
|
90
131
|
<div class="delete">
|
|
@@ -54,6 +54,7 @@ const valueIsImagePath = computed(() => {
|
|
|
54
54
|
:icon="computedCell.icon"
|
|
55
55
|
:number="computedCell.value ?? value"
|
|
56
56
|
:separator="computedCell.separator"
|
|
57
|
+
:maximum-fraction-digits="computedCell.maximumFractionDigits"
|
|
57
58
|
:link="computedCell.link"
|
|
58
59
|
:color="computedCell.color"
|
|
59
60
|
:icon-color="computedCell.iconColor"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { type Component, computed } from 'vue'
|
|
3
3
|
import { type TableCellValueColor } from '../composables/Table'
|
|
4
|
-
import { format } from '../support/Num'
|
|
5
4
|
import SLink from './SLink.vue'
|
|
6
5
|
|
|
7
6
|
const props = defineProps<{
|
|
@@ -11,6 +10,7 @@ const props = defineProps<{
|
|
|
11
10
|
icon?: Component
|
|
12
11
|
number?: number | null
|
|
13
12
|
separator?: boolean
|
|
13
|
+
maximumFractionDigits?: number | null
|
|
14
14
|
color?: TableCellValueColor
|
|
15
15
|
iconColor?: TableCellValueColor
|
|
16
16
|
link?: string | null
|
|
@@ -25,6 +25,29 @@ const classes = computed(() => [
|
|
|
25
25
|
_color,
|
|
26
26
|
{ link: !!(props.link || props.onClick) }
|
|
27
27
|
])
|
|
28
|
+
|
|
29
|
+
// We format the value inline (rather than via `Num.format`) so we can
|
|
30
|
+
// thread `useGrouping` and `maximumFractionDigits` through the same
|
|
31
|
+
// `toLocaleString` call. `Num.format` is kept for callers that just
|
|
32
|
+
// want the default separator-on / unbounded-digits behavior.
|
|
33
|
+
//
|
|
34
|
+
// When neither `separator` nor `maximumFractionDigits` is requested we
|
|
35
|
+
// return the raw number and let Vue's template interpolation stringify
|
|
36
|
+
// it. `toLocaleString` would otherwise round very small numbers to
|
|
37
|
+
// `"0"` (e.g. `1e-25` → `"0"` at 20 digits), losing information that
|
|
38
|
+
// the plain `String(number)` form preserves via scientific notation.
|
|
39
|
+
const formatted = computed(() => {
|
|
40
|
+
if (props.number == null) {
|
|
41
|
+
return ''
|
|
42
|
+
}
|
|
43
|
+
if (!props.separator && props.maximumFractionDigits == null) {
|
|
44
|
+
return props.number
|
|
45
|
+
}
|
|
46
|
+
return props.number.toLocaleString('en-US', {
|
|
47
|
+
useGrouping: props.separator === true,
|
|
48
|
+
maximumFractionDigits: props.maximumFractionDigits ?? 20
|
|
49
|
+
})
|
|
50
|
+
})
|
|
28
51
|
</script>
|
|
29
52
|
|
|
30
53
|
<template>
|
|
@@ -40,7 +63,7 @@ const classes = computed(() => [
|
|
|
40
63
|
<component :is="icon" class="svg" />
|
|
41
64
|
</div>
|
|
42
65
|
<div class="value" :class="_color">
|
|
43
|
-
{{
|
|
66
|
+
{{ formatted }}
|
|
44
67
|
</div>
|
|
45
68
|
</SLink>
|
|
46
69
|
</div>
|
package/lib/composables/Table.ts
CHANGED
|
@@ -115,6 +115,12 @@ export interface TableCellNumber<V = any, R = any> extends TableCellBase {
|
|
|
115
115
|
icon?: Component
|
|
116
116
|
value?: number | null
|
|
117
117
|
separator?: boolean
|
|
118
|
+
/**
|
|
119
|
+
* Caps the displayed fractional digits using
|
|
120
|
+
* `Intl.NumberFormat`-style "maximum fractional digits" semantics.
|
|
121
|
+
* `null` / `undefined` shows the value as-is (no rounding).
|
|
122
|
+
*/
|
|
123
|
+
maximumFractionDigits?: number | null
|
|
118
124
|
link?: string | null
|
|
119
125
|
color?: TableCellValueColor
|
|
120
126
|
iconColor?: TableCellValueColor
|
package/lib/http/Http.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parse as parseContentDisposition } from '@tinyhttp/content-disposition'
|
|
2
2
|
import { parse as parseCookie } from '@tinyhttp/cookie'
|
|
3
|
-
import FileSaver from 'file-saver'
|
|
4
3
|
import { FetchError, type FetchOptions, type FetchResponse } from 'ofetch'
|
|
5
4
|
import { stringify } from 'qs'
|
|
5
|
+
import { saveAs } from '../support/File'
|
|
6
6
|
import { objectToFormData } from '../support/Http'
|
|
7
7
|
|
|
8
8
|
type Config = ReturnType<typeof import('../stores/HttpConfig').useHttpConfig>
|
|
@@ -116,20 +116,15 @@ export class Http {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
async download(url: string, options?: FetchOptions): Promise<void> {
|
|
119
|
-
const { _data: blob, headers } =
|
|
120
|
-
method: 'GET',
|
|
121
|
-
responseType: 'blob',
|
|
122
|
-
...options
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
if (!blob) {
|
|
126
|
-
throw new Error('No blob')
|
|
127
|
-
}
|
|
119
|
+
const { _data: blob, headers } =
|
|
120
|
+
await this.performRequestRaw<Blob>(url, { method: 'GET', responseType: 'blob', ...options })
|
|
128
121
|
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
let filename
|
|
123
|
+
try {
|
|
124
|
+
filename = parseContentDisposition(headers.get('Content-Disposition') || '').parameters.filename
|
|
125
|
+
} catch {}
|
|
131
126
|
|
|
132
|
-
|
|
127
|
+
saveAs(blob, filename as string | undefined)
|
|
133
128
|
}
|
|
134
129
|
}
|
|
135
130
|
|
package/lib/support/Chart.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* https://github.com/radix-ui/colors/blob/main/LICENSE
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import FileSaver from 'file-saver'
|
|
10
9
|
import html2canvas from 'html2canvas'
|
|
10
|
+
import { saveAs } from './File'
|
|
11
11
|
|
|
12
12
|
export const c = {
|
|
13
13
|
text1: 'light-dark(#1c2024, #edeef0)',
|
|
@@ -86,6 +86,10 @@ export async function exportAsPng(_el: any, fileName = 'chart.png', delay = 0):
|
|
|
86
86
|
}
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
const
|
|
90
|
-
|
|
89
|
+
const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/png'))
|
|
90
|
+
if (!blob) {
|
|
91
|
+
throw new Error('Failed to export chart as PNG: unable to create blob from canvas')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
saveAs(blob, fileName)
|
|
91
95
|
}
|
package/lib/support/Day.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import dayjs, { type ConfigType, type Dayjs } from 'dayjs'
|
|
2
|
-
import PluginRelativeTime from 'dayjs/plugin/relativeTime'
|
|
3
|
-
import PluginTimezone from 'dayjs/plugin/timezone'
|
|
4
|
-
import PluginUtc from 'dayjs/plugin/utc'
|
|
1
|
+
import dayjs, { type ConfigType, type Dayjs } from 'dayjs/esm'
|
|
2
|
+
import PluginRelativeTime from 'dayjs/esm/plugin/relativeTime'
|
|
3
|
+
import PluginTimezone from 'dayjs/esm/plugin/timezone'
|
|
4
|
+
import PluginUtc from 'dayjs/esm/plugin/utc'
|
|
5
|
+
import 'dayjs/esm/locale/ja'
|
|
5
6
|
|
|
6
7
|
dayjs.extend(PluginUtc)
|
|
7
8
|
dayjs.extend(PluginTimezone)
|
package/lib/support/File.ts
CHANGED
|
@@ -13,3 +13,28 @@ export function formatSize(files: File | File[]): string {
|
|
|
13
13
|
const i = Math.min(Math.floor(Math.log(size) / Math.log(1000)), units.length - 1)
|
|
14
14
|
return `${(size / 1000 ** i).toFixed(2)} ${units[i]}`
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
export function saveAs(blob: Blob | undefined, filename: string | undefined): void {
|
|
18
|
+
if (typeof window === 'undefined') {
|
|
19
|
+
throw new TypeError('saveAs can only be used in a browser environment.')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!(blob instanceof Blob)) {
|
|
23
|
+
throw new TypeError('The first argument must be a Blob.')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const url = URL.createObjectURL(blob)
|
|
27
|
+
const anchor = document.createElement('a')
|
|
28
|
+
anchor.href = url
|
|
29
|
+
anchor.download = filename || 'download'
|
|
30
|
+
anchor.rel = 'noopener'
|
|
31
|
+
anchor.style.display = 'none'
|
|
32
|
+
|
|
33
|
+
document.body.appendChild(anchor)
|
|
34
|
+
anchor.click()
|
|
35
|
+
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
anchor.remove()
|
|
38
|
+
URL.revokeObjectURL(url)
|
|
39
|
+
}, 4e4)
|
|
40
|
+
}
|
package/lib/support/Num.ts
CHANGED
|
@@ -2,8 +2,9 @@ export function format(value: number): string {
|
|
|
2
2
|
return value.toLocaleString('en-US', { maximumFractionDigits: 20 })
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
export function abbreviate(value: number, precision = 0): string {
|
|
6
|
-
|
|
5
|
+
export function abbreviate(value: number, precision = 0, lang: 'en' | 'ja' = 'en'): string {
|
|
6
|
+
const locale = lang === 'ja' ? 'ja-JP' : 'en-US'
|
|
7
|
+
return value.toLocaleString(locale, {
|
|
7
8
|
notation: 'compact',
|
|
8
9
|
maximumFractionDigits: precision
|
|
9
10
|
})
|
package/lib/support/Utils.ts
CHANGED
|
@@ -14,3 +14,16 @@ export function isObject(value: unknown): value is Record<PropertyKey, unknown>
|
|
|
14
14
|
export function isString(value: unknown): value is string {
|
|
15
15
|
return typeof value === 'string'
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
export function getLength(value: unknown): number {
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
// Count Unicode code points, not UTF-16 code units (which `String.length`
|
|
21
|
+
// returns). This matches how the database measures column length (MySQL
|
|
22
|
+
// `CHAR_LENGTH`, PostgreSQL `length`) and the backend's PHP `mb_strlen`.
|
|
23
|
+
return [...value].length
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
return value.length
|
|
27
|
+
}
|
|
28
|
+
throw new TypeError('Value must be a string or an array')
|
|
29
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getLength } from '../../support/Utils'
|
|
2
|
+
|
|
1
3
|
export function maxLength(value: unknown, length: number): boolean {
|
|
2
|
-
return (
|
|
4
|
+
try { return getLength(value) <= length } catch { return false }
|
|
3
5
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export function maxTotalFileSize(value: unknown, size: string): boolean {
|
|
2
|
-
|
|
2
|
+
// The model may mix freshly selected `File`s with `string` references to
|
|
3
|
+
// already-uploaded files (see `SInputFileUpload`). Reject anything else,
|
|
4
|
+
// but allow string references through — only `File`s contribute to the
|
|
5
|
+
// total, since an already-uploaded file has no client-side size (the
|
|
6
|
+
// server validates its real size). This means the total under-counts kept
|
|
7
|
+
// files, which is accepted for now.
|
|
8
|
+
if (!Array.isArray(value) || !value.every((v) => v instanceof File || typeof v === 'string')) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
3
11
|
|
|
4
12
|
const factor = /gb/i.test(size) ? 1e9 : /mb/i.test(size) ? 1e6 : /kb/i.test(size) ? 1e3 : 1
|
|
5
|
-
const total = value.reduce((total, file) => total + file.size, 0)
|
|
13
|
+
const total = value.reduce((total, file) => total + (file instanceof File ? file.size : 0), 0)
|
|
6
14
|
|
|
7
15
|
return total <= factor * Number.parseFloat(size.replace(/[^\d.]/g, ''))
|
|
8
16
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getLength } from '../../support/Utils'
|
|
2
|
+
|
|
1
3
|
export function minLength(value: unknown, length: number): boolean {
|
|
2
|
-
return (
|
|
4
|
+
try { return getLength(value) >= length } catch { return false }
|
|
3
5
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globalbrain/sefirot",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.45.0",
|
|
4
4
|
"description": "Vue Components for Global Brain Design System.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"./*": "./*"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"docs": "pnpm
|
|
40
|
+
"docs": "pnpm docs:dev",
|
|
41
41
|
"docs:dev": "vitepress dev docs --port 4011",
|
|
42
42
|
"docs:build": "vitepress build docs",
|
|
43
43
|
"docs:preview": "vitepress serve docs --port 4011",
|
|
44
|
-
"story": "pnpm
|
|
44
|
+
"story": "pnpm story:dev",
|
|
45
45
|
"story:dev": "NODE_NO_WARNINGS=1 VITE_CJS_IGNORE_WARNING=1 histoire dev --port 4010",
|
|
46
46
|
"story:build": "NODE_NO_WARNINGS=1 VITE_CJS_IGNORE_WARNING=1 histoire build",
|
|
47
47
|
"story:preview": "NODE_NO_WARNINGS=1 VITE_CJS_IGNORE_WARNING=1 histoire preview --port 4010",
|
|
@@ -51,72 +51,71 @@
|
|
|
51
51
|
"test": "vitest",
|
|
52
52
|
"test:fail": "vitest run",
|
|
53
53
|
"test:coverage": "vitest run --coverage",
|
|
54
|
-
"check": "pnpm run type
|
|
54
|
+
"check": "pnpm run --aggregate-output '/^(type|lint|test:fail)$/'",
|
|
55
|
+
"check:fail": "pnpm run --aggregate-output '/^(type|lint:fail|test:fail)$/'",
|
|
55
56
|
"release": "pnpm whoami >/dev/null 2>&1 || pnpm login && release-it"
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@iconify-json/ph": "^1.2.2",
|
|
59
60
|
"@iconify-json/ri": "^1.2.10",
|
|
60
61
|
"@popperjs/core": "^2.11.8",
|
|
61
|
-
"@sentry/browser": "^10.
|
|
62
|
-
"@sentry/vue": "^10.
|
|
62
|
+
"@sentry/browser": "^10.55.0",
|
|
63
|
+
"@sentry/vue": "^10.55.0",
|
|
63
64
|
"@tanstack/vue-virtual": "3.0.0-beta.62",
|
|
64
65
|
"@tinyhttp/content-disposition": "^2.2.4",
|
|
65
66
|
"@tinyhttp/cookie": "^2.1.1",
|
|
66
67
|
"@total-typescript/ts-reset": "^0.6.1",
|
|
67
68
|
"@types/body-scroll-lock": "^3.1.2",
|
|
68
69
|
"@types/d3": "^7.4.3",
|
|
69
|
-
"@types/file-saver": "^2.0.7",
|
|
70
70
|
"@types/lodash-es": "^4.17.12",
|
|
71
71
|
"@types/markdown-it": "^14.1.2",
|
|
72
|
-
"@types/qs": "^6.15.
|
|
73
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
74
|
-
"@vue/reactivity": "^3.5.
|
|
72
|
+
"@types/qs": "^6.15.1",
|
|
73
|
+
"@vitejs/plugin-vue": "^6.0.7",
|
|
74
|
+
"@vue/reactivity": "^3.5.35",
|
|
75
75
|
"@vuelidate/core": "^2.0.3",
|
|
76
76
|
"@vuelidate/validators": "^2.0.4",
|
|
77
|
-
"@vueuse/core": "^14.
|
|
77
|
+
"@vueuse/core": "^14.3.0",
|
|
78
78
|
"body-scroll-lock": "4.0.0-beta.0",
|
|
79
79
|
"d3": "^7.9.0",
|
|
80
|
-
"dayjs": "^1.11.
|
|
81
|
-
"dompurify": "^3.
|
|
82
|
-
"
|
|
83
|
-
"fuse.js": "^7.2.0",
|
|
80
|
+
"dayjs": "^1.11.21",
|
|
81
|
+
"dompurify": "^3.4.7",
|
|
82
|
+
"fuse.js": "^7.3.0",
|
|
84
83
|
"html2canvas": "^1.4.1",
|
|
85
|
-
"jsdom": "^29.
|
|
84
|
+
"jsdom": "^29.1.1",
|
|
86
85
|
"lodash-es": "^4.18.1",
|
|
87
86
|
"magic-string": "^0.30.21",
|
|
88
|
-
"markdown-it": "^14.
|
|
87
|
+
"markdown-it": "^14.2.0",
|
|
89
88
|
"normalize.css": "^8.0.1",
|
|
90
89
|
"ofetch": "^1.5.1",
|
|
91
90
|
"pinia": "^3.0.4",
|
|
92
|
-
"postcss": "^8.5.
|
|
91
|
+
"postcss": "^8.5.15",
|
|
93
92
|
"postcss-nested": "^7.0.2",
|
|
94
93
|
"punycode": "^2.3.1",
|
|
95
|
-
"qs": "^6.15.
|
|
94
|
+
"qs": "^6.15.2",
|
|
96
95
|
"unplugin-icons": "^23.0.1",
|
|
97
96
|
"v-calendar": "3.0.1",
|
|
98
|
-
"vite": "^7.3.
|
|
99
|
-
"vue": "^3.5.
|
|
97
|
+
"vite": "^7.3.3",
|
|
98
|
+
"vue": "^3.5.35",
|
|
100
99
|
"vue-draggable-plus": "^0.6.1",
|
|
101
|
-
"vue-router": "^5.0
|
|
100
|
+
"vue-router": "^5.1.0"
|
|
102
101
|
},
|
|
103
102
|
"devDependencies": {
|
|
104
|
-
"@globalbrain/eslint-config": "^3.0
|
|
103
|
+
"@globalbrain/eslint-config": "^3.1.0",
|
|
105
104
|
"@histoire/plugin-vue": "1.0.0-beta.1",
|
|
106
|
-
"@release-it/conventional-changelog": "^
|
|
107
|
-
"@types/jsdom": "^28.0.
|
|
108
|
-
"@types/node": "^25.
|
|
109
|
-
"@typescript-eslint/rule-tester": "^8.
|
|
110
|
-
"@vitest/coverage-v8": "^4.1.
|
|
111
|
-
"@vue/test-utils": "^2.4.
|
|
105
|
+
"@release-it/conventional-changelog": "^11.0.1",
|
|
106
|
+
"@types/jsdom": "^28.0.3",
|
|
107
|
+
"@types/node": "^25.9.1",
|
|
108
|
+
"@typescript-eslint/rule-tester": "^8.60.0",
|
|
109
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
110
|
+
"@vue/test-utils": "^2.4.10",
|
|
112
111
|
"eslint": "^9.39.4",
|
|
113
|
-
"happy-dom": "^20.
|
|
112
|
+
"happy-dom": "^20.9.0",
|
|
114
113
|
"histoire": "1.0.0-beta.1",
|
|
115
|
-
"release-it": "^
|
|
116
|
-
"typescript": "~
|
|
114
|
+
"release-it": "^20.2.0",
|
|
115
|
+
"typescript": "~6.0.3",
|
|
117
116
|
"vitepress": "^2.0.0-alpha.17",
|
|
118
|
-
"vitest": "^4.1.
|
|
119
|
-
"vue-tsc": "^3.
|
|
117
|
+
"vitest": "^4.1.7",
|
|
118
|
+
"vue-tsc": "^3.3.3"
|
|
120
119
|
},
|
|
121
|
-
"packageManager": "pnpm@
|
|
120
|
+
"packageManager": "pnpm@11.5.0"
|
|
122
121
|
}
|