@masterteam/components 0.0.57 → 0.0.59
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/assets/common.css +1 -1
- package/breadcrumb/index.d.ts +1 -0
- package/date-field/index.d.ts +1 -0
- package/fesm2022/masterteam-components-breadcrumb.mjs +4 -3
- package/fesm2022/masterteam-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/masterteam-components-date-field.mjs +5 -3
- package/fesm2022/masterteam-components-date-field.mjs.map +1 -1
- package/fesm2022/masterteam-components-paginator.mjs +2 -2
- package/fesm2022/masterteam-components-paginator.mjs.map +1 -1
- package/fesm2022/masterteam-components-table.mjs +2 -2
- package/fesm2022/masterteam-components-table.mjs.map +1 -1
- package/fesm2022/masterteam-components.mjs +254 -7
- package/fesm2022/masterteam-components.mjs.map +1 -1
- package/index.d.ts +181 -26
- package/package.json +43 -43
|
@@ -2,6 +2,9 @@ import { providePrimeNG } from 'primeng/config';
|
|
|
2
2
|
import Aura from '@primeuix/themes/aura';
|
|
3
3
|
import { updatePreset, definePreset } from '@primeuix/themes';
|
|
4
4
|
import { MessageService, ConfirmationService } from 'primeng/api';
|
|
5
|
+
import { computed } from '@angular/core';
|
|
6
|
+
import { of } from 'rxjs';
|
|
7
|
+
import { tap, catchError, finalize } from 'rxjs/operators';
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* Converts a hex color string to an HSL tuple.
|
|
@@ -447,12 +450,6 @@ function provideMTConfirmation() {
|
|
|
447
450
|
return ConfirmationService;
|
|
448
451
|
}
|
|
449
452
|
|
|
450
|
-
function isInvalid(control) {
|
|
451
|
-
if (!control)
|
|
452
|
-
return false;
|
|
453
|
-
return control && control?.invalid && control?.touched;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
453
|
class ValidatorConfig {
|
|
457
454
|
type;
|
|
458
455
|
value;
|
|
@@ -902,13 +899,263 @@ function wrapValidatorWithMessage(validator, errorKey, message) {
|
|
|
902
899
|
// return new TextFieldConfig()
|
|
903
900
|
// }
|
|
904
901
|
|
|
902
|
+
/**
|
|
903
|
+
* Base facade with smart query selector factory
|
|
904
|
+
*/
|
|
905
|
+
class BaseFacade {
|
|
906
|
+
/**
|
|
907
|
+
* Creates a query object with separate signals for data, loading, and error states
|
|
908
|
+
* Each property is its own signal for granular reactivity
|
|
909
|
+
*
|
|
910
|
+
* @example
|
|
911
|
+
* readonly modulesQuery = this.query(
|
|
912
|
+
* 'getModulesLoading',
|
|
913
|
+
* (state) => state.allModules
|
|
914
|
+
* );
|
|
915
|
+
*
|
|
916
|
+
* // In template - each is a separate signal:
|
|
917
|
+
* @if (modulesQuery.isPending()) { Loading... }
|
|
918
|
+
* @if (modulesQuery.error(); as error) { Error: {{ error }} }
|
|
919
|
+
* @if (modulesQuery.data(); as modules) {
|
|
920
|
+
* <div *ngFor="let m of modules">{{ m.title }}</div>
|
|
921
|
+
* }
|
|
922
|
+
*/
|
|
923
|
+
query(loadingKey, dataSelector) {
|
|
924
|
+
const stateSignal = this.state();
|
|
925
|
+
const isPending = computed(() => {
|
|
926
|
+
const currentState = stateSignal();
|
|
927
|
+
return currentState.loadingActive?.includes(loadingKey) ?? false;
|
|
928
|
+
}, ...(ngDevMode ? [{ debugName: "isPending" }] : []));
|
|
929
|
+
const error = computed(() => {
|
|
930
|
+
const currentState = stateSignal();
|
|
931
|
+
return currentState.errors?.[loadingKey] ?? null;
|
|
932
|
+
}, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
933
|
+
const data = computed(() => {
|
|
934
|
+
const currentState = stateSignal();
|
|
935
|
+
const hasError = currentState.errors?.[loadingKey];
|
|
936
|
+
return hasError ? null : dataSelector(currentState);
|
|
937
|
+
}, ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
938
|
+
const isSuccess = computed(() => !isPending() && !error() && data() !== null, ...(ngDevMode ? [{ debugName: "isSuccess" }] : []));
|
|
939
|
+
const isError = computed(() => !!error(), ...(ngDevMode ? [{ debugName: "isError" }] : []));
|
|
940
|
+
return {
|
|
941
|
+
data,
|
|
942
|
+
isPending,
|
|
943
|
+
isSuccess,
|
|
944
|
+
isError,
|
|
945
|
+
error,
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Creates a loading signal for a specific operation
|
|
950
|
+
*/
|
|
951
|
+
loading(loadingKey) {
|
|
952
|
+
const stateSignal = this.state();
|
|
953
|
+
return computed(() => {
|
|
954
|
+
const currentState = stateSignal();
|
|
955
|
+
return currentState.loadingActive?.includes(loadingKey) ?? false;
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Creates an error signal for a specific operation
|
|
960
|
+
*/
|
|
961
|
+
errorSignal(loadingKey) {
|
|
962
|
+
const stateSignal = this.state();
|
|
963
|
+
return computed(() => {
|
|
964
|
+
const currentState = stateSignal();
|
|
965
|
+
return currentState.errors?.[loadingKey] ?? null;
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
function createEntityAdapter() {
|
|
971
|
+
return {
|
|
972
|
+
addOne: (state, entity) => [...state, entity],
|
|
973
|
+
upsertOne: (state, entity, uniqueKey = 'id') => {
|
|
974
|
+
const key = entity[uniqueKey];
|
|
975
|
+
if (key == null)
|
|
976
|
+
return state;
|
|
977
|
+
const index = state.findIndex((e) => e[uniqueKey] === key);
|
|
978
|
+
if (index === -1) {
|
|
979
|
+
return [...state, entity];
|
|
980
|
+
}
|
|
981
|
+
const clone = [...state];
|
|
982
|
+
clone[index] = entity;
|
|
983
|
+
return clone;
|
|
984
|
+
},
|
|
985
|
+
updateOne: (state, id, changes, uniqueKey = 'id') => state.map((e) => (e[uniqueKey] === id ? { ...e, ...changes } : e)),
|
|
986
|
+
removeOne: (state, id, uniqueKey = 'id') => state.filter((e) => e[uniqueKey] !== id),
|
|
987
|
+
setAll: (_state, entities) => [...entities],
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
function startLoading(ctx, loadingName) {
|
|
992
|
+
const { loadingActive, errors } = ctx.getState();
|
|
993
|
+
if (!loadingActive.includes(loadingName)) {
|
|
994
|
+
ctx.patchState({
|
|
995
|
+
loadingActive: [...loadingActive, loadingName],
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
if (errors && errors[loadingName]) {
|
|
999
|
+
const { [loadingName]: _removed, ...rest } = errors;
|
|
1000
|
+
ctx.patchState({ errors: rest });
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function endLoading(ctx, loadingName) {
|
|
1004
|
+
const { loadingActive } = ctx.getState();
|
|
1005
|
+
ctx.patchState({
|
|
1006
|
+
loadingActive: loadingActive.filter((name) => name !== loadingName),
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
function setLoadingError(ctx, loadingName, message) {
|
|
1010
|
+
const { errors } = ctx.getState();
|
|
1011
|
+
ctx.patchState({
|
|
1012
|
+
errors: { ...errors, [loadingName]: message },
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
function handleApiRequest(config) {
|
|
1017
|
+
const { ctx, key, request$, onSuccess, onError, errorMessage } = config;
|
|
1018
|
+
startLoading(ctx, key);
|
|
1019
|
+
return request$.pipe(tap((response) => {
|
|
1020
|
+
const state = ctx.getState();
|
|
1021
|
+
const patch = onSuccess(response, state);
|
|
1022
|
+
if (patch) {
|
|
1023
|
+
ctx.patchState(patch);
|
|
1024
|
+
}
|
|
1025
|
+
}), catchError((error) => {
|
|
1026
|
+
const state = ctx.getState();
|
|
1027
|
+
const message = error?.error?.message ?? error?.message ?? errorMessage;
|
|
1028
|
+
setLoadingError(ctx, key, message);
|
|
1029
|
+
// Call onError callback if provided
|
|
1030
|
+
if (onError) {
|
|
1031
|
+
const patch = onError(error, state);
|
|
1032
|
+
if (patch) {
|
|
1033
|
+
ctx.patchState(patch);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return of(null);
|
|
1037
|
+
}), finalize(() => endLoading(ctx, key)));
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* T = entity type (Module, User, ...)
|
|
1042
|
+
* TState = full state model (must include LoadingStateShape)
|
|
1043
|
+
* TLoad = union type of loading keys for this feature
|
|
1044
|
+
*/
|
|
1045
|
+
class CrudStateBase {
|
|
1046
|
+
adapter = createEntityAdapter();
|
|
1047
|
+
/**
|
|
1048
|
+
* Helper to create default updateState function
|
|
1049
|
+
*/
|
|
1050
|
+
getDefaultUpdateState(stateProperty) {
|
|
1051
|
+
// Try to extract the property name from the stateProperty function
|
|
1052
|
+
const funcStr = stateProperty.toString();
|
|
1053
|
+
const match = funcStr.match(/\.([a-zA-Z_$][a-zA-Z0-9_$]*)/); // Match .propertyName
|
|
1054
|
+
const key = match ? match[1] : 'items';
|
|
1055
|
+
return (state, items) => ({ [key]: items });
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Load data (single item or array) with config object
|
|
1059
|
+
*/
|
|
1060
|
+
load(ctx, config) {
|
|
1061
|
+
return handleApiRequest({
|
|
1062
|
+
ctx,
|
|
1063
|
+
key: config.key,
|
|
1064
|
+
request$: config.request$,
|
|
1065
|
+
onSuccess: (response, state) => {
|
|
1066
|
+
const data = config.transform
|
|
1067
|
+
? config.transform(response.data)
|
|
1068
|
+
: response.data;
|
|
1069
|
+
// If stateProperty provided, use adapter for array operations
|
|
1070
|
+
if (config.stateProperty) {
|
|
1071
|
+
const items = this.adapter.setAll(config.stateProperty(state), data);
|
|
1072
|
+
const updateState = config.updateState ??
|
|
1073
|
+
this.getDefaultUpdateState(config.stateProperty);
|
|
1074
|
+
return updateState(state, items);
|
|
1075
|
+
}
|
|
1076
|
+
// Otherwise, use custom updateState directly
|
|
1077
|
+
if (config.updateState) {
|
|
1078
|
+
return config.updateState(state, data);
|
|
1079
|
+
}
|
|
1080
|
+
throw new Error('Either stateProperty or updateState must be provided');
|
|
1081
|
+
},
|
|
1082
|
+
onError: config.onError,
|
|
1083
|
+
errorMessage: config.errorMessage ?? 'Failed to load data',
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Create one entity with config object
|
|
1088
|
+
*/
|
|
1089
|
+
create(ctx, config) {
|
|
1090
|
+
const updateState = config.updateState ?? this.getDefaultUpdateState(config.stateProperty);
|
|
1091
|
+
return handleApiRequest({
|
|
1092
|
+
ctx,
|
|
1093
|
+
key: config.key,
|
|
1094
|
+
request$: config.request$,
|
|
1095
|
+
onSuccess: (response, state) => {
|
|
1096
|
+
const entity = config.transform
|
|
1097
|
+
? config.transform(response.data)
|
|
1098
|
+
: response.data;
|
|
1099
|
+
const items = this.adapter.addOne(config.stateProperty(state), entity);
|
|
1100
|
+
return updateState(state, items);
|
|
1101
|
+
},
|
|
1102
|
+
onError: config.onError,
|
|
1103
|
+
errorMessage: config.errorMessage ?? 'Failed to create item',
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Update one entity with config object
|
|
1108
|
+
*/
|
|
1109
|
+
update(ctx, config) {
|
|
1110
|
+
const updateState = config.updateState ?? this.getDefaultUpdateState(config.stateProperty);
|
|
1111
|
+
return handleApiRequest({
|
|
1112
|
+
ctx,
|
|
1113
|
+
key: config.key,
|
|
1114
|
+
request$: config.request$,
|
|
1115
|
+
onSuccess: (response, state) => {
|
|
1116
|
+
const entity = config.transform
|
|
1117
|
+
? config.transform(response.data)
|
|
1118
|
+
: response.data;
|
|
1119
|
+
const items = this.adapter.upsertOne(config.stateProperty(state), entity, config.uniqueKey);
|
|
1120
|
+
return updateState(state, items);
|
|
1121
|
+
},
|
|
1122
|
+
onError: config.onError,
|
|
1123
|
+
errorMessage: config.errorMessage ?? 'Failed to update item',
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Delete one entity with config object
|
|
1128
|
+
*/
|
|
1129
|
+
delete(ctx, config) {
|
|
1130
|
+
const updateState = config.updateState ?? this.getDefaultUpdateState(config.stateProperty);
|
|
1131
|
+
return handleApiRequest({
|
|
1132
|
+
ctx,
|
|
1133
|
+
key: config.key,
|
|
1134
|
+
request$: config.request$,
|
|
1135
|
+
onSuccess: (_response, state) => {
|
|
1136
|
+
const items = this.adapter.removeOne(config.stateProperty(state), config.id, config.uniqueKey);
|
|
1137
|
+
return updateState(state, items);
|
|
1138
|
+
},
|
|
1139
|
+
onError: config.onError,
|
|
1140
|
+
errorMessage: config.errorMessage ?? 'Failed to delete item',
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function isInvalid(control) {
|
|
1146
|
+
if (!control)
|
|
1147
|
+
return false;
|
|
1148
|
+
return control && control?.invalid && control?.touched;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
905
1151
|
/*
|
|
906
1152
|
* Public API Surface of components
|
|
907
1153
|
*/
|
|
1154
|
+
// Config
|
|
908
1155
|
|
|
909
1156
|
/**
|
|
910
1157
|
* Generated bundle index. Do not edit.
|
|
911
1158
|
*/
|
|
912
1159
|
|
|
913
|
-
export { BaseFieldConfig, CheckboxFieldConfig, ColorPickerFieldConfig, DateFieldConfig, EditorFieldConfig, IconFieldConfig, MultiSelectFieldConfig, NumberFieldConfig, PickListFieldConfig, RadioButtonFieldConfig, RadioCardsFieldConfig, SelectFieldConfig, SliderFieldConfig, SpacerFieldConfig, TextFieldConfig, TextareaFieldConfig, ToggleFieldConfig, UploadFileFieldConfig, UserSearchFieldConfig, ValidatorConfig, changeBackgroundColor, changePrimaryColor, changeTextColor, createCustomValidator, generateTailwindPalette, isInvalid, provideMTComponents, provideMTConfirmation, provideMTMessages, wrapValidatorWithMessage };
|
|
1160
|
+
export { BaseFacade, BaseFieldConfig, CheckboxFieldConfig, ColorPickerFieldConfig, CrudStateBase, DateFieldConfig, EditorFieldConfig, IconFieldConfig, MultiSelectFieldConfig, NumberFieldConfig, PickListFieldConfig, RadioButtonFieldConfig, RadioCardsFieldConfig, SelectFieldConfig, SliderFieldConfig, SpacerFieldConfig, TextFieldConfig, TextareaFieldConfig, ToggleFieldConfig, UploadFileFieldConfig, UserSearchFieldConfig, ValidatorConfig, changeBackgroundColor, changePrimaryColor, changeTextColor, createCustomValidator, createEntityAdapter, endLoading, generateTailwindPalette, handleApiRequest, isInvalid, provideMTComponents, provideMTConfirmation, provideMTMessages, setLoadingError, startLoading, wrapValidatorWithMessage };
|
|
914
1161
|
//# sourceMappingURL=masterteam-components.mjs.map
|