@streamscloud/kit 0.2.10 → 0.2.12

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 (75) hide show
  1. package/dist/styles/_responsive.scss +48 -0
  2. package/dist/ui/button/cmp.button.svelte +2 -2
  3. package/dist/ui/button/cmp.button.svelte.d.ts +2 -2
  4. package/dist/ui/button/cmp.options-button.svelte +2 -2
  5. package/dist/ui/button/resources/button-base.svelte +3 -3
  6. package/dist/ui/button/resources/button-theme.svelte +2 -2
  7. package/dist/ui/dropdown/cmp.dropdown.svelte +8 -3
  8. package/dist/ui/icon-text/cmp.icon-text.svelte +2 -2
  9. package/dist/ui/icon-text/cmp.icon-text.svelte.d.ts +2 -0
  10. package/dist/ui/player/carousel/cmp.carousel.svelte +20 -11
  11. package/dist/ui/player/carousel/cmp.carousel.svelte.d.ts +4 -0
  12. package/dist/ui/seek-bar/cmp.seek-bar.svelte +5 -3
  13. package/dist/ui/table/cmp.table.svelte +419 -0
  14. package/dist/ui/table/cmp.table.svelte.d.ts +74 -0
  15. package/dist/ui/table/index.d.ts +7 -0
  16. package/dist/ui/table/index.js +5 -0
  17. package/dist/ui/table/service.d.ts +7 -0
  18. package/dist/ui/table/service.js +17 -0
  19. package/dist/ui/table/table-cells/index.d.ts +13 -0
  20. package/dist/ui/table/table-cells/index.js +13 -0
  21. package/dist/ui/table/table-cells/table-actions-cell.svelte +53 -0
  22. package/dist/ui/table/table-cells/table-actions-cell.svelte.d.ts +18 -0
  23. package/dist/ui/table/table-cells/table-badge-cell.svelte +15 -0
  24. package/dist/ui/table/table-cells/table-badge-cell.svelte.d.ts +38 -0
  25. package/dist/ui/table/table-cells/table-button-cell.svelte +20 -0
  26. package/dist/ui/table/table-cells/table-button-cell.svelte.d.ts +38 -0
  27. package/dist/ui/table/table-cells/table-by-cell.svelte +105 -0
  28. package/dist/ui/table/table-cells/table-by-cell.svelte.d.ts +38 -0
  29. package/dist/ui/table/table-cells/table-checkbox-cell.svelte +21 -0
  30. package/dist/ui/table/table-cells/table-checkbox-cell.svelte.d.ts +38 -0
  31. package/dist/ui/table/table-cells/table-custom-cell.svelte +5 -0
  32. package/dist/ui/table/table-cells/table-custom-cell.svelte.d.ts +38 -0
  33. package/dist/ui/table/table-cells/table-hideable-cell.svelte +7 -0
  34. package/dist/ui/table/table-cells/table-hideable-cell.svelte.d.ts +39 -0
  35. package/dist/ui/table/table-cells/table-icon-cell.svelte +53 -0
  36. package/dist/ui/table/table-cells/table-icon-cell.svelte.d.ts +48 -0
  37. package/dist/ui/table/table-cells/table-image-cell.svelte +64 -0
  38. package/dist/ui/table/table-cells/table-image-cell.svelte.d.ts +39 -0
  39. package/dist/ui/table/table-cells/table-move-row-cell.svelte +29 -0
  40. package/dist/ui/table/table-cells/table-move-row-cell.svelte.d.ts +9 -0
  41. package/dist/ui/table/table-cells/table-select-cell.svelte +22 -0
  42. package/dist/ui/table/table-cells/table-select-cell.svelte.d.ts +38 -0
  43. package/dist/ui/table/table-cells/table-text-cell.svelte +60 -0
  44. package/dist/ui/table/table-cells/table-text-cell.svelte.d.ts +47 -0
  45. package/dist/ui/table/table-cells/table-text-input-cell.svelte +83 -0
  46. package/dist/ui/table/table-cells/table-text-input-cell.svelte.d.ts +38 -0
  47. package/dist/ui/table/table-column-models.svelte.d.ts +28 -0
  48. package/dist/ui/table/table-column-models.svelte.js +57 -0
  49. package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte +86 -0
  50. package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte.d.ts +46 -0
  51. package/dist/ui/table/table-columns-manager/table-columns-manager-localization.d.ts +4 -0
  52. package/dist/ui/table/table-columns-manager/table-columns-manager-localization.js +19 -0
  53. package/dist/ui/table/table-group-actions/cmp.table-group-actions.svelte +56 -0
  54. package/dist/ui/table/table-group-actions/cmp.table-group-actions.svelte.d.ts +40 -0
  55. package/dist/ui/table/table-group-actions/table-group-actions-localization.d.ts +3 -0
  56. package/dist/ui/table/table-group-actions/table-group-actions-localization.js +12 -0
  57. package/dist/ui/table/table-group-actions/types.svelte.d.ts +8 -0
  58. package/dist/ui/table/table-group-actions/types.svelte.js +1 -0
  59. package/dist/ui/table/table-headers/index.d.ts +3 -0
  60. package/dist/ui/table/table-headers/index.js +3 -0
  61. package/dist/ui/table/table-headers/table-checkbox-header.svelte +18 -0
  62. package/dist/ui/table/table-headers/table-checkbox-header.svelte.d.ts +41 -0
  63. package/dist/ui/table/table-headers/table-header-sortable-localization.d.ts +7 -0
  64. package/dist/ui/table/table-headers/table-header-sortable-localization.js +40 -0
  65. package/dist/ui/table/table-headers/table-header-sortable.svelte +94 -0
  66. package/dist/ui/table/table-headers/table-header-sortable.svelte.d.ts +12 -0
  67. package/dist/ui/table/table-headers/table-header.svelte +18 -0
  68. package/dist/ui/table/table-headers/table-header.svelte.d.ts +10 -0
  69. package/dist/ui/table/table-localization.d.ts +6 -0
  70. package/dist/ui/table/table-localization.js +33 -0
  71. package/dist/ui/table/table-model.svelte.d.ts +42 -0
  72. package/dist/ui/table/table-model.svelte.js +207 -0
  73. package/dist/ui/table/types.d.ts +144 -0
  74. package/dist/ui/table/types.js +1 -0
  75. package/package.json +5 -1
@@ -0,0 +1,18 @@
1
+ <script lang="ts" generics="T extends {id: string}">import { Checkbox } from '../../checkbox';
2
+ import TableHeader from './table-header.svelte';
3
+ let { column } = $props();
4
+ const allSelected = $derived(!!column.data.items.length && column.data.items.every((x) => !!column.selection.items.find((i) => i.id === x.id)));
5
+ const canSelectAll = $derived(column.data.items.length > 0 && (!column.selection.limit || column.data.items.length <= column.selection.limit));
6
+ const toggleSelectedAll = () => {
7
+ if (allSelected) {
8
+ column.selection.remove(...column.data.items);
9
+ }
10
+ else {
11
+ column.selection.add(...column.data.items);
12
+ }
13
+ };
14
+ </script>
15
+
16
+ <TableHeader column={column}>
17
+ <Checkbox checked={allSelected} disabled={!allSelected && !canSelectAll} on={{ change: () => toggleSelectedAll() }} />
18
+ </TableHeader>
@@ -0,0 +1,41 @@
1
+ import type { Repository } from '../../../core/repository';
2
+ declare function $$render<T extends {
3
+ id: string;
4
+ }>(): {
5
+ props: {
6
+ column: {
7
+ title: string;
8
+ data: Repository<T>;
9
+ selection: Repository<T>;
10
+ };
11
+ };
12
+ exports: {};
13
+ bindings: "";
14
+ slots: {};
15
+ events: {};
16
+ };
17
+ declare class __sveltets_Render<T extends {
18
+ id: string;
19
+ }> {
20
+ props(): ReturnType<typeof $$render<T>>['props'];
21
+ events(): ReturnType<typeof $$render<T>>['events'];
22
+ slots(): ReturnType<typeof $$render<T>>['slots'];
23
+ bindings(): "";
24
+ exports(): {};
25
+ }
26
+ interface $$IsomorphicComponent {
27
+ new <T extends {
28
+ id: string;
29
+ }>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
30
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
31
+ } & ReturnType<__sveltets_Render<T>['exports']>;
32
+ <T extends {
33
+ id: string;
34
+ }>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
35
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
36
+ }
37
+ declare const TableCheckboxHeader: $$IsomorphicComponent;
38
+ type TableCheckboxHeader<T extends {
39
+ id: string;
40
+ }> = InstanceType<typeof TableCheckboxHeader<T>>;
41
+ export default TableCheckboxHeader;
@@ -0,0 +1,7 @@
1
+ export declare class TableHeaderSortableLocalization {
2
+ get orderBy(): string;
3
+ get newestFirst(): string;
4
+ get oldestFirst(): string;
5
+ get ascending(): string;
6
+ get descending(): string;
7
+ }
@@ -0,0 +1,40 @@
1
+ import { AppLocale } from '../../../core/locale';
2
+ export class TableHeaderSortableLocalization {
3
+ get orderBy() {
4
+ return loc.orderBy[AppLocale.current];
5
+ }
6
+ get newestFirst() {
7
+ return loc.newestFirst[AppLocale.current];
8
+ }
9
+ get oldestFirst() {
10
+ return loc.oldestFirst[AppLocale.current];
11
+ }
12
+ get ascending() {
13
+ return loc.ascending[AppLocale.current];
14
+ }
15
+ get descending() {
16
+ return loc.descending[AppLocale.current];
17
+ }
18
+ }
19
+ const loc = {
20
+ orderBy: {
21
+ en: 'Order by:',
22
+ no: 'Sorter etter:'
23
+ },
24
+ newestFirst: {
25
+ en: 'Newest first',
26
+ no: 'Nyeste først'
27
+ },
28
+ oldestFirst: {
29
+ en: 'Oldest first',
30
+ no: 'Eldste først'
31
+ },
32
+ ascending: {
33
+ en: 'A → Z',
34
+ no: 'A → Å'
35
+ },
36
+ descending: {
37
+ en: 'Z → A',
38
+ no: 'Å → A'
39
+ }
40
+ };
@@ -0,0 +1,94 @@
1
+ <script lang="ts">import { Checkbox } from '../../checkbox';
2
+ import { Dropdown } from '../../dropdown';
3
+ import { Icon } from '../../icon';
4
+ import { TableHeaderSortableLocalization } from './table-header-sortable-localization';
5
+ import TableHeader from './table-header.svelte';
6
+ import IconCaretDownFilled from '@fluentui/svg-icons/icons/caret_down_16_filled.svg?raw';
7
+ import {} from 'svelte';
8
+ let { column, on, children } = $props();
9
+ const localization = new TableHeaderSortableLocalization();
10
+ const changeSort = (direction) => {
11
+ if (column.sortDirection === direction) {
12
+ direction = 'none';
13
+ }
14
+ column.sortDirection = direction;
15
+ on?.sortApplied?.();
16
+ column.onSort?.(column.sortDirection);
17
+ };
18
+ </script>
19
+
20
+ <TableHeader column={column}>
21
+ <div class="th-sortable" class:th-sortable--centered={column.centered}>
22
+ {@render children?.()}
23
+ <span>&nbsp;</span>
24
+ <Dropdown position="bottom-start">
25
+ {#snippet trigger()}
26
+ <button type="button" class="th-sortable__marker">
27
+ <span class="th-sortable__title">
28
+ {column.title}
29
+ </span>
30
+ <Icon src={IconCaretDownFilled} />
31
+ </button>
32
+ {/snippet}
33
+
34
+ <div class="th-sortable__dropdown">
35
+ <div class="th-sortable__dropdown-title">{localization.orderBy}</div>
36
+ {#if column.type === 'by'}
37
+ <div class="th-sortable__dropdown-option">
38
+ {localization.newestFirst}
39
+ <Checkbox checked={column.sortDirection === 'desc'} on={{ change: () => changeSort('desc') }} />
40
+ </div>
41
+ <div class="th-sortable__dropdown-option">
42
+ {localization.oldestFirst}
43
+ <Checkbox checked={column.sortDirection === 'asc'} on={{ change: () => changeSort('asc') }} />
44
+ </div>
45
+ {:else}
46
+ <div class="th-sortable__dropdown-option">
47
+ {localization.ascending}
48
+ <Checkbox checked={column.sortDirection === 'asc'} on={{ change: () => changeSort('asc') }} />
49
+ </div>
50
+ <div class="th-sortable__dropdown-option">
51
+ {localization.descending}
52
+ <Checkbox checked={column.sortDirection === 'desc'} on={{ change: () => changeSort('desc') }} />
53
+ </div>
54
+ {/if}
55
+ </div>
56
+ </Dropdown>
57
+ </div>
58
+ </TableHeader>
59
+
60
+ <style>.th-sortable {
61
+ font-size: 1em;
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: flex-start;
65
+ }
66
+ .th-sortable--centered {
67
+ justify-content: center;
68
+ }
69
+ .th-sortable__title, .th-sortable__marker {
70
+ color: inherit;
71
+ display: inline-block;
72
+ white-space: nowrap;
73
+ align-self: center;
74
+ text-transform: inherit;
75
+ }
76
+ .th-sortable__dropdown {
77
+ font-size: 0.875em;
78
+ min-width: 14.5625em;
79
+ padding: 1.375em 1.75em;
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 0.625em;
83
+ }
84
+ .th-sortable__dropdown-title {
85
+ font-weight: 600;
86
+ }
87
+ .th-sortable__dropdown-option {
88
+ display: flex;
89
+ justify-content: space-between;
90
+ align-items: center;
91
+ }
92
+ .th-sortable__marker {
93
+ --sc-kit--icon--size: 0.75em;
94
+ }</style>
@@ -0,0 +1,12 @@
1
+ import type { SortableTableColumn } from '../table-column-models.svelte';
2
+ import { type Snippet } from 'svelte';
3
+ type Props = {
4
+ column: SortableTableColumn;
5
+ on?: {
6
+ sortApplied?: () => void;
7
+ };
8
+ children?: Snippet;
9
+ };
10
+ declare const TableHeaderSortable: import("svelte").Component<Props, {}, "">;
11
+ type TableHeaderSortable = ReturnType<typeof TableHeaderSortable>;
12
+ export default TableHeaderSortable;
@@ -0,0 +1,18 @@
1
+ <script lang="ts">let { column, children } = $props();
2
+ export {};
3
+ </script>
4
+
5
+ <div class="table-header">
6
+ {#if children}
7
+ {@render children()}
8
+ {:else}
9
+ {column.title}
10
+ {/if}
11
+ </div>
12
+
13
+ <style>.table-header {
14
+ font-size: var(--_table--cell--font-size);
15
+ font-weight: 400;
16
+ text-transform: none;
17
+ white-space: nowrap;
18
+ }</style>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Props = {
3
+ column: {
4
+ title: string;
5
+ };
6
+ children?: Snippet;
7
+ };
8
+ declare const TableHeader: import("svelte").Component<Props, {}, "">;
9
+ type TableHeader = ReturnType<typeof TableHeader>;
10
+ export default TableHeader;
@@ -0,0 +1,6 @@
1
+ export declare class TableLocalization {
2
+ get noItemsFoundTitle(): string;
3
+ get noItemsFoundBody(): string;
4
+ get save(): string;
5
+ get cancel(): string;
6
+ }
@@ -0,0 +1,33 @@
1
+ import { AppLocale } from '../../core/locale';
2
+ export class TableLocalization {
3
+ get noItemsFoundTitle() {
4
+ return loc.noItemsFoundTitle[AppLocale.current];
5
+ }
6
+ get noItemsFoundBody() {
7
+ return loc.noItemsFoundBody[AppLocale.current];
8
+ }
9
+ get save() {
10
+ return loc.save[AppLocale.current];
11
+ }
12
+ get cancel() {
13
+ return loc.cancel[AppLocale.current];
14
+ }
15
+ }
16
+ const loc = {
17
+ noItemsFoundTitle: {
18
+ en: 'No Items <span>Found</span>',
19
+ no: 'Ingen elementer <span>funnet</span>'
20
+ },
21
+ noItemsFoundBody: {
22
+ en: 'No data found. Create one to get started',
23
+ no: 'Ingen data funnet. Opprett en for å komme i gang'
24
+ },
25
+ save: {
26
+ en: 'Save',
27
+ no: 'Lagre'
28
+ },
29
+ cancel: {
30
+ en: 'Cancel',
31
+ no: 'Avbryt'
32
+ }
33
+ };
@@ -0,0 +1,42 @@
1
+ import { type Repository } from '../../core/repository';
2
+ import { ResolvedColumn } from './table-column-models.svelte';
3
+ import type { TableGroupAction } from './table-group-actions/types.svelte';
4
+ import type { TableItemAction, TableStyles, WithId, SelectionSettings, IAnyTableColumn } from './types';
5
+ type TableModelInit<T extends WithId> = {
6
+ columns: IAnyTableColumn<T>[];
7
+ items?: T[];
8
+ itemActions?: TableItemAction<T>[];
9
+ itemGroupActions?: TableGroupAction<T>[];
10
+ styles?: TableStyles;
11
+ selectionSettings?: SelectionSettings<T>;
12
+ };
13
+ export declare class TableModel<T extends WithId> {
14
+ private _init;
15
+ private _items;
16
+ private _columns;
17
+ private _itemActions;
18
+ private _itemGroupActions;
19
+ private _styles;
20
+ private _selection;
21
+ private _preserveSelection;
22
+ private _dataProvider;
23
+ private _editingItem;
24
+ private _highlightedItemIds;
25
+ constructor(init: TableModelInit<T>);
26
+ get items(): T[];
27
+ get columns(): ResolvedColumn<T>[];
28
+ get itemActions(): TableItemAction<T>[];
29
+ get itemGroupActions(): TableGroupAction<T>[];
30
+ get styles(): TableStyles;
31
+ get selection(): Repository<T>;
32
+ get editingItem(): T | null;
33
+ get highlightedItemIds(): string[];
34
+ set items(value: T[]);
35
+ set itemActions(value: TableItemAction<T>[]);
36
+ set columns(value: IAnyTableColumn<T>[]);
37
+ set editingItem(value: T | null);
38
+ set highlightedItemIds(value: string[]);
39
+ private reconcileColumns;
40
+ private mapColumn;
41
+ }
42
+ export {};
@@ -0,0 +1,207 @@
1
+ import { Css } from '../../core/css';
2
+ import { createRepository } from '../../core/repository';
3
+ import { Utils } from '../../core/utils';
4
+ import { DynamicComponentModel } from '../dynamic-component';
5
+ import { ResolvedColumn } from './table-column-models.svelte';
6
+ import { TableCheckboxHeader, TableHeader, TableHeaderSortable } from './table-headers';
7
+ import { untrack } from 'svelte';
8
+ export class TableModel {
9
+ _init;
10
+ _items = $state.raw([]);
11
+ _columns = $state.raw([]);
12
+ _itemActions = $state.raw([]);
13
+ _itemGroupActions = $state.raw([]);
14
+ _styles;
15
+ _selection;
16
+ _preserveSelection = false;
17
+ _dataProvider;
18
+ _editingItem = $state(null);
19
+ _highlightedItemIds = $state.raw([]);
20
+ constructor(init) {
21
+ this._init = init;
22
+ this._selection = init.selectionSettings?.repository ?? createRepository();
23
+ this._preserveSelection = init.selectionSettings?.preserveSelection || false;
24
+ this._dataProvider = createRepository();
25
+ this._itemActions = init.itemActions || [];
26
+ this._itemGroupActions = init.itemGroupActions || [];
27
+ this._styles = init.styles || { stickyHeader: true };
28
+ // Use setter to also populate _dataProvider for checkbox header
29
+ if (init.items?.length) {
30
+ this.items = init.items;
31
+ }
32
+ // Reactive reconciliation: columns + itemActions
33
+ $effect(() => {
34
+ const columnDefs = this._init.columns;
35
+ const actions = this._init.itemActions;
36
+ untrack(() => {
37
+ this._itemActions = actions || [];
38
+ this.reconcileColumns(columnDefs);
39
+ });
40
+ });
41
+ // Reactive reconciliation: itemGroupActions
42
+ $effect(() => {
43
+ const groupActions = this._init.itemGroupActions;
44
+ untrack(() => {
45
+ this._itemGroupActions = groupActions || [];
46
+ });
47
+ });
48
+ }
49
+ get items() {
50
+ return this._items;
51
+ }
52
+ get columns() {
53
+ return this._columns;
54
+ }
55
+ get itemActions() {
56
+ return this._itemActions;
57
+ }
58
+ get itemGroupActions() {
59
+ return this._itemGroupActions;
60
+ }
61
+ get styles() {
62
+ return this._styles;
63
+ }
64
+ get selection() {
65
+ return this._selection;
66
+ }
67
+ get editingItem() {
68
+ return this._editingItem;
69
+ }
70
+ get highlightedItemIds() {
71
+ return this._highlightedItemIds;
72
+ }
73
+ set items(value) {
74
+ this._items = value;
75
+ this._dataProvider.set(...value);
76
+ if (!this._preserveSelection) {
77
+ this._selection.clear();
78
+ }
79
+ if (this._editingItem && !this._items.find((x) => x.id === this._editingItem?.id)) {
80
+ this._editingItem = null;
81
+ }
82
+ }
83
+ set itemActions(value) {
84
+ this._itemActions = value;
85
+ }
86
+ set columns(value) {
87
+ this.reconcileColumns(value);
88
+ }
89
+ set editingItem(value) {
90
+ if (!this._items.find((x) => x.id === value?.id)) {
91
+ this._editingItem = null;
92
+ }
93
+ else {
94
+ this._editingItem = structuredClone($state.snapshot(value));
95
+ }
96
+ }
97
+ set highlightedItemIds(value) {
98
+ this._highlightedItemIds = value;
99
+ }
100
+ reconcileColumns = (newDefs) => {
101
+ // Save state from current columns
102
+ const stateMap = new Map();
103
+ for (const col of this._columns) {
104
+ stateMap.set(`${String(col.id)}:${col.type}`, {
105
+ hidden: col.hidden,
106
+ sortDirection: col.sortDirection
107
+ });
108
+ }
109
+ // Create new instances from definitions
110
+ const result = newDefs.map(this.mapColumn);
111
+ // Restore persisted state
112
+ for (const col of result) {
113
+ const state = stateMap.get(`${String(col.id)}:${col.type}`);
114
+ if (state) {
115
+ col.hidden = state.hidden;
116
+ col.sortDirection = state.sortDirection;
117
+ }
118
+ }
119
+ // Append actions column if needed
120
+ if (this._itemActions.length) {
121
+ const actionsColumn = new ResolvedColumn({ type: 'actions', centered: true, fixedCssWidth: Css.em(75) });
122
+ actionsColumn.headerView = new DynamicComponentModel({
123
+ component: TableHeader,
124
+ props: { column: { title: 'Actions' } }
125
+ });
126
+ result.push(actionsColumn);
127
+ }
128
+ this._columns = result;
129
+ };
130
+ mapColumn = (column) => {
131
+ const resolveSortableHeader = (resolved) => {
132
+ if (resolved.onSort) {
133
+ return new DynamicComponentModel({
134
+ component: TableHeaderSortable,
135
+ props: {
136
+ column: resolved,
137
+ on: {
138
+ sortApplied: () => {
139
+ for (const col of this._columns) {
140
+ if (col.uniqueId !== resolved.uniqueId) {
141
+ col.sortDirection = 'none';
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ });
148
+ }
149
+ return new DynamicComponentModel({
150
+ component: TableHeader,
151
+ props: { column: resolved }
152
+ });
153
+ };
154
+ const resolveEditorColumn = (column) => {
155
+ switch (column.type) {
156
+ case 'text-input':
157
+ case 'select': {
158
+ const resolved = new ResolvedColumn(column);
159
+ resolved.headerView = new DynamicComponentModel({
160
+ component: TableHeader,
161
+ props: { column: resolved }
162
+ });
163
+ return resolved;
164
+ }
165
+ default: {
166
+ Utils.assertUnreachable(column);
167
+ }
168
+ }
169
+ };
170
+ switch (column.type) {
171
+ case 'checkbox': {
172
+ const resolved = new ResolvedColumn({
173
+ ...column,
174
+ centered: true,
175
+ fixedCssWidth: column.fixedCssWidth || Css.em(50)
176
+ });
177
+ resolved.headerView = new DynamicComponentModel({
178
+ component: TableCheckboxHeader,
179
+ props: { column: { title: '', data: this._dataProvider, selection: this._selection } }
180
+ });
181
+ return resolved;
182
+ }
183
+ case 'move-row': {
184
+ const resolved = new ResolvedColumn({
185
+ ...column,
186
+ centered: true,
187
+ fixedCssWidth: column.fixedCssWidth || Css.em(75)
188
+ });
189
+ resolved.headerView = resolveSortableHeader(resolved);
190
+ return resolved;
191
+ }
192
+ case 'text': {
193
+ const resolved = new ResolvedColumn(column);
194
+ resolved.headerView = resolveSortableHeader(resolved);
195
+ if (column.editorColumn) {
196
+ resolved.editorColumn = resolveEditorColumn(column.editorColumn);
197
+ }
198
+ return resolved;
199
+ }
200
+ default: {
201
+ const resolved = new ResolvedColumn(column);
202
+ resolved.headerView = resolveSortableHeader(resolved);
203
+ return resolved;
204
+ }
205
+ }
206
+ };
207
+ }
@@ -0,0 +1,144 @@
1
+ import type { Repository } from '../../core/repository';
2
+ import type { BadgeColor } from '../badge';
3
+ import type { ButtonSize, ButtonVariant } from '../button';
4
+ import { DynamicComponentModel } from '../dynamic-component';
5
+ import type { IconColor } from '../icon';
6
+ import type { SelectOption } from '../selects';
7
+ import type { ISchema } from 'yup';
8
+ export type WithId = {
9
+ id: string;
10
+ };
11
+ export type IAnyTableColumn<T> = {
12
+ [P in keyof T]: IOneOfTableColumn<T, P>;
13
+ }[keyof T];
14
+ export type IOneOfTableColumn<T, K extends keyof T> = ITableBadgeColumn<T> | ITableButtonColumn<T> | ITableByColumn<T> | ITableCheckboxColumn | ITableCustomColumn<T> | ITableIconColumn<T> | ITableImageColumn<T> | ITableMoveRowColumn | ITableSelectColumn<T, K> | ITableTextColumn<T> | ITableTextInputColumn<T>;
15
+ export type IEditorColumn<T> = ITableTextInputColumn<T> | ITableSelectColumn<T, keyof T>;
16
+ export type TableColumnType = 'actions' | 'badge' | 'button' | 'by' | 'checkbox' | 'custom' | 'icon' | 'image' | 'move-row' | 'select' | 'text' | 'text-input';
17
+ interface ITableColumnBase {
18
+ type: TableColumnType;
19
+ fixedCssWidth?: string;
20
+ centered?: boolean;
21
+ }
22
+ export interface ITableColumn<T> extends ITableColumnBase {
23
+ id: keyof T;
24
+ title: string;
25
+ onSort?: ((state: TableColumnSortDirection) => Promise<void>) | null;
26
+ sortDirection?: TableColumnSortDirection;
27
+ onClick?: ((item: T) => Promise<void> | void) | null;
28
+ hidden?: boolean;
29
+ hideable?: boolean;
30
+ }
31
+ export interface ITableActionsColumn extends ITableColumnBase {
32
+ type: 'actions';
33
+ }
34
+ export interface ITableBadgeColumn<T> extends ITableColumn<T> {
35
+ type: 'badge';
36
+ colorFactory?: ((item: T) => BadgeColor) | null;
37
+ valueFactory?: ((item: T) => string) | null;
38
+ roundedBadge?: boolean;
39
+ }
40
+ export interface ITableByColumn<T> extends ITableColumn<T> {
41
+ type: 'by';
42
+ valueFactory?: ((item: T) => Date) | null;
43
+ byValueFactory?: ((item: T) => {
44
+ id: string;
45
+ name: string;
46
+ handle: string;
47
+ image: string;
48
+ }) | null;
49
+ /** Returns href for the user link. If not provided, no link is rendered. */
50
+ hrefFactory?: ((by: {
51
+ id: string;
52
+ handle: string;
53
+ }) => string) | null;
54
+ /** Called when user clicks the avatar link. Use for SPA navigation. */
55
+ onNavigate?: ((by: {
56
+ id: string;
57
+ handle: string;
58
+ }) => void) | null;
59
+ }
60
+ export interface ITableButtonColumn<T> extends ITableColumn<T> {
61
+ type: 'button';
62
+ styleFactory?: ((item: T) => ButtonVariant) | null;
63
+ sizeFactory?: ((item: T) => ButtonSize) | null;
64
+ valueFactory?: ((item: T) => string) | null;
65
+ }
66
+ export interface ITableCheckboxColumn extends ITableColumnBase {
67
+ type: 'checkbox';
68
+ }
69
+ export interface ITableCustomColumn<T> extends ITableColumn<T> {
70
+ type: 'custom';
71
+ componentFactory: (item: T) => DynamicComponentModel;
72
+ }
73
+ export interface ITableIconColumn<T> extends ITableColumn<T> {
74
+ type: 'icon';
75
+ colorFactory?: ((item: T) => IconColor) | null;
76
+ iconSrcFactory?: ((item: T) => string) | null;
77
+ tooltipTextFactory?: ((item: T) => string) | null;
78
+ }
79
+ export interface ITableImageColumn<T> extends ITableColumn<T> {
80
+ type: 'image';
81
+ valueFactory?: ((item: T) => string) | null;
82
+ format?: TableImageColumnFormat;
83
+ coverAspectRatio?: number;
84
+ sizeCss?: string;
85
+ }
86
+ export interface ITableMoveRowColumn extends ITableColumnBase {
87
+ type: 'move-row';
88
+ disableFactory?: (() => boolean) | null;
89
+ }
90
+ export interface ITableSelectColumn<T, K extends keyof T> extends ITableColumn<T> {
91
+ id: K;
92
+ type: 'select';
93
+ valueFactory?: ((item: T) => T[K]) | null;
94
+ optionsFactory: (item: T) => SelectOption<T[K]>[];
95
+ placeholder?: string | null;
96
+ disabledFactory?: ((item: T) => boolean) | null;
97
+ visibilityFactory?: ((item: T) => boolean) | null;
98
+ allowReset?: boolean;
99
+ onSelected: (item: T, value: T[K] | null) => void;
100
+ }
101
+ export interface ITableTextColumn<T> extends ITableColumn<T> {
102
+ type: 'text';
103
+ format?: TableTextColumnFormat | null;
104
+ maxLines?: number | 'single-line-no-trim' | null;
105
+ valueFactory?: ((item: T) => string) | null;
106
+ editorColumn?: IEditorColumn<T> | null;
107
+ }
108
+ export interface ITableTextInputColumn<T> extends ITableColumn<T> {
109
+ type: 'text-input';
110
+ inputType?: 'text' | 'number' | null;
111
+ validationSchema?: ISchema<unknown> | null;
112
+ onValidated?: ((item: T, error: string) => void) | null;
113
+ onInput?: ((item: T, value: string) => void) | null;
114
+ }
115
+ export type TableTextColumnFormat = 'text' | 'html' | 'money' | 'date' | 'date-time';
116
+ export type TableImageColumnFormat = 'circle' | 'square-contain' | 'square-cover';
117
+ export type TableItemAction<T> = {
118
+ title: string;
119
+ icon?: string;
120
+ color?: IconColor;
121
+ action: (item: T) => void;
122
+ visibilityFactory?: (item: T) => boolean;
123
+ };
124
+ export type TableStyles = {
125
+ stickyHeader?: boolean;
126
+ actionsDropdownTopDirection?: boolean;
127
+ };
128
+ export type TableOrderByState<TOrder> = {
129
+ orderBy: TOrder;
130
+ ascendingOrder: boolean;
131
+ };
132
+ export type PageQuery<TOrder> = {
133
+ ascendingOrder: boolean;
134
+ fetchTotal: boolean;
135
+ orderBy: TOrder;
136
+ page: number;
137
+ perPage: number;
138
+ };
139
+ export type SelectionSettings<T extends WithId> = {
140
+ preserveSelection?: boolean;
141
+ repository?: Repository<T>;
142
+ };
143
+ export type TableColumnSortDirection = 'none' | 'asc' | 'desc';
144
+ export {};
@@ -0,0 +1 @@
1
+ import { DynamicComponentModel } from '../dynamic-component';