@hybridly/vue 0.10.0-beta.26 → 0.10.0-beta.28
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.
- package/dist/index.d.mts +65 -29
- package/dist/index.mjs +102 -36
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -34,10 +34,8 @@ declare const Deferred: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
34
34
|
type Errors$1<T extends SearchableObject$1> = { [K in keyof T]?: T[K] extends Record<string, any> ? Errors$1<T[K]> : string };
|
|
35
35
|
type FormFieldBehavior$1 = boolean | string[];
|
|
36
36
|
type DefaultFormOptions = Pick<FormOptions<object>, 'timeout' | 'resetOnSuccess' | 'resetOnError' | 'setDefaultOnSuccess' | 'progress' | 'preserveScroll' | 'preserveState' | 'preserveUrl' | 'headers' | 'errorBag' | 'spoof' | 'transformUrl' | 'updateHistoryState' | 'useFormData'>;
|
|
37
|
-
|
|
38
|
-
fields: T;
|
|
37
|
+
type FormSubmitOptions$1<T extends SearchableObject$1> = Omit<HybridRequestOptions, 'data' | 'url' | 'reset'> & {
|
|
39
38
|
url?: UrlResolvable | (() => UrlResolvable);
|
|
40
|
-
key?: string | false;
|
|
41
39
|
/**
|
|
42
40
|
* Defines the delay after which the `recentlySuccessful` and `recentlyFailed` variables are reset to `false`.
|
|
43
41
|
*/
|
|
@@ -61,6 +59,27 @@ interface FormOptions<T extends SearchableObject$1> extends Omit<HybridRequestOp
|
|
|
61
59
|
* Callback executed before the form submission for transforming the fields.
|
|
62
60
|
*/
|
|
63
61
|
transform?: (fields: T) => any;
|
|
62
|
+
};
|
|
63
|
+
type FormAutomaticallySubmitOptions<T extends SearchableObject$1> = true | (FormSubmitOptions$1<T> & {
|
|
64
|
+
/**
|
|
65
|
+
* Debounce delay in milliseconds before submitting automatically.
|
|
66
|
+
* @default 100
|
|
67
|
+
*/
|
|
68
|
+
debounce?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Whether to immediately submit the form on any change. If `false`, submits after the `debounce` delay.
|
|
71
|
+
* @default true
|
|
72
|
+
*/
|
|
73
|
+
immediate?: boolean;
|
|
74
|
+
});
|
|
75
|
+
interface FormOptions<T extends SearchableObject$1> extends FormSubmitOptions$1<T> {
|
|
76
|
+
fields: T;
|
|
77
|
+
key?: string | false;
|
|
78
|
+
/**
|
|
79
|
+
* Automatically submits the form when fields change.
|
|
80
|
+
* Pass `true` to use defaults or an object to customize submit overrides and debounce delay.
|
|
81
|
+
*/
|
|
82
|
+
automaticallySubmit?: FormAutomaticallySubmitOptions<T>;
|
|
64
83
|
}
|
|
65
84
|
interface FormReturn<T extends SearchableObject$1, P extends Path$1<T> & string = Path$1<T> & string> {
|
|
66
85
|
resetFields: (...keys: P[]) => void;
|
|
@@ -74,7 +93,7 @@ interface FormReturn<T extends SearchableObject$1, P extends Path$1<T> & string
|
|
|
74
93
|
clearError: (key: P) => void;
|
|
75
94
|
setDefault: (newDefault: Partial<T>) => void;
|
|
76
95
|
hasDirty: (...keys: P[]) => boolean;
|
|
77
|
-
submit: (optionsOverrides?:
|
|
96
|
+
submit: (optionsOverrides?: FormSubmitOptions$1<T>) => Promise<any>;
|
|
78
97
|
hasErrors: boolean;
|
|
79
98
|
defaults: DeepReadonly<T>;
|
|
80
99
|
loaded: DeepReadonly<T>;
|
|
@@ -292,7 +311,7 @@ declare const WhenVisible: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
292
311
|
}>> & Readonly<{
|
|
293
312
|
onLoading?: ((_state: LoadStateSlotProps) => any) | undefined;
|
|
294
313
|
}>, {
|
|
295
|
-
options: Omit<HybridRequestOptions, "
|
|
314
|
+
options: Omit<HybridRequestOptions<Record<string, any>>, "data" | "method" | "url">;
|
|
296
315
|
as: string;
|
|
297
316
|
buffer: number;
|
|
298
317
|
root: string | Element | null;
|
|
@@ -325,6 +344,14 @@ interface BulkSelection<T = any> {
|
|
|
325
344
|
/** Excluded records. */
|
|
326
345
|
except: Set<T>;
|
|
327
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Returns the inclusive range between two records in the given order.
|
|
349
|
+
*
|
|
350
|
+
* This is useful for implementing shift-click bulk selection: keep track of the last selected anchor,
|
|
351
|
+
* then pass the currently visible record identifiers and the clicked target identifier to this helper.
|
|
352
|
+
* If the target is not in the list, an empty range is returned. If the anchor is missing, only the target is returned.
|
|
353
|
+
*/
|
|
354
|
+
declare function getBulkSelectionRange<T>(records: readonly T[], anchor: T | undefined, target: T): T[];
|
|
328
355
|
declare function useBulkSelect<T = any>(): {
|
|
329
356
|
allSelected: vue.ComputedRef<boolean>;
|
|
330
357
|
anySelected: vue.ComputedRef<boolean>;
|
|
@@ -1052,12 +1079,13 @@ declare const registerHook: typeof registerHook$1;
|
|
|
1052
1079
|
//#region src/composables/table.d.ts
|
|
1053
1080
|
interface Table<T extends Record<string, any> = any, PaginatorKind extends 'cursor' | 'length-aware' | 'simple' = 'length-aware'> {
|
|
1054
1081
|
id: string;
|
|
1055
|
-
keyName:
|
|
1082
|
+
keyName: keyof T | null;
|
|
1056
1083
|
scope?: string;
|
|
1057
1084
|
columns: Column<T>[];
|
|
1058
1085
|
inlineActions: InlineAction[];
|
|
1059
1086
|
bulkActions: BulkAction[];
|
|
1060
1087
|
records: Array<T>;
|
|
1088
|
+
cells: TableCellRow<T>[];
|
|
1061
1089
|
paginator: Omit<PaginatorKind extends 'cursor' ? CursorPaginator<T> : (PaginatorKind extends 'simple' ? SimplePaginator<T> : Paginator<T>), 'data'>;
|
|
1062
1090
|
refinements: Refinements;
|
|
1063
1091
|
endpoint: string;
|
|
@@ -1072,6 +1100,14 @@ interface Column<T extends object = never> {
|
|
|
1072
1100
|
/** Metadata of this column. */
|
|
1073
1101
|
metadata: Record<string, any>;
|
|
1074
1102
|
}
|
|
1103
|
+
interface TableCell<T extends object = never> {
|
|
1104
|
+
value: any;
|
|
1105
|
+
extra: Record<string, any>;
|
|
1106
|
+
}
|
|
1107
|
+
interface TableCellRow<T extends object = never> {
|
|
1108
|
+
key: RecordIdentifier | null;
|
|
1109
|
+
columns: Partial<Record<keyof T | string, TableCell<T>>>;
|
|
1110
|
+
}
|
|
1075
1111
|
interface Action {
|
|
1076
1112
|
/** The name of this action. */
|
|
1077
1113
|
name: string;
|
|
@@ -1094,10 +1130,6 @@ interface BulkActionOptions extends Omit<HybridRequestOptions, 'url'> {
|
|
|
1094
1130
|
}
|
|
1095
1131
|
interface InlineAction extends Action {}
|
|
1096
1132
|
type RecordIdentifier = string | number;
|
|
1097
|
-
type AsRecordTypeWithExtra<T extends Record<string, any>> = { [K in keyof T]: {
|
|
1098
|
-
extra: Record<string, any>;
|
|
1099
|
-
value: T[K];
|
|
1100
|
-
} };
|
|
1101
1133
|
interface TableDefaultOptions extends AvailableHybridRequestOptions {
|
|
1102
1134
|
/**
|
|
1103
1135
|
* Whether to include existing query parameters in the request.
|
|
@@ -1113,15 +1145,15 @@ type UseTableNavigationResponse = Promise<_hybridly_core0.NavigationResponse | u
|
|
|
1113
1145
|
type ExtractRefValue<T> = T extends {
|
|
1114
1146
|
value: infer Value;
|
|
1115
1147
|
} ? Value : T;
|
|
1116
|
-
interface UseTableInlineActionItem<RecordType extends Record<string, any
|
|
1148
|
+
interface UseTableInlineActionItem<RecordType extends Record<string, any>> extends InlineAction {
|
|
1117
1149
|
/** Executes the action. */
|
|
1118
|
-
execute: (record:
|
|
1150
|
+
execute: (record: RecordIdentifier | RecordType) => UseTableNavigationResponse;
|
|
1119
1151
|
}
|
|
1120
1152
|
interface UseTableBulkActionItem extends BulkAction {
|
|
1121
1153
|
/** Executes the action. */
|
|
1122
1154
|
execute: (options?: BulkActionOptions) => UseTableNavigationResponse;
|
|
1123
1155
|
}
|
|
1124
|
-
interface UseTableColumn<
|
|
1156
|
+
interface UseTableColumn<RecordType extends Record<string, any>> extends Column<RecordType> {
|
|
1125
1157
|
/** Toggles sorting for this column. */
|
|
1126
1158
|
toggleSort: (options?: ToggleSortOptions) => UseTableNavigationResponse;
|
|
1127
1159
|
/** Checks whether the column is being sorted. */
|
|
@@ -1135,11 +1167,15 @@ interface UseTableColumn<RecordTypeWithExtra extends Record<string, any>> extend
|
|
|
1135
1167
|
/** Checks whether the column is filterable. */
|
|
1136
1168
|
isFilterable: boolean;
|
|
1137
1169
|
}
|
|
1138
|
-
interface UseTableRecordItem<RecordType extends Record<string, any
|
|
1170
|
+
interface UseTableRecordItem<RecordType extends Record<string, any>> {
|
|
1139
1171
|
/** The actual record. */
|
|
1140
1172
|
record: RecordType;
|
|
1141
|
-
/**
|
|
1173
|
+
/** Local key of the record. Use this as a rendering key. */
|
|
1142
1174
|
key: RecordIdentifier;
|
|
1175
|
+
/** Server-side key of the record, if any. */
|
|
1176
|
+
recordKey: RecordIdentifier | undefined;
|
|
1177
|
+
/** Whether this record has a server-side key. */
|
|
1178
|
+
hasKey: boolean;
|
|
1143
1179
|
/** Executes the given inline action. */
|
|
1144
1180
|
execute: (action: string | InlineAction) => UseTableNavigationResponse;
|
|
1145
1181
|
/** Gets the available inline actions. */
|
|
@@ -1155,11 +1191,11 @@ interface UseTableRecordItem<RecordType extends Record<string, any>, RecordTypeW
|
|
|
1155
1191
|
/** Checks whether this record is selected. */
|
|
1156
1192
|
selected: boolean;
|
|
1157
1193
|
/** Gets the value of the record for the specified column. */
|
|
1158
|
-
value: (column: string | Column<
|
|
1194
|
+
value: (column: string | Column<RecordType>) => any;
|
|
1159
1195
|
/** Gets the extra object of the record for the specified column. */
|
|
1160
|
-
extra: (column: string | Column<
|
|
1196
|
+
extra: (column: string | Column<RecordType>, path: string) => any;
|
|
1161
1197
|
}
|
|
1162
|
-
interface UseTableReturn<T extends Table<any, any>, RecordType extends Record<string, any> = (T extends Table<infer R, any> ? R : any), PaginatorKind extends 'cursor' | 'length-aware' | 'simple' = (T extends Table<any, infer P> ? P : 'length-aware')
|
|
1198
|
+
interface UseTableReturn<T extends Table<any, any>, RecordType extends Record<string, any> = (T extends Table<infer R, any> ? R : any), PaginatorKind extends 'cursor' | 'length-aware' | 'simple' = (T extends Table<any, infer P> ? P : 'length-aware')> extends Omit<UseRefinements, 'filters' | 'sorts' | 'filtersKey' | 'sortsKey'> {
|
|
1163
1199
|
/** Selects all records. */
|
|
1164
1200
|
selectAll: () => void;
|
|
1165
1201
|
/** Deselects all records. */
|
|
@@ -1171,7 +1207,7 @@ interface UseTableReturn<T extends Table<any, any>, RecordType extends Record<st
|
|
|
1171
1207
|
/** Whether all records on the current page are selected. */
|
|
1172
1208
|
isPageSelected: boolean;
|
|
1173
1209
|
/** Checks if the given record is selected. */
|
|
1174
|
-
isSelected: (record:
|
|
1210
|
+
isSelected: (record: RecordType) => boolean;
|
|
1175
1211
|
/** Whether all records are selected. */
|
|
1176
1212
|
allSelected: boolean;
|
|
1177
1213
|
/** Whether any records are selected. */
|
|
@@ -1185,33 +1221,33 @@ interface UseTableReturn<T extends Table<any, any>, RecordType extends Record<st
|
|
|
1185
1221
|
value: RecordIdentifier;
|
|
1186
1222
|
};
|
|
1187
1223
|
/** Toggles selection for the given record. */
|
|
1188
|
-
toggle: (record:
|
|
1224
|
+
toggle: (record: RecordType, force?: boolean) => void;
|
|
1189
1225
|
/** Toggles selection for all records. */
|
|
1190
1226
|
toggleAll: (force?: boolean) => void;
|
|
1191
1227
|
/** Selects selection for the given record. */
|
|
1192
|
-
select: (record:
|
|
1228
|
+
select: (record: RecordType) => void;
|
|
1193
1229
|
/** Deselects selection for the given record. */
|
|
1194
|
-
deselect: (record:
|
|
1230
|
+
deselect: (record: RecordType) => void;
|
|
1195
1231
|
/** List of inline actions for this table. */
|
|
1196
|
-
inlineActions: Array<UseTableInlineActionItem<RecordType
|
|
1232
|
+
inlineActions: Array<UseTableInlineActionItem<RecordType>>;
|
|
1197
1233
|
/** List of bulk actions for this table. */
|
|
1198
1234
|
bulkActions: Array<UseTableBulkActionItem>;
|
|
1199
1235
|
/** Executes the given inline action for the given record. */
|
|
1200
1236
|
executeInlineAction: (action: InlineAction | string, options: {
|
|
1201
|
-
record:
|
|
1237
|
+
record: RecordIdentifier | RecordType;
|
|
1202
1238
|
} & Omit<HybridRequestOptions, 'url'>) => UseTableNavigationResponse;
|
|
1203
1239
|
/** Executes the given bulk action. */
|
|
1204
1240
|
executeBulkAction: (action: BulkAction | string, options?: Omit<HybridRequestOptions, 'url'> & {
|
|
1205
1241
|
deselect?: boolean;
|
|
1206
1242
|
}) => UseTableNavigationResponse;
|
|
1207
1243
|
/** List of columns for this table. */
|
|
1208
|
-
columns: Array<UseTableColumn<
|
|
1244
|
+
columns: Array<UseTableColumn<RecordType>>;
|
|
1209
1245
|
/** List of records for this table. */
|
|
1210
1246
|
data: RecordType[];
|
|
1211
1247
|
/** List of records for this table. */
|
|
1212
|
-
records: Array<UseTableRecordItem<RecordType
|
|
1248
|
+
records: Array<UseTableRecordItem<RecordType>>;
|
|
1213
1249
|
/** Paginated meta and links. */
|
|
1214
|
-
paginator: PaginatorResult<
|
|
1250
|
+
paginator: PaginatorResult<RecordType, Table<RecordType, PaginatorKind>['paginator']>;
|
|
1215
1251
|
/** Available filters. */
|
|
1216
1252
|
filters: ExtractRefValue<UseRefinements['filters']>;
|
|
1217
1253
|
/** Available sorts. */
|
|
@@ -1224,7 +1260,7 @@ interface UseTableReturn<T extends Table<any, any>, RecordType extends Record<st
|
|
|
1224
1260
|
/**
|
|
1225
1261
|
* Provides utilities for working with tables.
|
|
1226
1262
|
*/
|
|
1227
|
-
declare function useTable<T extends Table<any, any>, RecordType extends Record<string, any> = (T extends Table<infer R, any> ? R : any), PaginatorKind extends 'cursor' | 'length-aware' | 'simple' = (T extends Table<any, infer P> ? P : 'length-aware')
|
|
1263
|
+
declare function useTable<T extends Table<any, any>, RecordType extends Record<string, any> = (T extends Table<infer R, any> ? R : any), PaginatorKind extends 'cursor' | 'length-aware' | 'simple' = (T extends Table<any, infer P> ? P : 'length-aware')>(input: MaybeRefOrGetter<T>, defaultOptions?: TableDefaultOptions): UseTableReturn<T, RecordType, PaginatorKind>;
|
|
1228
1264
|
//#endregion
|
|
1229
1265
|
//#region src/composables/validation.d.ts
|
|
1230
1266
|
/** Accesses all validation errors grouped by bag name. */
|
|
@@ -1322,4 +1358,4 @@ interface SetupArguments {
|
|
|
1322
1358
|
payload: Record<string, any>;
|
|
1323
1359
|
}
|
|
1324
1360
|
//#endregion
|
|
1325
|
-
export { Action, AvailableHybridRequestOptions, AvailableHybridRequestOptionsForFilters, BaseFilterRefinement, BindFilterOptions, BooleanFilterRefinement, BoundBooleanFilterRefinement, BoundCallbackFilterRefinement, BoundDateFilterRefinement, BoundFilterRefinement, BoundSelectFilterRefinement, BoundSortRefinement, BoundTernaryFilterRefinement, BoundTextFilterRefinement, BoundTrashedFilterRefinement, BulkAction, BulkSelection, CallbackFilterRefinement, Column, DateFilterRefinement, DefaultFormOptions, Deferred, FilterOperator, FilterRefinement, Form, type FormProps, FormReturn, type FormSlotProps, type FormSubmitOptions, type InitializeOptions, InlineAction, InternalProperties, MaybeWithData, NumericFilterRefinement, PaginatorResult, RecordIdentifier, Refinements, RouterLink, SelectFilterRefinement, SortDirection, SortRefinement, Table, TableDefaultOptions, TernaryFilterRefinement, TextFilterRefinement, TimeSuggestion, TimeframeSuggestion, ToggleSortOptions, TrashedFilterRefinement, UseRefinements, UseTableBulkActionItem, UseTableColumn, UseTableInlineActionItem, UseTableRecordItem, UseTableReturn, WhenVisible, createPaginator, initializeHybridly, isBooleanFilter, isCallbackFilter, isDateFilter, isSelectFilter, isTernaryFilter, isTextFilter, isTrashedFilter, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable, useValidation, useValidationBag };
|
|
1361
|
+
export { Action, AvailableHybridRequestOptions, AvailableHybridRequestOptionsForFilters, BaseFilterRefinement, BindFilterOptions, BooleanFilterRefinement, BoundBooleanFilterRefinement, BoundCallbackFilterRefinement, BoundDateFilterRefinement, BoundFilterRefinement, BoundSelectFilterRefinement, BoundSortRefinement, BoundTernaryFilterRefinement, BoundTextFilterRefinement, BoundTrashedFilterRefinement, BulkAction, BulkSelection, CallbackFilterRefinement, Column, DateFilterRefinement, DefaultFormOptions, Deferred, FilterOperator, FilterRefinement, Form, type FormProps, FormReturn, type FormSlotProps, type FormSubmitOptions, type InitializeOptions, InlineAction, InternalProperties, MaybeWithData, NumericFilterRefinement, PaginatorResult, RecordIdentifier, Refinements, RouterLink, SelectFilterRefinement, SortDirection, SortRefinement, Table, TableCell, TableCellRow, TableDefaultOptions, TernaryFilterRefinement, TextFilterRefinement, TimeSuggestion, TimeframeSuggestion, ToggleSortOptions, TrashedFilterRefinement, UseRefinements, UseTableBulkActionItem, UseTableColumn, UseTableInlineActionItem, UseTableRecordItem, UseTableReturn, WhenVisible, createPaginator, getBulkSelectionRange, initializeHybridly, isBooleanFilter, isCallbackFilter, isDateFilter, isSelectFilter, isTernaryFilter, isTextFilter, isTrashedFilter, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable, useValidation, useValidationBag };
|
package/dist/index.mjs
CHANGED
|
@@ -3,11 +3,11 @@ import { debug, merge, random, showViewComponentErrorModal, wrap } from "@hybrid
|
|
|
3
3
|
import { computed, createApp, defineComponent, getCurrentInstance, h, isRef, nextTick, onMounted, onUnmounted, reactive, readonly, ref, shallowRef, toRaw, toValue, triggerRef, unref, watch } from "vue";
|
|
4
4
|
import { createRouter, definePlugin, makeUrl, parseQueryString, registerHook as registerHook$1, route, route as route$1, router, router as router$1, stringifyQueryString } from "@hybridly/core";
|
|
5
5
|
import { get, set, unset } from "es-toolkit/compat";
|
|
6
|
+
import { debounce } from "es-toolkit/function";
|
|
6
7
|
import { clone, cloneDeep } from "es-toolkit/object";
|
|
7
8
|
import { isEqual } from "es-toolkit/predicate";
|
|
8
9
|
import { setupDevtoolsPlugin } from "@vue/devtools-api";
|
|
9
10
|
import nprogress from "nprogress";
|
|
10
|
-
import { debounce } from "es-toolkit/function";
|
|
11
11
|
import { getByPath } from "@clickbar/dot-diver";
|
|
12
12
|
//#region src/stores/state.ts
|
|
13
13
|
const state = {
|
|
@@ -216,7 +216,7 @@ function useForm(options) {
|
|
|
216
216
|
* Submits the form.
|
|
217
217
|
*/
|
|
218
218
|
function submit(optionsOverrides) {
|
|
219
|
-
const { fields: _f, key: _k, ...optionsWithoutFields } = options;
|
|
219
|
+
const { fields: _f, key: _k, automaticallySubmit: _as, ...optionsWithoutFields } = options;
|
|
220
220
|
const resolvedOptions = optionsOverrides ? merge(optionsWithoutFields, optionsOverrides, { mergePlainObjects: true }) : optionsWithoutFields;
|
|
221
221
|
const { timeout, resetOnSuccess, resetOnError, setDefaultOnSuccess, transform, ...requestOptions } = merge(formStore.getDefaultConfig(), resolvedOptions, { mergePlainObjects: true });
|
|
222
222
|
const url = typeof requestOptions.url === "function" ? requestOptions.url() : requestOptions.url;
|
|
@@ -274,6 +274,23 @@ function useForm(options) {
|
|
|
274
274
|
}
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
+
if (options.automaticallySubmit) {
|
|
278
|
+
const submitOptions = options.automaticallySubmit === true ? void 0 : (() => {
|
|
279
|
+
const { debounce: _debounce, ...submitOptions } = options.automaticallySubmit;
|
|
280
|
+
return submitOptions;
|
|
281
|
+
})();
|
|
282
|
+
const automaticallySubmitOptions = options.automaticallySubmit === true ? {
|
|
283
|
+
debounce: 100,
|
|
284
|
+
immediate: true
|
|
285
|
+
} : options.automaticallySubmit;
|
|
286
|
+
watch(() => fields, debounce(() => {
|
|
287
|
+
if (!isDirty.value) return;
|
|
288
|
+
submit(submitOptions);
|
|
289
|
+
}, automaticallySubmitOptions.debounce ?? 100), {
|
|
290
|
+
deep: true,
|
|
291
|
+
immediate: automaticallySubmitOptions.immediate ?? true
|
|
292
|
+
});
|
|
293
|
+
}
|
|
277
294
|
/**
|
|
278
295
|
* Clears all errors.
|
|
279
296
|
*/
|
|
@@ -1263,6 +1280,9 @@ async function initializeHybridly(options = {}) {
|
|
|
1263
1280
|
onContextUpdate: (context) => {
|
|
1264
1281
|
state.setContext(context);
|
|
1265
1282
|
},
|
|
1283
|
+
onPropertiesUpdate: (properties) => {
|
|
1284
|
+
state.setProperties(properties);
|
|
1285
|
+
},
|
|
1266
1286
|
onViewSwap: async (options) => {
|
|
1267
1287
|
if (options.component) {
|
|
1268
1288
|
onMountedCallbacks.push(() => options.onMounted?.({ isDialog: false }));
|
|
@@ -1373,6 +1393,21 @@ function useBackForward(options) {
|
|
|
1373
1393
|
}
|
|
1374
1394
|
//#endregion
|
|
1375
1395
|
//#region src/composables/bulk-select.ts
|
|
1396
|
+
/**
|
|
1397
|
+
* Returns the inclusive range between two records in the given order.
|
|
1398
|
+
*
|
|
1399
|
+
* This is useful for implementing shift-click bulk selection: keep track of the last selected anchor,
|
|
1400
|
+
* then pass the currently visible record identifiers and the clicked target identifier to this helper.
|
|
1401
|
+
* If the target is not in the list, an empty range is returned. If the anchor is missing, only the target is returned.
|
|
1402
|
+
*/
|
|
1403
|
+
function getBulkSelectionRange(records, anchor, target) {
|
|
1404
|
+
const targetIndex = records.indexOf(target);
|
|
1405
|
+
if (targetIndex === -1) return [];
|
|
1406
|
+
if (anchor === void 0) return [target];
|
|
1407
|
+
const anchorIndex = records.indexOf(anchor);
|
|
1408
|
+
if (anchorIndex === -1) return [target];
|
|
1409
|
+
return records.slice(Math.min(anchorIndex, targetIndex), Math.max(anchorIndex, targetIndex) + 1);
|
|
1410
|
+
}
|
|
1376
1411
|
function useBulkSelect() {
|
|
1377
1412
|
const selection = ref({
|
|
1378
1413
|
all: false,
|
|
@@ -1921,11 +1956,24 @@ function useTable(input, defaultOptions = {}) {
|
|
|
1921
1956
|
*/
|
|
1922
1957
|
function getRecordKey(record) {
|
|
1923
1958
|
if (typeof record !== "object") return record;
|
|
1924
|
-
if (
|
|
1925
|
-
if (!table.value.keyName) throw new Error("Record key cannot be fetched because the table has no defined key.");
|
|
1959
|
+
if (!table.value.keyName) return;
|
|
1926
1960
|
const value = Reflect.get(record, table.value.keyName);
|
|
1927
|
-
if (typeof value === "
|
|
1928
|
-
|
|
1961
|
+
if (typeof value === "string" || typeof value === "number") return value;
|
|
1962
|
+
}
|
|
1963
|
+
function getPageRecordKeys() {
|
|
1964
|
+
return table.value.records.map((record) => getRecordKey(record)).filter((key) => key !== void 0);
|
|
1965
|
+
}
|
|
1966
|
+
function warnMissingRecordKey(action) {
|
|
1967
|
+
console.warn(`Cannot ${action} because this table record has no key.`);
|
|
1968
|
+
}
|
|
1969
|
+
function getColumnName(column) {
|
|
1970
|
+
return typeof column === "string" ? column : column.name;
|
|
1971
|
+
}
|
|
1972
|
+
function getCell(index, column) {
|
|
1973
|
+
return table.value.cells[index]?.columns[getColumnName(column)] ?? {
|
|
1974
|
+
value: void 0,
|
|
1975
|
+
extra: {}
|
|
1976
|
+
};
|
|
1929
1977
|
}
|
|
1930
1978
|
function resolveInlineAction(action) {
|
|
1931
1979
|
if (typeof action !== "string") return action;
|
|
@@ -1944,10 +1992,15 @@ function useTable(input, defaultOptions = {}) {
|
|
|
1944
1992
|
*/
|
|
1945
1993
|
async function executeInlineAction(action, options) {
|
|
1946
1994
|
const resolvedAction = resolveInlineAction(action);
|
|
1995
|
+
const recordKey = getRecordKey(options.record);
|
|
1947
1996
|
if (!resolvedAction) {
|
|
1948
1997
|
console.warn(`Action [${action}] is not defined`);
|
|
1949
1998
|
return;
|
|
1950
1999
|
}
|
|
2000
|
+
if (recordKey === void 0) {
|
|
2001
|
+
warnMissingRecordKey("execute an inline action");
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
1951
2004
|
return await router$1.navigate({
|
|
1952
2005
|
method: "post",
|
|
1953
2006
|
url: getActionUrl(resolvedAction, table.value),
|
|
@@ -1957,7 +2010,7 @@ function useTable(input, defaultOptions = {}) {
|
|
|
1957
2010
|
type: "action:inline",
|
|
1958
2011
|
action: resolvedAction.name,
|
|
1959
2012
|
tableId: table.value.id,
|
|
1960
|
-
recordId:
|
|
2013
|
+
recordId: recordKey
|
|
1961
2014
|
}
|
|
1962
2015
|
});
|
|
1963
2016
|
}
|
|
@@ -1996,20 +2049,35 @@ function useTable(input, defaultOptions = {}) {
|
|
|
1996
2049
|
});
|
|
1997
2050
|
}
|
|
1998
2051
|
return reactive({
|
|
1999
|
-
selectAll: bulk.selectAll,
|
|
2052
|
+
selectAll: () => table.value.keyName ? bulk.selectAll() : warnMissingRecordKey("select all records"),
|
|
2000
2053
|
deselectAll: bulk.deselectAll,
|
|
2001
|
-
selectPage: () => bulk.select(...
|
|
2002
|
-
deselectPage: () => bulk.deselect(...
|
|
2003
|
-
isPageSelected: computed(() =>
|
|
2004
|
-
|
|
2054
|
+
selectPage: () => bulk.select(...getPageRecordKeys()),
|
|
2055
|
+
deselectPage: () => bulk.deselect(...getPageRecordKeys()),
|
|
2056
|
+
isPageSelected: computed(() => {
|
|
2057
|
+
const keys = getPageRecordKeys();
|
|
2058
|
+
return keys.length > 0 && keys.every((key) => bulk.selected(key));
|
|
2059
|
+
}),
|
|
2060
|
+
isSelected: (record) => {
|
|
2061
|
+
const key = getRecordKey(record);
|
|
2062
|
+
return key === void 0 ? false : bulk.selected(key);
|
|
2063
|
+
},
|
|
2005
2064
|
allSelected: bulk.allSelected,
|
|
2006
2065
|
anySelected: bulk.anySelected,
|
|
2007
2066
|
selection: bulk.selection,
|
|
2008
2067
|
bindCheckbox: (key) => bulk.bindCheckbox(key),
|
|
2009
|
-
toggle: (record, force) =>
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2068
|
+
toggle: (record, force) => {
|
|
2069
|
+
const key = getRecordKey(record);
|
|
2070
|
+
return key === void 0 ? warnMissingRecordKey("toggle record selection") : bulk.toggle(key, force);
|
|
2071
|
+
},
|
|
2072
|
+
toggleAll: (force) => table.value.keyName ? bulk.toggleAll(force) : warnMissingRecordKey("toggle all records"),
|
|
2073
|
+
select: (record) => {
|
|
2074
|
+
const key = getRecordKey(record);
|
|
2075
|
+
return key === void 0 ? warnMissingRecordKey("select this record") : bulk.select(key);
|
|
2076
|
+
},
|
|
2077
|
+
deselect: (record) => {
|
|
2078
|
+
const key = getRecordKey(record);
|
|
2079
|
+
return key === void 0 ? warnMissingRecordKey("deselect this record") : bulk.deselect(key);
|
|
2080
|
+
},
|
|
2013
2081
|
inlineActions: computed(() => table.value.inlineActions.map((action) => ({
|
|
2014
2082
|
execute: (record) => executeInlineAction(action, { record }),
|
|
2015
2083
|
...action
|
|
@@ -2029,29 +2097,27 @@ function useTable(input, defaultOptions = {}) {
|
|
|
2029
2097
|
isSortable: !!refinements.sorts.value.find((sort) => sort.name === column.name),
|
|
2030
2098
|
isFilterable: !!refinements.filters.value.find((filters) => filters.name === column.name)
|
|
2031
2099
|
}))),
|
|
2032
|
-
data: computed(() =>
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
}).filter(Boolean);
|
|
2038
|
-
}),
|
|
2039
|
-
records: computed(() => table.value.records.map((record) => {
|
|
2040
|
-
const entries = Object.entries(record).map(([key, value]) => [key, value.value]).filter(([key]) => key !== "__hybridId");
|
|
2100
|
+
data: computed(() => table.value.records),
|
|
2101
|
+
records: computed(() => table.value.records.map((record, index) => {
|
|
2102
|
+
const recordKey = getRecordKey(record);
|
|
2103
|
+
const localKey = recordKey ?? `row-${index}`;
|
|
2104
|
+
const selected = recordKey === void 0 ? false : bulk.selected(recordKey);
|
|
2041
2105
|
return {
|
|
2042
|
-
record
|
|
2043
|
-
key:
|
|
2044
|
-
|
|
2106
|
+
record,
|
|
2107
|
+
key: localKey,
|
|
2108
|
+
recordKey,
|
|
2109
|
+
hasKey: recordKey !== void 0,
|
|
2110
|
+
execute: (action) => executeInlineAction(action, { record }),
|
|
2045
2111
|
actions: table.value.inlineActions.map((action) => ({
|
|
2046
2112
|
...action,
|
|
2047
|
-
execute: () => executeInlineAction(action.name, { record
|
|
2113
|
+
execute: () => executeInlineAction(action.name, { record })
|
|
2048
2114
|
})),
|
|
2049
|
-
select: () => bulk.select(
|
|
2050
|
-
deselect: () => bulk.deselect(
|
|
2051
|
-
toggle: (force) => bulk.toggle(
|
|
2052
|
-
selected
|
|
2053
|
-
value: (column) =>
|
|
2054
|
-
extra: (column, path) => getByPath(
|
|
2115
|
+
select: () => recordKey === void 0 ? warnMissingRecordKey("select this record") : bulk.select(recordKey),
|
|
2116
|
+
deselect: () => recordKey === void 0 ? warnMissingRecordKey("deselect this record") : bulk.deselect(recordKey),
|
|
2117
|
+
toggle: (force) => recordKey === void 0 ? warnMissingRecordKey("toggle record selection") : bulk.toggle(recordKey, force),
|
|
2118
|
+
selected,
|
|
2119
|
+
value: (column) => getCell(index, column).value,
|
|
2120
|
+
extra: (column, path) => getByPath(getCell(index, column).extra, path)
|
|
2055
2121
|
};
|
|
2056
2122
|
})),
|
|
2057
2123
|
paginator: computed(() => createPaginator(table.value.paginator, defaultOptions)),
|
|
@@ -2069,4 +2135,4 @@ function useValidationBag(bag = "default") {
|
|
|
2069
2135
|
return readonly(toReactive(computed(() => state.context.value?.validation?.[bag] ?? {})));
|
|
2070
2136
|
}
|
|
2071
2137
|
//#endregion
|
|
2072
|
-
export { Deferred, Form, RouterLink, WhenVisible, createPaginator, initializeHybridly, isBooleanFilter, isCallbackFilter, isDateFilter, isSelectFilter, isTernaryFilter, isTextFilter, isTrashedFilter, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable, useValidation, useValidationBag };
|
|
2138
|
+
export { Deferred, Form, RouterLink, WhenVisible, createPaginator, getBulkSelectionRange, initializeHybridly, isBooleanFilter, isCallbackFilter, isDateFilter, isSelectFilter, isTernaryFilter, isTextFilter, isTrashedFilter, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable, useValidation, useValidationBag };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridly/vue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.10.0-beta.
|
|
4
|
+
"version": "0.10.0-beta.28",
|
|
5
5
|
"description": "Vue adapter for Hybridly",
|
|
6
6
|
"author": "Enzo Innocenzi <enzo@innocenzi.dev>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@clickbar/dot-diver": "^1.0.7",
|
|
49
49
|
"es-toolkit": "^1.45.1",
|
|
50
|
-
"@hybridly/core": "0.10.0-beta.
|
|
51
|
-
"@hybridly/utils": "0.10.0-beta.
|
|
50
|
+
"@hybridly/core": "0.10.0-beta.28",
|
|
51
|
+
"@hybridly/utils": "0.10.0-beta.28",
|
|
52
52
|
"@vue/devtools-api": "^8.1.0",
|
|
53
53
|
"defu": "^6.1.4",
|
|
54
54
|
"nprogress": "^0.2.0"
|