@jobber/components-native 0.41.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/src/AutoLink/AutoLink.js +23 -0
  2. package/dist/src/AutoLink/clipboard.js +9 -0
  3. package/dist/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.js +19 -0
  4. package/dist/src/AutoLink/components/Link/Link.js +7 -0
  5. package/dist/src/AutoLink/components/index.js +2 -0
  6. package/dist/src/AutoLink/hooks/useCreateLinkedText.js +24 -0
  7. package/dist/src/AutoLink/hooks/useTokenGenerator.js +10 -0
  8. package/dist/src/AutoLink/index.js +1 -0
  9. package/dist/src/AutoLink/messages.js +18 -0
  10. package/dist/src/AutoLink/types.js +1 -0
  11. package/dist/src/AutoLink/utils.js +45 -0
  12. package/dist/src/index.js +1 -0
  13. package/dist/tsconfig.tsbuildinfo +1 -1
  14. package/dist/types/src/AutoLink/AutoLink.d.ts +3 -0
  15. package/dist/types/src/AutoLink/clipboard.d.ts +2 -0
  16. package/dist/types/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.d.ts +3 -0
  17. package/dist/types/src/AutoLink/components/Link/Link.d.ts +8 -0
  18. package/dist/types/src/AutoLink/components/index.d.ts +2 -0
  19. package/dist/types/src/AutoLink/hooks/useCreateLinkedText.d.ts +12 -0
  20. package/dist/types/src/AutoLink/hooks/useTokenGenerator.d.ts +1 -0
  21. package/dist/types/src/AutoLink/index.d.ts +1 -0
  22. package/dist/types/src/AutoLink/messages.d.ts +17 -0
  23. package/dist/types/src/AutoLink/types.d.ts +32 -0
  24. package/dist/types/src/AutoLink/utils.d.ts +6 -0
  25. package/dist/types/src/index.d.ts +1 -0
  26. package/package.json +4 -2
  27. package/src/AutoLink/AutoLink.test.tsx +203 -0
  28. package/src/AutoLink/AutoLink.tsx +36 -0
  29. package/src/AutoLink/clipboard.ts +14 -0
  30. package/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.tsx +38 -0
  31. package/src/AutoLink/components/Link/Link.test.tsx +30 -0
  32. package/src/AutoLink/components/Link/Link.tsx +21 -0
  33. package/src/AutoLink/components/index.ts +2 -0
  34. package/src/AutoLink/hooks/useCreateLinkedText.ts +35 -0
  35. package/src/AutoLink/hooks/useTokenGenerator.ts +11 -0
  36. package/src/AutoLink/index.ts +1 -0
  37. package/src/AutoLink/messages.ts +19 -0
  38. package/src/AutoLink/types.ts +39 -0
  39. package/src/AutoLink/utils.ts +63 -0
  40. package/src/index.ts +1 -0
@@ -0,0 +1,23 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from "react";
13
+ import { Text as RNText } from "react-native";
14
+ import { ComposeTextWithLinks } from "./components";
15
+ import { useCreateLinkedText } from "./hooks/useCreateLinkedText";
16
+ import { TypographyGestureDetector } from "../Typography";
17
+ import { tokens } from "../utils/design";
18
+ export function AutoLink(_a) {
19
+ var { children: text = "", bottomTabsVisible = true, selectable = true } = _a, rest = __rest(_a, ["children", "bottomTabsVisible", "selectable"]);
20
+ const { splitText, matches } = useCreateLinkedText(Object.assign({ text }, rest));
21
+ return (React.createElement(TypographyGestureDetector, null,
22
+ React.createElement(RNText, { selectable: selectable, selectionColor: tokens["color-brand--highlight"] }, splitText.map((part, index) => (React.createElement(ComposeTextWithLinks, { key: index, part: part, index: index, match: matches[part], bottomTabsVisible: bottomTabsVisible, selectable: selectable }))))));
23
+ }
@@ -0,0 +1,9 @@
1
+ import Clipboard from "@react-native-clipboard/clipboard";
2
+ import { showToast } from "../Toast";
3
+ export function copyTextToClipboard(text, toastConfig) {
4
+ Clipboard.setString(text);
5
+ if (toastConfig) {
6
+ const { message, bottomTabsVisible } = toastConfig;
7
+ showToast({ message, bottomTabsVisible });
8
+ }
9
+ }
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { useIntl } from "react-intl";
3
+ import { Platform } from "react-native";
4
+ import { onLongPressLink, onPressLink } from "../../utils";
5
+ import { Link } from "../Link/Link";
6
+ import { Text } from "../../../Text";
7
+ export function ComposeTextWithLinks({ part, index, match, bottomTabsVisible, selectable = true, }) {
8
+ const { formatMessage } = useIntl();
9
+ const isLink = match === null || match === void 0 ? void 0 : match.getType();
10
+ if (isLink) {
11
+ return (React.createElement(Link, { key: index, onPress: () => onPressLink(match), onLongPress: () => {
12
+ if (selectable && Platform.OS === "android") {
13
+ return;
14
+ }
15
+ onLongPressLink(match, bottomTabsVisible, formatMessage);
16
+ } }, match.getAnchorText()));
17
+ }
18
+ return React.createElement(Text, { key: index }, part);
19
+ }
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { Text as RNText } from "react-native";
3
+ import { Text } from "../../../Text";
4
+ export function Link({ children, onPress, onLongPress, }) {
5
+ return (React.createElement(RNText, { onPress: onPress, onLongPress: onLongPress },
6
+ React.createElement(Text, { variation: "interactive" }, children)));
7
+ }
@@ -0,0 +1,2 @@
1
+ export { Link } from "./Link/Link";
2
+ export { ComposeTextWithLinks } from "./ComposeTextWithLinks/ComposeTextWithLinks";
@@ -0,0 +1,24 @@
1
+ import Autolinker from "autolinker";
2
+ import { useTokenGenerator } from "./useTokenGenerator";
3
+ import { shouldIgnoreURL } from "../utils";
4
+ export function useCreateLinkedText({ text = "", email = true, phone = true, urls = true, }) {
5
+ const [generateToken, tokenRegexp] = useTokenGenerator();
6
+ const matches = {};
7
+ const linkedText = Autolinker.link(text, {
8
+ email,
9
+ phone,
10
+ urls,
11
+ replaceFn: match => {
12
+ if (shouldIgnoreURL(text, match))
13
+ return false;
14
+ const token = generateToken();
15
+ matches[token] = match;
16
+ return token;
17
+ },
18
+ });
19
+ const splitText = splitLinkedText(linkedText, tokenRegexp);
20
+ return { splitText, matches };
21
+ }
22
+ function splitLinkedText(linkedText, tokenRegexp) {
23
+ return linkedText.split(tokenRegexp).filter(part => Boolean(part));
24
+ }
@@ -0,0 +1,10 @@
1
+ import { useState } from "react";
2
+ import { v1 } from "react-native-uuid";
3
+ export function useTokenGenerator() {
4
+ let counter = 0;
5
+ const [identifier] = useState(v1());
6
+ return [
7
+ () => `@__ELEMENT-${identifier}-${counter++}__@`,
8
+ new RegExp(`(@__ELEMENT-${identifier}-\\d+__@)`, "g"),
9
+ ];
10
+ }
@@ -0,0 +1 @@
1
+ export * from "./AutoLink";
@@ -0,0 +1,18 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ phoneCopied: {
4
+ id: "phoneCopied",
5
+ defaultMessage: "Phone number copied",
6
+ description: "Message shown after copying a phone number",
7
+ },
8
+ emailCopied: {
9
+ id: "emailCopied",
10
+ defaultMessage: "Email copied",
11
+ description: "Message shown after copying an email",
12
+ },
13
+ urlCopied: {
14
+ id: "urlCopied",
15
+ defaultMessage: "URL copied",
16
+ description: "Message shown after copying a URL",
17
+ },
18
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import { Linking } from "react-native";
2
+ import { messages } from "./messages";
3
+ import { copyTextToClipboard } from "./clipboard";
4
+ function hasPrefix(text, prefixes) {
5
+ return prefixes.some(prefix => text.includes(prefix));
6
+ }
7
+ export function shouldIgnoreURL(text, match) {
8
+ const matchedText = match.getMatchedText().toLocaleLowerCase();
9
+ const urlPrefixes = ["http://", "https://", "www."];
10
+ const ignorePrefixes = ["file://", "ftp://"];
11
+ const previousChar = text.charAt(match.getOffset() - 1);
12
+ if (match.getType() === "url") {
13
+ const hasUrlPrefix = hasPrefix(matchedText, urlPrefixes);
14
+ const hasIgnorePrefix = hasPrefix(matchedText, ignorePrefixes) || previousChar === "/";
15
+ return hasIgnorePrefix && !hasUrlPrefix;
16
+ }
17
+ return false;
18
+ }
19
+ export function getUrl(match, immediateOpen = true) {
20
+ const matchType = match.getType();
21
+ switch (matchType) {
22
+ case "email":
23
+ return immediateOpen
24
+ ? `mailto:${encodeURIComponent(match.getEmail())}`
25
+ : match.getEmail();
26
+ case "phone":
27
+ return immediateOpen
28
+ ? `tel:${match.getNumber()}`
29
+ : match.getNumber();
30
+ default:
31
+ return match.getAnchorHref();
32
+ }
33
+ }
34
+ export function onLongPressLink(match, bottomTabsVisible, formatMessage) {
35
+ const linkUrl = getUrl(match, false);
36
+ const toastConfig = {
37
+ message: formatMessage(messages[`${match.getType()}Copied`]),
38
+ bottomTabsVisible,
39
+ };
40
+ copyTextToClipboard(linkUrl, toastConfig);
41
+ }
42
+ export function onPressLink(match) {
43
+ const linkUrl = getUrl(match);
44
+ Linking.openURL(linkUrl);
45
+ }
package/dist/src/index.js CHANGED
@@ -2,6 +2,7 @@ export * from "./ActionItem";
2
2
  export * from "./ActionLabel";
3
3
  export * from "./ActivityIndicator";
4
4
  export * from "./AtlantisContext";
5
+ export * from "./AutoLink";
5
6
  export * from "./Banner";
6
7
  export * from "./BottomSheet";
7
8
  export * from "./Button";