@globalbrain/sefirot 4.40.3 → 4.41.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.
@@ -6,28 +6,19 @@ export type FilterOperator =
6
6
  | '<'
7
7
  | '<='
8
8
  | 'in'
9
+ | 'contains'
10
+ | 'startsWith'
11
+ | 'endsWith'
9
12
 
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' }
13
+ export const FilterOperatorLabelDict: Record<FilterOperator, string> = {
14
+ '=': 'is',
15
+ '!=': 'is not',
16
+ '>': 'greater',
17
+ '>=': 'greater or equal',
18
+ '<': 'less',
19
+ '<=': 'less or equal',
20
+ 'in': 'in',
21
+ 'contains': 'contains',
22
+ 'startsWith': 'starts with',
23
+ 'endsWith': 'ends with'
33
24
  }
@@ -1,6 +1,10 @@
1
1
  export type Rule =
2
2
  | MaxLengthRule
3
3
  | RequiredRule
4
+ | BeforeRule
5
+ | BeforeOrEqualRule
6
+ | AfterRule
7
+ | AfterOrEqualRule
4
8
 
5
9
  export interface MaxLengthRule {
6
10
  type: 'max_length'
@@ -10,3 +14,23 @@ export interface MaxLengthRule {
10
14
  export interface RequiredRule {
11
15
  type: 'required'
12
16
  }
17
+
18
+ export interface BeforeRule {
19
+ type: 'before'
20
+ date: string
21
+ }
22
+
23
+ export interface BeforeOrEqualRule {
24
+ type: 'before_or_equal'
25
+ date: string
26
+ }
27
+
28
+ export interface AfterRule {
29
+ type: 'after'
30
+ date: string
31
+ }
32
+
33
+ export interface AfterOrEqualRule {
34
+ type: 'after_or_equal'
35
+ date: string
36
+ }
@@ -135,7 +135,7 @@ const queryFilter = computed(() => {
135
135
  return []
136
136
  }
137
137
  return ['$or', props.queryKeys.map((key) => {
138
- return [key, 'like', `%${query.value}%`]
138
+ return [key, 'contains', query.value]
139
139
  })]
140
140
  })
141
141
 
@@ -2,7 +2,7 @@
2
2
  import { computedAsync } from '@vueuse/core'
3
3
  import { computed } from 'vue'
4
4
  import { type FieldData } from '../FieldData'
5
- import { type FilterOperator, FilterOperatorTextDict } from '../FilterOperator'
5
+ import { type FilterOperator, FilterOperatorLabelDict } from '../FilterOperator'
6
6
  import { useFieldFactory } from '../composables/FieldFactory'
7
7
 
8
8
  export interface Props {
@@ -33,7 +33,7 @@ const fieldText = computed(() => {
33
33
  })
34
34
 
35
35
  const operatorText = computed(() => {
36
- return FilterOperatorTextDict[props.condition.operator]
36
+ return FilterOperatorLabelDict[props.condition.operator]
37
37
  })
38
38
 
39
39
  const valueText = computedAsync(async () => {
@@ -8,7 +8,7 @@ import { useTrans } from '../../../composables/Lang'
8
8
  import { useValidation } from '../../../composables/Validation'
9
9
  import { required } from '../../../validation/rules'
10
10
  import { type FieldData } from '../FieldData'
11
- import { type FilterOperator, FilterOperatorOptionDict } from '../FilterOperator'
11
+ import { type FilterOperator, FilterOperatorLabelDict } from '../FilterOperator'
12
12
  import { useFieldFactory } from '../composables/FieldFactory'
13
13
  import { type FilterInput } from '../filter-inputs/FilterInput'
14
14
 
@@ -53,7 +53,7 @@ const field = computed(() => {
53
53
 
54
54
  const operatorOptions = computed(() => {
55
55
  return field.value?.availableFilterOperators().map((op) => {
56
- return FilterOperatorOptionDict[op]
56
+ return { label: FilterOperatorLabelDict[op], value: op }
57
57
  }) ?? []
58
58
  })
59
59
 
@@ -20,7 +20,10 @@ export class TextField extends Field<TextFieldData> {
20
20
 
21
21
  return {
22
22
  '=': text,
23
- '!=': text
23
+ '!=': text,
24
+ 'contains': text,
25
+ 'startsWith': text,
26
+ 'endsWith': text
24
27
  }
25
28
  }
26
29
 
@@ -20,7 +20,10 @@ export class TextareaField extends Field<TextareaFieldData> {
20
20
 
21
21
  return {
22
22
  '=': text,
23
- '!=': text
23
+ '!=': text,
24
+ 'contains': text,
25
+ 'startsWith': text,
26
+ 'endsWith': text
24
27
  }
25
28
  }
26
29
 
@@ -1,5 +1,6 @@
1
1
  import { type ValidationArgs, type ValidationRuleWithParams } from '@vuelidate/core'
2
- import { maxLength, required } from '../../../validation/rules'
2
+ import { type Day, day } from '../../../support/Day'
3
+ import { after, afterOrEqual, before, beforeOrEqual, maxLength, required } from '../../../validation/rules'
3
4
  import { type Rule } from '../Rule'
4
5
 
5
6
  /**
@@ -18,5 +19,42 @@ function mapRule(rule: Rule): ValidationRuleWithParams {
18
19
  return maxLength(rule.length)
19
20
  case 'required':
20
21
  return required()
22
+ case 'before':
23
+ return before(resolveDate(rule.date))
24
+ case 'before_or_equal':
25
+ return beforeOrEqual(resolveDate(rule.date))
26
+ case 'after':
27
+ return after(resolveDate(rule.date))
28
+ case 'after_or_equal':
29
+ return afterOrEqual(resolveDate(rule.date))
30
+ default: {
31
+ const _exhaustive: never = rule
32
+ throw new Error(`Unsupported rule type: ${(_exhaustive as Rule).type}`)
33
+ }
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Resolves a date string from the backend rule definition into a `Day`. The
39
+ * keywords mirror the relative date strings accepted by Laravel's `before`
40
+ * and `after` validators.
41
+ */
42
+ function resolveDate(date: string): Day {
43
+ switch (date) {
44
+ case 'now':
45
+ return day()
46
+ case 'today':
47
+ return day().startOf('day')
48
+ case 'tomorrow':
49
+ return day().add(1, 'day').startOf('day')
50
+ case 'yesterday':
51
+ return day().subtract(1, 'day').startOf('day')
52
+ default: {
53
+ const parsed = day(date)
54
+ if (!parsed.isValid()) {
55
+ throw new Error(`Invalid date string in validation rule: "${date}"`)
56
+ }
57
+ return parsed
58
+ }
21
59
  }
22
60
  }
@@ -119,6 +119,7 @@ function onClick(): void {
119
119
  :class="classes"
120
120
  :href
121
121
  role="button"
122
+ :tabindex="props.disabled ? -1 : 0"
122
123
  @click="onClick"
123
124
  >
124
125
  <span class="content">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "4.40.3",
3
+ "version": "4.41.0",
4
4
  "description": "Vue Components for Global Brain Design System.",
5
5
  "keywords": [
6
6
  "components",
@@ -48,11 +48,10 @@
48
48
  "type": "vue-tsc --noEmit",
49
49
  "lint": "eslint --fix",
50
50
  "lint:fail": "eslint --max-warnings 0",
51
- "vitest": "vitest",
52
- "vitest:run": "vitest run",
53
- "coverage": "vitest run --coverage",
54
- "test": "pnpm run type && pnpm run lint && pnpm run coverage",
55
- "test:fail": "pnpm run type && pnpm run lint:fail && pnpm run coverage",
51
+ "test": "vitest",
52
+ "test:fail": "vitest run",
53
+ "test:coverage": "vitest run --coverage",
54
+ "check": "pnpm run type && pnpm run lint:fail && pnpm run test:fail",
56
55
  "release": "pnpm whoami >/dev/null 2>&1 || pnpm login && release-it"
57
56
  },
58
57
  "dependencies": {