@rdlabo/ionic-angular-kit 0.0.14 → 0.0.16

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/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@rdlabo/ionic-angular-kit",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.0.0",
6
6
  "@angular/core": "^21.0.0",
7
7
  "@angular/router": "^21.0.0",
8
8
  "@ionic/angular": "^8.0.0",
9
9
  "@ionic/storage-angular": "^4.0.0",
10
+ "@angular/fire": ">=21.0.0-rc.0",
11
+ "firebase": "^11.0.0",
10
12
  "@capacitor/core": ">=6.0.0 <9.0.0",
11
13
  "@capacitor/haptics": ">=6.0.0 <9.0.0",
12
14
  "@capacitor/keyboard": ">=6.0.0 <9.0.0",
@@ -14,11 +16,19 @@
14
16
  "@capacitor/preferences": ">=6.0.0 <9.0.0",
15
17
  "@capacitor/status-bar": ">=6.0.0 <9.0.0",
16
18
  "@capacitor-community/in-app-review": ">=6.0.0 <9.0.0",
19
+ "@capacitor-community/facebook-login": ">=8.0.0 <9.0.0",
20
+ "@capacitor-community/apple-sign-in": "*",
17
21
  "@rdlabo/capacitor-brotherprint": ">=6.0.0 <9.0.0",
18
22
  "dom-to-image-more": "^3.0.0",
19
23
  "rxjs": "^7.8.0"
20
24
  },
21
25
  "peerDependenciesMeta": {
26
+ "@angular/fire": {
27
+ "optional": true
28
+ },
29
+ "firebase": {
30
+ "optional": true
31
+ },
22
32
  "@capacitor/preferences": {
23
33
  "optional": true
24
34
  },
@@ -28,6 +38,12 @@
28
38
  "@capacitor-community/in-app-review": {
29
39
  "optional": true
30
40
  },
41
+ "@capacitor-community/facebook-login": {
42
+ "optional": true
43
+ },
44
+ "@capacitor-community/apple-sign-in": {
45
+ "optional": true
46
+ },
31
47
  "@rdlabo/capacitor-brotherprint": {
32
48
  "optional": true
33
49
  },
@@ -48,6 +64,26 @@
48
64
  ".": {
49
65
  "types": "./types/rdlabo-ionic-angular-kit.d.ts",
50
66
  "default": "./fesm2022/rdlabo-ionic-angular-kit.mjs"
67
+ },
68
+ "./auth-firebase": {
69
+ "types": "./types/rdlabo-ionic-angular-kit-auth-firebase.d.ts",
70
+ "default": "./fesm2022/rdlabo-ionic-angular-kit-auth-firebase.mjs"
71
+ },
72
+ "./auth-firebase/social": {
73
+ "types": "./types/rdlabo-ionic-angular-kit-auth-firebase-social.d.ts",
74
+ "default": "./fesm2022/rdlabo-ionic-angular-kit-auth-firebase-social.mjs"
75
+ },
76
+ "./printer": {
77
+ "types": "./types/rdlabo-ionic-angular-kit-printer.d.ts",
78
+ "default": "./fesm2022/rdlabo-ionic-angular-kit-printer.mjs"
79
+ },
80
+ "./review": {
81
+ "types": "./types/rdlabo-ionic-angular-kit-review.d.ts",
82
+ "default": "./fesm2022/rdlabo-ionic-angular-kit-review.mjs"
83
+ },
84
+ "./theme": {
85
+ "types": "./types/rdlabo-ionic-angular-kit-theme.d.ts",
86
+ "default": "./fesm2022/rdlabo-ionic-angular-kit-theme.mjs"
51
87
  }
52
88
  },
53
89
  "type": "module"
@@ -0,0 +1,104 @@
1
+ import { Auth } from 'firebase/auth';
2
+
3
+ /** How a social-credential failure is classified for the app's error hook. */
4
+ type KitOAuthErrorCategory = 'already-in-use' | 'cancelled' | 'other';
5
+ /** The mode a social login runs in. */
6
+ type KitOAuthModeName = 'new' | 'link' | 'credential';
7
+ /**
8
+ * The mode discriminator. `'credential'` links an email/password to the (re-authenticated) social
9
+ * account, so it requires the new email/password; `'new'` / `'link'` do not.
10
+ */
11
+ type KitOAuthMode = {
12
+ mode: 'new';
13
+ } | {
14
+ mode: 'link';
15
+ } | {
16
+ mode: 'credential';
17
+ emailLogin: {
18
+ email: string;
19
+ password: string;
20
+ };
21
+ };
22
+ /**
23
+ * The apple identity payload handed to the `success` hook for the backend call. Populated from the
24
+ * native plugin on device, or synthesized from the popup result on the web.
25
+ */
26
+ interface KitAppleResponse {
27
+ user: string | null;
28
+ email: string | null;
29
+ givenName: string | null;
30
+ familyName: string | null;
31
+ identityToken: string | null;
32
+ authorizationCode: string | null;
33
+ }
34
+ /**
35
+ * The uniform lifecycle hooks for a social flow — the same `before / success / error / finally`
36
+ * shape as {@link KitFirebaseAuthService}'s hooks, so a call site reads the same everywhere. All are
37
+ * optional; the kit renders nothing itself.
38
+ *
39
+ * @typeParam Info - the identity payload handed to {@link success} (Facebook access token / Apple
40
+ * response), so an app can notify its backend and give feedback in one place.
41
+ *
42
+ * @remarks
43
+ * `before` runs before the plugin login starts, `success` after the mode's Firebase op succeeds
44
+ * (carrying the identity payload — do the backend call and the toast here), `error` on a classified
45
+ * failure (`'cancelled'` is passed through so the app can stay silent on a user cancel), and
46
+ * `finally` always. The kit swallows none of these errors.
47
+ */
48
+ interface KitSocialHooks<Info> {
49
+ before?: () => void | Promise<unknown>;
50
+ success?: (info: Info) => void | Promise<unknown>;
51
+ error?: (category: KitOAuthErrorCategory, error: unknown) => void | Promise<unknown>;
52
+ finally?: () => void | Promise<unknown>;
53
+ }
54
+ /** Options for {@link kitFacebookLogin}. */
55
+ type KitFacebookLoginOptions = KitOAuthMode & KitSocialHooks<{
56
+ accessToken: string;
57
+ mode: KitOAuthModeName;
58
+ }> & {
59
+ /** Facebook permissions to request. */
60
+ permissions: string[];
61
+ };
62
+ /** Options for {@link kitAppleLogin}. */
63
+ type KitAppleLoginOptions = KitOAuthMode & KitSocialHooks<{
64
+ response: KitAppleResponse;
65
+ mode: KitOAuthModeName;
66
+ }>;
67
+ /**
68
+ * Facebook login / link, bundled: native plugin → credential → the shared 3-mode state machine.
69
+ *
70
+ * @remarks
71
+ * On iOS the credential is built from the OIDC token with a nonce (`OAuthProvider('facebook.com')`);
72
+ * elsewhere from the access token (`FacebookAuthProvider`). Returns `{ status: false }` on a
73
+ * cancelled/failed plugin login or a handled Firebase error (the app was already notified via the
74
+ * hooks).
75
+ */
76
+ declare const kitFacebookLogin: (auth: Auth, options: KitFacebookLoginOptions) => Promise<{
77
+ status: boolean;
78
+ }>;
79
+ /**
80
+ * Log out of the Facebook SDK (best-effort; errors are ignored).
81
+ *
82
+ * @remarks
83
+ * Apps that offer Facebook login typically call this alongside the Firebase sign-out, so it lives
84
+ * here to keep the `@capacitor-community/facebook-login` import out of the app.
85
+ */
86
+ declare const kitFacebookLogout: () => Promise<void>;
87
+ /**
88
+ * Sign in with Apple / link, bundled. Native uses the plugin; the web uses the Firebase popup.
89
+ *
90
+ * @remarks
91
+ * - **Native**: `SignInWithApple.authorize()` → `OAuthProvider('apple.com')` credential → the shared
92
+ * 3-mode state machine.
93
+ * - **Web**: `signInWithPopup` / `linkWithPopup` (with `email`/`name` scopes), or, for `credential`,
94
+ * `reauthenticateWithPopup` then link the email/password. The identity payload for the backend is
95
+ * synthesized from the popup result.
96
+ *
97
+ * Every failure path (including popup errors) is routed through `onError`.
98
+ */
99
+ declare const kitAppleLogin: (auth: Auth, options: KitAppleLoginOptions) => Promise<{
100
+ status: boolean;
101
+ }>;
102
+
103
+ export { kitAppleLogin, kitFacebookLogin, kitFacebookLogout };
104
+ export type { KitAppleLoginOptions, KitAppleResponse, KitFacebookLoginOptions, KitOAuthErrorCategory, KitOAuthMode, KitOAuthModeName };
@@ -0,0 +1,266 @@
1
+ import { InjectionToken, EnvironmentProviders } from '@angular/core';
2
+ import { FirebaseOptions } from '@angular/fire/app';
3
+ import { Auth, User, UserCredential } from 'firebase/auth';
4
+ import { Observable } from 'rxjs';
5
+
6
+ /**
7
+ * DI token for the Firebase `Auth` instance.
8
+ *
9
+ * @remarks
10
+ * Inject this (`inject(KIT_FIREBASE_AUTH)`) instead of `@angular/fire`'s `Auth`, so the
11
+ * `@angular/fire` dependency stays isolated inside the kit. This is the seam that makes the planned
12
+ * `@angular/fire` → `firebase/auth` migration a kit-internal change: only {@link provideKitFirebase}
13
+ * (which binds this token) has to change; every consumer keeps injecting `KIT_FIREBASE_AUTH`.
14
+ *
15
+ * The value is a `firebase/auth` `Auth` (the SDK type is exposed directly, not re-abstracted —
16
+ * Firebase Auth itself is not being dropped, only the `@angular/fire` wrapper).
17
+ */
18
+ declare const KIT_FIREBASE_AUTH: InjectionToken<Auth>;
19
+ /** Configuration for {@link provideKitFirebase}. */
20
+ interface KitFirebaseConfig {
21
+ /** The Firebase project options (`apiKey`, `authDomain`, `projectId`, …). */
22
+ readonly firebaseConfig: FirebaseOptions;
23
+ }
24
+ /**
25
+ * Wire Firebase App + Auth into the application and bind {@link KIT_FIREBASE_AUTH}.
26
+ *
27
+ * @remarks
28
+ * Replaces each app's hand-rolled `provideFirebaseApp(...)` + `provideAuth(...)` (with its
29
+ * native/web persistence branch) with one call, and — crucially — keeps `@angular/fire` out of the
30
+ * application: apps inject {@link KIT_FIREBASE_AUTH} and import auth operations/types straight from
31
+ * `firebase/auth`. On a native platform the persistence uses `indexedDBLocalPersistence`; on the web
32
+ * it uses the default (`getAuth`).
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * bootstrapApplication(AppComponent, {
37
+ * providers: [provideKitFirebase({ firebaseConfig: environment.firebase })],
38
+ * });
39
+ * ```
40
+ */
41
+ declare const provideKitFirebase: (config: KitFirebaseConfig) => EnvironmentProviders;
42
+ /**
43
+ * Wire Firebase Analytics into the application (optional; only the apps that use it call this).
44
+ */
45
+ declare const provideKitFirebaseAnalytics: () => EnvironmentProviders;
46
+
47
+ /** A user-facing message (alert header + body). */
48
+ interface KitAuthMessage {
49
+ readonly header: string;
50
+ readonly message: string;
51
+ }
52
+ /**
53
+ * The fleet's canonical Firebase auth error dictionary: error `code` → message, plus a fallback for
54
+ * unmapped codes.
55
+ *
56
+ * @remarks
57
+ * The kit does *not* present errors itself (that's an app side effect). This is offered as an
58
+ * importable constant so an app can render its error alert from a shared, canonical source instead of
59
+ * re-declaring the same five messages. Apps that need `$localize` (i18n) keep their own dictionary;
60
+ * JA-only apps can import {@link KIT_DEFAULT_AUTH_TEXT} and spread it, overriding the odd code.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { KIT_DEFAULT_AUTH_TEXT } from '@rdlabo/ionic-angular-kit/auth-firebase';
65
+ *
66
+ * const AUTH_ERRORS = { ...KIT_DEFAULT_AUTH_TEXT.errors, 'auth/wrong-password': { header: '…', message: '…' } };
67
+ * presentError(code: string) {
68
+ * const msg = AUTH_ERRORS[code] ?? KIT_DEFAULT_AUTH_TEXT.fallbackError;
69
+ * return this.overlay.alertClose(msg);
70
+ * }
71
+ * ```
72
+ */
73
+ interface KitAuthText {
74
+ /** Firebase error `code` → message. */
75
+ readonly errors: Readonly<Record<string, KitAuthMessage>>;
76
+ /** Shown when an error has no matching `code`. */
77
+ readonly fallbackError: KitAuthMessage;
78
+ }
79
+ /** The fleet's canonical Japanese error dictionary (see {@link KitAuthText}). */
80
+ declare const KIT_DEFAULT_AUTH_TEXT: KitAuthText;
81
+
82
+ /**
83
+ * Uniform lifecycle hooks for the bundled email/password auth flows — where the app hangs its own
84
+ * side effects on a flow.
85
+ *
86
+ * @remarks
87
+ * The kit performs the Firebase operation and renders nothing itself. `before` runs before the op,
88
+ * `success` on success, `error` on failure (with the raw error — the app presents it, from its own
89
+ * dictionary), and `finally` always. Failures are *not* thrown: value flows resolve to `null` and
90
+ * boolean flows to `false`. Return values are awaited and ignored.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * kitSignIn(auth, email, password, {
95
+ * error: (e) => this.presentAuthError(e), // app's own error dictionary
96
+ * success: () => this.nav.navigateRoot('/'),
97
+ * });
98
+ * ```
99
+ */
100
+ interface KitAuthHooks {
101
+ before?: () => void | Promise<unknown>;
102
+ success?: () => void | Promise<unknown>;
103
+ error?: (error: unknown) => void | Promise<unknown>;
104
+ finally?: () => void | Promise<unknown>;
105
+ }
106
+ /**
107
+ * Sign in with email and password.
108
+ *
109
+ * @remarks
110
+ * Bundles the Firebase op so the app never imports `signInWithEmailAndPassword` directly (the SDK
111
+ * stays isolated in the kit). Resolves the credential, or `null` on failure (handed to the `error`
112
+ * hook).
113
+ */
114
+ declare const kitSignIn: (auth: Auth, email: string, password: string, hooks?: KitAuthHooks) => Promise<UserCredential | null>;
115
+ /**
116
+ * Create an account and send the verification email.
117
+ *
118
+ * @remarks
119
+ * Bundles the two-step "create → send verification" sequence. Resolves the credential, or `null` on
120
+ * failure. Any success toast is the caller's, via the `success` hook.
121
+ */
122
+ declare const kitSignUp: (auth: Auth, email: string, password: string, hooks?: KitAuthHooks) => Promise<UserCredential | null>;
123
+ /**
124
+ * Sign out.
125
+ *
126
+ * @remarks
127
+ * App-specific cleanup (clearing stores, toasts, navigation, third-party logout) is the caller's,
128
+ * done via the hooks — the kit only owns the Firebase op. `true` on success, `false` on failure.
129
+ */
130
+ declare const kitSignOut: (auth: Auth, hooks?: KitAuthHooks) => Promise<boolean>;
131
+ /** Send a password-reset email. `true` on success, `false` on failure. */
132
+ declare const kitSendPasswordReset: (auth: Auth, email: string, hooks?: KitAuthHooks) => Promise<boolean>;
133
+ /**
134
+ * Unlink a linked auth provider (e.g. `'facebook.com'`, `'apple.com'`) from the current user.
135
+ *
136
+ * @remarks
137
+ * Exposed from the core (not `/social`) so an app can unlink without importing `unlink` from
138
+ * `firebase/auth` directly — keeping the invariant that the SDK is only imported inside the kit. Any
139
+ * app-specific step around it (e.g. a backend DELETE before unlinking) goes in the `before` hook.
140
+ * Resolves the updated `User`, or `null` on failure (including when there is no signed-in user).
141
+ */
142
+ declare const kitUnlinkProvider: (auth: Auth, providerId: string, hooks?: KitAuthHooks) => Promise<User | null>;
143
+ /**
144
+ * (Re-)send the verification email to the signed-in user (a no-op when signed out).
145
+ *
146
+ * @remarks
147
+ * `true` on success (including the signed-out no-op), `false` on failure.
148
+ */
149
+ declare const kitSendEmailVerification: (auth: Auth, hooks?: KitAuthHooks) => Promise<boolean>;
150
+ /**
151
+ * The current Firebase user as an Observable (emits on every auth-state change; `null` when signed out).
152
+ *
153
+ * @remarks
154
+ * Wraps `onAuthStateChanged` so consumers get an rxjs stream without pulling in `@angular/fire`'s
155
+ * `authState` (or `rxfire`). Emits the current value on subscribe and completes its listener on
156
+ * teardown.
157
+ *
158
+ * @param auth - the Firebase `Auth` instance (inject `KIT_FIREBASE_AUTH`)
159
+ */
160
+ declare const kitAuthState: (auth: Auth) => Observable<User | null>;
161
+ /**
162
+ * The current user's ID token, or `null` when signed out.
163
+ *
164
+ * @remarks
165
+ * For building `Authorization` / bearer headers in interceptors and services. Failure to fetch a
166
+ * token is **thrown, not swallowed** — the caller decides the fallback (e.g. an empty header) as its
167
+ * own side effect, so the kit never silently hides an auth failure.
168
+ *
169
+ * @param auth - the Firebase `Auth` instance (inject `KIT_FIREBASE_AUTH`)
170
+ * @param forceRefresh - force a token refresh (default `false`)
171
+ * @returns the ID token, or `null` if there is no signed-in user
172
+ * @throws if the token fetch fails for a signed-in user
173
+ */
174
+ declare const kitGetIdToken: (auth: Auth, forceRefresh?: boolean) => Promise<string | null>;
175
+ /**
176
+ * The app-supplied side effects for {@link kitReauthWithRetry}.
177
+ *
178
+ * @remarks
179
+ * The kit owns the *control flow* but generates no UI; every user-facing effect (the prompt, the
180
+ * loading overlay) is a callback the app implements, rendering from its own dictionary.
181
+ */
182
+ interface KitReauthWithRetryOptions {
183
+ /**
184
+ * Present the current-password prompt.
185
+ *
186
+ * @remarks
187
+ * A side effect — the app presents whatever it likes (e.g. an `ion-alert` with a masked input and
188
+ * dictionary text). Receives `true` when re-prompting after a wrong password.
189
+ *
190
+ * @returns the entered password, or `null` if the user cancels/dismisses
191
+ */
192
+ prompt: (wrongPasswordRetry: boolean) => Promise<string | null>;
193
+ /**
194
+ * The sensitive change to run once re-authenticated.
195
+ *
196
+ * @remarks
197
+ * Keep this pure — just the Firebase op(s) (e.g. `updatePassword(user, next)`). Loading and other
198
+ * UI are side effects handled by {@link withLoading}, not here.
199
+ */
200
+ mutate: (user: User) => Promise<void>;
201
+ /**
202
+ * Wrap the re-authentication + mutation with a loading indicator (a side effect).
203
+ *
204
+ * @remarks
205
+ * Optional. Runs only after a password is entered, around each attempt — so no loading flashes on a
206
+ * cancelled prompt, and it re-shows on a wrong-password retry. The app implements it (e.g.
207
+ * present/dismiss an `ion-loading`).
208
+ */
209
+ withLoading?: (run: () => Promise<void>) => Promise<void>;
210
+ }
211
+ /**
212
+ * Run the fleet's canonical "confirm current password → change" flow, re-prompting in place on a
213
+ * wrong password.
214
+ *
215
+ * @remarks
216
+ * Owns the drift-prone *control flow* (the retry loop, the wrong-password classification every app
217
+ * once got wrong, and when to show loading) while generating **no UI** — the prompt and the loading
218
+ * overlay are {@link KitReauthWithRetryOptions | side-effect callbacks} the app supplies. On a wrong
219
+ * password the loop re-prompts instead of dropping the user out of the flow. Any non-wrong-password
220
+ * re-auth failure (lockout, offline, expired session) and any error from `mutate` are re-thrown —
221
+ * re-auth failures unwrapped to the underlying Firebase error so the caller's error dictionary can
222
+ * read its `code`.
223
+ *
224
+ * @param auth - the Firebase `Auth` instance
225
+ * @param currentEmail - the current email (for the re-auth credential)
226
+ * @param options - the pure mutation plus the app's prompt / loading side effects
227
+ * @returns `true` if the mutation completed, `false` if the user cancelled
228
+ * @throws the underlying Firebase error on a non-wrong-password failure, or `mutate`'s own error
229
+ */
230
+ declare const kitReauthWithRetry: (auth: Auth, currentEmail: string, options: KitReauthWithRetryOptions) => Promise<boolean>;
231
+ /** The fleet's 3-state auth status derived from the Firebase user. */
232
+ type KitAuthStatus = 'user' | 'confirm' | 'required';
233
+ /** Options for {@link kitResolveAuthStatus}. */
234
+ interface KitResolveAuthStatusOptions {
235
+ /**
236
+ * Provider IDs that count as verified even without `emailVerified` — a social login (e.g.
237
+ * `'facebook.com'`, `'apple.com'`) has no email-verification step but is a real, trusted account.
238
+ */
239
+ readonly verifiedProviders?: readonly string[];
240
+ /**
241
+ * Extra predicate to treat a signed-in user as fully authed regardless of verification — for an
242
+ * e2e bypass or an anonymous-allowed app. Receives the current user.
243
+ */
244
+ readonly allowWhen?: (user: User) => boolean;
245
+ }
246
+ /**
247
+ * Classify a Firebase user into the fleet's 3-state auth status.
248
+ *
249
+ * @remarks
250
+ * `null` (signed out) → `'required'`. A signed-in user is `'user'` when their email is verified, OR
251
+ * they signed in with one of `verifiedProviders`, OR `allowWhen` returns true; otherwise `'confirm'`
252
+ * (signed in but unverified). This is only the shared classification — app-specific side effects
253
+ * around it (reloading the user to refresh `emailVerified`, caching a token) stay in the app.
254
+ *
255
+ * @example
256
+ * ```ts
257
+ * kitResolveAuthStatus(user, {
258
+ * verifiedProviders: ['facebook.com', 'apple.com'],
259
+ * allowWhen: () => environment.e2e,
260
+ * });
261
+ * ```
262
+ */
263
+ declare const kitResolveAuthStatus: (user: User | null, options?: KitResolveAuthStatusOptions) => KitAuthStatus;
264
+
265
+ export { KIT_DEFAULT_AUTH_TEXT, KIT_FIREBASE_AUTH, kitAuthState, kitGetIdToken, kitReauthWithRetry, kitResolveAuthStatus, kitSendEmailVerification, kitSendPasswordReset, kitSignIn, kitSignOut, kitSignUp, kitUnlinkProvider, provideKitFirebase, provideKitFirebaseAnalytics };
266
+ export type { KitAuthHooks, KitAuthMessage, KitAuthStatus, KitAuthText, KitFirebaseConfig, KitReauthWithRetryOptions, KitResolveAuthStatusOptions };
@@ -0,0 +1,81 @@
1
+ import { BRLMPrinterModelName, BRLMPrinterLabelName, BRLMPrintOptions } from '@rdlabo/capacitor-brotherprint';
2
+
3
+ /**
4
+ * Rotate a base64 image 90°, returning a new base64 data URL of the same MIME type.
5
+ *
6
+ * @remarks
7
+ * Pure DOM/canvas work — no DI. Used before sending a label to the printer when the artwork must be
8
+ * turned to match the tape orientation. Extracted verbatim from the fleet's printer services so the
9
+ * canvas handling lives in one place.
10
+ *
11
+ * @param imageData - a base64 data URL (e.g. `data:image/png;base64,...`)
12
+ * @returns a Promise resolving to the rotated image as a base64 data URL
13
+ */
14
+ declare const kitRotationImage: (imageData: string) => Promise<string>;
15
+ /** Options for {@link kitDomToPng}. */
16
+ interface KitDomToPngOptions {
17
+ /** When `true`, the rendered PNG is rotated 90° via {@link kitRotationImage}. Defaults to `false`. */
18
+ readonly rotate?: boolean;
19
+ /** Rendering scale passed to `dom-to-image-more`. Defaults to `3` (the fleet's print resolution). */
20
+ readonly scale?: number;
21
+ }
22
+ /**
23
+ * Render a DOM element to a base64 PNG for label printing, with the fleet's device-specific fixes.
24
+ *
25
+ * @remarks
26
+ * Pure function — no DI (reads the platform from `Capacitor`, uses the global `document`), so the
27
+ * caller presents its own loading UI around it. Centralizes the hard-won device quirks: on iOS it
28
+ * pads width/height by 2px (otherwise the bottom is clipped), on Android it does not (the padding
29
+ * introduces a black line). Retries the `dom-to-image-more` render up to 10 times because the first
30
+ * pass can occasionally return empty. This is exactly the kind of plumbing where a future fix should
31
+ * land in every app at once.
32
+ *
33
+ * @param element - the element to rasterize (e.g. the label preview host)
34
+ * @param options - rendering options; see {@link KitDomToPngOptions}
35
+ * @returns a Promise resolving to the PNG as a base64 data URL (empty string if every attempt failed)
36
+ * @example
37
+ * ```ts
38
+ * const loading = await this.#loadingCtrl.create({ message: this.text.generating });
39
+ * await loading.present();
40
+ * const png = await kitDomToPng(this.preview().nativeElement, { rotate: true });
41
+ * await loading.dismiss();
42
+ * ```
43
+ */
44
+ declare const kitDomToPng: (element: HTMLElement, options?: KitDomToPngOptions) => Promise<string>;
45
+ /** Parameters for {@link kitBuildBrotherPrintSettings}. */
46
+ interface KitBrotherPrintSettingsParams {
47
+ /** The target printer model. */
48
+ readonly modelName: BRLMPrinterModelName;
49
+ /** The label artwork as a base64 data URL (the `data:...,` prefix is stripped internally). */
50
+ readonly printBase64: string;
51
+ /** The selected label/paper (its `W<width>H<height>` code drives the tape dimensions). */
52
+ readonly label: BRLMPrinterLabelName;
53
+ /** Number of copies to print. Passed by the caller (apps differ: some use the print option, some fix 1). */
54
+ readonly numberOfCopies: number;
55
+ /** Halftone threshold for the print. */
56
+ readonly halftoneThreshold: number;
57
+ }
58
+ /**
59
+ * Assemble the Brother `BRLMPrintOptions` for a die-cut label print, minus the transport fields.
60
+ *
61
+ * @remarks
62
+ * Pure function — no DI. Centralizes the fleet's canonical print settings (fit-page scale, centered,
63
+ * best quality, threshold halftone, 2mm/1mm margins, `gapLength` 2.0) and the tape sizing derived
64
+ * from the label's `W<width>H<height>` code. The caller merges the printer's `port` / `channelInfo`
65
+ * onto the result before calling `BrotherPrint.printImage()`, so channel selection and loading UI stay
66
+ * in the app.
67
+ *
68
+ * @param params - model, artwork, label, copies, and halftone threshold; see {@link KitBrotherPrintSettingsParams}
69
+ * @returns the `BRLMPrintOptions` ready to be spread with `{ port, channelInfo }`
70
+ * @example
71
+ * ```ts
72
+ * const settings = kitBuildBrotherPrintSettings({
73
+ * modelName, printBase64, label, numberOfCopies: printOptions.printNum, halftoneThreshold: printOptions.halftoneThreshold,
74
+ * });
75
+ * await BrotherPrint.printImage({ ...settings, port: channel.port, channelInfo: channel.channelInfo });
76
+ * ```
77
+ */
78
+ declare const kitBuildBrotherPrintSettings: (params: KitBrotherPrintSettingsParams) => BRLMPrintOptions;
79
+
80
+ export { kitBuildBrotherPrintSettings, kitDomToPng, kitRotationImage };
81
+ export type { KitBrotherPrintSettingsParams, KitDomToPngOptions };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Options for {@link kitRequestReview}.
3
+ */
4
+ interface KitRequestReviewOptions {
5
+ /**
6
+ * Key under which the timestamp of the last review request is stored (via `@capacitor/preferences`).
7
+ *
8
+ * @remarks
9
+ * Supplied by the caller so the kit ships no storage keys of its own; each app passes its own enum
10
+ * value.
11
+ */
12
+ readonly storageKey: string;
13
+ /**
14
+ * Minimum number of months between review prompts.
15
+ *
16
+ * @remarks
17
+ * A prompt is only shown when this much time has elapsed since the last one (or when there is no
18
+ * record yet), so the OS review dialog is never nagged repeatedly.
19
+ */
20
+ readonly throttleMonths: number;
21
+ }
22
+ /**
23
+ * Request the native in-app review dialog, throttled so the user is prompted at most once per window.
24
+ *
25
+ * @remarks
26
+ * A plain function — no DI needed (`@capacitor/preferences`, `@capacitor-community/in-app-review` and
27
+ * `Capacitor` are all static), so the caller invokes it directly and passes its own config rather
28
+ * than injecting a controller. A no-op on non-native platforms. When enough time has elapsed since
29
+ * the last prompt (per {@link KitRequestReviewOptions.throttleMonths}, tracked under
30
+ * {@link KitRequestReviewOptions.storageKey}), it briefly waits for the app to settle, calls
31
+ * `InAppReview.requestReview()`, and records the new timestamp. The wait/throttle/record sequence
32
+ * was previously copy-pasted verbatim across the fleet; centralizing it means a single place to tune
33
+ * the prompt cadence.
34
+ *
35
+ * @param options - the storage key and throttle window; see {@link KitRequestReviewOptions}
36
+ * @returns a Promise that resolves once the request has been made (or immediately if throttled / on web)
37
+ * @example
38
+ * ```ts
39
+ * await kitRequestReview({ storageKey: StorageEnum.lastRequestRate, throttleMonths: 3 });
40
+ * ```
41
+ */
42
+ declare const kitRequestReview: (options: KitRequestReviewOptions) => Promise<void>;
43
+
44
+ export { kitRequestReview };
45
+ export type { KitRequestReviewOptions };