@pushwoosh/dumb-components 2.8.1 → 2.9.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/InboxPreview/InboxPreview.d.ts +2 -0
- package/InboxPreview/InboxPreview.js +2 -0
- package/InboxPreview/constants.d.ts +4 -1
- package/InboxPreview/constants.js +4 -1
- package/InboxPreview/helpers.d.ts +1 -0
- package/InboxPreview/helpers.js +1 -0
- package/InboxPreview/types.d.ts +20 -5
- package/package.json +1 -1
- package/polyglot/__tests__/filters.test.js +29 -0
- package/polyglot/liquid/filters.js +18 -0
|
@@ -7,6 +7,8 @@ import type { InboxPreviewProps } from './types';
|
|
|
7
7
|
* a carousel shows at most five valid slides. Content without a single filled
|
|
8
8
|
* field renders the dashed placeholder of the requested layout.
|
|
9
9
|
*
|
|
10
|
+
* @deprecated Use `InboxCellPreview` from `@pushwoosh/websdk-common/inbox`, the renderer the WebSDK widget shares.
|
|
11
|
+
*
|
|
10
12
|
* @example
|
|
11
13
|
* <InboxPreview platform="ios" localizedContent={preset.localizedContent} language="en" />
|
|
12
14
|
*/
|
|
@@ -21,6 +21,8 @@ const CELL_BY_PLATFORM = {
|
|
|
21
21
|
* a carousel shows at most five valid slides. Content without a single filled
|
|
22
22
|
* field renders the dashed placeholder of the requested layout.
|
|
23
23
|
*
|
|
24
|
+
* @deprecated Use `InboxCellPreview` from `@pushwoosh/websdk-common/inbox`, the renderer the WebSDK widget shares.
|
|
25
|
+
*
|
|
24
26
|
* @example
|
|
25
27
|
* <InboxPreview platform="ios" localizedContent={preset.localizedContent} language="en" />
|
|
26
28
|
*/
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { InboxAvatarShape, InboxLayoutType, InboxPreviewPlatform } from './types';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The SDK renders at most this many carousel slides and silently drops the rest.
|
|
4
|
+
* @deprecated Use `INBOX_MAX_CAROUSEL_SLIDES` from `@pushwoosh/websdk-common/inbox`.
|
|
5
|
+
*/
|
|
3
6
|
export declare const MAX_CAROUSEL_SLIDES = 5;
|
|
4
7
|
/** Layouts the SDK knows; anything else falls back to the heuristic. */
|
|
5
8
|
export declare const KNOWN_LAYOUTS: readonly InboxLayoutType[];
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ShapeRadius } from '@pushwoosh/kit-constants';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The SDK renders at most this many carousel slides and silently drops the rest.
|
|
4
|
+
* @deprecated Use `INBOX_MAX_CAROUSEL_SLIDES` from `@pushwoosh/websdk-common/inbox`.
|
|
5
|
+
*/
|
|
3
6
|
export const MAX_CAROUSEL_SLIDES = 5;
|
|
4
7
|
/** Layouts the SDK knows; anything else falls back to the heuristic. */
|
|
5
8
|
export const KNOWN_LAYOUTS = ['classic', 'captioned', 'banner', 'carousel'];
|
|
@@ -11,6 +11,7 @@ export declare const getHeroUrl: (content: InboxPreviewContent) => string;
|
|
|
11
11
|
/**
|
|
12
12
|
* Resolves the layout the SDK would actually draw: the requested one when it can render,
|
|
13
13
|
* the SDK heuristic for unknown/absent layouts, and the classic degradation otherwise.
|
|
14
|
+
* @deprecated Use `resolveInboxLayout` from `@pushwoosh/websdk-common/inbox`.
|
|
14
15
|
*/
|
|
15
16
|
export declare const resolveInboxLayout: (content: InboxPreviewContent) => InboxLayoutType;
|
|
16
17
|
/** True when the content has nothing to render yet, so the preview shows the layout placeholder. */
|
package/InboxPreview/helpers.js
CHANGED
|
@@ -22,6 +22,7 @@ export const getHeroUrl = content => content.bannerUrl || content.iconUrl || '';
|
|
|
22
22
|
/**
|
|
23
23
|
* Resolves the layout the SDK would actually draw: the requested one when it can render,
|
|
24
24
|
* the SDK heuristic for unknown/absent layouts, and the classic degradation otherwise.
|
|
25
|
+
* @deprecated Use `resolveInboxLayout` from `@pushwoosh/websdk-common/inbox`.
|
|
25
26
|
*/
|
|
26
27
|
export const resolveInboxLayout = content => {
|
|
27
28
|
const hasTitle = !!content.title;
|
package/InboxPreview/types.d.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { TypographyVariant } from '@pushwoosh/kit-typography';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Cell layout of an Inbox message.
|
|
5
|
+
* @deprecated Use `InboxLayout` from `@pushwoosh/websdk-common/inbox`.
|
|
6
|
+
*/
|
|
4
7
|
export type InboxLayoutType = 'classic' | 'captioned' | 'banner' | 'carousel';
|
|
5
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* One carousel slide of an Inbox message.
|
|
10
|
+
* @deprecated Use `InboxSlide` from `@pushwoosh/websdk-common/inbox`.
|
|
11
|
+
*/
|
|
6
12
|
export interface InboxPreviewSlide {
|
|
7
13
|
/** Slide image URL; a slide without it is dropped, like in the SDK. */
|
|
8
14
|
imageUrl?: string;
|
|
9
15
|
/** Caption overlaid at the bottom of the slide. */
|
|
10
16
|
caption?: string;
|
|
11
17
|
}
|
|
12
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* One localized Inbox content (mirrors the rpc-v2 `AppInboxPresetLocale` shape).
|
|
20
|
+
* @deprecated Use `InboxCellContent` from `@pushwoosh/websdk-common/inbox`.
|
|
21
|
+
*/
|
|
13
22
|
export interface InboxPreviewContent {
|
|
14
23
|
/** Cell title. */
|
|
15
24
|
title?: string;
|
|
@@ -24,7 +33,10 @@ export interface InboxPreviewContent {
|
|
|
24
33
|
/** Carousel slides; only the first five valid ones are rendered. */
|
|
25
34
|
carousel?: InboxPreviewSlide[];
|
|
26
35
|
}
|
|
27
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Platform skin of {@link InboxPreview}: each OS draws the inbox cell differently.
|
|
38
|
+
* @deprecated Use `InboxCellPlatform` from `@pushwoosh/websdk-common/inbox`.
|
|
39
|
+
*/
|
|
28
40
|
export type InboxPreviewPlatform = 'ios' | 'android' | 'web';
|
|
29
41
|
/** Inbox icon geometry of one platform. */
|
|
30
42
|
export interface InboxAvatarShape {
|
|
@@ -49,7 +61,10 @@ export interface InboxCellProps {
|
|
|
49
61
|
/** Draw the unread dot. */
|
|
50
62
|
unread: boolean;
|
|
51
63
|
}
|
|
52
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Props of {@link InboxPreview}.
|
|
66
|
+
* @deprecated Use `InboxCellPreviewProps` from `@pushwoosh/websdk-common/inbox`.
|
|
67
|
+
*/
|
|
53
68
|
export interface InboxPreviewProps {
|
|
54
69
|
/** Platform skin to render (default `ios`); the editor switches it with platform chips. */
|
|
55
70
|
platform?: InboxPreviewPlatform;
|
package/package.json
CHANGED
|
@@ -72,6 +72,35 @@ describe('filters', () => {
|
|
|
72
72
|
expect(filters.pluralize('not a number', [scalar('a'), scalar('b')], createContext())).toBe('not a number');
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
|
+
describe('pluralize with CLDR forms', () => {
|
|
76
|
+
const arabic = ['صفر', 'صف', 'صفان', 'صفوف', 'صفًا', 'صف*'].map(scalar);
|
|
77
|
+
test('picks each of the six Arabic forms', () => {
|
|
78
|
+
const ctx = createContext('ar');
|
|
79
|
+
expect(filters.pluralize(0, arabic, ctx)).toBe('صفر');
|
|
80
|
+
expect(filters.pluralize(1, arabic, ctx)).toBe('صف');
|
|
81
|
+
expect(filters.pluralize(2, arabic, ctx)).toBe('صفان');
|
|
82
|
+
expect(filters.pluralize(3, arabic, ctx)).toBe('صفوف');
|
|
83
|
+
expect(filters.pluralize(10, arabic, ctx)).toBe('صفوف');
|
|
84
|
+
expect(filters.pluralize(11, arabic, ctx)).toBe('صفًا');
|
|
85
|
+
expect(filters.pluralize(99, arabic, ctx)).toBe('صفًا');
|
|
86
|
+
expect(filters.pluralize(100, arabic, ctx)).toBe('صف*');
|
|
87
|
+
expect(filters.pluralize(103, arabic, ctx)).toBe('صفوف');
|
|
88
|
+
});
|
|
89
|
+
test('keeps the legacy one/other split when fewer forms are given', () => {
|
|
90
|
+
const ctx = createContext('ar');
|
|
91
|
+
expect(filters.pluralize(1, [scalar('صف'), scalar('صفوف')], ctx)).toBe('صف');
|
|
92
|
+
expect(filters.pluralize(0, [scalar('صف'), scalar('صفوف')], ctx)).toBe('صفوف');
|
|
93
|
+
expect(filters.pluralize(2, [scalar('صف'), scalar('صفوف')], ctx)).toBe('صفوف');
|
|
94
|
+
});
|
|
95
|
+
test('Russian three-form rule matches CLDR one/few/many for integers', () => {
|
|
96
|
+
const ctx = createContext('ru');
|
|
97
|
+
const forms = [scalar('one'), scalar('few'), scalar('many')];
|
|
98
|
+
const rules = new Intl.PluralRules('ru');
|
|
99
|
+
for (let n = 0; n <= 1000; n += 1) {
|
|
100
|
+
expect(filters.pluralize(n, forms, ctx)).toBe(rules.select(n));
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
75
104
|
describe('formatNumber', () => {
|
|
76
105
|
test('formats integer with spaces', () => {
|
|
77
106
|
expect(filters.formatNumber('1000000', [], createContext())).toBe('1 000 000');
|
|
@@ -15,6 +15,20 @@ const pluralizers = {
|
|
|
15
15
|
de: universalPluralize,
|
|
16
16
|
es: universalPluralize
|
|
17
17
|
};
|
|
18
|
+
const CLDR_CATEGORY_ORDER = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|
19
|
+
const cldrPluralize = (language, num, plurals) => {
|
|
20
|
+
let rules;
|
|
21
|
+
try {
|
|
22
|
+
rules = new Intl.PluralRules(language);
|
|
23
|
+
} catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const categories = CLDR_CATEGORY_ORDER.filter(c => rules.resolvedOptions().pluralCategories.includes(c));
|
|
27
|
+
if (categories.length < 2 || plurals.length < categories.length) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return plurals[categories.indexOf(rules.select(num))];
|
|
31
|
+
};
|
|
18
32
|
export const filters = {
|
|
19
33
|
capitalize: value => typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : value,
|
|
20
34
|
upperCase: value => typeof value === 'string' ? value.toUpperCase() : value,
|
|
@@ -24,6 +38,10 @@ export const filters = {
|
|
|
24
38
|
return value;
|
|
25
39
|
}
|
|
26
40
|
const variants = args.map(arg => unpackScalarOrValue(arg, context));
|
|
41
|
+
const cldr = cldrPluralize(context.language, value, variants);
|
|
42
|
+
if (cldr !== undefined) {
|
|
43
|
+
return cldr;
|
|
44
|
+
}
|
|
27
45
|
const pluralizer = pluralizers[context.language] || universalPluralize;
|
|
28
46
|
return pluralizer(value, variants);
|
|
29
47
|
},
|