craft-native 0.0.492 → 0.0.497
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.
|
@@ -1313,13 +1313,7 @@ internal class CraftNativeChrome(
|
|
|
1313
1313
|
action.layoutParams = LayoutParams(dp(48), dp(48)).apply { marginStart = if (grouped) 0 else dp(8) }
|
|
1314
1314
|
}
|
|
1315
1315
|
accessory.layoutParams = LayoutParams(dp(if (grouped) 48 else 64), dp(if (grouped) 48 else 64)).apply { marginStart = if (grouped) 0 else dp(8) }
|
|
1316
|
-
|
|
1317
|
-
for (row in listOf(accessoryGroup, companionRow)) {
|
|
1318
|
-
row.showDividers = if (grouped) SHOW_DIVIDER_MIDDLE else SHOW_DIVIDER_NONE
|
|
1319
|
-
row.dividerDrawable = if (grouped) divider.constantState?.newDrawable() else null
|
|
1320
|
-
row.dividerPadding = dp(12)
|
|
1321
|
-
}
|
|
1322
|
-
// An empty companion row must not leave a divider above a single icon.
|
|
1316
|
+
// A group is one control: no divider between its actions, as on iOS.
|
|
1323
1317
|
companionRow.visibility = if (companionViews.isEmpty()) View.GONE else View.VISIBLE
|
|
1324
1318
|
}
|
|
1325
1319
|
|
package/dist/cli.js
CHANGED
|
@@ -3246,7 +3246,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
3246
3246
|
`);
|
|
3247
3247
|
}
|
|
3248
3248
|
// package.json
|
|
3249
|
-
var version = "0.0.
|
|
3249
|
+
var version = "0.0.497";
|
|
3250
3250
|
|
|
3251
3251
|
// bin/cli.ts
|
|
3252
3252
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -1248,7 +1248,9 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1248
1248
|
private var companionButtons: [UIButton] = []
|
|
1249
1249
|
private var companionModels: [CraftChrome.Tab] = []
|
|
1250
1250
|
private var companionGlasses: [UIVisualEffectView] = []
|
|
1251
|
-
|
|
1251
|
+
/// Whether the shared surface was last configured for a group; its
|
|
1252
|
+
/// material is replaced only when that changes, never on a badge update.
|
|
1253
|
+
private var accessorySurfaceGrouped: Bool?
|
|
1252
1254
|
private let accessoryBadge = UILabel()
|
|
1253
1255
|
private let accessoryGlass = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))
|
|
1254
1256
|
private static let tabPictures = NSCache<NSURL, UIImage>()
|
|
@@ -1506,7 +1508,6 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1506
1508
|
glass.clipsToBounds = true
|
|
1507
1509
|
glass.isUserInteractionEnabled = false
|
|
1508
1510
|
view.addSubview(glass)
|
|
1509
|
-
view.addSubview(button)
|
|
1510
1511
|
companionGlasses.append(glass)
|
|
1511
1512
|
companionButtons.append(button)
|
|
1512
1513
|
}
|
|
@@ -1515,22 +1516,22 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1515
1516
|
companionButtons[index].accessibilityTraits = chrome.accessorySelected(action) ? [.button, .selected] : [.button]
|
|
1516
1517
|
}
|
|
1517
1518
|
let grouped = model?.accessoryLayout != nil
|
|
1519
|
+
// A group is one control, as the map controls in Maps are: its
|
|
1520
|
+
// actions live inside the shared surface, so the glass lights the
|
|
1521
|
+
// one being pressed and keeps every symbol legible over the page.
|
|
1522
|
+
// Separate actions stay in the shell, each on its own surface.
|
|
1523
|
+
let actionHost: UIView = grouped ? accessoryGlass.contentView : view
|
|
1518
1524
|
for glass in companionGlasses { glass.isHidden = grouped }
|
|
1519
|
-
for button in companionButtons {
|
|
1525
|
+
for button in companionButtons {
|
|
1526
|
+
if button.superview !== actionHost { actionHost.addSubview(button) }
|
|
1527
|
+
button.tintColor = grouped ? .label : nil
|
|
1528
|
+
button.configuration?.preferredSymbolConfigurationForImage = Self.accessorySymbol(grouped: grouped)
|
|
1529
|
+
}
|
|
1520
1530
|
accessoryButton.tintColor = grouped ? .label : nil
|
|
1521
|
-
for separator in accessorySeparators { separator.removeFromSuperview() }
|
|
1522
|
-
accessorySeparators = grouped ? companionButtons.map { _ in
|
|
1523
|
-
let separator = UIView()
|
|
1524
|
-
separator.backgroundColor = .separator
|
|
1525
|
-
separator.isUserInteractionEnabled = false
|
|
1526
|
-
separator.isAccessibilityElement = false
|
|
1527
|
-
view.addSubview(separator)
|
|
1528
|
-
return separator
|
|
1529
|
-
} : []
|
|
1530
1531
|
if let model {
|
|
1531
1532
|
var configuration = UIButton.Configuration.plain()
|
|
1532
1533
|
configuration.image = UIImage(systemName: model.symbol)
|
|
1533
|
-
configuration.preferredSymbolConfigurationForImage =
|
|
1534
|
+
configuration.preferredSymbolConfigurationForImage = Self.accessorySymbol(grouped: grouped)
|
|
1534
1535
|
configuration.title = model.iconOnly ? nil : model.displayTitle
|
|
1535
1536
|
configuration.subtitle = model.iconOnly ? nil : model.badge
|
|
1536
1537
|
configuration.imagePadding = model.iconOnly ? 0 : 8
|
|
@@ -1559,22 +1560,17 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1559
1560
|
// Older systems have no bottom-accessory container. Keep the action
|
|
1560
1561
|
// available above the system bar, without recreating the tab control.
|
|
1561
1562
|
#if compiler(>=6.2)
|
|
1562
|
-
if #available(iOS 26.0, *) {
|
|
1563
|
-
bottomAccessory = nil
|
|
1564
|
-
accessoryGlass.effect = UIGlassEffect()
|
|
1565
|
-
}
|
|
1563
|
+
if #available(iOS 26.0, *) { bottomAccessory = nil }
|
|
1566
1564
|
#endif
|
|
1567
|
-
if model != nil,
|
|
1565
|
+
if model != nil, accessoryGlass.superview !== view || accessoryButton.superview !== actionHost {
|
|
1568
1566
|
accessoryButton.removeFromSuperview()
|
|
1569
|
-
view.addSubview(accessoryGlass)
|
|
1570
|
-
|
|
1567
|
+
if accessoryGlass.superview !== view { view.addSubview(accessoryGlass) }
|
|
1568
|
+
actionHost.addSubview(accessoryButton)
|
|
1571
1569
|
view.addSubview(accessoryBadge)
|
|
1572
1570
|
}
|
|
1573
1571
|
accessoryButton.isHidden = model == nil
|
|
1574
1572
|
accessoryGlass.isHidden = model == nil
|
|
1575
|
-
|
|
1576
|
-
accessoryGlass.layer.cornerRadius = grouped ? 26 : 24
|
|
1577
|
-
accessoryGlass.clipsToBounds = true
|
|
1573
|
+
configureAccessorySurface(grouped: grouped)
|
|
1578
1574
|
accessoryButton.backgroundColor = .clear
|
|
1579
1575
|
accessoryButton.layer.cornerRadius = 24
|
|
1580
1576
|
accessoryBadge.text = model?.badge
|
|
@@ -1591,15 +1587,63 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1591
1587
|
// companion-only update creates new controls or a shelf changes mode.
|
|
1592
1588
|
if accessoryGlass.superview === view {
|
|
1593
1589
|
view.bringSubviewToFront(accessoryGlass)
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1590
|
+
if !grouped {
|
|
1591
|
+
for button in companionButtons { view.bringSubviewToFront(button) }
|
|
1592
|
+
view.bringSubviewToFront(accessoryButton)
|
|
1593
|
+
}
|
|
1597
1594
|
view.bringSubviewToFront(accessoryBadge)
|
|
1598
1595
|
}
|
|
1599
1596
|
for nav in stacks.values { nav.additionalSafeAreaInsets.bottom = safeAreaForTabBar() }
|
|
1600
1597
|
view.setNeedsLayout()
|
|
1601
1598
|
}
|
|
1602
1599
|
|
|
1600
|
+
/// Symbols in a group carry the weight of the system's own map controls;
|
|
1601
|
+
/// a separate action keeps the lighter bar-button weight.
|
|
1602
|
+
private static func accessorySymbol(grouped: Bool) -> UIImage.SymbolConfiguration {
|
|
1603
|
+
UIImage.SymbolConfiguration(pointSize: grouped ? 20 : 22, weight: grouped ? .medium : .regular)
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
/// The surface under the floating actions. A group is a capsule of
|
|
1607
|
+
/// interactive Liquid Glass on iOS 26, shaped by the system so its rim,
|
|
1608
|
+
/// lensing and shadow are not clipped away; before iOS 26 it is the tab
|
|
1609
|
+
/// bar's material with a hairline. A single action stays a plain circle.
|
|
1610
|
+
private func configureAccessorySurface(grouped: Bool) {
|
|
1611
|
+
accessoryGlass.isUserInteractionEnabled = grouped
|
|
1612
|
+
if accessorySurfaceGrouped != grouped {
|
|
1613
|
+
accessorySurfaceGrouped = grouped
|
|
1614
|
+
var system = false
|
|
1615
|
+
#if compiler(>=6.2)
|
|
1616
|
+
if #available(iOS 26.0, *) {
|
|
1617
|
+
let glass = UIGlassEffect()
|
|
1618
|
+
glass.isInteractive = grouped
|
|
1619
|
+
accessoryGlass.effect = glass
|
|
1620
|
+
accessoryGlass.cornerConfiguration = grouped ? .capsule() : .corners(radius: 24)
|
|
1621
|
+
system = true
|
|
1622
|
+
}
|
|
1623
|
+
#endif
|
|
1624
|
+
if system {
|
|
1625
|
+
accessoryGlass.layer.cornerRadius = 0
|
|
1626
|
+
accessoryGlass.layer.borderWidth = 0
|
|
1627
|
+
accessoryGlass.clipsToBounds = false
|
|
1628
|
+
} else {
|
|
1629
|
+
accessoryGlass.effect = UIBlurEffect(style: grouped ? .systemUltraThinMaterial : .systemMaterial)
|
|
1630
|
+
accessoryGlass.layer.cornerCurve = .continuous
|
|
1631
|
+
accessoryGlass.layer.borderWidth = grouped ? 0.5 : 0
|
|
1632
|
+
accessoryGlass.layer.borderColor = UIColor.white.withAlphaComponent(0.35).cgColor
|
|
1633
|
+
accessoryGlass.clipsToBounds = true
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
// Before iOS 26 the capsule follows the group's shorter side.
|
|
1637
|
+
if accessoryGlass.clipsToBounds {
|
|
1638
|
+
accessoryGlass.layer.cornerRadius = grouped ? Self.accessoryGroupBreadth / 2 : 24
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
/// A group's breadth, and each action's length along it: the system map
|
|
1643
|
+
/// controls' proportions, every target at least 48 points.
|
|
1644
|
+
static let accessoryGroupBreadth: CGFloat = 48
|
|
1645
|
+
static let accessoryGroupStep: CGFloat = 52
|
|
1646
|
+
|
|
1603
1647
|
@objc private func openTabAccessory() {
|
|
1604
1648
|
if let accessoryModel { hybrid.open(accessoryModel.id) }
|
|
1605
1649
|
}
|
|
@@ -1617,6 +1661,11 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1617
1661
|
}
|
|
1618
1662
|
#endif
|
|
1619
1663
|
let iconOnly = accessoryModel?.iconOnly == true
|
|
1664
|
+
if let axis = accessoryModel?.accessoryLayout {
|
|
1665
|
+
layoutAccessoryGroup(vertical: axis == "vertical")
|
|
1666
|
+
CraftChrome.shared.layoutChanged(tabBar.isHidden ? 0 : max(0, view.bounds.maxY - tabBar.frame.minY))
|
|
1667
|
+
return
|
|
1668
|
+
}
|
|
1620
1669
|
let height: CGFloat = iconOnly ? 48 : 44
|
|
1621
1670
|
let width: CGFloat = iconOnly ? 48 : max(0, view.bounds.width - 32)
|
|
1622
1671
|
let trailingX = view.effectiveUserInterfaceLayoutDirection == .rightToLeft
|
|
@@ -1624,25 +1673,12 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1624
1673
|
let x = iconOnly ? trailingX : 16
|
|
1625
1674
|
accessoryButton.frame = CGRect(x: x, y: tabBar.frame.minY - height - (iconOnly ? 8 : 0), width: width, height: height)
|
|
1626
1675
|
accessoryGlass.frame = accessoryButton.frame
|
|
1627
|
-
let layout = accessoryModel?.accessoryLayout
|
|
1628
1676
|
for (index, button) in companionButtons.enumerated() {
|
|
1629
1677
|
let offset = CGFloat(companionButtons.count - index)
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
} else {
|
|
1633
|
-
let direction: CGFloat = view.effectiveUserInterfaceLayoutDirection == .rightToLeft ? 1 : -1
|
|
1634
|
-
button.frame = accessoryButton.frame.offsetBy(dx: direction * offset * (width + (layout == nil ? 12 : 0)), dy: 0)
|
|
1635
|
-
}
|
|
1678
|
+
let direction: CGFloat = view.effectiveUserInterfaceLayoutDirection == .rightToLeft ? 1 : -1
|
|
1679
|
+
button.frame = accessoryButton.frame.offsetBy(dx: direction * offset * (width + 12), dy: 0)
|
|
1636
1680
|
companionGlasses[index].frame = button.frame
|
|
1637
|
-
if layout != nil {
|
|
1638
|
-
accessoryGlass.frame = accessoryGlass.frame.union(button.frame)
|
|
1639
|
-
let line = 1 / (view.window?.screen.scale ?? 2)
|
|
1640
|
-
accessorySeparators[index].frame = layout == "vertical"
|
|
1641
|
-
? CGRect(x: button.frame.minX + 12, y: button.frame.maxY - line / 2, width: width - 24, height: line)
|
|
1642
|
-
: CGRect(x: view.effectiveUserInterfaceLayoutDirection == .rightToLeft ? button.frame.minX : button.frame.maxX - line / 2, y: button.frame.minY + 12, width: line, height: height - 24)
|
|
1643
|
-
}
|
|
1644
1681
|
}
|
|
1645
|
-
if layout != nil { accessoryGlass.frame = accessoryGlass.frame.insetBy(dx: -2, dy: -2) }
|
|
1646
1682
|
let badgeWidth = max(18, accessoryBadge.intrinsicContentSize.width + 8)
|
|
1647
1683
|
accessoryBadge.frame = CGRect(x: accessoryButton.frame.maxX - badgeWidth + 4, y: accessoryButton.frame.minY - 3, width: badgeWidth, height: 18)
|
|
1648
1684
|
// A compact action floats over the page, not across its whole width.
|
|
@@ -1651,6 +1687,31 @@ final class CraftHybridController: UITabBarController, UITabBarControllerDelegat
|
|
|
1651
1687
|
CraftChrome.shared.layoutChanged(tabBar.isHidden ? 0 : max(0, view.bounds.maxY - tabBar.frame.minY) + accessoryInset)
|
|
1652
1688
|
}
|
|
1653
1689
|
|
|
1690
|
+
/// One capsule above the trailing end of the tab bar, companions first
|
|
1691
|
+
/// and the primary action last. Nothing divides the actions: the glass
|
|
1692
|
+
/// is one control, and each action is found by its place and its symbol.
|
|
1693
|
+
private func layoutAccessoryGroup(vertical: Bool) {
|
|
1694
|
+
let breadth = Self.accessoryGroupBreadth
|
|
1695
|
+
let step = Self.accessoryGroupStep
|
|
1696
|
+
let buttons = companionButtons + [accessoryButton]
|
|
1697
|
+
let length = step * CGFloat(buttons.count)
|
|
1698
|
+
let size = vertical ? CGSize(width: breadth, height: length) : CGSize(width: length, height: breadth)
|
|
1699
|
+
let rightToLeft = view.effectiveUserInterfaceLayoutDirection == .rightToLeft
|
|
1700
|
+
// The tab bar's own platter sits this far in from the screen's edge.
|
|
1701
|
+
let margin: CGFloat = 22
|
|
1702
|
+
let x = rightToLeft ? view.safeAreaInsets.left + margin : view.bounds.maxX - view.safeAreaInsets.right - size.width - margin
|
|
1703
|
+
accessoryGlass.frame = CGRect(x: x, y: tabBar.frame.minY - size.height - 10, width: size.width, height: size.height)
|
|
1704
|
+
for (index, button) in buttons.enumerated() {
|
|
1705
|
+
let place = CGFloat(rightToLeft && !vertical ? buttons.count - 1 - index : index) * step
|
|
1706
|
+
button.frame = vertical
|
|
1707
|
+
? CGRect(x: 0, y: place, width: breadth, height: step)
|
|
1708
|
+
: CGRect(x: place, y: 0, width: step, height: breadth)
|
|
1709
|
+
}
|
|
1710
|
+
let badgeWidth = max(18, accessoryBadge.intrinsicContentSize.width + 8)
|
|
1711
|
+
let primary = accessoryButton.convert(accessoryButton.bounds, to: view)
|
|
1712
|
+
accessoryBadge.frame = CGRect(x: primary.maxX - badgeWidth + 4, y: primary.minY - 3, width: badgeWidth, height: 18)
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1654
1715
|
private var webAttached = false
|
|
1655
1716
|
|
|
1656
1717
|
private func installTabSwipeGestures() {
|