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 +9 -0
- package/android/src/main/java/com/albermonte/extendeddialog/DialogStyleOptions.java +3 -1
- package/android/src/main/java/com/albermonte/extendeddialog/ExtendedDialog.java +4 -0
- package/android/src/main/java/com/albermonte/extendeddialog/ExtendedDialogPlugin.java +4 -0
- package/android/src/main/java/com/albermonte/extendeddialog/SheetBottomDialogFragment.java +191 -43
- package/dist/docs.json +14 -0
- package/dist/esm/definitions.d.ts +4 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.js +27 -12
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +27 -12
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +27 -12
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/ExtendedDialogPlugin/ExtendedDialog.swift +9 -4
- package/ios/Sources/ExtendedDialogPlugin/ExtendedDialogPlugin.swift +4 -0
- package/ios/Sources/ExtendedDialogPlugin/FullScreenDialogViewController.swift +43 -2
- package/package.json +1 -1
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)
|
|
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
|
-
|
|
151
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
447
|
+
rootLayout.addView(buttonContainer);
|
|
384
448
|
|
|
385
|
-
return
|
|
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
|
-
//
|
|
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(
|
|
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
|
|
547
|
+
int btnHeight = 0;
|
|
449
548
|
if (buttonContainer != null) {
|
|
450
549
|
buttonContainer.measure(widthSpec, heightSpec);
|
|
451
|
-
|
|
550
|
+
btnHeight = buttonContainer.getMeasuredHeight();
|
|
452
551
|
}
|
|
453
552
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
int
|
|
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
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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.
|
|
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"]}
|