@pallasoft/ps-mobile-components 1.12.0 → 1.13.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/components/ps-action-sheet/ps-action-sheet.js +18 -2
- package/dist/components/ps-barcode-scanner-sheet/ps-barcode-scanner-sheet.js +2 -1
- package/dist/components/ps-document-viewer/ps-document-viewer.js +2 -1
- package/dist/components/ps-document-zoom-image/ps-document-zoom-image.js +10 -0
- package/dist/components/ps-infinite-list/ps-infinite-list-props.d.ts +2 -0
- package/dist/components/ps-infinite-list/ps-infinite-list.d.ts +1 -1
- package/dist/components/ps-infinite-list/ps-infinite-list.js +12 -5
- package/dist/components/ps-list/ps-list-props.d.ts +2 -0
- package/dist/components/ps-list/ps-list.d.ts +1 -1
- package/dist/components/ps-list/ps-list.js +1 -1
- package/dist/components/ps-menu-popup/ps-menu-popup.js +3 -2
- package/dist/components/ps-screen/ps-screen-props.d.ts +2 -0
- package/dist/components/ps-screen/ps-screen.d.ts +1 -1
- package/dist/components/ps-screen/ps-screen.js +12 -5
- package/dist/components/ps-sheet-content/ps-sheet-content.js +4 -2
- package/dist/components/ps-sheet-presenter/ps-sheet-presenter.ios.js +15 -5
- package/dist/components/ps-sheet-presenter/ps-sheet-presenter.js +16 -3
- package/dist/components/ps-sortable-grid/ps-sortable-grid.js +4 -1
- package/dist/components/ps-widget-list/ps-widget-grid.js +16 -7
- package/dist/components/ps-widget-list/ps-widget-list-props.d.ts +2 -0
- package/dist/components/ps-widget-list/ps-widget-list.d.ts +1 -1
- package/dist/components/ps-widget-list/ps-widget-list.js +12 -5
- package/dist/constants/ps-content-width.d.ts +6 -0
- package/dist/constants/ps-content-width.js +5 -0
- package/dist/constants/ps-document-search-config.d.ts +0 -3
- package/dist/constants/ps-document-search-config.js +0 -3
- package/dist/constants/ps-layout-class-config.d.ts +12 -0
- package/dist/constants/ps-layout-class-config.js +12 -0
- package/dist/constants/ps-layout-class.d.ts +5 -0
- package/dist/constants/ps-layout-class.js +4 -0
- package/dist/constants/ps-menu-popup-config.d.ts +1 -0
- package/dist/constants/ps-menu-popup-config.js +1 -0
- package/dist/constants/ps-orientation-config.d.ts +3 -0
- package/dist/constants/ps-orientation-config.js +3 -0
- package/dist/constants/ps-sheet-config.d.ts +1 -0
- package/dist/constants/ps-sheet-config.js +1 -0
- package/dist/constants/ps-sortable-grid-config.d.ts +2 -0
- package/dist/constants/ps-sortable-grid-config.js +2 -0
- package/dist/hooks/use-ps-layout-class.d.ts +2 -0
- package/dist/hooks/use-ps-layout-class.js +6 -0
- package/dist/hooks/use-ps-menu-anchor.d.ts +1 -1
- package/dist/hooks/use-ps-menu-anchor.js +14 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/interfaces/ps-document-search-match.d.ts +2 -4
- package/dist/interfaces/ps-document-text-box.d.ts +2 -6
- package/dist/interfaces/ps-document-text-layer-word.d.ts +2 -5
- package/dist/interfaces/ps-document-text-layer.d.ts +2 -6
- package/dist/interfaces/ps-document-text-segment.d.ts +2 -4
- package/dist/interfaces/ps-menu-popup-insets.d.ts +2 -0
- package/dist/interfaces/ps-menu-popup-layout.d.ts +1 -0
- package/dist/services/ps-document-search-service.d.ts +0 -4
- package/dist/services/ps-document-search-service.js +9 -96
- package/dist/services/ps-layout-service.d.ts +12 -0
- package/dist/services/ps-layout-service.js +41 -0
- package/dist/services/ps-menu-popup-service.js +8 -4
- package/dist/services/ps-sheet-service.d.ts +5 -2
- package/dist/services/ps-sheet-service.js +17 -4
- package/dist/services/ps-sortable-grid-service.d.ts +3 -2
- package/dist/services/ps-sortable-grid-service.js +26 -22
- package/package.json +2 -2
- package/dist/interfaces/ps-document-normalized-text.d.ts +0 -5
- package/dist/interfaces/ps-document-normalized-text.js +0 -1
|
@@ -2,6 +2,7 @@ export declare const PsSheetConfig: {
|
|
|
2
2
|
readonly actionMinWidth: 44;
|
|
3
3
|
readonly actionSpinnerGap: 6;
|
|
4
4
|
readonly cornerRadius: 20;
|
|
5
|
+
readonly formSizingMinIos: 18;
|
|
5
6
|
readonly headerMinHeight: 64;
|
|
6
7
|
readonly headerPaddingBottom: 12;
|
|
7
8
|
readonly headerPaddingHorizontal: 16;
|
|
@@ -2,7 +2,9 @@ export declare const PsSortableGridConfig: {
|
|
|
2
2
|
readonly activeScale: 1.03;
|
|
3
3
|
readonly activeZIndex: 10;
|
|
4
4
|
readonly columnGap: 12;
|
|
5
|
+
readonly compactUnits: 2;
|
|
5
6
|
readonly edgeRatio: 0.14;
|
|
7
|
+
readonly fullUnits: 2;
|
|
6
8
|
readonly holdTolerance: 8;
|
|
7
9
|
readonly longPressMs: 400;
|
|
8
10
|
readonly maxScrollStep: 18;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ElementRef, type RefObject } from 'react';
|
|
2
|
-
import type
|
|
2
|
+
import { type View } from 'react-native';
|
|
3
3
|
import type { PsMenuAnchor } from '../interfaces/ps-menu-anchor';
|
|
4
4
|
export interface PsMenuAnchorResult {
|
|
5
5
|
anchor: PsMenuAnchor | undefined;
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import { useRef, useState } from 'react';
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useWindowDimensions } from 'react-native';
|
|
3
|
+
import { PsMenuPopupConfig } from '../constants/ps-menu-popup-config';
|
|
2
4
|
export const usePsMenuAnchor = () => {
|
|
3
5
|
const ref = useRef(null);
|
|
4
6
|
const [anchor, setAnchor] = useState(undefined);
|
|
7
|
+
const { height, width } = useWindowDimensions();
|
|
8
|
+
const isOpen = anchor !== undefined;
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!isOpen)
|
|
11
|
+
return;
|
|
12
|
+
const timer = setTimeout(() => {
|
|
13
|
+
ref.current?.measureInWindow((x, y, anchorWidth, anchorHeight) => setAnchor({ height: anchorHeight, width: anchorWidth, x, y }));
|
|
14
|
+
}, PsMenuPopupConfig.remeasureMs);
|
|
15
|
+
return () => clearTimeout(timer);
|
|
16
|
+
}, [height, isOpen, width]);
|
|
5
17
|
return {
|
|
6
18
|
anchor,
|
|
7
19
|
close: () => setAnchor(undefined),
|
|
8
20
|
open: () => {
|
|
9
|
-
ref.current?.measureInWindow((x, y,
|
|
21
|
+
ref.current?.measureInWindow((x, y, anchorWidth, anchorHeight) => setAnchor({ height: anchorHeight, width: anchorWidth, x, y }));
|
|
10
22
|
},
|
|
11
23
|
ref,
|
|
12
24
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -194,3 +194,7 @@ export * from './interfaces/ps-infinite-data-result';
|
|
|
194
194
|
export * from './interfaces/ps-infinite-data-update';
|
|
195
195
|
export * from './interfaces/ps-infinite-page';
|
|
196
196
|
export { usePsDebouncedValue } from '@pallasoft/ps-utilities/react';
|
|
197
|
+
export * from './constants/ps-layout-class';
|
|
198
|
+
export * from './constants/ps-content-width';
|
|
199
|
+
export * from './hooks/use-ps-layout-class';
|
|
200
|
+
export { PsLayoutService } from './services/ps-layout-service';
|
package/dist/index.js
CHANGED
|
@@ -189,3 +189,7 @@ export * from './interfaces/ps-infinite-data-result';
|
|
|
189
189
|
export * from './interfaces/ps-infinite-data-update';
|
|
190
190
|
export * from './interfaces/ps-infinite-page';
|
|
191
191
|
export { usePsDebouncedValue } from '@pallasoft/ps-utilities/react';
|
|
192
|
+
export * from './constants/ps-layout-class';
|
|
193
|
+
export * from './constants/ps-content-width';
|
|
194
|
+
export * from './hooks/use-ps-layout-class';
|
|
195
|
+
export { PsLayoutService } from './services/ps-layout-service';
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
3
|
-
box: PsDocumentTextBox;
|
|
4
|
-
text: string;
|
|
5
|
-
}
|
|
1
|
+
import type { TextLayerWord } from '@pallasoft/ps-utilities';
|
|
2
|
+
export type PsDocumentTextLayerWord = TextLayerWord;
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
3
|
-
height: number;
|
|
4
|
-
width: number;
|
|
5
|
-
words: PsDocumentTextLayerWord[];
|
|
6
|
-
}
|
|
1
|
+
import type { TextLayer } from '@pallasoft/ps-utilities';
|
|
2
|
+
export type PsDocumentTextLayer = TextLayer;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PsDocumentHighlightRect } from '../interfaces/ps-document-highlight-rect';
|
|
2
2
|
import type { PsDocumentItem } from '../interfaces/ps-document-item';
|
|
3
3
|
import type { PsDocumentLabels } from '../interfaces/ps-document-labels';
|
|
4
|
-
import type { PsDocumentNormalizedText } from '../interfaces/ps-document-normalized-text';
|
|
5
4
|
import type { PsDocumentPoint } from '../interfaces/ps-document-point';
|
|
6
5
|
import type { PsDocumentSearchLabels } from '../interfaces/ps-document-search-labels';
|
|
7
6
|
import type { PsDocumentSearchLocation } from '../interfaces/ps-document-search-location';
|
|
@@ -14,11 +13,9 @@ import type { PsDocumentViewerEntry } from '../interfaces/ps-document-viewer-ent
|
|
|
14
13
|
import type { PsDocumentWordMatch } from '../interfaces/ps-document-word-match';
|
|
15
14
|
import type { PsSize } from '../interfaces/ps-size';
|
|
16
15
|
export declare class PsDocumentSearchService {
|
|
17
|
-
static normalize(text: string): PsDocumentNormalizedText;
|
|
18
16
|
static terms(query: string): string[];
|
|
19
17
|
static matches(text: string, query: string): PsDocumentSearchMatch[];
|
|
20
18
|
static segments(text: string, matches: PsDocumentSearchMatch[]): PsDocumentTextSegment[];
|
|
21
|
-
static joinedWords(layer: PsDocumentTextLayer): string;
|
|
22
19
|
static wordMatches(layer: PsDocumentTextLayer, query: string): PsDocumentWordMatch[];
|
|
23
20
|
static fit(layer: PsDocumentTextLayer, container: PsSize): PsDocumentTextBox;
|
|
24
21
|
static rect(box: PsDocumentTextBox, layer: PsDocumentTextLayer, container: PsSize): PsDocumentTextBox;
|
|
@@ -36,5 +33,4 @@ export declare class PsDocumentSearchService {
|
|
|
36
33
|
static countLabel(template: string, current: number, total: number): string;
|
|
37
34
|
static labels(labels: PsDocumentLabels): PsDocumentSearchLabels | null;
|
|
38
35
|
static isSearchable(items: PsDocumentItem[]): boolean;
|
|
39
|
-
private static merge;
|
|
40
36
|
}
|
|
@@ -1,104 +1,29 @@
|
|
|
1
|
+
import { Common } from '@pallasoft/ps-utilities';
|
|
1
2
|
import { PsDocumentKind } from '../constants/ps-document-kind';
|
|
2
3
|
import { PsDocumentSearchConfig } from '../constants/ps-document-search-config';
|
|
3
4
|
export class PsDocumentSearchService {
|
|
4
|
-
static normalize(text) {
|
|
5
|
-
const starts = [];
|
|
6
|
-
const ends = [];
|
|
7
|
-
let value = '';
|
|
8
|
-
let offset = 0;
|
|
9
|
-
for (const character of Array.from(text)) {
|
|
10
|
-
const folded = character
|
|
11
|
-
.normalize('NFD')
|
|
12
|
-
.replace(PsDocumentSearchConfig.combiningMarkPattern, '')
|
|
13
|
-
.toLowerCase();
|
|
14
|
-
for (let position = 0; position < folded.length; position += 1) {
|
|
15
|
-
starts.push(offset);
|
|
16
|
-
ends.push(offset + character.length);
|
|
17
|
-
}
|
|
18
|
-
value += folded;
|
|
19
|
-
offset += character.length;
|
|
20
|
-
}
|
|
21
|
-
return { ends, starts, value };
|
|
22
|
-
}
|
|
23
5
|
static terms(query) {
|
|
24
|
-
return
|
|
25
|
-
.value.split(PsDocumentSearchConfig.termSeparatorPattern)
|
|
26
|
-
.filter((term) => term !== '');
|
|
6
|
+
return Common.TextSearchService.terms(query);
|
|
27
7
|
}
|
|
28
8
|
static matches(text, query) {
|
|
29
|
-
|
|
30
|
-
if (terms.length === 0)
|
|
31
|
-
return [];
|
|
32
|
-
const normalized = PsDocumentSearchService.normalize(text);
|
|
33
|
-
const ranges = [];
|
|
34
|
-
for (const term of terms) {
|
|
35
|
-
let from = normalized.value.indexOf(term);
|
|
36
|
-
while (from >= 0) {
|
|
37
|
-
ranges.push({ end: from + term.length, start: from });
|
|
38
|
-
from = normalized.value.indexOf(term, from + term.length);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return PsDocumentSearchService.merge(ranges).map((range) => ({
|
|
42
|
-
end: normalized.ends[range.end - 1],
|
|
43
|
-
start: normalized.starts[range.start],
|
|
44
|
-
}));
|
|
9
|
+
return Common.TextSearchService.findTerms(text, query);
|
|
45
10
|
}
|
|
46
11
|
static segments(text, matches) {
|
|
47
|
-
|
|
48
|
-
let cursor = 0;
|
|
49
|
-
matches.forEach((match, index) => {
|
|
50
|
-
if (match.start > cursor)
|
|
51
|
-
segments.push({ matchIndex: null, text: text.slice(cursor, match.start) });
|
|
52
|
-
segments.push({ matchIndex: index, text: text.slice(match.start, match.end) });
|
|
53
|
-
cursor = match.end;
|
|
54
|
-
});
|
|
55
|
-
if (cursor < text.length)
|
|
56
|
-
segments.push({ matchIndex: null, text: text.slice(cursor) });
|
|
57
|
-
return segments;
|
|
58
|
-
}
|
|
59
|
-
static joinedWords(layer) {
|
|
60
|
-
return layer.words.map((word) => word.text).join(PsDocumentSearchConfig.wordSeparator);
|
|
12
|
+
return Common.TextSearchService.segments(text, matches);
|
|
61
13
|
}
|
|
62
14
|
static wordMatches(layer, query) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let cursor = 0;
|
|
66
|
-
for (const word of layer.words) {
|
|
67
|
-
bounds.push({ end: cursor + word.text.length, start: cursor });
|
|
68
|
-
cursor += word.text.length + PsDocumentSearchConfig.wordSeparator.length;
|
|
69
|
-
}
|
|
70
|
-
return matches.map((match) => ({
|
|
71
|
-
wordIndices: bounds.flatMap((bound, index) => bound.start < match.end && bound.end > match.start ? [index] : []),
|
|
15
|
+
return Common.TextLayerService.termMatches(layer, query).map((match) => ({
|
|
16
|
+
wordIndices: match.parts.map((part) => part.itemIndex),
|
|
72
17
|
}));
|
|
73
18
|
}
|
|
74
19
|
static fit(layer, container) {
|
|
75
|
-
|
|
76
|
-
return { height: 0, left: 0, top: 0, width: 0 };
|
|
77
|
-
const scale = Math.min(container.width / layer.width, container.height / layer.height);
|
|
78
|
-
const width = layer.width * scale;
|
|
79
|
-
const height = layer.height * scale;
|
|
80
|
-
return {
|
|
81
|
-
height,
|
|
82
|
-
left: (container.width - width) / 2,
|
|
83
|
-
top: (container.height - height) / 2,
|
|
84
|
-
width,
|
|
85
|
-
};
|
|
20
|
+
return Common.TextLayerService.fit(layer, container);
|
|
86
21
|
}
|
|
87
22
|
static rect(box, layer, container) {
|
|
88
|
-
|
|
89
|
-
const scale = layer.width <= 0 ? 0 : fitted.width / layer.width;
|
|
90
|
-
return {
|
|
91
|
-
height: box.height * scale,
|
|
92
|
-
left: fitted.left + box.left * scale,
|
|
93
|
-
top: fitted.top + box.top * scale,
|
|
94
|
-
width: box.width * scale,
|
|
95
|
-
};
|
|
23
|
+
return Common.TextLayerService.rect(box, layer, container);
|
|
96
24
|
}
|
|
97
25
|
static highlights(layer, query, container, activeIndex) {
|
|
98
|
-
return
|
|
99
|
-
box: PsDocumentSearchService.rect(layer.words[wordIndex].box, layer, container),
|
|
100
|
-
isActive: matchIndex === activeIndex,
|
|
101
|
-
})));
|
|
26
|
+
return Common.TextLayerService.wordRects(layer, Common.TextLayerService.termMatches(layer, query), container).map((rect) => ({ box: rect.box, isActive: rect.matchIndex === activeIndex }));
|
|
102
27
|
}
|
|
103
28
|
static center(box) {
|
|
104
29
|
return { x: box.left + box.width / 2, y: box.top + box.height / 2 };
|
|
@@ -186,16 +111,4 @@ export class PsDocumentSearchService {
|
|
|
186
111
|
item.textLayer !== undefined ||
|
|
187
112
|
(item.pageTextLayers !== undefined && item.pageTextLayers.length > 0));
|
|
188
113
|
}
|
|
189
|
-
static merge(ranges) {
|
|
190
|
-
const sorted = [...ranges].sort((a, b) => a.start === b.start ? a.end - b.end : a.start - b.start);
|
|
191
|
-
const merged = [];
|
|
192
|
-
for (const range of sorted) {
|
|
193
|
-
const last = merged[merged.length - 1];
|
|
194
|
-
if (last !== undefined && range.start < last.end)
|
|
195
|
-
merged[merged.length - 1] = { end: Math.max(last.end, range.end), start: last.start };
|
|
196
|
-
else
|
|
197
|
-
merged.push({ ...range });
|
|
198
|
-
}
|
|
199
|
-
return merged;
|
|
200
|
-
}
|
|
201
114
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
import { PsContentWidth } from '../constants/ps-content-width';
|
|
3
|
+
import { PsLayoutClass } from '../constants/ps-layout-class';
|
|
4
|
+
export declare class PsLayoutService {
|
|
5
|
+
static classOf(width: number, height: number): PsLayoutClass;
|
|
6
|
+
static maxWidth(layoutClass: PsLayoutClass, contentWidth: PsContentWidth): number | undefined;
|
|
7
|
+
static frame(layoutClass: PsLayoutClass, contentWidth: PsContentWidth): ViewStyle;
|
|
8
|
+
static gridUnits(layoutClass: PsLayoutClass): number;
|
|
9
|
+
static widgetBasis(layoutClass: PsLayoutClass): string;
|
|
10
|
+
static widgetWidth(containerWidth: number, layoutClass: PsLayoutClass, gap: number): number | undefined;
|
|
11
|
+
static menuMaxWidth(windowWidth: number, edgeMargin: number): number;
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PsContentWidth } from '../constants/ps-content-width';
|
|
2
|
+
import { PsLayoutClass } from '../constants/ps-layout-class';
|
|
3
|
+
import { PsLayoutClassConfig } from '../constants/ps-layout-class-config';
|
|
4
|
+
export class PsLayoutService {
|
|
5
|
+
static classOf(width, height) {
|
|
6
|
+
return width >= PsLayoutClassConfig.regularMinWidth &&
|
|
7
|
+
height >= PsLayoutClassConfig.regularMinHeight
|
|
8
|
+
? PsLayoutClass.regular
|
|
9
|
+
: PsLayoutClass.compact;
|
|
10
|
+
}
|
|
11
|
+
static maxWidth(layoutClass, contentWidth) {
|
|
12
|
+
if (layoutClass === PsLayoutClass.compact || contentWidth === PsContentWidth.full)
|
|
13
|
+
return undefined;
|
|
14
|
+
return contentWidth === PsContentWidth.wide
|
|
15
|
+
? PsLayoutClassConfig.wideMaxWidth
|
|
16
|
+
: PsLayoutClassConfig.readableMaxWidth;
|
|
17
|
+
}
|
|
18
|
+
static frame(layoutClass, contentWidth) {
|
|
19
|
+
const maxWidth = PsLayoutService.maxWidth(layoutClass, contentWidth);
|
|
20
|
+
return maxWidth === undefined ? {} : { alignSelf: 'center', maxWidth, width: '100%' };
|
|
21
|
+
}
|
|
22
|
+
static gridUnits(layoutClass) {
|
|
23
|
+
return layoutClass === PsLayoutClass.regular
|
|
24
|
+
? PsLayoutClassConfig.regularGridUnits
|
|
25
|
+
: PsLayoutClassConfig.compactGridUnits;
|
|
26
|
+
}
|
|
27
|
+
static widgetBasis(layoutClass) {
|
|
28
|
+
return layoutClass === PsLayoutClass.regular
|
|
29
|
+
? PsLayoutClassConfig.regularWidgetBasis
|
|
30
|
+
: PsLayoutClassConfig.compactWidgetBasis;
|
|
31
|
+
}
|
|
32
|
+
static widgetWidth(containerWidth, layoutClass, gap) {
|
|
33
|
+
if (layoutClass === PsLayoutClass.compact || containerWidth <= 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
const columns = PsLayoutService.gridUnits(layoutClass);
|
|
36
|
+
return Math.max((containerWidth - gap * (columns - 1)) / columns, 0);
|
|
37
|
+
}
|
|
38
|
+
static menuMaxWidth(windowWidth, edgeMargin) {
|
|
39
|
+
return Math.max(windowWidth - edgeMargin * 2, 0);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -3,20 +3,24 @@ export class PsMenuPopupService {
|
|
|
3
3
|
static layout(anchor, window, insets, contentHeight, contentWidth, isFullWidth) {
|
|
4
4
|
const margin = PsMenuPopupConfig.edgeMargin;
|
|
5
5
|
const gap = PsMenuPopupConfig.anchorGap;
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const minX = Math.max(margin, insets.left);
|
|
7
|
+
const maxX = window.width - Math.max(margin, insets.right);
|
|
8
|
+
const maxWidth = Math.max(maxX - minX, 0);
|
|
9
|
+
const width = isFullWidth ? Math.min(anchor.width, maxWidth) : undefined;
|
|
10
|
+
const menuWidth = Math.min(width === undefined ? contentWidth : width, maxWidth);
|
|
8
11
|
const below = window.height - (anchor.y + anchor.height) - gap - Math.max(margin, insets.bottom);
|
|
9
12
|
const above = anchor.y - gap - Math.max(margin, insets.top);
|
|
10
13
|
const isBelow = contentHeight <= below || below >= above;
|
|
11
14
|
const room = isBelow ? below : above;
|
|
12
15
|
const height = Math.min(contentHeight, Math.max(room, 0));
|
|
13
16
|
const top = isBelow ? anchor.y + anchor.height + gap : anchor.y - gap - height;
|
|
14
|
-
const alignedRight = anchor.x + menuWidth >
|
|
17
|
+
const alignedRight = anchor.x + menuWidth > maxX;
|
|
15
18
|
const left = alignedRight ? anchor.x + anchor.width - menuWidth : anchor.x;
|
|
16
19
|
return {
|
|
17
20
|
isBelow,
|
|
18
|
-
left: Math.max(
|
|
21
|
+
left: Math.max(minX, Math.min(left, maxX - menuWidth)),
|
|
19
22
|
maxHeight: Math.max(room, 0),
|
|
23
|
+
maxWidth,
|
|
20
24
|
top,
|
|
21
25
|
width,
|
|
22
26
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { ViewStyle } from 'react-native';
|
|
2
|
+
import { PsLayoutClass } from '../constants/ps-layout-class';
|
|
2
3
|
import type { PsSheetAction } from '../interfaces/ps-sheet-action';
|
|
3
4
|
import type { PsSheetLeadingKind } from '../interfaces/ps-sheet-leading-kind';
|
|
4
5
|
export declare class PsSheetService {
|
|
5
|
-
static maxHeight(windowHeight: number): number;
|
|
6
|
+
static maxHeight(windowHeight: number, layoutClass?: PsLayoutClass): number;
|
|
7
|
+
static fittedMaxWidth(windowWidth: number, layoutClass: PsLayoutClass): number | undefined;
|
|
8
|
+
static supportsFormSizing(iosVersion: string | number): boolean;
|
|
6
9
|
static handlesInset(os: string): boolean;
|
|
7
10
|
static bottomPadding(isFloating: boolean, bottomInset: number): number;
|
|
8
|
-
static fittedHeight(headerHeight: number, bodyHeight: number, windowHeight: number): number;
|
|
11
|
+
static fittedHeight(headerHeight: number, bodyHeight: number, windowHeight: number, layoutClass?: PsLayoutClass): number;
|
|
9
12
|
static raisedHeight(height: number, keyboardHeight: number, windowHeight: number, topInset: number): number;
|
|
10
13
|
static closeAction(label: string | undefined, onPress: () => void): PsSheetAction | undefined;
|
|
11
14
|
static isActionInactive(action: PsSheetAction): boolean;
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
import { PsLayoutClass } from '../constants/ps-layout-class';
|
|
2
|
+
import { PsLayoutClassConfig } from '../constants/ps-layout-class-config';
|
|
1
3
|
import { PsLayoutConfig } from '../constants/ps-layout-config';
|
|
2
4
|
import { PsSheetConfig } from '../constants/ps-sheet-config';
|
|
3
5
|
export class PsSheetService {
|
|
4
|
-
static maxHeight(windowHeight) {
|
|
5
|
-
return Math.floor(windowHeight *
|
|
6
|
+
static maxHeight(windowHeight, layoutClass = PsLayoutClass.compact) {
|
|
7
|
+
return Math.floor(windowHeight *
|
|
8
|
+
(layoutClass === PsLayoutClass.regular
|
|
9
|
+
? PsLayoutClassConfig.formSheetMaxHeightFraction
|
|
10
|
+
: PsSheetConfig.maxHeightFraction));
|
|
11
|
+
}
|
|
12
|
+
static fittedMaxWidth(windowWidth, layoutClass) {
|
|
13
|
+
return layoutClass === PsLayoutClass.regular
|
|
14
|
+
? Math.min(PsLayoutClassConfig.formSheetWidth, windowWidth)
|
|
15
|
+
: undefined;
|
|
16
|
+
}
|
|
17
|
+
static supportsFormSizing(iosVersion) {
|
|
18
|
+
return Number.parseInt(String(iosVersion), 10) >= PsSheetConfig.formSizingMinIos;
|
|
6
19
|
}
|
|
7
20
|
static handlesInset(os) {
|
|
8
21
|
return os === 'ios' || os === 'android';
|
|
@@ -10,8 +23,8 @@ export class PsSheetService {
|
|
|
10
23
|
static bottomPadding(isFloating, bottomInset) {
|
|
11
24
|
return PsLayoutConfig.sheetGutter + (isFloating ? 0 : bottomInset);
|
|
12
25
|
}
|
|
13
|
-
static fittedHeight(headerHeight, bodyHeight, windowHeight) {
|
|
14
|
-
return Math.min(Math.ceil(headerHeight + bodyHeight), PsSheetService.maxHeight(windowHeight));
|
|
26
|
+
static fittedHeight(headerHeight, bodyHeight, windowHeight, layoutClass = PsLayoutClass.compact) {
|
|
27
|
+
return Math.min(Math.ceil(headerHeight + bodyHeight), PsSheetService.maxHeight(windowHeight, layoutClass));
|
|
15
28
|
}
|
|
16
29
|
static raisedHeight(height, keyboardHeight, windowHeight, topInset) {
|
|
17
30
|
return Math.min(height + keyboardHeight, windowHeight - topInset);
|
|
@@ -8,8 +8,9 @@ export declare class PsSortableGridService {
|
|
|
8
8
|
id: string;
|
|
9
9
|
}>(items: T[]): string[];
|
|
10
10
|
static isSameOrder(first: string[], second: string[]): boolean;
|
|
11
|
-
static
|
|
12
|
-
static
|
|
11
|
+
static units(span: PsSortableGridSpan): number;
|
|
12
|
+
static rows(spans: PsSortableGridSpan[], capacity?: number): number[][];
|
|
13
|
+
static layout(spans: PsSortableGridSpan[], heights: number[], width: number, capacity?: number): PsSortableRect[];
|
|
13
14
|
static extras(rects: PsSortableRect[], heights: number[]): number[];
|
|
14
15
|
static natural(total: number, extra: number): number;
|
|
15
16
|
static contentHeight(rects: PsSortableRect[]): number;
|
|
@@ -16,34 +16,38 @@ export class PsSortableGridService {
|
|
|
16
16
|
static isSameOrder(first, second) {
|
|
17
17
|
return first.length === second.length && first.every((id, index) => id === second[index]);
|
|
18
18
|
}
|
|
19
|
-
static
|
|
20
|
-
return
|
|
19
|
+
static units(span) {
|
|
20
|
+
return span === PsSortableGridSpan.half ? 1 : PsSortableGridConfig.fullUnits;
|
|
21
|
+
}
|
|
22
|
+
static rows(spans, capacity = PsSortableGridConfig.compactUnits) {
|
|
23
|
+
const rows = [];
|
|
24
|
+
let used = 0;
|
|
25
|
+
spans.forEach((span, index) => {
|
|
26
|
+
const units = PsSortableGridService.units(span);
|
|
21
27
|
const last = rows[rows.length - 1];
|
|
22
|
-
|
|
23
|
-
last !== undefined &&
|
|
24
|
-
last.length === 1 &&
|
|
25
|
-
spans[last[0]] === PsSortableGridSpan.half;
|
|
26
|
-
if (canJoin)
|
|
28
|
+
if (last !== undefined && used + units <= capacity) {
|
|
27
29
|
last.push(index);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
used += units;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
rows.push([index]);
|
|
34
|
+
used = units;
|
|
35
|
+
});
|
|
36
|
+
return rows;
|
|
32
37
|
}
|
|
33
|
-
static layout(spans, heights, width) {
|
|
34
|
-
const
|
|
38
|
+
static layout(spans, heights, width, capacity = PsSortableGridConfig.compactUnits) {
|
|
39
|
+
const gap = PsSortableGridConfig.columnGap;
|
|
35
40
|
const rects = [];
|
|
36
41
|
let top = 0;
|
|
37
|
-
PsSortableGridService.rows(spans).forEach((row) => {
|
|
42
|
+
PsSortableGridService.rows(spans, capacity).forEach((row) => {
|
|
38
43
|
const rowHeight = Math.max(...row.map((index) => heights[index]));
|
|
39
|
-
row.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
};
|
|
44
|
+
const units = row.reduce((sum, index) => sum + PsSortableGridService.units(spans[index]), 0);
|
|
45
|
+
const unitWidth = Math.max(width - gap * (row.length - 1), 0) / units;
|
|
46
|
+
let left = 0;
|
|
47
|
+
row.forEach((index) => {
|
|
48
|
+
const itemWidth = unitWidth * PsSortableGridService.units(spans[index]);
|
|
49
|
+
rects[index] = { height: rowHeight, width: itemWidth, x: left, y: top };
|
|
50
|
+
left += itemWidth + gap;
|
|
47
51
|
});
|
|
48
52
|
top += rowHeight + PsSortableGridConfig.rowGap;
|
|
49
53
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pallasoft/ps-mobile-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Native iOS (SwiftUI) and Android (Jetpack Compose) Ps components for Pallasoft mobile apps",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@pallasoft/ps-design-system": "^1.19.0",
|
|
38
38
|
"@pallasoft/ps-icons": "^1.12.0",
|
|
39
|
-
"@pallasoft/ps-utilities": "^2.
|
|
39
|
+
"@pallasoft/ps-utilities": "^2.30.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@expo/ui": "~58.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|