panelui-native 0.32.0 → 0.34.0

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.
Files changed (35) hide show
  1. package/lib/module/components/button/index.js +106 -11
  2. package/lib/module/components/button/index.js.map +1 -1
  3. package/lib/module/components/drawer/index.js +477 -0
  4. package/lib/module/components/drawer/index.js.map +1 -0
  5. package/lib/module/components/panelside/index.js +1024 -0
  6. package/lib/module/components/panelside/index.js.map +1 -0
  7. package/lib/module/components/select/index.js +14 -3
  8. package/lib/module/components/select/index.js.map +1 -1
  9. package/lib/module/icons/index.js +20 -0
  10. package/lib/module/icons/index.js.map +1 -1
  11. package/lib/module/index.js +3 -1
  12. package/lib/module/index.js.map +1 -1
  13. package/lib/module/native/index.js +30 -0
  14. package/lib/module/native/index.js.map +1 -1
  15. package/lib/typescript/src/components/button/index.d.ts +22 -1
  16. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  17. package/lib/typescript/src/components/drawer/index.d.ts +146 -0
  18. package/lib/typescript/src/components/drawer/index.d.ts.map +1 -0
  19. package/lib/typescript/src/components/panelside/index.d.ts +354 -0
  20. package/lib/typescript/src/components/panelside/index.d.ts.map +1 -0
  21. package/lib/typescript/src/components/select/index.d.ts.map +1 -1
  22. package/lib/typescript/src/icons/index.d.ts +1 -0
  23. package/lib/typescript/src/icons/index.d.ts.map +1 -1
  24. package/lib/typescript/src/index.d.ts +3 -1
  25. package/lib/typescript/src/index.d.ts.map +1 -1
  26. package/lib/typescript/src/native/index.d.ts +20 -0
  27. package/lib/typescript/src/native/index.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/button/index.tsx +140 -8
  30. package/src/components/drawer/index.tsx +662 -0
  31. package/src/components/panelside/index.tsx +1358 -0
  32. package/src/components/select/index.tsx +23 -3
  33. package/src/icons/index.tsx +14 -0
  34. package/src/index.ts +33 -0
  35. package/src/native/index.ts +51 -0
@@ -514,10 +514,20 @@ function SelectRoot({
514
514
 
515
515
  {open && overlayPosition ? (
516
516
  <Portal>
517
- {/* Full-screen catcher so a press anywhere else dismisses the list. */}
517
+ {/*
518
+ * Full-screen catcher so a press anywhere else dismisses the list.
519
+ *
520
+ * Hidden from assistive tech, and deliberately: it is a dismiss
521
+ * affordance for a pointer, and announcing it would put an unlabelled
522
+ * full-screen "button" ahead of the options in the reading order,
523
+ * where swiping through the list would land on it before the first
524
+ * one. Escaping the list is the back gesture's job, and on iOS the
525
+ * modal flag's.
526
+ */}
518
527
  <Pressable
519
- accessibilityRole="button"
520
- accessibilityLabel="Close"
528
+ accessible={false}
529
+ importantForAccessibility="no-hide-descendants"
530
+ accessibilityElementsHidden
521
531
  onPress={close}
522
532
  style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
523
533
  />
@@ -527,6 +537,16 @@ function SelectRoot({
527
537
  exiting={FadeOut.duration(120)}
528
538
  onLayout={onListLayout}
529
539
  style={overlayPosition}
540
+ /*
541
+ * The floating list is a modal layer, the same as the sheet
542
+ * presentation's is — it covers the screen with a catcher and
543
+ * takes the back button. Without this the page behind it stays
544
+ * in the accessibility tree, so a screen reader could walk out
545
+ * of the open list into content the list is covering and act on
546
+ * it. The sheet gets this from BottomSheet; the anchored list
547
+ * has to say it itself.
548
+ */
549
+ accessibilityViewIsModal
530
550
  className={slots.list()}
531
551
  >
532
552
  {search}
@@ -231,6 +231,20 @@ export function EllipsisIcon({ size = 16, color, ...props }: IconProps) {
231
231
  );
232
232
  }
233
233
 
234
+ export function MenuIcon({ size = 20, color, ...props }: IconProps) {
235
+ const resolved = useResolvedColor(color, '#737373');
236
+ return (
237
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
238
+ <Path
239
+ d="M4 6h16M4 12h16M4 18h16"
240
+ stroke={resolved}
241
+ strokeWidth={2}
242
+ strokeLinecap="round"
243
+ />
244
+ </Svg>
245
+ );
246
+ }
247
+
234
248
  export function XIcon({ size = 16, color, ...props }: IconProps) {
235
249
  const resolved = useResolvedColor(color, '#737373');
236
250
  return (
package/src/index.ts CHANGED
@@ -304,6 +304,18 @@ export {
304
304
  type ChipVariant,
305
305
  type ChipSize,
306
306
  } from './components/chip';
307
+ export {
308
+ Drawer,
309
+ type DrawerProps,
310
+ type DrawerTriggerProps,
311
+ type DrawerContentProps,
312
+ type DrawerHeaderProps,
313
+ type DrawerBodyProps,
314
+ type DrawerFooterProps,
315
+ type DrawerCloseProps,
316
+ type DrawerSide,
317
+ type DrawerSize,
318
+ } from './components/drawer';
307
319
  export {
308
320
  EmptyState,
309
321
  type EmptyStateProps,
@@ -349,6 +361,26 @@ export {
349
361
  type NumberInputProps,
350
362
  } from './components/number-input';
351
363
  export { OtpInput, type OtpInputProps } from './components/otp-input';
364
+ export {
365
+ Panelside,
366
+ usePanelside,
367
+ type PanelsideProps,
368
+ type PanelsidePanelProps,
369
+ type PanelsideHeaderProps,
370
+ type PanelsideSearchProps,
371
+ type PanelsideContentProps,
372
+ type PanelsideGroupProps,
373
+ type PanelsideGroupLabelProps,
374
+ type PanelsideItemProps,
375
+ type PanelsideActionProps,
376
+ type PanelsideFooterProps,
377
+ type PanelsideCtaProps,
378
+ type PanelsideSceneProps,
379
+ type PanelsideTriggerProps,
380
+ type PanelsideMode,
381
+ type PanelsideSwipeFrom,
382
+ type UsePanelsideResult,
383
+ } from './components/panelside';
352
384
  export { Textarea, type TextareaProps } from './components/textarea';
353
385
  export {
354
386
  Item,
@@ -670,6 +702,7 @@ export {
670
702
  ListChecksIcon,
671
703
  LockIcon,
672
704
  MaximizeIcon,
705
+ MenuIcon,
673
706
  MessageCircleIcon,
674
707
  MicIcon,
675
708
  MinusIcon,
@@ -97,3 +97,54 @@ export function getNativeUI(): NativeUIModule | null {
97
97
  export function hasNativeUI(): boolean {
98
98
  return getNativeUI() !== null;
99
99
  }
100
+
101
+ /**
102
+ * The SwiftUI view modifiers, for the handful of things the portable props
103
+ * cannot express.
104
+ *
105
+ * The universal components cover the common ground — a variant, a size, an
106
+ * enabled flag — but the platform has looks with no cross-platform equivalent,
107
+ * and Liquid Glass is the one that matters: it is the material iOS 26 draws its
108
+ * own floating controls in, and nothing in the portable API asks for it. A
109
+ * modifier is how SwiftUI is configured, so this is the door to it.
110
+ *
111
+ * iOS only, and lazily resolved like everything else here. Android's toolkit
112
+ * has its own modifier system and no equivalent material, so asking for glass
113
+ * there is not a downgrade — it is a different question.
114
+ */
115
+ interface SwiftUIModifiers {
116
+ buttonStyle: (
117
+ style:
118
+ | 'automatic'
119
+ | 'bordered'
120
+ | 'borderedProminent'
121
+ | 'borderless'
122
+ | 'glass'
123
+ | 'glassProminent'
124
+ | 'plain'
125
+ ) => unknown;
126
+ buttonBorderShape: (
127
+ shape: 'automatic' | 'capsule' | 'roundedRectangle' | 'circle',
128
+ cornerRadius?: number
129
+ ) => unknown;
130
+ controlSize: (size: 'mini' | 'small' | 'regular' | 'large' | 'extraLarge') => unknown;
131
+ }
132
+
133
+ let modifiersResolved = false;
134
+ let modifiers: SwiftUIModifiers | null = null;
135
+
136
+ export function getSwiftUIModifiers(): SwiftUIModifiers | null {
137
+ if (modifiersResolved) return modifiers;
138
+ modifiersResolved = true;
139
+
140
+ if (Platform.OS !== 'ios') return null;
141
+
142
+ try {
143
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
144
+ modifiers = require('@expo/ui/swift-ui/modifiers') as SwiftUIModifiers;
145
+ } catch {
146
+ modifiers = null;
147
+ }
148
+
149
+ return modifiers;
150
+ }