@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.
Files changed (55) hide show
  1. package/config/nuxt.js +44 -1
  2. package/config/vite.js +2 -3
  3. package/lib/blocks/lens/FieldContext.ts +5 -0
  4. package/lib/blocks/lens/FieldData.ts +140 -0
  5. package/lib/blocks/lens/FieldRegistry.ts +23 -0
  6. package/lib/blocks/lens/FileDownloader.ts +1 -0
  7. package/lib/blocks/lens/FilterOperator.ts +33 -0
  8. package/lib/blocks/lens/LensQuery.ts +10 -0
  9. package/lib/blocks/lens/LensResult.ts +20 -0
  10. package/lib/blocks/lens/ResourceFetcher.ts +3 -0
  11. package/lib/blocks/lens/Rule.ts +12 -0
  12. package/lib/blocks/lens/components/LensCatalog.vue +490 -0
  13. package/lib/blocks/lens/components/LensCatalogControl.vue +220 -0
  14. package/lib/blocks/lens/components/LensCatalogFooter.vue +46 -0
  15. package/lib/blocks/lens/components/LensCatalogStateFilter.vue +171 -0
  16. package/lib/blocks/lens/components/LensCatalogStateFilterCondition.vue +86 -0
  17. package/lib/blocks/lens/components/LensCatalogStateFilterGroup.vue +102 -0
  18. package/lib/blocks/lens/components/LensCatalogStateSort.vue +159 -0
  19. package/lib/blocks/lens/components/LensFormFilter.vue +169 -0
  20. package/lib/blocks/lens/components/LensFormFilterCondition.vue +205 -0
  21. package/lib/blocks/lens/components/LensFormFilterGroup.vue +175 -0
  22. package/lib/blocks/lens/components/LensFormOverride.vue +45 -0
  23. package/lib/blocks/lens/components/LensFormOverrideBase.vue +204 -0
  24. package/lib/blocks/lens/components/LensFormView.vue +347 -0
  25. package/lib/blocks/lens/components/LensTable.vue +154 -0
  26. package/lib/blocks/lens/composables/FieldFactory.ts +27 -0
  27. package/lib/blocks/lens/composables/FieldRegistry.ts +16 -0
  28. package/lib/blocks/lens/composables/FileDownloader.ts +10 -0
  29. package/lib/blocks/lens/composables/ResourceFetcher.ts +30 -0
  30. package/lib/blocks/lens/composables/SetupLens.ts +55 -0
  31. package/lib/blocks/lens/fields/ContentField.ts +34 -0
  32. package/lib/blocks/lens/fields/DateField.ts +66 -0
  33. package/lib/blocks/lens/fields/DatetimeField.ts +35 -0
  34. package/lib/blocks/lens/fields/Field.ts +244 -0
  35. package/lib/blocks/lens/fields/FileUploadField.ts +63 -0
  36. package/lib/blocks/lens/fields/IdField.ts +34 -0
  37. package/lib/blocks/lens/fields/LinkField.ts +53 -0
  38. package/lib/blocks/lens/fields/NumberField.ts +32 -0
  39. package/lib/blocks/lens/fields/RelatedManyField.ts +62 -0
  40. package/lib/blocks/lens/fields/SelectField.ts +198 -0
  41. package/lib/blocks/lens/fields/SlackMessageField.ts +34 -0
  42. package/lib/blocks/lens/fields/TextField.ts +46 -0
  43. package/lib/blocks/lens/fields/TextareaField.ts +49 -0
  44. package/lib/blocks/lens/filter-inputs/FilterInput.ts +72 -0
  45. package/lib/blocks/lens/filter-inputs/NumberFilterInput.ts +26 -0
  46. package/lib/blocks/lens/filter-inputs/SelectFilterInput.ts +76 -0
  47. package/lib/blocks/lens/filter-inputs/TextFilterInput.ts +26 -0
  48. package/lib/blocks/lens/validation/RuleMapper.ts +22 -0
  49. package/lib/components/SInputTextarea.vue +28 -10
  50. package/lib/components/STable.vue +230 -61
  51. package/lib/components/STableCell.vue +2 -2
  52. package/lib/composables/TableAnimation.ts +180 -0
  53. package/lib/support/Scroll.ts +263 -0
  54. package/lib/support/Utils.ts +1 -1
  55. 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 vite.mergeConfig(baseConfig, config)
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 = `${path.resolve(import.meta.dirname, '../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/': fileURLToPath(new URL('../lib/', import.meta.url))
43
+ 'sefirot/': lib
45
44
  },
46
45
 
47
46
  // list the client-side direct dependencies/peerDependencies which get bundled
@@ -0,0 +1,5 @@
1
+ import { type Lang } from '../../composables/Lang'
2
+
3
+ export interface FieldContext {
4
+ lang: Lang
5
+ }
@@ -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,10 @@
1
+ export interface LensQuery {
2
+ entity: string
3
+ select: string[]
4
+ filters: any[]
5
+ sort: LensQuerySort[]
6
+ page: number
7
+ perPage: number
8
+ }
9
+
10
+ export type LensQuerySort = [key: string, direction: 'asc' | 'desc']
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ export type ResourceFetcher = (method: ResourceFetchMethod, url: string) => Promise<any>
2
+
3
+ export type ResourceFetchMethod = 'get' | 'post'
@@ -0,0 +1,12 @@
1
+ export type Rule =
2
+ | MaxLengthRule
3
+ | RequiredRule
4
+
5
+ export interface MaxLengthRule {
6
+ type: 'max_length'
7
+ length: number
8
+ }
9
+
10
+ export interface RequiredRule {
11
+ type: 'required'
12
+ }