@kanso-labs/react-native-kanso-ui 0.8.0 → 0.10.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.
- package/README.md +4 -3
- package/dist/autocomplete/index.js +15 -1
- package/dist/autocomplete/index.js.map +1 -1
- package/dist/badge/index.js +9 -70
- package/dist/badge/index.js.map +1 -1
- package/dist/button/group.d.ts +5 -0
- package/dist/button/group.js +115 -0
- package/dist/button/group.js.map +1 -0
- package/dist/button/index.d.ts +4 -1
- package/dist/button/index.js +45 -23
- package/dist/button/index.js.map +1 -1
- package/dist/button/palettes.d.ts +2 -0
- package/dist/button/slots.js +2 -1
- package/dist/button/slots.js.map +1 -1
- package/dist/calendar/index.js +351 -182
- package/dist/calendar/index.js.map +1 -1
- package/dist/calendar/styles.js +33 -2
- package/dist/calendar/styles.js.map +1 -1
- package/dist/carousel/arrangement.d.ts +5 -0
- package/dist/carousel/arrangement.js +123 -0
- package/dist/carousel/arrangement.js.map +1 -0
- package/dist/chequer/index.js +95 -0
- package/dist/chequer/index.js.map +1 -0
- package/dist/collection/index.d.ts +157 -0
- package/dist/collection/index.js +1331 -0
- package/dist/collection/index.js.map +1 -0
- package/dist/color-thumb/index.js +56 -0
- package/dist/color-thumb/index.js.map +1 -0
- package/dist/components/badge/index.d.ts +48 -0
- package/dist/components/badge/index.js +122 -0
- package/dist/components/badge/index.js.map +1 -0
- package/dist/{badge → components/badge}/styles.js +10 -6
- package/dist/components/badge/styles.js.map +1 -0
- package/dist/components/breadcrumbs/index.d.ts +66 -0
- package/dist/components/breadcrumbs/index.js +285 -0
- package/dist/components/breadcrumbs/index.js.map +1 -0
- package/dist/components/button/index.d.ts +4 -2
- package/dist/components/button/index.js +227 -188
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/button-group/index.d.ts +87 -0
- package/dist/components/button-group/index.js +275 -0
- package/dist/components/button-group/index.js.map +1 -0
- package/dist/components/calendar/index.d.ts +11 -3
- package/dist/components/calendar/index.js +60 -45
- package/dist/components/calendar/index.js.map +1 -1
- package/dist/components/carousel/index.d.ts +72 -0
- package/dist/components/carousel/index.js +496 -0
- package/dist/components/carousel/index.js.map +1 -0
- package/dist/components/checkbox/index.d.ts +7 -1
- package/dist/components/checkbox/index.js +183 -138
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/checkbox-group/index.d.ts +92 -0
- package/dist/components/checkbox-group/index.js +306 -0
- package/dist/components/checkbox-group/index.js.map +1 -0
- package/dist/components/code/index.d.ts +25 -0
- package/dist/components/code/index.js +87 -0
- package/dist/components/code/index.js.map +1 -0
- package/dist/components/color-area/index.d.ts +85 -0
- package/dist/components/color-area/index.js +630 -0
- package/dist/components/color-area/index.js.map +1 -0
- package/dist/components/color-field/index.d.ts +144 -0
- package/dist/components/color-field/index.js +516 -0
- package/dist/components/color-field/index.js.map +1 -0
- package/dist/components/color-picker/index.d.ts +74 -0
- package/dist/components/color-picker/index.js +317 -0
- package/dist/components/color-picker/index.js.map +1 -0
- package/dist/components/color-slider/index.d.ts +82 -0
- package/dist/components/color-slider/index.js +456 -0
- package/dist/components/color-slider/index.js.map +1 -0
- package/dist/components/color-swatch/index.d.ts +46 -0
- package/dist/components/color-swatch/index.js +127 -0
- package/dist/components/color-swatch/index.js.map +1 -0
- package/dist/components/color-swatch-picker/index.d.ts +81 -0
- package/dist/components/color-swatch-picker/index.js +287 -0
- package/dist/components/color-swatch-picker/index.js.map +1 -0
- package/dist/components/color-wheel/index.d.ts +71 -0
- package/dist/components/color-wheel/index.js +407 -0
- package/dist/components/color-wheel/index.js.map +1 -0
- package/dist/components/combo-box/index.d.ts +193 -0
- package/dist/components/combo-box/index.js +616 -0
- package/dist/components/combo-box/index.js.map +1 -0
- package/dist/components/container/index.d.ts +47 -0
- package/dist/components/container/index.js +85 -0
- package/dist/components/container/index.js.map +1 -0
- package/dist/components/date-field/index.d.ts +120 -0
- package/dist/components/date-field/index.js +111 -0
- package/dist/components/date-field/index.js.map +1 -0
- package/dist/components/date-picker/index.d.ts +130 -0
- package/dist/components/date-picker/index.js +310 -0
- package/dist/components/date-picker/index.js.map +1 -0
- package/dist/components/date-range-picker/index.d.ts +139 -0
- package/dist/components/date-range-picker/index.js +421 -0
- package/dist/components/date-range-picker/index.js.map +1 -0
- package/dist/components/disclosure/index.d.ts +94 -0
- package/dist/components/disclosure/index.js +365 -0
- package/dist/components/disclosure/index.js.map +1 -0
- package/dist/components/disclosure-group/index.d.ts +61 -0
- package/dist/components/disclosure-group/index.js +100 -0
- package/dist/components/disclosure-group/index.js.map +1 -0
- package/dist/components/drop-zone/index.d.ts +113 -0
- package/dist/components/drop-zone/index.js +304 -0
- package/dist/components/drop-zone/index.js.map +1 -0
- package/dist/components/fab/index.d.ts +80 -0
- package/dist/components/fab/index.js +246 -0
- package/dist/components/fab/index.js.map +1 -0
- package/dist/components/fab-menu/index.d.ts +120 -0
- package/dist/components/fab-menu/index.js +640 -0
- package/dist/components/fab-menu/index.js.map +1 -0
- package/dist/components/feed/index.d.ts +57 -0
- package/dist/components/feed/index.js +167 -0
- package/dist/components/feed/index.js.map +1 -0
- package/dist/components/form/index.d.ts +3 -2
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/icon-button/index.d.ts +4 -2
- package/dist/components/icon-button/index.js +204 -171
- package/dist/components/icon-button/index.js.map +1 -1
- package/dist/components/keycap/index.d.ts +27 -0
- package/dist/components/keycap/index.js +136 -0
- package/dist/components/keycap/index.js.map +1 -0
- package/dist/components/list/index.d.ts +15 -158
- package/dist/components/list/index.js +21 -1047
- package/dist/components/list/index.js.map +1 -1
- package/dist/components/list-box/index.d.ts +73 -0
- package/dist/components/list-box/index.js +82 -0
- package/dist/components/list-box/index.js.map +1 -0
- package/dist/components/loading-indicator/index.d.ts +32 -0
- package/dist/components/loading-indicator/index.js +174 -0
- package/dist/components/loading-indicator/index.js.map +1 -0
- package/dist/components/menu/index.js +1 -1
- package/dist/components/navigation-tree/index.d.ts +117 -0
- package/dist/components/navigation-tree/index.js +135 -0
- package/dist/components/navigation-tree/index.js.map +1 -0
- package/dist/components/number-field/index.js +132 -143
- package/dist/components/number-field/index.js.map +1 -1
- package/dist/components/range-calendar/index.d.ts +69 -0
- package/dist/components/range-calendar/index.js +144 -0
- package/dist/components/range-calendar/index.js.map +1 -0
- package/dist/components/search-view/index.d.ts +78 -0
- package/dist/components/search-view/index.js +570 -0
- package/dist/components/search-view/index.js.map +1 -0
- package/dist/components/select/index.d.ts +152 -0
- package/dist/components/select/index.js +419 -0
- package/dist/components/select/index.js.map +1 -0
- package/dist/components/separator/index.d.ts +3 -2
- package/dist/components/separator/index.js +29 -26
- package/dist/components/separator/index.js.map +1 -1
- package/dist/components/slider/index.d.ts +111 -0
- package/dist/components/slider/index.js +673 -0
- package/dist/components/slider/index.js.map +1 -0
- package/dist/components/split-button/index.d.ts +77 -0
- package/dist/components/split-button/index.js +354 -0
- package/dist/components/split-button/index.js.map +1 -0
- package/dist/components/supporting-pane/index.d.ts +44 -0
- package/dist/components/supporting-pane/index.js +109 -0
- package/dist/components/supporting-pane/index.js.map +1 -0
- package/dist/components/tabs/index.d.ts +196 -0
- package/dist/components/tabs/index.js +1137 -0
- package/dist/components/tabs/index.js.map +1 -0
- package/dist/components/text/index.d.ts +1 -1
- package/dist/components/text/index.js +49 -21
- package/dist/components/text/index.js.map +1 -1
- package/dist/components/text-area/index.d.ts +145 -0
- package/dist/components/text-area/index.js +231 -0
- package/dist/components/text-area/index.js.map +1 -0
- package/dist/components/time-field/index.d.ts +43 -0
- package/dist/components/time-field/index.js +107 -0
- package/dist/components/time-field/index.js.map +1 -0
- package/dist/components/time-picker/index.d.ts +65 -0
- package/dist/components/time-picker/index.js +1168 -0
- package/dist/components/time-picker/index.js.map +1 -0
- package/dist/components/toolbar/index.d.ts +53 -0
- package/dist/components/toolbar/index.js +185 -0
- package/dist/components/toolbar/index.js.map +1 -0
- package/dist/components/tooltip/index.d.ts +101 -0
- package/dist/components/tooltip/index.js +223 -0
- package/dist/components/tooltip/index.js.map +1 -0
- package/dist/components/tree/index.d.ts +112 -0
- package/dist/components/tree/index.js +157 -0
- package/dist/components/tree/index.js.map +1 -0
- package/dist/control/group.js +23 -0
- package/dist/control/group.js.map +1 -0
- package/dist/disclosure/chevron.js +75 -0
- package/dist/disclosure/chevron.js.map +1 -0
- package/dist/disclosure/index.js +7 -0
- package/dist/disclosure/index.js.map +1 -0
- package/dist/drop/index.d.ts +54 -0
- package/dist/drop/index.js +161 -0
- package/dist/drop/index.js.map +1 -0
- package/dist/fab/index.d.ts +19 -0
- package/dist/fab/index.js +147 -0
- package/dist/fab/index.js.map +1 -0
- package/dist/field/chevron.js +74 -0
- package/dist/field/chevron.js.map +1 -0
- package/dist/field/index.d.ts +2 -1
- package/dist/field/index.js +350 -153
- package/dist/field/index.js.map +1 -1
- package/dist/field/styles.js +27 -0
- package/dist/field/styles.js.map +1 -1
- package/dist/files/index.d.ts +18 -0
- package/dist/files/index.js +107 -0
- package/dist/files/index.js.map +1 -0
- package/dist/form/index.d.ts +6 -4
- package/dist/form/index.js +64 -85
- package/dist/form/index.js.map +1 -1
- package/dist/glyphs/index.js +92 -1
- package/dist/glyphs/index.js.map +1 -1
- package/dist/i18n/index.js +20 -1
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/messages.js +1394 -34
- package/dist/i18n/messages.js.map +1 -1
- package/dist/index.d.ts +51 -6
- package/dist/index.js +47 -4
- package/dist/indicator/paths.js +23 -1
- package/dist/indicator/paths.js.map +1 -1
- package/dist/modal/index.js +96 -68
- package/dist/modal/index.js.map +1 -1
- package/dist/navigation/index.js +8 -5
- package/dist/navigation/index.js.map +1 -1
- package/dist/number/keyboard.js +16 -0
- package/dist/number/keyboard.js.map +1 -0
- package/dist/overlay/anchored.js +68 -38
- package/dist/overlay/anchored.js.map +1 -1
- package/dist/overlay/keyboard.js +57 -0
- package/dist/overlay/keyboard.js.map +1 -0
- package/dist/overlay/panel.js +173 -19
- package/dist/overlay/panel.js.map +1 -1
- package/dist/overlay/placement.js +16 -2
- package/dist/overlay/placement.js.map +1 -1
- package/dist/picker/index.js +322 -0
- package/dist/picker/index.js.map +1 -0
- package/dist/press/index.d.ts +2 -0
- package/dist/press/index.js +102 -100
- package/dist/press/index.js.map +1 -1
- package/dist/row/index.js +77 -69
- package/dist/row/index.js.map +1 -1
- package/dist/row/styles.js +13 -2
- package/dist/row/styles.js.map +1 -1
- package/dist/segments/field.js +277 -0
- package/dist/segments/field.js.map +1 -0
- package/dist/segments/index.js +574 -0
- package/dist/segments/index.js.map +1 -0
- package/dist/segments/styles.js +24 -0
- package/dist/segments/styles.js.map +1 -0
- package/dist/separator/index.js +7 -0
- package/dist/separator/index.js.map +1 -0
- package/dist/slider/index.js +145 -0
- package/dist/slider/index.js.map +1 -0
- package/dist/swatch/index.js +56 -0
- package/dist/swatch/index.js.map +1 -0
- package/dist/typography/size.js +14 -0
- package/dist/typography/size.js.map +1 -0
- package/package.json +11 -2
- package/dist/badge/styles.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["ComponentRef","ReactNode","Ref","RefObject","GestureResponderEvent","HostInstance","PressableProps","StyleProp","TextStyle","ViewStyle","AnimatedStyle","Key","Node","TreeProps","TreeState","useCallback","useEffect","useMemo","useRef","useState","I18nManager","Text","NativeText","Pressable","StyleSheet","View","Animated","Easing","useAnimatedStyle","useReducedMotion","useSharedValue","withTiming","useMenuTriggerState","useTreeState","FabSize","FabTone","IconStyle","AnimatedPressable","buttonStyles","FAB_ICON_SIZES","fabColorsOf","fabCornersOf","fabPalettesOf","fabShadowOf","fabSizesOf","CloseGlyph","IconStyleContext","Overlay","useAnchoredPlacement","DismissLayer","useBackToClose","useFocusOnPlaced","useReturnFocus","usePressFeedback","refsOf","useTheme","composeStyles","themedStyles","useTypeRole","CLOSE_SIZE","RISE_FROM","HAS_MENU","CLOSE","FabMenuItemProps","Omit","children","icon","id","isDisabled","onAction","ref","style","textValue","FabMenuProps","defaultOpen","isOpen","key","onOpenChange","size","testID","tone","styles","create","base","alignItems","flexShrink","justifyContent","label","stylesOf","radii","sizing","spacing","action","columnGap","sm","flexDirection","minHeight","controlLg","minWidth","paddingHorizontal","xl","corner","borderRadius","pill","menu","rowGap","xs","FabMenu","t0","$","_c","t1","t2","undefined","theme","t3","state","open","fab","anchor","useCloseButtonAnchor","content","feedback","color","morph","useCloseMorph","t4","toggle","t5","close","T0","t7","t8","handlers","t9","t10","container","ring","t11","clip","t12","layer","T1","T2","t14","iconStyleOf","t15","t16","t17","t13","t18","t6","t19","t20","FabMenuItem","_props","getCollectionNode","props","hasChildNodes","rendered","type","FabMenuAction","activate","node","setFocusTarget","own","role","onBlur","onFocus","onHoverIn","onHoverOut","onPress","onPressIn","onPressOut","_id","_isDisabled","_onAction","_textValue","palettes","colors","disabled","tonal","corners","pressThen","md","FabMenuPanel","align","side","sideOffset","placement","rise","useRiseIn","placed","focusTarget","firstActionKey","focusKey","onLayout","collection","selectionManager","map","node_0","getKeys","event","edge","current","measureInWindow","callback","x","y","width","height","isRTL","reduceMotion","motion","fill","timing","duration","durationMedium1","easing","bezier","easingEmphasized","backgroundColor","shown","set","durationShort3","easingEmphasizedDecelerate","progress","get","opacity","transform","translateY","Item","_c","NativeText"],"sources":["../../../src/components/fab-menu/index.tsx"],"sourcesContent":["import type { ComponentRef, ReactNode, Ref, RefObject } from 'react'\nimport type {\n GestureResponderEvent,\n HostInstance,\n PressableProps,\n StyleProp,\n TextStyle,\n ViewStyle,\n} from 'react-native'\nimport type { AnimatedStyle } from 'react-native-reanimated'\nimport type { Key, Node } from 'react-stately'\nimport type { TreeProps, TreeState } from 'react-stately/useTreeState'\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n I18nManager,\n Text as NativeText,\n Pressable,\n StyleSheet,\n View,\n} from 'react-native'\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\nimport { useMenuTriggerState } from 'react-stately/useMenuTriggerState'\nimport { useTreeState } from 'react-stately/useTreeState'\n\nimport type { FabSize, FabTone } from '../../fab'\nimport type { IconStyle } from '../../glyphs/icon-style'\n\nimport { AnimatedPressable, buttonStyles } from '../../button'\nimport {\n FAB_ICON_SIZES,\n fabColorsOf,\n fabCornersOf,\n fabPalettesOf,\n fabShadowOf,\n fabSizesOf,\n} from '../../fab'\nimport { CloseGlyph } from '../../glyphs'\nimport { IconStyleContext } from '../../glyphs/icon-style'\nimport { Overlay, useAnchoredPlacement } from '../../overlay'\nimport {\n DismissLayer,\n useBackToClose,\n useFocusOnPlaced,\n useReturnFocus,\n} from '../../overlay/panel'\nimport { usePressFeedback } from '../../press'\nimport { refsOf } from '../../ref'\nimport { useTheme } from '../../theme/scope'\nimport { composeStyles, themedStyles } from '../../theme/styles'\nimport { useTypeRole } from '../../typography/roles'\n\n// kanso-ui's FabMenu: the FAB menu page's menu, a FAB that opens two to six\n// related actions floating above it, in place of a speed dial. Open, the FAB\n// becomes the menu's close button, the page's 56dp circle in the tone itself\n// with a 20dp close mark, and the actions stand in a column 8dp above it,\n// lined up on its trailing edge: each a 56dp pill on the tone's container\n// pair with 24dp at either end, a 24dp icon 8dp before a title-medium label,\n// 4dp apart and raised on the level 3 shadow, lifted to level 4 under a\n// hovering pointer as Fab is. The three tones are the page's three colour\n// sets: the close button takes the tone and the actions its container, so\n// the two contrast as the page draws them.\n//\n// The FAB is the menu's own rather than a child the call site places, as on\n// web, because what it draws depends on whether the menu is open. Closed, it\n// is Fab at any of its sizes, from src/fab's metrics and colours. As the menu\n// opens, its width, height, corner and container ease to the close button's\n// over the medium1 duration on the emphasised curve, and back as it closes.\n// The icon is swapped for the close mark at once, in the colour drawn on the\n// container it is easing to. Under reduced motion the change is made at once.\n//\n// The actions are a collection, built by React Stately's tree state as\n// Menu's items are, so `FabMenu.Item` renders nothing on its own. They are\n// drawn in the overlay host above the screen with src/overlay's anchored\n// placement, on the FAB's top side at its end, and rise 8dp into place over\n// the short3 duration on the emphasised decelerating curve, at once under\n// reduced motion. As on web, they leave at once.\n//\n// They are placed against the close button rather than against the FAB that\n// opens them. A FAB opening a menu sits in its screen's bottom trailing\n// corner, so the 80 and 96dp sizes shrink into that corner, and the actions\n// stand 8dp above the 56dp circle they shrink to rather than above where the\n// larger FAB was.\n//\n// A press outside the actions lands on the dismiss layer under them and\n// closes the menu, as does a press on the close button, which that layer\n// covers. Android's back gesture and VoiceOver's escape gesture close it\n// too. A press on an action runs it and closes the menu. A screen reader is\n// sent to the first action that takes a press once they are placed, and back\n// to the FAB once they have gone, and the FAB reports whether its menu is\n// expanded. Web's arrow keys between the actions need a hardware keyboard,\n// which this pass leaves out, as Menu does. Web's forced-colours rules have\n// no counterpart on iOS or Android and are not drawn.\n\n// The close mark at the page's 20dp.\nconst CLOSE_SIZE = 20\n\n// How far below its place the column starts as it arrives, web's keyframes'.\nconst RISE_FROM = 8\n\n// React Native Web writes `aria-haspopup` onto the element, which React\n// Native's types do not name.\nconst HAS_MENU: { readonly 'aria-haspopup': 'menu' } = {\n 'aria-haspopup': 'menu',\n}\n\n// Hoisted so it is one stable element per render, which is what react-perf's\n// no-jsx-as-prop is after.\nconst CLOSE = <CloseGlyph />\n\ntype FabMenuItemProps = Omit<\n PressableProps,\n 'children' | 'disabled' | 'id' | 'role' | 'style'\n> & {\n /** The action's name, drawn as its label. */\n readonly children: ReactNode\n /**\n * An icon before the label, which takes the label's colour at the page's\n * 24dp through `useIconStyle()`.\n */\n readonly icon?: ReactNode\n /**\n * The key the action is reported by. Give one to every action the call\n * site needs to tell apart.\n */\n readonly id?: Key\n /**\n * Draws the action disabled, without its shadow, and takes no presses on\n * it.\n * @default false\n */\n readonly isDisabled?: boolean\n /**\n * Called when a press runs the action, in place of the menu's `onAction`\n * for this one.\n */\n readonly onAction?: () => void\n readonly ref?: Ref<HostInstance>\n readonly style?: StyleProp<ViewStyle>\n /**\n * The action's text, read off `children` when they are a plain string, so\n * an action whose label is an element passes it.\n */\n readonly textValue?: string\n}\n\ntype FabMenuProps = {\n /**\n * What the FAB does, in words: an icon alone has no name, and the menu\n * takes its name from the FAB that opens it.\n */\n readonly 'aria-label': string\n /** The actions, as `FabMenu.Item`s. The page asks for two to six. */\n readonly children: ReactNode\n /**\n * Whether the menu starts open, when it keeps its own state.\n * @default false\n */\n readonly defaultOpen?: boolean\n /**\n * The FAB's icon while the menu is closed. The FAB hands it its colour and\n * the size's icon size through `useIconStyle()`.\n */\n readonly icon: ReactNode\n /** Whether the menu is open, when the call site holds the state. */\n readonly isOpen?: boolean\n /** Called with an action's `id` when a press runs it. */\n readonly onAction?: (key: Key) => void\n /** Called with the new state as the menu opens or closes. */\n readonly onOpenChange?: (isOpen: boolean) => void\n readonly ref?: Ref<ComponentRef<typeof View>>\n /**\n * The FAB's size while the menu is closed, as Fab's: `md` 56dp, `lg` 80dp\n * or `xl` 96dp. Open, it is the close button's 56dp whatever it was.\n * @default 'md'\n */\n readonly size?: FabSize\n readonly style?: StyleProp<ViewStyle>\n readonly testID?: string\n /**\n * The page's three colour sets: the close button takes the tone and the\n * actions its container pair.\n * @default 'primary'\n */\n readonly tone?: FabTone\n}\n\nconst styles = StyleSheet.create({\n // The icon sits in the middle of the FAB, and a row never squeezes it.\n base: {\n alignItems: 'center',\n flexShrink: 0,\n justifyContent: 'center',\n },\n icon: {\n alignItems: 'center',\n flexShrink: 0,\n justifyContent: 'center',\n },\n label: {\n flexShrink: 1,\n },\n})\n\nconst stylesOf = themedStyles(({ radii, sizing, spacing }) =>\n StyleSheet.create({\n // An action: a pill as tall as the close button, its icon 8dp before the\n // label, 24dp in from either end. Its height is a floor, so a label the\n // device's text size enlarges grows the pill rather than spilling out.\n action: {\n alignItems: 'center',\n columnGap: spacing.sm,\n flexDirection: 'row',\n minHeight: sizing.controlLg,\n minWidth: sizing.controlLg,\n paddingHorizontal: spacing.xl,\n },\n corner: {\n borderRadius: radii.pill,\n },\n // The actions in a column on the FAB's trailing edge, 4dp apart.\n menu: {\n alignItems: 'flex-end',\n rowGap: spacing.xs,\n },\n }),\n)\n\n/**\n * A FAB that opens a column of related actions above it, and closes them\n * again. The actions are `FabMenu.Item`s.\n *\n * ```tsx\n * <FabMenu aria-label=\"Label\" icon={<PlusIcon />}>\n * <FabMenu.Item icon={<FirstIcon />} id=\"first\">\n * First item\n * </FabMenu.Item>\n * <FabMenu.Item icon={<SecondIcon />} id=\"second\">\n * Second item\n * </FabMenu.Item>\n * </FabMenu>\n * ```\n *\n * `style`, `ref` and `testID` land on the FAB, which is what a call site\n * positions over its screen.\n */\nfunction FabMenu({\n 'aria-label': label,\n children,\n defaultOpen,\n icon,\n isOpen,\n onAction,\n onOpenChange,\n ref,\n size = 'md',\n style,\n testID,\n tone = 'primary',\n}: FabMenuProps) {\n const theme = useTheme()\n const state = useMenuTriggerState({ defaultOpen, isOpen, onOpenChange })\n const open = state.isOpen\n const fab = useRef<HostInstance>(null)\n const anchor = useCloseButtonAnchor(fab, theme.sizing.controlLg)\n const { content } = fabColorsOf(theme)[open ? 'filled' : 'tonal'][tone]\n const feedback = usePressFeedback({ color: content })\n const morph = useCloseMorph(open, size, tone)\n const toggle = useCallback(() => {\n state.toggle()\n }, [state])\n const close = useCallback(() => {\n state.close()\n }, [state])\n\n useReturnFocus(open, false, fab)\n\n return (\n <>\n <AnimatedPressable\n {...HAS_MENU}\n aria-expanded={open}\n aria-label={label}\n role=\"button\"\n testID={testID}\n {...feedback.handlers}\n onPress={toggle}\n ref={refsOf<HostInstance>(fab, ref)}\n style={composeStyles<AnimatedStyle<ViewStyle>>(\n styles.base,\n morph.container,\n fabShadowOf(feedback, false, theme),\n feedback.ring,\n style,\n )}\n >\n <Animated.View\n style={composeStyles<AnimatedStyle<ViewStyle>>(\n buttonStyles.clip,\n morph.clip,\n )}\n >\n {feedback.layer}\n </Animated.View>\n <View style={styles.icon}>\n <IconStyleContext\n value={iconStyleOf(\n content,\n open ? CLOSE_SIZE : FAB_ICON_SIZES[size],\n )}\n >\n {open ? CLOSE : icon}\n </IconStyleContext>\n </View>\n </AnimatedPressable>\n {open ? (\n <Overlay>\n <FabMenuPanel\n anchor={anchor}\n close={close}\n label={label}\n onAction={onAction}\n tone={tone}\n >\n {children}\n </FabMenuPanel>\n </Overlay>\n ) : null}\n </>\n )\n}\n\n/**\n * One action: a pill holding an icon and a label, on the menu's tone. A press\n * on it runs it and closes the menu.\n *\n * The menu draws it from its entry in the collection, so it renders nothing\n * on its own. `style`, `ref` and `testID` land on the pill.\n */\nfunction FabMenuItem(_props: FabMenuItemProps): null {\n return null\n}\n\n// The entry the collection holds for an action, as React Stately's own\n// `Item` gives one: keyed by the action's `id`, and carrying the props the\n// pill is drawn from.\nFabMenuItem.getCollectionNode = function* getCollectionNode(\n props: FabMenuItemProps,\n) {\n yield {\n hasChildNodes: false,\n key: props.id,\n props,\n rendered: props.children,\n textValue:\n props.textValue ??\n (typeof props.children === 'string' ? props.children : ''),\n type: 'item',\n }\n}\n\n/** An action's pill, drawn from its entry in the collection. */\nfunction FabMenuAction({\n activate,\n isDisabled,\n node,\n setFocusTarget,\n tone,\n}: {\n readonly activate: (node: Node<object>) => void\n readonly isDisabled: boolean\n readonly node: Node<object>\n /** Keeps the pill a screen reader is sent to as the menu opens. */\n readonly setFocusTarget: ((target: HostInstance | null) => void) | undefined\n readonly tone: FabTone\n}) {\n const theme = useTheme()\n const own = stylesOf(theme)\n const role = useTypeRole('titleMedium')\n // oxlint-disable-next-line typescript/no-unsafe-assignment -- a node carries the props its action was written with, which React Stately types as `any`\n const {\n children,\n icon,\n id: _id,\n isDisabled: _isDisabled,\n onAction: _onAction,\n onBlur,\n onFocus,\n onHoverIn,\n onHoverOut,\n onPress,\n onPressIn,\n onPressOut,\n ref,\n style,\n textValue: _textValue,\n ...props\n }: FabMenuItemProps = node.props\n const palettes = fabPalettesOf(theme)\n const colors = isDisabled ? palettes.disabled : palettes.tonal[tone]\n const feedback = usePressFeedback({\n color: colors.content,\n corners: own.corner,\n disabled: isDisabled,\n onBlur,\n onFocus,\n onHoverIn,\n onHoverOut,\n onPressIn,\n onPressOut,\n })\n\n return (\n <Pressable\n role=\"menuitem\"\n {...props}\n {...feedback.handlers}\n disabled={isDisabled}\n onPress={pressThen(onPress, activate, node)}\n ref={refsOf(setFocusTarget, ref)}\n style={composeStyles<ViewStyle>(\n own.action,\n own.corner,\n colors.container,\n fabShadowOf(feedback, isDisabled, theme),\n feedback.ring,\n style,\n )}\n >\n {feedback.layer}\n {icon === undefined ? null : (\n <View style={styles.icon}>\n <IconStyleContext\n value={iconStyleOf(colors.content, FAB_ICON_SIZES.md)}\n >\n {icon}\n </IconStyleContext>\n </View>\n )}\n <NativeText\n numberOfLines={1}\n style={composeStyles<TextStyle>(role, styles.label, colors.label)}\n >\n {children}\n </NativeText>\n </Pressable>\n )\n}\n\n/**\n * The open menu: the dismiss layer, then the column of actions, placed above\n * the close button's end and risen into place once it has been.\n */\nfunction FabMenuPanel({\n anchor,\n children,\n close,\n label,\n onAction,\n tone,\n}: {\n readonly anchor: RefObject<Pick<HostInstance, 'measureInWindow'>>\n readonly children: ReactNode\n readonly close: () => void\n readonly label: string\n readonly onAction: ((key: Key) => void) | undefined\n readonly tone: FabTone\n}) {\n const theme = useTheme()\n const own = stylesOf(theme)\n const state = useTreeState<object>({\n // Each action builds its own entry in the collection; see\n // `FabMenuItem.getCollectionNode`. The collection skips what is not an\n // element, as a ReactNode may be, and asks any element for its entry.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- see above\n children: children as TreeProps<object>['children'],\n })\n const placement = useAnchoredPlacement({\n align: 'end',\n anchor,\n side: 'top',\n sideOffset: theme.spacing.sm,\n })\n const rise = useRiseIn(placement.placed)\n const [focusTarget, setFocusTarget] = useState<HostInstance | null>(null)\n const focusKey = firstActionKey(state)\n const activate = useCallback(\n (node: Node<object>) => {\n // oxlint-disable-next-line typescript/no-unsafe-assignment -- a node carries the props its action was written with, which React Stately types as `any`\n const action: FabMenuItemProps = node.props\n\n if (action.onAction === undefined) {\n onAction?.(node.key)\n } else {\n action.onAction()\n }\n close()\n },\n [close, onAction],\n )\n\n useBackToClose(close, true)\n useFocusOnPlaced(placement.placed, focusTarget)\n\n return (\n <>\n <DismissLayer onPress={close} />\n <Animated.View\n aria-label={label}\n onAccessibilityEscape={close}\n onLayout={placement.onLayout}\n role=\"menu\"\n style={composeStyles<AnimatedStyle<ViewStyle>>(\n own.menu,\n placement.style,\n rise,\n )}\n >\n {[...state.collection].map((node) => (\n <FabMenuAction\n activate={activate}\n isDisabled={state.selectionManager.isDisabled(node.key)}\n key={node.key}\n node={node}\n setFocusTarget={node.key === focusKey ? setFocusTarget : undefined}\n tone={tone}\n />\n ))}\n </Animated.View>\n </>\n )\n}\n\n/** The first action a press reaches, which a screen reader is sent to. */\nfunction firstActionKey(state: TreeState<object>) {\n for (const key of state.collection.getKeys()) {\n if (!state.selectionManager.isDisabled(key)) {\n return key\n }\n }\n\n return null\n}\n\nfunction iconStyleOf(color: string, size: number): IconStyle {\n return { color, size }\n}\n\n/**\n * The press handler of an action: the call site's own `onPress`, then the\n * action's activation. Built by a call rather than written inline at the\n * prop, which is what react-perf's no-new-function-as-prop is after.\n */\nfunction pressThen(\n onPress: PressableProps['onPress'],\n activate: (node: Node<object>) => void,\n node: Node<object>,\n) {\n return (event: GestureResponderEvent) => {\n onPress?.(event)\n activate(node)\n }\n}\n\n/**\n * The close button the FAB becomes, for the actions to be placed against: a\n * square of the close button's edge in the FAB's bottom trailing corner, read\n * off the FAB wherever in its change it is when it is measured.\n */\nfunction useCloseButtonAnchor(\n fab: RefObject<HostInstance | null>,\n edge: number,\n) {\n return useMemo<RefObject<Pick<HostInstance, 'measureInWindow'>>>(\n () => ({\n current: {\n measureInWindow: (callback) => {\n fab.current?.measureInWindow((x, y, width, height) => {\n callback(\n I18nManager.isRTL ? x : x + width - edge,\n y + height - edge,\n edge,\n edge,\n )\n })\n },\n },\n }),\n [edge, fab],\n )\n}\n\n/**\n * The FAB's change into the close button and back: its width, height,\n * corner and container eased to the state's over medium1 on the emphasised\n * curve, at once under reduced motion. The corner is returned twice, for the\n * container and for the clip its press feedback is drawn in.\n */\nfunction useCloseMorph(isOpen: boolean, size: FabSize, tone: FabTone) {\n const theme = useTheme()\n const reduceMotion = useReducedMotion()\n const { motion, sizing } = theme\n const edge = isOpen ? sizing.controlLg : fabSizesOf(theme)[size].width\n const corner = isOpen\n ? sizing.controlLg / 2\n : fabCornersOf(theme)[size].borderRadius\n const fill = fabColorsOf(theme)[isOpen ? 'filled' : 'tonal'][tone].container\n const timing = {\n duration: motion.durationMedium1,\n easing: Easing.bezier(...motion.easingEmphasized),\n }\n\n const container = useAnimatedStyle(() => {\n 'worklet'\n return {\n backgroundColor: reduceMotion ? fill : withTiming(fill, timing),\n borderRadius: reduceMotion ? corner : withTiming(corner, timing),\n height: reduceMotion ? edge : withTiming(edge, timing),\n width: reduceMotion ? edge : withTiming(edge, timing),\n }\n })\n const clip = useAnimatedStyle(() => {\n 'worklet'\n return {\n borderRadius: reduceMotion ? corner : withTiming(corner, timing),\n }\n })\n\n return { clip, container }\n}\n\n/**\n * The actions' arrival: they fade in and rise 8dp into place over short3 on\n * the emphasised decelerating curve once they have been placed, and stay\n * transparent until then. Under reduced motion they arrive at once.\n */\nfunction useRiseIn(placed: boolean) {\n const { motion } = useTheme()\n const reduceMotion = useReducedMotion()\n const shown = useSharedValue(0)\n\n useEffect(() => {\n if (!placed) {\n return\n }\n\n shown.set(\n reduceMotion\n ? 1\n : withTiming(1, {\n duration: motion.durationShort3,\n easing: Easing.bezier(...motion.easingEmphasizedDecelerate),\n }),\n )\n }, [motion, placed, reduceMotion, shown])\n\n return useAnimatedStyle(() => {\n 'worklet'\n const progress = shown.get()\n\n return {\n opacity: progress,\n transform: [{ translateY: RISE_FROM * (1 - progress) }],\n }\n })\n}\n\nFabMenu.Item = FabMenuItem\n\nexport { FabMenu, FabMenuItem }\nexport type { FabMenuItemProps, FabMenuProps }\n"],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { View, ViewProps } from "react-native";
|
|
2
|
+
import { ComponentRef, ReactNode, Ref } from "react";
|
|
3
|
+
//#region src/components/feed/index.d.ts
|
|
4
|
+
type FeedProps = Omit<ViewProps, 'children'> & {
|
|
5
|
+
/**
|
|
6
|
+
* The items, each laid into a cell of its own. An element is one item,
|
|
7
|
+
* whatever it renders, so hand the feed the items themselves rather than a
|
|
8
|
+
* component listing them; a fragment counts as the items it holds. A cell
|
|
9
|
+
* is as tall as the tallest item in its line, and an item that should fill
|
|
10
|
+
* that height, as a card in a grid does, sets `flexGrow: 1`.
|
|
11
|
+
*/
|
|
12
|
+
readonly children?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* How narrow a cell may get before the grid drops a column, in dp or as a
|
|
15
|
+
* share of the room the feed is given. Every column is at least this wide
|
|
16
|
+
* and the grid fits as many as the room allows, which is how Material
|
|
17
|
+
* Design describes an adaptive grid: by its cell rather than by a column
|
|
18
|
+
* count per window size. Given less room than this, the one column takes
|
|
19
|
+
* the room it is given rather than overflowing it.
|
|
20
|
+
*
|
|
21
|
+
* Worth setting. The default is the figure Material Design's own example
|
|
22
|
+
* uses, and it is a floor rather than advice: only the contents know how
|
|
23
|
+
* narrow they can go.
|
|
24
|
+
* @default 180
|
|
25
|
+
*/
|
|
26
|
+
readonly minItemWidth?: `${number}%` | number;
|
|
27
|
+
readonly ref?: Ref<ComponentRef<typeof View>>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Material Design's feed layout: a grid of comparable items that fits as many
|
|
31
|
+
* columns as the room allows, down to a single column when it allows only
|
|
32
|
+
* one.
|
|
33
|
+
*
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <Feed minItemWidth={260}>
|
|
36
|
+
* {items.map((item) => (
|
|
37
|
+
* <Card key={item.id} style={FILL}>…</Card>
|
|
38
|
+
* ))}
|
|
39
|
+
* </Feed>
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Layout only: it paints no surface. Each element it is handed sits in a
|
|
43
|
+
* cell of the feed's, which is what sizes it: a fragment counts as the items
|
|
44
|
+
* it holds and `null` as none, while a component counts as one item whatever
|
|
45
|
+
* it renders, since a grid on native sees elements rather than what they
|
|
46
|
+
* draw.
|
|
47
|
+
*
|
|
48
|
+
* It reads the room it is in rather than the width of the window, so a feed
|
|
49
|
+
* inside a pane reflows with the pane.
|
|
50
|
+
*
|
|
51
|
+
* `style`, `ref` and `testID` land on the outer `View`, and a `style` there
|
|
52
|
+
* applies over the feed's own.
|
|
53
|
+
*/
|
|
54
|
+
declare function Feed({ children, minItemWidth, style, ...props }: FeedProps): import("react").JSX.Element;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { Feed, type FeedProps };
|
|
57
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { useTheme } from "../../theme/scope.js";
|
|
2
|
+
import { composeStyles, themedStyles } from "../../theme/styles.js";
|
|
3
|
+
import { c } from "react/compiler-runtime";
|
|
4
|
+
import { StyleSheet, View, useWindowDimensions } from "react-native";
|
|
5
|
+
import { Children, Fragment, isValidElement, useState } from "react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/feed/index.tsx
|
|
8
|
+
const DEFAULT_MIN_ITEM_WIDTH = 180;
|
|
9
|
+
const ROUNDING = .5;
|
|
10
|
+
const EPSILON = 1e-6;
|
|
11
|
+
const styles = StyleSheet.create({
|
|
12
|
+
cell: {
|
|
13
|
+
flexGrow: 1,
|
|
14
|
+
flexShrink: 1,
|
|
15
|
+
minWidth: 0
|
|
16
|
+
},
|
|
17
|
+
grid: {
|
|
18
|
+
alignSelf: "stretch",
|
|
19
|
+
flexDirection: "row",
|
|
20
|
+
flexWrap: "wrap"
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const stylesOf = themedStyles(({ spacing }) => StyleSheet.create({ grid: {
|
|
24
|
+
columnGap: spacing.xl,
|
|
25
|
+
rowGap: spacing.xl
|
|
26
|
+
} }));
|
|
27
|
+
function cellsOf(children, columns) {
|
|
28
|
+
const cells = itemsOf(children, "");
|
|
29
|
+
for (let at = cells.length; at % columns !== 0; at += 1) cells.push({ key: `empty-${at}` });
|
|
30
|
+
return cells;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* How many columns of at least `minItemWidth` fit in `room` with `gap`
|
|
34
|
+
* between them, as `repeat(auto-fill, minmax(min(…, 100%), 1fr))` counts
|
|
35
|
+
* them, and never fewer than one.
|
|
36
|
+
*/
|
|
37
|
+
function columnsOf(room, minItemWidth, gap) {
|
|
38
|
+
const least = typeof minItemWidth === "number" ? minItemWidth : room * Number.parseFloat(minItemWidth) / 100;
|
|
39
|
+
const cell = Math.min(least, room);
|
|
40
|
+
return Math.max(1, Math.floor((room + gap) / (cell + gap) + EPSILON));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Material Design's feed layout: a grid of comparable items that fits as many
|
|
44
|
+
* columns as the room allows, down to a single column when it allows only
|
|
45
|
+
* one.
|
|
46
|
+
*
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <Feed minItemWidth={260}>
|
|
49
|
+
* {items.map((item) => (
|
|
50
|
+
* <Card key={item.id} style={FILL}>…</Card>
|
|
51
|
+
* ))}
|
|
52
|
+
* </Feed>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* Layout only: it paints no surface. Each element it is handed sits in a
|
|
56
|
+
* cell of the feed's, which is what sizes it: a fragment counts as the items
|
|
57
|
+
* it holds and `null` as none, while a component counts as one item whatever
|
|
58
|
+
* it renders, since a grid on native sees elements rather than what they
|
|
59
|
+
* draw.
|
|
60
|
+
*
|
|
61
|
+
* It reads the room it is in rather than the width of the window, so a feed
|
|
62
|
+
* inside a pane reflows with the pane.
|
|
63
|
+
*
|
|
64
|
+
* `style`, `ref` and `testID` land on the outer `View`, and a `style` there
|
|
65
|
+
* applies over the feed's own.
|
|
66
|
+
*/
|
|
67
|
+
function Feed(t0) {
|
|
68
|
+
const $ = c(16);
|
|
69
|
+
let children;
|
|
70
|
+
let props;
|
|
71
|
+
let style;
|
|
72
|
+
let t1;
|
|
73
|
+
if ($[0] !== t0) {
|
|
74
|
+
({children, minItemWidth: t1, style, ...props} = t0);
|
|
75
|
+
$[0] = t0;
|
|
76
|
+
$[1] = children;
|
|
77
|
+
$[2] = props;
|
|
78
|
+
$[3] = style;
|
|
79
|
+
$[4] = t1;
|
|
80
|
+
} else {
|
|
81
|
+
children = $[1];
|
|
82
|
+
props = $[2];
|
|
83
|
+
style = $[3];
|
|
84
|
+
t1 = $[4];
|
|
85
|
+
}
|
|
86
|
+
const minItemWidth = t1 === void 0 ? DEFAULT_MIN_ITEM_WIDTH : t1;
|
|
87
|
+
const theme = useTheme();
|
|
88
|
+
const own = stylesOf(theme);
|
|
89
|
+
const dimensions = useWindowDimensions();
|
|
90
|
+
const [measured, setMeasured] = useState();
|
|
91
|
+
const room = measured ?? dimensions.width;
|
|
92
|
+
const gap = theme.spacing.xl;
|
|
93
|
+
const columns = columnsOf(room, minItemWidth, gap);
|
|
94
|
+
const share = shareOf(room, columns, gap);
|
|
95
|
+
const T0 = View;
|
|
96
|
+
const T1 = View;
|
|
97
|
+
let t2;
|
|
98
|
+
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
99
|
+
t2 = widthTo(setMeasured);
|
|
100
|
+
$[5] = t2;
|
|
101
|
+
} else t2 = $[5];
|
|
102
|
+
const t3 = composeStyles(styles.grid, own.grid);
|
|
103
|
+
const t5 = cellsOf(children, columns).map((t4) => {
|
|
104
|
+
const { item, key } = t4;
|
|
105
|
+
return /* @__PURE__ */ jsx(View, {
|
|
106
|
+
style: composeStyles(styles.cell, share),
|
|
107
|
+
children: item
|
|
108
|
+
}, key);
|
|
109
|
+
});
|
|
110
|
+
let t6;
|
|
111
|
+
if ($[6] !== T1 || $[7] !== t2 || $[8] !== t3 || $[9] !== t5) {
|
|
112
|
+
t6 = /* @__PURE__ */ jsx(T1, {
|
|
113
|
+
onLayout: t2,
|
|
114
|
+
style: t3,
|
|
115
|
+
children: t5
|
|
116
|
+
});
|
|
117
|
+
$[6] = T1;
|
|
118
|
+
$[7] = t2;
|
|
119
|
+
$[8] = t3;
|
|
120
|
+
$[9] = t5;
|
|
121
|
+
$[10] = t6;
|
|
122
|
+
} else t6 = $[10];
|
|
123
|
+
let t7;
|
|
124
|
+
if ($[11] !== T0 || $[12] !== props || $[13] !== style || $[14] !== t6) {
|
|
125
|
+
t7 = /* @__PURE__ */ jsx(T0, {
|
|
126
|
+
...props,
|
|
127
|
+
style,
|
|
128
|
+
children: t6
|
|
129
|
+
});
|
|
130
|
+
$[11] = T0;
|
|
131
|
+
$[12] = props;
|
|
132
|
+
$[13] = style;
|
|
133
|
+
$[14] = t6;
|
|
134
|
+
$[15] = t7;
|
|
135
|
+
} else t7 = $[15];
|
|
136
|
+
return t7;
|
|
137
|
+
}
|
|
138
|
+
function itemsOf(children, within) {
|
|
139
|
+
return Children.toArray(children).flatMap((item, at) => {
|
|
140
|
+
if (!isValidElement(item)) return [{
|
|
141
|
+
item,
|
|
142
|
+
key: `${within}item-${at}`
|
|
143
|
+
}];
|
|
144
|
+
const key = `${within}${item.key ?? `item-${at}`}`;
|
|
145
|
+
return item.type === Fragment ? itemsOf(item.props.children, key) : [{
|
|
146
|
+
item,
|
|
147
|
+
key
|
|
148
|
+
}];
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A cell's share of a line as a style: an equal part of the room left after
|
|
153
|
+
* the gaps, less the rounding the cells grow back from.
|
|
154
|
+
*/
|
|
155
|
+
function shareOf(room, columns, gap) {
|
|
156
|
+
const share = (room - gap * (columns - 1)) / columns;
|
|
157
|
+
return { flexBasis: Math.max(0, share - ROUNDING) };
|
|
158
|
+
}
|
|
159
|
+
function widthTo(onMeasure) {
|
|
160
|
+
return (event) => {
|
|
161
|
+
onMeasure(event.nativeEvent.layout.width);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { Feed };
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["ComponentRef","ReactNode","Ref","LayoutChangeEvent","ViewProps","ViewStyle","Children","Fragment","isValidElement","useState","StyleSheet","useWindowDimensions","View","useTheme","composeStyles","themedStyles","DEFAULT_MIN_ITEM_WIDTH","ROUNDING","EPSILON","styles","create","cell","flexGrow","flexShrink","minWidth","grid","alignSelf","flexDirection","flexWrap","stylesOf","spacing","columnGap","xl","rowGap","Cell","item","ReturnType","toArray","key","FeedProps","Omit","children","minItemWidth","ref","cellsOf","columns","cells","itemsOf","at","length","push","columnsOf","room","NonNullable","gap","least","Number","parseFloat","Math","min","max","floor","Feed","t0","$","_c","props","style","t1","undefined","theme","own","dimensions","measured","setMeasured","width","share","shareOf","T0","T1","t2","Symbol","for","widthTo","t3","t5","map","t4","t6","t7","within","flatMap","type","flexBasis","onMeasure","event","nativeEvent","layout","_c"],"sources":["../../../src/components/feed/index.tsx"],"sourcesContent":["import type { ComponentRef, ReactNode, Ref } from 'react'\nimport type { LayoutChangeEvent, ViewProps, ViewStyle } from 'react-native'\n\nimport { Children, Fragment, isValidElement, useState } from 'react'\nimport { StyleSheet, useWindowDimensions, View } from 'react-native'\n\nimport { useTheme } from '../../theme/scope'\nimport { composeStyles, themedStyles } from '../../theme/styles'\n\n// Material Design's example minimum for an adaptive grid cell, and the only\n// number the spec puts on one. It is a floor rather than a recommendation: how\n// narrow a cell can get before its contents stop making sense is a property of\n// the contents, which is why Material Design leaves it a parameter. Most feeds\n// should say what theirs is instead of taking this.\nconst DEFAULT_MIN_ITEM_WIDTH = 180\n\n// How far under its share of the line a cell starts, before it grows back to\n// it. The layout rounds every box to the device's pixels, so cells summing to\n// exactly the room could come out a fraction wider than it and wrap the last\n// one onto a line of its own.\nconst ROUNDING = 0.5\n\n// Room for rounding in the width the layout reports, so a room exactly wide\n// enough for one more column is not short of it by a fraction of a dp.\nconst EPSILON = 1e-6\n\n// The third of Material Design's canonical layouts, after list-detail and\n// supporting pane, as kanso-ui's Feed draws it: one pane arranged into a grid\n// of comparable things, described by its cell rather than by its columns.\n// Compose spells it `GridCells.Adaptive(minSize)`: every column is at least\n// that wide, the grid fits as many as it can, and always at least one, which\n// takes the whole width even where that is narrower than the minimum.\n//\n// React Native has no grid, so the feed works out the column count itself\n// from the room it is given, and wraps the items into lines of that many\n// equal cells. The last line is filled out with empty cells, which is web's\n// `auto-fill` rather than `auto-fit`: two items in a line with room for four\n// stay a cell wide rather than stretching to share it. Every cell of a line is\n// as tall as its tallest item, as grid cells are.\n//\n// The room is the width of the grid inside the feed's own padding, which the\n// layout reports once the feed has drawn, so a feed inside a pane reflows\n// with the pane rather than with the window. Before that report arrives the\n// first render guesses the window's width, the room a feed most often has.\n//\n// Every cell is a child of the one grid, so an item keeps its place in the\n// tree, and whatever state it holds, as the column count changes.\n//\n// It virtualises nothing, as on web: every item is drawn whether or not it is\n// on screen. A feed of hundreds of items is a `FlatList` with `numColumns`,\n// which draws only what can be seen.\nconst styles = StyleSheet.create({\n // A cell grows back to its share of the line from under it, and shrinks\n // past its content rather than overflowing the line.\n cell: {\n flexGrow: 1,\n flexShrink: 1,\n minWidth: 0,\n },\n // The grid spans the feed's content box, whatever the feed aligns its\n // content to, since its width is the room the columns are counted in.\n grid: {\n alignSelf: 'stretch',\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n})\n\nconst stylesOf = themedStyles(({ spacing }) =>\n StyleSheet.create({\n // The gap between lines and the one between cells, which web's grid\n // spells `gap: spacing.xl` for both.\n grid: {\n columnGap: spacing.xl,\n rowGap: spacing.xl,\n },\n }),\n)\n\ntype Cell = {\n readonly item?: ReturnType<typeof Children.toArray>[number]\n readonly key: string\n}\n\ntype FeedProps = Omit<ViewProps, 'children'> & {\n /**\n * The items, each laid into a cell of its own. An element is one item,\n * whatever it renders, so hand the feed the items themselves rather than a\n * component listing them; a fragment counts as the items it holds. A cell\n * is as tall as the tallest item in its line, and an item that should fill\n * that height, as a card in a grid does, sets `flexGrow: 1`.\n */\n readonly children?: ReactNode\n /**\n * How narrow a cell may get before the grid drops a column, in dp or as a\n * share of the room the feed is given. Every column is at least this wide\n * and the grid fits as many as the room allows, which is how Material\n * Design describes an adaptive grid: by its cell rather than by a column\n * count per window size. Given less room than this, the one column takes\n * the room it is given rather than overflowing it.\n *\n * Worth setting. The default is the figure Material Design's own example\n * uses, and it is a floor rather than advice: only the contents know how\n * narrow they can go.\n * @default 180\n */\n readonly minItemWidth?: `${number}%` | number\n readonly ref?: Ref<ComponentRef<typeof View>>\n}\n\n// The items as cells, the last line filled out with empty ones.\nfunction cellsOf(children: ReactNode, columns: number) {\n const cells = itemsOf(children, '')\n for (let at = cells.length; at % columns !== 0; at += 1) {\n cells.push({ key: `empty-${at}` })\n }\n return cells\n}\n\n/**\n * How many columns of at least `minItemWidth` fit in `room` with `gap`\n * between them, as `repeat(auto-fill, minmax(min(…, 100%), 1fr))` counts\n * them, and never fewer than one.\n */\nfunction columnsOf(\n room: number,\n minItemWidth: NonNullable<FeedProps['minItemWidth']>,\n gap: number,\n) {\n const least =\n typeof minItemWidth === 'number'\n ? minItemWidth\n : (room * Number.parseFloat(minItemWidth)) / 100\n const cell = Math.min(least, room)\n return Math.max(1, Math.floor((room + gap) / (cell + gap) + EPSILON))\n}\n\n/**\n * Material Design's feed layout: a grid of comparable items that fits as many\n * columns as the room allows, down to a single column when it allows only\n * one.\n *\n * ```tsx\n * <Feed minItemWidth={260}>\n * {items.map((item) => (\n * <Card key={item.id} style={FILL}>…</Card>\n * ))}\n * </Feed>\n * ```\n *\n * Layout only: it paints no surface. Each element it is handed sits in a\n * cell of the feed's, which is what sizes it: a fragment counts as the items\n * it holds and `null` as none, while a component counts as one item whatever\n * it renders, since a grid on native sees elements rather than what they\n * draw.\n *\n * It reads the room it is in rather than the width of the window, so a feed\n * inside a pane reflows with the pane.\n *\n * `style`, `ref` and `testID` land on the outer `View`, and a `style` there\n * applies over the feed's own.\n */\nfunction Feed({\n children,\n minItemWidth = DEFAULT_MIN_ITEM_WIDTH,\n style,\n ...props\n}: FeedProps) {\n const theme = useTheme()\n const own = stylesOf(theme)\n const dimensions = useWindowDimensions()\n const [measured, setMeasured] = useState<number>()\n const room = measured ?? dimensions.width\n const gap = theme.spacing.xl\n const columns = columnsOf(room, minItemWidth, gap)\n const share = shareOf(room, columns, gap)\n\n return (\n <View {...props} style={style}>\n <View\n onLayout={widthTo(setMeasured)}\n style={composeStyles<ViewStyle>(styles.grid, own.grid)}\n >\n {cellsOf(children, columns).map(({ item, key }) => (\n <View key={key} style={composeStyles<ViewStyle>(styles.cell, share)}>\n {item}\n </View>\n ))}\n </View>\n </View>\n )\n}\n\n// Each item as a cell, with a fragment's items in its place, as a grid on web\n// lays out what a fragment holds rather than the fragment. A cell takes the\n// key `Children.toArray` gives its element under the keys of the fragments\n// around it, or its place for a bare string or number, which takes none.\nfunction itemsOf(children: ReactNode, within: string): Cell[] {\n return Children.toArray(children).flatMap((item, at) => {\n if (!isValidElement<{ children?: ReactNode }>(item)) {\n return [{ item, key: `${within}item-${at}` }]\n }\n const key = `${within}${item.key ?? `item-${at}`}`\n return item.type === Fragment\n ? itemsOf(item.props.children, key)\n : [{ item, key }]\n })\n}\n\n/**\n * A cell's share of a line as a style: an equal part of the room left after\n * the gaps, less the rounding the cells grow back from.\n */\nfunction shareOf(room: number, columns: number, gap: number): ViewStyle {\n const share = (room - gap * (columns - 1)) / columns\n return { flexBasis: Math.max(0, share - ROUNDING) }\n}\n\n// A layout handler handing the width it reports to `onMeasure`. Built by a\n// call rather than written inline, which is what react-perf's\n// jsx-no-new-function-as-prop is after; the React Compiler memoises it.\nfunction widthTo(onMeasure: (width: number) => void) {\n return (event: LayoutChangeEvent) => {\n onMeasure(event.nativeEvent.layout.width)\n }\n}\n\nexport type { FeedProps }\n\nexport { Feed }\n"],"mappings":"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"}
|
|
@@ -17,8 +17,9 @@ type FormProps = {
|
|
|
17
17
|
* Called with the values when the form is submitted: each field with a
|
|
18
18
|
* `name` and not disabled, as the string a web form submits for it, so a
|
|
19
19
|
* number field's value is its number written out, and an empty one is
|
|
20
|
-
* `''`.
|
|
21
|
-
*
|
|
20
|
+
* `''`. A checkbox group's is the list of its ticked entries' values, an
|
|
21
|
+
* empty list while none is ticked. Under `native` it is not called while a
|
|
22
|
+
* field blocks the submission.
|
|
22
23
|
*/
|
|
23
24
|
readonly onSubmit?: (values: FormValues) => void;
|
|
24
25
|
readonly ref?: Ref<FormHandle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["ReactNode","Ref","useImperativeHandle","useMemo","useState","FormValidationBehavior","FormValues","ValidationErrors","createRegistry","FIELD_VALIDATION_BEHAVIOR","FormContext","submitOf","FormHandle","requestSubmit","FormProps","children","onSubmit","values","ref","validationBehavior","validationErrors","NO_ERRORS","Form","t0","$","_c","t1","t2","undefined","registry","t3","t4","state","t5","t6","t7","_c"],"sources":["../../../src/components/form/index.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react'\n\nimport { useImperativeHandle, useMemo, useState } from 'react'\n\nimport type {\n FormValidationBehavior,\n FormValues,\n ValidationErrors,\n} from '../../form'\n\nimport {\n createRegistry,\n FIELD_VALIDATION_BEHAVIOR,\n FormContext,\n submitOf,\n} from '../../form'\n\n// No Material Design page of its own, as on web: a form is the fields inside\n// it, and the text fields page is what each of them draws. The error a form\n// reports lands in the field's supporting text, in the error role, under the\n// box.\n//\n// Native has no form element, so this is a context around its fields rather\n// than an element of its own. It draws nothing and lays nothing out; a Stack\n// inside it is what spaces the fields. It hands each field inside it two\n// things, as React Aria's Form does on web: `validationErrors`, keyed by each\n// field's `name`, which is how a server's answer reaches the fields without\n// any of them changing, and `validationBehavior`, which every field reads in\n// place of its own. And it reserves each field's message line, so an error\n// that arrives later moves nothing below the field.\n//\n// Native has no browser to validate or submit either, so the form does both.\n// A Button with `type=\"submit\"` inside it submits it, as does\n// `requestSubmit()` on its ref, which is how the keyboard's return key does.\n\n/** What a form's ref holds. */\ntype FormHandle = {\n /**\n * Submits the form, as a Button with `type=\"submit\"` inside it does: under\n * `native` it is held back while a field blocks it, and otherwise\n * `onSubmit` is handed the values. Named after the web form's method that\n * does the same.\n */\n readonly requestSubmit: () => void\n}\n\ntype FormProps = {\n readonly children?: ReactNode\n /**\n * Called with the values when the form is submitted: each field with a\n * `name` and not disabled, as the string a web form submits for it, so a\n * number field's value is its number written out, and an empty one is\n * `''`. Under `native` it is not called while a field blocks the
|
|
1
|
+
{"version":3,"file":"index.js","names":["ReactNode","Ref","useImperativeHandle","useMemo","useState","FormValidationBehavior","FormValues","ValidationErrors","createRegistry","FIELD_VALIDATION_BEHAVIOR","FormContext","submitOf","FormHandle","requestSubmit","FormProps","children","onSubmit","values","ref","validationBehavior","validationErrors","NO_ERRORS","Form","t0","$","_c","t1","t2","undefined","registry","t3","t4","state","t5","t6","t7","_c"],"sources":["../../../src/components/form/index.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react'\n\nimport { useImperativeHandle, useMemo, useState } from 'react'\n\nimport type {\n FormValidationBehavior,\n FormValues,\n ValidationErrors,\n} from '../../form'\n\nimport {\n createRegistry,\n FIELD_VALIDATION_BEHAVIOR,\n FormContext,\n submitOf,\n} from '../../form'\n\n// No Material Design page of its own, as on web: a form is the fields inside\n// it, and the text fields page is what each of them draws. The error a form\n// reports lands in the field's supporting text, in the error role, under the\n// box.\n//\n// Native has no form element, so this is a context around its fields rather\n// than an element of its own. It draws nothing and lays nothing out; a Stack\n// inside it is what spaces the fields. It hands each field inside it two\n// things, as React Aria's Form does on web: `validationErrors`, keyed by each\n// field's `name`, which is how a server's answer reaches the fields without\n// any of them changing, and `validationBehavior`, which every field reads in\n// place of its own. And it reserves each field's message line, so an error\n// that arrives later moves nothing below the field.\n//\n// Native has no browser to validate or submit either, so the form does both.\n// A Button with `type=\"submit\"` inside it submits it, as does\n// `requestSubmit()` on its ref, which is how the keyboard's return key does.\n\n/** What a form's ref holds. */\ntype FormHandle = {\n /**\n * Submits the form, as a Button with `type=\"submit\"` inside it does: under\n * `native` it is held back while a field blocks it, and otherwise\n * `onSubmit` is handed the values. Named after the web form's method that\n * does the same.\n */\n readonly requestSubmit: () => void\n}\n\ntype FormProps = {\n readonly children?: ReactNode\n /**\n * Called with the values when the form is submitted: each field with a\n * `name` and not disabled, as the string a web form submits for it, so a\n * number field's value is its number written out, and an empty one is\n * `''`. A checkbox group's is the list of its ticked entries' values, an\n * empty list while none is ticked. Under `native` it is not called while a\n * field blocks the submission.\n */\n readonly onSubmit?: (values: FormValues) => void\n readonly ref?: Ref<FormHandle>\n /**\n * How the fields inside validate. `aria` marks a field invalid and shows\n * its error as soon as the field says so, through its `validate`, and\n * lets the form submit regardless. `native` holds the submission back\n * while a field is required and empty or rejected by its `validate`, shows\n * each such field's error once submission is tried, and focuses the first\n * of them.\n *\n * Under `aria`, moving focus after a server answers is the call site's.\n * Each error is announced as it appears under its field, but nothing\n * moves, because no part of the form knows a round trip happened:\n * `validationErrors` is a prop rather than an event, so a form cannot tell\n * a submission coming back from a first render that was given errors to\n * begin with. Focus the first field that came back invalid through its\n * `inputRef`, as the Async submit story does.\n * @default 'aria'\n */\n readonly validationBehavior?: FormValidationBehavior\n /**\n * Errors to show under the fields, keyed by each field's `name`, such as\n * what a server sent back: one message, or several shown as one line. A\n * field's error stays until the field is edited, and a new object shows\n * them all again.\n */\n readonly validationErrors?: ValidationErrors\n}\n\nconst NO_ERRORS: ValidationErrors = {}\n\n/**\n * A form: the fields inside it and what they are told about validation. Pass\n * `validationErrors`, an object keyed by field `name`, to show what a server\n * sent back under each field, and `validationBehavior=\"native\"` to hold the\n * submission back while a required field is empty or a field's `validate`\n * rejects its value. A Button with `type=\"submit\"` inside it submits it, and\n * `onSubmit` is handed the values by name.\n *\n * ```tsx\n * <Form onSubmit={(values) => save(values)}>\n * <Stack gap=\"md\">\n * <TextField label=\"Headline\" name=\"headline\" />\n * <Button type=\"submit\">Save changes</Button>\n * </Stack>\n * </Form>\n * ```\n *\n * Handing `validationErrors` back from a submission is where a reader has to\n * be told something arrived: see `validationBehavior` for what the form does\n * and what it leaves to the call site.\n *\n * A form also reserves each field's message line. A field on its own draws\n * that line only once it has something to say, so an error arriving after a\n * submit or an async check makes the field taller and moves everything below\n * it down the screen. Inside a form the line is there from the start, empty,\n * and nothing moves when it fills.\n *\n * It draws nothing, so it takes no `style`; its ref is a handle whose\n * `requestSubmit()` submits it.\n */\nfunction Form({\n children,\n onSubmit,\n ref,\n validationBehavior = FIELD_VALIDATION_BEHAVIOR,\n validationErrors = NO_ERRORS,\n}: FormProps) {\n const [registry] = useState(createRegistry)\n const requestSubmit = submitOf(registry, validationBehavior, onSubmit)\n const state = useMemo(\n () => ({ registry, requestSubmit, validationBehavior, validationErrors }),\n [registry, requestSubmit, validationBehavior, validationErrors],\n )\n\n useImperativeHandle(ref, () => ({ requestSubmit }), [requestSubmit])\n\n return <FormContext value={state}>{children}</FormContext>\n}\n\nexport { Form }\nexport type { FormHandle, FormProps }\n"],"mappings":";;;;;AAqFA,MAAMqB,YAA8B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCrC,SAAAC,KAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAc,MAAA,EAAAV,UAAAC,UAAAE,KAAAC,oBAAAO,IAAAN,kBAAAO,OAAAJ;CAIZ,MAAAJ,qBAAAO,OAAAE,KAAAA,IAAAnB,4BAAAiB;CACA,MAAAN,mBAAAO,OAAAC,KAAAA,IAAAP,YAAAM;CAEA,MAAA,CAAAE,YAAmBzB,SAASI,cAAc;CAAC,IAAAsB;CAAA,IAAAN,EAAA,OAAAR,YAAAQ,EAAA,OAAAK,YAAAL,EAAA,OAAAL,oBAAA;EACrBW,KAAAnB,SAASkB,UAAUV,oBAAoBH,QAAQ;EAACQ,EAAA,KAAAR;EAAAQ,EAAA,KAAAK;EAAAL,EAAA,KAAAL;EAAAK,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAtE,MAAAX,gBAAsBiB;CAAgD,IAAAC;CAAA,IAAAP,EAAA,OAAAK,YAAAL,EAAA,OAAAX,iBAAAW,EAAA,OAAAL,sBAAAK,EAAA,OAAAJ,kBAAA;EAE7DW,KAAA;GAAAF;GAAAhB;GAAAM;GAAAC;EAAgE;EAACI,EAAA,KAAAK;EAAAL,EAAA,KAAAX;EAAAW,EAAA,KAAAL;EAAAK,EAAA,KAAAJ;EAAAI,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAD1E,MAAAQ,QACSD;CAER,IAAAE;CAAA,IAAAC;CAAA,IAAAV,EAAA,OAAAX,eAAA;EAEwBoB,YAAO,EAAApB,cAAgB;EAAIqB,KAAA,CAACrB,aAAa;EAACW,EAAA,KAAAX;EAAAW,EAAA,MAAAS;EAAAT,EAAA,MAAAU;CAAA,OAAA;EAAAD,KAAAT,EAAA;EAAAU,KAAAV,EAAA;CAAA;CAAnEtB,oBAAoBgB,KAAKe,IAA2BC,EAAe;CAAC,IAAAC;CAAA,IAAAX,EAAA,QAAAT,YAAAS,EAAA,QAAAQ,OAAA;EAE7DG,KAAA,oBAAC,aAAD;GAAoBH,OAAAA;GAAQjB;EAAhB,CAAA;EAAuCS,EAAA,MAAAT;EAAAS,EAAA,MAAAQ;EAAAR,EAAA,MAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,OAAnDW;AAAmD"}
|
|
@@ -19,6 +19,8 @@ type IconButtonProps = (ButtonLinkForm | ButtonPressForm | ButtonToggleForm) & O
|
|
|
19
19
|
* @default false
|
|
20
20
|
*/
|
|
21
21
|
readonly disableRipple?: boolean;
|
|
22
|
+
/** The key a ButtonGroup that selects reports the button by. */
|
|
23
|
+
readonly id?: string;
|
|
22
24
|
/**
|
|
23
25
|
* Draws the button disabled, and takes no presses.
|
|
24
26
|
* @default false
|
|
@@ -30,7 +32,7 @@ type IconButtonProps = (ButtonLinkForm | ButtonPressForm | ButtonToggleForm) & O
|
|
|
30
32
|
* the icon buttons spec page's XS to XL, and the same heights `Button`
|
|
31
33
|
* uses, so the two line up beside each other in a row. The icon is 20dp,
|
|
32
34
|
* 24dp, 24dp, 32dp and 40dp in turn.
|
|
33
|
-
* @default 'md'
|
|
35
|
+
* @default the size of the ButtonGroup around it, else 'md'
|
|
34
36
|
*/
|
|
35
37
|
readonly size?: IconButtonSize;
|
|
36
38
|
readonly style?: StyleProp<ViewStyle>;
|
|
@@ -62,7 +64,7 @@ type IconButtonVariant = 'filled' | 'outlined' | 'standard' | 'tonal';
|
|
|
62
64
|
* through `hitSlop`, which a `hitSlop` of the call site's own replaces.
|
|
63
65
|
* `style`, `ref` and `testID` land on the `Pressable`.
|
|
64
66
|
*/
|
|
65
|
-
declare function IconButton({ children, defaultSelected, delayLongPress, disableRipple, hitSlop: ownHitSlop, href, isDisabled, isPending, isSelected, onBlur, onChange, onFocus, onHoverIn, onHoverOut, onLayout, onLongPress, onPress, onPressIn, onPressOut, pendingLabel, ref, size, slot, style, type, variant, ...props }: IconButtonProps): import("react").JSX.Element;
|
|
67
|
+
declare function IconButton({ accessibilityHint, children, defaultSelected, delayLongPress, disableRipple, hitSlop: ownHitSlop, href, id, isDisabled: ownDisabled, isPending, isSelected, onBlur, onChange, onFocus, onHoverIn, onHoverOut, onLayout, onLongPress, onPress, onPressIn, onPressOut, pendingLabel, ref, size: ownSize, slot, style, type, variant, ...props }: IconButtonProps): import("react").JSX.Element;
|
|
66
68
|
//#endregion
|
|
67
69
|
export { IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant };
|
|
68
70
|
//# sourceMappingURL=index.d.ts.map
|