@12-apps/ui 6.41.1 → 6.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.
- package/dist/_internal/components/data-display/DataGrid/DataGrid.body.js +2 -2
- package/dist/_internal/components/data-display/DataGrid/DataGrid.cells.js +1 -1
- package/dist/_internal/components/data-display/DataGrid/DataGrid.js +3 -3
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +6 -6
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +5 -5
- package/dist/_internal/components/data-display/FleetMap/FleetMap.fixtures.js +1 -1
- package/dist/_internal/components/data-display/Lightbox/Lightbox.js +7 -7
- package/dist/_internal/components/data-display/Lightbox/LightboxControls.js +2 -2
- package/dist/_internal/components/data-display/Lightbox/LightboxCurrentMedia.js +3 -2
- package/dist/_internal/components/data-display/Lightbox/LightboxMedia.js +2 -1
- package/dist/_internal/components/data-display/Lightbox/LightboxOverlay.js +3 -3
- package/dist/_internal/components/data-display/Lightbox/LightboxThumbnails.js +2 -1
- package/dist/_internal/components/data-display/TimingDiagram/TimingDiagram.js +2 -2
- package/dist/_internal/components/data-display/TimingDiagram/TimingDiagram.views.js +1 -1
- package/dist/_internal/components/data-display/index.js +12 -12
- package/dist/_internal/components/feedback/TutorialOverlay/TutorialOverlay.js +2 -2
- package/dist/_internal/components/feedback/TutorialOverlay/TutorialStepBody.js +1 -1
- package/dist/_internal/components/feedback/index.js +2 -2
- package/dist/_internal/components/index.js +16 -16
- package/dist/_internal/components/layout/Dashboard/Dashboard.js +2 -2
- package/dist/_internal/components/layout/Dashboard/DashboardParts.js +1 -1
- package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +4 -4
- package/dist/_internal/components/layout/SettingsLayout/SettingsPanel.js +3 -3
- package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.js +2 -2
- package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.scroll.js +7 -1
- package/dist/_internal/components/layout/index.js +2 -2
- package/dist/_internal/en-US.data-display.js +3 -1
- package/dist/_internal/en-US.feedback.js +1 -1
- package/dist/_internal/pt-BR.data-display.js +3 -1
- package/dist/_internal/pt-BR.feedback.js +1 -1
- package/dist/{chunk-K4L42FF6.js → chunk-24JOJJ2J.js} +3 -3
- package/dist/chunk-24JOJJ2J.js.map +1 -0
- package/dist/{chunk-LODMNSLR.js → chunk-3GYPZ5MI.js} +4 -3
- package/dist/chunk-3GYPZ5MI.js.map +1 -0
- package/dist/{chunk-HFVYWHJT.js → chunk-AP4LSXRK.js} +2 -2
- package/dist/{chunk-MEBQKYH4.js → chunk-BX7QWHKC.js} +2 -2
- package/dist/{chunk-UFNIS7KC.js → chunk-GGBFDHXE.js} +11 -8
- package/dist/chunk-GGBFDHXE.js.map +1 -0
- package/dist/chunk-GT2RCOHM.js +184 -0
- package/dist/chunk-GT2RCOHM.js.map +1 -0
- package/dist/{chunk-2XHIF3M3.js → chunk-GXQDWHPN.js} +25 -3
- package/dist/chunk-GXQDWHPN.js.map +1 -0
- package/dist/{chunk-F7JTIHV5.js → chunk-ICDAYOJ6.js} +6 -5
- package/dist/chunk-ICDAYOJ6.js.map +1 -0
- package/dist/{chunk-ASCUWG55.js → chunk-IOCY5G43.js} +8 -3
- package/dist/chunk-IOCY5G43.js.map +1 -0
- package/dist/{chunk-RZ2VZ7SL.js → chunk-JMEPGXJG.js} +2 -2
- package/dist/{chunk-3MEIGSDK.js → chunk-LTTYUSJ2.js} +5 -2
- package/dist/chunk-LTTYUSJ2.js.map +1 -0
- package/dist/{chunk-3AQD2EA6.js → chunk-M42ZOCO7.js} +10 -9
- package/dist/chunk-M42ZOCO7.js.map +1 -0
- package/dist/{chunk-GJFAI3J5.js → chunk-OOB3YWPX.js} +17 -10
- package/dist/chunk-OOB3YWPX.js.map +1 -0
- package/dist/{chunk-TZASFX6G.js → chunk-P53KRCKW.js} +4 -4
- package/dist/{chunk-2DWBJJK6.js → chunk-RBGUS7WO.js} +2 -2
- package/dist/{chunk-ZEYUSS3W.js → chunk-SQNQQTP7.js} +4 -3
- package/dist/chunk-SQNQQTP7.js.map +1 -0
- package/dist/chunk-SV4FYSDL.js +92 -0
- package/dist/chunk-SV4FYSDL.js.map +1 -0
- package/dist/{chunk-CKHFYTIX.js → chunk-TBMGYQJF.js} +15 -5
- package/dist/chunk-TBMGYQJF.js.map +1 -0
- package/dist/{chunk-TCNTIGMY.js → chunk-TDXEO2UI.js} +2 -2
- package/dist/{chunk-ASHXIAJO.js → chunk-UGH2DDST.js} +5 -2
- package/dist/chunk-UGH2DDST.js.map +1 -0
- package/dist/{chunk-WFAJTO2B.js → chunk-UVFZQCC7.js} +5 -9
- package/dist/chunk-UVFZQCC7.js.map +1 -0
- package/dist/{chunk-U5SH3VRJ.js → chunk-V5ZLUJV7.js} +25 -3
- package/dist/chunk-V5ZLUJV7.js.map +1 -0
- package/dist/{chunk-VCBV5JM7.js → chunk-VNOXUWK7.js} +2 -2
- package/dist/{chunk-IVJKILIX.js → chunk-VZ4VAQX3.js} +2 -2
- package/dist/{chunk-5QAJ3Y5F.js → chunk-XQWUVQ2F.js} +2 -2
- package/dist/{chunk-H5ZTIELC.js → chunk-ZFXTRPQO.js} +5 -4
- package/dist/chunk-ZFXTRPQO.js.map +1 -0
- package/dist/{chunk-UT73NGRS.js → chunk-ZSTUKSTJ.js} +2 -2
- package/dist/data-display/DataGrid.js +3 -3
- package/dist/data-display/DataViews.js +7 -7
- package/dist/data-display/Lightbox.js +7 -7
- package/dist/data-display/TimingDiagram.js +2 -2
- package/dist/en-US.js +4 -2
- package/dist/feedback/TutorialOverlay.js +2 -2
- package/dist/layout/Dashboard.js +2 -2
- package/dist/layout/SettingsLayout.js +4 -4
- package/dist/locales.js +8 -4
- package/dist/locales.js.map +1 -1
- package/dist/pt-BR.js +4 -2
- package/dist/types/components/data-display/DataGrid/DataGrid.body.d.ts.map +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts +3 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts.map +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.d.ts +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts +12 -2
- package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +8 -2
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-grid-bodies.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/LightboxMedia.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/LightboxThumbnails.d.ts.map +1 -1
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.d.ts.map +1 -1
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.views.d.ts +2 -0
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.views.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.d.ts +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts +22 -12
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts +1 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts.map +1 -1
- package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.d.ts.map +1 -1
- package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.scroll.d.ts +20 -2
- package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.scroll.d.ts.map +1 -1
- package/dist/types/copy/data-display.d.ts +40 -1
- package/dist/types/copy/data-display.d.ts.map +1 -1
- package/dist/types/copy/feedback.d.ts +7 -1
- package/dist/types/copy/feedback.d.ts.map +1 -1
- package/dist/types/en-US.data-display.d.ts +2 -1
- package/dist/types/en-US.data-display.d.ts.map +1 -1
- package/dist/types/en-US.feedback.d.ts.map +1 -1
- package/dist/types/locales.d.ts +2 -1
- package/dist/types/locales.d.ts.map +1 -1
- package/dist/types/pt-BR.data-display.d.ts +2 -1
- package/dist/types/pt-BR.data-display.d.ts.map +1 -1
- package/dist/types/pt-BR.feedback.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/data-display/DataGrid/DataGrid.body.tsx +2 -1
- package/src/components/data-display/DataGrid/DataGrid.cells.tsx +7 -4
- package/src/components/data-display/DataGrid/DataGrid.tsx +2 -1
- package/src/components/data-display/DataGrid/DataGrid.types.ts +13 -2
- package/src/components/data-display/DataViews/data-views-copy.ts +8 -2
- package/src/components/data-display/DataViews/data-views-grid-bodies.tsx +1 -0
- package/src/components/data-display/Lightbox/Lightbox.tsx +8 -2
- package/src/components/data-display/Lightbox/LightboxMedia.tsx +5 -2
- package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +7 -3
- package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +10 -7
- package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +6 -2
- package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +2 -2
- package/src/components/layout/Dashboard/Dashboard.types.ts +22 -12
- package/src/components/layout/Dashboard/DashboardParts.tsx +10 -7
- package/src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts +212 -28
- package/src/components/layout/SettingsLayout/SettingsSectionChips.tsx +24 -4
- package/src/copy/data-display.ts +41 -1
- package/src/copy/feedback.ts +7 -1
- package/src/en-US.data-display.ts +23 -0
- package/src/en-US.feedback.ts +3 -0
- package/src/locales.ts +2 -0
- package/src/pt-BR.data-display.ts +23 -0
- package/src/pt-BR.feedback.ts +3 -0
- package/dist/chunk-2XHIF3M3.js.map +0 -1
- package/dist/chunk-3AQD2EA6.js.map +0 -1
- package/dist/chunk-3MEIGSDK.js.map +0 -1
- package/dist/chunk-ASCUWG55.js.map +0 -1
- package/dist/chunk-ASHXIAJO.js.map +0 -1
- package/dist/chunk-BAFDSAWY.js +0 -86
- package/dist/chunk-BAFDSAWY.js.map +0 -1
- package/dist/chunk-CKHFYTIX.js.map +0 -1
- package/dist/chunk-F7JTIHV5.js.map +0 -1
- package/dist/chunk-GJFAI3J5.js.map +0 -1
- package/dist/chunk-H5ZTIELC.js.map +0 -1
- package/dist/chunk-K4L42FF6.js.map +0 -1
- package/dist/chunk-LODMNSLR.js.map +0 -1
- package/dist/chunk-SLJAQA2X.js +0 -82
- package/dist/chunk-SLJAQA2X.js.map +0 -1
- package/dist/chunk-U5SH3VRJ.js.map +0 -1
- package/dist/chunk-UFNIS7KC.js.map +0 -1
- package/dist/chunk-WFAJTO2B.js.map +0 -1
- package/dist/chunk-ZEYUSS3W.js.map +0 -1
- /package/dist/{chunk-HFVYWHJT.js.map → chunk-AP4LSXRK.js.map} +0 -0
- /package/dist/{chunk-MEBQKYH4.js.map → chunk-BX7QWHKC.js.map} +0 -0
- /package/dist/{chunk-RZ2VZ7SL.js.map → chunk-JMEPGXJG.js.map} +0 -0
- /package/dist/{chunk-TZASFX6G.js.map → chunk-P53KRCKW.js.map} +0 -0
- /package/dist/{chunk-2DWBJJK6.js.map → chunk-RBGUS7WO.js.map} +0 -0
- /package/dist/{chunk-TCNTIGMY.js.map → chunk-TDXEO2UI.js.map} +0 -0
- /package/dist/{chunk-VCBV5JM7.js.map → chunk-VNOXUWK7.js.map} +0 -0
- /package/dist/{chunk-IVJKILIX.js.map → chunk-VZ4VAQX3.js.map} +0 -0
- /package/dist/{chunk-5QAJ3Y5F.js.map → chunk-XQWUVQ2F.js.map} +0 -0
- /package/dist/{chunk-UT73NGRS.js.map → chunk-ZSTUKSTJ.js.map} +0 -0
|
@@ -21,6 +21,24 @@ const LANDED_SLACK = 1;
|
|
|
21
21
|
*/
|
|
22
22
|
const QUIET_BEFORE_SETTLED_MS = 250;
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* How much `scrollLeft` has to move, tick to tick, before a `scroll` event is
|
|
26
|
+
* even a CANDIDATE for arming (FUT-2775). Below this, a browser's own rounding
|
|
27
|
+
* or a repeated event carrying no real motion cannot arm anything by itself.
|
|
28
|
+
*
|
|
29
|
+
* This alone does not stop the false latch the ticket describes: the strip's
|
|
30
|
+
* own `scrollTo` produces real per-tick deltas well past this line, same as a
|
|
31
|
+
* drag would. It only rules out a scroll event that moved nothing.
|
|
32
|
+
*/
|
|
33
|
+
const SCROLL_DELTA_EPSILON = 2;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* How far a pointer or touch has to travel from where it went down before it
|
|
37
|
+
* counts as having MOVED, rather than merely resting (FUT-2775). Below this,
|
|
38
|
+
* an held-still finger's sub-pixel tremor does not count as a drag.
|
|
39
|
+
*/
|
|
40
|
+
const POINTER_MOVE_EPSILON = 2;
|
|
41
|
+
|
|
24
42
|
interface VisitorScrollWatch {
|
|
25
43
|
/** True once the visitor has moved the strip themselves. */
|
|
26
44
|
hasScrolled: () => boolean;
|
|
@@ -29,10 +47,14 @@ interface VisitorScrollWatch {
|
|
|
29
47
|
* strip must not scroll itself under it: that would yank a drag in progress.
|
|
30
48
|
*/
|
|
31
49
|
isUndecided: () => boolean;
|
|
32
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Where the strip last aimed itself, PHYSICAL pixels (see {@link physicalScrollLeft}) —
|
|
52
|
+
* direction-blind, like every other geometry read in this file. `NaN` before it has.
|
|
53
|
+
*/
|
|
33
54
|
aimedAt: () => number;
|
|
34
55
|
/**
|
|
35
|
-
* The strip is about to scroll itself to `left
|
|
56
|
+
* The strip is about to scroll itself to `left` (physical pixels). Records the
|
|
57
|
+
* aim and NOTHING
|
|
36
58
|
* else: it used to disarm too, and a re-centre landing between a visitor's key
|
|
37
59
|
* press (or wheel, or pan) and the first tick of the scroll it causes wiped
|
|
38
60
|
* the arming — their scroll went unclaimed, read as the strip's own. Left
|
|
@@ -62,13 +84,172 @@ interface WatchState {
|
|
|
62
84
|
aimed: number;
|
|
63
85
|
quiet: ReturnType<typeof setTimeout> | undefined;
|
|
64
86
|
settled: () => void;
|
|
87
|
+
/** `scrollLeft` as of the last `scroll` tick, updated every tick regardless of arming. */
|
|
88
|
+
lastScrollLeft: number;
|
|
89
|
+
/** Where a `pointerdown` on the strip landed, in viewport `clientX`. `NaN` while up. */
|
|
90
|
+
pointerDownAt: number;
|
|
91
|
+
/** True once that pointer has travelled past {@link POINTER_MOVE_EPSILON} from `pointerDownAt`. */
|
|
92
|
+
pointerMoved: boolean;
|
|
93
|
+
/** Same pair, for `touchstart`/`touchmove` — a distinct event stream on some engines. */
|
|
94
|
+
touchDownAt: number;
|
|
95
|
+
touchMoved: boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type RtlScrollType = 'default' | 'negative' | 'reverse';
|
|
99
|
+
|
|
100
|
+
let cachedRtlScrollType: RtlScrollType | undefined;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Which of the three incompatible conventions this engine reports an RTL
|
|
104
|
+
* scroller's `scrollLeft` in, probed once and cached (FUT-2775).
|
|
105
|
+
*
|
|
106
|
+
* Per the CSSOM View spec, an RTL scroller's `scrollLeft` is `0` at its
|
|
107
|
+
* (right-hand) start and goes NEGATIVE toward the end — `'negative'` below,
|
|
108
|
+
* what every current evergreen engine implements. Older WebKit mirrored that
|
|
109
|
+
* (`'reverse'`: `0` at the start, growing toward `+max`), and older
|
|
110
|
+
* Chromium/Safari ignored `dir` altogether and kept the plain left-to-right
|
|
111
|
+
* numbering (`'default'`). A hidden probe, not a version sniff, tells them
|
|
112
|
+
* apart — the same technique `@mui/utils`'s `detectScrollType` uses for
|
|
113
|
+
* `Tabs`; reimplemented here rather than taking a new dependency for one
|
|
114
|
+
* probe.
|
|
115
|
+
*/
|
|
116
|
+
function detectRtlScrollType(doc: Document): RtlScrollType {
|
|
117
|
+
if (cachedRtlScrollType) return cachedRtlScrollType;
|
|
118
|
+
// The exact pixel values below are the probe's mechanism, not a design size:
|
|
119
|
+
// what matters is only that the INNER box is wider than the OUTER one, so the
|
|
120
|
+
// outer one has something to scroll — same technique `@mui/utils` uses,
|
|
121
|
+
// detached and off-screen either way.
|
|
122
|
+
const probe = doc.createElement('div');
|
|
123
|
+
const inner = doc.createElement('div');
|
|
124
|
+
inner.style.width = '10px';
|
|
125
|
+
probe.appendChild(inner);
|
|
126
|
+
probe.dir = 'rtl';
|
|
127
|
+
probe.style.width = '4px';
|
|
128
|
+
probe.style.position = 'absolute';
|
|
129
|
+
probe.style.top = '-1000px';
|
|
130
|
+
probe.style.overflow = 'scroll';
|
|
131
|
+
doc.body.appendChild(probe);
|
|
132
|
+
let type: RtlScrollType = 'reverse';
|
|
133
|
+
if (probe.scrollLeft > 0) {
|
|
134
|
+
type = 'default';
|
|
135
|
+
} else {
|
|
136
|
+
probe.scrollLeft = 1;
|
|
137
|
+
if (probe.scrollLeft === 0) type = 'negative';
|
|
138
|
+
}
|
|
139
|
+
doc.body.removeChild(probe);
|
|
140
|
+
cachedRtlScrollType = type;
|
|
141
|
+
return type;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** True when the strip's own computed direction is right-to-left. */
|
|
145
|
+
export function isRtlStrip(strip: HTMLElement): boolean {
|
|
146
|
+
const view = strip.ownerDocument.defaultView;
|
|
147
|
+
const getComputedStyle = view?.getComputedStyle ?? globalThis.getComputedStyle;
|
|
148
|
+
return getComputedStyle(strip).direction === 'rtl';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* `strip.scrollLeft`, renumbered so `0` is always the strip's physical LEFT
|
|
153
|
+
* edge and larger is always further physically right — whatever `direction`
|
|
154
|
+
* and whatever convention this engine uses to report it raw (FUT-2775).
|
|
155
|
+
*
|
|
156
|
+
* Every geometry read in this file (`getBoundingClientRect`) is already in
|
|
157
|
+
* that same physical, direction-blind coordinate space, so this is what makes
|
|
158
|
+
* `scrollLeft` combinable with it at all.
|
|
159
|
+
*/
|
|
160
|
+
export function physicalScrollLeft(strip: HTMLElement): number {
|
|
161
|
+
const raw = strip.scrollLeft;
|
|
162
|
+
if (!isRtlStrip(strip)) return raw;
|
|
163
|
+
const max = strip.scrollWidth - strip.clientWidth;
|
|
164
|
+
const type = detectRtlScrollType(strip.ownerDocument);
|
|
165
|
+
if (type === 'negative') return raw + max;
|
|
166
|
+
if (type === 'reverse') return max - raw;
|
|
167
|
+
return raw;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** The inverse of {@link physicalScrollLeft}: a physical offset back to this engine's raw `scrollLeft`. */
|
|
171
|
+
export function toRawScrollLeft(strip: HTMLElement, physical: number): number {
|
|
172
|
+
if (!isRtlStrip(strip)) return physical;
|
|
173
|
+
const max = strip.scrollWidth - strip.clientWidth;
|
|
174
|
+
const type = detectRtlScrollType(strip.ownerDocument);
|
|
175
|
+
if (type === 'negative') return physical - max;
|
|
176
|
+
if (type === 'reverse') return max - physical;
|
|
177
|
+
return physical;
|
|
65
178
|
}
|
|
66
179
|
|
|
67
180
|
/** Whether the strip came to rest where it last aimed itself — clamped as the browser would. */
|
|
68
181
|
function restsOnAim(strip: HTMLElement, aimed: number): boolean {
|
|
69
182
|
const reachable = Math.min(aimed, strip.scrollWidth - strip.clientWidth);
|
|
70
183
|
// Written so that `NaN` — the strip never aimed — reads as "not on aim".
|
|
71
|
-
return Math.abs(strip
|
|
184
|
+
return Math.abs(physicalScrollLeft(strip) - reachable) <= LANDED_SLACK;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** The pointer/touch/keydown/wheel listeners that arm `state`, split out of `watchVisitorScroll` (line budget). */
|
|
188
|
+
function createGestureListeners(state: WatchState): { onStrip: Listeners; onView: Listeners } {
|
|
189
|
+
// `MouseEvent`, not `PointerEvent`: a real `PointerEvent` IS one (it extends
|
|
190
|
+
// `MouseEvent`), so this reads `clientX` off it just the same in a browser —
|
|
191
|
+
// but jsdom (this file's own test environment) has never implemented
|
|
192
|
+
// `PointerEvent` at all, and the bare identifier throws a `ReferenceError`
|
|
193
|
+
// the moment anything evaluates `instanceof PointerEvent`, pointer event or
|
|
194
|
+
// not. Same reasoning as feature-checking `scrollTo` elsewhere in this file:
|
|
195
|
+
// nothing in here is worth a crash over which constructor a probe prefers.
|
|
196
|
+
const onPointerDown = (event: Event): void => {
|
|
197
|
+
state.pointer = true;
|
|
198
|
+
state.pointerMoved = false;
|
|
199
|
+
state.pointerDownAt = event instanceof MouseEvent ? event.clientX : Number.NaN;
|
|
200
|
+
};
|
|
201
|
+
const onPointerMove = (event: Event): void => {
|
|
202
|
+
if (!(event instanceof MouseEvent) || Number.isNaN(state.pointerDownAt)) return;
|
|
203
|
+
if (Math.abs(event.clientX - state.pointerDownAt) > POINTER_MOVE_EPSILON) state.pointerMoved = true;
|
|
204
|
+
};
|
|
205
|
+
const onPointerUp = (): void => {
|
|
206
|
+
state.pointer = false;
|
|
207
|
+
state.pointerDownAt = Number.NaN;
|
|
208
|
+
};
|
|
209
|
+
const onTouchStart = (event: Event): void => {
|
|
210
|
+
state.touch = true;
|
|
211
|
+
state.touchMoved = false;
|
|
212
|
+
state.touchDownAt = event instanceof TouchEvent ? (event.touches[0]?.clientX ?? Number.NaN) : Number.NaN;
|
|
213
|
+
};
|
|
214
|
+
const onTouchMove = (event: Event): void => {
|
|
215
|
+
if (!(event instanceof TouchEvent) || Number.isNaN(state.touchDownAt)) return;
|
|
216
|
+
const clientX = event.touches[0]?.clientX;
|
|
217
|
+
if (clientX !== undefined && Math.abs(clientX - state.touchDownAt) > POINTER_MOVE_EPSILON) {
|
|
218
|
+
state.touchMoved = true;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const onTouchEnd = (): void => {
|
|
222
|
+
state.touch = false;
|
|
223
|
+
state.touchDownAt = Number.NaN;
|
|
224
|
+
};
|
|
225
|
+
const onPointerCancel = (): void => {
|
|
226
|
+
state.nudged = true;
|
|
227
|
+
onPointerUp();
|
|
228
|
+
};
|
|
229
|
+
const onKeydown = (): void => {
|
|
230
|
+
state.nudged = true;
|
|
231
|
+
};
|
|
232
|
+
const onWheel = (event: Event): void => {
|
|
233
|
+
if (horizontalDelta(event) !== 0) state.nudged = true;
|
|
234
|
+
};
|
|
235
|
+
return {
|
|
236
|
+
onStrip: [
|
|
237
|
+
['pointerdown', onPointerDown],
|
|
238
|
+
['pointermove', onPointerMove],
|
|
239
|
+
['touchstart', onTouchStart],
|
|
240
|
+
['touchmove', onTouchMove],
|
|
241
|
+
['pointercancel', onPointerCancel],
|
|
242
|
+
['keydown', onKeydown],
|
|
243
|
+
['wheel', onWheel],
|
|
244
|
+
],
|
|
245
|
+
// A gesture can END off the strip, so its end is heard on the window.
|
|
246
|
+
onView: [
|
|
247
|
+
['pointerup', onPointerUp],
|
|
248
|
+
['pointercancel', onPointerUp],
|
|
249
|
+
['touchend', onTouchEnd],
|
|
250
|
+
['touchcancel', onTouchEnd],
|
|
251
|
+
],
|
|
252
|
+
};
|
|
72
253
|
}
|
|
73
254
|
|
|
74
255
|
/**
|
|
@@ -115,12 +296,12 @@ export function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {
|
|
|
115
296
|
aimed: Number.NaN,
|
|
116
297
|
quiet: undefined,
|
|
117
298
|
settled: () => undefined,
|
|
299
|
+
lastScrollLeft: physicalScrollLeft(strip),
|
|
300
|
+
pointerDownAt: Number.NaN,
|
|
301
|
+
pointerMoved: false,
|
|
302
|
+
touchDownAt: Number.NaN,
|
|
303
|
+
touchMoved: false,
|
|
118
304
|
};
|
|
119
|
-
const set =
|
|
120
|
-
(key: 'pointer' | 'touch' | 'nudged', value: boolean) =>
|
|
121
|
-
(): void => {
|
|
122
|
-
state[key] = value;
|
|
123
|
-
};
|
|
124
305
|
const settle = (): void => {
|
|
125
306
|
// Only a scroll that was UNDER JUDGEMENT disarms. Chromium can end the
|
|
126
307
|
// strip's own smooth scroll with a `scrollend` when another scroll cuts it
|
|
@@ -132,33 +313,36 @@ export function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {
|
|
|
132
313
|
if (!restsOnAim(strip, state.aimed)) state.scrolled = true;
|
|
133
314
|
state.settled();
|
|
134
315
|
};
|
|
135
|
-
const onWheel = (event: Event): void => {
|
|
136
|
-
if (horizontalDelta(event) !== 0) state.nudged = true;
|
|
137
|
-
};
|
|
138
316
|
const onScroll = (): void => {
|
|
139
|
-
|
|
317
|
+
const now = physicalScrollLeft(strip);
|
|
318
|
+
const movedFarEnough = Math.abs(now - state.lastScrollLeft) > SCROLL_DELTA_EPSILON;
|
|
319
|
+
state.lastScrollLeft = now;
|
|
320
|
+
// Pointer/touch need BOTH signals (FUT-2775): the pointer/finger must have
|
|
321
|
+
// itself MOVED since going down, AND this tick's delta must be real. Either
|
|
322
|
+
// alone still latches on the other's shape — a pointer merely resting on
|
|
323
|
+
// the strip while its OWN `scrollTo` produces real per-tick deltas would
|
|
324
|
+
// arm under a delta-only check (`pointerMoved`/`touchMoved` rules that out);
|
|
325
|
+
// a pointer that drifts a sub-epsilon amount while resting would arm under
|
|
326
|
+
// a moved-only check with no delta floor (`movedFarEnough` rules that out).
|
|
327
|
+
const pointerDrag = state.pointer && state.pointerMoved && movedFarEnough;
|
|
328
|
+
const touchDrag = state.touch && state.touchMoved && movedFarEnough;
|
|
329
|
+
// `nudged` (a keypress, a sideways wheel, the browser taking the pointer
|
|
330
|
+
// over to pan) is already a discrete, one-shot gesture with no "resting
|
|
331
|
+
// pointer coincides with an unrelated animation" shape to rule out — unlike
|
|
332
|
+
// pointer/touch, requiring a delta on the SAME tick that arms it would only
|
|
333
|
+
// race the strip's own scroll ending before a qualifying tick arrives (seen:
|
|
334
|
+
// it broke the existing "keeps a wheel/drag scroll" stories against a real
|
|
335
|
+
// browser's `scrollend` timing). So it arms as it always has.
|
|
336
|
+
if (pointerDrag || touchDrag || state.nudged) state.undecided = true;
|
|
140
337
|
if (!state.undecided || hasScrollEnd) return;
|
|
141
338
|
// Every tick while undecided, armed or not: a quiet spell that began while
|
|
142
339
|
// the strip was still moving would judge it mid-flight, away from its aim.
|
|
143
340
|
clearTimeout(state.quiet);
|
|
144
341
|
state.quiet = setTimeout(settle, QUIET_BEFORE_SETTLED_MS);
|
|
145
342
|
};
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
['pointercancel', set('nudged', true)],
|
|
150
|
-
['keydown', set('nudged', true)],
|
|
151
|
-
['wheel', onWheel],
|
|
152
|
-
['scroll', onScroll],
|
|
153
|
-
['scrollend', settle],
|
|
154
|
-
];
|
|
155
|
-
// A gesture can END off the strip, so its end is heard on the window.
|
|
156
|
-
const onView: Listeners = [
|
|
157
|
-
['pointerup', set('pointer', false)],
|
|
158
|
-
['pointercancel', set('pointer', false)],
|
|
159
|
-
['touchend', set('touch', false)],
|
|
160
|
-
['touchcancel', set('touch', false)],
|
|
161
|
-
];
|
|
343
|
+
const gestures = createGestureListeners(state);
|
|
344
|
+
const onStrip: Listeners = [...gestures.onStrip, ['scroll', onScroll], ['scrollend', settle]];
|
|
345
|
+
const onView = gestures.onView;
|
|
162
346
|
for (const [type, listener] of onStrip) strip.addEventListener(type, listener, { passive: true });
|
|
163
347
|
for (const [type, listener] of onView) view?.addEventListener(type, listener, { passive: true });
|
|
164
348
|
return {
|
|
@@ -4,7 +4,7 @@ import Box from '@mui/material/Box/index.js';
|
|
|
4
4
|
import { alpha, useTheme, type Theme } from '@mui/material/styles/index.js';
|
|
5
5
|
import React, { useEffect, useRef, type RefObject } from 'react';
|
|
6
6
|
|
|
7
|
-
import { watchVisitorScroll } from './SettingsSectionChips.scroll';
|
|
7
|
+
import { physicalScrollLeft, toRawScrollLeft, watchVisitorScroll } from './SettingsSectionChips.scroll';
|
|
8
8
|
import { SettingsStatusMarker } from './SettingsStatusMarker';
|
|
9
9
|
import { TOUCH_TARGET } from './SettingsLayout.styles';
|
|
10
10
|
import { rem, sxRem } from '../../../tokens/relative';
|
|
@@ -48,11 +48,20 @@ function prefersReducedMotion(): boolean {
|
|
|
48
48
|
* it. The clamp hid that for the last chip; a middle one was simply off-centre.
|
|
49
49
|
* The boxes are both in viewport coordinates, so their difference is the strip's
|
|
50
50
|
* own, whatever the host wraps it in.
|
|
51
|
+
*
|
|
52
|
+
* Read and returned in PHYSICAL pixels (`physicalScrollLeft`, FUT-2775): the
|
|
53
|
+
* bounding-rect arithmetic above is already direction-blind, and an RTL
|
|
54
|
+
* scroller's raw `scrollLeft` is not — the CSSOM View spec has it `0` at the
|
|
55
|
+
* strip's right-hand start and NEGATIVE past it, not `0`-to-`scrollWidth` like
|
|
56
|
+
* an LTR one. `Math.max(0, …)` alone, against that raw value, would clamp every
|
|
57
|
+
* legitimate RTL target straight back to the start. Physical throughout keeps
|
|
58
|
+
* this comparable to {@link VisitorScrollWatch.aimedAt}; the caller converts to
|
|
59
|
+
* this engine's raw `scrollLeft` (`toRawScrollLeft`) only at the `scrollTo` call.
|
|
51
60
|
*/
|
|
52
61
|
function centredScrollLeft(strip: HTMLElement, chip: HTMLElement): number {
|
|
53
62
|
const chipBox = chip.getBoundingClientRect();
|
|
54
63
|
const visibleStart = strip.getBoundingClientRect().left + strip.clientLeft;
|
|
55
|
-
const chipCentre = chipBox.left - visibleStart + strip
|
|
64
|
+
const chipCentre = chipBox.left - visibleStart + physicalScrollLeft(strip) + chipBox.width / 2;
|
|
56
65
|
const target = chipCentre - strip.clientWidth / 2;
|
|
57
66
|
return Math.max(0, Math.min(target, strip.scrollWidth - strip.clientWidth));
|
|
58
67
|
}
|
|
@@ -122,13 +131,16 @@ function useCentreActiveChip(
|
|
|
122
131
|
// Not while a scroll that may be the visitor's is still moving: a resize
|
|
123
132
|
// mid-drag must not yank the strip. It is re-tried once that scroll rests.
|
|
124
133
|
if (!chip || visitor.hasScrolled() || visitor.isUndecided()) return;
|
|
134
|
+
// Physical pixels throughout (FUT-2775) — comparable to `aimedAt()` and to
|
|
135
|
+
// what `beforeOwnScroll` records; converted to this engine's raw
|
|
136
|
+
// `scrollLeft` only for the actual `scrollTo` call below.
|
|
125
137
|
const left = centredScrollLeft(strip, chip);
|
|
126
138
|
// Only when the target MOVED: a resize that leaves it where it was must not
|
|
127
139
|
// restart a smooth scroll that is already on its way there. The aim is a
|
|
128
140
|
// runtime-computed scroll offset, like the exempt `left` below — not a size.
|
|
129
141
|
if (Math.abs(left - visitor.aimedAt()) < 0.5) return;
|
|
130
142
|
visitor.beforeOwnScroll(left);
|
|
131
|
-
strip.scrollTo({ left, behavior: prefersReducedMotion() ? 'auto' : 'smooth' });
|
|
143
|
+
strip.scrollTo({ left: toRawScrollLeft(strip, left), behavior: prefersReducedMotion() ? 'auto' : 'smooth' });
|
|
132
144
|
};
|
|
133
145
|
visitor.onSettled(centre);
|
|
134
146
|
centre();
|
|
@@ -250,7 +262,15 @@ export function SettingsSectionChips({
|
|
|
250
262
|
display: 'flex',
|
|
251
263
|
alignItems: 'center',
|
|
252
264
|
gap: 0.75,
|
|
253
|
-
|
|
265
|
+
// The start side keeps its old, symmetric 0.25 — nothing sits flush
|
|
266
|
+
// against it once scrolled. The END side is where a scrolled-to-end
|
|
267
|
+
// chip's own border used to sit almost against the clip boundary
|
|
268
|
+
// (FUT-2775): sized like the gap BETWEEN chips (`gap` above) rather
|
|
269
|
+
// than invented fresh, so the last chip clears the edge by the same
|
|
270
|
+
// margin any two chips clear each other. Logical, not `pr`: the side
|
|
271
|
+
// that gets clipped is the strip's END, whichever edge that is.
|
|
272
|
+
paddingInlineStart: 0.25,
|
|
273
|
+
paddingInlineEnd: 0.75,
|
|
254
274
|
py: 0.25,
|
|
255
275
|
overflowX: 'auto',
|
|
256
276
|
overflowY: 'hidden',
|
package/src/copy/data-display.ts
CHANGED
|
@@ -24,6 +24,16 @@ export interface LightboxCopy {
|
|
|
24
24
|
/** The slideshow toggle, in its two states. */
|
|
25
25
|
play: string;
|
|
26
26
|
pause: string;
|
|
27
|
+
/** The dialog's own accessible name, read out before its hidden title. */
|
|
28
|
+
dialogLabel: string;
|
|
29
|
+
/** The hidden title's item count, when the current item has no `alt`. */
|
|
30
|
+
itemPosition: (index: number, total: number) => string;
|
|
31
|
+
/** A `<video>`'s accessible name, when the item has no `alt`. */
|
|
32
|
+
videoFallback: (index: number, total: number) => string;
|
|
33
|
+
/** An `<img>`'s `alt`, when the item has no `alt`. */
|
|
34
|
+
imageFallback: (index: number, total: number) => string;
|
|
35
|
+
/** A filmstrip thumbnail's `alt`, when the item has no `alt`. */
|
|
36
|
+
thumbnailFallback: (index: number) => string;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
/** The map preview's control bar — same shape, same reason, as the lightbox. */
|
|
@@ -42,10 +52,40 @@ export interface CarouselCopy {
|
|
|
42
52
|
next: string;
|
|
43
53
|
}
|
|
44
54
|
|
|
45
|
-
/** The request-timing diagram's own
|
|
55
|
+
/** The request-timing diagram's own words: its region, its phases, its totals. */
|
|
46
56
|
export interface TimingDiagramCopy {
|
|
47
57
|
regionLabel: string;
|
|
48
58
|
heading: string;
|
|
59
|
+
/** The five phases a waterfall/stacked/horizontal bar can show. */
|
|
60
|
+
dns: string;
|
|
61
|
+
connect: string;
|
|
62
|
+
ssl: string;
|
|
63
|
+
request: string;
|
|
64
|
+
response: string;
|
|
65
|
+
/** The stacked view's own total sentence, e.g. "Total: 1.20s". */
|
|
66
|
+
total: (formatted: string) => string;
|
|
67
|
+
/** The horizontal view's own total sentence, e.g. "Total Time: 1.20s". */
|
|
68
|
+
totalTime: (formatted: string) => string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The DataGrid's own words — every one a fallback the caller can still
|
|
73
|
+
* override: `column.ariaLabel`, `expansion.expandLabel`/`collapseLabel` and
|
|
74
|
+
* the grid's own `ariaLabel` all win when given. REQUIRED: the fallbacks were
|
|
75
|
+
* English literals with no way to localise them at all.
|
|
76
|
+
*/
|
|
77
|
+
export interface DataGridCopy {
|
|
78
|
+
/** A sortable header button's accessible name, unless the column's own `ariaLabel` wins. */
|
|
79
|
+
sortBy: (header: string) => string;
|
|
80
|
+
/** A row's selection checkbox, unless `selection` is off. */
|
|
81
|
+
selectRow: (rowNumber: number) => string;
|
|
82
|
+
/** The header's select-all checkbox. */
|
|
83
|
+
selectAllRows: string;
|
|
84
|
+
/** The expand chevron's two states, unless `expansion.expandLabel`/`collapseLabel` win. */
|
|
85
|
+
expandRow: string;
|
|
86
|
+
collapseRow: string;
|
|
87
|
+
/** The grid's own accessible name, unless the caller's `ariaLabel` wins. */
|
|
88
|
+
gridLabel: string;
|
|
49
89
|
}
|
|
50
90
|
|
|
51
91
|
export interface DataStateCopy {
|
package/src/copy/feedback.ts
CHANGED
|
@@ -15,12 +15,18 @@
|
|
|
15
15
|
* table, the grid, the async container, the hover card and the infinite
|
|
16
16
|
* scroller each rendered their own copy of.
|
|
17
17
|
*/
|
|
18
|
-
/** The guided tour's
|
|
18
|
+
/** The guided tour's controls, and the toast/modal chrome around it. */
|
|
19
19
|
export interface TutorialCopy {
|
|
20
20
|
skip: string;
|
|
21
21
|
previous: string;
|
|
22
22
|
next: string;
|
|
23
23
|
restart: string;
|
|
24
|
+
/** The last step's own next button, when it is the tour's only step. */
|
|
25
|
+
complete: string;
|
|
26
|
+
/** The last step's own next button, in a tour of more than one step. */
|
|
27
|
+
finish: string;
|
|
28
|
+
/** The next/finish button's title while `requiresActionBeforeNext` blocks it. */
|
|
29
|
+
requiresAction: string;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
/** Chrome that carries a glyph and no text, across several small surfaces. */
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { DataViewsCopy } from "./components/data-display/DataViews/data-views-copy";
|
|
6
6
|
import type {
|
|
7
7
|
CarouselCopy,
|
|
8
|
+
DataGridCopy,
|
|
8
9
|
DataStateCopy,
|
|
9
10
|
LightboxCopy,
|
|
10
11
|
MapPreviewCopy,
|
|
@@ -26,6 +27,20 @@ export const EN_US_LIGHTBOX_COPY: LightboxCopy = {
|
|
|
26
27
|
resetZoom: "Reset zoom",
|
|
27
28
|
play: "Start the slideshow",
|
|
28
29
|
pause: "Pause the slideshow",
|
|
30
|
+
dialogLabel: "Lightbox",
|
|
31
|
+
itemPosition: (index, total) => `Item ${index} of ${total}`,
|
|
32
|
+
videoFallback: (index, total) => `Video ${index} of ${total}`,
|
|
33
|
+
imageFallback: (index, total) => `Image ${index} of ${total}`,
|
|
34
|
+
thumbnailFallback: (index) => `Thumbnail ${index}`,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const EN_US_DATA_GRID_COPY: DataGridCopy = {
|
|
38
|
+
sortBy: (header) => `Sort by ${header}`,
|
|
39
|
+
selectRow: (rowNumber) => `Select row ${rowNumber}`,
|
|
40
|
+
selectAllRows: "Select all rows",
|
|
41
|
+
expandRow: "Expand row",
|
|
42
|
+
collapseRow: "Collapse row",
|
|
43
|
+
gridLabel: "Data grid",
|
|
29
44
|
};
|
|
30
45
|
|
|
31
46
|
export const EN_US_MAP_PREVIEW_COPY: MapPreviewCopy = {
|
|
@@ -45,6 +60,13 @@ export const EN_US_CAROUSEL_COPY: CarouselCopy = {
|
|
|
45
60
|
export const EN_US_TIMING_DIAGRAM_COPY: TimingDiagramCopy = {
|
|
46
61
|
regionLabel: "Timing diagram",
|
|
47
62
|
heading: "Request timing",
|
|
63
|
+
dns: "DNS Lookup",
|
|
64
|
+
connect: "Connection",
|
|
65
|
+
ssl: "SSL/TLS",
|
|
66
|
+
request: "Request",
|
|
67
|
+
response: "Response",
|
|
68
|
+
total: (formatted) => `Total: ${formatted}`,
|
|
69
|
+
totalTime: (formatted) => `Total Time: ${formatted}`,
|
|
48
70
|
};
|
|
49
71
|
|
|
50
72
|
export const EN_US_DATA_STATE_COPY: DataStateCopy = {
|
|
@@ -161,6 +183,7 @@ export const EN_US_DATA_VIEWS_COPY: DataViewsCopy = {
|
|
|
161
183
|
},
|
|
162
184
|
tableFilter: EN_US_TABLE_FILTER_COPY,
|
|
163
185
|
grid: {
|
|
186
|
+
...EN_US_DATA_GRID_COPY,
|
|
164
187
|
rowActions: "Actions",
|
|
165
188
|
bulkActions: (selectedCount) => `Actions (${selectedCount}) ▾`,
|
|
166
189
|
emptyFilteredTitle: "No results for these filters",
|
package/src/en-US.feedback.ts
CHANGED
|
@@ -13,6 +13,9 @@ export const EN_US_TUTORIAL_COPY: TutorialCopy = {
|
|
|
13
13
|
previous: "Back",
|
|
14
14
|
next: "Next",
|
|
15
15
|
restart: "Start over",
|
|
16
|
+
complete: "Complete",
|
|
17
|
+
finish: "Finish",
|
|
18
|
+
requiresAction: "Complete the required action first",
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
export const EN_US_CHROME_COPY: ChromeCopy = {
|
package/src/locales.ts
CHANGED
|
@@ -30,6 +30,7 @@ import type {
|
|
|
30
30
|
CodeEditorCopy,
|
|
31
31
|
CommandPaletteCopy,
|
|
32
32
|
ConfirmActionCopy,
|
|
33
|
+
DataGridCopy,
|
|
33
34
|
DataStateCopy,
|
|
34
35
|
InstallPromptCopy,
|
|
35
36
|
LightboxCopy,
|
|
@@ -69,6 +70,7 @@ export const DATA_STATE_COPY = pack<DataStateCopy>(
|
|
|
69
70
|
pt.PT_BR_DATA_STATE_COPY,
|
|
70
71
|
en.EN_US_DATA_STATE_COPY,
|
|
71
72
|
);
|
|
73
|
+
export const DATA_GRID_COPY = pack<DataGridCopy>(pt.PT_BR_DATA_GRID_COPY, en.EN_US_DATA_GRID_COPY);
|
|
72
74
|
export const DATA_VIEWS_COPY = pack<DataViewsCopy>(
|
|
73
75
|
pt.PT_BR_DATA_VIEWS_COPY,
|
|
74
76
|
en.EN_US_DATA_VIEWS_COPY,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { DataViewsCopy } from "./components/data-display/DataViews/data-views-copy";
|
|
6
6
|
import type {
|
|
7
7
|
CarouselCopy,
|
|
8
|
+
DataGridCopy,
|
|
8
9
|
DataStateCopy,
|
|
9
10
|
LightboxCopy,
|
|
10
11
|
MapPreviewCopy,
|
|
@@ -26,6 +27,20 @@ export const PT_BR_LIGHTBOX_COPY: LightboxCopy = {
|
|
|
26
27
|
resetZoom: "Restaurar o zoom",
|
|
27
28
|
play: "Iniciar a apresentação",
|
|
28
29
|
pause: "Pausar a apresentação",
|
|
30
|
+
dialogLabel: "Galeria de imagens",
|
|
31
|
+
itemPosition: (index, total) => `Item ${index} de ${total}`,
|
|
32
|
+
videoFallback: (index, total) => `Vídeo ${index} de ${total}`,
|
|
33
|
+
imageFallback: (index, total) => `Imagem ${index} de ${total}`,
|
|
34
|
+
thumbnailFallback: (index) => `Miniatura ${index}`,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const PT_BR_DATA_GRID_COPY: DataGridCopy = {
|
|
38
|
+
sortBy: (header) => `Ordenar por ${header}`,
|
|
39
|
+
selectRow: (rowNumber) => `Selecionar linha ${rowNumber}`,
|
|
40
|
+
selectAllRows: "Selecionar todas as linhas",
|
|
41
|
+
expandRow: "Expandir linha",
|
|
42
|
+
collapseRow: "Recolher linha",
|
|
43
|
+
gridLabel: "Grade de dados",
|
|
29
44
|
};
|
|
30
45
|
|
|
31
46
|
export const PT_BR_MAP_PREVIEW_COPY: MapPreviewCopy = {
|
|
@@ -45,6 +60,13 @@ export const PT_BR_CAROUSEL_COPY: CarouselCopy = {
|
|
|
45
60
|
export const PT_BR_TIMING_DIAGRAM_COPY: TimingDiagramCopy = {
|
|
46
61
|
regionLabel: "Diagrama de tempos",
|
|
47
62
|
heading: "Tempo da requisição",
|
|
63
|
+
dns: "Busca de DNS",
|
|
64
|
+
connect: "Conexão",
|
|
65
|
+
ssl: "SSL/TLS",
|
|
66
|
+
request: "Requisição",
|
|
67
|
+
response: "Resposta",
|
|
68
|
+
total: (formatted) => `Total: ${formatted}`,
|
|
69
|
+
totalTime: (formatted) => `Tempo total: ${formatted}`,
|
|
48
70
|
};
|
|
49
71
|
|
|
50
72
|
export const PT_BR_DATA_STATE_COPY: DataStateCopy = {
|
|
@@ -158,6 +180,7 @@ export const PT_BR_DATA_VIEWS_COPY: DataViewsCopy = {
|
|
|
158
180
|
},
|
|
159
181
|
tableFilter: PT_BR_TABLE_FILTER_COPY,
|
|
160
182
|
grid: {
|
|
183
|
+
...PT_BR_DATA_GRID_COPY,
|
|
161
184
|
rowActions: "Ações",
|
|
162
185
|
bulkActions: (selectedCount) => `Ações (${selectedCount}) ▾`,
|
|
163
186
|
emptyFilteredTitle: "Nenhum resultado para esses filtros",
|
package/src/pt-BR.feedback.ts
CHANGED
|
@@ -13,6 +13,9 @@ export const PT_BR_TUTORIAL_COPY: TutorialCopy = {
|
|
|
13
13
|
previous: "Anterior",
|
|
14
14
|
next: "Próximo",
|
|
15
15
|
restart: "Recomeçar",
|
|
16
|
+
complete: "Concluir",
|
|
17
|
+
finish: "Finalizar",
|
|
18
|
+
requiresAction: "Conclua a ação obrigatória primeiro",
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
export const PT_BR_CHROME_COPY: ChromeCopy = {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/en-US.data-display.ts"],"sourcesContent":["/**\n * The en-US pack for the data-display family. Split the same way\n * `pt-BR.data-display.ts` is — see `en-US.ts` for why.\n */\nimport type { DataViewsCopy } from \"./components/data-display/DataViews/data-views-copy\";\nimport type {\n CarouselCopy,\n DataStateCopy,\n LightboxCopy,\n MapPreviewCopy,\n TimingDiagramCopy,\n} from './copy';\nimport { EN_US_TABLE_FILTER_COPY } from './en-US.layout';\nimport {\n EN_US_CATEGORY_SELECT_COPY,\n EN_US_CONFIRM_ACTION_COPY,\n EN_US_SAVED_VIEWS_LABELS,\n} from './en-US.shared';\n\nexport const EN_US_LIGHTBOX_COPY: LightboxCopy = {\n close: \"Close\",\n previous: \"Previous\",\n next: \"Next\",\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n resetZoom: \"Reset zoom\",\n play: \"Start the slideshow\",\n pause: \"Pause the slideshow\",\n};\n\nexport const EN_US_MAP_PREVIEW_COPY: MapPreviewCopy = {\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n center: \"Centre the map\",\n mapType: \"Change the map type\",\n fullscreen: \"Full screen\",\n search: \"Search for an address\",\n};\n\nexport const EN_US_CAROUSEL_COPY: CarouselCopy = {\n previous: \"Previous\",\n next: \"Next\",\n};\n\nexport const EN_US_TIMING_DIAGRAM_COPY: TimingDiagramCopy = {\n regionLabel: \"Timing diagram\",\n heading: \"Request timing\",\n};\n\nexport const EN_US_DATA_STATE_COPY: DataStateCopy = {\n empty: \"Nothing here\",\n loading: \"Loading…\",\n endOfList: \"No more items to load\",\n dismissAlert: \"Dismiss\",\n dismissBanner: \"Dismiss this banner\",\n};\n\nexport const EN_US_DATA_VIEWS_COPY: DataViewsCopy = {\n savedViewsMenu: EN_US_SAVED_VIEWS_LABELS,\n confirmAction: EN_US_CONFIRM_ACTION_COPY,\n categorySelect: EN_US_CATEGORY_SELECT_COPY,\n board: {\n countOnPage: (label, count) => `${label}: ${count} on this page`,\n onThisPage: (count) => `${count} on this page`,\n pageSum: (sum) => `This page totals ${sum}`,\n emptyColumn: \"Nothing at this stage\",\n pageScopeNote: \"The counts and totals below cover only the items on this page.\",\n },\n deleteView: {\n title: \"Delete view\",\n target: (viewName) => `Delete \"${viewName}\"?`,\n sharedWarning: \"This view is shared — the team will lose access to it.\",\n // `entityLabel` is the HOST's word for what the rows are, so the sentence is\n // built around it rather than naming a noun of its own.\n rowsUnaffected: (entityLabel) =>\n `${entityLabel} are not affected; only the saved slice is removed.`,\n confirm: \"Delete view\",\n cancel: \"Cancel\",\n },\n manageViews: {\n title: \"Manage views\",\n empty: \"No saved views.\",\n edit: \"Edit\",\n defaultTag: \"Default\",\n otherUserTag: \"Another user's\",\n deleteTitle: \"Delete this saved view?\",\n deleteBody: \"The filters and columns it holds are lost. This cannot be undone.\",\n deleteConfirm: \"Delete\",\n },\n saveView: {\n sharedDescription: \"Anyone in the store will be able to open and use this view.\",\n setDefaultTitle: \"Set as default\",\n setDefaultDescription: \"This screen opens on this view instead of the Main view.\",\n previewHeading: \"What this view holds\",\n previewUnchanged: \"Nothing has changed — this view will match the Main view.\",\n sortRowLabel: \"Sorting\",\n saveFailed: \"Could not save the view.\",\n titleEditing: \"Edit view\",\n titleCreating: \"Save view\",\n descriptionLabel: \"Description — optional\",\n descriptionPlaceholder: \"What this view is for\",\n submitEditing: \"Save changes\",\n submitCreating: \"Save view\",\n nameLabel: \"Name\",\n cancel: \"Cancel\",\n pinnedTitle: \"Pin to the sidebar\",\n pinnedDescription: \"Appears as a shortcut in the menu, under this screen.\",\n sharedTitle: \"Share with the team\",\n namePlaceholder: \"e.g. Declined card payments this week\",\n previewFilters: \"Filters\",\n previewHiddenColumns: \"Hidden columns\",\n },\n columns: {\n visibleCount: (visible, total) => `${visible} of ${total} visible`,\n reset: \"Default\",\n showAll: \"Show all\",\n dragHint: \"Drag to reorder the columns.\",\n moveUp: (columnLabel) => `Move ${columnLabel} up`,\n moveDown: (columnLabel) => `Move ${columnLabel} down`,\n },\n display: {\n sortTab: \"Sort\",\n columnsTab: \"Columns\",\n panelTab: \"Display\",\n direction: \"Direction\",\n layoutHints: {\n table: \"Comparable columns, good for scanning numbers.\",\n list: \"One row per item, with the key fields.\",\n cards: \"Larger blocks, good for a handful of items.\",\n board: \"A column per stage, for tracking what is where.\",\n },\n densityHeadings: {\n table: \"Row height\",\n list: \"Row height\",\n cards: \"Cards per row\",\n board: \"Column width\",\n },\n densityLabels: {\n table: { compact: \"Low\", cozy: \"Medium\", comfortable: \"High\" },\n list: { compact: \"Low\", cozy: \"Medium\", comfortable: \"High\" },\n cards: { compact: \"Many\", cozy: \"Some\", comfortable: \"Few\" },\n board: { compact: \"Narrow\", cozy: \"Medium\", comfortable: \"Wide\" },\n },\n boardUnavailable: \"This screen declares no stages, so it offers no board.\",\n densityUnavailableNarrow:\n \"One card per row at this width — density returns on larger screens.\",\n trigger: \"Display\",\n fieldHeading: \"Field\",\n formatHeading: \"Format\",\n cardZoom: \"Card size\",\n },\n export: {\n formats: {\n // The extension is the file's, not a word: it stays as it is written on\n // disk in every language.\n json: { label: \"JSON (.json)\", hint: \"For integrations\" },\n },\n visibleColumns: (columnCount) => `${columnCount} visible columns, in their current order`,\n trigger: \"Export\",\n triggerLabel: \"Export\",\n },\n tableFilter: EN_US_TABLE_FILTER_COPY,\n grid: {\n rowActions: \"Actions\",\n bulkActions: (selectedCount) => `Actions (${selectedCount}) ▾`,\n emptyFilteredTitle: \"No results for these filters\",\n emptyFilteredHint: \"Adjust or remove the filters.\",\n emptyFilteredAction: \"Clear filters\",\n },\n filters: {\n moreFilters: (count) => `More filters: ${count} did not fit in the bar`,\n moreFiltersApplied: (count, appliedCount) =>\n `More filters: ${count} did not fit in the bar, ${appliedCount} applied`,\n moreTriggerLabel: \"More\",\n moreHeading: \"More filters\",\n overflowNote: \"did not fit in the bar\",\n rangeEnd: \"To\",\n rangeInvalid: \"The start must be earlier than the end.\",\n rangeInclusiveNote: \"Both dates are included in the result.\",\n rangeStart: \"From\",\n // The mask is what the reader TYPES, so it follows their own date order\n // rather than being carried over. A translated label above an unchanged\n // mask is the shape that gets a date entered backwards.\n dayMask: \"mm/dd/yyyy\",\n clearAllFilters: \"Clear all filters\",\n // The KEYS are the package's own preset ids and stay as they are — the\n // surface matches on them. Only the labels beside them are words.\n rangePresets: {\n hoje: \"Today\",\n ontem: \"Yesterday\",\n semana: \"This week\",\n mes: \"This month\",\n ano: \"This year\",\n },\n scopesLabel: \"Status\",\n panelTitle: \"Filters\",\n clear: \"Clear\",\n clearAll: \"Clear filters\",\n clearRange: (label) => `Clear ${label}`,\n allOption: \"All\",\n optionSearchPlaceholder: \"Search…\",\n optionsEmpty: \"No results\",\n optionsHeading: \"Options\",\n },\n selection: {\n selectAllOnPage: \"Select all on this page\",\n clearSelection: \"Clear selection\",\n selectAll: \"Select all\",\n onThisPage: (count) => `${count} on this page`,\n selectRow: \"Select\",\n expandRow: \"Expand details\",\n collapseRow: \"Collapse details\",\n },\n nav: {\n mainView: \"Main view\",\n defaultTag: \"Default\",\n viewOptions: (viewName) => `${viewName} options`,\n emptyHint: \"No saved views. Adjust filters, columns or sorting and save below.\",\n setDefault: \"Set as default\",\n deleteView: \"Delete view\",\n unsavedChanges: \"Unsaved changes\",\n label: \"View\",\n update: \"Update view\",\n save: \"Save view\",\n saveAs: \"Save as new\",\n reset: \"Reset\",\n updateFailed: \"Could not update the view\",\n dismissError: \"Dismiss\",\n goBack: \"Back\",\n pageSize: \"Show:\",\n saveFailed: \"Could not save the change to the view.\",\n editView: \"Rename and edit\",\n pinToSidebar: \"Pin to the sidebar\",\n shareWithTeam: \"Share with the team\",\n },\n search: {\n placeholder: \"Search…\",\n allColumnsLabel: \"Search every column\",\n keywordPlaceholder: \"Press Enter to filter\",\n open: \"Search\",\n close: \"Close search\",\n clear: \"Clear search\",\n },\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/TimingDiagram/TimingDiagram.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport Paper from '@mui/material/Paper/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { alpha, styled } from '@mui/material/styles/index.js';\nimport type { FC } from 'react';\nimport React, { useMemo } from 'react';\n\nimport type { TimingData, TimingDiagramProps } from './TimingDiagram.types';\nimport type { Phase, PhaseKey, TimingViewProps } from './TimingDiagram.views';\nimport {\n HorizontalView,\n phaseColors,\n StackedView,\n WaterfallView,\n} from './TimingDiagram.views';\nimport { rem } from '../../../tokens/relative';\n\n// Styled components\nconst DiagramContainer = styled(Paper)(({ theme }) => ({\n padding: theme.spacing(3),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.9)} 0%, ${alpha(theme.palette.background.paper, 0.8)} 100%)`,\n backdropFilter: `blur(${rem(theme, 10)})`,\n WebkitBackdropFilter: `blur(${rem(theme, 10)})`,\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n borderRadius: theme.shape.borderRadius * 2,\n}));\n\nconst Legend = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginTop: theme.spacing(2),\n paddingTop: theme.spacing(2),\n borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n}));\n\nconst LegendItem = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n '& .color': {\n width: rem(theme, 12),\n height: rem(theme, 12),\n borderRadius: rem(theme, 2),\n },\n '& .label': {\n fontSize: rem(theme, 12.8),\n color: theme.palette.text.secondary,\n },\n}));\n\n// Helper functions\nconst calculatePercentages = (data: TimingData): Record<string, number> => {\n const total = data.total || 1;\n return {\n dns: ((data.dns || 0) / total) * 100,\n connect: ((data.connect || 0) / total) * 100,\n ssl: ((data.ssl || 0) / total) * 100,\n request: ((data.request || 0) / total) * 100,\n response: ((data.response || 0) / total) * 100,\n };\n};\n\n// A phase with no recorded time never happened — an HTTP request has no SSL\n// handshake, for instance — so it gets no bar and no legend entry.\nconst phasesOf = (data: TimingData): Phase[] =>\n [\n { key: 'dns', label: 'DNS Lookup', value: data.dns },\n { key: 'connect', label: 'Connection', value: data.connect },\n { key: 'ssl', label: 'SSL/TLS', value: data.ssl },\n { key: 'request', label: 'Request', value: data.request },\n { key: 'response', label: 'Response', value: data.response },\n ].filter((phase) => phase.value !== undefined && phase.value > 0);\n\nconst VIEWS: Record<string, FC<TimingViewProps>> = {\n waterfall: WaterfallView,\n stacked: StackedView,\n horizontal: HorizontalView,\n};\n\n// Main component\nexport const TimingDiagram: FC<TimingDiagramProps> = ({\n copy,\n data,\n showLabels = true,\n height,\n animated = true,\n showTooltips = true,\n variant = 'waterfall',\n}) => {\n const percentages = useMemo(() => calculatePercentages(data), [data]);\n const phases = phasesOf(data);\n const View = VIEWS[variant];\n\n return (\n <DiagramContainer elevation={2} role=\"region\" aria-label={copy.regionLabel} tabIndex={0}>\n <Typography variant=\"h6\" fontWeight=\"bold\" gutterBottom>\n {copy.heading}\n </Typography>\n\n {View && (\n <View\n phases={phases}\n percentages={percentages}\n data={data}\n animated={animated}\n showLabels={showLabels}\n showTooltips={showTooltips}\n // The waterfall's plot height, 40 design px unless the caller says otherwise.\n plotHeightPx={height ?? 40}\n />\n )}\n\n {showLabels && (\n <Legend>\n {phases.map((phase) => (\n <LegendItem key={phase.key}>\n <Box\n className=\"color\"\n sx={(theme) => ({ backgroundColor: phaseColors(theme)[phase.key as PhaseKey] })}\n />\n <Typography className=\"label\">{phase.label}</Typography>\n </LegendItem>\n ))}\n </Legend>\n )}\n </DiagramContainer>\n );\n};\n\n// Export default\nexport default TimingDiagram;\n"],"mappings":";;;;;;;;;;;AAAA,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,gBAAgB;AACvB,SAAS,OAAO,cAAc;AAE9B,SAAgB,eAAe;AA2FzB,cAoBM,YApBN;AA9EN,IAAM,mBAAmB,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,OAAO;AAAA,EACrD,SAAS,MAAM,QAAQ,CAAC;AAAA,EACxB,YAAY,2BAA2B,MAAM,MAAM,QAAQ,WAAW,OAAO,GAAG,CAAC,QAAQ,MAAM,MAAM,QAAQ,WAAW,OAAO,GAAG,CAAC;AAAA,EACnI,gBAAgB,QAAQ,IAAI,OAAO,EAAE,CAAC;AAAA,EACtC,sBAAsB,QAAQ,IAAI,OAAO,EAAE,CAAC;AAAA,EAC5C,QAAQ,aAAa,MAAM,MAAM,QAAQ,SAAS,IAAI,CAAC;AAAA,EACvD,cAAc,MAAM,MAAM,eAAe;AAC3C,EAAE;AAEF,IAAM,SAAS,OAAO,GAAG,EAAE,CAAC,EAAE,MAAM,OAAO;AAAA,EACzC,SAAS;AAAA,EACT,UAAU;AAAA,EACV,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpB,WAAW,MAAM,QAAQ,CAAC;AAAA,EAC1B,YAAY,MAAM,QAAQ,CAAC;AAAA,EAC3B,WAAW,aAAa,MAAM,MAAM,QAAQ,SAAS,GAAG,CAAC;AAC3D,EAAE;AAEF,IAAM,aAAa,OAAO,GAAG,EAAE,CAAC,EAAE,MAAM,OAAO;AAAA,EAC7C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpB,YAAY;AAAA,IACV,OAAO,IAAI,OAAO,EAAE;AAAA,IACpB,QAAQ,IAAI,OAAO,EAAE;AAAA,IACrB,cAAc,IAAI,OAAO,CAAC;AAAA,EAC5B;AAAA,EACA,YAAY;AAAA,IACV,UAAU,IAAI,OAAO,IAAI;AAAA,IACzB,OAAO,MAAM,QAAQ,KAAK;AAAA,EAC5B;AACF,EAAE;AAGF,IAAM,uBAAuB,CAAC,SAA6C;AACzE,QAAM,QAAQ,KAAK,SAAS;AAC5B,SAAO;AAAA,IACL,MAAO,KAAK,OAAO,KAAK,QAAS;AAAA,IACjC,UAAW,KAAK,WAAW,KAAK,QAAS;AAAA,IACzC,MAAO,KAAK,OAAO,KAAK,QAAS;AAAA,IACjC,UAAW,KAAK,WAAW,KAAK,QAAS;AAAA,IACzC,WAAY,KAAK,YAAY,KAAK,QAAS;AAAA,EAC7C;AACF;AAIA,IAAM,WAAW,CAAC,SAChB;AAAA,EACE,EAAE,KAAK,OAAO,OAAO,cAAc,OAAO,KAAK,IAAI;AAAA,EACnD,EAAE,KAAK,WAAW,OAAO,cAAc,OAAO,KAAK,QAAQ;AAAA,EAC3D,EAAE,KAAK,OAAO,OAAO,WAAW,OAAO,KAAK,IAAI;AAAA,EAChD,EAAE,KAAK,WAAW,OAAO,WAAW,OAAO,KAAK,QAAQ;AAAA,EACxD,EAAE,KAAK,YAAY,OAAO,YAAY,OAAO,KAAK,SAAS;AAC7D,EAAE,OAAO,CAAC,UAAU,MAAM,UAAU,UAAa,MAAM,QAAQ,CAAC;AAElE,IAAM,QAA6C;AAAA,EACjD,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AACd;AAGO,IAAM,gBAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,WAAW;AAAA,EACX,eAAe;AAAA,EACf,UAAU;AACZ,MAAM;AACJ,QAAM,cAAc,QAAQ,MAAM,qBAAqB,IAAI,GAAG,CAAC,IAAI,CAAC;AACpE,QAAM,SAAS,SAAS,IAAI;AAC5B,QAAM,OAAO,MAAM,OAAO;AAE1B,SACE,qBAAC,oBAAiB,WAAW,GAAG,MAAK,UAAS,cAAY,KAAK,aAAa,UAAU,GACpF;AAAA,wBAAC,cAAW,SAAQ,MAAK,YAAW,QAAO,cAAY,MACpD,eAAK,SACR;AAAA,IAEC,QACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QAEA,cAAc,UAAU;AAAA;AAAA,IAC1B;AAAA,IAGD,cACC,oBAAC,UACE,iBAAO,IAAI,CAAC,UACX,qBAAC,cACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,IAAI,CAAC,WAAW,EAAE,iBAAiB,YAAY,KAAK,EAAE,MAAM,GAAe,EAAE;AAAA;AAAA,MAC/E;AAAA,MACA,oBAAC,cAAW,WAAU,SAAS,gBAAM,OAAM;AAAA,SAL5B,MAAM,GAMvB,CACD,GACH;AAAA,KAEJ;AAEJ;AAGA,IAAO,wBAAQ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pt-BR.feedback.ts"],"sourcesContent":["/**\n * The pt-BR pack for the feedback family. Split out of `pt-BR.ts`, which is a\n * barrel over this folder — see that file for why.\n */\nimport type {\n ChromeCopy,\n NotificationUnblockCopy,\n TutorialCopy,\n} from './copy';\n\nexport const PT_BR_TUTORIAL_COPY: TutorialCopy = {\n skip: \"Pular\",\n previous: \"Anterior\",\n next: \"Próximo\",\n restart: \"Recomeçar\",\n};\n\nexport const PT_BR_CHROME_COPY: ChromeCopy = {\n dismissToast: \"Fechar o aviso\",\n goBack: \"Voltar\",\n closePanel: \"Fechar\",\n closeTab: \"Fechar a aba\",\n scrollRegion: \"Conteúdo rolável\",\n scrollToTop: \"Voltar ao topo\",\n share: \"Compartilhar\",\n};\n\nconst PT_BR_CHROMIUM_DESKTOP = [\n \"Clique no ícone à esquerda do endereço do site.\",\n \"Abra \\\"Configurações do site\\\".\",\n \"Em \\\"Notificações\\\", escolha \\\"Permitir\\\".\",\n \"Volte a esta página e recarregue.\",\n] as const;\n\nconst PT_BR_CHROMIUM_ANDROID = [\n \"Toque no ícone à esquerda do endereço do site.\",\n \"Toque em \\\"Permissões\\\".\",\n \"Toque em \\\"Notificações\\\" e escolha \\\"Permitir\\\".\",\n \"Volte a esta página e recarregue.\",\n] as const;\n\nexport const PT_BR_NOTIFICATION_UNBLOCK_COPY: NotificationUnblockCopy = {\n ios: [\n \"Abra os Ajustes do iPhone.\",\n \"Toque em \\\"Notificações\\\".\",\n \"Encontre este app na lista e ative \\\"Permitir Notificações\\\".\",\n ],\n chrome: { desktop: PT_BR_CHROMIUM_DESKTOP, android: PT_BR_CHROMIUM_ANDROID },\n edge: {\n desktop: [\n \"Clique no cadeado à esquerda do endereço do site.\",\n \"Abra \\\"Permissões para este site\\\".\",\n \"Em \\\"Notificações\\\", escolha \\\"Permitir\\\".\",\n \"Volte a esta página e recarregue.\",\n ],\n android: PT_BR_CHROMIUM_ANDROID,\n },\n firefox: {\n desktop: [\n \"Clique no ícone de permissões à esquerda do endereço do site.\",\n \"Ao lado de \\\"Enviar notificações\\\", clique no X para tirar o bloqueio.\",\n \"Recarregue a página e ative as notificações de novo.\",\n ],\n android: [\n \"Abra o menu do navegador e toque em \\\"Configurações\\\".\",\n \"Toque em \\\"Permissões de sites\\\" e depois em \\\"Notificações\\\".\",\n \"Encontre este site e escolha \\\"Permitir\\\".\",\n \"Volte a esta página e recarregue.\",\n ],\n },\n opera: { desktop: PT_BR_CHROMIUM_DESKTOP, android: PT_BR_CHROMIUM_ANDROID },\n safari: {\n desktop: [\n \"No menu Safari, abra \\\"Ajustes\\\".\",\n \"Vá na aba \\\"Sites\\\" e, na lateral, em \\\"Notificações\\\".\",\n \"Encontre este site e escolha \\\"Permitir\\\".\",\n \"Volte a esta página e recarregue.\",\n ],\n },\n samsung: {\n android: [\n \"Abra o menu do navegador e toque em \\\"Configurações\\\".\",\n \"Toque em \\\"Sites e downloads\\\" e depois em \\\"Notificações\\\".\",\n \"Encontre este site e permita as notificações.\",\n \"Volte a esta página e recarregue.\",\n ],\n },\n other: [\n \"Abra as configurações do navegador.\",\n \"Procure as permissões dos sites e depois \\\"Notificações\\\".\",\n \"Permita as notificações para este site.\",\n \"Volte a esta página e recarregue.\",\n ],\n};\n"],"mappings":";AAUO,IAAM,sBAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AACX;AAEO,IAAM,oBAAgC;AAAA,EAC3C,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,OAAO;AACT;AAEA,IAAM,yBAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,yBAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kCAA2D;AAAA,EACtE,KAAK;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ,EAAE,SAAS,wBAAwB,SAAS,uBAAuB;AAAA,EAC3E,MAAM;AAAA,IACJ,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO,EAAE,SAAS,wBAAwB,SAAS,uBAAuB;AAAA,EAC1E,QAAQ;AAAA,IACN,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/Lightbox/LightboxMedia.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport React from 'react';\n\nimport type { LightboxItem } from './Lightbox.types';\n\nexport interface LightboxMediaProps {\n item: LightboxItem;\n index: number;\n total: number;\n zoomLevel: number;\n panOffset: { x: number; y: number };\n zoomable: boolean;\n isDragging: boolean;\n testId: (suffix: string) => string;\n onLoadStart: () => void;\n onLoaded: () => void;\n onWheel: (event: React.WheelEvent) => void;\n onDoubleClick: () => void;\n}\n\nconst cursorFor = (zoomLevel: number, zoomable: boolean): string => {\n if (zoomLevel > 1) return 'move';\n return zoomable ? 'zoom-in' : 'default';\n};\n\nexport const LightboxMedia: FC<LightboxMediaProps> = ({\n item,\n index,\n total,\n zoomLevel,\n panOffset,\n zoomable,\n isDragging,\n testId,\n onLoadStart,\n onLoaded,\n onWheel,\n onDoubleClick,\n}) => {\n if (item.type === 'video') {\n return (\n <video\n src={item.src}\n controls\n style={{ maxWidth: '90vw', maxHeight: '80vh', objectFit: 'contain' }}\n onLoadStart={onLoadStart}\n onLoadedData={onLoaded}\n aria-label={item.alt || `Video ${index + 1} of ${total}`}\n data-testid={testId('video')}\n />\n );\n }\n\n return (\n <img\n src={item.src}\n alt={item.alt || `Image ${index + 1} of ${total}`}\n style={{\n // At 1x the image is bounded by the viewport; once zoomed it is allowed\n // to overflow so there is something to pan around.\n maxWidth: zoomLevel === 1 ? '90vw' : 'none',\n maxHeight: zoomLevel === 1 ? '80vh' : 'none',\n transform: `scale(${zoomLevel}) translate(${panOffset.x}px, ${panOffset.y}px)`,\n transformOrigin: 'center',\n cursor: cursorFor(zoomLevel, zoomable),\n transition: isDragging ? 'none' : 'transform 0.2s ease',\n objectFit: 'contain',\n }}\n onLoad={onLoaded}\n onWheel={onWheel}\n onDoubleClick={onDoubleClick}\n draggable={false}\n data-testid={testId('image')}\n />\n );\n};\n"],"mappings":";AAyCM;AArBN,IAAM,YAAY,CAAC,WAAmB,aAA8B;AAClE,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO,WAAW,YAAY;AAChC;AAEO,IAAM,gBAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,MAAI,KAAK,SAAS,SAAS;AACzB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK,KAAK;AAAA,QACV,UAAQ;AAAA,QACR,OAAO,EAAE,UAAU,QAAQ,WAAW,QAAQ,WAAW,UAAU;AAAA,QACnE;AAAA,QACA,cAAc;AAAA,QACd,cAAY,KAAK,OAAO,SAAS,QAAQ,CAAC,OAAO,KAAK;AAAA,QACtD,eAAa,OAAO,OAAO;AAAA;AAAA,IAC7B;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,KAAK;AAAA,MACV,KAAK,KAAK,OAAO,SAAS,QAAQ,CAAC,OAAO,KAAK;AAAA,MAC/C,OAAO;AAAA;AAAA;AAAA,QAGL,UAAU,cAAc,IAAI,SAAS;AAAA,QACrC,WAAW,cAAc,IAAI,SAAS;AAAA,QACtC,WAAW,SAAS,SAAS,eAAe,UAAU,CAAC,OAAO,UAAU,CAAC;AAAA,QACzE,iBAAiB;AAAA,QACjB,QAAQ,UAAU,WAAW,QAAQ;AAAA,QACrC,YAAY,aAAa,SAAS;AAAA,QAClC,WAAW;AAAA,MACb;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,eAAa,OAAO,OAAO;AAAA;AAAA,EAC7B;AAEJ;","names":[]}
|