capacitor-extended-dialog 0.0.11 → 0.0.13

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/README.md CHANGED
@@ -9,6 +9,13 @@ npm install capacitor-extended-dialog
9
9
  npx cap sync
10
10
  ```
11
11
 
12
+ ## Android sheet behavior
13
+
14
+ - In `mode: 'basic'`, native Android sheets open between 50% and 80% of screen height.
15
+ - Dragging up continuously increases available body space while keeping header content at the top and actions pinned to the bottom.
16
+ - If sheet content exceeds the 80% initial cap, the body area becomes internally scrollable.
17
+ - In `mode: 'fullscreen'`, the same top-content/bottom-actions layout is preserved with a scrollable body area for overflow.
18
+
12
19
  ## API
13
20
 
14
21
  <docgen-index>
@@ -241,6 +248,7 @@ Show a message sheet dialog with an optional header logo, title, and message.
241
248
  | ------------------------ | ------------------------------------------------- | -------------------------------------------------------- |
242
249
  | **`headerLogo`** | <code>string</code> | Header logo - supports base64 data URL or HTTP/HTTPS URL |
243
250
  | **`title`** | <code>string</code> | Sheet title |
251
+ | **`subtitle`** | <code>string</code> | Optional subtitle displayed between title and rows |
244
252
  | **`rows`** | <code>{}</code> | Description rows |
245
253
  | **`confirmButtonTitle`** | <code>string</code> | Confirm button title |
246
254
  | **`cancelButtonTitle`** | <code>string</code> | Cancel button title |
@@ -269,6 +277,7 @@ Show a message sheet dialog with an optional header logo, title, and message.
269
277
  | ------------------------ | ------------------------------------------------- | -------------------------------------------------------- |
270
278
  | **`headerLogo`** | <code>string</code> | Header logo - supports base64 data URL or HTTP/HTTPS URL |
271
279
  | **`title`** | <code>string</code> | Sheet title |
280
+ | **`subtitle`** | <code>string</code> | Optional subtitle displayed between title and message |
272
281
  | **`message`** | <code>string</code> | Message body displayed in the sheet |
273
282
  | **`confirmButtonTitle`** | <code>string</code> | Confirm button title |
274
283
  | **`cancelButtonTitle`** | <code>string</code> | Cancel button title |
@@ -171,7 +171,9 @@ public class DialogStyleOptions {
171
171
  options.messageFontSize = bundle.containsKey(KEY_MESSAGE_FONT_SIZE) ? bundle.getFloat(KEY_MESSAGE_FONT_SIZE) : null;
172
172
  options.buttonFontSize = bundle.containsKey(KEY_BUTTON_FONT_SIZE) ? bundle.getFloat(KEY_BUTTON_FONT_SIZE) : null;
173
173
  options.contentButtonSpacing = bundle.containsKey(KEY_CONTENT_BUTTON_SPACING) ? bundle.getFloat(KEY_CONTENT_BUTTON_SPACING) : null;
174
- options.headerLogoCornerRadius = bundle.containsKey(KEY_HEADER_LOGO_CORNER_RADIUS) ? bundle.getFloat(KEY_HEADER_LOGO_CORNER_RADIUS) : null;
174
+ options.headerLogoCornerRadius = bundle.containsKey(KEY_HEADER_LOGO_CORNER_RADIUS)
175
+ ? bundle.getFloat(KEY_HEADER_LOGO_CORNER_RADIUS)
176
+ : null;
175
177
  return options;
176
178
  }
177
179
  }
@@ -744,6 +744,7 @@ public class ExtendedDialog {
744
744
  public void showSheet(
745
745
  Activity activity,
746
746
  String title,
747
+ String subtitle,
747
748
  String headerLogo,
748
749
  JSONArray rows,
749
750
  String confirmButtonTitle,
@@ -760,6 +761,7 @@ public class ExtendedDialog {
760
761
  fragmentActivity.runOnUiThread(() -> {
761
762
  SheetBottomDialogFragment fragment = SheetBottomDialogFragment.newInstance(
762
763
  title,
764
+ subtitle,
763
765
  headerLogo,
764
766
  rows.toString(),
765
767
  confirmButtonTitle != null ? confirmButtonTitle : "Confirm",
@@ -775,6 +777,7 @@ public class ExtendedDialog {
775
777
  public void showMessageSheet(
776
778
  Activity activity,
777
779
  String title,
780
+ String subtitle,
778
781
  String message,
779
782
  String headerLogo,
780
783
  String confirmButtonTitle,
@@ -791,6 +794,7 @@ public class ExtendedDialog {
791
794
  fragmentActivity.runOnUiThread(() -> {
792
795
  SheetBottomDialogFragment fragment = SheetBottomDialogFragment.newMessageInstance(
793
796
  title,
797
+ subtitle,
794
798
  headerLogo,
795
799
  message,
796
800
  confirmButtonTitle != null ? confirmButtonTitle : "Confirm",
@@ -211,6 +211,7 @@ public class ExtendedDialogPlugin extends Plugin {
211
211
  @PluginMethod
212
212
  public void sheet(PluginCall call) {
213
213
  String title = call.getString("title");
214
+ String subtitle = call.getString("subtitle");
214
215
  String headerLogo = call.getString("headerLogo");
215
216
  JSArray rowsArray = call.getArray("rows");
216
217
  String confirmButtonTitle = call.getString("confirmButtonTitle");
@@ -235,6 +236,7 @@ public class ExtendedDialogPlugin extends Plugin {
235
236
  implementation.showSheet(
236
237
  getActivity(),
237
238
  title,
239
+ subtitle,
238
240
  headerLogo,
239
241
  rows,
240
242
  confirmButtonTitle,
@@ -255,6 +257,7 @@ public class ExtendedDialogPlugin extends Plugin {
255
257
  @PluginMethod
256
258
  public void messageSheet(PluginCall call) {
257
259
  String title = call.getString("title");
260
+ String subtitle = call.getString("subtitle");
258
261
  String message = call.getString("message");
259
262
  String headerLogo = call.getString("headerLogo");
260
263
  String confirmButtonTitle = call.getString("confirmButtonTitle");
@@ -276,6 +279,7 @@ public class ExtendedDialogPlugin extends Plugin {
276
279
  implementation.showMessageSheet(
277
280
  getActivity(),
278
281
  title,
282
+ subtitle,
279
283
  message,
280
284
  headerLogo,
281
285
  confirmButtonTitle,
@@ -21,6 +21,9 @@ import android.widget.ScrollView;
21
21
  import android.widget.TextView;
22
22
  import androidx.annotation.NonNull;
23
23
  import androidx.annotation.Nullable;
24
+ import androidx.core.graphics.Insets;
25
+ import androidx.core.view.ViewCompat;
26
+ import androidx.core.view.WindowInsetsCompat;
24
27
  import androidx.core.widget.TextViewCompat;
25
28
  import com.google.android.material.bottomsheet.BottomSheetBehavior;
26
29
  import com.google.android.material.bottomsheet.BottomSheetDialog;
@@ -46,18 +49,27 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
46
49
  private static final String ARG_CONFIRM_BUTTON = "confirmButton";
47
50
  private static final String ARG_CANCEL_BUTTON = "cancelButton";
48
51
  private static final String ARG_FULLSCREEN = "fullscreen";
52
+ private static final String ARG_SUBTITLE = "subtitle";
49
53
  private static final String ARG_IS_MESSAGE_SHEET = "isMessageSheet";
50
54
 
51
55
  private ExtendedDialog.SheetCallback sheetCallback;
52
56
  private boolean dismissed = false;
53
57
  private Context themedContext;
58
+ private LinearLayout rootLayout;
54
59
  private ScrollView scrollView;
55
60
  private LinearLayout headerLayout;
56
61
  private LinearLayout bodyLayout;
57
62
  private LinearLayout buttonContainer;
63
+ private int buttonHorizontalPaddingPx;
64
+ private int buttonTopPaddingPx;
65
+ private int buttonBottomBasePaddingPx;
66
+ private int buttonBottomInsetsPx;
67
+ private int buttonExpandedExtraPaddingPx;
68
+ private boolean applyExpandedButtonOffset;
58
69
 
59
70
  public static SheetBottomDialogFragment newInstance(
60
71
  String title,
72
+ String subtitle,
61
73
  String headerLogo,
62
74
  String rowsJson,
63
75
  String confirmButton,
@@ -68,6 +80,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
68
80
  SheetBottomDialogFragment fragment = new SheetBottomDialogFragment();
69
81
  Bundle args = new Bundle();
70
82
  args.putString(ARG_TITLE, title);
83
+ args.putString(ARG_SUBTITLE, subtitle);
71
84
  args.putString(ARG_HEADER_LOGO, headerLogo);
72
85
  args.putString(ARG_ROWS, rowsJson);
73
86
  args.putString(ARG_CONFIRM_BUTTON, confirmButton);
@@ -83,6 +96,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
83
96
 
84
97
  public static SheetBottomDialogFragment newMessageInstance(
85
98
  String title,
99
+ String subtitle,
86
100
  String headerLogo,
87
101
  String message,
88
102
  String confirmButton,
@@ -93,6 +107,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
93
107
  SheetBottomDialogFragment fragment = new SheetBottomDialogFragment();
94
108
  Bundle args = new Bundle();
95
109
  args.putString(ARG_TITLE, title);
110
+ args.putString(ARG_SUBTITLE, subtitle);
96
111
  args.putString(ARG_HEADER_LOGO, headerLogo);
97
112
  args.putString(ARG_MESSAGE, message);
98
113
  args.putString(ARG_CONFIRM_BUTTON, confirmButton);
@@ -134,6 +149,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
134
149
  }
135
150
 
136
151
  String title = args.getString(ARG_TITLE, "");
152
+ String subtitle = args.getString(ARG_SUBTITLE);
137
153
  String headerLogo = args.getString(ARG_HEADER_LOGO);
138
154
  String rowsJson = args.getString(ARG_ROWS);
139
155
  String message = args.getString(ARG_MESSAGE, "");
@@ -145,10 +161,13 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
145
161
 
146
162
  Context ctx = getThemedContext();
147
163
  float density = getResources().getDisplayMetrics().density;
164
+ int screenHeight = getResources().getDisplayMetrics().heightPixels;
165
+ int initialRootHeight = fullscreen ? screenHeight : (int) (screenHeight * 0.5f);
148
166
 
149
167
  // Root layout
150
- LinearLayout root = new LinearLayout(ctx);
151
- root.setOrientation(LinearLayout.VERTICAL);
168
+ rootLayout = new LinearLayout(ctx);
169
+ rootLayout.setOrientation(LinearLayout.VERTICAL);
170
+ rootLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, initialRootHeight));
152
171
 
153
172
  // Apply background color
154
173
  if (styleOptions.getBackgroundColor() != null) {
@@ -161,7 +180,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
161
180
  .build();
162
181
  MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeModel);
163
182
  shapeDrawable.setFillColor(ColorStateList.valueOf(styleOptions.getBackgroundColor()));
164
- root.setBackground(shapeDrawable);
183
+ rootLayout.setBackground(shapeDrawable);
165
184
  }
166
185
 
167
186
  // Drag handle (only shown in basic/non-fullscreen mode)
@@ -180,7 +199,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
180
199
  handleDrawable.setCornerRadius(handleHeight / 2f);
181
200
  handleDrawable.setColor(outlineVariantColor);
182
201
  dragHandle.setBackground(handleDrawable);
183
- root.addView(dragHandle);
202
+ rootLayout.addView(dragHandle);
184
203
  }
185
204
 
186
205
  int horizontalPadding = (int) (24 * density);
@@ -212,12 +231,14 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
212
231
  }
213
232
  if (radiusPx > 0) {
214
233
  logoView.setClipToOutline(true);
215
- logoView.setOutlineProvider(new android.view.ViewOutlineProvider() {
216
- @Override
217
- public void getOutline(android.view.View view, android.graphics.Outline outline) {
218
- outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), radiusPx);
234
+ logoView.setOutlineProvider(
235
+ new android.view.ViewOutlineProvider() {
236
+ @Override
237
+ public void getOutline(android.view.View view, android.graphics.Outline outline) {
238
+ outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), radiusPx);
239
+ }
219
240
  }
220
- });
241
+ );
221
242
  }
222
243
 
223
244
  headerLayout.addView(logoView);
@@ -243,16 +264,40 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
243
264
  LinearLayout.LayoutParams.MATCH_PARENT,
244
265
  LinearLayout.LayoutParams.WRAP_CONTENT
245
266
  );
246
- titleParams.bottomMargin = (int) (20 * density);
267
+ titleParams.bottomMargin = (subtitle != null && !subtitle.isEmpty()) ? (int) (4 * density) : (int) (20 * density);
247
268
  titleView.setLayoutParams(titleParams);
248
269
  headerLayout.addView(titleView);
249
270
  }
250
- root.addView(headerLayout);
271
+
272
+ // Subtitle
273
+ if (subtitle != null && !subtitle.isEmpty()) {
274
+ TextView subtitleView = new TextView(ctx);
275
+ subtitleView.setText(subtitle);
276
+ TextViewCompat.setTextAppearance(subtitleView, com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
277
+ if (styleOptions.getMessageColor() != null) {
278
+ subtitleView.setTextColor(styleOptions.getMessageColor());
279
+ } else {
280
+ int secondaryColor = MaterialColors.getColor(ctx, android.R.attr.textColorSecondary, 0xFF49454F);
281
+ subtitleView.setTextColor(secondaryColor);
282
+ }
283
+ if (styleOptions.getMessageFontSize() != null) {
284
+ subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_SP, styleOptions.getMessageFontSize());
285
+ }
286
+ subtitleView.setGravity(Gravity.CENTER);
287
+ LinearLayout.LayoutParams subtitleParams = new LinearLayout.LayoutParams(
288
+ LinearLayout.LayoutParams.MATCH_PARENT,
289
+ LinearLayout.LayoutParams.WRAP_CONTENT
290
+ );
291
+ subtitleParams.bottomMargin = (int) (20 * density);
292
+ subtitleView.setLayoutParams(subtitleParams);
293
+ headerLayout.addView(subtitleView);
294
+ }
295
+ rootLayout.addView(headerLayout);
251
296
 
252
297
  // ScrollView for body content (rows/message only)
253
298
  scrollView = new ScrollView(ctx);
254
299
  scrollView.setFillViewport(true);
255
- scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
300
+ scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
256
301
 
257
302
  bodyLayout = new LinearLayout(ctx);
258
303
  bodyLayout.setOrientation(LinearLayout.VERTICAL);
@@ -265,9 +310,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
265
310
  int messagePadding = (int) (16 * density);
266
311
  messageContainer.setPadding(messagePadding, messagePadding, messagePadding, messagePadding);
267
312
 
268
- ShapeAppearanceModel messageShape = ShapeAppearanceModel.builder()
269
- .setAllCornerSizes(12 * density)
270
- .build();
313
+ ShapeAppearanceModel messageShape = ShapeAppearanceModel.builder().setAllCornerSizes(12 * density).build();
271
314
  MaterialShapeDrawable messageBackground = new MaterialShapeDrawable(messageShape);
272
315
  int surfaceVariant = MaterialColors.getColor(ctx, com.google.android.material.R.attr.colorSurfaceVariant, 0xFFE7E0EC);
273
316
  messageBackground.setFillColor(ColorStateList.valueOf(surfaceVariant));
@@ -312,14 +355,35 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
312
355
  }
313
356
 
314
357
  scrollView.addView(bodyLayout);
315
- root.addView(scrollView);
358
+ rootLayout.addView(scrollView);
316
359
 
317
360
  // Button container pinned at bottom
318
361
  buttonContainer = new LinearLayout(ctx);
319
362
  buttonContainer.setOrientation(LinearLayout.VERTICAL);
320
363
  float topSpacing = styleOptions.getContentButtonSpacing() != null ? styleOptions.getContentButtonSpacing() : 12f;
321
-
322
- buttonContainer.setPadding(horizontalPadding, (int) (topSpacing * density), horizontalPadding, (int) (4 * density));
364
+ int buttonTopPadding = (int) (topSpacing * density);
365
+ int baseBottomPadding = (int) ((fullscreen ? 4f : 12f) * density);
366
+ int nonFullscreenExtraBottomPadding = fullscreen ? 0 : (int) (4 * density);
367
+ int bottomPaddingWithoutInsets = baseBottomPadding + nonFullscreenExtraBottomPadding;
368
+
369
+ buttonHorizontalPaddingPx = horizontalPadding;
370
+ buttonTopPaddingPx = buttonTopPadding;
371
+ buttonBottomBasePaddingPx = bottomPaddingWithoutInsets;
372
+ buttonBottomInsetsPx = 0;
373
+ buttonExpandedExtraPaddingPx = (int) (48 * density);
374
+ applyExpandedButtonOffset = fullscreen;
375
+
376
+ applyButtonContainerPadding();
377
+
378
+ ViewCompat.setOnApplyWindowInsetsListener(buttonContainer, (viewWithInsets, windowInsets) -> {
379
+ Insets systemBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
380
+ Insets gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
381
+ Insets tappableInsets = windowInsets.getInsets(WindowInsetsCompat.Type.tappableElement());
382
+ buttonBottomInsetsPx = Math.max(systemBarInsets.bottom, Math.max(gestureInsets.bottom, tappableInsets.bottom));
383
+ applyButtonContainerPadding();
384
+ return windowInsets;
385
+ });
386
+ ViewCompat.requestApplyInsets(buttonContainer);
323
387
 
324
388
  int primaryColor = MaterialColors.getColor(ctx, android.R.attr.colorPrimary, 0xFF6750A4);
325
389
 
@@ -380,9 +444,9 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
380
444
  cancelBtn.setLayoutParams(cancelParams);
381
445
  buttonContainer.addView(cancelBtn);
382
446
 
383
- root.addView(buttonContainer);
447
+ rootLayout.addView(buttonContainer);
384
448
 
385
- return root;
449
+ return rootLayout;
386
450
  }
387
451
 
388
452
  @Override
@@ -413,22 +477,57 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
413
477
  behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
414
478
  // Prevent dragging down in fullscreen mode
415
479
  behavior.setDraggable(false);
480
+ setExpandedButtonOffset(true);
481
+ behavior.addBottomSheetCallback(
482
+ new BottomSheetBehavior.BottomSheetCallback() {
483
+ @Override
484
+ public void onStateChanged(@NonNull View sheet, int newState) {
485
+ if (newState == BottomSheetBehavior.STATE_EXPANDED) {
486
+ setExpandedButtonOffset(true);
487
+ setRootHeight(getVisibleSheetHeight(sheet));
488
+ }
489
+ }
490
+
491
+ @Override
492
+ public void onSlide(@NonNull View sheet, float slideOffset) {
493
+ setExpandedButtonOffset(true);
494
+ setRootHeight(getVisibleSheetHeight(sheet));
495
+ }
496
+ }
497
+ );
498
+ bottomSheet.post(() -> setRootHeight(getVisibleSheetHeight(bottomSheet)));
416
499
  } else {
417
- // Dynamic height based on content (min 50%, max 80%), drag down to close
500
+ // Multi-stop bottom sheet: drag up to fullscreen, drag down to dismiss
418
501
  ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
419
502
  layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
420
503
  bottomSheet.setLayoutParams(layoutParams);
421
504
 
422
- behavior.setFitToContents(true);
505
+ behavior.setFitToContents(false);
423
506
  behavior.setSkipCollapsed(true);
424
507
  behavior.setHideable(true);
425
508
  behavior.setDraggable(true);
426
509
 
510
+ behavior.addBottomSheetCallback(
511
+ new BottomSheetBehavior.BottomSheetCallback() {
512
+ @Override
513
+ public void onStateChanged(@NonNull View sheet, int newState) {
514
+ if (newState == BottomSheetBehavior.STATE_HALF_EXPANDED || newState == BottomSheetBehavior.STATE_EXPANDED) {
515
+ setExpandedButtonOffset(newState == BottomSheetBehavior.STATE_EXPANDED);
516
+ setRootHeight(getVisibleSheetHeight(sheet));
517
+ }
518
+ }
519
+
520
+ @Override
521
+ public void onSlide(@NonNull View sheet, float slideOffset) {
522
+ setExpandedButtonOffset(slideOffset >= 0.9f);
523
+ setRootHeight(getVisibleSheetHeight(sheet));
524
+ }
525
+ }
526
+ );
527
+
427
528
  bottomSheet.post(() -> {
428
529
  int screenHeight = getResources().getDisplayMetrics().heightPixels;
429
- int width = bottomSheet.getWidth() > 0
430
- ? bottomSheet.getWidth()
431
- : getResources().getDisplayMetrics().widthPixels;
530
+ int width = bottomSheet.getWidth() > 0 ? bottomSheet.getWidth() : getResources().getDisplayMetrics().widthPixels;
432
531
 
433
532
  int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
434
533
  int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
@@ -445,36 +544,85 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
445
544
  bodyHeight = bodyLayout.getMeasuredHeight();
446
545
  }
447
546
 
448
- int buttonHeight = 0;
547
+ int btnHeight = 0;
449
548
  if (buttonContainer != null) {
450
549
  buttonContainer.measure(widthSpec, heightSpec);
451
- buttonHeight = buttonContainer.getMeasuredHeight();
550
+ btnHeight = buttonContainer.getMeasuredHeight();
452
551
  }
453
552
 
454
- int minHeight = (int) (screenHeight * 0.5f);
455
- int maxHeight = (int) (screenHeight * 0.8f);
456
- int desiredHeight = headerHeight + bodyHeight + buttonHeight;
457
- desiredHeight = Math.max(desiredHeight, minHeight);
458
- desiredHeight = Math.min(desiredHeight, maxHeight);
459
-
460
- if (scrollView != null) {
461
- ViewGroup.LayoutParams scrollParams = scrollView.getLayoutParams();
462
- int scrollHeight = Math.max(0, desiredHeight - headerHeight - buttonHeight);
463
- scrollParams.height = scrollHeight;
464
- scrollView.setLayoutParams(scrollParams);
465
- }
553
+ // Add drag handle height (~28dp)
554
+ float density = getResources().getDisplayMetrics().density;
555
+ int dragHandleHeight = (int) (28 * density);
466
556
 
467
- ViewGroup.LayoutParams sheetParams = bottomSheet.getLayoutParams();
468
- sheetParams.height = desiredHeight;
469
- bottomSheet.setLayoutParams(sheetParams);
557
+ int contentRequiredHeight = headerHeight + bodyHeight + btnHeight + dragHandleHeight;
558
+ int desiredHeight = clampInitialSheetHeight(screenHeight, contentRequiredHeight);
559
+ float ratio = calculateHalfExpandedRatio(screenHeight, desiredHeight);
470
560
 
561
+ setRootHeight(desiredHeight);
562
+ behavior.setHalfExpandedRatio(ratio);
471
563
  behavior.setPeekHeight(desiredHeight);
472
- behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
564
+ behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
565
+ bottomSheet.post(() -> setRootHeight(getVisibleSheetHeight(bottomSheet)));
473
566
  });
474
567
  }
475
568
  });
476
569
  }
477
570
 
571
+ static int clampInitialSheetHeight(int screenHeight, int contentRequiredHeight) {
572
+ int minHeight = (int) (screenHeight * 0.5f);
573
+ int maxHeight = (int) (screenHeight * 0.8f);
574
+ int clampedToMin = Math.max(contentRequiredHeight, minHeight);
575
+ return Math.min(clampedToMin, maxHeight);
576
+ }
577
+
578
+ static float calculateHalfExpandedRatio(int screenHeight, int desiredHeight) {
579
+ if (screenHeight <= 0) {
580
+ return 0.5f;
581
+ }
582
+ float ratio = (float) desiredHeight / screenHeight;
583
+ return Math.max(0.5f, Math.min(ratio, 0.8f));
584
+ }
585
+
586
+ private int getVisibleSheetHeight(@NonNull View sheet) {
587
+ View parent = sheet.getParent() instanceof View ? (View) sheet.getParent() : null;
588
+ int parentHeight = parent != null ? parent.getHeight() : getResources().getDisplayMetrics().heightPixels;
589
+ int visibleHeight = parentHeight - sheet.getTop();
590
+ int nonNegativeHeight = Math.max(0, visibleHeight);
591
+ // Clamp to parent bounds to avoid overshoot during spring/drag transitions.
592
+ return Math.min(parentHeight, nonNegativeHeight);
593
+ }
594
+
595
+ private void setRootHeight(int targetHeight) {
596
+ if (rootLayout == null || targetHeight <= 0) {
597
+ return;
598
+ }
599
+ ViewGroup.LayoutParams params = rootLayout.getLayoutParams();
600
+ if (params == null) {
601
+ params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, targetHeight);
602
+ } else if (params.height == targetHeight) {
603
+ return;
604
+ }
605
+ params.height = targetHeight;
606
+ rootLayout.setLayoutParams(params);
607
+ }
608
+
609
+ private void setExpandedButtonOffset(boolean enabled) {
610
+ if (applyExpandedButtonOffset == enabled) {
611
+ return;
612
+ }
613
+ applyExpandedButtonOffset = enabled;
614
+ applyButtonContainerPadding();
615
+ }
616
+
617
+ private void applyButtonContainerPadding() {
618
+ if (buttonContainer == null) {
619
+ return;
620
+ }
621
+ int expandedExtraBottomPadding = applyExpandedButtonOffset ? buttonExpandedExtraPaddingPx : 0;
622
+ int resolvedBottomPadding = buttonBottomBasePaddingPx + buttonBottomInsetsPx + expandedExtraBottomPadding;
623
+ buttonContainer.setPadding(buttonHorizontalPaddingPx, buttonTopPaddingPx, buttonHorizontalPaddingPx, resolvedBottomPadding);
624
+ }
625
+
478
626
  private LinearLayout createSheetRow(
479
627
  Context context,
480
628
  JSONObject row,
package/dist/docs.json CHANGED
@@ -540,6 +540,13 @@
540
540
  "complexTypes": [],
541
541
  "type": "string"
542
542
  },
543
+ {
544
+ "name": "subtitle",
545
+ "tags": [],
546
+ "docs": "Optional subtitle displayed between title and rows",
547
+ "complexTypes": [],
548
+ "type": "string | undefined"
549
+ },
543
550
  {
544
551
  "name": "rows",
545
552
  "tags": [],
@@ -641,6 +648,13 @@
641
648
  "complexTypes": [],
642
649
  "type": "string"
643
650
  },
651
+ {
652
+ "name": "subtitle",
653
+ "tags": [],
654
+ "docs": "Optional subtitle displayed between title and message",
655
+ "complexTypes": [],
656
+ "type": "string | undefined"
657
+ },
644
658
  {
645
659
  "name": "message",
646
660
  "tags": [],
@@ -270,6 +270,8 @@ export interface SheetOptions extends DialogStyleOptions {
270
270
  headerLogo?: string;
271
271
  /** Sheet title */
272
272
  title: string;
273
+ /** Optional subtitle displayed between title and rows */
274
+ subtitle?: string;
273
275
  /** Description rows */
274
276
  rows: SheetRow[];
275
277
  /** Confirm button title */
@@ -284,6 +286,8 @@ export interface MessageSheetOptions extends DialogStyleOptions {
284
286
  headerLogo?: string;
285
287
  /** Sheet title */
286
288
  title: string;
289
+ /** Optional subtitle displayed between title and message */
290
+ subtitle?: string;
287
291
  /** Message body displayed in the sheet */
288
292
  message: string;
289
293
  /** Confirm button title */
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Dialog presentation mode.\n *\n * - `'basic'` — Standard modal dialog (default)\n * - `'fullscreen'` — Full-screen dialog presentation\n */\nexport type DialogMode = 'basic' | 'fullscreen';\n\nexport interface DialogStyleOptions {\n /**\n * Color for the OK/primary button (hex format, e.g., \"#FF5722\")\n */\n buttonColor?: string;\n /**\n * Color for the cancel button (hex format, e.g., \"#757575\")\n */\n cancelButtonColor?: string;\n /**\n * Color for the title text (hex format, e.g., \"#000000\")\n */\n titleColor?: string;\n /**\n * Color for the message text (hex format, e.g., \"#666666\")\n */\n messageColor?: string;\n /**\n * Background color of the dialog (hex format, e.g., \"#FFFFFF\")\n */\n backgroundColor?: string;\n /**\n * Font size for the title text in sp/pt (e.g., 20)\n */\n titleFontSize?: number;\n /**\n * Font size for the message text in sp/pt (e.g., 16)\n */\n messageFontSize?: number;\n /**\n * Font size for the button text in sp/pt (e.g., 14)\n */\n buttonFontSize?: number;\n /**\n * Vertical spacing between dialog content and the confirm/cancel buttons in dp/pt/px (e.g., 16).\n * Only applies to fullscreen and sheet modes.\n *\n * @example\n * // Fullscreen confirm with extra spacing between content and buttons\n * await ExtendedDialog.confirm({\n * title: 'Delete Account',\n * message: 'This action cannot be undone.',\n * mode: 'fullscreen',\n * contentButtonSpacing: 32,\n * });\n *\n * @example\n * // Sheet with tight spacing\n * await ExtendedDialog.sheet({\n * title: 'Order Summary',\n * rows: [{ title: 'Total', value: '$9.99' }],\n * contentButtonSpacing: 8,\n * });\n */\n contentButtonSpacing?: number;\n /**\n * Corner radius for the header logo in sheet dialogs (in dp/pt/px).\n * - Positive number: specific radius (e.g., 12)\n * - 0: square corners (no rounding)\n * - -1: full circle (radius = half of logo size)\n *\n * @default 8\n *\n * @example\n * // Custom rounded corners (12px)\n * await ExtendedDialog.sheet({\n * title: 'Settings',\n * headerLogo: 'https://example.com/logo.png',\n * headerLogoCornerRadius: 12,\n * rows: [],\n * });\n *\n * @example\n * // Full circle logo\n * await ExtendedDialog.sheet({\n * title: 'Profile',\n * headerLogo: 'https://example.com/avatar.png',\n * headerLogoCornerRadius: -1,\n * rows: [],\n * });\n *\n * @example\n * // Square logo (no rounding)\n * await ExtendedDialog.sheet({\n * title: 'Document',\n * headerLogo: 'https://example.com/icon.png',\n * headerLogoCornerRadius: 0,\n * rows: [],\n * });\n */\n headerLogoCornerRadius?: number;\n}\n\nexport interface BaseDialogOptions extends DialogStyleOptions {\n /**\n * Title displayed at the top of the dialog.\n */\n title?: string;\n /**\n * Message body displayed in the dialog.\n */\n message: string;\n /**\n * Presentation mode for the dialog.\n *\n * @default 'basic'\n */\n mode?: DialogMode;\n}\n\nexport interface AlertOptions extends BaseDialogOptions {\n /**\n * Title for the dismiss button.\n *\n * @default \"OK\"\n */\n buttonTitle?: string;\n}\n\nexport interface ConfirmOptions extends BaseDialogOptions {\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface PromptOptions extends BaseDialogOptions {\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n /**\n * Placeholder text shown in the input field when empty.\n */\n inputPlaceholder?: string;\n /**\n * Pre-filled value for the input field.\n */\n inputText?: string;\n /**\n * Whether to automatically focus the input field and open the keyboard when the dialog appears.\n *\n * Note: On iOS, basic (non-fullscreen) dialogs always auto-focus the input field due to\n * UIAlertController's built-in behavior. This option only takes effect on iOS when using\n * fullscreen mode (`mode: 'fullscreen'`). On Android and web, this works for all modes.\n *\n * @default false\n */\n focusInput?: boolean;\n}\n\nexport interface SelectOption {\n /**\n * Display text for the option.\n */\n label: string;\n /**\n * Value returned when the option is selected.\n */\n value: string;\n}\n\nexport interface SingleSelectOptions extends BaseDialogOptions {\n /**\n * List of options to display for selection.\n */\n options: SelectOption[];\n /**\n * Value of the initially selected option.\n */\n selectedValue?: string;\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface MultiSelectOptions extends BaseDialogOptions {\n /**\n * List of options to display for selection.\n */\n options: SelectOption[];\n /**\n * Values of the initially selected options.\n */\n selectedValues?: string[];\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface ConfirmResult {\n /**\n * Whether the user confirmed (`true`) or cancelled (`false`).\n */\n value: boolean;\n}\n\nexport interface PromptResult {\n /**\n * The text entered by the user. Empty string if cancelled.\n */\n value: string;\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface SingleSelectResult {\n /**\n * The value of the selected option, or `null` if cancelled.\n */\n value: string | null;\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface MultiSelectResult {\n /**\n * The values of the selected options. Empty array if cancelled.\n */\n values: string[];\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface SheetRow {\n /** Row title (required) */\n title: string;\n /** Optional logo/icon - supports base64 data URL or HTTP/HTTPS URL */\n logo?: string;\n /** Optional value displayed on the right */\n value?: string;\n}\n\nexport interface SheetOptions extends DialogStyleOptions {\n /** Header logo - supports base64 data URL or HTTP/HTTPS URL */\n headerLogo?: string;\n /** Sheet title */\n title: string;\n /** Description rows */\n rows: SheetRow[];\n /** Confirm button title */\n confirmButtonTitle?: string; // default: \"Confirm\"\n /** Cancel button title */\n cancelButtonTitle?: string; // default: \"Cancel\"\n /** Dialog mode */\n mode?: DialogMode;\n}\n\nexport interface MessageSheetOptions extends DialogStyleOptions {\n /** Header logo - supports base64 data URL or HTTP/HTTPS URL */\n headerLogo?: string;\n /** Sheet title */\n title: string;\n /** Message body displayed in the sheet */\n message: string;\n /** Confirm button title */\n confirmButtonTitle?: string; // default: \"Confirm\"\n /** Cancel button title */\n cancelButtonTitle?: string; // default: \"Cancel\"\n /** Dialog mode */\n mode?: DialogMode;\n}\n\nexport interface SheetResult {\n /** True if confirmed, false if cancelled */\n confirmed: boolean;\n}\n\nexport interface MessageSheetResult {\n /** True if confirmed, false if cancelled */\n confirmed: boolean;\n}\n\nexport interface ExtendedDialogPlugin {\n /**\n * Show an alert dialog with a single dismiss button.\n *\n * @param options - Alert configuration options.\n */\n alert(options: AlertOptions): Promise<void>;\n /**\n * Show a confirmation dialog with OK and Cancel buttons.\n *\n * @param options - Confirm configuration options.\n * @returns The user's confirmation choice.\n */\n confirm(options: ConfirmOptions): Promise<ConfirmResult>;\n /**\n * Show a prompt dialog with a text input field.\n *\n * @param options - Prompt configuration options.\n * @returns The entered text and whether the dialog was cancelled.\n */\n prompt(options: PromptOptions): Promise<PromptResult>;\n /**\n * Show a single-select dialog where the user picks one option.\n *\n * @param options - Single select configuration options.\n * @returns The selected value and whether the dialog was cancelled.\n */\n singleSelect(options: SingleSelectOptions): Promise<SingleSelectResult>;\n /**\n * Show a multi-select dialog where the user picks one or more options.\n *\n * @param options - Multi select configuration options.\n * @returns The selected values and whether the dialog was cancelled.\n */\n multiSelect(options: MultiSelectOptions): Promise<MultiSelectResult>;\n /**\n * Show a sheet dialog with a header, title, and structured data rows.\n *\n * @param options - Sheet configuration options.\n * @returns Whether the user confirmed or cancelled the sheet.\n */\n sheet(options: SheetOptions): Promise<SheetResult>;\n\n /**\n * Show a message sheet dialog with an optional header logo, title, and message.\n *\n * @param options - Message sheet configuration options.\n * @returns Whether the user confirmed or cancelled the sheet.\n */\n messageSheet(options: MessageSheetOptions): Promise<MessageSheetResult>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Dialog presentation mode.\n *\n * - `'basic'` — Standard modal dialog (default)\n * - `'fullscreen'` — Full-screen dialog presentation\n */\nexport type DialogMode = 'basic' | 'fullscreen';\n\nexport interface DialogStyleOptions {\n /**\n * Color for the OK/primary button (hex format, e.g., \"#FF5722\")\n */\n buttonColor?: string;\n /**\n * Color for the cancel button (hex format, e.g., \"#757575\")\n */\n cancelButtonColor?: string;\n /**\n * Color for the title text (hex format, e.g., \"#000000\")\n */\n titleColor?: string;\n /**\n * Color for the message text (hex format, e.g., \"#666666\")\n */\n messageColor?: string;\n /**\n * Background color of the dialog (hex format, e.g., \"#FFFFFF\")\n */\n backgroundColor?: string;\n /**\n * Font size for the title text in sp/pt (e.g., 20)\n */\n titleFontSize?: number;\n /**\n * Font size for the message text in sp/pt (e.g., 16)\n */\n messageFontSize?: number;\n /**\n * Font size for the button text in sp/pt (e.g., 14)\n */\n buttonFontSize?: number;\n /**\n * Vertical spacing between dialog content and the confirm/cancel buttons in dp/pt/px (e.g., 16).\n * Only applies to fullscreen and sheet modes.\n *\n * @example\n * // Fullscreen confirm with extra spacing between content and buttons\n * await ExtendedDialog.confirm({\n * title: 'Delete Account',\n * message: 'This action cannot be undone.',\n * mode: 'fullscreen',\n * contentButtonSpacing: 32,\n * });\n *\n * @example\n * // Sheet with tight spacing\n * await ExtendedDialog.sheet({\n * title: 'Order Summary',\n * rows: [{ title: 'Total', value: '$9.99' }],\n * contentButtonSpacing: 8,\n * });\n */\n contentButtonSpacing?: number;\n /**\n * Corner radius for the header logo in sheet dialogs (in dp/pt/px).\n * - Positive number: specific radius (e.g., 12)\n * - 0: square corners (no rounding)\n * - -1: full circle (radius = half of logo size)\n *\n * @default 8\n *\n * @example\n * // Custom rounded corners (12px)\n * await ExtendedDialog.sheet({\n * title: 'Settings',\n * headerLogo: 'https://example.com/logo.png',\n * headerLogoCornerRadius: 12,\n * rows: [],\n * });\n *\n * @example\n * // Full circle logo\n * await ExtendedDialog.sheet({\n * title: 'Profile',\n * headerLogo: 'https://example.com/avatar.png',\n * headerLogoCornerRadius: -1,\n * rows: [],\n * });\n *\n * @example\n * // Square logo (no rounding)\n * await ExtendedDialog.sheet({\n * title: 'Document',\n * headerLogo: 'https://example.com/icon.png',\n * headerLogoCornerRadius: 0,\n * rows: [],\n * });\n */\n headerLogoCornerRadius?: number;\n}\n\nexport interface BaseDialogOptions extends DialogStyleOptions {\n /**\n * Title displayed at the top of the dialog.\n */\n title?: string;\n /**\n * Message body displayed in the dialog.\n */\n message: string;\n /**\n * Presentation mode for the dialog.\n *\n * @default 'basic'\n */\n mode?: DialogMode;\n}\n\nexport interface AlertOptions extends BaseDialogOptions {\n /**\n * Title for the dismiss button.\n *\n * @default \"OK\"\n */\n buttonTitle?: string;\n}\n\nexport interface ConfirmOptions extends BaseDialogOptions {\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface PromptOptions extends BaseDialogOptions {\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n /**\n * Placeholder text shown in the input field when empty.\n */\n inputPlaceholder?: string;\n /**\n * Pre-filled value for the input field.\n */\n inputText?: string;\n /**\n * Whether to automatically focus the input field and open the keyboard when the dialog appears.\n *\n * Note: On iOS, basic (non-fullscreen) dialogs always auto-focus the input field due to\n * UIAlertController's built-in behavior. This option only takes effect on iOS when using\n * fullscreen mode (`mode: 'fullscreen'`). On Android and web, this works for all modes.\n *\n * @default false\n */\n focusInput?: boolean;\n}\n\nexport interface SelectOption {\n /**\n * Display text for the option.\n */\n label: string;\n /**\n * Value returned when the option is selected.\n */\n value: string;\n}\n\nexport interface SingleSelectOptions extends BaseDialogOptions {\n /**\n * List of options to display for selection.\n */\n options: SelectOption[];\n /**\n * Value of the initially selected option.\n */\n selectedValue?: string;\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface MultiSelectOptions extends BaseDialogOptions {\n /**\n * List of options to display for selection.\n */\n options: SelectOption[];\n /**\n * Values of the initially selected options.\n */\n selectedValues?: string[];\n /**\n * Title for the confirmation button.\n *\n * @default \"OK\"\n */\n okButtonTitle?: string;\n /**\n * Title for the cancel button.\n *\n * @default \"Cancel\"\n */\n cancelButtonTitle?: string;\n}\n\nexport interface ConfirmResult {\n /**\n * Whether the user confirmed (`true`) or cancelled (`false`).\n */\n value: boolean;\n}\n\nexport interface PromptResult {\n /**\n * The text entered by the user. Empty string if cancelled.\n */\n value: string;\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface SingleSelectResult {\n /**\n * The value of the selected option, or `null` if cancelled.\n */\n value: string | null;\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface MultiSelectResult {\n /**\n * The values of the selected options. Empty array if cancelled.\n */\n values: string[];\n /**\n * Whether the user cancelled the dialog.\n */\n cancelled: boolean;\n}\n\nexport interface SheetRow {\n /** Row title (required) */\n title: string;\n /** Optional logo/icon - supports base64 data URL or HTTP/HTTPS URL */\n logo?: string;\n /** Optional value displayed on the right */\n value?: string;\n}\n\nexport interface SheetOptions extends DialogStyleOptions {\n /** Header logo - supports base64 data URL or HTTP/HTTPS URL */\n headerLogo?: string;\n /** Sheet title */\n title: string;\n /** Optional subtitle displayed between title and rows */\n subtitle?: string;\n /** Description rows */\n rows: SheetRow[];\n /** Confirm button title */\n confirmButtonTitle?: string; // default: \"Confirm\"\n /** Cancel button title */\n cancelButtonTitle?: string; // default: \"Cancel\"\n /** Dialog mode */\n mode?: DialogMode;\n}\n\nexport interface MessageSheetOptions extends DialogStyleOptions {\n /** Header logo - supports base64 data URL or HTTP/HTTPS URL */\n headerLogo?: string;\n /** Sheet title */\n title: string;\n /** Optional subtitle displayed between title and message */\n subtitle?: string;\n /** Message body displayed in the sheet */\n message: string;\n /** Confirm button title */\n confirmButtonTitle?: string; // default: \"Confirm\"\n /** Cancel button title */\n cancelButtonTitle?: string; // default: \"Cancel\"\n /** Dialog mode */\n mode?: DialogMode;\n}\n\nexport interface SheetResult {\n /** True if confirmed, false if cancelled */\n confirmed: boolean;\n}\n\nexport interface MessageSheetResult {\n /** True if confirmed, false if cancelled */\n confirmed: boolean;\n}\n\nexport interface ExtendedDialogPlugin {\n /**\n * Show an alert dialog with a single dismiss button.\n *\n * @param options - Alert configuration options.\n */\n alert(options: AlertOptions): Promise<void>;\n /**\n * Show a confirmation dialog with OK and Cancel buttons.\n *\n * @param options - Confirm configuration options.\n * @returns The user's confirmation choice.\n */\n confirm(options: ConfirmOptions): Promise<ConfirmResult>;\n /**\n * Show a prompt dialog with a text input field.\n *\n * @param options - Prompt configuration options.\n * @returns The entered text and whether the dialog was cancelled.\n */\n prompt(options: PromptOptions): Promise<PromptResult>;\n /**\n * Show a single-select dialog where the user picks one option.\n *\n * @param options - Single select configuration options.\n * @returns The selected value and whether the dialog was cancelled.\n */\n singleSelect(options: SingleSelectOptions): Promise<SingleSelectResult>;\n /**\n * Show a multi-select dialog where the user picks one or more options.\n *\n * @param options - Multi select configuration options.\n * @returns The selected values and whether the dialog was cancelled.\n */\n multiSelect(options: MultiSelectOptions): Promise<MultiSelectResult>;\n /**\n * Show a sheet dialog with a header, title, and structured data rows.\n *\n * @param options - Sheet configuration options.\n * @returns Whether the user confirmed or cancelled the sheet.\n */\n sheet(options: SheetOptions): Promise<SheetResult>;\n\n /**\n * Show a message sheet dialog with an optional header logo, title, and message.\n *\n * @param options - Message sheet configuration options.\n * @returns Whether the user confirmed or cancelled the sheet.\n */\n messageSheet(options: MessageSheetOptions): Promise<MessageSheetResult>;\n}\n"]}