@pushwoosh/smart-components-kit 1.9.1 → 1.11.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.
Files changed (53) hide show
  1. package/PickerSort/components/PickerSortMenu/PickerSortMenu.d.ts +4 -0
  2. package/PickerSort/components/PickerSortMenu/PickerSortMenu.js +44 -0
  3. package/PickerSort/components/PickerSortMenu/index.d.ts +1 -0
  4. package/PickerSort/components/PickerSortMenu/index.js +1 -0
  5. package/PickerSort/components/PickerSortMenu/types.d.ts +12 -0
  6. package/PickerSort/components/PickerSortMenu/types.js +1 -0
  7. package/PickerSort/constants.d.ts +6 -0
  8. package/PickerSort/constants.js +5 -0
  9. package/PickerSort/helpers.d.ts +12 -0
  10. package/PickerSort/helpers.js +135 -0
  11. package/PickerSort/index.d.ts +7 -0
  12. package/PickerSort/index.js +5 -0
  13. package/PickerSort/polyglot/index.d.ts +4 -0
  14. package/PickerSort/polyglot/index.js +41 -0
  15. package/PickerSort/polyglot/messages_ar.d.ts +3 -0
  16. package/PickerSort/polyglot/messages_ar.js +8 -0
  17. package/PickerSort/polyglot/messages_bn.d.ts +3 -0
  18. package/PickerSort/polyglot/messages_bn.js +8 -0
  19. package/PickerSort/polyglot/messages_de.d.ts +3 -0
  20. package/PickerSort/polyglot/messages_de.js +8 -0
  21. package/PickerSort/polyglot/messages_en.d.ts +3 -0
  22. package/PickerSort/polyglot/messages_en.js +8 -0
  23. package/PickerSort/polyglot/messages_es.d.ts +3 -0
  24. package/PickerSort/polyglot/messages_es.js +8 -0
  25. package/PickerSort/polyglot/messages_fr.d.ts +3 -0
  26. package/PickerSort/polyglot/messages_fr.js +8 -0
  27. package/PickerSort/polyglot/messages_he.d.ts +3 -0
  28. package/PickerSort/polyglot/messages_he.js +8 -0
  29. package/PickerSort/polyglot/messages_hi.d.ts +3 -0
  30. package/PickerSort/polyglot/messages_hi.js +8 -0
  31. package/PickerSort/polyglot/messages_ja.d.ts +3 -0
  32. package/PickerSort/polyglot/messages_ja.js +8 -0
  33. package/PickerSort/polyglot/messages_ko.d.ts +3 -0
  34. package/PickerSort/polyglot/messages_ko.js +8 -0
  35. package/PickerSort/polyglot/messages_pt.d.ts +3 -0
  36. package/PickerSort/polyglot/messages_pt.js +8 -0
  37. package/PickerSort/polyglot/messages_ru.d.ts +3 -0
  38. package/PickerSort/polyglot/messages_ru.js +8 -0
  39. package/PickerSort/polyglot/messages_th.d.ts +3 -0
  40. package/PickerSort/polyglot/messages_th.js +8 -0
  41. package/PickerSort/polyglot/messages_zh.d.ts +3 -0
  42. package/PickerSort/polyglot/messages_zh.js +8 -0
  43. package/PickerSort/polyglot/types.d.ts +9 -0
  44. package/PickerSort/polyglot/types.js +1 -0
  45. package/PickerSort/types.d.ts +72 -0
  46. package/PickerSort/types.js +1 -0
  47. package/PickerSort/usePagedItems.d.ts +3 -0
  48. package/PickerSort/usePagedItems.js +91 -0
  49. package/PickerSort/usePickerSortOrder.d.ts +3 -0
  50. package/PickerSort/usePickerSortOrder.js +51 -0
  51. package/index.d.ts +1 -0
  52. package/index.js +1 -0
  53. package/package.json +2 -2
@@ -0,0 +1,4 @@
1
+ import { type FC } from 'react';
2
+ import { type PickerSortMenuProps } from './types';
3
+ /** Compact "⇅ <order> ▾" button that lets the user pick the order of a picker list. */
4
+ export declare const PickerSortMenu: FC<PickerSortMenuProps>;
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DropdownMenuButton, DropdownMenuItem, DropdownMenuSection } from '@pushwoosh/dumb-components';
3
+ import { DropdownIcon, SortIcon } from '@pushwoosh/kit-icons';
4
+ import { PICKER_SORT_ORDERS } from '../../constants';
5
+ import { ORDER_MESSAGES, useLang } from '../../polyglot';
6
+ /** Compact "⇅ <order> ▾" button that lets the user pick the order of a picker list. */
7
+ export const PickerSortMenu = ({
8
+ value,
9
+ onChange,
10
+ orders = PICKER_SORT_ORDERS,
11
+ isDisabled
12
+ }) => {
13
+ const lang = useLang();
14
+ return _jsx(DropdownMenuButton, {
15
+ color: "secondary",
16
+ view: "ghost",
17
+ size: "compact",
18
+ icon: _jsx(SortIcon, {
19
+ size: "small",
20
+ type: "not-sorted"
21
+ }),
22
+ rightIcon: _jsx(DropdownIcon, {
23
+ direction: "down",
24
+ size: "small"
25
+ }),
26
+ label: lang({
27
+ message: ORDER_MESSAGES[value]
28
+ }),
29
+ isDisabled: isDisabled,
30
+ menuPlacement: "bottom-end",
31
+ children: _jsx(DropdownMenuSection, {
32
+ title: lang({
33
+ message: 'SMART.PICKER_SORT.TITLE'
34
+ }),
35
+ children: orders.map(order => _jsx(DropdownMenuItem, {
36
+ isActive: order === value,
37
+ onClick: () => onChange(order),
38
+ children: lang({
39
+ message: ORDER_MESSAGES[order]
40
+ })
41
+ }, order))
42
+ })
43
+ });
44
+ };
@@ -0,0 +1 @@
1
+ export { PickerSortMenu } from './PickerSortMenu';
@@ -0,0 +1 @@
1
+ export { PickerSortMenu } from './PickerSortMenu';
@@ -0,0 +1,12 @@
1
+ import { type PickerSortOrder } from '../../types';
2
+ /** Props of {@link PickerSortMenu}. */
3
+ export type PickerSortMenuProps = {
4
+ /** Current order. */
5
+ readonly value: PickerSortOrder;
6
+ /** Fires with the order the user picked. */
7
+ readonly onChange: (order: PickerSortOrder) => void;
8
+ /** Orders to offer; defaults to all of them. */
9
+ readonly orders?: readonly PickerSortOrder[];
10
+ /** Disable the trigger. */
11
+ readonly isDisabled?: boolean;
12
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { type PickerSortOrder } from './types';
2
+ /** Every order a picker may offer, in menu order. */
3
+ export declare const PICKER_SORT_ORDERS: readonly PickerSortOrder[];
4
+ /** Orders `popupFormsContents.List` can serve; it has no created date. */
5
+ export declare const POPUP_CONTENTS_SORT_ORDERS: readonly PickerSortOrder[];
6
+ export declare const PICKER_SORT_STORAGE_PREFIX = "picker-sort";
@@ -0,0 +1,5 @@
1
+ /** Every order a picker may offer, in menu order. */
2
+ export const PICKER_SORT_ORDERS = ['created-desc', 'created-asc', 'updated-desc', 'name-asc', 'name-desc'];
3
+ /** Orders `popupFormsContents.List` can serve; it has no created date. */
4
+ export const POPUP_CONTENTS_SORT_ORDERS = ['updated-desc', 'name-asc', 'name-desc'];
5
+ export const PICKER_SORT_STORAGE_PREFIX = 'picker-sort';
@@ -0,0 +1,12 @@
1
+ import { type PickerContentType, type PickerSortAccessors, type PickerSortOrder, type PopupContentsListOrder, type PresetListOrder, type RichMediaListOrder } from './types';
2
+ /** Map a picker order to the `orderBy` / `orderDirection` of the preset `List` RPCs. */
3
+ export declare function toPresetListOrder(order: PickerSortOrder): PresetListOrder;
4
+ /** Map a picker order to the `orderBy` / `orderType` of `richMedia.List`. */
5
+ export declare function toRichMediaListOrder(order: PickerSortOrder): RichMediaListOrder;
6
+ /** Map a picker order to `popupFormsContents.List`; created orders, which it lacks, fall back to the updated date. */
7
+ export declare function toPopupContentsListOrder(order: PickerSortOrder): PopupContentsListOrder;
8
+ /** Sort a list the source returns whole, as the picker order asks; stable, returns a new array. */
9
+ export declare function sortItemsByPickerOrder<T>(items: readonly T[], order: PickerSortOrder, { getName, getCreated, getUpdated }: PickerSortAccessors<T>): T[];
10
+ export declare function isPickerSortOrder(value: unknown): value is PickerSortOrder;
11
+ export declare function resolvePickerSortOrder(stored: unknown, defaultOrder: PickerSortOrder, supportedOrders: readonly PickerSortOrder[]): PickerSortOrder;
12
+ export declare function pickerSortStorageKey(userEmail: string, contentType: PickerContentType): string;
@@ -0,0 +1,135 @@
1
+ import { PICKER_SORT_ORDERS, PICKER_SORT_STORAGE_PREFIX } from './constants';
2
+ const PRESET_LIST_ORDERS = {
3
+ 'created-desc': {
4
+ orderBy: 'CREATED',
5
+ orderDirection: 'DESC'
6
+ },
7
+ 'created-asc': {
8
+ orderBy: 'CREATED',
9
+ orderDirection: 'ASC'
10
+ },
11
+ 'updated-desc': {
12
+ orderBy: 'UPDATED',
13
+ orderDirection: 'DESC'
14
+ },
15
+ 'name-asc': {
16
+ orderBy: 'NAME',
17
+ orderDirection: 'ASC'
18
+ },
19
+ 'name-desc': {
20
+ orderBy: 'NAME',
21
+ orderDirection: 'DESC'
22
+ }
23
+ };
24
+ const RICH_MEDIA_LIST_ORDERS = {
25
+ 'created-desc': {
26
+ orderBy: 'CREATED_DATE',
27
+ orderType: 'DESC'
28
+ },
29
+ 'created-asc': {
30
+ orderBy: 'CREATED_DATE',
31
+ orderType: 'ASC'
32
+ },
33
+ 'updated-desc': {
34
+ orderBy: 'UPDATED_DATE',
35
+ orderType: 'DESC'
36
+ },
37
+ 'name-asc': {
38
+ orderBy: 'NAME',
39
+ orderType: 'ASC'
40
+ },
41
+ 'name-desc': {
42
+ orderBy: 'NAME',
43
+ orderType: 'DESC'
44
+ }
45
+ };
46
+ const POPUP_CONTENTS_LIST_ORDERS = {
47
+ 'created-desc': {
48
+ orderBy: 'UPDATED',
49
+ orderDirection: 'DESC'
50
+ },
51
+ 'created-asc': {
52
+ orderBy: 'UPDATED',
53
+ orderDirection: 'ASC'
54
+ },
55
+ 'updated-desc': {
56
+ orderBy: 'UPDATED',
57
+ orderDirection: 'DESC'
58
+ },
59
+ 'name-asc': {
60
+ orderBy: 'NAME',
61
+ orderDirection: 'ASC'
62
+ },
63
+ 'name-desc': {
64
+ orderBy: 'NAME',
65
+ orderDirection: 'DESC'
66
+ }
67
+ };
68
+ const nameCollator = new Intl.Collator(undefined, {
69
+ numeric: true,
70
+ sensitivity: 'base'
71
+ });
72
+ /** Map a picker order to the `orderBy` / `orderDirection` of the preset `List` RPCs. */
73
+ export function toPresetListOrder(order) {
74
+ return PRESET_LIST_ORDERS[order];
75
+ }
76
+ /** Map a picker order to the `orderBy` / `orderType` of `richMedia.List`. */
77
+ export function toRichMediaListOrder(order) {
78
+ return RICH_MEDIA_LIST_ORDERS[order];
79
+ }
80
+ /** Map a picker order to `popupFormsContents.List`; created orders, which it lacks, fall back to the updated date. */
81
+ export function toPopupContentsListOrder(order) {
82
+ return POPUP_CONTENTS_LIST_ORDERS[order];
83
+ }
84
+ function toTime(date) {
85
+ if (date === null || date === undefined || date === '') {
86
+ return undefined;
87
+ }
88
+ const time = date instanceof Date ? date.getTime() : new Date(date).getTime();
89
+ return Number.isNaN(time) ? undefined : time;
90
+ }
91
+ function sortByDate(items, getDate, direction) {
92
+ if (!getDate) {
93
+ return [...items];
94
+ }
95
+ const dated = items.map(item => ({
96
+ item,
97
+ time: toTime(getDate(item))
98
+ }));
99
+ return dated.sort((a, b) => {
100
+ if (a.time === undefined || b.time === undefined) {
101
+ return Number(a.time === undefined) - Number(b.time === undefined);
102
+ }
103
+ return (a.time - b.time) * direction;
104
+ }).map(({
105
+ item
106
+ }) => item);
107
+ }
108
+ /** Sort a list the source returns whole, as the picker order asks; stable, returns a new array. */
109
+ export function sortItemsByPickerOrder(items, order, {
110
+ getName,
111
+ getCreated,
112
+ getUpdated
113
+ }) {
114
+ switch (order) {
115
+ case 'name-asc':
116
+ return [...items].sort((a, b) => nameCollator.compare(getName(a), getName(b)));
117
+ case 'name-desc':
118
+ return [...items].sort((a, b) => nameCollator.compare(getName(b), getName(a)));
119
+ case 'created-desc':
120
+ return sortByDate(items, getCreated, -1);
121
+ case 'created-asc':
122
+ return sortByDate(items, getCreated, 1);
123
+ case 'updated-desc':
124
+ return sortByDate(items, getUpdated, -1);
125
+ }
126
+ }
127
+ export function isPickerSortOrder(value) {
128
+ return typeof value === 'string' && PICKER_SORT_ORDERS.includes(value);
129
+ }
130
+ export function resolvePickerSortOrder(stored, defaultOrder, supportedOrders) {
131
+ return isPickerSortOrder(stored) && supportedOrders.includes(stored) ? stored : defaultOrder;
132
+ }
133
+ export function pickerSortStorageKey(userEmail, contentType) {
134
+ return `${PICKER_SORT_STORAGE_PREFIX}:${userEmail}:${contentType}`;
135
+ }
@@ -0,0 +1,7 @@
1
+ export { PickerSortMenu } from './components/PickerSortMenu';
2
+ export { PICKER_SORT_ORDERS, POPUP_CONTENTS_SORT_ORDERS } from './constants';
3
+ export { sortItemsByPickerOrder, toPopupContentsListOrder, toPresetListOrder, toRichMediaListOrder } from './helpers';
4
+ export { usePagedItems } from './usePagedItems';
5
+ export { usePickerSortOrder } from './usePickerSortOrder';
6
+ export type { PickerSortMenuProps } from './components/PickerSortMenu/types';
7
+ export type { LoadPagedItems, PagedItemsPage, PagedItemsState, PickerContentType, PickerSortAccessors, PickerSortDate, PickerSortOrder, PickerSortOrderState, PopupContentsListOrder, PresetListOrder, RichMediaListOrder, RichMediaListOrderBy, UsePickerSortOrderOptions, } from './types';
@@ -0,0 +1,5 @@
1
+ export { PickerSortMenu } from './components/PickerSortMenu';
2
+ export { PICKER_SORT_ORDERS, POPUP_CONTENTS_SORT_ORDERS } from './constants';
3
+ export { sortItemsByPickerOrder, toPopupContentsListOrder, toPresetListOrder, toRichMediaListOrder } from './helpers';
4
+ export { usePagedItems } from './usePagedItems';
5
+ export { usePickerSortOrder } from './usePickerSortOrder';
@@ -0,0 +1,4 @@
1
+ import { type PickerSortOrder } from '../types';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const Lang: import("react").FC<import("@pushwoosh/dumb-components/polyglot").LangProps<PickerSortMessages>>, useLang: () => (props: import("@pushwoosh/dumb-components/polyglot").LangProps<PickerSortMessages>) => string;
4
+ export declare const ORDER_MESSAGES: Record<PickerSortOrder, keyof PickerSortMessages>;
@@ -0,0 +1,41 @@
1
+ import { createLang } from '@pushwoosh/dumb-components/polyglot';
2
+ import { messages as ar } from './messages_ar';
3
+ import { messages as bn } from './messages_bn';
4
+ import { messages as de } from './messages_de';
5
+ import { messages as en } from './messages_en';
6
+ import { messages as es } from './messages_es';
7
+ import { messages as fr } from './messages_fr';
8
+ import { messages as he } from './messages_he';
9
+ import { messages as hi } from './messages_hi';
10
+ import { messages as ja } from './messages_ja';
11
+ import { messages as ko } from './messages_ko';
12
+ import { messages as pt } from './messages_pt';
13
+ import { messages as ru } from './messages_ru';
14
+ import { messages as th } from './messages_th';
15
+ import { messages as zh } from './messages_zh';
16
+ export const {
17
+ Lang,
18
+ useLang
19
+ } = createLang({
20
+ ar,
21
+ bn,
22
+ de,
23
+ en,
24
+ es,
25
+ fr,
26
+ he,
27
+ hi,
28
+ ja,
29
+ ko,
30
+ pt,
31
+ ru,
32
+ th,
33
+ zh
34
+ });
35
+ export const ORDER_MESSAGES = {
36
+ 'created-desc': 'SMART.PICKER_SORT.ORDER.CREATED_DESC',
37
+ 'created-asc': 'SMART.PICKER_SORT.ORDER.CREATED_ASC',
38
+ 'updated-desc': 'SMART.PICKER_SORT.ORDER.UPDATED_DESC',
39
+ 'name-asc': 'SMART.PICKER_SORT.ORDER.NAME_ASC',
40
+ 'name-desc': 'SMART.PICKER_SORT.ORDER.NAME_DESC'
41
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'ترتيب حسب',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'الأحدث أولاً',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'الأقدم أولاً',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'المحدّثة مؤخرًا',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'الاسم أ→ي',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'الاسم ي→أ'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'সাজান',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'নতুন আগে',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'পুরনো আগে',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'সম্প্রতি আপডেট করা',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'নাম A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'নাম Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Sortieren nach',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Neueste zuerst',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Älteste zuerst',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Zuletzt aktualisiert',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Name A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Name Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Sort by',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Newest first',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Oldest first',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Recently updated',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Name A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Name Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Ordenar por',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Más recientes primero',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Más antiguos primero',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Actualizados recientemente',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Nombre A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Nombre Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Trier par',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Plus récents d’abord',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Plus anciens d’abord',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Modifiés récemment',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Nom A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Nom Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'מיון לפי',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'החדשים קודם',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'הישנים קודם',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'עודכנו לאחרונה',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'שם א→ת',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'שם ת→א'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'क्रमबद्ध करें',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'नए पहले',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'पुराने पहले',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'हाल ही में अपडेट किए गए',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'नाम A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'नाम Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': '並べ替え',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': '新しい順',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': '古い順',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': '最近更新した順',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': '名前 A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': '名前 Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': '정렬',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': '최신순',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': '오래된순',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': '최근 업데이트순',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': '이름 A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': '이름 Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Ordenar por',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Mais recentes primeiro',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Mais antigos primeiro',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Atualizados recentemente',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Nome A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Nome Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'Сортировка',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'Сначала новые',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'Сначала старые',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'Недавно изменённые',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'Название А→Я',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'Название Я→А'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': 'เรียงตาม',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': 'ใหม่สุดก่อน',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': 'เก่าสุดก่อน',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': 'อัปเดตล่าสุด',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': 'ชื่อ A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': 'ชื่อ Z→A'
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { LangMessages } from '@pushwoosh/dumb-components/polyglot';
2
+ import { type PickerSortMessages } from './types';
3
+ export declare const messages: LangMessages<PickerSortMessages>;
@@ -0,0 +1,8 @@
1
+ export const messages = {
2
+ 'SMART.PICKER_SORT.TITLE': '排序方式',
3
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': '最新优先',
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': '最早优先',
5
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': '最近更新',
6
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': '名称 A→Z',
7
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': '名称 Z→A'
8
+ };
@@ -0,0 +1,9 @@
1
+ import type { NoParams } from '@pushwoosh/dumb-components/polyglot';
2
+ export type PickerSortMessages = {
3
+ 'SMART.PICKER_SORT.TITLE': NoParams;
4
+ 'SMART.PICKER_SORT.ORDER.CREATED_DESC': NoParams;
5
+ 'SMART.PICKER_SORT.ORDER.CREATED_ASC': NoParams;
6
+ 'SMART.PICKER_SORT.ORDER.UPDATED_DESC': NoParams;
7
+ 'SMART.PICKER_SORT.ORDER.NAME_ASC': NoParams;
8
+ 'SMART.PICKER_SORT.ORDER.NAME_DESC': NoParams;
9
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
1
+ import { type ListPresetsRequest_OrderBy, type ListPresetsRequest_OrderDirection } from '@pushwoosh/rpc-v2-http-api-data/presets';
2
+ import { type ListRequest_OrderBy as PopupContentsListRequestOrderBy, type ListRequest_OrderDirection as PopupContentsListRequestOrderDirection } from '@pushwoosh/rpc-v2-http-api-data/pushwoosh_rpc_popup_forms_contents_v3';
3
+ import { type ListRequest_OrderType as RichMediaListRequestOrderType } from '@pushwoosh/rpc-v2-http-api-data/rich_medias';
4
+ /** Order a picker can list its items in. */
5
+ export type PickerSortOrder = 'created-desc' | 'created-asc' | 'updated-desc' | 'name-asc' | 'name-desc';
6
+ /** Content kind a picker lists; the chosen order is remembered per user and per kind. */
7
+ export type PickerContentType = 'push' | 'sms' | 'email' | 'line' | 'kakao' | 'inbox' | 'whatsapp' | 'viber' | 'richmedia' | 'popup';
8
+ /** `orderBy` / `orderDirection` pair of `presets.List`; `smsPresets`, `linePresets`, `kakaoPresets` and `appInboxPresets` share the same enums. */
9
+ export type PresetListOrder = {
10
+ readonly orderBy: ListPresetsRequest_OrderBy;
11
+ readonly orderDirection: ListPresetsRequest_OrderDirection;
12
+ };
13
+ /** `orderBy` of `richMedia.List`; local until `NAME` reaches the published rpc-v2 types. */
14
+ export type RichMediaListOrderBy = 'CREATED_DATE' | 'UPDATED_DATE' | 'NAME';
15
+ /** `orderBy` / `orderType` pair of `richMedia.List`. */
16
+ export type RichMediaListOrder = {
17
+ readonly orderBy: RichMediaListOrderBy;
18
+ readonly orderType: RichMediaListRequestOrderType;
19
+ };
20
+ /** `orderBy` / `orderDirection` pair of `popupFormsContents.List`. */
21
+ export type PopupContentsListOrder = {
22
+ readonly orderBy: PopupContentsListRequestOrderBy;
23
+ readonly orderDirection: PopupContentsListRequestOrderDirection;
24
+ };
25
+ /** Date accepted by {@link sortItemsByPickerOrder}; an unparsable or missing one counts as no date. */
26
+ export type PickerSortDate = Date | string | number | null | undefined;
27
+ /** Getters {@link sortItemsByPickerOrder} reads; a date order without its getter keeps the input order. */
28
+ export type PickerSortAccessors<T> = {
29
+ readonly getName: (item: T) => string;
30
+ readonly getCreated?: (item: T) => PickerSortDate;
31
+ readonly getUpdated?: (item: T) => PickerSortDate;
32
+ };
33
+ /** Options of {@link usePickerSortOrder}. */
34
+ export type UsePickerSortOrderOptions = {
35
+ /** Content kind the picker lists. */
36
+ readonly contentType: PickerContentType;
37
+ /** Order shown until the user picks one, and whenever the stored one is not supported here. */
38
+ readonly defaultOrder: PickerSortOrder;
39
+ /** Orders this picker can request; defaults to all of them. */
40
+ readonly supportedOrders?: readonly PickerSortOrder[];
41
+ };
42
+ /** Result of {@link usePickerSortOrder}. */
43
+ export type PickerSortOrderState = {
44
+ /** Order to request. */
45
+ readonly order: PickerSortOrder;
46
+ /** Remember a new order for this user and content kind. */
47
+ readonly setOrder: (order: PickerSortOrder) => void;
48
+ /** `false` until the stored choice is read; load the first page only after that to avoid a double request. */
49
+ readonly isReady: boolean;
50
+ };
51
+ /** One page returned by a {@link usePagedItems} loader. */
52
+ export type PagedItemsPage<T> = {
53
+ /** Items of the requested page. */
54
+ readonly items: T[];
55
+ /** Whether a next page exists. */
56
+ readonly hasMore: boolean;
57
+ };
58
+ /** Loads one zero-based page. */
59
+ export type LoadPagedItems<T> = (page: number) => Promise<PagedItemsPage<T>>;
60
+ /** Result of {@link usePagedItems}. */
61
+ export type PagedItemsState<T> = {
62
+ /** Items of all pages loaded so far. */
63
+ readonly items: T[];
64
+ /** A page is being loaded. */
65
+ readonly isLoading: boolean;
66
+ /** A next page exists. */
67
+ readonly hasMore: boolean;
68
+ /** The last page request failed; `loadMore` retries it. */
69
+ readonly isError: boolean;
70
+ /** Load the next page; no-op while loading or when there is nothing more. Wire it to `onMenuScrollToBottom`. */
71
+ readonly loadMore: () => void;
72
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { type LoadPagedItems, type PagedItemsState } from './types';
2
+ /** Accumulates pages of a server-sorted list for infinite scroll; a new `resetKey` restarts from page 0. */
3
+ export declare function usePagedItems<T>(loadPage: LoadPagedItems<T>, resetKey: string, enabled?: boolean): PagedItemsState<T>;
@@ -0,0 +1,91 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { usePersistentFunction } from '@pushwoosh/kit-helpers';
3
+ /** Accumulates pages of a server-sorted list for infinite scroll; a new `resetKey` restarts from page 0. */
4
+ export function usePagedItems(loadPage, resetKey, enabled = true) {
5
+ const [state, setState] = useState({
6
+ items: [],
7
+ hasMore: true,
8
+ isLoading: enabled,
9
+ isError: false
10
+ });
11
+ const load = usePersistentFunction(loadPage);
12
+ const runRef = useRef(0);
13
+ const cursorRef = useRef({
14
+ next: 0,
15
+ hasMore: true,
16
+ isFetching: false
17
+ });
18
+ const fetchPage = useCallback(page => {
19
+ const run = runRef.current;
20
+ cursorRef.current.isFetching = true;
21
+ setState(prev => ({
22
+ ...prev,
23
+ isLoading: true,
24
+ isError: false
25
+ }));
26
+ load(page).then(({
27
+ items,
28
+ hasMore
29
+ }) => {
30
+ if (run !== runRef.current) {
31
+ return;
32
+ }
33
+ cursorRef.current = {
34
+ next: page + 1,
35
+ hasMore,
36
+ isFetching: false
37
+ };
38
+ setState(prev => ({
39
+ items: page === 0 ? items : [...prev.items, ...items],
40
+ hasMore,
41
+ isLoading: false,
42
+ isError: false
43
+ }));
44
+ }).catch(() => {
45
+ if (run === runRef.current) {
46
+ cursorRef.current.isFetching = false;
47
+ setState(prev => ({
48
+ ...prev,
49
+ isLoading: false,
50
+ isError: true
51
+ }));
52
+ }
53
+ });
54
+ }, [load]);
55
+ useEffect(() => {
56
+ cursorRef.current = {
57
+ next: 0,
58
+ hasMore: true,
59
+ isFetching: false
60
+ };
61
+ setState({
62
+ items: [],
63
+ hasMore: true,
64
+ isLoading: enabled,
65
+ isError: false
66
+ });
67
+ if (enabled) {
68
+ fetchPage(0);
69
+ }
70
+ return () => {
71
+ runRef.current += 1;
72
+ };
73
+ }, [resetKey, enabled, fetchPage]);
74
+ const loadMore = useCallback(() => {
75
+ const {
76
+ next,
77
+ hasMore,
78
+ isFetching
79
+ } = cursorRef.current;
80
+ if (enabled && hasMore && !isFetching) {
81
+ fetchPage(next);
82
+ }
83
+ }, [enabled, fetchPage]);
84
+ return {
85
+ items: state.items,
86
+ isLoading: state.isLoading,
87
+ hasMore: state.hasMore,
88
+ isError: state.isError,
89
+ loadMore
90
+ };
91
+ }
@@ -0,0 +1,3 @@
1
+ import { type PickerSortOrderState, type UsePickerSortOrderOptions } from './types';
2
+ /** Order the user chose for pickers of one content kind, kept in the shell key-value storage. */
3
+ export declare function usePickerSortOrder({ contentType, defaultOrder, supportedOrders, }: UsePickerSortOrderOptions): PickerSortOrderState;
@@ -0,0 +1,51 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useSession, useSPAContext } from '@pushwoosh/spa-context';
3
+ import { PICKER_SORT_ORDERS } from './constants';
4
+ import { pickerSortStorageKey, resolvePickerSortOrder } from './helpers';
5
+ /** Order the user chose for pickers of one content kind, kept in the shell key-value storage. */
6
+ export function usePickerSortOrder({
7
+ contentType,
8
+ defaultOrder,
9
+ supportedOrders = PICKER_SORT_ORDERS
10
+ }) {
11
+ const {
12
+ keyValueStorage
13
+ } = useSPAContext();
14
+ const {
15
+ user
16
+ } = useSession();
17
+ const storageKey = pickerSortStorageKey(user.email, contentType);
18
+ const [stored, setStored] = useState(null);
19
+ useEffect(() => {
20
+ let isActive = true;
21
+ let isChanged = false;
22
+ const unsubscribe = keyValueStorage.subscribe(storageKey, change => {
23
+ isChanged = true;
24
+ setStored({
25
+ key: storageKey,
26
+ value: change.value
27
+ });
28
+ });
29
+ keyValueStorage.get(storageKey).catch(() => undefined).then(value => {
30
+ if (isActive && !isChanged) {
31
+ setStored({
32
+ key: storageKey,
33
+ value
34
+ });
35
+ }
36
+ });
37
+ return () => {
38
+ isActive = false;
39
+ unsubscribe();
40
+ };
41
+ }, [keyValueStorage, storageKey]);
42
+ const setOrder = useCallback(order => {
43
+ keyValueStorage.set(storageKey, order).catch(() => undefined);
44
+ }, [keyValueStorage, storageKey]);
45
+ const isReady = stored?.key === storageKey;
46
+ return {
47
+ order: resolvePickerSortOrder(isReady ? stored.value : undefined, defaultOrder, supportedOrders),
48
+ setOrder,
49
+ isReady
50
+ };
51
+ }
package/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export * from './ResendModal';
15
15
  export * from './RichMessageEditorSmart';
16
16
  export * from './Table';
17
17
  export * from './OpenActions';
18
+ export * from './PickerSort';
18
19
  export * from './SystemParcel';
19
20
  export * from './ModalCloningJourney';
20
21
  export * from './types';
package/index.js CHANGED
@@ -15,6 +15,7 @@ export * from './ResendModal';
15
15
  export * from './RichMessageEditorSmart';
16
16
  export * from './Table';
17
17
  export * from './OpenActions';
18
+ export * from './PickerSort';
18
19
  export * from './SystemParcel';
19
20
  export * from './ModalCloningJourney';
20
21
  export * from './types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/smart-components-kit",
3
- "version": "1.9.1",
3
+ "version": "1.11.0",
4
4
  "description": "Stateful, data-connected React components shared by Pushwoosh micro-frontends",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@floating-ui/react-dom": "^2.1.2",
20
- "@pushwoosh/dumb-components": "^2.11.3",
20
+ "@pushwoosh/dumb-components": "^2.11.4",
21
21
  "@pushwoosh/kit-constants": "^2.1.1",
22
22
  "@pushwoosh/kit-helpers": "^4.14.0",
23
23
  "@pushwoosh/kit-icons": "^2.3.10",