@pallasoft/ps-mobile-components 1.7.0 → 1.8.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.
Files changed (74) hide show
  1. package/dist/components/ps-accessibility-gate/index.d.ts +2 -0
  2. package/dist/components/ps-accessibility-gate/index.js +2 -0
  3. package/dist/components/ps-accessibility-gate/ps-accessibility-gate-props.d.ts +5 -0
  4. package/dist/components/ps-accessibility-gate/ps-accessibility-gate-props.js +1 -0
  5. package/dist/components/ps-accessibility-gate/ps-accessibility-gate.d.ts +2 -0
  6. package/dist/components/ps-accessibility-gate/ps-accessibility-gate.js +4 -0
  7. package/dist/components/ps-app-lock-screen/ps-app-lock-screen.js +1 -1
  8. package/dist/components/ps-cartesian-chart/ps-cartesian-chart.d.ts +1 -1
  9. package/dist/components/ps-cartesian-chart/ps-cartesian-chart.js +25 -17
  10. package/dist/components/ps-chart-empty-state/ps-chart-empty-state.js +5 -1
  11. package/dist/components/ps-chart-frame/ps-chart-frame.js +10 -1
  12. package/dist/components/ps-chart-legend/ps-chart-legend.js +11 -2
  13. package/dist/components/ps-chart-readout/ps-chart-readout-props.d.ts +1 -0
  14. package/dist/components/ps-chart-readout/ps-chart-readout.d.ts +1 -1
  15. package/dist/components/ps-chart-readout/ps-chart-readout.js +8 -2
  16. package/dist/components/ps-chart-skeleton/ps-chart-skeleton.d.ts +1 -1
  17. package/dist/components/ps-chart-skeleton/ps-chart-skeleton.js +5 -1
  18. package/dist/components/ps-donut-chart/ps-donut-chart.js +23 -5
  19. package/dist/components/ps-kpi-card/ps-kpi-card.js +4 -1
  20. package/dist/components/ps-privacy-cover/ps-privacy-cover-props.d.ts +1 -0
  21. package/dist/components/ps-privacy-cover/ps-privacy-cover.d.ts +1 -1
  22. package/dist/components/ps-privacy-cover/ps-privacy-cover.js +12 -3
  23. package/dist/components/ps-sortable-grid/ps-sortable-grid.js +7 -4
  24. package/dist/components/ps-sortable-grid/ps-sortable-item-props.d.ts +2 -1
  25. package/dist/components/ps-sortable-grid/ps-sortable-item.d.ts +1 -1
  26. package/dist/components/ps-sortable-grid/ps-sortable-item.js +4 -3
  27. package/dist/components/ps-sparkline/ps-sparkline.d.ts +1 -1
  28. package/dist/components/ps-sparkline/ps-sparkline.js +3 -1
  29. package/dist/components/ps-waterfall-chart/ps-waterfall-chart.d.ts +1 -1
  30. package/dist/components/ps-waterfall-chart/ps-waterfall-chart.js +15 -9
  31. package/dist/constants/ps-accessibility-config.d.ts +5 -0
  32. package/dist/constants/ps-accessibility-config.js +5 -0
  33. package/dist/constants/ps-chart-config.d.ts +26 -1
  34. package/dist/constants/ps-chart-config.js +26 -1
  35. package/dist/constants/ps-screen-capture-config.d.ts +4 -0
  36. package/dist/constants/ps-screen-capture-config.js +4 -0
  37. package/dist/constants/ps-sortable-grid-config.d.ts +1 -0
  38. package/dist/constants/ps-sortable-grid-config.js +1 -0
  39. package/dist/contexts/ps-widget-fill-context.d.ts +1 -0
  40. package/dist/contexts/ps-widget-fill-context.js +2 -0
  41. package/dist/hooks/use-ps-screen-capture-prevention.d.ts +2 -0
  42. package/dist/hooks/use-ps-screen-capture-prevention.js +12 -0
  43. package/dist/hooks/use-ps-widget-fill.d.ts +1 -0
  44. package/dist/hooks/use-ps-widget-fill.js +3 -0
  45. package/dist/index.d.ts +4 -0
  46. package/dist/index.js +4 -0
  47. package/dist/interfaces/ps-chart-bar-group.d.ts +4 -0
  48. package/dist/interfaces/ps-chart-bar-group.js +1 -0
  49. package/dist/interfaces/ps-chart-x-labels.d.ts +4 -0
  50. package/dist/interfaces/ps-chart-x-labels.js +1 -0
  51. package/dist/interfaces/ps-donut-chart-layout.d.ts +4 -0
  52. package/dist/interfaces/ps-donut-chart-layout.js +1 -0
  53. package/dist/interfaces/ps-screen-capture-native.d.ts +4 -0
  54. package/dist/interfaces/ps-screen-capture-native.js +1 -0
  55. package/dist/interfaces/use-ps-screen-capture-prevention-options.d.ts +3 -0
  56. package/dist/interfaces/use-ps-screen-capture-prevention-options.js +1 -0
  57. package/dist/services/ps-chart-axis-service.d.ts +5 -0
  58. package/dist/services/ps-chart-axis-service.js +32 -0
  59. package/dist/services/ps-chart-bar-service.d.ts +2 -0
  60. package/dist/services/ps-chart-bar-service.js +11 -4
  61. package/dist/services/ps-chart-donut-service.d.ts +3 -0
  62. package/dist/services/ps-chart-donut-service.js +11 -0
  63. package/dist/services/ps-chart-readout-service.d.ts +3 -0
  64. package/dist/services/ps-chart-readout-service.js +25 -0
  65. package/dist/services/ps-chart-scale-service.d.ts +1 -1
  66. package/dist/services/ps-chart-scale-service.js +2 -2
  67. package/dist/services/ps-chart-text-service.d.ts +6 -0
  68. package/dist/services/ps-chart-text-service.js +23 -0
  69. package/dist/services/ps-screen-capture-service.d.ts +6 -0
  70. package/dist/services/ps-screen-capture-service.js +35 -0
  71. package/dist/services/ps-sortable-grid-service.d.ts +2 -0
  72. package/dist/services/ps-sortable-grid-service.js +10 -3
  73. package/dist/services/ps-waterfall-service.js +2 -3
  74. package/package.json +5 -1
@@ -1,31 +1,56 @@
1
1
  export const PsChartConfig = {
2
2
  areaOpacity: 0.18,
3
- axisLabelSize: 10,
3
+ axisLabelGap: 8,
4
+ axisLabelMaxWidth: 48,
5
+ axisLabelSize: 11,
6
+ axisTickGap: 6,
4
7
  barGapRatio: 0.3,
5
8
  barRadius: 4,
9
+ charWidthRatio: 0.62,
10
+ compactBarGapRatio: 0.15,
11
+ compactSlot: 24,
6
12
  cardPadding: 16,
7
13
  cardRadius: 16,
8
14
  chartHeight: 180,
9
15
  deltaIconSize: 10,
10
16
  donutHeight: 160,
11
17
  donutThickness: 22,
18
+ donutCenterFontMax: 18,
19
+ donutCenterFontMin: 11,
20
+ donutCenterPadding: 8,
21
+ donutGap: 16,
22
+ donutMinLegendWidth: 120,
12
23
  donutSliceGap: 2,
13
24
  drawMs: 700,
25
+ ellipsis: '…',
14
26
  gridLineCount: 3,
15
27
  gridLineWidth: 1,
28
+ kpiDeltaHeight: 20,
16
29
  kpiGap: 12,
30
+ kpiPeriodHeight: 16,
31
+ kpiValueFontMax: 24,
32
+ kpiValueFontMin: 16,
33
+ legendHitSlop: 8,
17
34
  legendDot: 8,
18
35
  lineWidth: 2.5,
19
36
  markerRadius: 4,
37
+ minBarWidth: 4,
20
38
  maxXLabels: 4,
39
+ minXLabels: 2,
21
40
  paddingBottom: 22,
22
41
  paddingRight: 8,
23
42
  paddingTop: 8,
24
43
  readoutHeight: 40,
44
+ readoutItemGap: 12,
45
+ readoutLineHeight: 22,
46
+ readoutRowGap: 2,
47
+ readoutValueSize: 15,
25
48
  scrubLineWidth: 1,
26
49
  skeletonBarHeights: [0.45, 0.7, 0.55, 0.85, 0.65, 0.95, 0.75],
27
50
  skeletonPulseMs: 900,
28
51
  sparklineHeight: 40,
29
52
  sparklineWidth: 2,
53
+ yAxisMaxRatio: 0.35,
54
+ yAxisMinWidth: 28,
30
55
  yAxisWidth: 52,
31
56
  };
@@ -0,0 +1,4 @@
1
+ export declare const PsScreenCaptureConfig: {
2
+ readonly key: "ps-mobile-components";
3
+ readonly moduleName: "expo-screen-capture";
4
+ };
@@ -0,0 +1,4 @@
1
+ export const PsScreenCaptureConfig = {
2
+ key: 'ps-mobile-components',
3
+ moduleName: 'expo-screen-capture',
4
+ };
@@ -6,6 +6,7 @@ export declare const PsSortableGridConfig: {
6
6
  readonly holdTolerance: 8;
7
7
  readonly longPressMs: 400;
8
8
  readonly maxScrollStep: 18;
9
+ readonly measureTolerance: 1;
9
10
  readonly moveMs: 220;
10
11
  readonly outlineOffset: 0;
11
12
  readonly outlineWidth: 2;
@@ -8,6 +8,7 @@ export const PsSortableGridConfig = {
8
8
  holdTolerance: 8,
9
9
  longPressMs: 400,
10
10
  maxScrollStep: 18,
11
+ measureTolerance: 1,
11
12
  moveMs: 220,
12
13
  outlineOffset: 0,
13
14
  outlineWidth: 2,
@@ -0,0 +1 @@
1
+ export declare const PsWidgetFillContext: import("react").Context<number>;
@@ -0,0 +1,2 @@
1
+ import { createContext } from 'react';
2
+ export const PsWidgetFillContext = createContext(0);
@@ -0,0 +1,2 @@
1
+ import type { UsePsScreenCapturePreventionOptions } from '../interfaces/use-ps-screen-capture-prevention-options';
2
+ export declare const usePsScreenCapturePrevention: ({ isEnabled, }?: UsePsScreenCapturePreventionOptions) => void;
@@ -0,0 +1,12 @@
1
+ import { useEffect } from 'react';
2
+ import { PsScreenCaptureService } from '../services/ps-screen-capture-service';
3
+ export const usePsScreenCapturePrevention = ({ isEnabled = true, } = {}) => {
4
+ useEffect(() => {
5
+ if (!isEnabled)
6
+ return;
7
+ void PsScreenCaptureService.prevent();
8
+ return () => {
9
+ void PsScreenCaptureService.allow();
10
+ };
11
+ }, [isEnabled]);
12
+ };
@@ -0,0 +1 @@
1
+ export declare const usePsWidgetFill: () => number;
@@ -0,0 +1,3 @@
1
+ import { useContext } from 'react';
2
+ import { PsWidgetFillContext } from '../contexts/ps-widget-fill-context';
3
+ export const usePsWidgetFill = () => useContext(PsWidgetFillContext);
package/dist/index.d.ts CHANGED
@@ -146,10 +146,14 @@ export * from './interfaces/ps-text-variant';
146
146
  export * from './interfaces/ps-sheet-action';
147
147
  export * from './interfaces/ps-sheet-leading-kind';
148
148
  export * from './interfaces/ps-sheet-page';
149
+ export * from './components/ps-accessibility-gate';
149
150
  export * from './components/ps-app-lock-screen';
150
151
  export * from './components/ps-privacy-cover';
151
152
  export * from './constants/ps-biometry-kind';
152
153
  export * from './hooks/use-ps-app-lock';
154
+ export * from './hooks/use-ps-screen-capture-prevention';
155
+ export * from './interfaces/use-ps-screen-capture-prevention-options';
156
+ export { PsScreenCaptureService } from './services/ps-screen-capture-service';
153
157
  export * from './interfaces/ps-app-lock-prompt';
154
158
  export * from './interfaces/use-ps-app-lock-options';
155
159
  export * from './interfaces/use-ps-app-lock-result';
package/dist/index.js CHANGED
@@ -141,10 +141,14 @@ export * from './interfaces/ps-text-variant';
141
141
  export * from './interfaces/ps-sheet-action';
142
142
  export * from './interfaces/ps-sheet-leading-kind';
143
143
  export * from './interfaces/ps-sheet-page';
144
+ export * from './components/ps-accessibility-gate';
144
145
  export * from './components/ps-app-lock-screen';
145
146
  export * from './components/ps-privacy-cover';
146
147
  export * from './constants/ps-biometry-kind';
147
148
  export * from './hooks/use-ps-app-lock';
149
+ export * from './hooks/use-ps-screen-capture-prevention';
150
+ export * from './interfaces/use-ps-screen-capture-prevention-options';
151
+ export { PsScreenCaptureService } from './services/ps-screen-capture-service';
148
152
  export * from './interfaces/ps-app-lock-prompt';
149
153
  export * from './interfaces/use-ps-app-lock-options';
150
154
  export * from './interfaces/use-ps-app-lock-result';
@@ -0,0 +1,4 @@
1
+ export interface PsChartBarGroup {
2
+ offset: number;
3
+ width: number;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export interface PsChartXLabels {
2
+ indexes: number[];
3
+ maxWidth: number;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export interface PsDonutChartLayout {
2
+ isStacked: boolean;
3
+ size: number;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export interface PsScreenCaptureNative {
2
+ allowScreenCaptureAsync: (key?: string) => Promise<void>;
3
+ preventScreenCaptureAsync: (key?: string) => Promise<void>;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export interface UsePsScreenCapturePreventionOptions {
2
+ isEnabled?: boolean;
3
+ }
@@ -0,0 +1,5 @@
1
+ import type { PsChartXLabels } from '../interfaces/ps-chart-x-labels';
2
+ export declare class PsChartAxisService {
3
+ static yAxisWidth(labels: string[], width: number): number;
4
+ static xLabels(labels: string[], available: number, isBand: boolean): PsChartXLabels;
5
+ }
@@ -0,0 +1,32 @@
1
+ import { PsChartConfig } from '../constants/ps-chart-config';
2
+ import { PsChartTextService } from './ps-chart-text-service';
3
+ export class PsChartAxisService {
4
+ static yAxisWidth(labels, width) {
5
+ if (width <= 0)
6
+ return PsChartConfig.yAxisWidth;
7
+ const wanted = PsChartTextService.widest(labels, PsChartConfig.axisLabelSize) + PsChartConfig.axisTickGap;
8
+ return Math.min(Math.max(Math.ceil(wanted), PsChartConfig.yAxisMinWidth), Math.max(width * PsChartConfig.yAxisMaxRatio, PsChartConfig.yAxisMinWidth));
9
+ }
10
+ static xLabels(labels, available, isBand) {
11
+ const count = labels.length;
12
+ const all = Array.from({ length: count }, (_, index) => index);
13
+ if (count === 0 || available <= 0)
14
+ return { indexes: [], maxWidth: 0 };
15
+ const wanted = Math.min(PsChartTextService.widest(labels, PsChartConfig.axisLabelSize), PsChartConfig.axisLabelMaxWidth) + PsChartConfig.axisLabelGap;
16
+ if (isBand) {
17
+ const pitch = available / count;
18
+ const step = Math.max(Math.ceil(wanted / pitch), 1);
19
+ return {
20
+ indexes: all.filter((index) => index % step === 0),
21
+ maxWidth: Math.max(pitch * step - PsChartConfig.axisLabelGap, 0),
22
+ };
23
+ }
24
+ if (count === 1)
25
+ return { indexes: all, maxWidth: available };
26
+ const shown = Math.min(Math.max(Math.floor(available / wanted) + 1, PsChartConfig.minXLabels), count);
27
+ return {
28
+ indexes: Array.from({ length: shown }, (_, index) => Math.round((index * (count - 1)) / (shown - 1))),
29
+ maxWidth: Math.max(available / (shown - 1) - PsChartConfig.axisLabelGap, 0),
30
+ };
31
+ }
32
+ }
@@ -1,5 +1,6 @@
1
1
  import type { PsAreaChartDatum } from '../interfaces/ps-area-chart-datum';
2
2
  import type { PsCartesianChartSeries } from '../interfaces/ps-cartesian-chart-series';
3
+ import type { PsChartBarGroup } from '../interfaces/ps-chart-bar-group';
3
4
  import type { PsChartBarRect } from '../interfaces/ps-chart-bar-rect';
4
5
  import type { PsChartDomain } from '../interfaces/ps-chart-domain';
5
6
  import type { PsChartPlot } from '../interfaces/ps-chart-plot';
@@ -7,5 +8,6 @@ export declare class PsChartBarService {
7
8
  static grouped(data: PsAreaChartDatum[], series: PsCartesianChartSeries[], colors: string[], domain: PsChartDomain, plot: PsChartPlot): PsChartBarRect[];
8
9
  static stacked(data: PsAreaChartDatum[], series: PsCartesianChartSeries[], colors: string[], domain: PsChartDomain, plot: PsChartPlot): PsChartBarRect[];
9
10
  static slot(count: number, plot: PsChartPlot): number;
11
+ static group(slot: number, size: number): PsChartBarGroup;
10
12
  private static rect;
11
13
  }
@@ -4,18 +4,18 @@ import { PsChartSeriesService } from './ps-chart-series-service';
4
4
  export class PsChartBarService {
5
5
  static grouped(data, series, colors, domain, plot) {
6
6
  const slot = PsChartBarService.slot(data.length, plot);
7
- const width = (slot * (1 - PsChartConfig.barGapRatio)) / series.length;
7
+ const { offset, width } = PsChartBarService.group(slot, series.length);
8
8
  const zero = PsChartScaleService.y(0, domain, plot);
9
9
  return data.flatMap((datum, row) => series.map((entry, column) => {
10
10
  const value = PsChartSeriesService.value(datum, entry.dataKey);
11
11
  const top = PsChartScaleService.y(value, domain, plot);
12
- const left = plot.left + row * slot + (slot * PsChartConfig.barGapRatio) / 2 + column * width;
12
+ const left = plot.left + row * slot + offset + column * width;
13
13
  return PsChartBarService.rect(`${row}:${entry.dataKey}`, colors[column], left, width, zero, top, value < 0);
14
14
  }));
15
15
  }
16
16
  static stacked(data, series, colors, domain, plot) {
17
17
  const slot = PsChartBarService.slot(data.length, plot);
18
- const width = slot * (1 - PsChartConfig.barGapRatio);
18
+ const { offset, width } = PsChartBarService.group(slot, 1);
19
19
  return data.flatMap((datum, row) => {
20
20
  let positive = 0;
21
21
  let negative = 0;
@@ -27,13 +27,20 @@ export class PsChartBarService {
27
27
  negative = to;
28
28
  else
29
29
  positive = to;
30
- return PsChartBarService.rect(`${row}:${entry.dataKey}`, colors[column], plot.left + row * slot + (slot * PsChartConfig.barGapRatio) / 2, width, PsChartScaleService.y(from, domain, plot), PsChartScaleService.y(to, domain, plot), value < 0);
30
+ return PsChartBarService.rect(`${row}:${entry.dataKey}`, colors[column], plot.left + row * slot + offset, width, PsChartScaleService.y(from, domain, plot), PsChartScaleService.y(to, domain, plot), value < 0);
31
31
  });
32
32
  });
33
33
  }
34
34
  static slot(count, plot) {
35
35
  return (plot.right - plot.left) / Math.max(count, 1);
36
36
  }
37
+ static group(slot, size) {
38
+ const gap = slot < PsChartConfig.compactSlot
39
+ ? PsChartConfig.compactBarGapRatio
40
+ : PsChartConfig.barGapRatio;
41
+ const total = Math.max(slot * (1 - gap), Math.min(PsChartConfig.minBarWidth * size, slot));
42
+ return { offset: (slot - total) / 2, width: total / size };
43
+ }
37
44
  static rect(id, color, x, width, from, to, isNegative) {
38
45
  return {
39
46
  color,
@@ -1,6 +1,9 @@
1
1
  import type { PsDonutChartDatum } from '../interfaces/ps-donut-chart-datum';
2
+ import type { PsDonutChartLayout } from '../interfaces/ps-donut-chart-layout';
2
3
  import type { PsDonutSliceData } from '../interfaces/ps-donut-slice-data';
3
4
  export declare class PsChartDonutService {
5
+ static layout(width: number, height: number): PsDonutChartLayout;
6
+ static centerFontSize(text: string, size: number): number;
4
7
  static radius(size: number): number;
5
8
  static circumference(size: number): number;
6
9
  static slices(data: PsDonutChartDatum[], colors: string[], size: number): PsDonutSliceData[];
@@ -1,5 +1,16 @@
1
1
  import { PsChartConfig } from '../constants/ps-chart-config';
2
+ import { PsChartTextService } from './ps-chart-text-service';
2
3
  export class PsChartDonutService {
4
+ static layout(width, height) {
5
+ const side = height + PsChartConfig.donutGap + PsChartConfig.donutMinLegendWidth;
6
+ if (width >= side)
7
+ return { isStacked: false, size: height };
8
+ return { isStacked: true, size: Math.min(height, Math.max(width, 0)) };
9
+ }
10
+ static centerFontSize(text, size) {
11
+ const inner = size - 2 * (PsChartConfig.donutThickness + PsChartConfig.donutCenterPadding);
12
+ return PsChartTextService.fontSize(text, Math.max(inner, 0), PsChartConfig.donutCenterFontMax, PsChartConfig.donutCenterFontMin);
13
+ }
3
14
  static radius(size) {
4
15
  return (size - PsChartConfig.donutThickness) / 2;
5
16
  }
@@ -4,4 +4,7 @@ import type { PsChartReadoutItem } from '../interfaces/ps-chart-readout-item';
4
4
  export declare class PsChartReadoutService {
5
5
  static items(datum: PsAreaChartDatum, series: PsCartesianChartSeries[], colors: string[], formatValue: (value: number) => string): PsChartReadoutItem[];
6
6
  static summary(title: string, items: PsChartReadoutItem[]): string;
7
+ static lines(items: PsChartReadoutItem[], width: number): number;
8
+ static maxLines(rows: PsChartReadoutItem[][], width: number): number;
9
+ static height(lines: number): number;
7
10
  }
@@ -1,4 +1,6 @@
1
+ import { PsChartConfig } from '../constants/ps-chart-config';
1
2
  import { PsChartSeriesService } from './ps-chart-series-service';
3
+ import { PsChartTextService } from './ps-chart-text-service';
2
4
  export class PsChartReadoutService {
3
5
  static items(datum, series, colors, formatValue) {
4
6
  return series.map((entry, index) => ({
@@ -10,4 +12,27 @@ export class PsChartReadoutService {
10
12
  static summary(title, items) {
11
13
  return [title, ...items.map((item) => `${item.label} ${item.value}`)].join(', ');
12
14
  }
15
+ static lines(items, width) {
16
+ let lines = 1;
17
+ let used = 0;
18
+ items.forEach((item) => {
19
+ const wanted = PsChartConfig.legendDot +
20
+ PsChartConfig.axisTickGap +
21
+ PsChartTextService.estimateWidth(item.value, PsChartConfig.readoutValueSize);
22
+ if (used > 0 && used + PsChartConfig.readoutItemGap + wanted > width) {
23
+ lines += 1;
24
+ used = wanted;
25
+ return;
26
+ }
27
+ used += used > 0 ? PsChartConfig.readoutItemGap + wanted : wanted;
28
+ });
29
+ return lines;
30
+ }
31
+ static maxLines(rows, width) {
32
+ return rows.reduce((most, row) => Math.max(most, PsChartReadoutService.lines(row, width)), 1);
33
+ }
34
+ static height(lines) {
35
+ return (PsChartConfig.readoutHeight +
36
+ (Math.max(lines, 1) - 1) * (PsChartConfig.readoutLineHeight + PsChartConfig.readoutRowGap));
37
+ }
13
38
  }
@@ -1,7 +1,7 @@
1
1
  import type { PsChartDomain } from '../interfaces/ps-chart-domain';
2
2
  import type { PsChartPlot } from '../interfaces/ps-chart-plot';
3
3
  export declare class PsChartScaleService {
4
- static plot(width: number, height: number): PsChartPlot;
4
+ static plot(width: number, height: number, yAxisWidth?: number): PsChartPlot;
5
5
  static sparkPlot(width: number, height: number): PsChartPlot;
6
6
  static domain(values: number[]): PsChartDomain;
7
7
  static spanDomain(values: number[]): PsChartDomain;
@@ -1,9 +1,9 @@
1
1
  import { PsChartConfig } from '../constants/ps-chart-config';
2
2
  export class PsChartScaleService {
3
- static plot(width, height) {
3
+ static plot(width, height, yAxisWidth = PsChartConfig.yAxisWidth) {
4
4
  return {
5
5
  bottom: height - PsChartConfig.paddingBottom,
6
- left: PsChartConfig.yAxisWidth,
6
+ left: yAxisWidth,
7
7
  right: width - PsChartConfig.paddingRight,
8
8
  top: PsChartConfig.paddingTop,
9
9
  };
@@ -0,0 +1,6 @@
1
+ export declare class PsChartTextService {
2
+ static estimateWidth(text: string, fontSize: number): number;
3
+ static widest(texts: string[], fontSize: number): number;
4
+ static fit(text: string, maxWidth: number, fontSize: number): string;
5
+ static fontSize(text: string, maxWidth: number, largest: number, smallest: number): number;
6
+ }
@@ -0,0 +1,23 @@
1
+ import { PsChartConfig } from '../constants/ps-chart-config';
2
+ export class PsChartTextService {
3
+ static estimateWidth(text, fontSize) {
4
+ return text.length * fontSize * PsChartConfig.charWidthRatio;
5
+ }
6
+ static widest(texts, fontSize) {
7
+ return texts.reduce((widest, text) => Math.max(widest, PsChartTextService.estimateWidth(text, fontSize)), 0);
8
+ }
9
+ static fit(text, maxWidth, fontSize) {
10
+ if (PsChartTextService.estimateWidth(text, fontSize) <= maxWidth)
11
+ return text;
12
+ const characters = Math.floor(maxWidth / (fontSize * PsChartConfig.charWidthRatio));
13
+ if (characters < 1)
14
+ return '';
15
+ return `${text.slice(0, Math.max(characters - 1, 1))}${PsChartConfig.ellipsis}`;
16
+ }
17
+ static fontSize(text, maxWidth, largest, smallest) {
18
+ if (PsChartTextService.estimateWidth(text, largest) <= maxWidth)
19
+ return largest;
20
+ const fitted = Math.floor(maxWidth / (text.length * PsChartConfig.charWidthRatio));
21
+ return Math.min(Math.max(fitted, smallest), largest);
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ import type { PsScreenCaptureNative } from '../interfaces/ps-screen-capture-native';
2
+ export declare class PsScreenCaptureService {
3
+ static load(): PsScreenCaptureNative | null;
4
+ static prevent(): Promise<boolean>;
5
+ static allow(): Promise<void>;
6
+ }
@@ -0,0 +1,35 @@
1
+ import { PsScreenCaptureConfig } from '../constants/ps-screen-capture-config';
2
+ export class PsScreenCaptureService {
3
+ static load() {
4
+ try {
5
+ const loaded = require('expo-screen-capture');
6
+ return typeof loaded.preventScreenCaptureAsync === 'function' ? loaded : null;
7
+ }
8
+ catch {
9
+ return null;
10
+ }
11
+ }
12
+ static async prevent() {
13
+ const native = PsScreenCaptureService.load();
14
+ if (native === null)
15
+ return false;
16
+ try {
17
+ await native.preventScreenCaptureAsync(PsScreenCaptureConfig.key);
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ static async allow() {
25
+ const native = PsScreenCaptureService.load();
26
+ if (native === null)
27
+ return;
28
+ try {
29
+ await native.allowScreenCaptureAsync(PsScreenCaptureConfig.key);
30
+ }
31
+ catch {
32
+ return;
33
+ }
34
+ }
35
+ }
@@ -10,6 +10,8 @@ export declare class PsSortableGridService {
10
10
  static isSameOrder(first: string[], second: string[]): boolean;
11
11
  static rows(spans: PsSortableGridSpan[]): number[][];
12
12
  static layout(spans: PsSortableGridSpan[], heights: number[], width: number): PsSortableRect[];
13
+ static extras(rects: PsSortableRect[], heights: number[]): number[];
14
+ static natural(total: number, extra: number): number;
13
15
  static contentHeight(rects: PsSortableRect[]): number;
14
16
  static indexAt(rects: PsSortableRect[], x: number, y: number, current: number): number;
15
17
  static move<T>(items: T[], from: number, to: number): T[];
@@ -35,19 +35,26 @@ export class PsSortableGridService {
35
35
  const rects = [];
36
36
  let top = 0;
37
37
  PsSortableGridService.rows(spans).forEach((row) => {
38
+ const rowHeight = Math.max(...row.map((index) => heights[index]));
38
39
  row.forEach((index, column) => {
39
- const isHalf = spans[index] === PsSortableGridSpan.half;
40
+ const isHalf = spans[index] === PsSortableGridSpan.half && row.length === 2;
40
41
  rects[index] = {
41
- height: heights[index],
42
+ height: rowHeight,
42
43
  width: isHalf ? half : width,
43
44
  x: column === 0 ? 0 : half + PsSortableGridConfig.columnGap,
44
45
  y: top,
45
46
  };
46
47
  });
47
- top += Math.max(...row.map((index) => heights[index])) + PsSortableGridConfig.rowGap;
48
+ top += rowHeight + PsSortableGridConfig.rowGap;
48
49
  });
49
50
  return rects;
50
51
  }
52
+ static extras(rects, heights) {
53
+ return rects.map((rect, index) => Math.max(rect.height - heights[index], 0));
54
+ }
55
+ static natural(total, extra) {
56
+ return Math.max(total - extra, 0);
57
+ }
51
58
  static contentHeight(rects) {
52
59
  return rects.reduce((bottom, rect) => Math.max(bottom, rect.y + rect.height), 0);
53
60
  }
@@ -1,4 +1,3 @@
1
- import { PsChartConfig } from '../constants/ps-chart-config';
2
1
  import { PsChartBarService } from './ps-chart-bar-service';
3
2
  import { PsChartScaleService } from './ps-chart-scale-service';
4
3
  export class PsWaterfallService {
@@ -20,7 +19,7 @@ export class PsWaterfallService {
20
19
  }
21
20
  static rects(steps, colors, domain, plot) {
22
21
  const slot = PsChartBarService.slot(steps.length, plot);
23
- const width = slot * (1 - PsChartConfig.barGapRatio);
22
+ const { offset, width } = PsChartBarService.group(slot, 1);
24
23
  return steps.map((step, row) => {
25
24
  const from = PsChartScaleService.y(step.start, domain, plot);
26
25
  const to = PsChartScaleService.y(step.end, domain, plot);
@@ -30,7 +29,7 @@ export class PsWaterfallService {
30
29
  id: `${row}:${step.label}`,
31
30
  isNegative: step.end < step.start,
32
31
  width,
33
- x: plot.left + row * slot + (slot * PsChartConfig.barGapRatio) / 2,
32
+ x: plot.left + row * slot + offset,
34
33
  y: Math.min(from, to),
35
34
  };
36
35
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-mobile-components",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
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",
@@ -53,6 +53,7 @@
53
53
  "expo-local-authentication": "~58.0.0",
54
54
  "expo-quick-actions": "^6.0.2",
55
55
  "expo-router": "~58.0.0",
56
+ "expo-screen-capture": "~58.0.0",
56
57
  "react": "^19.3.0",
57
58
  "react-native": "~0.88.0",
58
59
  "react-native-document-scanner-plugin": "^2.0.4",
@@ -90,6 +91,9 @@
90
91
  "expo-router": {
91
92
  "optional": true
92
93
  },
94
+ "expo-screen-capture": {
95
+ "optional": true
96
+ },
93
97
  "react-native-document-scanner-plugin": {
94
98
  "optional": true
95
99
  },