@globalbrain/sefirot 4.57.0 → 4.58.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 (51) hide show
  1. package/lib/blocks/lens/components/LensFormFilterCondition.vue +2 -1
  2. package/lib/blocks/lens/components/LensFormFilterGroup.vue +1 -1
  3. package/lib/blocks/lens/components/{LensAvatarInput.vue → LensInputAvatar.vue} +5 -3
  4. package/lib/blocks/lens/components/LensInputDropdown.vue +102 -0
  5. package/lib/blocks/lens/components/LensSheetAvatarField.vue +2 -2
  6. package/lib/blocks/lens/components/LensTableEditableCell.vue +5 -4
  7. package/lib/blocks/lens/fields/AvatarField.ts +2 -2
  8. package/lib/blocks/lens/fields/Field.ts +10 -6
  9. package/lib/blocks/lens/filter-inputs/SelectFilterInput.ts +2 -1
  10. package/lib/components/SButton.vue +2 -10
  11. package/lib/components/SControlInputSearch.vue +6 -3
  12. package/lib/components/SDescPill.vue +3 -2
  13. package/lib/components/SDescState.vue +3 -2
  14. package/lib/components/SInputAddon.vue +4 -2
  15. package/lib/components/{SInputSelectSearch.vue → SInputAsyncDropdown.vue} +91 -83
  16. package/lib/components/SInputBase.vue +1 -3
  17. package/lib/components/SInputCheckbox.vue +10 -18
  18. package/lib/components/SInputCheckboxes.vue +16 -33
  19. package/lib/components/SInputDate.vue +10 -20
  20. package/lib/components/SInputDropdown.vue +22 -43
  21. package/lib/components/SInputDropdownItem.vue +7 -24
  22. package/lib/components/SInputFile.vue +10 -18
  23. package/lib/components/SInputFileUpload.vue +12 -34
  24. package/lib/components/SInputFileUploadItem.vue +7 -21
  25. package/lib/components/SInputHMS.vue +6 -7
  26. package/lib/components/SInputImage.vue +11 -16
  27. package/lib/components/SInputNumber.vue +1 -3
  28. package/lib/components/SInputRadio.vue +9 -19
  29. package/lib/components/SInputRadios.vue +18 -40
  30. package/lib/components/SInputSegments.vue +15 -26
  31. package/lib/components/SInputSegmentsOption.vue +7 -7
  32. package/lib/components/SInputSelect.vue +14 -19
  33. package/lib/components/SInputSwitch.vue +10 -19
  34. package/lib/components/SInputSwitches.vue +16 -30
  35. package/lib/components/SInputText.vue +1 -4
  36. package/lib/components/SInputTextarea.vue +0 -2
  37. package/lib/components/SInputYMD.vue +6 -7
  38. package/lib/components/SPagination.vue +1 -1
  39. package/lib/components/SPill.vue +2 -2
  40. package/lib/components/SState.vue +2 -2
  41. package/lib/components/STableCellPill.vue +3 -2
  42. package/lib/components/STableCellState.vue +3 -2
  43. package/lib/composables/Table.ts +8 -15
  44. package/lib/support/Color.ts +4 -0
  45. package/lib/support/InputBase.ts +5 -0
  46. package/lib/support/InputDropdown.ts +15 -0
  47. package/lib/support/InputFileUpload.ts +22 -0
  48. package/lib/support/InputOption.ts +8 -0
  49. package/lib/support/InputText.ts +6 -0
  50. package/package.json +1 -1
  51. package/lib/blocks/lens/components/LensInputSelect.vue +0 -92
@@ -1,29 +1,18 @@
1
1
  <script setup lang="ts">
2
- import { type Component, computed } from 'vue'
3
- import { type Validatable } from '../composables/Validation'
4
- import SInputBase, { type Color, type Size } from './SInputBase.vue'
2
+ import { computed } from 'vue'
3
+ import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
5
4
 
6
- export type { Color, Size }
7
5
  export type ActiveColor = 'info' | 'success' | 'warning' | 'danger'
8
6
 
9
- const props = withDefaults(defineProps<{
10
- size?: Size
11
- name?: string
12
- label?: string
13
- info?: string
14
- note?: string
7
+ export interface Props extends BaseProps {
15
8
  text?: string
16
9
  color?: ActiveColor
17
- help?: string
18
- checkIcon?: Component
19
- checkText?: string
20
- checkColor?: Color
21
10
  disabled?: boolean
22
11
  value?: boolean
23
12
  modelValue?: boolean
24
- hideError?: boolean
25
- validation?: Validatable
26
- }>(), {
13
+ }
14
+
15
+ const props = withDefaults(defineProps<Props>(), {
27
16
  value: undefined,
28
17
  modelValue: undefined
29
18
  })
@@ -64,12 +53,14 @@ function emitChange(): void {
64
53
  :label
65
54
  :note
66
55
  :info
56
+ :help
67
57
  :check-icon
68
58
  :check-text
69
59
  :check-color
70
- :help
71
- :hide-error
72
60
  :validation
61
+ :warning
62
+ :hide-error
63
+ :hide-warning
73
64
  >
74
65
  <div class="container">
75
66
  <div class="input" :class="{ on: _value }" role="button" @click="emitChange">
@@ -1,46 +1,30 @@
1
- <script setup lang="ts">
2
- import { type Component, computed } from 'vue'
3
- import { type Validatable } from '../composables/Validation'
4
- import SInputBase, { type Color, type Size } from './SInputBase.vue'
1
+ <script setup lang="ts" generic="T = any">
2
+ import { computed } from 'vue'
3
+ import { type Option } from '../support/InputOption'
4
+ import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
5
5
  import SInputSwitch from './SInputSwitch.vue'
6
6
 
7
- export type { Color, Size }
8
-
9
- export interface Option {
10
- label: string
11
- value: any
7
+ export interface Props<T = any> extends BaseProps {
8
+ options: Option<T>[]
9
+ disabled?: boolean
10
+ modelValue: T[]
12
11
  }
13
12
 
14
- const props = defineProps<{
15
- size?: Size
16
- name?: string
17
- label?: string
18
- info?: string
19
- note?: string
20
- help?: string
21
- checkIcon?: Component
22
- checkText?: string
23
- checkColor?: Color
24
- options: Option[]
25
- disabled?: boolean
26
- modelValue: any[]
27
- hideError?: boolean
28
- validation?: Validatable
29
- }>()
13
+ const props = defineProps<Props<T>>()
30
14
 
31
15
  const emit = defineEmits<{
32
- 'update:model-value': [value: any[]]
16
+ 'update:model-value': [value: T[]]
33
17
  }>()
34
18
 
35
19
  const classes = computed(() => [
36
20
  props.size ?? 'small'
37
21
  ])
38
22
 
39
- function isChecked(value: any): boolean {
23
+ function isChecked(value: T): boolean {
40
24
  return props.modelValue.includes(value)
41
25
  }
42
26
 
43
- function onChange(value: any): void {
27
+ function onChange(value: T): void {
44
28
  const difference = props.modelValue
45
29
  .filter((v) => v !== value)
46
30
  .concat(props.modelValue.includes(value) ? [] : [value])
@@ -62,8 +46,10 @@ function onChange(value: any): void {
62
46
  :check-icon
63
47
  :check-text
64
48
  :check-color
65
- :hide-error
66
49
  :validation
50
+ :warning
51
+ :hide-error
52
+ :hide-warning
67
53
  >
68
54
  <div class="container">
69
55
  <div class="row">
@@ -71,7 +57,7 @@ function onChange(value: any): void {
71
57
  <SInputSwitch
72
58
  size="sm"
73
59
  :text="option.label"
74
- :disabled
60
+ :disabled="option.disabled ?? disabled"
75
61
  :model-value="isChecked(option.value)"
76
62
  @update:model-value="onChange(option.value)"
77
63
  />
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import { type Component, computed, ref } from 'vue'
3
+ import { type Align, type TextColor } from '../support/InputText'
3
4
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
4
5
 
5
- export type { Color, Size } from './SInputBase.vue'
6
6
  export interface Props extends BaseProps {
7
7
  type?: string
8
8
  placeholder?: string
@@ -16,9 +16,6 @@ export interface Props extends BaseProps {
16
16
  displayValue?: string | null
17
17
  }
18
18
 
19
- export type Align = 'left' | 'center' | 'right'
20
- export type TextColor = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
21
-
22
19
  const props = defineProps<Props>()
23
20
 
24
21
  const emit = defineEmits<{
@@ -4,8 +4,6 @@ import SDivider from './SDivider.vue'
4
4
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
5
5
  import SInputSegments from './SInputSegments.vue'
6
6
 
7
- export type { Color, Size } from './SInputBase.vue'
8
-
9
7
  export interface Props extends BaseProps {
10
8
  placeholder?: string
11
9
  disabled?: boolean
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref } from 'vue'
3
+ import { type Ymd } from '../support/Day'
3
4
  import SInputBase, { type Props as BaseProps } from './SInputBase.vue'
4
5
 
5
- export type { Color, Size } from './SInputBase.vue'
6
6
  export interface Props extends BaseProps {
7
7
  placeholder?: Placeholder
8
8
  noYear?: boolean
@@ -14,11 +14,7 @@ export interface Props extends BaseProps {
14
14
  modelValue?: Value
15
15
  }
16
16
 
17
- export interface Value {
18
- year: number | null
19
- month: number | null
20
- date: number | null
21
- }
17
+ export type Value = Ymd
22
18
 
23
19
  export type ValueType = 'year' | 'month' | 'date'
24
20
 
@@ -135,6 +131,7 @@ function createRequiredTouched(): boolean[] {
135
131
  class="SInputYMD"
136
132
  :class="[size ?? 'small', { disabled }]"
137
133
  :size
134
+ :name
138
135
  :label
139
136
  :note
140
137
  :info
@@ -142,8 +139,10 @@ function createRequiredTouched(): boolean[] {
142
139
  :check-icon
143
140
  :check-text
144
141
  :check-color
145
- :hide-error
146
142
  :validation
143
+ :warning
144
+ :hide-error
145
+ :hide-warning
147
146
  >
148
147
  <div class="container" :class="{ focus: isFocused, block }">
149
148
  <input
@@ -3,11 +3,11 @@ import IconCaretLeft from '~icons/ph/caret-left-bold'
3
3
  import IconCaretRight from '~icons/ph/caret-right-bold'
4
4
  import { computed } from 'vue'
5
5
  import { useTrans } from '../composables/Lang'
6
+ import { type Align } from '../support/InputText'
6
7
  import { format } from '../support/Num'
7
8
  import SButton from './SButton.vue'
8
9
 
9
10
  export type Size = 'xs' | 'sm' | 'md' | 'mini' | 'small' | 'medium'
10
- export type Align = 'left' | 'center' | 'right'
11
11
 
12
12
  const props = withDefaults(defineProps<{
13
13
  size?: Size
@@ -1,15 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
+ import { type ColorMode } from '../support/Color'
3
4
 
4
5
  export type Size = 'mini' | 'small' | 'medium' | 'large'
5
6
  export type Type = 'dimm' | 'fill'
6
- export type Mode = 'default' | 'mute' | 'neutral' | 'info' | 'success' | 'warning' | 'danger'
7
7
 
8
8
  const props = defineProps<{
9
9
  as?: string
10
10
  size?: Size
11
11
  type?: Type
12
- mode?: Mode
12
+ mode?: ColorMode
13
13
  label?: string
14
14
  clickable?: boolean
15
15
  }>()
@@ -1,13 +1,13 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
+ import { type ColorMode } from '../support/Color'
3
4
 
4
5
  export type Size = 'mini' | 'small' | 'medium' | 'large'
5
- export type Mode = 'default' | 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
6
6
 
7
7
  const props = defineProps<{
8
8
  as?: string
9
9
  size?: Size
10
- mode?: Mode
10
+ mode?: ColorMode
11
11
  label: string
12
12
  }>()
13
13
 
@@ -1,9 +1,10 @@
1
1
  <script setup lang="ts">
2
- import SPill, { type Mode } from './SPill.vue'
2
+ import { type ColorMode } from '../support/Color'
3
+ import SPill from './SPill.vue'
3
4
 
4
5
  defineProps<{
5
6
  pill?: string
6
- color?: Mode
7
+ color?: ColorMode
7
8
  }>()
8
9
  </script>
9
10
 
@@ -1,9 +1,10 @@
1
1
  <script setup lang="ts">
2
- import SState, { type Mode } from './SState.vue'
2
+ import { type ColorMode } from '../support/Color'
3
+ import SState from './SState.vue'
3
4
 
4
5
  defineProps<{
5
6
  state?: string
6
- mode?: Mode
7
+ mode?: ColorMode
7
8
  }>()
8
9
  </script>
9
10
 
@@ -1,7 +1,9 @@
1
1
  import { type Component, type MaybeRef, type MaybeRefOrGetter } from 'vue'
2
2
  import { type Mode as ButtonMode } from '../components/SButton.vue'
3
3
  import { type State as IndicatorState } from '../components/SIndicator.vue'
4
+ import { type ColorMode } from '../support/Color'
4
5
  import { type Day } from '../support/Day'
6
+ import { type Align } from '../support/InputText'
5
7
  import { type DropdownSection } from './Dropdown'
6
8
  import { type Position } from './Tooltip'
7
9
 
@@ -85,22 +87,13 @@ export type TableCellType =
85
87
  | 'component'
86
88
  | 'actions'
87
89
 
88
- export type ColorModes =
89
- | 'default'
90
- | 'mute'
91
- | 'neutral'
92
- | 'info'
93
- | 'success'
94
- | 'warning'
95
- | 'danger'
96
-
97
90
  export interface TableCellBase {
98
91
  type: TableCellType
99
92
  }
100
93
 
101
94
  export interface TableCellText<V = any, R = any> extends TableCellBase {
102
95
  type: 'text'
103
- align?: 'left' | 'center' | 'right'
96
+ align?: Align
104
97
  icon?: Component
105
98
  value?: string | null
106
99
  link?: string | null
@@ -111,7 +104,7 @@ export interface TableCellText<V = any, R = any> extends TableCellBase {
111
104
 
112
105
  export interface TableCellNumber<V = any, R = any> extends TableCellBase {
113
106
  type: 'number'
114
- align?: 'left' | 'center' | 'right'
107
+ align?: Align
115
108
  icon?: Component
116
109
  value?: number | null
117
110
  separator?: boolean
@@ -139,11 +132,11 @@ export interface TableCellPathSegment {
139
132
  onClick?(): void
140
133
  }
141
134
 
142
- export type TableCellValueColor = ColorModes | 'soft'
135
+ export type TableCellValueColor = ColorMode | 'soft'
143
136
 
144
137
  export interface TableCellDay extends TableCellBase {
145
138
  type: 'day'
146
- align?: 'left' | 'center' | 'right'
139
+ align?: Align
147
140
  value?: Day | null
148
141
  format?: string
149
142
  color?: 'neutral' | 'soft' | 'mute'
@@ -155,7 +148,7 @@ export interface TableCellPill extends TableCellBase {
155
148
  color?: TableCellPillColor
156
149
  }
157
150
 
158
- export type TableCellPillColor = ColorModes
151
+ export type TableCellPillColor = ColorMode
159
152
 
160
153
  export interface TableCellPills extends TableCellBase {
161
154
  type: 'pills'
@@ -207,7 +200,7 @@ export interface TableCellComponent extends TableCellBase {
207
200
  export interface TableCellState extends TableCellBase {
208
201
  type: 'state'
209
202
  label: string
210
- mode?: ColorModes
203
+ mode?: ColorMode
211
204
  }
212
205
 
213
206
  export interface TableCellIndicator extends TableCellBase {
@@ -0,0 +1,4 @@
1
+ // The semantic color modes shared by the colored components (SButton, SPill,
2
+ // SState, SInputSegments, and table cells).
3
+
4
+ export type ColorMode = 'default' | 'mute' | 'neutral' | 'info' | 'success' | 'warning' | 'danger'
@@ -0,0 +1,5 @@
1
+ // The size and color scales shared by SInputBase and every input built on it.
2
+
3
+ export type Size = 'sm' | 'md' | 'mini' | 'small' | 'medium'
4
+
5
+ export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
@@ -0,0 +1,15 @@
1
+ // The dropdown option (text or avatar row) shared by SInputDropdown and
2
+ // SInputAsyncDropdown — the base choice option (InputOption) plus a render type.
3
+
4
+ import { type Option as BaseOption } from './InputOption'
5
+
6
+ export type Option<T = any> = OptionText<T> | OptionAvatar<T>
7
+
8
+ export interface OptionText<T = any> extends BaseOption<T> {
9
+ type?: 'text'
10
+ }
11
+
12
+ export interface OptionAvatar<T = any> extends BaseOption<T> {
13
+ type: 'avatar'
14
+ image?: string | null
15
+ }
@@ -0,0 +1,22 @@
1
+ // The file/action shapes shared by SInputFileUpload and its item child.
2
+
3
+ import { type Component } from 'vue'
4
+ import { type Mode as ButtonMode } from '../components/SButton.vue'
5
+ import { type State as IndicatorState } from '../components/SIndicator.vue'
6
+
7
+ export interface FileObject {
8
+ file: File
9
+ indicatorState?: IndicatorState | null
10
+ canRemove?: boolean
11
+ action?: Action | null
12
+ errorMessage?: string | null
13
+ }
14
+
15
+ export interface Action {
16
+ mode?: ButtonMode
17
+ icon?: Component
18
+ leadIcon?: Component
19
+ trailIcon?: Component
20
+ label?: string
21
+ onClick(): void
22
+ }
@@ -0,0 +1,8 @@
1
+ // The label + value option shape shared by the choice-list inputs (SInputSelect,
2
+ // SInputCheckboxes, SInputRadios, SInputSegments, SInputSwitches).
3
+
4
+ export interface Option<T = any> {
5
+ label: string
6
+ value: T
7
+ disabled?: boolean
8
+ }
@@ -0,0 +1,6 @@
1
+ // The text alignment and color scales shared by SInputText / SInputNumber (and
2
+ // anything that mirrors them, e.g. SPagination's align).
3
+
4
+ export type Align = 'left' | 'center' | 'right'
5
+
6
+ export type TextColor = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "4.57.0",
3
+ "version": "4.58.0",
4
4
  "description": "Vue Components for Global Brain Design System.",
5
5
  "keywords": [
6
6
  "components",
@@ -1,92 +0,0 @@
1
- <script setup lang="ts">
2
- import SInputSelectSearch, { type Option } from '../../../components/SInputSelectSearch.vue'
3
- import { useMutation } from '../../../composables/Api'
4
- import { useLang } from '../../../composables/Lang'
5
- import { type LensQuerySettings, type LensQuerySort } from '../LensQuery'
6
- import { isAuthError } from '../validation/ServerErrors'
7
-
8
- export type { Color, Size } from '../../../components/SInputBase.vue'
9
- export type { Option }
10
-
11
- // A lens-backed search-select. Combines the search (a lens query), the fetch (no
12
- // repo needed), and the row → option mapping (no ops needed) into one component:
13
- // the consumer configures the entity and how a row becomes an option, and the
14
- // component searches the server as the user types via SInputSelectSearch.
15
- //
16
- // Selection UI props (multiple, nullable, disabled, placeholder, size, label,
17
- // validation, position, closeOnSelect, debounce, …) fall through to
18
- // SInputSelectSearch as attributes.
19
- export interface Props {
20
- // The lens search endpoint (e.g. `/api/admin/lens/search`).
21
- endpoint: string
22
-
23
- // The entity to search.
24
- entity: string
25
-
26
- // Columns to fetch for each row, projected into an option by `toOption`.
27
- select: string[]
28
-
29
- // Columns matched against the typed query — OR-ed together with `contains`.
30
- // An empty query fetches the initial (unfiltered) page. Named to match
31
- // LensCatalog's `queryKeys`.
32
- queryKeys: string[]
33
-
34
- // Sort applied to the results (e.g. `[['name', 'asc']]`). Re-read on each fetch,
35
- // so a locale-dependent sort stays current.
36
- sort?: LensQuerySort[]
37
-
38
- // Page size of each search. The server enforces its own perPage ceiling.
39
- perPage?: number
40
-
41
- // Per-request settings (e.g. language). Usually unneeded — the server negotiates
42
- // language from the request headers.
43
- settings?: LensQuerySettings
44
-
45
- // Map a raw result row to an option. The selected option(s) are the model, so
46
- // include everything the consumer needs back (e.g. a related record), plus the
47
- // `value` / `label` (and `image` for an avatar option) the select renders.
48
- toOption: (row: Record<string, any>) => Option
49
- }
50
-
51
- const props = defineProps<Props>()
52
-
53
- // Pass the selection through to SInputSelectSearch. Typed loosely so a consumer
54
- // can bind a ref of its own richer option type (see SInputSelectSearch).
55
- const model = defineModel<any>({ required: true })
56
-
57
- // Don't let lens-config attributes that happen to share a name leak onto the
58
- // child; only the explicitly-forwarded selection props (via `$attrs`) should.
59
- defineOptions({ inheritAttrs: false })
60
-
61
- // Default the request language to the active app language (like LensCatalog), so
62
- // server-localized fields come back in the right locale even when HttpConfig /
63
- // request headers differ; explicit `settings` (incl. `lang`) overrides it.
64
- const lang = useLang()
65
-
66
- const { execute } = useMutation((http, query: string) =>
67
- http.post<{ data: Record<string, any>[] }>(props.endpoint, {
68
- entity: props.entity,
69
- select: props.select,
70
- filters: query
71
- ? [['$or', props.queryKeys.map((key) => [key, 'contains', query])]]
72
- : [],
73
- sort: props.sort ?? [],
74
- page: 1,
75
- perPage: props.perPage ?? 25,
76
- settings: { lang, ...props.settings }
77
- })
78
- )
79
-
80
- // Read every config field through `props` at call time so a reactive change
81
- // (e.g. a locale-dependent sort or label) takes effect on the next search.
82
- async function fetch(query: string): Promise<Option[]> {
83
- const res = await execute(query)
84
- return res.data.map(props.toOption)
85
- }
86
- </script>
87
-
88
- <template>
89
- <SInputSelectSearch v-model="model" :fetch :rethrow="isAuthError" v-bind="$attrs">
90
- <template v-if="$slots.info" #info><slot name="info" /></template>
91
- </SInputSelectSearch>
92
- </template>