@remit/ui 0.0.88 → 0.0.89

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/ui",
3
- "version": "0.0.88",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -1,6 +1,7 @@
1
1
  import type { ReactElement } from "react";
2
2
  import { useEffect, useState } from "react";
3
3
  import ReactPullToRefresh from "react-simple-pull-to-refresh";
4
+ import { DESKTOP_MEDIA_QUERY } from "../lib/layout-breakpoints.js";
4
5
 
5
6
  export interface PullToRefreshProps {
6
7
  children: ReactElement;
@@ -28,9 +29,9 @@ const useMatchMedia = (query: string): boolean => {
28
29
 
29
30
  /**
30
31
  * Wraps a scrollable list with a pull-to-refresh gesture on mobile. Below the
31
- * desktop breakpoint (Tailwind `lg`, 1024px) a downward pull at the top of the
32
- * list fires `onRefresh`; at desktop widths the gesture is inert and children
33
- * render directly, since there is no touch list to pull.
32
+ * desktop breakpoint (Tailwind `lg`) a downward pull at the top of the list
33
+ * fires `onRefresh`; at desktop the gesture is inert and children render
34
+ * directly, since there is no touch list to pull.
34
35
  *
35
36
  * Presentational: the caller owns what refreshing means via `onRefresh` and
36
37
  * surfaces in-flight state through `isRefreshing`.
@@ -40,7 +41,7 @@ export const PullToRefresh = ({
40
41
  onRefresh,
41
42
  isRefreshing,
42
43
  }: PullToRefreshProps): ReactElement => {
43
- const isDesktop = useMatchMedia("(min-width: 1024px)");
44
+ const isDesktop = useMatchMedia(DESKTOP_MEDIA_QUERY);
44
45
 
45
46
  if (isDesktop) {
46
47
  return children;
package/src/index.ts CHANGED
@@ -699,6 +699,10 @@ export {
699
699
  labelColorOptions,
700
700
  labelDotClass,
701
701
  } from "./lib/label-color.js";
702
+ export {
703
+ DESKTOP_MEDIA_QUERY,
704
+ DESKTOP_MIN_WIDTH,
705
+ } from "./lib/layout-breakpoints.js";
702
706
  export {
703
707
  derivePropertyClauses,
704
708
  normalizeSubject,
@@ -0,0 +1,12 @@
1
+ export const DESKTOP_MIN_WIDTH = 1024;
2
+
3
+ /**
4
+ * The desktop gate. Width alone is not enough: a large tablet in portrait is
5
+ * exactly 1024px wide, and the multi-pane shell does not fit a surface held
6
+ * upright. A coarse pointer in portrait therefore never counts as desktop,
7
+ * while a tall monitor (fine pointer) still does.
8
+ *
9
+ * `tokens.css` redefines Tailwind's `lg` variant with this exact condition,
10
+ * so the CSS-gated chrome and anything reading the query in JS flip together.
11
+ */
12
+ export const DESKTOP_MEDIA_QUERY = `(min-width: ${DESKTOP_MIN_WIDTH}px) and (not ((orientation: portrait) and (pointer: coarse)))`;
package/src/tokens.css CHANGED
@@ -11,6 +11,19 @@
11
11
  .dark on a wrapper; an app would toggle it on <html>. */
12
12
  @custom-variant dark (&:is(.dark *));
13
13
 
14
+ /* Tailwind's built-in lg variant, redefined: desktop chrome is a device
15
+ posture, not a width. A large tablet is exactly 1024px wide in portrait
16
+ and belongs in the single-pane layout, so a coarse pointer held upright
17
+ never reaches lg regardless of width. A tall desktop monitor has a fine
18
+ pointer and keeps it. Every lg: class in the app and the workbench rides
19
+ this rule; it must stay identical to DESKTOP_MEDIA_QUERY in
20
+ src/lib/layout-breakpoints.ts. */
21
+ @custom-variant lg {
22
+ @media (min-width: 1024px) and (not ((orientation: portrait) and (pointer: coarse))) {
23
+ @slot;
24
+ }
25
+ }
26
+
14
27
  /* @theme inline aliases Tailwind utilities (bg-surface, text-fg, etc.)
15
28
  to the semantic CSS variables declared on :root / .dark below. The
16
29
  :root / .dark blocks MUST come after this @theme block — otherwise