@stonecrop/atable 0.11.9 → 0.12.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.
@@ -1,26 +1,26 @@
1
1
  <template>
2
2
  <div class="column-filter">
3
3
  <input
4
- v-if="(column.filterType || 'text') === 'text'"
4
+ v-if="resolvedFilterType === 'text'"
5
5
  v-model="filterValue"
6
6
  type="text"
7
7
  class="filter-input"
8
8
  @input="updateFilter(filterValue)" />
9
9
 
10
10
  <input
11
- v-else-if="column.filterType === 'number'"
11
+ v-else-if="resolvedFilterType === 'number'"
12
12
  v-model="filterValue"
13
13
  type="number"
14
14
  class="filter-input"
15
15
  @input="updateFilter(filterValue)" />
16
16
 
17
- <label v-else-if="column.filterType === 'checkbox'" class="checkbox-filter">
17
+ <label v-else-if="resolvedFilterType === 'checkbox'" class="checkbox-filter">
18
18
  <input v-model="filterValue" type="checkbox" class="filter-checkbox" @change="updateFilter(filterValue)" />
19
19
  <span>{{ column.label }}</span>
20
20
  </label>
21
21
 
22
22
  <select
23
- v-else-if="column.filterType === 'select'"
23
+ v-else-if="resolvedFilterType === 'select'"
24
24
  v-model="filterValue"
25
25
  class="filter-select"
26
26
  @change="updateFilter(filterValue)">
@@ -31,13 +31,13 @@
31
31
  </select>
32
32
 
33
33
  <input
34
- v-else-if="column.filterType === 'date'"
34
+ v-else-if="resolvedFilterType === 'date'"
35
35
  v-model="filterValue"
36
36
  type="date"
37
37
  class="filter-input"
38
38
  @change="updateFilter(filterValue)" />
39
39
 
40
- <div v-else-if="column.filterType === 'dateRange'" class="date-range-filter">
40
+ <div v-else-if="resolvedFilterType === 'dateRange'" class="date-range-filter">
41
41
  <input
42
42
  v-model="dateFilter.startValue"
43
43
  type="date"
@@ -53,7 +53,7 @@
53
53
 
54
54
  <component
55
55
  :is="column.filterComponent"
56
- v-else-if="column.filterType === 'component' && column.filterComponent"
56
+ v-else-if="resolvedFilterType === 'component' && column.filterComponent"
57
57
  :value="filterValue"
58
58
  :column="column"
59
59
  :col-index="colIndex"
@@ -81,6 +81,28 @@ const dateFilter = reactive({
81
81
  endValue: '',
82
82
  })
83
83
 
84
+ const resolvedFilterType = computed(() => {
85
+ if (column.filterType) return column.filterType
86
+ switch (column.fieldtype) {
87
+ case 'Check':
88
+ return 'checkbox'
89
+ case 'Date':
90
+ return 'date'
91
+ case 'Datetime':
92
+ return 'dateRange'
93
+ case 'Select':
94
+ return 'select'
95
+ case 'Int':
96
+ case 'Float':
97
+ case 'Currency':
98
+ case 'Decimal':
99
+ case 'Quantity':
100
+ return 'number'
101
+ default:
102
+ return 'text'
103
+ }
104
+ })
105
+
84
106
  const getSelectOptions = (column: TableColumn): any[] => {
85
107
  if (column.filterOptions) return column.filterOptions
86
108
 
@@ -105,7 +127,7 @@ const hasActiveFilter = computed(() => {
105
127
 
106
128
  // Filter actions
107
129
  const updateFilter = (value: any) => {
108
- if (!value && column.filterType !== 'checkbox') {
130
+ if (!value && resolvedFilterType.value !== 'checkbox') {
109
131
  store.clearFilter(colIndex)
110
132
  filterValue.value = ''
111
133
  } else {
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import ATableModal from './components/ATableModal.vue'
13
13
  export { createTableStore } from './stores/table'
14
14
  export type { FilterState, FilterStateRecord } from './stores/table'
15
15
  export type * from './types'
16
+ export { schemaToColumns } from './schemaToColumns'
16
17
 
17
18
  // Icon exports
18
19
  export { AddIcon, DeleteIcon, DuplicateIcon, InsertAboveIcon, InsertBelowIcon, MoveIcon, actionIcons } from './icons'
@@ -0,0 +1,24 @@
1
+ import type { ColumnSchema } from '@stonecrop/schema'
2
+
3
+ import type { TableColumn } from './types'
4
+
5
+ /**
6
+ * Convert an array of doctype field descriptors into ATable column definitions.
7
+ *
8
+ * Fields are excluded when:
9
+ * - `hidden: true` — field should not be visible in any view
10
+ * - no `fieldtype` — non-scalar entry (nested table or fieldset), has no column equivalent
11
+ *
12
+ * `fieldname` is renamed to `name`; `hidden` is stripped. All other `ColumnSchema` properties
13
+ * spread through automatically.
14
+ *
15
+ * @public
16
+ */
17
+ export function schemaToColumns(schema: ColumnSchema[]): TableColumn[] {
18
+ return schema
19
+ .filter(f => !f.hidden && f.fieldtype)
20
+ .map(({ fieldname, hidden: _hidden, ...rest }) => ({
21
+ name: fieldname,
22
+ ...rest,
23
+ }))
24
+ }
@@ -425,7 +425,16 @@ export const createTableStore = (initData: {
425
425
  const format = column.format
426
426
 
427
427
  if (!format) {
428
- return value
428
+ switch (column.fieldtype) {
429
+ case 'Check':
430
+ return value ? '✓' : '✗'
431
+ case 'Date':
432
+ return value != null ? new Date(value as string).toLocaleDateString() : value
433
+ case 'Datetime':
434
+ return value != null ? new Date(value as string).toLocaleString() : value
435
+ default:
436
+ return value
437
+ }
429
438
  }
430
439
 
431
440
  if (typeof format === 'function') {
@@ -1,191 +1,54 @@
1
1
  import { useElementBounding } from '@vueuse/core'
2
2
  import type { Ref, ShallowRef } from 'vue'
3
3
 
4
+ import type { ColumnSchema } from '@stonecrop/schema'
5
+
4
6
  import { createTableStore } from '../stores/table'
5
7
 
6
8
  /**
7
- * Table column definition.
9
+ * Runtime column definition for ATable.
10
+ *
11
+ * Extends `ColumnSchema` from `@stonecrop/schema` — all authoring properties (`label`, `fieldtype`, `width`,
12
+ * `pinned`, filter config, cell/modal component names, etc.) are inherited. The overrides
13
+ * below widen three properties for runtime use (live functions, broader alignment values)
14
+ * and add two runtime-only additions (`mask`, `originalIndex`).
15
+ *
16
+ * Schema-based callers should author columns as `ColumnSchema[]` (using `fieldname`) and
17
+ * pass them via ATable's `:schema` prop — `TableColumn` is the internal runtime type and
18
+ * callers working from a doctype schema never need to construct it directly.
8
19
  * @public
9
20
  */
10
- export interface TableColumn {
11
- /**
12
- * The key of the column. This is used to identify the column in the table.
13
- */
21
+ export interface TableColumn extends Omit<ColumnSchema, 'fieldname' | 'hidden' | 'format' | 'modalComponent'> {
22
+ /** Runtime column key. Corresponds to `fieldname` in `ColumnSchema`; populated by `schemaToColumns`. */
14
23
  name: string
15
24
 
16
25
  /**
17
- * The alignment of the column. Possible values:
18
- * - `left` - left aligned
19
- * - `center` - center aligned
20
- * - `right` - right aligned
21
- * - `start` - aligned to the start of the column
22
- * - `end` - aligned to the end of the column
23
- *
24
- * @defaultValue 'center'
25
- */
26
- align?: CanvasTextAlign
27
-
28
- /**
29
- * Control whether cells for the column is editable.
30
- *
31
- * @defaultValue false
32
- */
33
- edit?: boolean
34
-
35
- /**
36
- * The label of the column. This is displayed in the table header.
37
- *
38
- * @defaultValue If no label is provided, a character will be assigned alphabetically,
39
- * starting from 'A' for the first column, 'B' for the second column, and so on.
40
- */
41
- label?: string
42
-
43
- /**
44
- * The semantic field type of the column. Uses the same StonecropFieldType enum as forms.
45
- * Common values: 'Data', 'Text', 'Int', 'Float', 'Date', 'Select', 'Link', 'Check', etc.
46
- *
47
- * @public
48
- */
49
- fieldtype?: string
50
-
51
- /**
52
- * The width of the column. This can be a number (in pixels) or a string (in CSS units).
53
- *
54
- * @defaultValue '40ch'
55
- */
56
- width?: string
57
-
58
- /**
59
- * Control whether the column should be pinned to the table.
60
- *
61
- * @defaultValue false
62
- */
63
- pinned?: boolean
64
-
65
- /**
66
- * Control whether the column can be resized by the user.
67
- *
68
- * @defaultValue false
69
- */
70
- resizable?: boolean
71
-
72
- /**
73
- * Control whether the column should be sortable.
74
- *
75
- * @defaultValue true
76
- */
77
- sortable?: boolean
78
-
79
- /**
80
- * Control whether the column should be filterable and define filter configuration.
81
- *
82
- * @defaultValue true
83
- */
84
- filterable?: boolean
85
-
86
- /**
87
- * The type of filter for the column.
88
- *
89
- * @defaultValue 'text'
26
+ * Widens `ColumnSchema.format` (string-only) to also accept a live function at runtime.
27
+ * Serialized string functions are deserialized by the table store's `getFormattedValue`.
90
28
  */
91
- filterType?: 'text' | 'select' | 'number' | 'date' | 'dateRange' | 'checkbox' | 'component'
92
-
93
- /**
94
- * Options for select-type filters.
95
- */
96
- filterOptions?: any[]
97
-
98
- /**
99
- * Custom component for filtering.
100
- */
101
- filterComponent?: string
102
-
103
- /**
104
- * The component to use to render the cell for the column. If not provided, the table will
105
- * render the default `<td>` element.
106
- */
107
- cellComponent?: string
108
-
109
- /**
110
- * Additional properties to pass to the table's cell component.
111
- *
112
- * Only applicable if the `cellComponent` property is set for the column.
113
- */
114
- cellComponentProps?: Record<string, any>
29
+ format?: string | ((value: any, context: CellContext) => string)
115
30
 
116
31
  /**
117
- * The component to use for the modal. If a function is provided, it will be called with the cell context.
118
- * The following properties are available on the cell context:
119
- * - `row` - the row object
120
- * - `column` - the column object
121
- * - `table` - the table object
122
- *
123
- * The function should return the name of the component to use for the modal.
124
- *
125
- * Additionally, the following properties will be automatically passed to the modal component:
126
- * - `colIndex` - the column index of the current cell
127
- * - `rowIndex` - the row index of the current cell
128
- * - `store` - the table data store
32
+ * Widens `ColumnSchema.modalComponent` (string-only) to also accept a factory function.
33
+ * When a function is provided it receives the cell context and returns the component name.
34
+ * The cell context exposes:
35
+ * - `row` — the row object for the current cell
36
+ * - `column` — the column object for the current cell
37
+ * - `table` — the table object
129
38
  */
130
-
131
39
  modalComponent?: string | ((context: CellContext) => string)
132
40
 
133
41
  /**
134
- * Additional properties to pass to the modal component.
135
- *
136
- * Only applicable if the `modalComponent` property is set for the column.
137
- */
138
- modalComponentExtraProps?: Record<string, any>
139
-
140
- /**
141
- * The format function to use to format the value of the cell. This can either be a normal or stringified
142
- * function that takes the value and the cell context and returns a string.
143
- */
144
- format?: string | ((value: any, context: CellContext) => string)
145
-
146
- /**
147
- * The masking function to use to apply an input mask to the cell. This will accept an input value and
148
- * return the masked value.
42
+ * Input mask applied to the cell value before display. Accepts a live function only —
43
+ * masks cannot be serialized to JSON so they are absent from `ColumnSchema`.
149
44
  */
150
45
  mask?: (value: any) => any
151
46
 
152
47
  /**
153
- * Whether the column is a Gantt column.
154
- *
155
- * Only applicable for Gantt tables.
156
- *
157
- * @defaultValue false
158
- */
159
- isGantt?: boolean
160
-
161
- /**
162
- * The component to use to render the Gantt bar for the column.
163
- *
164
- * Only applicable for Gantt tables.
165
- *
166
- * @defaultValue 'AGanttCell'
167
- */
168
- ganttComponent?: string
169
-
170
- /**
171
- * The colspan of the Gantt bar for the column. This determines how many columns
172
- * the Gantt bar should span across.
173
- *
174
- * Only applicable for Gantt tables.
175
- *
176
- * @defaultValue The number of columns in the table, excluding any pinned columns.
177
- */
178
- colspan?: number
179
-
180
- /**
181
- * The original column index for the Gantt bar, excluding any pinned columns.
182
- * This is evaluated automatically while rendering the table.
183
- *
184
- * Only applicable for Gantt tables.
185
- *
186
- * @defaultValue 0
48
+ * Runtime Gantt column index (excluding pinned columns). Set automatically during
49
+ * Gantt table rendering.
187
50
  */
188
- originalIndex?: number
51
+ readonly originalIndex?: number
189
52
  }
190
53
 
191
54
  /**