@jobber/components-native 0.108.0 → 0.108.1-visual-reg-5479aeb.25

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.
@@ -116,6 +116,46 @@ function ThemedComponent() {
116
116
  }
117
117
  ```
118
118
 
119
+ ### Cross-tab theme sync (Web Only)
120
+
121
+ The provider can keep the theme in sync across a user's open browser tabs. This
122
+ is opt-in: pass the `localStorage` key your app writes to as the `storageKey`
123
+ prop. The provider then listens for
124
+ [`storage` events](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event)
125
+ on that key and applies theme changes from other tabs. The `storage` event fires
126
+ only in tabs *other* than the one that wrote the value, so there's no feedback
127
+ loop.
128
+
129
+ **Your app is responsible for writing to `localStorage`** when the theme changes
130
+ — Atlantis only handles the listen-and-react side.
131
+
132
+ ```tsx
133
+ <AtlantisThemeContextProvider storageKey="my_app_theme">
134
+ <ThemedComponent />
135
+ </AtlantisThemeContextProvider>
136
+ ```
137
+
138
+ ```tsx
139
+ // Theme toggle — write to the same key after calling updateTheme
140
+ import { updateTheme } from "@jobber/components/AtlantisThemeContext";
141
+
142
+ function toggleTheme(newTheme: "light" | "dark") {
143
+ updateTheme(newTheme); // updates all providers in this tab immediately
144
+
145
+ try {
146
+ localStorage.setItem("my_app_theme", newTheme); // signals other tabs
147
+ } catch {
148
+ // localStorage unavailable (e.g. private mode) — degrades gracefully
149
+ }
150
+ }
151
+ ```
152
+
153
+ Omit `storageKey` and no `storage` listener is added, keeping the previous
154
+ within-tab-only behavior. Multiple dynamic providers on the same page all share
155
+ the same internal store, so a single provider with a `storageKey` is enough — a
156
+ cross-tab signal updates every dynamic provider at once. Providers mounted with
157
+ `dangerouslyOverrideTheme` are unaffected.
158
+
119
159
  ### Forcing a theme for an AtlantisThemeContextProvider
120
160
 
121
161
  In some scenarios you may want to force a theme for specific components
@@ -429,59 +429,66 @@ export function IconSizesExample() {
429
429
 
430
430
  ### Other
431
431
 
432
- | Icon | `Name` |
433
- | :--- | :---------------- |
434
- | | `apps` |
435
- | | `at` |
436
- | | `camera` |
437
- | | `checkmark` |
438
- | | `checkmarkCircle` |
439
- | | `circle` |
440
- | | `cog` |
441
- | | `dashboard` |
442
- | | `desktop` |
443
- | | `website` |
444
- | | `eye` |
445
- | | `eyeCrossed` |
446
- | | `flash` |
447
- | | `flashAuto` |
448
- | | `flashOff` |
449
- | | `gift` |
450
- | | `grid` |
451
- | | `happyFace` |
452
- | | `headset` |
453
- | | `home` |
454
- | | `link` |
455
- | | `loadingCheck` |
456
- | | `lock` |
457
- | | `logout` |
458
- | | `measurement` |
459
- | | `menu` |
460
- | | `microphone` |
461
- | | `microphoneMuted` |
462
- | | `mobile` |
463
- | | `more` |
464
- | | `number` |
465
- | | `offline` |
466
- | | `phone` |
467
- | | `pinned` |
468
- | | `presentation` |
469
- | | `priceTag` |
470
- | | `quickbooks` |
471
- | | `reports` |
472
- | | `shape` |
473
- | | `sidebar` |
474
- | | `signature` |
475
- | | `sneaker` |
476
- | | `sparkles` |
477
- | | `sprout` |
478
- | | `starburst` |
479
- | | `sun` |
480
- | | `tableColumns` |
481
- | | `thumbsDown` |
482
- | | `thumbsUp` |
483
- | | `unPinned` |
484
- | | `xero` |
432
+ | Icon | `Name` |
433
+ | :--- | :------------------ |
434
+ | | `apps` |
435
+ | | `at` |
436
+ | | `camera` |
437
+ | | `checkmark` |
438
+ | | `checkmarkCircle` |
439
+ | | `circle` |
440
+ | | `cog` |
441
+ | | `dashboard` |
442
+ | | `desktop` |
443
+ | | `website` |
444
+ | | `eye` |
445
+ | | `eyeCrossed` |
446
+ | | `flash` |
447
+ | | `flashAuto` |
448
+ | | `flashOff` |
449
+ | | `gift` |
450
+ | | `grid` |
451
+ | | `happyFace` |
452
+ | | `headset` |
453
+ | | `home` |
454
+ | | `link` |
455
+ | | `loadingCheck` |
456
+ | | `lock` |
457
+ | | `logout` |
458
+ | | `measurement` |
459
+ | | `menu` |
460
+ | | `microphone` |
461
+ | | `microphoneMuted` |
462
+ | | `mobile` |
463
+ | | `more` |
464
+ | | `number` |
465
+ | | `numpad` |
466
+ | | `offline` |
467
+ | | `phone` |
468
+ | | `phoneCall` |
469
+ | | `phoneDisconnected` |
470
+ | | `phoneEnd` |
471
+ | | `phoneIncoming` |
472
+ | | `phoneOutgoing` |
473
+ | | `pinned` |
474
+ | | `presentation` |
475
+ | | `priceTag` |
476
+ | | `quickbooks` |
477
+ | | `reports` |
478
+ | | `shape` |
479
+ | | `sidebar` |
480
+ | | `signature` |
481
+ | | `sneaker` |
482
+ | | `sparkles` |
483
+ | | `speaker` |
484
+ | | `sprout` |
485
+ | | `starburst` |
486
+ | | `sun` |
487
+ | | `tableColumns` |
488
+ | | `thumbsDown` |
489
+ | | `thumbsUp` |
490
+ | | `unPinned` |
491
+ | | `xero` |
485
492
 
486
493
  ### Legacy
487
494
 
@@ -29,6 +29,14 @@ number automatically fills in the rest of the time. For example, typing `2` will
29
29
  fill in `2:00 PM` and typing `1` waits for a few milliseconds in case the user
30
30
  wants to type `10`, `11`, or `12`.
31
31
 
32
+ ## Sizes and the placeholder
33
+
34
+ Consistent with other inputs, `size="small"` does not show the floating mini
35
+ label. The placeholder appears while the field is empty and unfocused, and is
36
+ hidden while the field is being edited or has a value, keeping the field at its
37
+ small height throughout. The default and `large` sizes float the placeholder up
38
+ as a mini label while editing or once a value is set.
39
+
32
40
 
33
41
  ## Props
34
42
 
@@ -1,5 +1,14 @@
1
1
  # Progress Bar
2
2
 
3
+ > **Deprecated.** Use [ProgressIndicator](/components/ProgressIndicator) for new
4
+ > work. `ProgressIndicator` is the supported determinate progress indicator
5
+ > going forward — it offers the same semantic with a cleaner prop surface
6
+ > (`value` / `max` instead of `currentStep` / `totalSteps`,
7
+ > `variation="continuous"` instead of `"progress"`, plain `className` / `style`
8
+ > instead of `UNSAFE_*`), theme-adaptive tokens, and a unified
9
+ > `<div role="progressbar">` structure across continuous and stepped variations.
10
+ > `ProgressBar` continues to work unchanged for existing call sites.
11
+
3
12
  A ProgressBar is a visual indicator of how close something is to completion.
4
13
 
5
14
  ## Design & usage guidelines
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.108.0",
3
+ "version": "0.108.1-visual-reg-5479aeb.25+5479aebb",
4
4
  "license": "MIT",
5
5
  "description": "React Native implementation of Atlantis",
6
6
  "repository": {
@@ -73,7 +73,7 @@
73
73
  "devDependencies": {
74
74
  "@babel/runtime": "^7.29.2",
75
75
  "@gorhom/bottom-sheet": "^5.2.8",
76
- "@jobber/design": "0.107.0",
76
+ "@jobber/design": "0.107.1-visual-reg-5479aeb.32+5479aebb",
77
77
  "@jobber/hooks": "2.21.0",
78
78
  "@react-native-community/datetimepicker": "^8.4.5",
79
79
  "@react-native/babel-preset": "^0.82.1",
@@ -124,5 +124,5 @@
124
124
  "react-native-screens": ">=4.18.0",
125
125
  "react-native-svg": ">=12.0.0"
126
126
  },
127
- "gitHead": "d5470a957047c13206da81b769b223f08e670d92"
127
+ "gitHead": "5479aebba6969f3d68ca0fb11654375c8439ab96"
128
128
  }
@@ -23,7 +23,7 @@ import { useIsScreenReaderEnabled } from "../hooks";
23
23
  import { IconButton } from "../IconButton";
24
24
  import { Heading } from "../Heading";
25
25
  import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
26
- import { useAtlantisTheme } from "../AtlantisThemeContext";
26
+ import { AtlantisThemeContextProvider, useAtlantisTheme, } from "../AtlantisThemeContext";
27
27
  /**
28
28
  * Signals whether keyboard handling inside a ContentOverlay is delegated to
29
29
  * a keyboard-aware scroll view (e.g. BottomSheetKeyboardAwareScrollView).
@@ -54,7 +54,7 @@ export function ContentOverlay({ children, title, accessibilityLabel, fullScreen
54
54
  const [currentPosition, setCurrentPosition] = useState(-1);
55
55
  const styles = useStyles();
56
56
  const { t } = useAtlantisI18n();
57
- const { tokens } = useAtlantisTheme();
57
+ const { theme, tokens } = useAtlantisTheme();
58
58
  const isScreenReaderEnabled = useIsScreenReaderEnabled();
59
59
  const behavior = computeContentOverlayBehavior({
60
60
  fullScreen,
@@ -179,11 +179,12 @@ export function ContentOverlay({ children, title, accessibilityLabel, fullScreen
179
179
  return (React.createElement(Backdrop, Object.assign({}, props, { pressBehavior: isCloseableOnOverlayTap ? "close" : "none" })));
180
180
  }, [isCloseableOnOverlayTap]);
181
181
  return (React.createElement(BottomSheetModal, { ref: bottomSheetModalRef, containerComponent: Platform.OS === "ios" ? Container : undefined, onChange: handleChange, style: sheetStyle, backgroundStyle: backgroundStyle, handleStyle: styles.handleWrapper, handleIndicatorStyle: handleIndicatorStyles, backdropComponent: backdropComponent, snapPoints: snapPoints, enablePanDownToClose: enablePanDownToClose !== null && enablePanDownToClose !== void 0 ? enablePanDownToClose : effectiveIsDraggable, enableContentPanningGesture: enableContentPanningGesture !== null && enableContentPanningGesture !== void 0 ? enableContentPanningGesture : effectiveIsDraggable, enableHandlePanningGesture: effectiveIsDraggable, enableDynamicSizing: !customSnapPoints && behavior.initialHeight === "contentHeight", keyboardBehavior: "interactive", keyboardBlurBehavior: "restore", topInset: topInset, onDismiss: () => onClose === null || onClose === void 0 ? void 0 : onClose() },
182
- React.createElement(ContentOverlayKeyboardContext.Provider, { value: scrollEnabled }, scrollEnabled ? (React.createElement(BottomSheetKeyboardAwareScrollView, { ref: scrollViewRef, contentContainerStyle: { paddingBottom: insets.bottom }, keyboardShouldPersistTaps: keyboardShouldPersistTaps ? "handled" : "never", showsVerticalScrollIndicator: false, onScroll: handleOnScroll, stickyHeaderIndices: [0], bottomOffset: KEYBOARD_TOP_PADDING_AUTO_SCROLL },
183
- renderHeader(),
184
- React.createElement(View, { testID: "ATL-Overlay-Children" }, children))) : (React.createElement(BottomSheetView, null,
185
- renderHeader(),
186
- React.createElement(View, { style: { paddingBottom: insets.bottom }, testID: "ATL-Overlay-Children" }, children))))));
182
+ React.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: theme },
183
+ React.createElement(ContentOverlayKeyboardContext.Provider, { value: scrollEnabled }, scrollEnabled ? (React.createElement(BottomSheetKeyboardAwareScrollView, { ref: scrollViewRef, contentContainerStyle: { paddingBottom: insets.bottom }, keyboardShouldPersistTaps: keyboardShouldPersistTaps ? "handled" : "never", showsVerticalScrollIndicator: false, onScroll: handleOnScroll, stickyHeaderIndices: [0], bottomOffset: KEYBOARD_TOP_PADDING_AUTO_SCROLL },
184
+ renderHeader(),
185
+ React.createElement(View, { testID: "ATL-Overlay-Children" }, children))) : (React.createElement(BottomSheetView, null,
186
+ renderHeader(),
187
+ React.createElement(View, { style: { paddingBottom: insets.bottom }, testID: "ATL-Overlay-Children" }, children)))))));
187
188
  }
188
189
  function Backdrop(bottomSheetBackdropProps) {
189
190
  const styles = useStyles();