@lmb-it/kitsconcerto-native 0.1.286 → 0.1.287

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.
@@ -85,7 +85,9 @@ function ImageCropper(rawProps) {
85
85
  ratio,
86
86
  maxZoom,
87
87
  // ⚠️ ALWAYS FALSE ON NATIVE — see the note at the top of the file.
88
- resizable: false
88
+ resizable: false,
89
+ inset: constants.STAGE_INSET_NATIVE,
90
+ squareFactor: constants.SQUARE_CROP_FACTOR
89
91
  }),
90
92
  [image, viewport, ratio, maxZoom]
91
93
  );
@@ -250,186 +252,388 @@ function ImageCropper(rawProps) {
250
252
  const { crop, transform, rotation } = state;
251
253
  const oriented = image ? geometry.orientedSize({ width: image.width, height: image.height }, rotation) : null;
252
254
  const band = cropperState.scaleRange(state);
253
- const zoomLabel = Number.isFinite(band.min) && band.min > 0 ? `${(transform.scale / band.min).toFixed(1)}\xD7` : "1.0\xD7";
255
+ const zoomLabel = Number.isFinite(band.min) && band.min > 0 ? `${Math.round(transform.scale / band.min * 100)}%` : "100%";
254
256
  const windowRadius = isCircle ? Math.max(crop.width, crop.height) / 2 : Number(el.mask?.borderRadius ?? 0);
255
257
  const SCRIM = Math.ceil(Math.max(viewport.width, viewport.height)) || 1;
256
- const toolButton = (icon, label, onPress, disabled) => /* @__PURE__ */ jsxRuntime.jsxs(
258
+ const aspectLabel = `${aspect[0]}:${aspect[1]}`;
259
+ const subtitle = ready ? "Drag to move \xB7 pinch to zoom" : isCircle ? `Circle \xB7 ${aspectLabel}` : `Banner \xB7 ${aspectLabel}`;
260
+ const budgetKb = Math.round((output?.maxBytes ?? constants.DEFAULT_MAX_BYTES) / 1024);
261
+ const previewWidth = isCircle ? 60 : 160;
262
+ const previewHeight = isCircle ? 60 : Math.round(160 / ratio);
263
+ const stageTool = (icon, label, onPress) => /* @__PURE__ */ jsxRuntime.jsxs(
257
264
  reactNative.Pressable,
258
265
  {
259
266
  onPress,
260
- disabled,
267
+ disabled: !ready,
261
268
  accessibilityRole: "button",
262
269
  accessibilityLabel: label,
263
- accessibilityState: { disabled: !!disabled },
264
- style: {
265
- flexDirection: "row",
266
- alignItems: "center",
267
- gap: 6,
268
- paddingHorizontal: 8,
269
- paddingVertical: 8,
270
- opacity: disabled ? 0.5 : 1
271
- },
270
+ accessibilityState: { disabled: !ready },
271
+ style: { width: 58, alignItems: "center", gap: 4 },
272
272
  children: [
273
- /* @__PURE__ */ jsxRuntime.jsx(index_native.Icon, { name: icon, size: "sm", color: el.icon?.color }),
274
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: el.text, children: label })
273
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: {
274
+ width: 44,
275
+ height: 44,
276
+ borderRadius: 22,
277
+ backgroundColor: "rgba(255,255,255,0.09)",
278
+ alignItems: "center",
279
+ justifyContent: "center"
280
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(index_native.Icon, { name: icon, size: 19, color: "#FFFFFF" }) }),
281
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 11, fontWeight: "600", color: "rgba(255,255,255,0.75)" }, children: label })
275
282
  ]
276
283
  }
277
284
  );
278
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID, style: [{ width: "100%" }, el.root], children: [
279
- title != null && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [{ flexDirection: "row", alignItems: "center" }, el.header], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: el.title, children: title }) }),
280
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [el.content], children: !source || error ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [{ alignItems: "center" }, el.dropZone], children: [
281
- /* @__PURE__ */ jsxRuntime.jsx(index_native.Icon, { name: "image", size: "lg", color: el.icon?.color }),
282
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: el.text, children: error ? error.message : text.dropZone })
283
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
284
- /* @__PURE__ */ jsxRuntime.jsx(StageFrame, { gesture: detector, children: /* @__PURE__ */ jsxRuntime.jsxs(
285
- reactNative.View,
286
- {
287
- ref: stageRef,
288
- onLayout: onStageLayout,
289
- ...detector ? scrollBlocker.panHandlers : responder.panHandlers,
290
- style: [{ width: "100%", aspectRatio: 4 / 3, overflow: "hidden" }, el.container],
291
- children: [
292
- ready && image && oriented && /* @__PURE__ */ jsxRuntime.jsx(
293
- reactNative.Image,
294
- {
295
- source: { uri: image.uri },
296
- resizeMode: "stretch",
297
- style: {
298
- position: "absolute",
299
- left: transform.x,
300
- top: transform.y,
301
- width: oriented.width * transform.scale,
302
- height: oriented.height * transform.scale,
303
- transform: [{ rotate: `${rotation}deg` }]
304
- }
305
- }
306
- ),
307
- ready && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
308
- /* @__PURE__ */ jsxRuntime.jsx(
309
- reactNative.View,
310
- {
311
- pointerEvents: "none",
312
- style: [
313
- {
285
+ return /* @__PURE__ */ jsxRuntime.jsxs(
286
+ reactNative.View,
287
+ {
288
+ testID,
289
+ style: [
290
+ /**
291
+ * ⚠️ NO `flex: 1` HERE, THOUGH THE MOCKUP IS FULL-SCREEN. A
292
+ * child with `flex: 1` inside a parent that was never given a
293
+ * height measures 0 on Yoga, and this component does not own
294
+ * the screen — a consumer mounts it in a modal, a sheet or a
295
+ * form. The footer's `marginTop: 'auto'` gets the mockup's
296
+ * pinned-to-the-bottom footer when the parent DOES bound the
297
+ * height, and does nothing when it does not.
298
+ */
299
+ { width: "100%" },
300
+ el.root,
301
+ /**
302
+ * ⛔ THE PHONE CROPPER IS A DARK SHEET, AND THAT OVERRIDES THE
303
+ * `root` SLOT ON NATIVE ONLY. The mockup draws web as a light
304
+ * modal card and the phone as a full-screen dark surface, and
305
+ * one `root` token cannot be both. It has to be the dark one
306
+ * here because the controls below it are load-bearing white:
307
+ * on a light sheet the Rotate and Reset labels vanish.
308
+ *
309
+ * ⚠️ SO `slots.root.backgroundColor` DOES NOT REACH THIS ON
310
+ * NATIVE. That is the deliberate cost; the stage's own colour
311
+ * has carried the same argument since the component shipped.
312
+ */
313
+ { backgroundColor: "#0B1517" }
314
+ ],
315
+ children: [
316
+ title != null && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
317
+ { alignItems: "center" },
318
+ el.header,
319
+ {
320
+ paddingLeft: 18,
321
+ paddingRight: 18,
322
+ paddingTop: 12,
323
+ paddingBottom: 14,
324
+ borderBottomWidth: 0,
325
+ gap: 0
326
+ }
327
+ ], children: [
328
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [el.title, { fontSize: 16, fontWeight: "800", color: "#FFFFFF" }], children: title }),
329
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { marginTop: 3, fontSize: 12, color: "rgba(255,255,255,0.6)" }, children: subtitle })
330
+ ] }),
331
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [el.content, { paddingLeft: 0, paddingRight: 0, paddingTop: 0, paddingBottom: 0 }], children: [
332
+ /* @__PURE__ */ jsxRuntime.jsx(StageFrame, { gesture: detector, children: /* @__PURE__ */ jsxRuntime.jsxs(
333
+ reactNative.View,
334
+ {
335
+ ref: stageRef,
336
+ onLayout: onStageLayout,
337
+ ...detector ? scrollBlocker.panHandlers : responder.panHandlers,
338
+ style: [
339
+ { width: "100%", aspectRatio: constants.STAGE_ASPECT_NATIVE, overflow: "hidden" },
340
+ el.container
341
+ ],
342
+ children: [
343
+ ready && image && oriented && /* @__PURE__ */ jsxRuntime.jsx(
344
+ reactNative.Image,
345
+ {
346
+ source: { uri: image.uri },
347
+ resizeMode: "stretch",
348
+ style: {
314
349
  position: "absolute",
315
- left: crop.x - SCRIM,
316
- top: crop.y - SCRIM,
317
- width: crop.width + SCRIM * 2,
318
- height: crop.height + SCRIM * 2,
319
- borderWidth: SCRIM,
320
- borderColor: el.shade?.backgroundColor ?? "rgba(0,0,0,0.6)",
321
- borderRadius: windowRadius + SCRIM
350
+ left: transform.x,
351
+ top: transform.y,
352
+ width: oriented.width * transform.scale,
353
+ height: oriented.height * transform.scale,
354
+ transform: [{ rotate: `${rotation}deg` }]
355
+ }
356
+ }
357
+ ),
358
+ (!source || error) && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
359
+ {
360
+ position: "absolute",
361
+ left: 18,
362
+ top: 18,
363
+ right: 18,
364
+ bottom: 18,
365
+ alignItems: "center",
366
+ justifyContent: "center"
367
+ },
368
+ el.dropZone,
369
+ { borderRadius: 18 }
370
+ ], children: [
371
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: {
372
+ width: 60,
373
+ height: 60,
374
+ borderRadius: 30,
375
+ backgroundColor: "rgba(32,170,176,0.16)",
376
+ alignItems: "center",
377
+ justifyContent: "center"
378
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(index_native.Icon, { name: "image", size: 26, color: constants.CROP_ACCENT_SOFT }) }),
379
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 16, fontWeight: "800", color: "#FFFFFF", textAlign: "center" }, children: text.dropZone }),
380
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 12.5, color: "rgba(255,255,255,0.6)", textAlign: "center" }, children: "JPG, PNG or WebP" }),
381
+ error && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: {
382
+ fontSize: 12.5,
383
+ fontWeight: "600",
384
+ color: constants.CROP_DANGER,
385
+ textAlign: "center"
386
+ }, children: error.message })
387
+ ] }),
388
+ ready && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
389
+ /* @__PURE__ */ jsxRuntime.jsx(
390
+ reactNative.View,
391
+ {
392
+ pointerEvents: "none",
393
+ style: [
394
+ {
395
+ position: "absolute",
396
+ left: crop.x - SCRIM,
397
+ top: crop.y - SCRIM,
398
+ width: crop.width + SCRIM * 2,
399
+ height: crop.height + SCRIM * 2,
400
+ borderWidth: SCRIM,
401
+ borderColor: el.shade?.backgroundColor ?? "rgba(0,0,0,0.6)",
402
+ borderRadius: windowRadius + SCRIM
403
+ }
404
+ ]
405
+ }
406
+ ),
407
+ /* @__PURE__ */ jsxRuntime.jsx(
408
+ reactNative.View,
409
+ {
410
+ pointerEvents: "none",
411
+ style: [
412
+ {
413
+ position: "absolute",
414
+ left: crop.x,
415
+ top: crop.y,
416
+ width: crop.width,
417
+ height: crop.height,
418
+ borderStyle: "solid"
419
+ },
420
+ el.cropWindow,
421
+ { borderRadius: windowRadius }
422
+ ],
423
+ children: !hideGrid && [1, 2].map((n) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
424
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
425
+ {
426
+ position: "absolute",
427
+ top: 0,
428
+ bottom: 0,
429
+ width: 1,
430
+ left: crop.width * n / 3
431
+ },
432
+ el.gridLine
433
+ ] }),
434
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
435
+ {
436
+ position: "absolute",
437
+ left: 0,
438
+ right: 0,
439
+ height: 1,
440
+ top: crop.height * n / 3
441
+ },
442
+ el.gridLine
443
+ ] })
444
+ ] }, n))
322
445
  }
323
- ]
324
- }
325
- ),
326
- /* @__PURE__ */ jsxRuntime.jsx(
327
- reactNative.View,
328
- {
329
- pointerEvents: "none",
330
- style: [
446
+ ),
447
+ /* @__PURE__ */ jsxRuntime.jsx(
448
+ reactNative.View,
331
449
  {
450
+ pointerEvents: "none",
451
+ style: { position: "absolute", top: 12, left: 0, right: 0, alignItems: "center" },
452
+ children: /* @__PURE__ */ jsxRuntime.jsx(
453
+ reactNative.View,
454
+ {
455
+ style: [
456
+ { alignItems: "center", justifyContent: "center" },
457
+ el.zoomChip
458
+ ],
459
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: {
460
+ color: el.zoomChip?.color ?? "#FFFFFF",
461
+ fontSize: 11.5,
462
+ fontWeight: "700"
463
+ }, children: zoomLabel })
464
+ }
465
+ )
466
+ }
467
+ )
468
+ ] }),
469
+ (loading || busy) && /* @__PURE__ */ jsxRuntime.jsxs(
470
+ reactNative.View,
471
+ {
472
+ pointerEvents: "none",
473
+ style: {
332
474
  position: "absolute",
333
- left: crop.x,
334
- top: crop.y,
335
- width: crop.width,
336
- height: crop.height,
337
- borderStyle: "solid"
475
+ left: 0,
476
+ top: 0,
477
+ right: 0,
478
+ bottom: 0,
479
+ backgroundColor: "rgba(6,14,16,0.74)",
480
+ alignItems: "center",
481
+ justifyContent: "center",
482
+ gap: 14
338
483
  },
339
- el.cropWindow,
340
- { borderRadius: windowRadius }
341
- ],
342
- children: !hideGrid && [1, 2].map((n) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
343
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
344
- {
345
- position: "absolute",
346
- top: 0,
347
- bottom: 0,
348
- width: 1,
349
- left: crop.width * n / 3
350
- },
351
- el.gridLine
352
- ] }),
353
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
354
- {
355
- position: "absolute",
356
- left: 0,
357
- right: 0,
358
- height: 1,
359
- top: crop.height * n / 3
360
- },
361
- el.gridLine
362
- ] })
363
- ] }, n))
364
- }
365
- ),
366
- /* @__PURE__ */ jsxRuntime.jsx(
367
- reactNative.View,
368
- {
369
- pointerEvents: "none",
370
- style: [{ position: "absolute", right: 8, bottom: 8 }, el.zoomChip],
371
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { color: el.zoomChip?.color }, children: zoomLabel })
372
- }
373
- )
374
- ] }),
375
- (loading || busy) && /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [{ position: "absolute", left: 0, right: 0, bottom: 0 }, el.progressFill] })
376
- ]
377
- }
378
- ) }),
379
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
380
- /* @__PURE__ */ jsxRuntime.jsx(index_native.Icon, { name: "zoom-in", size: "sm", color: el.icon?.color }),
381
- /* @__PURE__ */ jsxRuntime.jsx(
382
- Slider,
383
- {
384
- style: { flex: 1 },
385
- minimumValue: 0,
386
- maximumValue: 1,
387
- value: cropperState.zoomFraction(state),
388
- disabled: !ready,
389
- minimumTrackTintColor: el.thumb?.backgroundColor,
390
- maximumTrackTintColor: el.track?.backgroundColor,
391
- thumbTintColor: el.thumb?.backgroundColor,
392
- onValueChange: (value) => dispatch({ type: "setZoom", value })
393
- }
394
- ),
395
- !hidePreview && ready && image && oriented && /* The preview is the same image, clipped and offset so the
396
- crop fills the frame — no pixel work, and therefore
397
- nothing that has to wait for an encoder. */
398
- /* @__PURE__ */ jsxRuntime.jsx(
399
- reactNative.View,
484
+ children: [
485
+ /* @__PURE__ */ jsxRuntime.jsx(
486
+ reactNative.ActivityIndicator,
487
+ {
488
+ size: "large",
489
+ color: el.progressFill?.backgroundColor ?? constants.CROP_ACCENT
490
+ }
491
+ ),
492
+ busy && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 14, fontWeight: "700", color: "#FFFFFF" }, children: text.processing })
493
+ ]
494
+ }
495
+ )
496
+ ]
497
+ }
498
+ ) }),
499
+ /* @__PURE__ */ jsxRuntime.jsxs(
500
+ reactNative.View,
501
+ {
502
+ pointerEvents: ready ? "auto" : "none",
503
+ style: {
504
+ paddingTop: 16,
505
+ paddingLeft: 18,
506
+ paddingRight: 18,
507
+ gap: 16,
508
+ opacity: ready ? 1 : 0.4
509
+ },
510
+ children: [
511
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
512
+ !hidePreview && ready && image && oriented && /* The preview is the same image, clipped and offset so the
513
+ crop fills the frame — no pixel work, and therefore
514
+ nothing that has to wait for an encoder. */
515
+ /* @__PURE__ */ jsxRuntime.jsx(
516
+ reactNative.View,
517
+ {
518
+ style: [
519
+ { width: previewWidth, height: previewHeight, overflow: "hidden" },
520
+ el.previewFrame,
521
+ isCircle ? { borderRadius: previewWidth / 2 } : null,
522
+ /* ⚠️ A 2px RING, NOT THE CARD'S 4. The slot
523
+ carries the desktop preview's ring; at 60pt
524
+ a 4pt ring eats the thumbnail. */
525
+ { borderWidth: 2 },
526
+ /* The mockup's float, in the native spelling —
527
+ `boxShadow` is the web file's half of this. */
528
+ {
529
+ shadowColor: "#000000",
530
+ shadowOpacity: 0.14,
531
+ shadowRadius: 14,
532
+ shadowOffset: { width: 0, height: 4 },
533
+ elevation: 4
534
+ }
535
+ ],
536
+ children: /* @__PURE__ */ jsxRuntime.jsx(
537
+ reactNative.Image,
538
+ {
539
+ source: { uri: image.uri },
540
+ resizeMode: "stretch",
541
+ style: {
542
+ position: "absolute",
543
+ width: oriented.width * transform.scale * (previewWidth / crop.width),
544
+ height: oriented.height * transform.scale * (previewWidth / crop.width),
545
+ left: (transform.x - crop.x) * (previewWidth / crop.width),
546
+ top: (transform.y - crop.y) * (previewWidth / crop.width),
547
+ transform: [{ rotate: `${rotation}deg` }]
548
+ }
549
+ }
550
+ )
551
+ }
552
+ ),
553
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flex: 1, alignItems: "flex-end" }, children: [
554
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 17, fontWeight: "800", color: "#FFFFFF" }, children: zoomLabel }),
555
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { marginTop: 2, fontSize: 11.5, color: "rgba(255,255,255,0.6)" }, children: `Under ${budgetKb} KB` })
556
+ ] })
557
+ ] }),
558
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center", gap: 10 }, children: [
559
+ stageTool("rotate-cw", text.rotate, () => dispatch({ type: "rotate" })),
560
+ /* @__PURE__ */ jsxRuntime.jsx(
561
+ Slider,
562
+ {
563
+ style: { flex: 1 },
564
+ minimumValue: 0,
565
+ maximumValue: 1,
566
+ value: cropperState.zoomFraction(state),
567
+ disabled: !ready,
568
+ minimumTrackTintColor: el.thumb?.backgroundColor,
569
+ maximumTrackTintColor: el.track?.backgroundColor,
570
+ thumbTintColor: el.thumb?.backgroundColor,
571
+ onValueChange: (value) => dispatch({ type: "setZoom", value })
572
+ }
573
+ ),
574
+ stageTool("rotate-ccw", text.reset, () => dispatch({ type: "reset" }))
575
+ ] })
576
+ ]
577
+ }
578
+ )
579
+ ] }),
580
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
581
+ { flexDirection: "row", alignItems: "center", marginTop: "auto" },
582
+ el.footer,
400
583
  {
401
- style: [
402
- { width: 64, height: 64, overflow: "hidden" },
403
- el.previewFrame,
404
- isCircle ? { borderRadius: 32 } : null
405
- ],
406
- children: /* @__PURE__ */ jsxRuntime.jsx(
407
- reactNative.Image,
408
- {
409
- source: { uri: image.uri },
410
- resizeMode: "stretch",
411
- style: {
412
- position: "absolute",
413
- width: oriented.width * transform.scale * (64 / crop.width),
414
- height: oriented.height * transform.scale * (64 / crop.width),
415
- left: (transform.x - crop.x) * (64 / crop.width),
416
- top: (transform.y - crop.y) * (64 / crop.width),
417
- transform: [{ rotate: `${rotation}deg` }]
418
- }
419
- }
420
- )
584
+ paddingLeft: 18,
585
+ paddingRight: 18,
586
+ paddingTop: 12,
587
+ paddingBottom: 28,
588
+ borderTopWidth: 1,
589
+ borderTopColor: "rgba(255,255,255,0.08)",
590
+ gap: 12
421
591
  }
422
- )
423
- ] })
424
- ] }) }),
425
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [{ flexDirection: "row", alignItems: "center" }, el.footer], children: [
426
- toolButton("rotate-cw", text.rotate, () => dispatch({ type: "rotate" }), !ready),
427
- toolButton("rotate-ccw", text.reset, () => dispatch({ type: "reset" }), !ready),
428
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { flex: 1 } }),
429
- toolButton("x", text.cancel, () => onCancel?.()),
430
- toolButton("check", busy ? text.processing : text.save, () => void save(), !canSave)
431
- ] })
432
- ] });
592
+ ], children: [
593
+ /* @__PURE__ */ jsxRuntime.jsx(
594
+ reactNative.Pressable,
595
+ {
596
+ onPress: () => onCancel?.(),
597
+ accessibilityRole: "button",
598
+ accessibilityLabel: text.cancel,
599
+ style: {
600
+ flex: 1,
601
+ height: 52,
602
+ borderRadius: 26,
603
+ backgroundColor: "rgba(255,255,255,0.1)",
604
+ alignItems: "center",
605
+ justifyContent: "center"
606
+ },
607
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 15, fontWeight: "700", color: "#FFFFFF" }, children: text.cancel })
608
+ }
609
+ ),
610
+ /* @__PURE__ */ jsxRuntime.jsx(
611
+ reactNative.Pressable,
612
+ {
613
+ onPress: () => void save(),
614
+ disabled: !canSave,
615
+ accessibilityRole: "button",
616
+ accessibilityLabel: text.save,
617
+ accessibilityState: { disabled: !canSave },
618
+ style: {
619
+ flex: 1.4,
620
+ height: 52,
621
+ borderRadius: 26,
622
+ backgroundColor: canSave ? constants.CROP_ACCENT : "rgba(32,170,176,0.35)",
623
+ alignItems: "center",
624
+ justifyContent: "center"
625
+ },
626
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: {
627
+ fontSize: 15,
628
+ fontWeight: "800",
629
+ color: canSave ? "#FFFFFF" : "rgba(255,255,255,0.55)"
630
+ }, children: busy ? text.processing : text.save })
631
+ }
632
+ )
633
+ ] })
634
+ ]
635
+ }
636
+ );
433
637
  }
434
638
 
435
639
  exports.ImageCropper = ImageCropper;