capacitor-extended-dialog 0.0.8 → 0.0.10

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.
@@ -16,6 +16,7 @@ public class DialogStyleOptions {
16
16
  private static final String KEY_TITLE_FONT_SIZE = "titleFontSize";
17
17
  private static final String KEY_MESSAGE_FONT_SIZE = "messageFontSize";
18
18
  private static final String KEY_BUTTON_FONT_SIZE = "buttonFontSize";
19
+ private static final String KEY_CONTENT_BUTTON_SPACING = "contentButtonSpacing";
19
20
 
20
21
  private Integer buttonColor;
21
22
  private Integer cancelButtonColor;
@@ -25,6 +26,7 @@ public class DialogStyleOptions {
25
26
  private Float titleFontSize;
26
27
  private Float messageFontSize;
27
28
  private Float buttonFontSize;
29
+ private Float contentButtonSpacing;
28
30
 
29
31
  public DialogStyleOptions() {}
30
32
 
@@ -43,34 +45,94 @@ public class DialogStyleOptions {
43
45
  return (size != null && size > 0) ? size.floatValue() : null;
44
46
  }
45
47
 
46
- public Integer getButtonColor() { return buttonColor; }
47
- public void setButtonColor(String hexColor) { this.buttonColor = parseColor(hexColor); }
48
+ private static Float parseSpacing(Double size) {
49
+ return (size != null && size >= 0) ? size.floatValue() : null;
50
+ }
51
+
52
+ public Integer getButtonColor() {
53
+ return buttonColor;
54
+ }
55
+
56
+ public void setButtonColor(String hexColor) {
57
+ this.buttonColor = parseColor(hexColor);
58
+ }
59
+
60
+ public Integer getCancelButtonColor() {
61
+ return cancelButtonColor;
62
+ }
63
+
64
+ public void setCancelButtonColor(String hexColor) {
65
+ this.cancelButtonColor = parseColor(hexColor);
66
+ }
67
+
68
+ public Integer getTitleColor() {
69
+ return titleColor;
70
+ }
71
+
72
+ public void setTitleColor(String hexColor) {
73
+ this.titleColor = parseColor(hexColor);
74
+ }
75
+
76
+ public Integer getMessageColor() {
77
+ return messageColor;
78
+ }
48
79
 
49
- public Integer getCancelButtonColor() { return cancelButtonColor; }
50
- public void setCancelButtonColor(String hexColor) { this.cancelButtonColor = parseColor(hexColor); }
80
+ public void setMessageColor(String hexColor) {
81
+ this.messageColor = parseColor(hexColor);
82
+ }
83
+
84
+ public Integer getBackgroundColor() {
85
+ return backgroundColor;
86
+ }
51
87
 
52
- public Integer getTitleColor() { return titleColor; }
53
- public void setTitleColor(String hexColor) { this.titleColor = parseColor(hexColor); }
88
+ public void setBackgroundColor(String hexColor) {
89
+ this.backgroundColor = parseColor(hexColor);
90
+ }
54
91
 
55
- public Integer getMessageColor() { return messageColor; }
56
- public void setMessageColor(String hexColor) { this.messageColor = parseColor(hexColor); }
92
+ public Float getTitleFontSize() {
93
+ return titleFontSize;
94
+ }
57
95
 
58
- public Integer getBackgroundColor() { return backgroundColor; }
59
- public void setBackgroundColor(String hexColor) { this.backgroundColor = parseColor(hexColor); }
96
+ public void setTitleFontSize(Double size) {
97
+ this.titleFontSize = parseSize(size);
98
+ }
60
99
 
61
- public Float getTitleFontSize() { return titleFontSize; }
62
- public void setTitleFontSize(Double size) { this.titleFontSize = parseSize(size); }
100
+ public Float getMessageFontSize() {
101
+ return messageFontSize;
102
+ }
63
103
 
64
- public Float getMessageFontSize() { return messageFontSize; }
65
- public void setMessageFontSize(Double size) { this.messageFontSize = parseSize(size); }
104
+ public void setMessageFontSize(Double size) {
105
+ this.messageFontSize = parseSize(size);
106
+ }
66
107
 
67
- public Float getButtonFontSize() { return buttonFontSize; }
68
- public void setButtonFontSize(Double size) { this.buttonFontSize = parseSize(size); }
108
+ public Float getButtonFontSize() {
109
+ return buttonFontSize;
110
+ }
111
+
112
+ public void setButtonFontSize(Double size) {
113
+ this.buttonFontSize = parseSize(size);
114
+ }
115
+
116
+ public Float getContentButtonSpacing() {
117
+ return contentButtonSpacing;
118
+ }
119
+
120
+ public void setContentButtonSpacing(Double size) {
121
+ this.contentButtonSpacing = parseSpacing(size);
122
+ }
69
123
 
70
124
  public boolean hasStyles() {
71
- return buttonColor != null || cancelButtonColor != null || titleColor != null ||
72
- messageColor != null || backgroundColor != null || titleFontSize != null ||
73
- messageFontSize != null || buttonFontSize != null;
125
+ return (
126
+ buttonColor != null ||
127
+ cancelButtonColor != null ||
128
+ titleColor != null ||
129
+ messageColor != null ||
130
+ backgroundColor != null ||
131
+ titleFontSize != null ||
132
+ messageFontSize != null ||
133
+ buttonFontSize != null ||
134
+ contentButtonSpacing != null
135
+ );
74
136
  }
75
137
 
76
138
  public void writeToBundle(Bundle bundle) {
@@ -82,6 +144,7 @@ public class DialogStyleOptions {
82
144
  if (titleFontSize != null) bundle.putFloat(KEY_TITLE_FONT_SIZE, titleFontSize);
83
145
  if (messageFontSize != null) bundle.putFloat(KEY_MESSAGE_FONT_SIZE, messageFontSize);
84
146
  if (buttonFontSize != null) bundle.putFloat(KEY_BUTTON_FONT_SIZE, buttonFontSize);
147
+ if (contentButtonSpacing != null) bundle.putFloat(KEY_CONTENT_BUTTON_SPACING, contentButtonSpacing);
85
148
  }
86
149
 
87
150
  public static DialogStyleOptions readFromBundle(Bundle bundle) {
@@ -94,6 +157,7 @@ public class DialogStyleOptions {
94
157
  options.titleFontSize = bundle.containsKey(KEY_TITLE_FONT_SIZE) ? bundle.getFloat(KEY_TITLE_FONT_SIZE) : null;
95
158
  options.messageFontSize = bundle.containsKey(KEY_MESSAGE_FONT_SIZE) ? bundle.getFloat(KEY_MESSAGE_FONT_SIZE) : null;
96
159
  options.buttonFontSize = bundle.containsKey(KEY_BUTTON_FONT_SIZE) ? bundle.getFloat(KEY_BUTTON_FONT_SIZE) : null;
160
+ options.contentButtonSpacing = bundle.containsKey(KEY_CONTENT_BUTTON_SPACING) ? bundle.getFloat(KEY_CONTENT_BUTTON_SPACING) : null;
97
161
  return options;
98
162
  }
99
163
  }
@@ -111,8 +111,7 @@ public class ExtendedDialog {
111
111
  // MaterialAlertDialogBuilder uses appcompat's alertTitle, not android's
112
112
  TextView titleView = dialog.findViewById(androidx.appcompat.R.id.alertTitle);
113
113
  if (titleView != null) {
114
- TextViewCompat.setTextAppearance(titleView,
115
- com.google.android.material.R.style.TextAppearance_Material3_HeadlineSmall);
114
+ TextViewCompat.setTextAppearance(titleView, com.google.android.material.R.style.TextAppearance_Material3_HeadlineSmall);
116
115
  // M3 dialog headline color: onSurface (#1D1B20)
117
116
  // Use MaterialColors for proper theme attribute resolution across different R class configurations
118
117
  int onSurfaceColor = MaterialColors.getColor(ctx, android.R.attr.textColorPrimary, 0xFF1D1B20);
@@ -122,8 +121,7 @@ public class ExtendedDialog {
122
121
  // Apply M3 BodyMedium to message with onSurfaceVariant color
123
122
  TextView messageView = dialog.findViewById(android.R.id.message);
124
123
  if (messageView != null) {
125
- TextViewCompat.setTextAppearance(messageView,
126
- com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
124
+ TextViewCompat.setTextAppearance(messageView, com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
127
125
  // M3 dialog supporting text color: onSurfaceVariant (#49454F)
128
126
  // Use MaterialColors for proper theme attribute resolution
129
127
  int onSurfaceVariantColor = MaterialColors.getColor(ctx, android.R.attr.textColorSecondary, 0xFF49454F);
@@ -198,8 +196,10 @@ public class ExtendedDialog {
198
196
  ) {
199
197
  activity.runOnUiThread(() -> {
200
198
  Context themedContext = getThemedContext(activity);
201
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(themedContext,
202
- R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog);
199
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
200
+ themedContext,
201
+ R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog
202
+ );
203
203
 
204
204
  if (title != null && !title.isEmpty()) {
205
205
  builder.setTitle(title);
@@ -268,8 +268,10 @@ public class ExtendedDialog {
268
268
  ) {
269
269
  activity.runOnUiThread(() -> {
270
270
  Context themedContext = getThemedContext(activity);
271
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(themedContext,
272
- R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog);
271
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
272
+ themedContext,
273
+ R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog
274
+ );
273
275
 
274
276
  if (title != null && !title.isEmpty()) {
275
277
  builder.setTitle(title);
@@ -370,8 +372,10 @@ public class ExtendedDialog {
370
372
  ) {
371
373
  activity.runOnUiThread(() -> {
372
374
  Context themedContext = getThemedContext(activity);
373
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(themedContext,
374
- R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog);
375
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
376
+ themedContext,
377
+ R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog
378
+ );
375
379
 
376
380
  if (title != null && !title.isEmpty()) {
377
381
  builder.setTitle(title);
@@ -379,8 +383,7 @@ public class ExtendedDialog {
379
383
  builder.setMessage(message);
380
384
 
381
385
  // Use Material 3 TextInputLayout with outlined style
382
- TextInputLayout textInputLayout = new TextInputLayout(themedContext, null,
383
- com.google.android.material.R.attr.textInputOutlinedStyle);
386
+ TextInputLayout textInputLayout = new TextInputLayout(themedContext);
384
387
  textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_OUTLINE);
385
388
 
386
389
  final TextInputEditText input = new TextInputEditText(textInputLayout.getContext());
@@ -520,8 +523,10 @@ public class ExtendedDialog {
520
523
 
521
524
  final int[] selectedIndex = { checkedItem };
522
525
 
523
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getThemedContext(activity),
524
- R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog);
526
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
527
+ getThemedContext(activity),
528
+ R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog
529
+ );
525
530
 
526
531
  if (title != null && !title.isEmpty()) {
527
532
  builder.setTitle(title);
@@ -663,8 +668,10 @@ public class ExtendedDialog {
663
668
 
664
669
  final Set<String> resultSet = new HashSet<>(selectedSet);
665
670
 
666
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getThemedContext(activity),
667
- R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog);
671
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
672
+ getThemedContext(activity),
673
+ R.style.ThemeOverlay_ExtendedDialog_MaterialAlertDialog
674
+ );
668
675
 
669
676
  if (title != null && !title.isEmpty()) {
670
677
  builder.setTitle(title);
@@ -25,6 +25,7 @@ public class ExtendedDialogPlugin extends Plugin {
25
25
  styleOptions.setTitleFontSize(call.getDouble("titleFontSize"));
26
26
  styleOptions.setMessageFontSize(call.getDouble("messageFontSize"));
27
27
  styleOptions.setButtonFontSize(call.getDouble("buttonFontSize"));
28
+ styleOptions.setContentButtonSpacing(call.getDouble("contentButtonSpacing"));
28
29
  return styleOptions;
29
30
  }
30
31
 
@@ -250,8 +250,7 @@ public class FullScreenDialogFragment extends DialogFragment {
250
250
  messageView.setTextSize(TypedValue.COMPLEX_UNIT_SP, styleOptions.getMessageFontSize());
251
251
  } else {
252
252
  // M3 dialog supporting text: 14sp, weight 400, tracking 0.25sp
253
- TextViewCompat.setTextAppearance(messageView,
254
- com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
253
+ TextViewCompat.setTextAppearance(messageView, com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
255
254
  }
256
255
  if (styleOptions.getMessageColor() != null) {
257
256
  messageView.setTextColor(styleOptions.getMessageColor());
@@ -293,7 +292,9 @@ public class FullScreenDialogFragment extends DialogFragment {
293
292
  buttonContainer.setOrientation(LinearLayout.HORIZONTAL);
294
293
  buttonContainer.setGravity(Gravity.END);
295
294
  int buttonPadding = (int) (16 * density);
296
- buttonContainer.setPadding(buttonPadding, buttonPadding, buttonPadding, buttonPadding);
295
+ float topSpacing = styleOptions.getContentButtonSpacing() != null ? styleOptions.getContentButtonSpacing() : 16f;
296
+ int buttonTopPadding = (int) (topSpacing * density);
297
+ buttonContainer.setPadding(buttonPadding, buttonTopPadding, buttonPadding, buttonPadding);
297
298
 
298
299
  // Cancel button (not shown for ALERT type)
299
300
  if (type != DialogType.ALERT) {
@@ -351,11 +352,11 @@ public class FullScreenDialogFragment extends DialogFragment {
351
352
  Context ctx = getThemedContext();
352
353
 
353
354
  // Use Material 3 TextInputLayout with outlined style
354
- TextInputLayout textInputLayout = new TextInputLayout(ctx, null,
355
- com.google.android.material.R.attr.textInputOutlinedStyle);
355
+ TextInputLayout textInputLayout = new TextInputLayout(ctx);
356
356
  textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_OUTLINE);
357
- textInputLayout.setLayoutParams(new LinearLayout.LayoutParams(
358
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
357
+ textInputLayout.setLayoutParams(
358
+ new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
359
+ );
359
360
 
360
361
  inputField = new TextInputEditText(textInputLayout.getContext());
361
362
  inputField.setInputType(InputType.TYPE_CLASS_TEXT);
@@ -372,15 +373,18 @@ public class FullScreenDialogFragment extends DialogFragment {
372
373
  if (focusInput) {
373
374
  inputField.requestFocus();
374
375
  // Show keyboard when dialog is shown
375
- inputField.postDelayed(() -> {
376
- if (getContext() != null) {
377
- android.view.inputmethod.InputMethodManager imm =
378
- (android.view.inputmethod.InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
379
- if (imm != null) {
380
- imm.showSoftInput(inputField, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);
376
+ inputField.postDelayed(
377
+ () -> {
378
+ if (getContext() != null) {
379
+ android.view.inputmethod.InputMethodManager imm =
380
+ (android.view.inputmethod.InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
381
+ if (imm != null) {
382
+ imm.showSoftInput(inputField, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);
383
+ }
381
384
  }
382
- }
383
- }, 200);
385
+ },
386
+ 200
387
+ );
384
388
  }
385
389
  }
386
390
 
@@ -404,8 +408,7 @@ public class FullScreenDialogFragment extends DialogFragment {
404
408
 
405
409
  RadioButton radioButton = new RadioButton(ctx);
406
410
  radioButton.setText(label);
407
- TextViewCompat.setTextAppearance(radioButton,
408
- com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
411
+ TextViewCompat.setTextAppearance(radioButton, com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
409
412
  // M3 list item text color: onSurface (#1D1B20)
410
413
  // Use android.R.attr.textColorPrimary which maps to onSurface in M3 themes
411
414
  int onSurfaceColor = MaterialColors.getColor(ctx, android.R.attr.textColorPrimary, 0xFF1D1B20);
@@ -466,8 +469,7 @@ public class FullScreenDialogFragment extends DialogFragment {
466
469
 
467
470
  CheckBox checkBox = new CheckBox(ctx);
468
471
  checkBox.setText(label);
469
- TextViewCompat.setTextAppearance(checkBox,
470
- com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
472
+ TextViewCompat.setTextAppearance(checkBox, com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
471
473
  // M3 list item text color: onSurface (#1D1B20)
472
474
  // Use android.R.attr.textColorPrimary which maps to onSurface in M3 themes
473
475
  int onSurfaceColor = MaterialColors.getColor(ctx, android.R.attr.textColorPrimary, 0xFF1D1B20);
@@ -1,7 +1,8 @@
1
1
  package com.albermonte.extendeddialog;
2
2
 
3
- import android.content.DialogInterface;
3
+ import android.app.Dialog;
4
4
  import android.content.Context;
5
+ import android.content.DialogInterface;
5
6
  import android.content.res.ColorStateList;
6
7
  import android.graphics.Bitmap;
7
8
  import android.graphics.BitmapFactory;
@@ -18,7 +19,6 @@ import android.widget.ImageView;
18
19
  import android.widget.LinearLayout;
19
20
  import android.widget.ScrollView;
20
21
  import android.widget.TextView;
21
- import android.app.Dialog;
22
22
  import androidx.annotation.NonNull;
23
23
  import androidx.annotation.Nullable;
24
24
  import androidx.core.widget.TextViewCompat;
@@ -140,7 +140,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
140
140
  handleParams.topMargin = (int) (16 * density);
141
141
  handleParams.bottomMargin = (int) (8 * density);
142
142
  dragHandle.setLayoutParams(handleParams);
143
- int outlineVariantColor = MaterialColors.getColor(ctx, com.google.android.material.R.attr.colorOutlineVariant, 0xFFCAC4D0);
143
+ int outlineVariantColor = MaterialColors.getColor(ctx, android.R.attr.textColorSecondary, 0xFFCAC4D0);
144
144
  android.graphics.drawable.GradientDrawable handleDrawable = new android.graphics.drawable.GradientDrawable();
145
145
  handleDrawable.setShape(android.graphics.drawable.GradientDrawable.RECTANGLE);
146
146
  handleDrawable.setCornerRadius(handleHeight / 2f);
@@ -151,8 +151,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
151
151
 
152
152
  // ScrollView for content
153
153
  ScrollView scrollView = new ScrollView(ctx);
154
- scrollView.setLayoutParams(new LinearLayout.LayoutParams(
155
- ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
154
+ scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
156
155
 
157
156
  LinearLayout contentLayout = new LinearLayout(ctx);
158
157
  contentLayout.setOrientation(LinearLayout.VERTICAL);
@@ -176,8 +175,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
176
175
  if (title != null && !title.isEmpty()) {
177
176
  TextView titleView = new TextView(ctx);
178
177
  titleView.setText(title);
179
- TextViewCompat.setTextAppearance(titleView,
180
- com.google.android.material.R.style.TextAppearance_Material3_HeadlineSmall);
178
+ TextViewCompat.setTextAppearance(titleView, com.google.android.material.R.style.TextAppearance_Material3_HeadlineSmall);
181
179
  if (styleOptions.getTitleColor() != null) {
182
180
  titleView.setTextColor(styleOptions.getTitleColor());
183
181
  } else {
@@ -214,10 +212,37 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
214
212
  scrollView.addView(contentLayout);
215
213
  root.addView(scrollView);
216
214
 
215
+ // Count rows for minimum height calculation
216
+ int rowCount = 0;
217
+ if (rowsJson != null) {
218
+ try {
219
+ JSONArray countRows = new JSONArray(rowsJson);
220
+ rowCount = countRows.length();
221
+ } catch (JSONException e) {
222
+ // ignore
223
+ }
224
+ }
225
+
217
226
  // Button container pinned at bottom
218
227
  LinearLayout buttonContainer = new LinearLayout(ctx);
219
228
  buttonContainer.setOrientation(LinearLayout.VERTICAL);
220
- buttonContainer.setPadding(horizontalPadding, (int) (12 * density), horizontalPadding, (int) (4 * density));
229
+ float topSpacing = styleOptions.getContentButtonSpacing() != null ? styleOptions.getContentButtonSpacing() : 12f;
230
+
231
+ // For sheets with ≤4 rows and no explicit spacing, add extra spacing to reach ~50% screen height
232
+ if (rowCount <= 4 && styleOptions.getContentButtonSpacing() == null) {
233
+ int screenHeight = getResources().getDisplayMetrics().heightPixels;
234
+ float targetHeight = screenHeight * 0.5f;
235
+ // Estimate current content height: header + title + rows + buttons
236
+ float estimatedContent = (16 + 8 + 48 + 12 + 20) * density; // drag handle + logo area + title + margins
237
+ estimatedContent += rowCount * 56 * density; // ~56dp per row
238
+ estimatedContent += (48 + 12 + 48 + 4) * density; // buttons + padding
239
+ estimatedContent += topSpacing * density;
240
+ if (targetHeight > estimatedContent) {
241
+ topSpacing += (targetHeight - estimatedContent) / density;
242
+ }
243
+ }
244
+
245
+ buttonContainer.setPadding(horizontalPadding, (int) (topSpacing * density), horizontalPadding, (int) (4 * density));
221
246
 
222
247
  int primaryColor = MaterialColors.getColor(ctx, android.R.attr.colorPrimary, 0xFF6750A4);
223
248
 
@@ -228,7 +253,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
228
253
  // Confirm button (filled style with purple background, white text)
229
254
  MaterialButton confirmBtn = new MaterialButton(ctx);
230
255
  confirmBtn.setText(confirmButton);
231
- confirmBtn.setOnClickListener(v -> {
256
+ confirmBtn.setOnClickListener((v) -> {
232
257
  handleConfirm();
233
258
  dismiss();
234
259
  });
@@ -237,7 +262,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
237
262
  } else {
238
263
  confirmBtn.setBackgroundTintList(ColorStateList.valueOf(primaryColor));
239
264
  }
240
- int onPrimaryColor = MaterialColors.getColor(ctx, com.google.android.material.R.attr.colorOnPrimary, 0xFFFFFFFF);
265
+ int onPrimaryColor = 0xFFFFFFFF;
241
266
  confirmBtn.setTextColor(ColorStateList.valueOf(onPrimaryColor));
242
267
  confirmBtn.setCornerRadius((int) (24 * density));
243
268
  confirmBtn.setMinHeight(buttonHeight);
@@ -246,19 +271,21 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
246
271
  confirmBtn.setTextSize(TypedValue.COMPLEX_UNIT_SP, styleOptions.getButtonFontSize());
247
272
  }
248
273
  LinearLayout.LayoutParams confirmParams = new LinearLayout.LayoutParams(
249
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
274
+ ViewGroup.LayoutParams.MATCH_PARENT,
275
+ ViewGroup.LayoutParams.WRAP_CONTENT
276
+ );
250
277
  confirmBtn.setLayoutParams(confirmParams);
251
278
  buttonContainer.addView(confirmBtn);
252
279
 
253
280
  // Cancel button (text-only style, no background fill)
254
281
  MaterialButton cancelBtn = new MaterialButton(ctx, null, android.R.attr.borderlessButtonStyle);
255
282
  cancelBtn.setText(cancelButton);
256
- cancelBtn.setOnClickListener(v -> {
283
+ cancelBtn.setOnClickListener((v) -> {
257
284
  handleCancel();
258
285
  dismiss();
259
286
  });
260
287
  cancelBtn.setBackgroundTintList(ColorStateList.valueOf(android.graphics.Color.TRANSPARENT));
261
- cancelBtn.setRippleColor(ColorStateList.valueOf(MaterialColors.getColor(ctx, com.google.android.material.R.attr.colorPrimary, 0xFF6750A4) & 0x1FFFFFFF));
288
+ cancelBtn.setRippleColor(ColorStateList.valueOf(primaryColor & 0x1FFFFFFF));
262
289
  if (styleOptions.getCancelButtonColor() != null) {
263
290
  cancelBtn.setTextColor(ColorStateList.valueOf(styleOptions.getCancelButtonColor()));
264
291
  } else {
@@ -270,7 +297,9 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
270
297
  cancelBtn.setTextSize(TypedValue.COMPLEX_UNIT_SP, styleOptions.getButtonFontSize());
271
298
  }
272
299
  LinearLayout.LayoutParams cancelParams = new LinearLayout.LayoutParams(
273
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
300
+ ViewGroup.LayoutParams.MATCH_PARENT,
301
+ ViewGroup.LayoutParams.WRAP_CONTENT
302
+ );
274
303
  cancelBtn.setLayoutParams(cancelParams);
275
304
  buttonContainer.addView(cancelBtn);
276
305
 
@@ -290,7 +319,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
290
319
  BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
291
320
  if (dialog == null) return;
292
321
 
293
- dialog.setOnShowListener(dialogInterface -> {
322
+ dialog.setOnShowListener((dialogInterface) -> {
294
323
  BottomSheetDialog d = (BottomSheetDialog) dialogInterface;
295
324
  FrameLayout bottomSheet = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
296
325
  if (bottomSheet == null) return;
@@ -315,12 +344,20 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
315
344
  });
316
345
  }
317
346
 
318
- private LinearLayout createSheetRow(Context context, JSONObject row, DialogStyleOptions styleOptions, float density, boolean showDivider) throws JSONException {
347
+ private LinearLayout createSheetRow(
348
+ Context context,
349
+ JSONObject row,
350
+ DialogStyleOptions styleOptions,
351
+ float density,
352
+ boolean showDivider
353
+ ) throws JSONException {
319
354
  LinearLayout rowLayout = new LinearLayout(context);
320
355
  rowLayout.setOrientation(LinearLayout.HORIZONTAL);
321
356
  rowLayout.setGravity(Gravity.CENTER_VERTICAL);
322
357
  LinearLayout.LayoutParams rowParams = new LinearLayout.LayoutParams(
323
- LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
358
+ LinearLayout.LayoutParams.MATCH_PARENT,
359
+ LinearLayout.LayoutParams.WRAP_CONTENT
360
+ );
324
361
  rowLayout.setLayoutParams(rowParams);
325
362
  rowLayout.setPadding(0, (int) (8 * density), 0, (int) (8 * density));
326
363
 
@@ -338,8 +375,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
338
375
  // Row title
339
376
  TextView rowTitle = new TextView(context);
340
377
  rowTitle.setText(row.getString("title"));
341
- TextViewCompat.setTextAppearance(rowTitle,
342
- com.google.android.material.R.style.TextAppearance_Material3_TitleMedium);
378
+ TextViewCompat.setTextAppearance(rowTitle, com.google.android.material.R.style.TextAppearance_Material3_TitleMedium);
343
379
  if (styleOptions.getMessageColor() != null) {
344
380
  rowTitle.setTextColor(styleOptions.getMessageColor());
345
381
  } else {
@@ -357,8 +393,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
357
393
  if (row.has("value") && !row.getString("value").isEmpty()) {
358
394
  TextView rowValue = new TextView(context);
359
395
  rowValue.setText(row.getString("value"));
360
- TextViewCompat.setTextAppearance(rowValue,
361
- com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
396
+ TextViewCompat.setTextAppearance(rowValue, com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
362
397
  int onSurfaceVariantColor = MaterialColors.getColor(context, android.R.attr.textColorSecondary, 0xFF49454F);
363
398
  rowValue.setTextColor(onSurfaceVariantColor);
364
399
  rowValue.setGravity(Gravity.END);
@@ -381,7 +416,9 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
381
416
  View divider = new View(context);
382
417
  divider.setBackgroundColor(MaterialColors.getColor(context, android.R.attr.listDivider, 0xFFE0E0E0));
383
418
  LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(
384
- LinearLayout.LayoutParams.MATCH_PARENT, (int) (1 * density));
419
+ LinearLayout.LayoutParams.MATCH_PARENT,
420
+ (int) (1 * density)
421
+ );
385
422
  divider.setLayoutParams(dividerParams);
386
423
  container.addView(divider);
387
424
  }
@@ -38,6 +38,28 @@ export interface DialogStyleOptions {
38
38
  * Font size for the button text in sp/pt (e.g., 14)
39
39
  */
40
40
  buttonFontSize?: number;
41
+ /**
42
+ * Vertical spacing between dialog content and the confirm/cancel buttons in dp/pt/px (e.g., 16).
43
+ * Only applies to fullscreen and sheet modes.
44
+ *
45
+ * @example
46
+ * // Fullscreen confirm with extra spacing between content and buttons
47
+ * await ExtendedDialog.confirm({
48
+ * title: 'Delete Account',
49
+ * message: 'This action cannot be undone.',
50
+ * mode: 'fullscreen',
51
+ * contentButtonSpacing: 32,
52
+ * });
53
+ *
54
+ * @example
55
+ * // Sheet with tight spacing
56
+ * await ExtendedDialog.sheet({
57
+ * title: 'Order Summary',
58
+ * rows: [{ title: 'Total', value: '$9.99' }],
59
+ * contentButtonSpacing: 8,
60
+ * });
61
+ */
62
+ contentButtonSpacing?: number;
41
63
  }
42
64
  export interface BaseDialogOptions extends DialogStyleOptions {
43
65
  /**
@@ -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\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 SheetResult {\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"]}
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\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 SheetResult {\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"]}