ferns-ui 0.36.3 → 0.36.5
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/package.json +3 -2
- package/src/ActionSheet.tsx +1231 -0
- package/src/Avatar.tsx +317 -0
- package/src/Badge.tsx +65 -0
- package/src/Banner.tsx +124 -0
- package/src/BlurBox.native.tsx +40 -0
- package/src/BlurBox.tsx +31 -0
- package/src/Body.tsx +32 -0
- package/src/Box.tsx +308 -0
- package/src/Button.tsx +219 -0
- package/src/Card.tsx +23 -0
- package/src/CheckBox.tsx +118 -0
- package/src/Common.ts +2743 -0
- package/src/Constants.ts +53 -0
- package/src/CustomSelect.tsx +85 -0
- package/src/DateTimeActionSheet.tsx +409 -0
- package/src/DateTimeField.android.tsx +101 -0
- package/src/DateTimeField.ios.tsx +83 -0
- package/src/DateTimeField.tsx +69 -0
- package/src/DecimalRangeActionSheet.tsx +113 -0
- package/src/ErrorBoundary.tsx +37 -0
- package/src/ErrorPage.tsx +44 -0
- package/src/FernsProvider.tsx +21 -0
- package/src/Field.tsx +299 -0
- package/src/FieldWithLabels.tsx +36 -0
- package/src/FlatList.tsx +2 -0
- package/src/Form.tsx +182 -0
- package/src/HeaderButtons.tsx +107 -0
- package/src/Heading.tsx +53 -0
- package/src/HeightActionSheet.tsx +104 -0
- package/src/Hyperlink.tsx +181 -0
- package/src/Icon.tsx +24 -0
- package/src/IconButton.tsx +165 -0
- package/src/Image.tsx +50 -0
- package/src/ImageBackground.tsx +14 -0
- package/src/InfoTooltipButton.tsx +23 -0
- package/src/Layer.tsx +17 -0
- package/src/Link.tsx +17 -0
- package/src/Mask.tsx +21 -0
- package/src/MediaQuery.ts +46 -0
- package/src/Meta.tsx +9 -0
- package/src/Modal.tsx +248 -0
- package/src/ModalSheet.tsx +58 -0
- package/src/NumberPickerActionSheet.tsx +66 -0
- package/src/Page.tsx +133 -0
- package/src/Permissions.ts +44 -0
- package/src/PickerSelect.tsx +553 -0
- package/src/Pill.tsx +24 -0
- package/src/Pog.tsx +87 -0
- package/src/ProgressBar.tsx +55 -0
- package/src/ScrollView.tsx +2 -0
- package/src/SegmentedControl.tsx +102 -0
- package/src/SelectList.tsx +89 -0
- package/src/SideDrawer.tsx +62 -0
- package/src/Spinner.tsx +20 -0
- package/src/SplitPage.native.tsx +160 -0
- package/src/SplitPage.tsx +302 -0
- package/src/Switch.tsx +19 -0
- package/src/Table.tsx +87 -0
- package/src/TableHeader.tsx +36 -0
- package/src/TableHeaderCell.tsx +76 -0
- package/src/TableRow.tsx +87 -0
- package/src/TapToEdit.tsx +221 -0
- package/src/Text.tsx +131 -0
- package/src/TextArea.tsx +16 -0
- package/src/TextField.tsx +401 -0
- package/src/TextFieldNumberActionSheet.tsx +61 -0
- package/src/Toast.tsx +106 -0
- package/src/Tooltip.tsx +269 -0
- package/src/UnifiedScreens.ts +24 -0
- package/src/Unifier.ts +371 -0
- package/src/Utilities.tsx +159 -0
- package/src/WithLabel.tsx +57 -0
- package/src/dayjsExtended.ts +10 -0
- package/src/index.tsx +1346 -0
- package/src/polyfill.d.ts +11 -0
- package/src/tableContext.tsx +80 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Originally based on https://github.com/pinterest/gestalt
|
|
2
|
+
// Forked, updated to Typescript, and added features.
|
|
3
|
+
import get from "lodash/get";
|
|
4
|
+
|
|
5
|
+
export function mergeInlineStyles(inlineStyle?: any, newStyle?: any) {
|
|
6
|
+
const inline = get(inlineStyle, "__style");
|
|
7
|
+
return {
|
|
8
|
+
__style: {
|
|
9
|
+
...inline,
|
|
10
|
+
...newStyle,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
|
|
17
|
+
Style is a monoid that capture the "to-be-applied" styles (inline and classes)
|
|
18
|
+
for a Box. It's basically set that is closed under an associative binary
|
|
19
|
+
operation and has an identity element such that for all HA HA HA. Yes, it's a
|
|
20
|
+
monoid, which sounds scary but it's not really and actually super useful. All
|
|
21
|
+
that means is that basically you can do two things with it:
|
|
22
|
+
|
|
23
|
+
1. concat(concat(a, b), c) === concat(a, concat(b, c));
|
|
24
|
+
2. concat(identity(), a) === concat(a, identity()) === a;
|
|
25
|
+
|
|
26
|
+
What that means is that it's really easy to compose styles together and the
|
|
27
|
+
order in which you do so doesn't really matter.
|
|
28
|
+
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
interface InlineStyle {
|
|
32
|
+
[key: string]: string | number | void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// TODO: This type should be opaque, however the Babel parser doesn't support
|
|
36
|
+
// the opaque syntax yet.
|
|
37
|
+
export interface Style {
|
|
38
|
+
className: Set<string>;
|
|
39
|
+
inlineStyle: InlineStyle;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const identity = (): Style => ({
|
|
43
|
+
className: new Set(),
|
|
44
|
+
inlineStyle: {},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const fromClassName = (...classNames: string[]): Style => ({
|
|
48
|
+
className: new Set(classNames),
|
|
49
|
+
inlineStyle: {},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const fromInlineStyle = (inlineStyle: InlineStyle): Style => ({
|
|
53
|
+
className: new Set(),
|
|
54
|
+
inlineStyle,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const concat = (styles: Style[]): Style =>
|
|
58
|
+
styles.reduce(
|
|
59
|
+
(
|
|
60
|
+
{className: classNameA, inlineStyle: inlineStyleA},
|
|
61
|
+
{className: classNameB, inlineStyle: inlineStyleB}
|
|
62
|
+
) => ({
|
|
63
|
+
className: new Set([...classNameA, ...classNameB]),
|
|
64
|
+
inlineStyle: {...inlineStyleA, ...inlineStyleB},
|
|
65
|
+
}),
|
|
66
|
+
identity()
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
export const mapClassName =
|
|
70
|
+
(fn: (x: string) => string) =>
|
|
71
|
+
({className, inlineStyle}: Style): Style => ({
|
|
72
|
+
className: new Set(Array.from(className).map(fn)),
|
|
73
|
+
inlineStyle,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export const toProps = ({
|
|
77
|
+
className,
|
|
78
|
+
inlineStyle,
|
|
79
|
+
}: Style): {className: string; style: InlineStyle} => {
|
|
80
|
+
const props: any = {};
|
|
81
|
+
|
|
82
|
+
if (className.size > 0) {
|
|
83
|
+
// Sorting here ensures that classNames are always stable, reducing diff
|
|
84
|
+
// churn. Box usually has a small number of properties so it's not a perf
|
|
85
|
+
// concern.
|
|
86
|
+
props.className = Array.from(className).sort().join(" ");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (Object.keys(inlineStyle).length > 0) {
|
|
90
|
+
props.style = inlineStyle;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return props;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
|
|
98
|
+
Transforms
|
|
99
|
+
|
|
100
|
+
These are a collection of a few functors that take values and returns Style's. OMG, I used the word functor - it's really just a fancy word for function.
|
|
101
|
+
|
|
102
|
+
*/
|
|
103
|
+
type Functor<T> = (n: T) => Style;
|
|
104
|
+
|
|
105
|
+
// Adds a classname when a property is present.
|
|
106
|
+
//
|
|
107
|
+
// <Box top />
|
|
108
|
+
//
|
|
109
|
+
export const toggle =
|
|
110
|
+
(...classNames: string[]) =>
|
|
111
|
+
(val?: boolean) =>
|
|
112
|
+
val ? fromClassName(...classNames) : identity();
|
|
113
|
+
|
|
114
|
+
// Maps string values to classes
|
|
115
|
+
//
|
|
116
|
+
// <Box alignItems="center" />
|
|
117
|
+
//
|
|
118
|
+
export const mapping = (map: {[key: string]: string}) => (val: string) =>
|
|
119
|
+
Object.prototype.hasOwnProperty.call(map, val) ? fromClassName(map[val]) : identity();
|
|
120
|
+
|
|
121
|
+
// Maps a range of integers to a range of classnames
|
|
122
|
+
//
|
|
123
|
+
// <Box padding={1} />
|
|
124
|
+
//
|
|
125
|
+
export const range =
|
|
126
|
+
(scale: string) =>
|
|
127
|
+
(n: number): Style =>
|
|
128
|
+
fromClassName(`${scale}${n < 0 ? `N${Math.abs(n)}` : n}`);
|
|
129
|
+
|
|
130
|
+
// Like `range`, maps a range of integers to a range of classnames, excluding
|
|
131
|
+
// zero values.
|
|
132
|
+
//
|
|
133
|
+
// <Box padding={0} />
|
|
134
|
+
export const rangeWithoutZero =
|
|
135
|
+
(scale: string) =>
|
|
136
|
+
(n: number): Style =>
|
|
137
|
+
n === 0 ? identity() : range(scale)(n);
|
|
138
|
+
|
|
139
|
+
// Binds a string classname to the value in an object. Useful when interacting
|
|
140
|
+
// with ranges that need to come dynamically from a style object. This is
|
|
141
|
+
// similar to the NPM package 'classnames/bind'.
|
|
142
|
+
export function bind<T>(
|
|
143
|
+
fn: Functor<T>,
|
|
144
|
+
scope:
|
|
145
|
+
| {
|
|
146
|
+
readonly [key: string]: string;
|
|
147
|
+
}
|
|
148
|
+
| any
|
|
149
|
+
): (val: T) => Style {
|
|
150
|
+
const map = mapClassName((name) => scope[name]);
|
|
151
|
+
return (val: T): Style => map(fn(val));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// This takes a series of the previously defined functors, runs them all
|
|
155
|
+
// against a value and returns the set of their classnames.
|
|
156
|
+
export const union =
|
|
157
|
+
<T,>(...fns: Functor<T>[]) =>
|
|
158
|
+
(val: T) =>
|
|
159
|
+
concat(fns.map((fn) => fn(val)));
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import {Box} from "./Box";
|
|
4
|
+
import {AlignItems, AllColors, JustifyContent, ReactChildren, TextSize} from "./Common";
|
|
5
|
+
import {Text} from "./Text";
|
|
6
|
+
|
|
7
|
+
export interface WithLabelProps {
|
|
8
|
+
children?: ReactChildren;
|
|
9
|
+
show?: boolean;
|
|
10
|
+
label?: string;
|
|
11
|
+
labelInline?: boolean;
|
|
12
|
+
labelColor?: AllColors;
|
|
13
|
+
labelJustifyContent?: JustifyContent;
|
|
14
|
+
labelAlignItems?: AlignItems;
|
|
15
|
+
labelPlacement?: "before" | "after";
|
|
16
|
+
labelSize?: TextSize;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function WithLabel({
|
|
20
|
+
label,
|
|
21
|
+
labelInline,
|
|
22
|
+
labelJustifyContent,
|
|
23
|
+
labelAlignItems,
|
|
24
|
+
labelPlacement,
|
|
25
|
+
labelSize,
|
|
26
|
+
labelColor,
|
|
27
|
+
show,
|
|
28
|
+
children,
|
|
29
|
+
}: WithLabelProps): React.ReactElement | null {
|
|
30
|
+
if (!children) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return (
|
|
34
|
+
<Box
|
|
35
|
+
alignItems={labelAlignItems}
|
|
36
|
+
direction={labelInline ? "row" : "column"}
|
|
37
|
+
justifyContent={labelJustifyContent}
|
|
38
|
+
width="100%"
|
|
39
|
+
>
|
|
40
|
+
{Boolean(label && labelPlacement !== "after") && (
|
|
41
|
+
<Box paddingY={1}>
|
|
42
|
+
<Text color={labelColor || "darkGray"} size={labelSize} weight="bold">
|
|
43
|
+
{show !== false ? label : " "}
|
|
44
|
+
</Text>
|
|
45
|
+
</Box>
|
|
46
|
+
)}
|
|
47
|
+
{children}
|
|
48
|
+
{Boolean(label && labelPlacement === "after") && (
|
|
49
|
+
<Box paddingY={1}>
|
|
50
|
+
<Text color={labelColor || "darkGray"} size={labelSize}>
|
|
51
|
+
{show !== false ? label : " "}
|
|
52
|
+
</Text>
|
|
53
|
+
</Box>
|
|
54
|
+
)}
|
|
55
|
+
</Box>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import relativeTime from "dayjs/plugin/relativeTime";
|
|
3
|
+
import timezone from "dayjs/plugin/timezone";
|
|
4
|
+
import utc from "dayjs/plugin/utc";
|
|
5
|
+
|
|
6
|
+
dayjs.extend(utc);
|
|
7
|
+
dayjs.extend(timezone);
|
|
8
|
+
dayjs.extend(relativeTime);
|
|
9
|
+
|
|
10
|
+
export default dayjs;
|