@ankhorage/zora 3.1.1 → 3.3.1
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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/dist/components/card/meta.d.ts +1 -1
- package/dist/components/progress/ProgressRing.d.ts +7 -0
- package/dist/components/progress/ProgressRing.d.ts.map +1 -0
- package/dist/components/progress/ProgressRing.js +100 -0
- package/dist/components/progress/ProgressRing.js.map +1 -0
- package/dist/components/progress/index.d.ts +2 -1
- package/dist/components/progress/index.d.ts.map +1 -1
- package/dist/components/progress/index.js +1 -0
- package/dist/components/progress/index.js.map +1 -1
- package/dist/components/progress/meta.d.ts +116 -0
- package/dist/components/progress/meta.d.ts.map +1 -1
- package/dist/components/progress/meta.js +97 -0
- package/dist/components/progress/meta.js.map +1 -1
- package/dist/components/progress/resolveProgressRingGeometry.d.ts +12 -0
- package/dist/components/progress/resolveProgressRingGeometry.d.ts.map +1 -0
- package/dist/components/progress/resolveProgressRingGeometry.js +27 -0
- package/dist/components/progress/resolveProgressRingGeometry.js.map +1 -0
- package/dist/components/progress/types.d.ts +12 -0
- package/dist/components/progress/types.d.ts.map +1 -1
- package/dist/components/progress/types.js.map +1 -1
- package/dist/foundation/meta.d.ts +4 -4
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/screen/meta.d.ts +1 -1
- package/dist/layout/screen-section/meta.d.ts +1 -1
- package/dist/metadata/allowedChildren.d.ts +4 -3
- package/dist/metadata/allowedChildren.d.ts.map +1 -1
- package/dist/metadata/allowedChildren.js +13 -0
- package/dist/metadata/allowedChildren.js.map +1 -1
- package/dist/metadata/bindableComponentMeta.d.ts +2 -2
- package/dist/metadata/componentMeta.d.ts.map +1 -1
- package/dist/metadata/componentMeta.js +4 -1
- package/dist/metadata/componentMeta.js.map +1 -1
- package/dist/patterns/content-rail/ContentRail.d.ts +10 -0
- package/dist/patterns/content-rail/ContentRail.d.ts.map +1 -0
- package/dist/patterns/content-rail/ContentRail.js +175 -0
- package/dist/patterns/content-rail/ContentRail.js.map +1 -0
- package/dist/patterns/content-rail/index.d.ts +3 -0
- package/dist/patterns/content-rail/index.d.ts.map +1 -0
- package/dist/patterns/content-rail/index.js +2 -0
- package/dist/patterns/content-rail/index.js.map +1 -0
- package/dist/patterns/content-rail/meta.d.ts +143 -0
- package/dist/patterns/content-rail/meta.d.ts.map +1 -0
- package/dist/patterns/content-rail/meta.js +130 -0
- package/dist/patterns/content-rail/meta.js.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailItemWidth.d.ts +10 -0
- package/dist/patterns/content-rail/resolveContentRailItemWidth.d.ts.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailItemWidth.js +25 -0
- package/dist/patterns/content-rail/resolveContentRailItemWidth.js.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailPhysicalOffset.d.ts +6 -0
- package/dist/patterns/content-rail/resolveContentRailPhysicalOffset.d.ts.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailPhysicalOffset.js +5 -0
- package/dist/patterns/content-rail/resolveContentRailPhysicalOffset.js.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailState.d.ts +18 -0
- package/dist/patterns/content-rail/resolveContentRailState.d.ts.map +1 -0
- package/dist/patterns/content-rail/resolveContentRailState.js +21 -0
- package/dist/patterns/content-rail/resolveContentRailState.js.map +1 -0
- package/dist/patterns/content-rail/types.d.ts +31 -0
- package/dist/patterns/content-rail/types.d.ts.map +1 -0
- package/dist/patterns/content-rail/types.js +2 -0
- package/dist/patterns/content-rail/types.js.map +1 -0
- package/dist/patterns/content-rail/useContentRailReducedMotion.d.ts +3 -0
- package/dist/patterns/content-rail/useContentRailReducedMotion.d.ts.map +1 -0
- package/dist/patterns/content-rail/useContentRailReducedMotion.js +21 -0
- package/dist/patterns/content-rail/useContentRailReducedMotion.js.map +1 -0
- package/dist/patterns/message-bubble/meta.d.ts +1 -1
- package/dist/patterns/notice/meta.d.ts +1 -1
- package/dist/patterns/panel/meta.d.ts +1 -1
- package/dist/patterns/post-card/meta.d.ts +1 -1
- package/dist/patterns/reader/meta.d.ts +2 -2
- package/dist/patterns/scanner/meta.d.ts +2 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -1
- package/dist/registry.js.map +1 -1
- package/package.json +2 -2
- package/src/components/progress/ProgressRing.test.ts +48 -0
- package/src/components/progress/ProgressRing.tsx +151 -0
- package/src/components/progress/index.ts +2 -1
- package/src/components/progress/meta.ts +99 -0
- package/src/components/progress/resolveProgressRingGeometry.test.ts +30 -0
- package/src/components/progress/resolveProgressRingGeometry.ts +44 -0
- package/src/components/progress/types.ts +13 -0
- package/src/index.ts +12 -2
- package/src/interactionPolicy.test.ts +22 -0
- package/src/metadata/allowedChildren.ts +14 -0
- package/src/metadata/componentMeta.test.ts +51 -0
- package/src/metadata/componentMeta.ts +4 -1
- package/src/patterns/content-rail/ContentRail.test.ts +44 -0
- package/src/patterns/content-rail/ContentRail.tsx +245 -0
- package/src/patterns/content-rail/index.ts +10 -0
- package/src/patterns/content-rail/meta.ts +133 -0
- package/src/patterns/content-rail/resolveContentRailItemWidth.test.ts +77 -0
- package/src/patterns/content-rail/resolveContentRailItemWidth.ts +39 -0
- package/src/patterns/content-rail/resolveContentRailPhysicalOffset.test.ts +29 -0
- package/src/patterns/content-rail/resolveContentRailPhysicalOffset.ts +12 -0
- package/src/patterns/content-rail/resolveContentRailState.test.ts +68 -0
- package/src/patterns/content-rail/resolveContentRailState.ts +36 -0
- package/src/patterns/content-rail/types.ts +35 -0
- package/src/patterns/content-rail/useContentRailReducedMotion.ts +28 -0
- package/src/registry.ts +4 -1
- package/src/showcaseCoverage.test.ts +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function resolveContentRailPhysicalOffset({
|
|
2
|
+
isRtl,
|
|
3
|
+
logicalOffset,
|
|
4
|
+
maxOffset,
|
|
5
|
+
}: {
|
|
6
|
+
isRtl: boolean;
|
|
7
|
+
logicalOffset: number;
|
|
8
|
+
maxOffset: number;
|
|
9
|
+
}): number {
|
|
10
|
+
const clampedOffset = Math.min(Math.max(0, logicalOffset), Math.max(0, maxOffset));
|
|
11
|
+
return isRtl ? Math.max(0, maxOffset) - clampedOffset : clampedOffset;
|
|
12
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { resolveContentRailState } from './resolveContentRailState';
|
|
4
|
+
|
|
5
|
+
describe('resolveContentRailState', () => {
|
|
6
|
+
test('resolves overflow, visible items, and the nearest navigation anchor', () => {
|
|
7
|
+
expect(
|
|
8
|
+
resolveContentRailState({
|
|
9
|
+
contentWidth: 848,
|
|
10
|
+
gap: 16,
|
|
11
|
+
itemCount: 4,
|
|
12
|
+
itemWidth: 200,
|
|
13
|
+
logicalOffset: 216,
|
|
14
|
+
viewportWidth: 432,
|
|
15
|
+
}),
|
|
16
|
+
).toEqual({
|
|
17
|
+
anchorIndex: 1,
|
|
18
|
+
canGoNext: true,
|
|
19
|
+
canGoPrevious: true,
|
|
20
|
+
firstVisibleIndex: 1,
|
|
21
|
+
lastVisibleIndex: 2,
|
|
22
|
+
maxOffset: 416,
|
|
23
|
+
offset: 216,
|
|
24
|
+
stride: 216,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('clamps boundaries without wrapping', () => {
|
|
29
|
+
const start = resolveContentRailState({
|
|
30
|
+
contentWidth: 848,
|
|
31
|
+
gap: 16,
|
|
32
|
+
itemCount: 4,
|
|
33
|
+
itemWidth: 200,
|
|
34
|
+
logicalOffset: -100,
|
|
35
|
+
viewportWidth: 432,
|
|
36
|
+
});
|
|
37
|
+
const end = resolveContentRailState({
|
|
38
|
+
contentWidth: 848,
|
|
39
|
+
gap: 16,
|
|
40
|
+
itemCount: 4,
|
|
41
|
+
itemWidth: 200,
|
|
42
|
+
logicalOffset: 1000,
|
|
43
|
+
viewportWidth: 432,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(start).toMatchObject({ offset: 0, canGoPrevious: false, canGoNext: true });
|
|
47
|
+
expect(end).toMatchObject({ offset: 416, canGoPrevious: true, canGoNext: false });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('degrades to a non-overflowing empty range', () => {
|
|
51
|
+
expect(
|
|
52
|
+
resolveContentRailState({
|
|
53
|
+
contentWidth: 0,
|
|
54
|
+
gap: 16,
|
|
55
|
+
itemCount: 0,
|
|
56
|
+
itemWidth: 0,
|
|
57
|
+
logicalOffset: 0,
|
|
58
|
+
viewportWidth: 432,
|
|
59
|
+
}),
|
|
60
|
+
).toMatchObject({
|
|
61
|
+
canGoNext: false,
|
|
62
|
+
canGoPrevious: false,
|
|
63
|
+
firstVisibleIndex: -1,
|
|
64
|
+
lastVisibleIndex: -1,
|
|
65
|
+
maxOffset: 0,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function resolveContentRailState({
|
|
2
|
+
contentWidth,
|
|
3
|
+
gap,
|
|
4
|
+
itemCount,
|
|
5
|
+
itemWidth,
|
|
6
|
+
logicalOffset,
|
|
7
|
+
viewportWidth,
|
|
8
|
+
}: {
|
|
9
|
+
contentWidth: number;
|
|
10
|
+
gap: number;
|
|
11
|
+
itemCount: number;
|
|
12
|
+
itemWidth: number;
|
|
13
|
+
logicalOffset: number;
|
|
14
|
+
viewportWidth: number;
|
|
15
|
+
}) {
|
|
16
|
+
const maxOffset = Math.max(0, contentWidth - viewportWidth);
|
|
17
|
+
const offset = Math.min(Math.max(0, logicalOffset), maxOffset);
|
|
18
|
+
const stride = itemWidth + gap;
|
|
19
|
+
const firstVisibleIndex = stride > 0 ? Math.min(itemCount - 1, Math.floor(offset / stride)) : 0;
|
|
20
|
+
const lastVisibleIndex =
|
|
21
|
+
stride > 0
|
|
22
|
+
? Math.min(itemCount - 1, Math.max(0, Math.ceil((offset + viewportWidth) / stride) - 1))
|
|
23
|
+
: 0;
|
|
24
|
+
const anchorIndex = stride > 0 ? Math.round(offset / stride) : 0;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
anchorIndex: Math.min(Math.max(0, anchorIndex), Math.max(0, itemCount - 1)),
|
|
28
|
+
canGoNext: itemCount > 0 && offset < maxOffset - 1,
|
|
29
|
+
canGoPrevious: itemCount > 0 && offset > 1,
|
|
30
|
+
firstVisibleIndex: itemCount === 0 ? -1 : firstVisibleIndex,
|
|
31
|
+
lastVisibleIndex: itemCount === 0 ? -1 : lastVisibleIndex,
|
|
32
|
+
maxOffset,
|
|
33
|
+
offset,
|
|
34
|
+
stride,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
4
|
+
|
|
5
|
+
export type ContentRailDirection = 'auto' | 'ltr' | 'rtl';
|
|
6
|
+
export type ContentRailItemSize = 'compact' | 'regular' | 'wide' | 'responsive';
|
|
7
|
+
export type ContentRailMotion = 'system' | 'animated' | 'reduced';
|
|
8
|
+
export type ContentRailSpacing = 'none' | 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
9
|
+
|
|
10
|
+
export interface ContentRailControlPressEvent {
|
|
11
|
+
direction: 'previous' | 'next';
|
|
12
|
+
targetIndex: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ContentRailVisibleRangeChangeEvent {
|
|
16
|
+
firstVisibleIndex: number;
|
|
17
|
+
lastVisibleIndex: number;
|
|
18
|
+
itemCount: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ContentRailProps extends ZoraBaseProps {
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
itemSize?: ContentRailItemSize;
|
|
24
|
+
gap?: ContentRailSpacing;
|
|
25
|
+
padding?: ContentRailSpacing;
|
|
26
|
+
peek?: number;
|
|
27
|
+
showControls?: boolean;
|
|
28
|
+
direction?: ContentRailDirection;
|
|
29
|
+
motion?: ContentRailMotion;
|
|
30
|
+
accessibilityLabel?: string;
|
|
31
|
+
previousLabel?: string;
|
|
32
|
+
nextLabel?: string;
|
|
33
|
+
onControlPress?: (event: ContentRailControlPressEvent) => void | Promise<void>;
|
|
34
|
+
onVisibleRangeChange?: (event: ContentRailVisibleRangeChangeEvent) => void | Promise<void>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AccessibilityInfo } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { ContentRailMotion } from './types';
|
|
5
|
+
|
|
6
|
+
export function useContentRailReducedMotion(motion: ContentRailMotion): boolean {
|
|
7
|
+
const [systemReducedMotion, setSystemReducedMotion] = React.useState(false);
|
|
8
|
+
|
|
9
|
+
React.useEffect(() => {
|
|
10
|
+
if (motion !== 'system') return;
|
|
11
|
+
|
|
12
|
+
let active = true;
|
|
13
|
+
void AccessibilityInfo.isReduceMotionEnabled().then((enabled) => {
|
|
14
|
+
if (active) setSystemReducedMotion(enabled);
|
|
15
|
+
});
|
|
16
|
+
const subscription = AccessibilityInfo.addEventListener(
|
|
17
|
+
'reduceMotionChanged',
|
|
18
|
+
setSystemReducedMotion,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return () => {
|
|
22
|
+
active = false;
|
|
23
|
+
subscription.remove();
|
|
24
|
+
};
|
|
25
|
+
}, [motion]);
|
|
26
|
+
|
|
27
|
+
return motion === 'reduced' || (motion === 'system' && systemReducedMotion);
|
|
28
|
+
}
|
package/src/registry.ts
CHANGED
|
@@ -30,7 +30,7 @@ import { Modal } from './components/modal';
|
|
|
30
30
|
import { NavigationItem } from './components/navigation-item';
|
|
31
31
|
import { NavigationList } from './components/navigation-list';
|
|
32
32
|
import { Pagination } from './components/pagination';
|
|
33
|
-
import { Progress } from './components/progress';
|
|
33
|
+
import { Progress, ProgressRing } from './components/progress';
|
|
34
34
|
import { Radio, RadioGroup } from './components/radio';
|
|
35
35
|
import { Rating } from './components/rating';
|
|
36
36
|
import { SearchBar } from './components/search-bar';
|
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
import { ChatListItem } from './patterns/chat-list-item';
|
|
73
73
|
import { CollectionEditor } from './patterns/collection-editor';
|
|
74
74
|
import { ConfirmDialog } from './patterns/confirm-dialog';
|
|
75
|
+
import { ContentRail } from './patterns/content-rail';
|
|
75
76
|
import { DisclosureSection } from './patterns/disclosure-section';
|
|
76
77
|
import { EmptyState } from './patterns/empty-state';
|
|
77
78
|
import { FilterBar } from './patterns/filter-bar';
|
|
@@ -162,6 +163,7 @@ const _ZORA_COMPONENT_REGISTRY = {
|
|
|
162
163
|
NavigationList,
|
|
163
164
|
Pagination,
|
|
164
165
|
Progress,
|
|
166
|
+
ProgressRing,
|
|
165
167
|
Radio,
|
|
166
168
|
RadioGroup,
|
|
167
169
|
Rating,
|
|
@@ -205,6 +207,7 @@ const _ZORA_COMPONENT_REGISTRY = {
|
|
|
205
207
|
ChatListItem,
|
|
206
208
|
CollectionEditor,
|
|
207
209
|
ConfirmDialog,
|
|
210
|
+
ContentRail,
|
|
208
211
|
DisclosureSection,
|
|
209
212
|
EmptyState,
|
|
210
213
|
FilterBar,
|