@jobber/components-native 0.109.1 → 0.111.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 (56) hide show
  1. package/dist/docs/ProgressBar/ProgressBar.md +1 -1
  2. package/dist/docs/ProgressIndicator/ProgressIndicator.md +117 -0
  3. package/dist/docs/index.md +1 -0
  4. package/dist/package.json +2 -2
  5. package/dist/src/ProgressBar/ProgressBar.js +6 -0
  6. package/dist/src/ProgressBar/ProgressBar.test.js +2 -0
  7. package/dist/src/ProgressIndicator/ProgressIndicator.js +106 -0
  8. package/dist/src/ProgressIndicator/ProgressIndicator.size.style.js +15 -0
  9. package/dist/src/ProgressIndicator/ProgressIndicator.style.js +51 -0
  10. package/dist/src/ProgressIndicator/ProgressIndicator.test.js +138 -0
  11. package/dist/src/ProgressIndicator/index.js +1 -0
  12. package/dist/src/ProgressIndicator/types.js +1 -0
  13. package/dist/src/hooks/useAtlantisI18n/locales/en.json +3 -0
  14. package/dist/src/hooks/useAtlantisI18n/locales/es.json +3 -0
  15. package/dist/src/hooks/useAtlantisI18n/releasedLanguages.js +21 -0
  16. package/dist/src/hooks/useAtlantisI18n/useAtlantisI18n.js +4 -2
  17. package/dist/src/hooks/useAtlantisI18n/useAtlantisI18n.test.js +115 -15
  18. package/dist/src/index.js +1 -0
  19. package/dist/src/utils/meta/meta.json +1 -0
  20. package/dist/tsconfig.build.tsbuildinfo +1 -1
  21. package/dist/types/src/ProgressBar/ProgressBar.d.ts +3 -0
  22. package/dist/types/src/ProgressBar/types.d.ts +3 -0
  23. package/dist/types/src/ProgressIndicator/ProgressIndicator.d.ts +3 -0
  24. package/dist/types/src/ProgressIndicator/ProgressIndicator.size.style.d.ts +19 -0
  25. package/dist/types/src/ProgressIndicator/ProgressIndicator.style.d.ts +48 -0
  26. package/dist/types/src/ProgressIndicator/ProgressIndicator.test.d.ts +1 -0
  27. package/dist/types/src/ProgressIndicator/index.d.ts +2 -0
  28. package/dist/types/src/ProgressIndicator/types.d.ts +44 -0
  29. package/dist/types/src/hooks/useAtlantisI18n/releasedLanguages.d.ts +18 -0
  30. package/dist/types/src/hooks/useAtlantisI18n/useAtlantisI18n.d.ts +3 -1
  31. package/dist/types/src/index.d.ts +1 -0
  32. package/package.json +2 -2
  33. package/src/ProgressBar/ProgressBar.stories.tsx +2 -0
  34. package/src/ProgressBar/ProgressBar.test.tsx +2 -0
  35. package/src/ProgressBar/ProgressBar.tsx +6 -0
  36. package/src/ProgressBar/docs/ProgressBarBasic.tsx +2 -0
  37. package/src/ProgressBar/docs/ProgressBarWithHeader.tsx +2 -0
  38. package/src/ProgressBar/types.ts +3 -0
  39. package/src/ProgressIndicator/ProgressIndicator.size.style.ts +20 -0
  40. package/src/ProgressIndicator/ProgressIndicator.stories.tsx +154 -0
  41. package/src/ProgressIndicator/ProgressIndicator.style.ts +53 -0
  42. package/src/ProgressIndicator/ProgressIndicator.test.tsx +214 -0
  43. package/src/ProgressIndicator/ProgressIndicator.tsx +198 -0
  44. package/src/ProgressIndicator/docs/ProgressIndicatorBasic.tsx +22 -0
  45. package/src/ProgressIndicator/docs/ProgressIndicatorPending.tsx +22 -0
  46. package/src/ProgressIndicator/docs/index.ts +2 -0
  47. package/src/ProgressIndicator/guide.md +104 -0
  48. package/src/ProgressIndicator/index.ts +2 -0
  49. package/src/ProgressIndicator/types.ts +51 -0
  50. package/src/hooks/useAtlantisI18n/locales/en.json +3 -0
  51. package/src/hooks/useAtlantisI18n/locales/es.json +3 -0
  52. package/src/hooks/useAtlantisI18n/releasedLanguages.ts +23 -0
  53. package/src/hooks/useAtlantisI18n/useAtlantisI18n.test.ts +202 -25
  54. package/src/hooks/useAtlantisI18n/useAtlantisI18n.ts +13 -3
  55. package/src/index.ts +1 -0
  56. package/src/utils/meta/meta.json +1 -0
@@ -1,3 +1,6 @@
1
1
  import React from "react";
2
2
  import type { ProgressBarProps } from "./types";
3
+ /**
4
+ * @deprecated Use `ProgressIndicator` from `@jobber/components-native` instead.
5
+ */
3
6
  export declare function ProgressBar({ loading, total, current, inProgress, reverseTheme, header, variation, size, UNSAFE_style, }: ProgressBarProps): React.JSX.Element;
@@ -1,5 +1,8 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { StyleProp, ViewStyle } from "react-native";
3
+ /**
4
+ * @deprecated Use `ProgressIndicator` from `@jobber/components-native` instead.
5
+ */
3
6
  export interface ProgressBarProps {
4
7
  /**
5
8
  * The total number of items to be completed
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { ProgressIndicatorProps } from "./types";
3
+ export declare function ProgressIndicator({ value, max, pendingValue, variation, size, accessibilityLabel, style, }: ProgressIndicatorProps): React.JSX.Element;
@@ -0,0 +1,19 @@
1
+ import type { ProgressIndicatorProps } from "./types";
2
+ type Size = NonNullable<ProgressIndicatorProps["size"]>;
3
+ /**
4
+ * Bar heights per size. Matches the web `ProgressIndicator` ladder and today's
5
+ * mobile `ProgressBar` sizing.
6
+ */
7
+ export declare const sizeHeights: Record<Size, number>;
8
+ export declare const sizeStyles: {
9
+ smaller: {
10
+ height: number;
11
+ };
12
+ small: {
13
+ height: number;
14
+ };
15
+ base: {
16
+ height: number;
17
+ };
18
+ };
19
+ export {};
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ProgressIndicator
3
+ *
4
+ * Colour tokens mirror the web `ProgressIndicator`: the fill / filled segments
5
+ * use `color-interactive--subtle`; the track / empty segments use
6
+ * `color-surface--active`. The mobile-only pending band / pending segments use
7
+ * `color-informative`, carried forward from today's `ProgressBar` `inProgress`
8
+ * overlay.
9
+ *
10
+ * The bar height is set by the size style; the border radius is derived from
11
+ * that height at render time so the fill and segments stay pill-shaped at every
12
+ * size.
13
+ */
14
+ export declare const useStyles: () => {
15
+ continuous: {
16
+ width: "100%";
17
+ flexDirection: "row";
18
+ overflow: "hidden";
19
+ backgroundColor: string;
20
+ };
21
+ fill: {
22
+ height: "100%";
23
+ backgroundColor: string;
24
+ };
25
+ pending: {
26
+ height: "100%";
27
+ position: "absolute";
28
+ left: number;
29
+ top: number;
30
+ backgroundColor: string;
31
+ };
32
+ stepped: {
33
+ width: "100%";
34
+ flexDirection: "row";
35
+ gap: number;
36
+ };
37
+ segment: {
38
+ flex: number;
39
+ height: "100%";
40
+ backgroundColor: string;
41
+ };
42
+ segmentFilled: {
43
+ backgroundColor: string;
44
+ };
45
+ segmentPending: {
46
+ backgroundColor: string;
47
+ };
48
+ };
@@ -0,0 +1,2 @@
1
+ export { ProgressIndicator } from "./ProgressIndicator";
2
+ export type { ProgressIndicatorProps } from "./types";
@@ -0,0 +1,44 @@
1
+ import type { StyleProp, ViewStyle } from "react-native";
2
+ export interface ProgressIndicatorProps {
3
+ /**
4
+ * Current progress. Expected to be in the range `0..max` inclusive.
5
+ */
6
+ readonly value: number;
7
+ /**
8
+ * Maximum value.
9
+ * @default 100
10
+ */
11
+ readonly max?: number;
12
+ /**
13
+ * Additional in-flight progress beyond `value`, measured on the same scale as
14
+ * `value` and `max`. The bar visually fills `value + pendingValue` of `max`,
15
+ * with the `value` portion shown as completed and the `pendingValue` portion
16
+ * shown as pending. Mobile-only; there is no web counterpart.
17
+ * @default 0
18
+ */
19
+ readonly pendingValue?: number;
20
+ /**
21
+ * Set the variation of the progress indicator. `continuous` renders a single
22
+ * fill; `stepped` renders one segment per integer step from `1..max`.
23
+ * @default continuous
24
+ */
25
+ readonly variation?: "continuous" | "stepped";
26
+ /**
27
+ * Set the size of the progress indicator. Corresponds to bar heights of
28
+ * 4px / 8px / 16px.
29
+ * @default base
30
+ */
31
+ readonly size?: "smaller" | "small" | "base";
32
+ /**
33
+ * Accessible label override. When omitted, the label is derived via
34
+ * `useAtlantisI18n`: `"{value}%"` when `max` is `100` (or omitted) and
35
+ * `pendingValue` is `0`; `"{value} / {max}"` when `max` is not `100` and
36
+ * `pendingValue` is `0`; `"{value} of {max}, {pendingValue} pending"` when
37
+ * `pendingValue` is greater than `0`.
38
+ */
39
+ readonly accessibilityLabel?: string;
40
+ /**
41
+ * Custom style applied to the root element.
42
+ */
43
+ readonly style?: StyleProp<ViewStyle>;
44
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Languages that have been fully released and are safe to surface to users.
3
+ * Any locale not present in this list will fall back to "en".
4
+ *
5
+ * To release a new language, add its BCP 47 language tag here (e.g. "es").
6
+ */
7
+ export declare const RELEASED_LANGUAGES: readonly string[];
8
+ /**
9
+ * Returns the locale to use based on what has been released. Matches on the
10
+ * language part of the locale (before the "-") so that regional variants like
11
+ * "en-CA" or "es-US" resolve correctly:
12
+ *
13
+ * - "en-CA" → "en-CA" (language "en" is released; full locale preserved for
14
+ * date/time formatting)
15
+ * - "es-US" → "en" (language "es" not yet released; falls back to "en")
16
+ * - "fr" → "en" (language "fr" not released; falls back to "en")
17
+ */
18
+ export declare function getReleasedLocale(locale: string): string;
@@ -2,7 +2,9 @@ import en from "./locales/en.json";
2
2
  export type I18nKeys = keyof typeof en;
3
3
  export interface useAtlantisI18nValue {
4
4
  /**
5
- * The set locale based on the AtlantisContext.
5
+ * The effective locale, resolved from the AtlantisContext locale against the
6
+ * list of released languages. Regional variants (e.g. "en-CA") are preserved
7
+ * when their language is released. Unreleased locales fall back to "en".
6
8
  */
7
9
  readonly locale: string;
8
10
  /**
@@ -37,6 +37,7 @@ export * from "./InputSearch";
37
37
  export * from "./InputText";
38
38
  export * from "./InputTime";
39
39
  export * from "./ProgressBar";
40
+ export * from "./ProgressIndicator";
40
41
  export * from "./Select";
41
42
  export * from "./StatusLabel";
42
43
  export * from "./Switch";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.109.1",
3
+ "version": "0.111.0",
4
4
  "license": "MIT",
5
5
  "description": "React Native implementation of Atlantis",
6
6
  "repository": {
@@ -124,5 +124,5 @@
124
124
  "react-native-screens": ">=4.18.0",
125
125
  "react-native-svg": ">=12.0.0"
126
126
  },
127
- "gitHead": "879bbb072a470c876e4ee7e9a9757f5edb0f3b82"
127
+ "gitHead": "6346e405a6b057bc5b03e75a03412811e44571b5"
128
128
  }
@@ -1,3 +1,5 @@
1
+ /* eslint-disable import/no-deprecated -- This file documents the deprecated
2
+ * ProgressBar component until it is removed or shimmed. */
1
3
  import type { ComponentProps } from "react";
2
4
  import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
3
5
  import { ProgressBar } from "@jobber/components-native";
@@ -1,3 +1,5 @@
1
+ /* eslint-disable import/no-deprecated -- This file tests the deprecated
2
+ * ProgressBar component until it is removed or shimmed. */
1
3
  import React from "react";
2
4
  import { render, screen } from "@testing-library/react-native";
3
5
  import type { ProgressBarProps } from ".";
@@ -1,3 +1,6 @@
1
+ /* eslint-disable import/no-deprecated -- This file implements the deprecated
2
+ * ProgressBar component; self-references predate the deprecation. Migrate to
3
+ * ProgressIndicator. */
1
4
  import React from "react";
2
5
  import { View } from "react-native";
3
6
  import type { ProgressBarProps } from "./types";
@@ -8,6 +11,9 @@ import { sizeStyles } from "./ProgressBar.size.style";
8
11
  import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
9
12
  import { useAtlantisTheme } from "../AtlantisThemeContext";
10
13
 
14
+ /**
15
+ * @deprecated Use `ProgressIndicator` from `@jobber/components-native` instead.
16
+ */
11
17
  export function ProgressBar({
12
18
  loading,
13
19
  total,
@@ -1,3 +1,5 @@
1
+ /* eslint-disable import/no-deprecated -- This example documents the deprecated
2
+ * ProgressBar component until it is removed or shimmed. */
1
3
  import React from "react";
2
4
  import { ProgressBar } from "@jobber/components-native";
3
5
  import type { ProgressBarProps } from "@jobber/components-native";
@@ -1,3 +1,5 @@
1
+ /* eslint-disable import/no-deprecated -- This example documents the deprecated
2
+ * ProgressBar component until it is removed or shimmed. */
1
3
  import React, { useState } from "react";
2
4
  import {
3
5
  Button,
@@ -1,6 +1,9 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { StyleProp, ViewStyle } from "react-native";
3
3
 
4
+ /**
5
+ * @deprecated Use `ProgressIndicator` from `@jobber/components-native` instead.
6
+ */
4
7
  export interface ProgressBarProps {
5
8
  /**
6
9
  * The total number of items to be completed
@@ -0,0 +1,20 @@
1
+ import { StyleSheet } from "react-native";
2
+ import type { ProgressIndicatorProps } from "./types";
3
+
4
+ type Size = NonNullable<ProgressIndicatorProps["size"]>;
5
+
6
+ /**
7
+ * Bar heights per size. Matches the web `ProgressIndicator` ladder and today's
8
+ * mobile `ProgressBar` sizing.
9
+ */
10
+ export const sizeHeights: Record<Size, number> = {
11
+ smaller: 4,
12
+ small: 8,
13
+ base: 16,
14
+ };
15
+
16
+ export const sizeStyles = StyleSheet.create({
17
+ smaller: { height: sizeHeights.smaller },
18
+ small: { height: sizeHeights.small },
19
+ base: { height: sizeHeights.base },
20
+ });
@@ -0,0 +1,154 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { View } from "react-native";
3
+ import type { ComponentProps } from "react";
4
+ import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
5
+ import { ProgressIndicator } from "@jobber/components-native";
6
+ import { ProgressIndicatorBasic, ProgressIndicatorPending } from "./docs";
7
+
8
+ type ProgressIndicatorStoryArgs = Partial<
9
+ Pick<
10
+ ComponentProps<typeof ProgressIndicator>,
11
+ | "value"
12
+ | "max"
13
+ | "pendingValue"
14
+ | "variation"
15
+ | "size"
16
+ | "accessibilityLabel"
17
+ >
18
+ >;
19
+
20
+ const meta = {
21
+ title: "Components/Status and Feedback/ProgressIndicator",
22
+ component: ProgressIndicator,
23
+ parameters: {
24
+ viewport: { defaultViewport: "mobile1" },
25
+ showNativeOnWebDisclaimer: true,
26
+ },
27
+ argTypes: {
28
+ variation: {
29
+ control: { type: "radio" },
30
+ options: ["continuous", "stepped"],
31
+ },
32
+ size: {
33
+ control: { type: "radio" },
34
+ options: ["smaller", "small", "base"],
35
+ },
36
+ },
37
+ } satisfies Meta<typeof ProgressIndicator>;
38
+
39
+ export default meta;
40
+
41
+ type Story = StoryObj<ProgressIndicatorStoryArgs>;
42
+
43
+ /**
44
+ * The default continuous bar, filled to `value` out of `max`.
45
+ */
46
+ export const Basic: Story = {
47
+ render: ProgressIndicatorBasic,
48
+ args: {
49
+ value: 75,
50
+ size: "base",
51
+ },
52
+ };
53
+
54
+ /**
55
+ * The three sizes stacked so the heights (4 / 8 / 16px) are visually
56
+ * comparable.
57
+ */
58
+ export const Sizes: Story = {
59
+ render: args => (
60
+ <View style={{ gap: 16 }}>
61
+ <ProgressIndicator {...args} value={args.value ?? 50} size="smaller" />
62
+ <ProgressIndicator {...args} value={args.value ?? 50} size="small" />
63
+ <ProgressIndicator {...args} value={args.value ?? 50} size="base" />
64
+ </View>
65
+ ),
66
+ args: {
67
+ value: 50,
68
+ },
69
+ };
70
+
71
+ /**
72
+ * The stepped variation renders one segment per step and fills the first
73
+ * `value` of `max`.
74
+ */
75
+ export const Stepped: Story = {
76
+ render: ProgressIndicatorBasic,
77
+ args: {
78
+ value: 2,
79
+ max: 5,
80
+ variation: "stepped",
81
+ size: "base",
82
+ },
83
+ };
84
+
85
+ /**
86
+ * Mobile-only pending overlay: `value` of `max` completed plus an additional
87
+ * `pendingValue` of `max` in flight.
88
+ */
89
+ export const Pending: Story = {
90
+ render: ProgressIndicatorPending,
91
+ args: {
92
+ value: 2,
93
+ max: 10,
94
+ pendingValue: 3,
95
+ },
96
+ };
97
+
98
+ /**
99
+ * The stepped variation with a pending overlay: the first `value` segments are
100
+ * filled and the next `pendingValue` segments are shown as in flight.
101
+ */
102
+ export const SteppedPending: Story = {
103
+ render: ProgressIndicatorPending,
104
+ args: {
105
+ value: 3,
106
+ max: 6,
107
+ pendingValue: 2,
108
+ variation: "stepped",
109
+ },
110
+ };
111
+
112
+ /**
113
+ * Demonstrates the default `"{value}%"` accessibility label when `max` is
114
+ * omitted or equal to 100.
115
+ */
116
+ export const Percentage: Story = {
117
+ render: ProgressIndicatorBasic,
118
+ args: {
119
+ value: 42,
120
+ },
121
+ };
122
+
123
+ /**
124
+ * Demonstrates the default `"{value} / {max}"` accessibility label when
125
+ * `max !== 100`.
126
+ */
127
+ export const Ratio: Story = {
128
+ render: ProgressIndicatorBasic,
129
+ args: {
130
+ value: 3,
131
+ max: 4,
132
+ },
133
+ };
134
+
135
+ /**
136
+ * Drives `value` over time so the determinate width transition is visible. The
137
+ * transition is intentionally preserved under a reduce-motion preference
138
+ * because it conveys functional progress (WCAG 2.3.3).
139
+ */
140
+ export const WithState: Story = {
141
+ render: function WithStateStory() {
142
+ const [value, setValue] = useState(0);
143
+
144
+ useEffect(() => {
145
+ const interval = setInterval(() => {
146
+ setValue(current => (current >= 100 ? 0 : current + 10));
147
+ }, 1000);
148
+
149
+ return () => clearInterval(interval);
150
+ }, []);
151
+
152
+ return <ProgressIndicator value={value} />;
153
+ },
154
+ };
@@ -0,0 +1,53 @@
1
+ import { buildThemedStyles } from "../AtlantisThemeContext";
2
+
3
+ /**
4
+ * ProgressIndicator
5
+ *
6
+ * Colour tokens mirror the web `ProgressIndicator`: the fill / filled segments
7
+ * use `color-interactive--subtle`; the track / empty segments use
8
+ * `color-surface--active`. The mobile-only pending band / pending segments use
9
+ * `color-informative`, carried forward from today's `ProgressBar` `inProgress`
10
+ * overlay.
11
+ *
12
+ * The bar height is set by the size style; the border radius is derived from
13
+ * that height at render time so the fill and segments stay pill-shaped at every
14
+ * size.
15
+ */
16
+ export const useStyles = buildThemedStyles(tokens => ({
17
+ /* Continuous: the root IS the track; the fill / pending sit on top. */
18
+ continuous: {
19
+ width: "100%",
20
+ flexDirection: "row",
21
+ overflow: "hidden",
22
+ backgroundColor: tokens["color-surface--active"],
23
+ },
24
+ fill: {
25
+ height: "100%",
26
+ backgroundColor: tokens["color-interactive--subtle"],
27
+ },
28
+ pending: {
29
+ height: "100%",
30
+ position: "absolute",
31
+ left: 0,
32
+ top: 0,
33
+ backgroundColor: tokens["color-informative"],
34
+ },
35
+
36
+ /* Stepped: the root IS the flex row; segments are direct children. */
37
+ stepped: {
38
+ width: "100%",
39
+ flexDirection: "row",
40
+ gap: tokens["space-small"],
41
+ },
42
+ segment: {
43
+ flex: 1,
44
+ height: "100%",
45
+ backgroundColor: tokens["color-surface--active"],
46
+ },
47
+ segmentFilled: {
48
+ backgroundColor: tokens["color-interactive--subtle"],
49
+ },
50
+ segmentPending: {
51
+ backgroundColor: tokens["color-informative"],
52
+ },
53
+ }));