@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":"chevron.js","names":["ColorValue","useEffect","I18nManager","Animated","Easing","useAnimatedStyle","useReducedMotion","useSharedValue","withTiming","ChevronEndGlyph","useTheme","ExpandChevron","t0","$","_c","color","isExpanded","motion","reduceMotion","turn","isRTL","angle","t1","t2","set","duration","durationShort3","easing","bezier","easingStandard","turned","transform","rotate","get","t3","t4","_c"],"sources":["../../src/disclosure/chevron.tsx"],"sourcesContent":["import type { ColorValue } from 'react-native'\n\nimport { useEffect } from 'react'\nimport { I18nManager } from 'react-native'\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\n\nimport { ChevronEndGlyph } from '../glyphs'\nimport { useTheme } from '../theme/scope'\n\n/**\n * The chevron of something that opens in place, a Disclosure's header or a\n * Tree's row, pointing at what it opens and turned a quarter to point down\n * once it is open, on short3 and the standard curve, and at once under\n * reduced motion. The glyph mirrors itself under right-to-left, so the turn\n * goes the other way there to point it down too. It takes its size from the\n * slot it sits in, and its colour too unless given one.\n */\nfunction ExpandChevron({\n color,\n isExpanded,\n}: {\n readonly color?: ColorValue\n readonly isExpanded: boolean\n}) {\n const { motion } = useTheme()\n const reduceMotion = useReducedMotion()\n const turn = isExpanded ? (I18nManager.isRTL ? -90 : 90) : 0\n const angle = useSharedValue(turn)\n\n useEffect(() => {\n angle.set(\n reduceMotion\n ? turn\n : withTiming(turn, {\n duration: motion.durationShort3,\n easing: Easing.bezier(...motion.easingStandard),\n }),\n )\n }, [angle, motion, reduceMotion, turn])\n\n const turned = useAnimatedStyle(() => {\n 'worklet'\n return { transform: [{ rotate: `${angle.get()}deg` }] }\n })\n\n return (\n <Animated.View style={turned}>\n <ChevronEndGlyph color={color} />\n </Animated.View>\n )\n}\n\nexport { ExpandChevron }\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,SAAAW,cAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAuB,MAAA,EAAAC,OAAAC,eAAAJ;CAOrB,MAAA,EAAAK,WAAmBP,SAAS;CAC5B,MAAAQ,eAAqBZ,iBAAiB;CACtC,MAAAa,OAAaH,aAAcd,YAAWkB,QAAX,MAAA,KAAd;CACb,MAAAC,QAAcd,eAAeY,IAAI;CAAC,IAAAG;CAAA,IAAAC;CAAA,IAAAV,EAAA,OAAAQ,SAAAR,EAAA,OAAAI,UAAAJ,EAAA,OAAAK,gBAAAL,EAAA,OAAAM,MAAA;EAExBG,WAAA;GACRD,MAAKG,IACHN,eAAAC,OAEIX,WAAWW,MAAM;IAAAM,UACLR,OAAMS;IAAeC,QACvBvB,OAAMwB,OAAO,GAAIX,OAAMY,cAAe;GAChD,CAAC,CACP;EAAC;EACAN,KAAA;GAACF;GAAOJ;GAAQC;GAAcC;EAAI;EAACN,EAAA,KAAAQ;EAAAR,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;EAAAL,EAAA,KAAAM;EAAAN,EAAA,KAAAS;EAAAT,EAAA,KAAAU;CAAA,OAAA;EAAAD,KAAAT,EAAA;EAAAU,KAAAV,EAAA;CAAA;CATtCZ,UAAUqB,IASPC,EAAmC;CAEtC,MAAAO,SAAezB,uBAAiB;EAAA;EAAA,OAEvB,EAAA0B,WAAa,CAAC,EAAAC,QAAU,GAAGX,MAAKY,IAAK,EAAC,KAAM,CAAC,EAAE;CAAC,CACxD;CAAC,IAAAC;CAAA,IAAArB,EAAA,OAAAE,OAAA;EAIEmB,KAAA,oBAAC,iBAAD,EAAwBnB,MAAK,CAAA;EAAIF,EAAA,KAAAE;EAAAF,EAAA,KAAAqB;CAAA,OAAAA,KAAArB,EAAA;CAAA,IAAAsB;CAAA,IAAAtB,EAAA,OAAAqB,MAAArB,EAAA,OAAAiB,QAAA;EADnCK,KAAA,oBAAA,SAAA,MAAA;GAAsBL,OAAAA;GACpBI,UAAAA;EACF,CAAA;EAAgBrB,EAAA,KAAAqB;EAAArB,EAAA,KAAAiB;EAAAjB,EAAA,MAAAsB;CAAA,OAAAA,KAAAtB,EAAA;CAAA,OAFhBsB;AAEgB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["DisclosureGroupState","createContext","DisclosureGroupStateContext"],"sources":["../../src/disclosure/index.ts"],"sourcesContent":["import type { DisclosureGroupState } from 'react-stately/useDisclosureGroupState'\n\nimport { createContext } from 'react'\n\n// The open keys of the DisclosureGroup around a Disclosure, as React Aria's\n// group state context is on web. A Disclosure inside one reads whether it is\n// open from the group's keys, under its `id`, and toggles that key when its\n// header is pressed. Null is no group, and a Disclosure then keeps its own\n// state.\nconst DisclosureGroupStateContext = createContext<DisclosureGroupState | null>(\n null,\n)\n\nexport { DisclosureGroupStateContext }\n"],"mappings":";;AASA,MAAME,8BAA8BD,cAClC,IACF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PickedFile } from "../files/index.js";
|
|
2
|
+
//#region src/drop/index.d.ts
|
|
3
|
+
/** The kinds of thing a drag carries, asked about one MIME type at a time. */
|
|
4
|
+
type DragTypes = {
|
|
5
|
+
readonly has: (type: string) => boolean;
|
|
6
|
+
};
|
|
7
|
+
/** Where something being dragged came over the target, from its top start corner. */
|
|
8
|
+
type DropEnterEvent = {
|
|
9
|
+
readonly type: 'dropenter';
|
|
10
|
+
readonly x: number;
|
|
11
|
+
readonly y: number;
|
|
12
|
+
};
|
|
13
|
+
/** What landed on the target, where, and what the drop does with it. */
|
|
14
|
+
type DropEvent = {
|
|
15
|
+
readonly dropOperation: Exclude<DropOperation, 'cancel'>;
|
|
16
|
+
readonly items: readonly DropItem[];
|
|
17
|
+
readonly type: 'drop';
|
|
18
|
+
readonly x: number;
|
|
19
|
+
readonly y: number;
|
|
20
|
+
};
|
|
21
|
+
/** Where something being dragged left the target. */
|
|
22
|
+
type DropExitEvent = {
|
|
23
|
+
readonly type: 'dropexit';
|
|
24
|
+
readonly x: number;
|
|
25
|
+
readonly y: number;
|
|
26
|
+
};
|
|
27
|
+
type DropItem = FileDropItem | TextDropItem;
|
|
28
|
+
/** What a drop does with what it carries, as web's drag and drop names it. */
|
|
29
|
+
type DropOperation = 'cancel' | 'copy' | 'link' | 'move';
|
|
30
|
+
/**
|
|
31
|
+
* A file dropped or picked: the file itself, and its contents as text, read
|
|
32
|
+
* when asked for.
|
|
33
|
+
*/
|
|
34
|
+
type FileDropItem = PickedFile & {
|
|
35
|
+
readonly getText: () => Promise<string>;
|
|
36
|
+
readonly kind: 'file';
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Text dropped from another page or app, in each of the MIME types it was
|
|
40
|
+
* dragged as, such as `text/plain` and `text/uri-list`. Only React Native
|
|
41
|
+
* Web takes one.
|
|
42
|
+
*/
|
|
43
|
+
type TextDropItem = {
|
|
44
|
+
readonly getText: (type: string) => Promise<string>;
|
|
45
|
+
readonly kind: 'text';
|
|
46
|
+
readonly types: ReadonlySet<string>;
|
|
47
|
+
};
|
|
48
|
+
/** Whether an item is a file, for picking the files out of a drop. */
|
|
49
|
+
declare function isFileDropItem(item: DropItem): item is FileDropItem;
|
|
50
|
+
/** Whether an item is dropped text, for picking it out of a drop. */
|
|
51
|
+
declare function isTextDropItem(item: DropItem): item is TextDropItem;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { type DragTypes, type DropEnterEvent, type DropEvent, type DropExitEvent, type DropItem, type DropOperation, type FileDropItem, type TextDropItem, isFileDropItem, isTextDropItem };
|
|
54
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//#region src/drop/index.ts
|
|
2
|
+
const EVERY = [
|
|
3
|
+
"copy",
|
|
4
|
+
"link",
|
|
5
|
+
"move"
|
|
6
|
+
];
|
|
7
|
+
const ALLOWED = {
|
|
8
|
+
all: EVERY,
|
|
9
|
+
copy: ["copy"],
|
|
10
|
+
copyLink: ["copy", "link"],
|
|
11
|
+
copyMove: ["copy", "move"],
|
|
12
|
+
link: ["link"],
|
|
13
|
+
linkMove: ["link", "move"],
|
|
14
|
+
move: ["move"],
|
|
15
|
+
none: [],
|
|
16
|
+
uninitialized: EVERY
|
|
17
|
+
};
|
|
18
|
+
const FILES = "Files";
|
|
19
|
+
function dragTypesOf(transfer) {
|
|
20
|
+
const files = Array.from(transfer.items, (item) => item.kind === "file" ? item.type : void 0).filter((type) => type !== void 0);
|
|
21
|
+
return typesOf([...transfer.types.filter((type) => type !== FILES), ...files]);
|
|
22
|
+
}
|
|
23
|
+
function droppedItemsOf(transfer) {
|
|
24
|
+
const files = Array.from(transfer.files, (file) => ({
|
|
25
|
+
getText: async () => file.text(),
|
|
26
|
+
kind: "file",
|
|
27
|
+
name: file.name,
|
|
28
|
+
size: file.size,
|
|
29
|
+
type: file.type,
|
|
30
|
+
uri: URL.createObjectURL(file)
|
|
31
|
+
}));
|
|
32
|
+
const texts = new Map(transfer.types.filter((type) => type !== FILES).map((type) => [type, transfer.getData(type)]));
|
|
33
|
+
if (texts.size === 0) return files;
|
|
34
|
+
const text = {
|
|
35
|
+
getText: async (type) => Promise.resolve(texts.get(type) ?? ""),
|
|
36
|
+
kind: "text",
|
|
37
|
+
types: new Set(texts.keys())
|
|
38
|
+
};
|
|
39
|
+
return [...files, text];
|
|
40
|
+
}
|
|
41
|
+
/** A picked file as a file drop item, whose text is read from its URI. */
|
|
42
|
+
function fileItemOf(file) {
|
|
43
|
+
return {
|
|
44
|
+
...file,
|
|
45
|
+
getText: async () => {
|
|
46
|
+
return (await fetch(file.uri)).text();
|
|
47
|
+
},
|
|
48
|
+
kind: "file"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Whether drops can be watched on a node: under React Native Web, where a
|
|
53
|
+
* View's node is its DOM element.
|
|
54
|
+
*/
|
|
55
|
+
function isDropTarget(node) {
|
|
56
|
+
return typeof node === "object" && node !== null && "addEventListener" in node && "removeEventListener" in node;
|
|
57
|
+
}
|
|
58
|
+
/** Whether an item is a file, for picking the files out of a drop. */
|
|
59
|
+
function isFileDropItem(item) {
|
|
60
|
+
return item.kind === "file";
|
|
61
|
+
}
|
|
62
|
+
/** Whether an item is dropped text, for picking it out of a drop. */
|
|
63
|
+
function isTextDropItem(item) {
|
|
64
|
+
return item.kind === "text";
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The operation a drop of these types would do: the call site's answer, else
|
|
68
|
+
* the first the drag allows, else none at all.
|
|
69
|
+
*/
|
|
70
|
+
function operationOf(handlers, types, allowed) {
|
|
71
|
+
const first = allowed.at(0);
|
|
72
|
+
if (first === void 0) return "cancel";
|
|
73
|
+
return handlers.getDropOperation?.(types, allowed) ?? first;
|
|
74
|
+
}
|
|
75
|
+
/** The kinds of thing a set of items carries, for `getDropOperation`. */
|
|
76
|
+
function typesOf(types) {
|
|
77
|
+
const set = new Set(types);
|
|
78
|
+
return { has: (type) => set.has(type) };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Takes HTML5 drag and drop on a React Native Web element, as web's React
|
|
82
|
+
* Aria does on a DropZone: `onDropEnter` once something the target will take
|
|
83
|
+
* comes over it, `onDropExit` once it leaves or lands, and `onDrop` with what
|
|
84
|
+
* landed. `handlers` is read at each event, so it can follow the props. A
|
|
85
|
+
* drag crossing the target's own children stays over it, counted in and out
|
|
86
|
+
* as the browser reports each. While `isDisabled` returns true nothing is
|
|
87
|
+
* taken, and the browser shows that nothing will be. It hands back what
|
|
88
|
+
* stops it.
|
|
89
|
+
*/
|
|
90
|
+
function watchDrops(target, handlers, isDisabled, setOver) {
|
|
91
|
+
let depth = 0;
|
|
92
|
+
let over = false;
|
|
93
|
+
const point = (event) => {
|
|
94
|
+
const box = target.getBoundingClientRect?.() ?? {
|
|
95
|
+
left: 0,
|
|
96
|
+
top: 0
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
x: event.clientX - box.left,
|
|
100
|
+
y: event.clientY - box.top
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const operation = (event) => event.dataTransfer === null || isDisabled() ? "cancel" : operationOf(handlers(), dragTypesOf(event.dataTransfer), ALLOWED[event.dataTransfer.effectAllowed] ?? EVERY);
|
|
104
|
+
const leave = (event) => {
|
|
105
|
+
if (over) {
|
|
106
|
+
over = false;
|
|
107
|
+
setOver(false);
|
|
108
|
+
handlers().onDropExit?.({
|
|
109
|
+
type: "dropexit",
|
|
110
|
+
...point(event)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const onDragEnter = (event) => {
|
|
115
|
+
depth += 1;
|
|
116
|
+
if (depth === 1 && operation(event) !== "cancel") {
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
over = true;
|
|
119
|
+
setOver(true);
|
|
120
|
+
handlers().onDropEnter?.({
|
|
121
|
+
type: "dropenter",
|
|
122
|
+
...point(event)
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const onDragOver = (event) => {
|
|
127
|
+
const chosen = operation(event);
|
|
128
|
+
if (event.dataTransfer !== null) event.dataTransfer.dropEffect = chosen === "cancel" ? "none" : chosen;
|
|
129
|
+
if (chosen !== "cancel") event.preventDefault();
|
|
130
|
+
};
|
|
131
|
+
const onDragLeave = (event) => {
|
|
132
|
+
depth = Math.max(0, depth - 1);
|
|
133
|
+
if (depth === 0) leave(event);
|
|
134
|
+
};
|
|
135
|
+
const onDrop = (event) => {
|
|
136
|
+
const chosen = operation(event);
|
|
137
|
+
depth = 0;
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
if (chosen !== "cancel" && event.dataTransfer !== null) handlers().onDrop?.({
|
|
140
|
+
dropOperation: chosen,
|
|
141
|
+
items: droppedItemsOf(event.dataTransfer),
|
|
142
|
+
type: "drop",
|
|
143
|
+
...point(event)
|
|
144
|
+
});
|
|
145
|
+
leave(event);
|
|
146
|
+
};
|
|
147
|
+
target.addEventListener("dragenter", onDragEnter);
|
|
148
|
+
target.addEventListener("dragover", onDragOver);
|
|
149
|
+
target.addEventListener("dragleave", onDragLeave);
|
|
150
|
+
target.addEventListener("drop", onDrop);
|
|
151
|
+
return () => {
|
|
152
|
+
target.removeEventListener("dragenter", onDragEnter);
|
|
153
|
+
target.removeEventListener("dragover", onDragOver);
|
|
154
|
+
target.removeEventListener("dragleave", onDragLeave);
|
|
155
|
+
target.removeEventListener("drop", onDrop);
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { fileItemOf, isDropTarget, isFileDropItem, isTextDropItem, operationOf, typesOf, watchDrops };
|
|
160
|
+
|
|
161
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["PickedFile","DomDataTransfer","dropEffect","effectAllowed","files","ArrayLike","DomFile","getData","format","items","kind","type","types","DomDragEvent","clientX","clientY","dataTransfer","preventDefault","DomDropTarget","addEventListener","listener","event","getBoundingClientRect","left","top","removeEventListener","Blob","name","text","Promise","DragTypes","has","DropEnterEvent","x","y","DropEvent","dropOperation","Exclude","DropOperation","DropItem","DropExitEvent","DropHandlers","getDropOperation","allowedOperations","onDrop","onDropEnter","onDropExit","FileDropItem","TextDropItem","getText","ReadonlySet","EVERY","ALLOWED","Readonly","Partial","Record","all","copy","copyLink","copyMove","link","linkMove","move","none","uninitialized","FILES","dragTypesOf","transfer","Array","from","item","undefined","filter","typesOf","droppedItemsOf","file","size","uri","URL","createObjectURL","texts","Map","map","resolve","get","Set","keys","fileItemOf","response","fetch","isDropTarget","node","isFileDropItem","isTextDropItem","operationOf","handlers","allowed","first","at","Iterable","set","watchDrops","target","isDisabled","setOver","isOver","depth","over","point","box","operation","leave","onDragEnter","onDragOver","chosen","onDragLeave","Math","max"],"sources":["../../src/drop/index.ts"],"sourcesContent":["import type { PickedFile } from '../files'\n\n// What a drop is, in web's React Aria's words, and how a DropZone takes one\n// under React Native Web, where the browser hands the page HTML5 drag and\n// drop. iOS and Android hand React Native no drag from another app, so there\n// the drop is a pick from the chooser, which DropZone turns into the same\n// event.\n\n// The slices of the DOM a drop reaches. The library is built without the DOM's\n// types, since Hermes has no DOM, so they are written out here, as far as\n// they are read.\ntype DomDataTransfer = {\n dropEffect: string\n readonly effectAllowed: string\n readonly files: ArrayLike<DomFile>\n readonly getData: (format: string) => string\n readonly items: ArrayLike<{ readonly kind: string; readonly type: string }>\n readonly types: readonly string[]\n}\n\ntype DomDragEvent = {\n readonly clientX: number\n readonly clientY: number\n readonly dataTransfer: DomDataTransfer | null\n readonly preventDefault: () => void\n}\n\ntype DomDropTarget = {\n readonly addEventListener: (\n type: string,\n listener: (event: DomDragEvent) => void,\n ) => void\n readonly getBoundingClientRect?: () => {\n readonly left: number\n readonly top: number\n }\n readonly removeEventListener: (\n type: string,\n listener: (event: DomDragEvent) => void,\n ) => void\n}\n\ntype DomFile = Blob & {\n readonly name: string\n readonly text: () => Promise<string>\n}\n\n/** The kinds of thing a drag carries, asked about one MIME type at a time. */\ntype DragTypes = {\n readonly has: (type: string) => boolean\n}\n\n/** Where something being dragged came over the target, from its top start corner. */\ntype DropEnterEvent = {\n readonly type: 'dropenter'\n readonly x: number\n readonly y: number\n}\n\n/** What landed on the target, where, and what the drop does with it. */\ntype DropEvent = {\n readonly dropOperation: Exclude<DropOperation, 'cancel'>\n readonly items: readonly DropItem[]\n readonly type: 'drop'\n readonly x: number\n readonly y: number\n}\n\n/** Where something being dragged left the target. */\ntype DropExitEvent = {\n readonly type: 'dropexit'\n readonly x: number\n readonly y: number\n}\n\n/** What the target does with each moment of a drag, all optional. */\ntype DropHandlers = {\n readonly getDropOperation?:\n | ((\n types: DragTypes,\n allowedOperations: readonly DropOperation[],\n ) => DropOperation)\n | undefined\n readonly onDrop?: ((event: DropEvent) => void) | undefined\n readonly onDropEnter?: ((event: DropEnterEvent) => void) | undefined\n readonly onDropExit?: ((event: DropExitEvent) => void) | undefined\n}\n\ntype DropItem = FileDropItem | TextDropItem\n\n/** What a drop does with what it carries, as web's drag and drop names it. */\ntype DropOperation = 'cancel' | 'copy' | 'link' | 'move'\n\n/**\n * A file dropped or picked: the file itself, and its contents as text, read\n * when asked for.\n */\ntype FileDropItem = PickedFile & {\n readonly getText: () => Promise<string>\n readonly kind: 'file'\n}\n\n/**\n * Text dropped from another page or app, in each of the MIME types it was\n * dragged as, such as `text/plain` and `text/uri-list`. Only React Native\n * Web takes one.\n */\ntype TextDropItem = {\n readonly getText: (type: string) => Promise<string>\n readonly kind: 'text'\n readonly types: ReadonlySet<string>\n}\n\n// Every operation, copy first: a file dragged in from the desktop is copied,\n// never moved.\nconst EVERY: readonly DropOperation[] = ['copy', 'link', 'move']\n\n// The operations each `effectAllowed` the dragging page set leaves open.\nconst ALLOWED: Readonly<Partial<Record<string, readonly DropOperation[]>>> = {\n all: EVERY,\n copy: ['copy'],\n copyLink: ['copy', 'link'],\n copyMove: ['copy', 'move'],\n link: ['link'],\n linkMove: ['link', 'move'],\n move: ['move'],\n none: [],\n uninitialized: EVERY,\n}\n\n// What a drag says of its files before it lands, and what a dragged string is\n// listed as. The browser lists files as `Files` alone, so their own types are\n// read off the items.\nconst FILES = 'Files'\n\n// What a drag over the target carries, read off its data transfer while it\n// is still over the target, where the browser shows only the types.\nfunction dragTypesOf(transfer: DomDataTransfer): DragTypes {\n const files = Array.from(transfer.items, (item) =>\n item.kind === 'file' ? item.type : undefined,\n ).filter((type) => type !== undefined)\n\n return typesOf([...transfer.types.filter((type) => type !== FILES), ...files])\n}\n\n// What a drop carries, read while the drop event runs, since the browser\n// guards the data transfer once it has: each file, and every string type\n// together as one text item.\nfunction droppedItemsOf(transfer: DomDataTransfer): DropItem[] {\n const files = Array.from(transfer.files, (file): FileDropItem => ({\n getText: async () => file.text(),\n kind: 'file',\n name: file.name,\n size: file.size,\n type: file.type,\n uri: URL.createObjectURL(file),\n }))\n const texts = new Map(\n transfer.types\n .filter((type) => type !== FILES)\n .map((type) => [type, transfer.getData(type)]),\n )\n\n if (texts.size === 0) {\n return files\n }\n\n const text: TextDropItem = {\n getText: async (type) => Promise.resolve(texts.get(type) ?? ''),\n kind: 'text',\n types: new Set(texts.keys()),\n }\n\n return [...files, text]\n}\n\n/** A picked file as a file drop item, whose text is read from its URI. */\nfunction fileItemOf(file: PickedFile): FileDropItem {\n return {\n ...file,\n getText: async () => {\n const response = await fetch(file.uri)\n return response.text()\n },\n kind: 'file',\n }\n}\n\n/**\n * Whether drops can be watched on a node: under React Native Web, where a\n * View's node is its DOM element.\n */\nfunction isDropTarget(node: unknown): node is DomDropTarget {\n return (\n typeof node === 'object' &&\n node !== null &&\n 'addEventListener' in node &&\n 'removeEventListener' in node\n )\n}\n\n/** Whether an item is a file, for picking the files out of a drop. */\nfunction isFileDropItem(item: DropItem): item is FileDropItem {\n return item.kind === 'file'\n}\n\n/** Whether an item is dropped text, for picking it out of a drop. */\nfunction isTextDropItem(item: DropItem): item is TextDropItem {\n return item.kind === 'text'\n}\n\n/**\n * The operation a drop of these types would do: the call site's answer, else\n * the first the drag allows, else none at all.\n */\nfunction operationOf(\n handlers: DropHandlers,\n types: DragTypes,\n allowed: readonly DropOperation[],\n): DropOperation {\n const first = allowed.at(0)\n\n if (first === undefined) {\n return 'cancel'\n }\n return handlers.getDropOperation?.(types, allowed) ?? first\n}\n\n/** The kinds of thing a set of items carries, for `getDropOperation`. */\nfunction typesOf(types: Iterable<string>): DragTypes {\n const set = new Set(types)\n return { has: (type) => set.has(type) }\n}\n\n/**\n * Takes HTML5 drag and drop on a React Native Web element, as web's React\n * Aria does on a DropZone: `onDropEnter` once something the target will take\n * comes over it, `onDropExit` once it leaves or lands, and `onDrop` with what\n * landed. `handlers` is read at each event, so it can follow the props. A\n * drag crossing the target's own children stays over it, counted in and out\n * as the browser reports each. While `isDisabled` returns true nothing is\n * taken, and the browser shows that nothing will be. It hands back what\n * stops it.\n */\nfunction watchDrops(\n target: DomDropTarget,\n handlers: () => DropHandlers,\n isDisabled: () => boolean,\n setOver: (isOver: boolean) => void,\n) {\n let depth = 0\n let over = false\n\n const point = (event: DomDragEvent) => {\n const box = target.getBoundingClientRect?.() ?? { left: 0, top: 0 }\n return { x: event.clientX - box.left, y: event.clientY - box.top }\n }\n const operation = (event: DomDragEvent) =>\n event.dataTransfer === null || isDisabled()\n ? 'cancel'\n : operationOf(\n handlers(),\n dragTypesOf(event.dataTransfer),\n ALLOWED[event.dataTransfer.effectAllowed] ?? EVERY,\n )\n const leave = (event: DomDragEvent) => {\n if (over) {\n over = false\n setOver(false)\n handlers().onDropExit?.({ type: 'dropexit', ...point(event) })\n }\n }\n\n const onDragEnter = (event: DomDragEvent) => {\n depth += 1\n\n if (depth === 1 && operation(event) !== 'cancel') {\n event.preventDefault()\n over = true\n setOver(true)\n handlers().onDropEnter?.({ type: 'dropenter', ...point(event) })\n }\n }\n const onDragOver = (event: DomDragEvent) => {\n const chosen = operation(event)\n\n if (event.dataTransfer !== null) {\n event.dataTransfer.dropEffect = chosen === 'cancel' ? 'none' : chosen\n }\n if (chosen !== 'cancel') {\n event.preventDefault()\n }\n }\n const onDragLeave = (event: DomDragEvent) => {\n depth = Math.max(0, depth - 1)\n\n if (depth === 0) {\n leave(event)\n }\n }\n const onDrop = (event: DomDragEvent) => {\n const chosen = operation(event)\n\n depth = 0\n event.preventDefault()\n\n if (chosen !== 'cancel' && event.dataTransfer !== null) {\n handlers().onDrop?.({\n dropOperation: chosen,\n items: droppedItemsOf(event.dataTransfer),\n type: 'drop',\n ...point(event),\n })\n }\n leave(event)\n }\n\n target.addEventListener('dragenter', onDragEnter)\n target.addEventListener('dragover', onDragOver)\n target.addEventListener('dragleave', onDragLeave)\n target.addEventListener('drop', onDrop)\n\n return () => {\n target.removeEventListener('dragenter', onDragEnter)\n target.removeEventListener('dragover', onDragOver)\n target.removeEventListener('dragleave', onDragLeave)\n target.removeEventListener('drop', onDrop)\n }\n}\n\nexport {\n fileItemOf,\n isDropTarget,\n isFileDropItem,\n isTextDropItem,\n operationOf,\n typesOf,\n watchDrops,\n}\nexport type {\n DragTypes,\n DropEnterEvent,\n DropEvent,\n DropExitEvent,\n DropHandlers,\n DropItem,\n DropOperation,\n FileDropItem,\n TextDropItem,\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "../button/palettes.js";
|
|
2
|
+
import "../typography/roles.js";
|
|
3
|
+
import { ViewStyle } from "react-native";
|
|
4
|
+
//#region src/fab/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The pages' three sizes: `md` the FAB at 56dp, `lg` the medium FAB at 80dp
|
|
7
|
+
* and `xl` the large FAB at 96dp.
|
|
8
|
+
*/
|
|
9
|
+
type FabSize = 'lg' | 'md' | 'xl';
|
|
10
|
+
/** The colour role a FAB is drawn in. */
|
|
11
|
+
type FabTone = 'primary' | 'secondary' | 'tertiary';
|
|
12
|
+
/**
|
|
13
|
+
* `tonal` draws the tone's container pair, the pages' default; `filled`
|
|
14
|
+
* draws the tone itself.
|
|
15
|
+
*/
|
|
16
|
+
type FabVariant = 'filled' | 'tonal';
|
|
17
|
+
//#endregion
|
|
18
|
+
export type { FabSize, FabTone, FabVariant };
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { themedStyles } from "../theme/styles.js";
|
|
2
|
+
import { palettesOf } from "../button/palettes.js";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
//#region src/fab/index.ts
|
|
5
|
+
const MEDIUM_SIZE = 80;
|
|
6
|
+
const MEDIUM_CORNER = 20;
|
|
7
|
+
/** The icon each size draws, from the pages' size token sets. */
|
|
8
|
+
const FAB_ICON_SIZES = {
|
|
9
|
+
lg: 28,
|
|
10
|
+
md: 24,
|
|
11
|
+
xl: 36
|
|
12
|
+
};
|
|
13
|
+
/** The type role the extended form sets its label in at each size. */
|
|
14
|
+
const EXTENDED_FAB_ROLES = {
|
|
15
|
+
lg: "titleLarge",
|
|
16
|
+
md: "titleMedium",
|
|
17
|
+
xl: "headlineSmall"
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Each size's corner, apart from its size so the press feedback can clip to
|
|
21
|
+
* the same one.
|
|
22
|
+
*/
|
|
23
|
+
const fabCornersOf = themedStyles(({ radii }) => StyleSheet.create({
|
|
24
|
+
lg: { borderRadius: MEDIUM_CORNER },
|
|
25
|
+
md: { borderRadius: radii.lg },
|
|
26
|
+
xl: { borderRadius: radii.xl }
|
|
27
|
+
}));
|
|
28
|
+
/** The FAB on its own: a square of the size's edge. */
|
|
29
|
+
const fabSizesOf = themedStyles(({ sizing }) => StyleSheet.create({
|
|
30
|
+
lg: {
|
|
31
|
+
height: MEDIUM_SIZE,
|
|
32
|
+
width: MEDIUM_SIZE
|
|
33
|
+
},
|
|
34
|
+
md: {
|
|
35
|
+
height: sizing.controlLg,
|
|
36
|
+
width: sizing.controlLg
|
|
37
|
+
},
|
|
38
|
+
xl: {
|
|
39
|
+
height: sizing.controlXl,
|
|
40
|
+
width: sizing.controlXl
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
/**
|
|
44
|
+
* The extended form: the size's height, with its padding at either end and
|
|
45
|
+
* the gap before the label. The 26dp and 28dp paddings fall between steps of
|
|
46
|
+
* the spacing scale and are written out, as on web.
|
|
47
|
+
*
|
|
48
|
+
* The height is a floor rather than a fixed size, so a label the device's
|
|
49
|
+
* text size enlarges grows the button rather than spilling out of it, which
|
|
50
|
+
* web's fixed height has no need to allow for.
|
|
51
|
+
*/
|
|
52
|
+
const extendedFabSizesOf = themedStyles(({ sizing, spacing }) => StyleSheet.create({
|
|
53
|
+
lg: {
|
|
54
|
+
columnGap: spacing.md,
|
|
55
|
+
minHeight: MEDIUM_SIZE,
|
|
56
|
+
paddingHorizontal: 26
|
|
57
|
+
},
|
|
58
|
+
md: {
|
|
59
|
+
columnGap: spacing.sm,
|
|
60
|
+
minHeight: sizing.controlLg,
|
|
61
|
+
paddingHorizontal: spacing.lg
|
|
62
|
+
},
|
|
63
|
+
xl: {
|
|
64
|
+
columnGap: spacing.lg,
|
|
65
|
+
minHeight: sizing.controlXl,
|
|
66
|
+
paddingHorizontal: 28
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
/**
|
|
70
|
+
* The six colour pairs, by variant and tone: each tone's container pair, and
|
|
71
|
+
* the tone itself. Plain colours, for FabMenu's FAB, which eases from one
|
|
72
|
+
* pair to another as its menu opens.
|
|
73
|
+
*/
|
|
74
|
+
const fabColorsOf = themedStyles(({ colors }) => ({
|
|
75
|
+
filled: {
|
|
76
|
+
primary: {
|
|
77
|
+
container: colors.primary,
|
|
78
|
+
content: colors.onPrimary
|
|
79
|
+
},
|
|
80
|
+
secondary: {
|
|
81
|
+
container: colors.secondary,
|
|
82
|
+
content: colors.onSecondary
|
|
83
|
+
},
|
|
84
|
+
tertiary: {
|
|
85
|
+
container: colors.tertiary,
|
|
86
|
+
content: colors.onTertiary
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
tonal: {
|
|
90
|
+
primary: {
|
|
91
|
+
container: colors.primaryContainer,
|
|
92
|
+
content: colors.onPrimaryContainer
|
|
93
|
+
},
|
|
94
|
+
secondary: {
|
|
95
|
+
container: colors.secondaryContainer,
|
|
96
|
+
content: colors.onSecondaryContainer
|
|
97
|
+
},
|
|
98
|
+
tertiary: {
|
|
99
|
+
container: colors.tertiaryContainer,
|
|
100
|
+
content: colors.onTertiaryContainer
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}));
|
|
104
|
+
/**
|
|
105
|
+
* The six colour pairs as the palettes a button draws, and the one disabled
|
|
106
|
+
* container every button shares: on-surface at the two disabled opacities,
|
|
107
|
+
* as src/button/palettes.ts draws it.
|
|
108
|
+
*/
|
|
109
|
+
const fabPalettesOf = themedStyles((theme) => {
|
|
110
|
+
const pairs = fabColorsOf(theme);
|
|
111
|
+
return {
|
|
112
|
+
disabled: palettesOf(theme).filledDisabled,
|
|
113
|
+
filled: palettesFor(pairs.filled),
|
|
114
|
+
tonal: palettesFor(pairs.tonal)
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
const fabShadowsOf = themedStyles(({ shadows }) => StyleSheet.create({
|
|
118
|
+
elevation3: { boxShadow: shadows.elevation3 },
|
|
119
|
+
elevation4: { boxShadow: shadows.elevation4 }
|
|
120
|
+
}));
|
|
121
|
+
/**
|
|
122
|
+
* The shadow a FAB draws in its state: level 3 at rest and while pressed,
|
|
123
|
+
* level 4 under a hovering pointer, and none while disabled, since a shadow
|
|
124
|
+
* says a control is there to press.
|
|
125
|
+
*/
|
|
126
|
+
function fabShadowOf({ hovered, pressed }, isDisabled, theme) {
|
|
127
|
+
if (isDisabled) return;
|
|
128
|
+
return fabShadowsOf(theme)[hovered && !pressed ? "elevation4" : "elevation3"];
|
|
129
|
+
}
|
|
130
|
+
function palette({ container, content }) {
|
|
131
|
+
return {
|
|
132
|
+
container: { backgroundColor: container },
|
|
133
|
+
content,
|
|
134
|
+
label: { color: content }
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function palettesFor(pairs) {
|
|
138
|
+
return {
|
|
139
|
+
primary: palette(pairs.primary),
|
|
140
|
+
secondary: palette(pairs.secondary),
|
|
141
|
+
tertiary: palette(pairs.tertiary)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
export { EXTENDED_FAB_ROLES, FAB_ICON_SIZES, extendedFabSizesOf, fabColorsOf, fabCornersOf, fabPalettesOf, fabShadowOf, fabSizesOf };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["ViewStyle","StyleSheet","Palette","ResolvedTheme","TypeRole","palettesOf","themedStyles","FabSize","FabTone","FabVariant","MEDIUM_SIZE","MEDIUM_CORNER","FAB_ICON_SIZES","Readonly","Record","lg","md","xl","EXTENDED_FAB_ROLES","fabCornersOf","radii","create","borderRadius","fabSizesOf","sizing","height","width","controlLg","controlXl","extendedFabSizesOf","spacing","columnGap","minHeight","paddingHorizontal","sm","FabColors","container","content","fabColorsOf","colors","filled","primary","onPrimary","secondary","onSecondary","tertiary","onTertiary","tonal","primaryContainer","onPrimaryContainer","secondaryContainer","onSecondaryContainer","tertiaryContainer","onTertiaryContainer","fabPalettesOf","theme","disabled","pairs","filledDisabled","palettesFor","fabShadowsOf","shadows","elevation3","boxShadow","elevation4","fabShadowOf","hovered","pressed","isDisabled","undefined","palette","backgroundColor","label","color"],"sources":["../../src/fab/index.ts"],"sourcesContent":["import type { ViewStyle } from 'react-native'\n\nimport { StyleSheet } from 'react-native'\n\nimport type { Palette } from '../button/palettes'\nimport type { ResolvedTheme } from '../theme/scope'\nimport type { TypeRole } from '../typography/roles'\n\nimport { palettesOf } from '../button/palettes'\nimport { themedStyles } from '../theme/styles'\n\n// The FAB's metrics and colours, shared by Fab and by the FAB that opens\n// FabMenu, which is the same button until its menu opens, as web's\n// src/fab/styles.ts is shared. Apart from either component, and outside\n// `src/components`, which holds the public components alone. Fab's header\n// gives the values and where they come from.\n\n/**\n * The pages' three sizes: `md` the FAB at 56dp, `lg` the medium FAB at 80dp\n * and `xl` the large FAB at 96dp.\n */\ntype FabSize = 'lg' | 'md' | 'xl'\n\n/** The colour role a FAB is drawn in. */\ntype FabTone = 'primary' | 'secondary' | 'tertiary'\n\n/**\n * `tonal` draws the tone's container pair, the pages' default; `filled`\n * draws the tone itself.\n */\ntype FabVariant = 'filled' | 'tonal'\n\n// The medium FAB's container and corner, between the steps of the control\n// and radius scales, so written out as web writes them.\nconst MEDIUM_SIZE = 80\nconst MEDIUM_CORNER = 20\n\n/** The icon each size draws, from the pages' size token sets. */\nconst FAB_ICON_SIZES: Readonly<Record<FabSize, number>> = {\n lg: 28,\n md: 24,\n xl: 36,\n}\n\n/** The type role the extended form sets its label in at each size. */\nconst EXTENDED_FAB_ROLES: Readonly<Record<FabSize, TypeRole>> = {\n lg: 'titleLarge',\n md: 'titleMedium',\n xl: 'headlineSmall',\n}\n\n/**\n * Each size's corner, apart from its size so the press feedback can clip to\n * the same one.\n */\nconst fabCornersOf = themedStyles(({ radii }) =>\n StyleSheet.create({\n lg: { borderRadius: MEDIUM_CORNER },\n md: { borderRadius: radii.lg },\n xl: { borderRadius: radii.xl },\n }),\n)\n\n/** The FAB on its own: a square of the size's edge. */\nconst fabSizesOf = themedStyles(({ sizing }) =>\n StyleSheet.create({\n lg: { height: MEDIUM_SIZE, width: MEDIUM_SIZE },\n md: { height: sizing.controlLg, width: sizing.controlLg },\n xl: { height: sizing.controlXl, width: sizing.controlXl },\n }),\n)\n\n/**\n * The extended form: the size's height, with its padding at either end and\n * the gap before the label. The 26dp and 28dp paddings fall between steps of\n * the spacing scale and are written out, as on web.\n *\n * The height is a floor rather than a fixed size, so a label the device's\n * text size enlarges grows the button rather than spilling out of it, which\n * web's fixed height has no need to allow for.\n */\nconst extendedFabSizesOf = themedStyles(({ sizing, spacing }) =>\n StyleSheet.create({\n lg: {\n columnGap: spacing.md,\n minHeight: MEDIUM_SIZE,\n paddingHorizontal: 26,\n },\n md: {\n columnGap: spacing.sm,\n minHeight: sizing.controlLg,\n paddingHorizontal: spacing.lg,\n },\n xl: {\n columnGap: spacing.lg,\n minHeight: sizing.controlXl,\n paddingHorizontal: 28,\n },\n }),\n)\n\n/** A FAB's container colour and the colour drawn on it. */\ntype FabColors = { readonly container: string; readonly content: string }\n\n/**\n * The six colour pairs, by variant and tone: each tone's container pair, and\n * the tone itself. Plain colours, for FabMenu's FAB, which eases from one\n * pair to another as its menu opens.\n */\nconst fabColorsOf = themedStyles(\n ({\n colors,\n }): Readonly<Record<FabVariant, Readonly<Record<FabTone, FabColors>>>> => ({\n filled: {\n primary: { container: colors.primary, content: colors.onPrimary },\n secondary: { container: colors.secondary, content: colors.onSecondary },\n tertiary: { container: colors.tertiary, content: colors.onTertiary },\n },\n tonal: {\n primary: {\n container: colors.primaryContainer,\n content: colors.onPrimaryContainer,\n },\n secondary: {\n container: colors.secondaryContainer,\n content: colors.onSecondaryContainer,\n },\n tertiary: {\n container: colors.tertiaryContainer,\n content: colors.onTertiaryContainer,\n },\n },\n }),\n)\n\n/**\n * The six colour pairs as the palettes a button draws, and the one disabled\n * container every button shares: on-surface at the two disabled opacities,\n * as src/button/palettes.ts draws it.\n */\nconst fabPalettesOf = themedStyles(\n (\n theme,\n ): {\n readonly disabled: Palette\n readonly filled: Readonly<Record<FabTone, Palette>>\n readonly tonal: Readonly<Record<FabTone, Palette>>\n } => {\n const pairs = fabColorsOf(theme)\n\n return {\n disabled: palettesOf(theme).filledDisabled,\n filled: palettesFor(pairs.filled),\n tonal: palettesFor(pairs.tonal),\n }\n },\n)\n\nconst fabShadowsOf = themedStyles(({ shadows }) =>\n StyleSheet.create({\n elevation3: { boxShadow: shadows.elevation3 },\n elevation4: { boxShadow: shadows.elevation4 },\n }),\n)\n\n/**\n * The shadow a FAB draws in its state: level 3 at rest and while pressed,\n * level 4 under a hovering pointer, and none while disabled, since a shadow\n * says a control is there to press.\n */\nfunction fabShadowOf(\n {\n hovered,\n pressed,\n }: { readonly hovered: boolean; readonly pressed: boolean },\n isDisabled: boolean,\n theme: ResolvedTheme,\n): undefined | ViewStyle {\n if (isDisabled) {\n return undefined\n }\n\n return fabShadowsOf(theme)[hovered && !pressed ? 'elevation4' : 'elevation3']\n}\n\nfunction palette({ container, content }: FabColors): Palette {\n return {\n container: { backgroundColor: container },\n content,\n label: { color: content },\n }\n}\n\nfunction palettesFor(\n pairs: Readonly<Record<FabTone, FabColors>>,\n): Readonly<Record<FabTone, Palette>> {\n return {\n primary: palette(pairs.primary),\n secondary: palette(pairs.secondary),\n tertiary: palette(pairs.tertiary),\n }\n}\n\nexport {\n EXTENDED_FAB_ROLES,\n extendedFabSizesOf,\n FAB_ICON_SIZES,\n fabColorsOf,\n fabCornersOf,\n fabPalettesOf,\n fabShadowOf,\n fabSizesOf,\n}\nexport type { FabColors, FabSize, FabTone, FabVariant }\n"],"mappings":";;;;AAkCA,MAAMU,cAAc;AACpB,MAAMC,gBAAgB;;AAGtB,MAAMC,iBAAoD;CACxDG,IAAI;CACJC,IAAI;CACJC,IAAI;AACN;;AAGA,MAAMC,qBAA0D;CAC9DH,IAAI;CACJC,IAAI;CACJC,IAAI;AACN;;;;;AAMA,MAAME,eAAeb,cAAc,EAAEc,YACnCnB,WAAWoB,OAAO;CAChBN,IAAI,EAAEO,cAAcX,cAAc;CAClCK,IAAI,EAAEM,cAAcF,MAAML,GAAG;CAC7BE,IAAI,EAAEK,cAAcF,MAAMH,GAAG;AAC/B,CAAC,CACH;;AAGA,MAAMM,aAAajB,cAAc,EAAEkB,aACjCvB,WAAWoB,OAAO;CAChBN,IAAI;EAAEU,QAAQf;EAAagB,OAAOhB;CAAY;CAC9CM,IAAI;EAAES,QAAQD,OAAOG;EAAWD,OAAOF,OAAOG;CAAU;CACxDV,IAAI;EAAEQ,QAAQD,OAAOI;EAAWF,OAAOF,OAAOI;CAAU;AAC1D,CAAC,CACH;;;;;;;;;;AAWA,MAAMC,qBAAqBvB,cAAc,EAAEkB,QAAQM,cACjD7B,WAAWoB,OAAO;CAChBN,IAAI;EACFgB,WAAWD,QAAQd;EACnBgB,WAAWtB;EACXuB,mBAAmB;CACrB;CACAjB,IAAI;EACFe,WAAWD,QAAQI;EACnBF,WAAWR,OAAOG;EAClBM,mBAAmBH,QAAQf;CAC7B;CACAE,IAAI;EACFc,WAAWD,QAAQf;EACnBiB,WAAWR,OAAOI;EAClBK,mBAAmB;CACrB;AACF,CAAC,CACH;;;;;;AAUA,MAAMK,cAAchC,cACjB,EACCiC,cACyE;CACzEC,QAAQ;EACNC,SAAS;GAAEL,WAAWG,OAAOE;GAASJ,SAASE,OAAOG;EAAU;EAChEC,WAAW;GAAEP,WAAWG,OAAOI;GAAWN,SAASE,OAAOK;EAAY;EACtEC,UAAU;GAAET,WAAWG,OAAOM;GAAUR,SAASE,OAAOO;EAAW;CACrE;CACAC,OAAO;EACLN,SAAS;GACPL,WAAWG,OAAOS;GAClBX,SAASE,OAAOU;EAClB;EACAN,WAAW;GACTP,WAAWG,OAAOW;GAClBb,SAASE,OAAOY;EAClB;EACAN,UAAU;GACRT,WAAWG,OAAOa;GAClBf,SAASE,OAAOc;EAClB;CACF;AACF,EACF;;;;;;AAOA,MAAMC,gBAAgBhD,cAElBiD,UAKG;CACH,MAAME,QAAQnB,YAAYiB,KAAK;CAE/B,OAAO;EACLC,UAAUnD,WAAWkD,KAAK,CAAC,CAACG;EAC5BlB,QAAQmB,YAAYF,MAAMjB,MAAM;EAChCO,OAAOY,YAAYF,MAAMV,KAAK;CAChC;AACF,CACF;AAEA,MAAMa,eAAetD,cAAc,EAAEuD,cACnC5D,WAAWoB,OAAO;CAChByC,YAAY,EAAEC,WAAWF,QAAQC,WAAW;CAC5CE,YAAY,EAAED,WAAWF,QAAQG,WAAW;AAC9C,CAAC,CACH;;;;;;AAOA,SAASC,YACP,EACEC,SACAC,WAEFC,YACAb,OACuB;CACvB,IAAIa,YACF;CAGF,OAAOR,aAAaL,KAAK,CAAC,CAACW,WAAW,CAACC,UAAU,eAAe;AAClE;AAEA,SAASG,QAAQ,EAAElC,WAAWC,WAA+B;CAC3D,OAAO;EACLD,WAAW,EAAEmC,iBAAiBnC,UAAU;EACxCC;EACAmC,OAAO,EAAEC,OAAOpC,QAAQ;CAC1B;AACF;AAEA,SAASsB,YACPF,OACoC;CACpC,OAAO;EACLhB,SAAS6B,QAAQb,MAAMhB,OAAO;EAC9BE,WAAW2B,QAAQb,MAAMd,SAAS;EAClCE,UAAUyB,QAAQb,MAAMZ,QAAQ;CAClC;AACF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useTheme } from "../theme/scope.js";
|
|
2
|
+
import { ChevronDownGlyph } from "../glyphs/index.js";
|
|
3
|
+
import { c } from "react/compiler-runtime";
|
|
4
|
+
import Animated, { Easing, useAnimatedStyle, useReducedMotion, useSharedValue, withTiming } from "react-native-reanimated";
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region src/field/chevron.tsx
|
|
8
|
+
const OPEN_TURN = -180;
|
|
9
|
+
/**
|
|
10
|
+
* The chevron in the trailing slot of a field that opens a list, pointing
|
|
11
|
+
* down at the list and turned to point up while it is open, on the step the
|
|
12
|
+
* list arrives on, short3 on the standard curve, and at once under reduced
|
|
13
|
+
* motion. It is the down chevron turned half a turn rather than web's end
|
|
14
|
+
* chevron turned a quarter either way, which draws the same two states; the
|
|
15
|
+
* down one does not mirror under right-to-left, so the turn needs no second
|
|
16
|
+
* direction. It takes its colour and size from the slot.
|
|
17
|
+
*/
|
|
18
|
+
function FieldChevron(t0) {
|
|
19
|
+
const $ = c(9);
|
|
20
|
+
const { isOpen } = t0;
|
|
21
|
+
const { motion } = useTheme();
|
|
22
|
+
const reduceMotion = useReducedMotion();
|
|
23
|
+
const turn = isOpen ? OPEN_TURN : 0;
|
|
24
|
+
const angle = useSharedValue(turn);
|
|
25
|
+
let t1;
|
|
26
|
+
let t2;
|
|
27
|
+
if ($[0] !== angle || $[1] !== motion || $[2] !== reduceMotion || $[3] !== turn) {
|
|
28
|
+
t1 = () => {
|
|
29
|
+
angle.set(reduceMotion ? turn : withTiming(turn, {
|
|
30
|
+
duration: motion.durationShort3,
|
|
31
|
+
easing: Easing.bezier(...motion.easingStandard)
|
|
32
|
+
}));
|
|
33
|
+
};
|
|
34
|
+
t2 = [
|
|
35
|
+
angle,
|
|
36
|
+
motion,
|
|
37
|
+
reduceMotion,
|
|
38
|
+
turn
|
|
39
|
+
];
|
|
40
|
+
$[0] = angle;
|
|
41
|
+
$[1] = motion;
|
|
42
|
+
$[2] = reduceMotion;
|
|
43
|
+
$[3] = turn;
|
|
44
|
+
$[4] = t1;
|
|
45
|
+
$[5] = t2;
|
|
46
|
+
} else {
|
|
47
|
+
t1 = $[4];
|
|
48
|
+
t2 = $[5];
|
|
49
|
+
}
|
|
50
|
+
useEffect(t1, t2);
|
|
51
|
+
const turned = useAnimatedStyle(() => {
|
|
52
|
+
"worklet";
|
|
53
|
+
return { transform: [{ rotate: `${angle.get()}deg` }] };
|
|
54
|
+
});
|
|
55
|
+
let t3;
|
|
56
|
+
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
|
57
|
+
t3 = /* @__PURE__ */ jsx(ChevronDownGlyph, {});
|
|
58
|
+
$[6] = t3;
|
|
59
|
+
} else t3 = $[6];
|
|
60
|
+
let t4;
|
|
61
|
+
if ($[7] !== turned) {
|
|
62
|
+
t4 = /* @__PURE__ */ jsx(Animated.View, {
|
|
63
|
+
style: turned,
|
|
64
|
+
children: t3
|
|
65
|
+
});
|
|
66
|
+
$[7] = turned;
|
|
67
|
+
$[8] = t4;
|
|
68
|
+
} else t4 = $[8];
|
|
69
|
+
return t4;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { FieldChevron };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=chevron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chevron.js","names":["useEffect","Animated","Easing","useAnimatedStyle","useReducedMotion","useSharedValue","withTiming","ChevronDownGlyph","useTheme","OPEN_TURN","FieldChevron","t0","$","_c","isOpen","motion","reduceMotion","turn","angle","t1","t2","set","duration","durationShort3","easing","bezier","easingStandard","turned","transform","rotate","get","t3","Symbol","for","t4","_c"],"sources":["../../src/field/chevron.tsx"],"sourcesContent":["import { useEffect } from 'react'\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\n\nimport { ChevronDownGlyph } from '../glyphs'\nimport { useTheme } from '../theme/scope'\n\n// How far the chevron turns while the list is open: half a turn, against\n// the clock as web's end chevron turns from pointing down to pointing up.\nconst OPEN_TURN = -180\n\n/**\n * The chevron in the trailing slot of a field that opens a list, pointing\n * down at the list and turned to point up while it is open, on the step the\n * list arrives on, short3 on the standard curve, and at once under reduced\n * motion. It is the down chevron turned half a turn rather than web's end\n * chevron turned a quarter either way, which draws the same two states; the\n * down one does not mirror under right-to-left, so the turn needs no second\n * direction. It takes its colour and size from the slot.\n */\nfunction FieldChevron({ isOpen }: { readonly isOpen: boolean }) {\n const { motion } = useTheme()\n const reduceMotion = useReducedMotion()\n const turn = isOpen ? OPEN_TURN : 0\n const angle = useSharedValue(turn)\n\n useEffect(() => {\n angle.set(\n reduceMotion\n ? turn\n : withTiming(turn, {\n duration: motion.durationShort3,\n easing: Easing.bezier(...motion.easingStandard),\n }),\n )\n }, [angle, motion, reduceMotion, turn])\n\n const turned = useAnimatedStyle(() => {\n 'worklet'\n return { transform: [{ rotate: `${angle.get()}deg` }] }\n })\n\n return (\n <Animated.View style={turned}>\n <ChevronDownGlyph />\n </Animated.View>\n )\n}\n\nexport { FieldChevron }\n"],"mappings":";;;;;;;AAcA,MAAMS,YAAY;;;;;;;;;;AAWlB,SAAAC,aAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAsB,MAAA,EAAAC,WAAAH;CACpB,MAAA,EAAAI,WAAmBP,SAAS;CAC5B,MAAAQ,eAAqBZ,iBAAiB;CACtC,MAAAa,OAAaH,SAAAL,YAAA;CACb,MAAAS,QAAcb,eAAeY,IAAI;CAAC,IAAAE;CAAA,IAAAC;CAAA,IAAAR,EAAA,OAAAM,SAAAN,EAAA,OAAAG,UAAAH,EAAA,OAAAI,gBAAAJ,EAAA,OAAAK,MAAA;EAExBE,WAAA;GACRD,MAAKG,IACHL,eAAAC,OAEIX,WAAWW,MAAM;IAAAK,UACLP,OAAMQ;IAAeC,QACvBtB,OAAMuB,OAAO,GAAIV,OAAMW,cAAe;GAChD,CAAC,CACP;EAAC;EACAN,KAAA;GAACF;GAAOH;GAAQC;GAAcC;EAAI;EAACL,EAAA,KAAAM;EAAAN,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;EAAAL,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;CAAA,OAAA;EAAAD,KAAAP,EAAA;EAAAQ,KAAAR,EAAA;CAAA;CATtCZ,UAAUmB,IASPC,EAAmC;CAEtC,MAAAO,SAAexB,uBAAiB;EAAA;EAAA,OAEvB,EAAAyB,WAAa,CAAC,EAAAC,QAAU,GAAGX,MAAKY,IAAK,EAAC,KAAM,CAAC,EAAE;CAAC,CACxD;CAAC,IAAAC;CAAA,IAAAnB,EAAA,OAAAoB,OAAAC,IAAA,2BAAA,GAAA;EAIEF,KAAA,oBAAC,kBAAD,CAAiB,CAAA;EAAGnB,EAAA,KAAAmB;CAAA,OAAAA,KAAAnB,EAAA;CAAA,IAAAsB;CAAA,IAAAtB,EAAA,OAAAe,QAAA;EADtBO,KAAA,oBAAA,SAAA,MAAA;GAAsBP,OAAAA;GACpBI,UAAAA;EACF,CAAA;EAAgBnB,EAAA,KAAAe;EAAAf,EAAA,KAAAsB;CAAA,OAAAA,KAAAtB,EAAA;CAAA,OAFhBsB;AAEgB"}
|
package/dist/field/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../form/index.js";
|
|
2
|
+
import { HostInstance, StyleProp, TextInput, TextInputProps, ViewProps, ViewStyle } from "react-native";
|
|
2
3
|
import "react-native-reanimated";
|
|
3
4
|
import { ComponentRef, ReactNode, Ref, RefObject } from "react";
|
|
4
5
|
//#region src/field/index.d.ts
|