@pepperi-addons/ngx-lib-react 0.5.20 → 0.5.22

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/index.d.ts CHANGED
@@ -33,4 +33,8 @@ export * from './pep-query-builder.js';
33
33
  export * from './pep-remote-loader.js';
34
34
  export * from './pep-addon-block-loader.js';
35
35
  export { PepRichHtmlTextarea } from './pep-rich-html-textarea.js';
36
+ export { PepSignature } from './pep-signature.js';
37
+ export type { PepSignatureProps } from './pep-signature.js';
38
+ export { PepSmartFilters } from './pep-smart-filters.js';
39
+ export type { PepSmartFiltersProps, PepSmartFiltersRef } from './pep-smart-filters.js';
36
40
  export * from './services.js';
package/index.js CHANGED
@@ -33,6 +33,8 @@ export * from './pep-query-builder.js';
33
33
  export * from './pep-remote-loader.js';
34
34
  export * from './pep-addon-block-loader.js';
35
35
  export { PepRichHtmlTextarea } from './pep-rich-html-textarea.js';
36
+ export { PepSignature } from './pep-signature.js';
37
+ export { PepSmartFilters } from './pep-smart-filters.js';
36
38
  // Export all service helpers (bridge-based access to Angular services)
37
39
  export * from './services.js';
38
40
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pepperi-addons/ngx-lib-react",
3
- "version": "0.5.20",
3
+ "version": "0.5.22",
4
4
  "description": "Thin React wrappers for Pepperi Angular Elements (Web Components) to improve DX in React.",
5
5
  "license": "MIT",
6
6
  "author": "Pepperi",
@@ -1,11 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from 'react';
3
3
  export const PepAddonBlockLoader = ({ keyProp, addonId, remoteEntry, slugName, blockType, name, hostObject, remoteLoaderOptions, onHostEvents, onBlockLoad, ...rest }) => {
4
- const ref = useRef(null);
4
+ const containerRef = useRef(null);
5
+ const elementRef = useRef(null);
5
6
  useEffect(() => {
6
- const el = ref.current;
7
- if (!el)
7
+ const container = containerRef.current;
8
+ if (!container) {
8
9
  return;
10
+ }
11
+ const el = document.createElement('pep-addon-block-loader-element');
12
+ elementRef.current = el;
9
13
  if (typeof addonId !== 'undefined')
10
14
  el.addonId = addonId;
11
15
  if (typeof remoteEntry !== 'undefined')
@@ -20,11 +24,17 @@ export const PepAddonBlockLoader = ({ keyProp, addonId, remoteEntry, slugName, b
20
24
  el.hostObject = hostObject;
21
25
  if (typeof remoteLoaderOptions !== 'undefined')
22
26
  el.remoteLoaderOptions = remoteLoaderOptions;
23
- }, [addonId, remoteEntry, slugName, blockType, name, hostObject, remoteLoaderOptions]);
27
+ container.replaceChildren(el);
28
+ return () => {
29
+ container.replaceChildren();
30
+ elementRef.current = null;
31
+ };
32
+ }, [keyProp]);
24
33
  useEffect(() => {
25
- const el = ref.current;
26
- if (!el)
34
+ const el = elementRef.current;
35
+ if (!el) {
27
36
  return;
37
+ }
28
38
  const handlers = [];
29
39
  if (onHostEvents) {
30
40
  handlers.push(['hostEvents', (e) => { var _a; return onHostEvents((_a = e.detail) !== null && _a !== void 0 ? _a : e); }]);
@@ -35,6 +45,26 @@ export const PepAddonBlockLoader = ({ keyProp, addonId, remoteEntry, slugName, b
35
45
  handlers.forEach(([n, h]) => el.addEventListener(n, h));
36
46
  return () => handlers.forEach(([n, h]) => el.removeEventListener(n, h));
37
47
  }, [onHostEvents, onBlockLoad]);
38
- return _jsx("pep-addon-block-loader-element", { ref: ref, ...rest }, keyProp);
48
+ useEffect(() => {
49
+ const el = elementRef.current;
50
+ if (!el) {
51
+ return;
52
+ }
53
+ if (typeof addonId !== 'undefined')
54
+ el.addonId = addonId;
55
+ if (typeof remoteEntry !== 'undefined')
56
+ el.remoteEntry = remoteEntry;
57
+ if (typeof slugName !== 'undefined')
58
+ el.slugName = slugName;
59
+ if (typeof blockType !== 'undefined')
60
+ el.blockType = blockType;
61
+ if (typeof name !== 'undefined')
62
+ el.name = name;
63
+ if (typeof hostObject !== 'undefined')
64
+ el.hostObject = hostObject;
65
+ if (typeof remoteLoaderOptions !== 'undefined')
66
+ el.remoteLoaderOptions = remoteLoaderOptions;
67
+ }, [addonId, remoteEntry, slugName, blockType, name, hostObject, remoteLoaderOptions]);
68
+ return _jsx("div", { ref: containerRef, ...rest }, keyProp);
39
69
  };
40
70
  //# sourceMappingURL=pep-addon-block-loader.js.map
@@ -1,26 +1,75 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from 'react';
3
3
  export const PepRemoteLoader = ({ keyProp, options, props, events, onLoad, ...rest }) => {
4
- const ref = useRef(null);
4
+ const containerRef = useRef(null);
5
+ const elementRef = useRef(null);
6
+ const mountTokenRef = useRef(0);
7
+ const loadUnsubRef = useRef(null);
8
+ const REMOTE_LOADER_TAG = 'pep-remote-loader-element-element';
5
9
  useEffect(() => {
6
- const el = ref.current;
7
- if (!el)
10
+ const container = containerRef.current;
11
+ if (!container) {
8
12
  return;
9
- if (typeof options !== 'undefined')
13
+ }
14
+ const token = ++mountTokenRef.current;
15
+ let didCleanup = false;
16
+ void (async () => {
17
+ try {
18
+ await customElements.whenDefined(REMOTE_LOADER_TAG);
19
+ }
20
+ catch {
21
+ // Ignore.
22
+ }
23
+ if (didCleanup || token !== mountTokenRef.current) {
24
+ return;
25
+ }
26
+ const el = document.createElement(REMOTE_LOADER_TAG);
27
+ elementRef.current = el;
28
+ if (loadUnsubRef.current) {
29
+ loadUnsubRef.current();
30
+ loadUnsubRef.current = null;
31
+ }
32
+ if (onLoad) {
33
+ const handler = () => onLoad();
34
+ el.addEventListener('load', handler);
35
+ loadUnsubRef.current = () => el.removeEventListener('load', handler);
36
+ }
37
+ if (typeof options !== 'undefined') {
38
+ el.options = options;
39
+ }
40
+ if (typeof props !== 'undefined') {
41
+ el.props = props;
42
+ }
43
+ if (typeof events !== 'undefined') {
44
+ el.events = events;
45
+ }
46
+ container.replaceChildren(el);
47
+ })();
48
+ return () => {
49
+ didCleanup = true;
50
+ if (loadUnsubRef.current) {
51
+ loadUnsubRef.current();
52
+ loadUnsubRef.current = null;
53
+ }
54
+ container.replaceChildren();
55
+ elementRef.current = null;
56
+ };
57
+ }, [keyProp]);
58
+ useEffect(() => {
59
+ const el = elementRef.current;
60
+ if (!el) {
61
+ return;
62
+ }
63
+ if (typeof options !== 'undefined') {
10
64
  el.options = options;
11
- if (typeof props !== 'undefined')
65
+ }
66
+ if (typeof props !== 'undefined') {
12
67
  el.props = props;
13
- if (typeof events !== 'undefined')
68
+ }
69
+ if (typeof events !== 'undefined') {
14
70
  el.events = events;
71
+ }
15
72
  }, [options, props, events]);
16
- useEffect(() => {
17
- const el = ref.current;
18
- if (!el || !onLoad)
19
- return;
20
- const handler = () => onLoad();
21
- el.addEventListener('load', handler);
22
- return () => el.removeEventListener('load', handler);
23
- }, [onLoad]);
24
- return _jsx("pep-remote-loader-element-element", { ref: ref, ...rest }, keyProp);
73
+ return _jsx("div", { ref: containerRef, ...rest }, keyProp);
25
74
  };
26
75
  //# sourceMappingURL=pep-remote-loader.js.map
@@ -0,0 +1,24 @@
1
+ /// <reference types="react" />
2
+ export interface PepSignatureProps {
3
+ keyProp?: string;
4
+ src?: string;
5
+ label?: string;
6
+ mandatory?: boolean;
7
+ disabled?: boolean;
8
+ readonly?: boolean;
9
+ xAlignment?: 'start' | 'center' | 'end';
10
+ rowSpan?: number;
11
+ signatureURL?: string;
12
+ visible?: boolean;
13
+ form?: any;
14
+ showTitle?: boolean;
15
+ renderTitle?: boolean;
16
+ layoutType?: 'form' | 'table' | 'card';
17
+ isActive?: boolean;
18
+ handleActions?: boolean;
19
+ onChooseFile?: () => void;
20
+ onFileChange?: (event: any) => void;
21
+ onElementClick?: (event: any) => void;
22
+ onValidationChange?: (isValid: boolean) => void;
23
+ }
24
+ export declare const PepSignature: React.FC<PepSignatureProps>;
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect } from 'react';
3
+ export const PepSignature = ({ keyProp, src, label, mandatory, disabled, readonly, xAlignment, rowSpan, signatureURL, visible, form, showTitle, renderTitle, layoutType, isActive, handleActions, onChooseFile, onFileChange, onElementClick, onValidationChange, }) => {
4
+ const elementRef = useRef(null);
5
+ useEffect(() => {
6
+ const element = elementRef.current;
7
+ if (!element)
8
+ return;
9
+ // Defer property setting to ensure Angular component initialization completes
10
+ setTimeout(() => {
11
+ if (keyProp !== undefined)
12
+ element.key = keyProp;
13
+ if (src !== undefined)
14
+ element.src = src;
15
+ if (label !== undefined)
16
+ element.label = label;
17
+ if (mandatory !== undefined)
18
+ element.mandatory = mandatory;
19
+ if (disabled !== undefined)
20
+ element.disabled = disabled;
21
+ if (readonly !== undefined)
22
+ element.readonly = readonly;
23
+ if (xAlignment !== undefined)
24
+ element.xAlignment = xAlignment;
25
+ if (rowSpan !== undefined)
26
+ element.rowSpan = rowSpan;
27
+ if (signatureURL !== undefined)
28
+ element.signatureURL = signatureURL;
29
+ if (visible !== undefined)
30
+ element.visible = visible;
31
+ if (form !== undefined)
32
+ element.form = form;
33
+ if (showTitle !== undefined)
34
+ element.showTitle = showTitle;
35
+ if (renderTitle !== undefined)
36
+ element.renderTitle = renderTitle;
37
+ if (layoutType !== undefined)
38
+ element.layoutType = layoutType;
39
+ if (isActive !== undefined)
40
+ element.isActive = isActive;
41
+ if (handleActions !== undefined)
42
+ element.handleActions = handleActions;
43
+ }, 0);
44
+ }, [keyProp, src, label, mandatory, disabled, readonly, xAlignment, rowSpan, signatureURL, visible, form, showTitle, renderTitle, layoutType, isActive, handleActions]);
45
+ useEffect(() => {
46
+ const element = elementRef.current;
47
+ if (!element)
48
+ return;
49
+ // Event listeners
50
+ const handleChooseFile = () => onChooseFile === null || onChooseFile === void 0 ? void 0 : onChooseFile();
51
+ const handleFileChange = (e) => onFileChange === null || onFileChange === void 0 ? void 0 : onFileChange(e.detail);
52
+ const handleElementClick = (e) => onElementClick === null || onElementClick === void 0 ? void 0 : onElementClick(e.detail);
53
+ const handleValidationChange = (e) => onValidationChange === null || onValidationChange === void 0 ? void 0 : onValidationChange(e.detail);
54
+ if (onChooseFile)
55
+ element.addEventListener('chooseFile', handleChooseFile);
56
+ if (onFileChange)
57
+ element.addEventListener('fileChange', handleFileChange);
58
+ if (onElementClick)
59
+ element.addEventListener('elementClick', handleElementClick);
60
+ if (onValidationChange)
61
+ element.addEventListener('validationChange', handleValidationChange);
62
+ return () => {
63
+ if (onChooseFile)
64
+ element.removeEventListener('chooseFile', handleChooseFile);
65
+ if (onFileChange)
66
+ element.removeEventListener('fileChange', handleFileChange);
67
+ if (onElementClick)
68
+ element.removeEventListener('elementClick', handleElementClick);
69
+ if (onValidationChange)
70
+ element.removeEventListener('validationChange', handleValidationChange);
71
+ };
72
+ }, [onChooseFile, onFileChange, onElementClick, onValidationChange]);
73
+ return _jsx("pep-signature-element", { ref: elementRef });
74
+ };
75
+ //# sourceMappingURL=pep-signature.js.map
@@ -0,0 +1,14 @@
1
+ export interface PepSmartFiltersProps {
2
+ title?: string;
3
+ filters?: any[];
4
+ fields?: any[];
5
+ useAsWebComponent?: boolean;
6
+ onFiltersChange?: (filters: any[]) => void;
7
+ onFieldToggleChange?: (field: any) => void;
8
+ }
9
+ export interface PepSmartFiltersRef {
10
+ clearFilters: () => void;
11
+ clearFilter: (fieldId: string) => void;
12
+ toggleField: (index: number, isOpen: boolean) => void;
13
+ }
14
+ export declare const PepSmartFilters: any;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useRef, useEffect } from 'react';
3
+ export const PepSmartFilters = React.forwardRef(({ title, filters, fields, useAsWebComponent = true, onFiltersChange, onFieldToggleChange, }, ref) => {
4
+ const elementRef = useRef(null);
5
+ // Expose methods via ref
6
+ React.useImperativeHandle(ref, () => ({
7
+ clearFilters: () => {
8
+ const element = elementRef.current;
9
+ if (element && typeof element.clearFilters === 'function') {
10
+ element.clearFilters();
11
+ }
12
+ else {
13
+ console.warn('clearFilters method not available on element', element);
14
+ }
15
+ },
16
+ clearFilter: (fieldId) => {
17
+ const element = elementRef.current;
18
+ if (element && typeof element.clearFilter === 'function') {
19
+ element.clearFilter(fieldId);
20
+ }
21
+ else {
22
+ console.warn('clearFilter method not available on element', element);
23
+ }
24
+ },
25
+ toggleField: (index, isOpen) => {
26
+ const element = elementRef.current;
27
+ if (element && typeof element.toggleField === 'function') {
28
+ element.toggleField(index, isOpen);
29
+ }
30
+ else {
31
+ console.warn('toggleField method not available on element', element);
32
+ }
33
+ },
34
+ }));
35
+ // Set initial properties only once on mount
36
+ useEffect(() => {
37
+ const element = elementRef.current;
38
+ if (!element)
39
+ return;
40
+ // Defer property setting to ensure Angular component initialization completes
41
+ setTimeout(() => {
42
+ if (title !== undefined)
43
+ element.title = title;
44
+ if (fields !== undefined)
45
+ element.fields = fields;
46
+ if (useAsWebComponent !== undefined)
47
+ element.useAsWebComponent = useAsWebComponent;
48
+ // Set initial filters only if provided
49
+ if (filters !== undefined && filters.length > 0) {
50
+ element.filters = filters;
51
+ }
52
+ }, 0);
53
+ }, []); // Empty deps - only run on mount
54
+ // Update title if it changes
55
+ useEffect(() => {
56
+ const element = elementRef.current;
57
+ if (element && title !== undefined) {
58
+ element.title = title;
59
+ }
60
+ }, [title]);
61
+ useEffect(() => {
62
+ const element = elementRef.current;
63
+ if (!element)
64
+ return;
65
+ // Event listeners
66
+ const handleFiltersChange = (event) => {
67
+ onFiltersChange === null || onFiltersChange === void 0 ? void 0 : onFiltersChange(event.detail);
68
+ };
69
+ const handleFieldToggleChange = (event) => {
70
+ onFieldToggleChange === null || onFieldToggleChange === void 0 ? void 0 : onFieldToggleChange(event.detail);
71
+ };
72
+ if (onFiltersChange)
73
+ element.addEventListener('filtersChange', handleFiltersChange);
74
+ if (onFieldToggleChange)
75
+ element.addEventListener('fieldToggleChange', handleFieldToggleChange);
76
+ return () => {
77
+ if (onFiltersChange)
78
+ element.removeEventListener('filtersChange', handleFiltersChange);
79
+ if (onFieldToggleChange)
80
+ element.removeEventListener('fieldToggleChange', handleFieldToggleChange);
81
+ };
82
+ }, [onFiltersChange, onFieldToggleChange]);
83
+ return _jsx("pep-smart-filters-element", { ref: elementRef });
84
+ });
85
+ PepSmartFilters.displayName = 'PepSmartFilters';
86
+ //# sourceMappingURL=pep-smart-filters.js.map
package/services.d.ts CHANGED
@@ -100,6 +100,16 @@ export interface PepDialogServiceBridge {
100
100
  openDefaultDialog(options: PepDialogDefaultOptions): any;
101
101
  openColorPicker?(options: any): any;
102
102
  }
103
+ export interface PepSnackBarData {
104
+ title?: string;
105
+ content?: string;
106
+ }
107
+ export interface PepSnackBarServiceBridge {
108
+ getSnackBarConfig?: (options?: {
109
+ duration?: number;
110
+ }) => unknown;
111
+ openDefaultSnackBar: (data: PepSnackBarData, config?: unknown) => unknown;
112
+ }
103
113
  export interface PepperiServicesBridge {
104
114
  http?: PepHttpServiceBridge;
105
115
  session?: PepSessionServiceBridge;
@@ -109,11 +119,13 @@ export interface PepperiServicesBridge {
109
119
  color?: PepColorServiceBridge;
110
120
  loader?: PepLoaderServiceBridge;
111
121
  dialog?: PepDialogServiceBridge;
122
+ snackBar?: PepSnackBarServiceBridge;
112
123
  }
113
124
  export declare function getPepHttpService(): PepHttpServiceBridge | undefined;
114
125
  export declare function getPepSessionService(): PepSessionServiceBridge | undefined;
115
126
  export declare function getPepTranslateService(): PepTranslateServiceBridge | undefined;
116
127
  export declare function getPepDialogService(): PepDialogServiceBridge | undefined;
128
+ export declare function getPepSnackBarService(): PepSnackBarServiceBridge | undefined;
117
129
  export declare function pepHttpGetViaService<T = any>(url: string, httpOptions?: any): Promise<T>;
118
130
  export declare function pepHttpPostViaService<T = any>(url: string, body: any | null, httpOptions?: any): Promise<T>;
119
131
  export declare function pepHttpGetWapi<T = any>(relativeUrl: string, httpOptions?: any): Promise<T>;
@@ -153,6 +165,9 @@ export declare function pepFindClosestAccessibleColor(adjustableColor: string, o
153
165
  export declare function pepLightOrDark(color: any): 'light' | 'dark';
154
166
  export declare function pepLoaderShow(): void;
155
167
  export declare function pepLoaderHide(): void;
168
+ export declare function pepOpenDefaultSnackBar(data: PepSnackBarData, options?: {
169
+ duration?: number;
170
+ }): unknown;
156
171
  export declare function pepOpenDefaultDialog<T = any>(options: PepDialogDefaultOptions): Promise<T | undefined>;
157
172
  export declare function pepOpenColorPickerDialog<T = any>(options: any): Promise<T | undefined>;
158
173
  export interface OpenReactPepDialogOptions<T = any> {
package/services.js CHANGED
@@ -93,6 +93,14 @@ export function getPepDialogService() {
93
93
  return undefined;
94
94
  }
95
95
  }
96
+ export function getPepSnackBarService() {
97
+ try {
98
+ return getPepperiServicesOrThrow().snackBar;
99
+ }
100
+ catch {
101
+ return undefined;
102
+ }
103
+ }
96
104
  function requirePepHttpService() {
97
105
  const http = getPepHttpService();
98
106
  if (!http) {
@@ -149,6 +157,13 @@ function requirePepDialogService() {
149
157
  }
150
158
  return dialog;
151
159
  }
160
+ function requirePepSnackBarService() {
161
+ const snackBar = getPepSnackBarService();
162
+ if (!snackBar) {
163
+ throw new Error('PepSnackBarService is not available on window.pepperi.services.snackBar. Ensure Elements bundle is loaded and services bridge is initialized.');
164
+ }
165
+ return snackBar;
166
+ }
152
167
  // -----------------------------------------------------------------------------
153
168
  // Internal: convert RxJS-like Observable to Promise without importing rxjs
154
169
  // -----------------------------------------------------------------------------
@@ -158,8 +173,7 @@ function observableToPromise(observable) {
158
173
  reject(new Error('Pepperi HTTP service did not return a subscribable object.'));
159
174
  return;
160
175
  }
161
- let subscription;
162
- subscription = observable.subscribe((value) => {
176
+ const subscription = observable.subscribe((value) => {
163
177
  try {
164
178
  resolve(value);
165
179
  }
@@ -330,6 +344,12 @@ export function pepLoaderShow() {
330
344
  export function pepLoaderHide() {
331
345
  requirePepLoaderService().hide();
332
346
  }
347
+ export function pepOpenDefaultSnackBar(data, options) {
348
+ var _a;
349
+ const snackBar = requirePepSnackBarService();
350
+ const config = (_a = snackBar.getSnackBarConfig) === null || _a === void 0 ? void 0 : _a.call(snackBar, options);
351
+ return snackBar.openDefaultSnackBar(data, config);
352
+ }
333
353
  // -----------------------------------------------------------------------------
334
354
  // Convenience helpers for PepDialogService (dialogs)
335
355
  // -----------------------------------------------------------------------------