# Using PEP-NgxLib Utilities in React

## ⚠️ IMPORTANT: No Angular Service Classes Are Exported

`@pepperi-addons/ngx-lib-react` does **not** export Angular service classes such
as `PepHttpService`, `PepSessionService`, or `PepCustomizationService`.

For a high-level summary of all exported helpers, bridge functions, and build
artifacts, see
[`docs/services-export-summary.md`](../../docs/services-export-summary.md).

Directly exporting those services would pull Angular and its DI runtime into
your React bundle, causing:

- Massive bundle size increase
- Build errors / version conflicts
- Runtime errors in React-only environments

Instead, the React package exposes:

1. **Standalone HTTP helpers** with no Angular dependency.
2. **Bridge-based helpers** that call selected Angular services via the
   Elements bundle at runtime (through `window.pepperi.services`).

## ✅ Alternatives for React

Instead of Angular services, use these React-friendly alternatives:

### For UUID Generation
```typescript
// Use crypto.randomUUID() (modern browsers)
const uuid = crypto.randomUUID();

// Or use a library like 'uuid'
import { v4 as uuidv4 } from 'uuid';
const uuid = uuidv4();
```

### For Email/URL Validation
```typescript
// Use native JavaScript
const isValidEmail = (email: string) => {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};

const isValidUrl = (url: string) => {
    try {
        new URL(url);
        return true;
    } catch {
        return false;
    }
};

// Or use a library like 'validator'
import validator from 'validator';
const isValid = validator.isEmail('test@example.com');
```

### For Cookie Management
```typescript
// Use js-cookie library
import Cookies from 'js-cookie';

Cookies.set('myCookie', 'value', { expires: 7 });
const value = Cookies.get('myCookie');
Cookies.remove('myCookie');
```

### For Color Utilities
```typescript
// Use a library like 'color' or 'tinycolor2'
import Color from 'color';

const rgb = Color('#FF5733').rgb().object();
const contrast = Color('#FF5733').isDark() ? '#FFFFFF' : '#000000';
```

## Summary

**No Angular service classes are exported from this package.** Use:

1. **HTTP helper functions** for API calls (`pepHttpGet`, `pepHttpPost`, etc.).
2. **Bridge-based helpers** to access `PepHttpService`, `PepSessionService`,
   and `PepCustomizationService` via the Elements bundle.
3. **Custom element components** for UI (`PepDialog`, `PepSnackBar`, etc.).
4. **Standard JavaScript libraries** for utilities (uuid, validator,
   js-cookie, color, etc.).

## Bridge-Based Service Helpers (via Elements bundle)

In addition to the standalone HTTP helpers, the React package exposes
**bridge-based helpers** that call selected Angular services at runtime via the
Angular Elements bundle. This lets you reuse existing Pepperi logic without
importing Angular into the React build.

> These helpers require that the Elements bundle is loaded and
> `NgxLibElementsModule` has run, so that `window.pepperi.services` is
> populated (see README for how to load the Elements scripts).

### PepHttpService helpers

```ts
import {
    pepHttpGetViaService,
    pepHttpPostViaService,
    pepHttpGetWapi,
    pepHttpPostWapi,
    pepHttpGetPapi,
    pepHttpPostPapi,
} from '@pepperi-addons/ngx-lib-react';

// PAPI example
const accounts = await pepHttpGetPapi<any[]>('/accounts');

// WAPI example
const created = await pepHttpPostWapi('/transactions', { Amount: 10 });
```

### PepSessionService helpers

```ts
import {
    pepGetIdpToken,
    pepGetWapiBaseUrl,
    pepGetPapiBaseUrl,
    pepSessionGetObject,
    pepSessionSetObject,
    pepSessionRemoveObject,
} from '@pepperi-addons/ngx-lib-react';

const token = pepGetIdpToken();
const wapiBaseUrl = pepGetWapiBaseUrl();
const papiBaseUrl = pepGetPapiBaseUrl();

pepSessionSetObject('myKey', { foo: 'bar' });
const value = pepSessionGetObject<{ foo: string }>('myKey');
pepSessionRemoveObject('myKey');
```

### PepCustomizationService helpers (theme & layout)

```ts
import {
    pepGetBrandingTheme,
    pepGetThemeVariables,
    pepSetThemeVariables,
    pepGetThemeVariable,
    pepGetTopBarHeight,
    pepHideFooter,
    pepShowFooter,
} from '@pepperi-addons/ngx-lib-react';

const theme = pepGetBrandingTheme();
const vars = pepGetThemeVariables();

pepSetThemeVariables({
    '--pep-color-user-primary': '#83b30c',
    '--pep-color-user-secondary': '#6c757d',
});

const topBarHeight = pepGetTopBarHeight();
pepHideFooter();
pepShowFooter();
```

Use these helpers when you want behavior identical to the Angular app (e.g.
PAPI/WAPI base URL resolution, theme persistence) but from React.

### PepTranslateService helpers (i18n)

```ts
import {
    pepTranslateInstant,
    pepTranslateGet,
    pepTranslateUse,
    pepTranslateGetDefaultLang,
    pepTranslateGetCurrentLang,
} from '@pepperi-addons/ngx-lib-react';

// Synchronous lookup (for already-loaded keys)
const label = pepTranslateInstant('Buttons.Save');

// Ensure a specific language is active (returns a Promise that resolves when loaded)
await pepTranslateUse('en');

// Async lookup (waits for translations to load)
const texts = await pepTranslateGet<{ [key: string]: string }>([
    'Buttons.Save',
    'Buttons.Cancel',
]);

const currentLang = pepTranslateGetCurrentLang();
const defaultLang = pepTranslateGetDefaultLang();
```

These helpers are thin wrappers over `window.pepperi.services.translate` which is
initialized by the Elements bundle (`NgxLibElementsModule`). Make sure the
Elements scripts are loaded before calling them.

### PepAddonService helpers (addons & CPI)

```ts
import {
    pepAddonGetApi,
    pepAddonPostApi,
    pepAddonGetCpi,
    pepAddonPostCpi,
    pepAddonGetServerBaseUrl,
    pepAddonGetStaticFolder,
    pepAddonSetStaticFolder,
} from '@pepperi-addons/ngx-lib-react';

// Classic addon API (sync or async)
const result = await pepAddonGetApi<any>(
    '00000000-0000-0000-0000-000000000000',
    'api',
    'my_function'
);

// CPI call example
const cpiResult = await pepAddonGetCpi<any>(
    '00000000-0000-0000-0000-000000000000',
    '/my/relative/url'
);

// Static folder helpers
const baseUrl = pepAddonGetServerBaseUrl('00000000-0000-0000-0000-000000000000');
const staticFolder = pepAddonGetStaticFolder('00000000-0000-0000-0000-000000000000');
pepAddonSetStaticFolder('/my/addon/', '00000000-0000-0000-0000-000000000000');
```

These map directly to `PepAddonService` and rely on `window.pepperi.services.addon`.

### PepColorService helpers (color utilities)

```ts
import {
    pepFindClosestAccessibleColor,
    pepLightOrDark,
} from '@pepperi-addons/ngx-lib-react';

const adjusted = pepFindClosestAccessibleColor('#ffffff', '#000000', 4.5);
const tone = pepLightOrDark('#83b30c'); // 'light' | 'dark'
```

These wrap `window.pepperi.services.color` (PepColorService) to reuse Pepperi’s
accessibility-oriented color logic.

### PepLoaderService helpers (global loader)

```ts
import { pepLoaderShow, pepLoaderHide } from '@pepperi-addons/ngx-lib-react';

async function doSomething() {
    try {
        pepLoaderShow();
        // ... async work ...
    } finally {
        pepLoaderHide();
    }
}
```

These call `window.pepperi.services.loader.show()` / `.hide()`, which in turn
drive the global Pepperi loader via `PepLoaderService`.

### PepDialogService helpers (default dialogs)

```ts
import {
    pepOpenDefaultDialog,
    pepOpenColorPickerDialog,
    PepDialogActionsType,
    PepDialogSizeType,
} from '@pepperi-addons/ngx-lib-react';

// Default dialog example
await pepOpenDefaultDialog<void>({
    title: 'Confirm Action',
    content: 'Opened from React via pepOpenDefaultDialog helper',
    actionsType: 'cancel-continue' as PepDialogActionsType,
    showClose: true,
    showHeader: true,
    showFooter: true,

    // Optional dialog config forwarded to PepDialogService.getDialogConfig
    size: 'small' as PepDialogSizeType, // 'inline' | 'small' | 'regular' | 'large' | 'full-screen'
    disableClose: false,
    hasBackdrop: true,
    minWidth: '320px',
    maxWidth: '600px',
    maxHeight: '80vh',
    panelClass: 'my-custom-dialog-class',
});

// Color picker dialog example
const colorResult = await pepOpenColorPickerDialog<any>({
    value: '#ff0000',
    type: 'regular',
    showAAComplient: true,
    checkAAComplient: true,
});
```

`pepOpenDefaultDialog` and `pepOpenColorPickerDialog` are thin Promise-based
wrappers over `window.pepperi.services.dialog`. They rely on the same
`PepDialogService` implementation used by Angular apps, so all Pepperi dialog
styling and behavior (including size classes from `PepDialogSizeType`) apply.

### React-only JSX dialog helper (openReactPepDialog)

In addition to the service-based dialogs, the React package exposes a
**React-only helper** for opening a Pepperi dialog shell with custom JSX
content.

```ts
import { openReactPepDialog, PepDialogSizeType } from '@pepperi-addons/ngx-lib-react';

const result = await openReactPepDialog<boolean>({
    title: 'React JSX Dialog',
    size: 'small' as PepDialogSizeType, // optional: controls the size CSS class
    renderContent: (close) => (
        <>
            {/* 1) First top-level wrapper = dialog body (mat-dialog-content) */}
            <div pep-dialog-content>
                <p>This dialog body is pure React JSX.</p>
                <p>It still uses the Pepperi dialog shell.</p>
            </div>

            {/* 2) Second top-level wrapper = dialog actions (mat-dialog-actions) */}
            <div
                pep-dialog-actions
                className="pep-spacing-element-negative"
                style={{ display: 'flex', justifyContent: 'flex-end' }}
            >
                <button
                    className="pep-spacing-element mat-button pep-button md weak"
                    onClick={() => close(false)}
                >
                    Cancel
                </button>
                <button
                    className="pep-spacing-element mat-button pep-button md strong"
                    onClick={() => close(true)}
                >
                    OK
                </button>
            </div>
        </>
    ),
});
```

Notes:

- `openReactPepDialog` is **pure React** – it does not call `PepDialogService`.
- It renders a `PepDialog` web component inside a Pepperi-styled overlay using
  the same DOM structure and CSS classes as the Angular dialogs.
- The `size` option is optional; when provided, it adds the corresponding size
  class (e.g. `small`, `regular`, `large`) to the dialog container.
- Starting from `@pepperi-addons/ngx-lib-react@0.5.7`, `PepDialog` uses
  **React portals** to inject JSX into the internal Angular
  `mat-dialog-content` / `mat-dialog-actions` containers.
- For correct placement:
  - `renderContent` should return **exactly two logical top-level children**
    (usually wrapped in a fragment `<>...</>`).
  - The **first** child is treated as the **content wrapper** and rendered into
    `mat-dialog-content`.
  - The **second** child is treated as the **actions wrapper** and rendered into
    `mat-dialog-actions`.
  - Inside these wrappers you can use either plain HTML elements or Pepperi
    React components (`PepSelect`, `PepButton`, etc.).

Example mirroring a permissions dialog (body with two selects + footer button):

```tsx
import { openReactPepDialog, PepSelect, PepButton } from '@pepperi-addons/ngx-lib-react';

async function openPermissionsDialogDemo() {
    await openReactPepDialog<void>({
        title: 'Add Permission',
        size: 'regular',
        renderContent: () => (
            <>
                <div pep-dialog-content className="permissions-dialog-content">
                    <PepSelect
                        keyProp="addon"
                        label="Select an Addon"
                        options={addonOptions}
                        value={selectedAddonKey}
                        emptyOption={false}
                        onValueChange={setSelectedAddonKey}
                    />

                    <PepSelect
                        keyProp="editor"
                        label="Select an Editor"
                        options={editorOptions}
                        value={selectedEditorKey}
                        emptyOption={false}
                        disabled={!selectedAddonKey}
                        onValueChange={setSelectedEditorKey}
                    />
                </div>

                <div pep-dialog-actions className="permissions-dialog-actions">
                    <PepButton
                        value="Confirm"
                        styleType="strong"
                        disabled={!selectedAddonKey || !selectedEditorKey}
                        onButtonClick={handleConfirmClick}
                    />
                </div>
            </>
        ),
    });
}
```

## Support

For issues or questions about specific services, please refer to the main PEP-NgxLib documentation or contact the Pepperi development team.
