@globalbrain/sefirot 4.34.1 → 4.35.1
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/config/nuxt.js +44 -1
- package/config/vite.js +2 -3
- package/lib/blocks/lens/FieldContext.ts +5 -0
- package/lib/blocks/lens/FieldData.ts +140 -0
- package/lib/blocks/lens/FieldRegistry.ts +23 -0
- package/lib/blocks/lens/FileDownloader.ts +1 -0
- package/lib/blocks/lens/FilterOperator.ts +33 -0
- package/lib/blocks/lens/LensQuery.ts +10 -0
- package/lib/blocks/lens/LensResult.ts +20 -0
- package/lib/blocks/lens/ResourceFetcher.ts +3 -0
- package/lib/blocks/lens/Rule.ts +12 -0
- package/lib/blocks/lens/components/LensCatalog.vue +490 -0
- package/lib/blocks/lens/components/LensCatalogControl.vue +220 -0
- package/lib/blocks/lens/components/LensCatalogFooter.vue +46 -0
- package/lib/blocks/lens/components/LensCatalogStateFilter.vue +171 -0
- package/lib/blocks/lens/components/LensCatalogStateFilterCondition.vue +86 -0
- package/lib/blocks/lens/components/LensCatalogStateFilterGroup.vue +102 -0
- package/lib/blocks/lens/components/LensCatalogStateSort.vue +159 -0
- package/lib/blocks/lens/components/LensFormFilter.vue +169 -0
- package/lib/blocks/lens/components/LensFormFilterCondition.vue +205 -0
- package/lib/blocks/lens/components/LensFormFilterGroup.vue +175 -0
- package/lib/blocks/lens/components/LensFormOverride.vue +45 -0
- package/lib/blocks/lens/components/LensFormOverrideBase.vue +204 -0
- package/lib/blocks/lens/components/LensFormView.vue +347 -0
- package/lib/blocks/lens/components/LensTable.vue +154 -0
- package/lib/blocks/lens/composables/FieldFactory.ts +27 -0
- package/lib/blocks/lens/composables/FieldRegistry.ts +16 -0
- package/lib/blocks/lens/composables/FileDownloader.ts +10 -0
- package/lib/blocks/lens/composables/ResourceFetcher.ts +30 -0
- package/lib/blocks/lens/composables/SetupLens.ts +55 -0
- package/lib/blocks/lens/fields/ContentField.ts +34 -0
- package/lib/blocks/lens/fields/DateField.ts +66 -0
- package/lib/blocks/lens/fields/DatetimeField.ts +35 -0
- package/lib/blocks/lens/fields/Field.ts +244 -0
- package/lib/blocks/lens/fields/FileUploadField.ts +63 -0
- package/lib/blocks/lens/fields/IdField.ts +34 -0
- package/lib/blocks/lens/fields/LinkField.ts +53 -0
- package/lib/blocks/lens/fields/NumberField.ts +32 -0
- package/lib/blocks/lens/fields/RelatedManyField.ts +62 -0
- package/lib/blocks/lens/fields/SelectField.ts +198 -0
- package/lib/blocks/lens/fields/SlackMessageField.ts +34 -0
- package/lib/blocks/lens/fields/TextField.ts +46 -0
- package/lib/blocks/lens/fields/TextareaField.ts +49 -0
- package/lib/blocks/lens/filter-inputs/FilterInput.ts +72 -0
- package/lib/blocks/lens/filter-inputs/NumberFilterInput.ts +26 -0
- package/lib/blocks/lens/filter-inputs/SelectFilterInput.ts +76 -0
- package/lib/blocks/lens/filter-inputs/TextFilterInput.ts +26 -0
- package/lib/blocks/lens/validation/RuleMapper.ts +22 -0
- package/lib/components/SInputTextarea.vue +28 -10
- package/lib/components/STable.vue +230 -61
- package/lib/components/STableCell.vue +2 -2
- package/lib/composables/TableAnimation.ts +180 -0
- package/lib/support/Scroll.ts +263 -0
- package/lib/support/Utils.ts +1 -1
- package/package.json +7 -15
package/config/nuxt.js
CHANGED
|
@@ -56,5 +56,48 @@ export const baseConfig = {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export function defineConfig(config = {}) {
|
|
59
|
-
return
|
|
59
|
+
return mergeConfig(baseConfig, config)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @template T
|
|
64
|
+
* @param {T} a
|
|
65
|
+
* @param {Partial<T>} b
|
|
66
|
+
* @see https://github.com/vuejs/vitepress/blob/d4796a0373eb486766cf48e63fdf461681424d43/src/node/config.ts#L291
|
|
67
|
+
*/
|
|
68
|
+
function mergeConfig(a, b, isRoot = true) {
|
|
69
|
+
const merged = /** @type {any} */ ({ ...a })
|
|
70
|
+
for (const key in b) {
|
|
71
|
+
const value = /** @type {any} */ (b[key])
|
|
72
|
+
if (value == null) {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
const existing = merged[key]
|
|
76
|
+
if (Array.isArray(existing) && Array.isArray(value)) {
|
|
77
|
+
merged[key] = [...existing, ...value]
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if (isObject(existing) && isObject(value)) {
|
|
81
|
+
if (isRoot && key === 'vite') {
|
|
82
|
+
merged[key] = vite.mergeConfig(existing, value)
|
|
83
|
+
} else {
|
|
84
|
+
merged[key] = mergeConfig(existing, value, false)
|
|
85
|
+
}
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
merged[key] = value
|
|
89
|
+
}
|
|
90
|
+
return merged
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {unknown} value
|
|
95
|
+
* @return {value is Record<PropertyKey, unknown>}
|
|
96
|
+
* @see file://./../lib/support/Utils.ts#isObject
|
|
97
|
+
*/
|
|
98
|
+
function isObject(value) {
|
|
99
|
+
if (value == null || typeof value !== 'object') { return false }
|
|
100
|
+
|
|
101
|
+
const proto = Object.getPrototypeOf(value)
|
|
102
|
+
return proto === null || proto === Object.prototype
|
|
60
103
|
}
|
package/config/vite.js
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
/// <reference lib="esnext" />
|
|
3
3
|
|
|
4
4
|
import { glob } from 'node:fs/promises'
|
|
5
|
-
import path from 'node:path'
|
|
6
5
|
import { fileURLToPath } from 'node:url'
|
|
7
6
|
import MagicString from 'magic-string'
|
|
8
7
|
import icons from 'unplugin-icons/vite'
|
|
9
8
|
import * as vite from 'vite'
|
|
10
9
|
|
|
11
|
-
const lib =
|
|
10
|
+
const lib = fileURLToPath(new URL('../lib/', import.meta.url))
|
|
12
11
|
// eslint-disable-next-line antfu/no-top-level-await
|
|
13
12
|
const files = (await Array.fromAsync(glob(`**/*.ts`, { cwd: lib })))
|
|
14
13
|
.filter((file) => !file.endsWith('.d.ts'))
|
|
@@ -41,7 +40,7 @@ export const baseConfig = {
|
|
|
41
40
|
|
|
42
41
|
resolve: {
|
|
43
42
|
alias: {
|
|
44
|
-
'sefirot/':
|
|
43
|
+
'sefirot/': lib
|
|
45
44
|
},
|
|
46
45
|
|
|
47
46
|
// list the client-side direct dependencies/peerDependencies which get bundled
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { type Rule } from './Rule'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Registry of all available field data types. This interface can be
|
|
5
|
+
* extended via declaration merging to add custom field types.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* declare module 'sefirot/pkg/lens/FieldData' {
|
|
9
|
+
* interface FieldDataRegistry {
|
|
10
|
+
* my_custom: MyCustomFieldData
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* interface MyCustomFieldData extends FieldDataBase {
|
|
15
|
+
* type: 'my_custom'
|
|
16
|
+
* customProp: string
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
export interface FieldDataRegistry {
|
|
20
|
+
content: ContentFieldData
|
|
21
|
+
date: DateFieldData
|
|
22
|
+
datetime: DatetimeFieldData
|
|
23
|
+
file_upload: FileUploadFieldData
|
|
24
|
+
id: IdFieldData
|
|
25
|
+
link: LinkFieldData
|
|
26
|
+
number: NumberFieldData
|
|
27
|
+
related_many: RelatedManyFieldData
|
|
28
|
+
select: SelectFieldData
|
|
29
|
+
slack_message: SlackMessageFieldData
|
|
30
|
+
text: TextFieldData
|
|
31
|
+
textarea: TextareaFieldData
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type FieldData = FieldDataRegistry[keyof FieldDataRegistry]
|
|
35
|
+
|
|
36
|
+
export type FieldDataType = keyof FieldDataRegistry
|
|
37
|
+
|
|
38
|
+
export interface FieldDataBase {
|
|
39
|
+
key: string
|
|
40
|
+
labelEn: string
|
|
41
|
+
labelJa: string
|
|
42
|
+
filterKey: string
|
|
43
|
+
sortable: boolean
|
|
44
|
+
freeze: boolean
|
|
45
|
+
width: number
|
|
46
|
+
required: boolean
|
|
47
|
+
rules: Rule[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ContentFieldData extends FieldDataBase {
|
|
51
|
+
type: 'content'
|
|
52
|
+
bodyEn: string
|
|
53
|
+
bodyJa: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface DateFieldData extends FieldDataBase {
|
|
57
|
+
type: 'date'
|
|
58
|
+
placeholderEn: string | null
|
|
59
|
+
placeholderJa: string | null
|
|
60
|
+
helpEn: string | null
|
|
61
|
+
helpJa: string | null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface DatetimeFieldData extends FieldDataBase {
|
|
65
|
+
type: 'datetime'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface FileUploadFieldData extends FieldDataBase {
|
|
69
|
+
type: 'file_upload'
|
|
70
|
+
placeholderEn: string | null
|
|
71
|
+
placeholderJa: string | null
|
|
72
|
+
helpEn: string | null
|
|
73
|
+
helpJa: string | null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface IdFieldData extends FieldDataBase {
|
|
77
|
+
type: 'id'
|
|
78
|
+
prefix: string
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface LinkFieldData extends FieldDataBase {
|
|
82
|
+
type: 'link'
|
|
83
|
+
placeholderEn: string | null
|
|
84
|
+
placeholderJa: string | null
|
|
85
|
+
helpEn: string | null
|
|
86
|
+
helpJa: string | null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface NumberFieldData extends FieldDataBase {
|
|
90
|
+
type: 'number'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface SelectFieldData extends FieldDataBase {
|
|
94
|
+
type: 'select'
|
|
95
|
+
displayAs: 'text' | 'state'
|
|
96
|
+
inputAs: 'dropdown' | 'radio'
|
|
97
|
+
placeholderEn: string | null
|
|
98
|
+
placeholderJa: string | null
|
|
99
|
+
helpEn: string | null
|
|
100
|
+
helpJa: string | null
|
|
101
|
+
options: SelectFieldDataOption[]
|
|
102
|
+
multiple: boolean
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface SelectFieldDataOption {
|
|
106
|
+
mode: 'default' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
|
|
107
|
+
value: string
|
|
108
|
+
labelEn: string
|
|
109
|
+
labelJa: string
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface RelatedManyFieldData extends FieldDataBase {
|
|
113
|
+
type: 'related_many'
|
|
114
|
+
title: string
|
|
115
|
+
resourceEndpointMethod: 'get' | 'post'
|
|
116
|
+
resourceEndpointPath: string
|
|
117
|
+
resourceEndpointDataKey: string | null
|
|
118
|
+
resourceTitle: string
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface SlackMessageFieldData extends FieldDataBase {
|
|
122
|
+
type: 'slack_message'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface TextFieldData extends FieldDataBase {
|
|
126
|
+
type: 'text'
|
|
127
|
+
placeholderEn: string | null
|
|
128
|
+
placeholderJa: string | null
|
|
129
|
+
helpEn: string | null
|
|
130
|
+
helpJa: string | null
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface TextareaFieldData extends FieldDataBase {
|
|
134
|
+
type: 'textarea'
|
|
135
|
+
placeholderEn: string | null
|
|
136
|
+
placeholderJa: string | null
|
|
137
|
+
helpEn: string | null
|
|
138
|
+
helpJa: string | null
|
|
139
|
+
rows: number
|
|
140
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type FieldContext } from './FieldContext'
|
|
2
|
+
import { type FieldData, type FieldDataType } from './FieldData'
|
|
3
|
+
import { type Field } from './fields/Field'
|
|
4
|
+
|
|
5
|
+
export type FieldProvider<T extends FieldData> = (ctx: FieldContext, fieldData: T) => Field<T>
|
|
6
|
+
|
|
7
|
+
export type FieldDataFor<T extends FieldDataType> = Extract<FieldData, { type: T }>
|
|
8
|
+
|
|
9
|
+
export class FieldRegistry {
|
|
10
|
+
private fields: Record<string, FieldProvider<any>> = {}
|
|
11
|
+
|
|
12
|
+
register<T extends FieldDataType>(type: T, provider: FieldProvider<FieldDataFor<T>>) {
|
|
13
|
+
this.fields[type] = provider
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
resolve<T extends FieldData>(fieldData: T): FieldProvider<T> {
|
|
17
|
+
const provider = this.fields[fieldData.type]
|
|
18
|
+
if (!provider) {
|
|
19
|
+
throw new Error(`Field "${fieldData.type}" is not registered in the FieldRegistry.`)
|
|
20
|
+
}
|
|
21
|
+
return provider
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type FileDownloader = (url: string) => Promise<any>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type FilterOperator =
|
|
2
|
+
| '='
|
|
3
|
+
| '!='
|
|
4
|
+
| '>'
|
|
5
|
+
| '>='
|
|
6
|
+
| '<'
|
|
7
|
+
| '<='
|
|
8
|
+
| 'in'
|
|
9
|
+
|
|
10
|
+
export const FilterOperatorTextDict: Record<FilterOperator, string> = {
|
|
11
|
+
'=': 'Is',
|
|
12
|
+
'!=': 'Is not',
|
|
13
|
+
'>': 'Greater',
|
|
14
|
+
'>=': 'Greater or equal',
|
|
15
|
+
'<': 'Less',
|
|
16
|
+
'<=': 'Less or equal',
|
|
17
|
+
'in': 'In'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface FilterOperatorOption {
|
|
21
|
+
label: string
|
|
22
|
+
value: FilterOperator
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const FilterOperatorOptionDict: Record<FilterOperator, FilterOperatorOption> = {
|
|
26
|
+
'=': { label: 'Is', value: '=' },
|
|
27
|
+
'!=': { label: 'Is not', value: '!=' },
|
|
28
|
+
'>': { label: 'Greater', value: '>' },
|
|
29
|
+
'>=': { label: 'Greater or equal', value: '>=' },
|
|
30
|
+
'<': { label: 'Less', value: '<' },
|
|
31
|
+
'<=': { label: 'Less or equal', value: '<=' },
|
|
32
|
+
'in': { label: 'In', value: 'in' }
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type FieldData } from './FieldData'
|
|
2
|
+
import { type LensQuery } from './LensQuery'
|
|
3
|
+
|
|
4
|
+
export interface LensResult {
|
|
5
|
+
query: LensQuery
|
|
6
|
+
fields: Record<string, FieldData>
|
|
7
|
+
data: Record<string, any>[]
|
|
8
|
+
pagination: LensResultPaginationMeta
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface LensResultPagination<T> {
|
|
12
|
+
data: T[]
|
|
13
|
+
meta: LensResultPaginationMeta
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface LensResultPaginationMeta {
|
|
17
|
+
total: number
|
|
18
|
+
page: number
|
|
19
|
+
perPage: number
|
|
20
|
+
}
|