@dangerousthings/react-native 0.1.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/DTAccordion.d.ts +75 -0
- package/dist/components/DTAccordion.d.ts.map +1 -0
- package/dist/components/DTAccordion.js +147 -0
- package/dist/components/DTAccordion.js.map +1 -0
- package/dist/components/DTButton.d.ts +68 -0
- package/dist/components/DTButton.d.ts.map +1 -0
- package/dist/components/DTButton.js +59 -0
- package/dist/components/DTButton.js.map +1 -0
- package/dist/components/DTCard.d.ts +97 -0
- package/dist/components/DTCard.d.ts.map +1 -0
- package/dist/components/DTCard.js +81 -0
- package/dist/components/DTCard.js.map +1 -0
- package/dist/components/DTCheckbox.d.ts +63 -0
- package/dist/components/DTCheckbox.d.ts.map +1 -0
- package/dist/components/DTCheckbox.js +55 -0
- package/dist/components/DTCheckbox.js.map +1 -0
- package/dist/components/DTChip.d.ts +40 -0
- package/dist/components/DTChip.d.ts.map +1 -0
- package/dist/components/DTChip.js +55 -0
- package/dist/components/DTChip.js.map +1 -0
- package/dist/components/DTDrawer.d.ts +82 -0
- package/dist/components/DTDrawer.d.ts.map +1 -0
- package/dist/components/DTDrawer.js +146 -0
- package/dist/components/DTDrawer.js.map +1 -0
- package/dist/components/DTGallery.d.ts +83 -0
- package/dist/components/DTGallery.d.ts.map +1 -0
- package/dist/components/DTGallery.js +160 -0
- package/dist/components/DTGallery.js.map +1 -0
- package/dist/components/DTHexagon.d.ts +81 -0
- package/dist/components/DTHexagon.d.ts.map +1 -0
- package/dist/components/DTHexagon.js +110 -0
- package/dist/components/DTHexagon.js.map +1 -0
- package/dist/components/DTLabel.d.ts +100 -0
- package/dist/components/DTLabel.d.ts.map +1 -0
- package/dist/components/DTLabel.js +189 -0
- package/dist/components/DTLabel.js.map +1 -0
- package/dist/components/DTMediaFrame.d.ts +77 -0
- package/dist/components/DTMediaFrame.d.ts.map +1 -0
- package/dist/components/DTMediaFrame.js +84 -0
- package/dist/components/DTMediaFrame.js.map +1 -0
- package/dist/components/DTMenu.d.ts +119 -0
- package/dist/components/DTMenu.d.ts.map +1 -0
- package/dist/components/DTMenu.js +188 -0
- package/dist/components/DTMenu.js.map +1 -0
- package/dist/components/DTModal.d.ts +64 -0
- package/dist/components/DTModal.d.ts.map +1 -0
- package/dist/components/DTModal.js +45 -0
- package/dist/components/DTModal.js.map +1 -0
- package/dist/components/DTProgressBar.d.ts +66 -0
- package/dist/components/DTProgressBar.d.ts.map +1 -0
- package/dist/components/DTProgressBar.js +82 -0
- package/dist/components/DTProgressBar.js.map +1 -0
- package/dist/components/DTQuantityStepper.d.ts +76 -0
- package/dist/components/DTQuantityStepper.d.ts.map +1 -0
- package/dist/components/DTQuantityStepper.js +108 -0
- package/dist/components/DTQuantityStepper.js.map +1 -0
- package/dist/components/DTRadioGroup.d.ts +79 -0
- package/dist/components/DTRadioGroup.d.ts.map +1 -0
- package/dist/components/DTRadioGroup.js +107 -0
- package/dist/components/DTRadioGroup.js.map +1 -0
- package/dist/components/DTSearchInput.d.ts +72 -0
- package/dist/components/DTSearchInput.d.ts.map +1 -0
- package/dist/components/DTSearchInput.js +71 -0
- package/dist/components/DTSearchInput.js.map +1 -0
- package/dist/components/DTSwitch.d.ts +52 -0
- package/dist/components/DTSwitch.d.ts.map +1 -0
- package/dist/components/DTSwitch.js +85 -0
- package/dist/components/DTSwitch.js.map +1 -0
- package/dist/components/DTTextInput.d.ts +58 -0
- package/dist/components/DTTextInput.d.ts.map +1 -0
- package/dist/components/DTTextInput.js +85 -0
- package/dist/components/DTTextInput.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/theme/DTThemeProvider.d.ts +49 -0
- package/dist/theme/DTThemeProvider.d.ts.map +1 -0
- package/dist/theme/DTThemeProvider.js +52 -0
- package/dist/theme/DTThemeProvider.js.map +1 -0
- package/dist/theme/colors.d.ts +42 -0
- package/dist/theme/colors.d.ts.map +1 -0
- package/dist/theme/colors.js +59 -0
- package/dist/theme/colors.js.map +1 -0
- package/dist/theme/paperTheme.d.ts +39 -0
- package/dist/theme/paperTheme.d.ts.map +1 -0
- package/dist/theme/paperTheme.js +116 -0
- package/dist/theme/paperTheme.js.map +1 -0
- package/dist/theme/typography.d.ts +57 -0
- package/dist/theme/typography.d.ts.map +1 -0
- package/dist/theme/typography.js +170 -0
- package/dist/theme/typography.js.map +1 -0
- package/dist/utils/bevelPaths.d.ts +42 -0
- package/dist/utils/bevelPaths.d.ts.map +1 -0
- package/dist/utils/bevelPaths.js +105 -0
- package/dist/utils/bevelPaths.js.map +1 -0
- package/dist/utils/useComponentLayout.d.ts +18 -0
- package/dist/utils/useComponentLayout.d.ts.map +1 -0
- package/dist/utils/useComponentLayout.js +24 -0
- package/dist/utils/useComponentLayout.js.map +1 -0
- package/dist/utils/variantColors.d.ts +12 -0
- package/dist/utils/variantColors.d.ts.map +1 -0
- package/dist/utils/variantColors.js +20 -0
- package/dist/utils/variantColors.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* DT Checkbox Component
|
|
4
|
+
*
|
|
5
|
+
* Custom-built angular checkbox following the Dangerous Things design language.
|
|
6
|
+
* Uses SVG for beveled shape and checkmark — RNP Checkbox enforces
|
|
7
|
+
* rounded corners (borderRadius: 18) so we build from scratch.
|
|
8
|
+
*
|
|
9
|
+
* Uses diagonal-symmetry bevels (top-left + bottom-right) on the indicator.
|
|
10
|
+
*/
|
|
11
|
+
import { StyleSheet, Pressable } from 'react-native';
|
|
12
|
+
import { Text } from 'react-native-paper';
|
|
13
|
+
import Svg, { Path } from 'react-native-svg';
|
|
14
|
+
import { DTColors } from '../theme/colors';
|
|
15
|
+
import { getVariantColor } from '../utils/variantColors';
|
|
16
|
+
import { buildBeveledRectPath } from '../utils/bevelPaths';
|
|
17
|
+
/**
|
|
18
|
+
* DT-styled Checkbox with beveled opposing corners (top-left + bottom-right)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <DTCheckbox checked={isChecked} onPress={() => setChecked(!isChecked)} label="Remember me" />
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <DTCheckbox checked={true} onPress={toggle} variant="success" label="Accepted" />
|
|
25
|
+
*/
|
|
26
|
+
export function DTCheckbox({ checked, onPress, variant = 'normal', label, disabled = false, size = 24, color, style, labelStyle, }) {
|
|
27
|
+
const accentColor = getVariantColor(variant, color);
|
|
28
|
+
const opacity = disabled ? 0.5 : 1;
|
|
29
|
+
const borderWidth = 2;
|
|
30
|
+
const bevelSize = Math.round(size * 0.3);
|
|
31
|
+
// Outer beveled path (border)
|
|
32
|
+
const outerPath = buildBeveledRectPath(size, size, {
|
|
33
|
+
corners: { topLeft: bevelSize, bottomRight: bevelSize },
|
|
34
|
+
strokeWidth: borderWidth,
|
|
35
|
+
});
|
|
36
|
+
return (_jsxs(Pressable, { onPress: onPress, disabled: disabled, style: ({ pressed }) => [
|
|
37
|
+
styles.container,
|
|
38
|
+
{ opacity: pressed ? 0.7 : opacity },
|
|
39
|
+
style,
|
|
40
|
+
], children: [_jsxs(Svg, { width: size, height: size, viewBox: `0 0 ${size} ${size}`, children: [_jsx(Path, { d: outerPath, fill: checked ? accentColor : 'transparent', stroke: accentColor, strokeWidth: borderWidth }), checked && (_jsx(Path, { d: `M ${size * 0.2} ${size * 0.5} L ${size * 0.4} ${size * 0.7} L ${size * 0.8} ${size * 0.25}`, fill: "none", stroke: DTColors.dark, strokeWidth: borderWidth + 0.5, strokeLinecap: "round", strokeLinejoin: "round" }))] }), label && (_jsx(Text, { style: [styles.label, { color: DTColors.light }, labelStyle], children: label }))] }));
|
|
41
|
+
}
|
|
42
|
+
const styles = StyleSheet.create({
|
|
43
|
+
container: {
|
|
44
|
+
flexDirection: 'row',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
gap: 12,
|
|
47
|
+
minHeight: 44,
|
|
48
|
+
paddingVertical: 8,
|
|
49
|
+
},
|
|
50
|
+
label: {
|
|
51
|
+
fontSize: 14,
|
|
52
|
+
letterSpacing: 0.3,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=DTCheckbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTCheckbox.js","sourceRoot":"","sources":["../../src/components/DTCheckbox.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DT Chip Component
|
|
3
|
+
*
|
|
4
|
+
* A themed chip/tag following the Dangerous Things design language.
|
|
5
|
+
* Useful for displaying chip types, statuses, and labels.
|
|
6
|
+
*/
|
|
7
|
+
import { ViewStyle, StyleProp } from 'react-native';
|
|
8
|
+
import { ChipProps } from 'react-native-paper';
|
|
9
|
+
type DTChipVariant = 'normal' | 'emphasis' | 'warning' | 'success' | 'other';
|
|
10
|
+
interface DTChipProps extends Omit<ChipProps, 'mode'> {
|
|
11
|
+
/**
|
|
12
|
+
* Visual variant of the chip
|
|
13
|
+
* @default 'normal'
|
|
14
|
+
*/
|
|
15
|
+
variant?: DTChipVariant;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the chip is in selected state
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
selected?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Additional styles
|
|
23
|
+
*/
|
|
24
|
+
style?: StyleProp<ViewStyle>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* DT-styled Chip component
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* <DTChip variant="normal">NTAG215</DTChip>
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* <DTChip variant="success" selected>Cloneable</DTChip>
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* <DTChip variant="warning">Non-Cloneable</DTChip>
|
|
37
|
+
*/
|
|
38
|
+
export declare function DTChip({ variant, selected, style, children, ...props }: DTChipProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=DTChip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTChip.d.ts","sourceRoot":"","sources":["../../src/components/DTChip.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAc,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAQ,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGrD,KAAK,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7E,UAAU,WAAY,SAAQ,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC;IACnD;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAUD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,EACrB,OAAkB,EAClB,QAAgB,EAChB,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,WAAW,2CAyBb"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* DT Chip Component
|
|
4
|
+
*
|
|
5
|
+
* A themed chip/tag following the Dangerous Things design language.
|
|
6
|
+
* Useful for displaying chip types, statuses, and labels.
|
|
7
|
+
*/
|
|
8
|
+
// React import not needed with new JSX transform
|
|
9
|
+
import { StyleSheet } from 'react-native';
|
|
10
|
+
import { Chip } from 'react-native-paper';
|
|
11
|
+
import { DTColors } from '../theme/colors';
|
|
12
|
+
const variantColors = {
|
|
13
|
+
normal: DTColors.modeNormal,
|
|
14
|
+
emphasis: DTColors.modeEmphasis,
|
|
15
|
+
warning: DTColors.modeWarning,
|
|
16
|
+
success: DTColors.modeSuccess,
|
|
17
|
+
other: DTColors.modeOther,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* DT-styled Chip component
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <DTChip variant="normal">NTAG215</DTChip>
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <DTChip variant="success" selected>Cloneable</DTChip>
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* <DTChip variant="warning">Non-Cloneable</DTChip>
|
|
30
|
+
*/
|
|
31
|
+
export function DTChip({ variant = 'normal', selected = false, style, children, ...props }) {
|
|
32
|
+
const color = variantColors[variant];
|
|
33
|
+
const chipStyle = {
|
|
34
|
+
backgroundColor: selected ? color : 'transparent',
|
|
35
|
+
borderColor: color,
|
|
36
|
+
borderWidth: 1,
|
|
37
|
+
borderRadius: 0, // Angular DT style
|
|
38
|
+
};
|
|
39
|
+
return (_jsx(Chip, { ...props, mode: "outlined", textStyle: [
|
|
40
|
+
styles.text,
|
|
41
|
+
{ color: selected ? DTColors.dark : color },
|
|
42
|
+
], style: [styles.chip, chipStyle, style], selectedColor: color, selected: selected, children: children }));
|
|
43
|
+
}
|
|
44
|
+
const styles = StyleSheet.create({
|
|
45
|
+
chip: {
|
|
46
|
+
marginRight: 8,
|
|
47
|
+
marginBottom: 8,
|
|
48
|
+
},
|
|
49
|
+
text: {
|
|
50
|
+
fontWeight: '600',
|
|
51
|
+
letterSpacing: 0.5,
|
|
52
|
+
fontSize: 12,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=DTChip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTChip.js","sourceRoot":"","sources":["../../src/components/DTChip.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,iDAAiD;AACjD,OAAO,EAAE,UAAU,EAAwB,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,IAAI,EAAa,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAqB3C,MAAM,aAAa,GAAkC;IACnD,MAAM,EAAE,QAAQ,CAAC,UAAU;IAC3B,QAAQ,EAAE,QAAQ,CAAC,YAAY;IAC/B,OAAO,EAAE,QAAQ,CAAC,WAAW;IAC7B,OAAO,EAAE,QAAQ,CAAC,WAAW;IAC7B,KAAK,EAAE,QAAQ,CAAC,SAAS;CAC1B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,QAAQ,EAClB,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACI;IACZ,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAErC,MAAM,SAAS,GAAc;QAC3B,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa;QACjD,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC,EAAE,mBAAmB;KACrC,CAAC;IAEF,OAAO,CACL,KAAC,IAAI,OACC,KAAK,EACT,IAAI,EAAC,UAAU,EACf,SAAS,EAAE;YACT,MAAM,CAAC,IAAI;YACX,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;SAC5C,EACD,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EACtC,aAAa,EAAE,KAAK,EACpB,QAAQ,EAAE,QAAQ,YAEjB,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;KAChB;IACD,IAAI,EAAE;QACJ,UAAU,EAAE,KAAK;QACjB,aAAa,EAAE,GAAG;QAClB,QAAQ,EAAE,EAAE;KACb;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DT Drawer Component
|
|
3
|
+
*
|
|
4
|
+
* Hybrid component: RNP Portal for layering + custom Animated panel
|
|
5
|
+
* for the sliding behavior. RNP has no sliding panel component.
|
|
6
|
+
*
|
|
7
|
+
* Uses the dual-SVG-path technique (outer border fill + inner dark fill)
|
|
8
|
+
* consistent with DTCard/DTMediaFrame for proper visual clipping at
|
|
9
|
+
* beveled corners.
|
|
10
|
+
*
|
|
11
|
+
* Web CSS reference (Aside.tsx):
|
|
12
|
+
* - Fixed sidebar sliding from right
|
|
13
|
+
* - Beveled left edges (top-left + bottom-left for right drawer)
|
|
14
|
+
* - Colored header bar
|
|
15
|
+
* - Overlay backdrop
|
|
16
|
+
* - transition: transform 200ms ease-in-out
|
|
17
|
+
*/
|
|
18
|
+
import { ViewStyle, StyleProp } from 'react-native';
|
|
19
|
+
import { type DTVariant } from '../utils/variantColors';
|
|
20
|
+
interface DTDrawerProps {
|
|
21
|
+
/**
|
|
22
|
+
* Whether the drawer is visible
|
|
23
|
+
*/
|
|
24
|
+
visible: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Called when the drawer is dismissed
|
|
27
|
+
*/
|
|
28
|
+
onDismiss: () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Heading text in the drawer header bar
|
|
31
|
+
*/
|
|
32
|
+
heading: string;
|
|
33
|
+
/**
|
|
34
|
+
* Visual variant for the header bar
|
|
35
|
+
* @default 'emphasis'
|
|
36
|
+
*/
|
|
37
|
+
headingVariant?: DTVariant;
|
|
38
|
+
/**
|
|
39
|
+
* Which side the drawer slides from
|
|
40
|
+
* @default 'right'
|
|
41
|
+
*/
|
|
42
|
+
position?: 'right' | 'left';
|
|
43
|
+
/**
|
|
44
|
+
* Drawer panel width in pixels
|
|
45
|
+
* @default 400
|
|
46
|
+
*/
|
|
47
|
+
width?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Bevel size in pixels
|
|
50
|
+
* @default 32
|
|
51
|
+
*/
|
|
52
|
+
bevelSize?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Border width in pixels
|
|
55
|
+
* @default 2
|
|
56
|
+
*/
|
|
57
|
+
borderWidth?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Drawer content
|
|
60
|
+
*/
|
|
61
|
+
children: React.ReactNode;
|
|
62
|
+
/**
|
|
63
|
+
* Additional styles
|
|
64
|
+
*/
|
|
65
|
+
style?: StyleProp<ViewStyle>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* DT-styled Drawer/Aside with beveled edges and slide animation
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* <DTDrawer visible={cartOpen} onDismiss={() => setCartOpen(false)} heading="Cart">
|
|
72
|
+
* <CartItems />
|
|
73
|
+
* </DTDrawer>
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* <DTDrawer visible={menuOpen} onDismiss={close} heading="Menu" position="left">
|
|
77
|
+
* <MenuItems />
|
|
78
|
+
* </DTDrawer>
|
|
79
|
+
*/
|
|
80
|
+
export declare function DTDrawer({ visible, onDismiss, heading, headingVariant, position, width: drawerWidth, bevelSize, borderWidth, children, style, }: DTDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=DTDrawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTDrawer.d.ts","sourceRoot":"","sources":["../../src/components/DTDrawer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAGL,SAAS,EACT,SAAS,EAMV,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,wBAAwB,CAAC;AAGvE,UAAU,aAAa;IACrB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,SAAS,EACT,OAAO,EACP,cAA2B,EAC3B,QAAkB,EAClB,KAAK,EAAE,WAAiB,EACxB,SAAc,EACd,WAAe,EACf,QAAQ,EACR,KAAK,GACN,EAAE,aAAa,2CA6Hf"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* DT Drawer Component
|
|
4
|
+
*
|
|
5
|
+
* Hybrid component: RNP Portal for layering + custom Animated panel
|
|
6
|
+
* for the sliding behavior. RNP has no sliding panel component.
|
|
7
|
+
*
|
|
8
|
+
* Uses the dual-SVG-path technique (outer border fill + inner dark fill)
|
|
9
|
+
* consistent with DTCard/DTMediaFrame for proper visual clipping at
|
|
10
|
+
* beveled corners.
|
|
11
|
+
*
|
|
12
|
+
* Web CSS reference (Aside.tsx):
|
|
13
|
+
* - Fixed sidebar sliding from right
|
|
14
|
+
* - Beveled left edges (top-left + bottom-left for right drawer)
|
|
15
|
+
* - Colored header bar
|
|
16
|
+
* - Overlay backdrop
|
|
17
|
+
* - transition: transform 200ms ease-in-out
|
|
18
|
+
*/
|
|
19
|
+
import { useRef, useEffect } from 'react';
|
|
20
|
+
import { StyleSheet, View, Pressable, Animated, BackHandler, ScrollView, useWindowDimensions, } from 'react-native';
|
|
21
|
+
import { Portal, Text } from 'react-native-paper';
|
|
22
|
+
import Svg, { Path } from 'react-native-svg';
|
|
23
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
24
|
+
import { DTColors } from '../theme/colors';
|
|
25
|
+
import { getVariantColor } from '../utils/variantColors';
|
|
26
|
+
import { buildDrawerBevelPath } from '../utils/bevelPaths';
|
|
27
|
+
/**
|
|
28
|
+
* DT-styled Drawer/Aside with beveled edges and slide animation
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* <DTDrawer visible={cartOpen} onDismiss={() => setCartOpen(false)} heading="Cart">
|
|
32
|
+
* <CartItems />
|
|
33
|
+
* </DTDrawer>
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* <DTDrawer visible={menuOpen} onDismiss={close} heading="Menu" position="left">
|
|
37
|
+
* <MenuItems />
|
|
38
|
+
* </DTDrawer>
|
|
39
|
+
*/
|
|
40
|
+
export function DTDrawer({ visible, onDismiss, heading, headingVariant = 'emphasis', position = 'right', width: drawerWidth = 400, bevelSize = 32, borderWidth = 2, children, style, }) {
|
|
41
|
+
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
42
|
+
const overlayAnim = useRef(new Animated.Value(0)).current;
|
|
43
|
+
const headerColor = getVariantColor(headingVariant);
|
|
44
|
+
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
|
|
45
|
+
const insets = useSafeAreaInsets();
|
|
46
|
+
const effectiveWidth = Math.min(drawerWidth, screenWidth);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (visible) {
|
|
49
|
+
Animated.parallel([
|
|
50
|
+
Animated.timing(slideAnim, {
|
|
51
|
+
toValue: 1,
|
|
52
|
+
duration: 200,
|
|
53
|
+
useNativeDriver: true,
|
|
54
|
+
}),
|
|
55
|
+
Animated.timing(overlayAnim, {
|
|
56
|
+
toValue: 1,
|
|
57
|
+
duration: 200,
|
|
58
|
+
useNativeDriver: true,
|
|
59
|
+
}),
|
|
60
|
+
]).start();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
Animated.parallel([
|
|
64
|
+
Animated.timing(slideAnim, {
|
|
65
|
+
toValue: 0,
|
|
66
|
+
duration: 200,
|
|
67
|
+
useNativeDriver: true,
|
|
68
|
+
}),
|
|
69
|
+
Animated.timing(overlayAnim, {
|
|
70
|
+
toValue: 0,
|
|
71
|
+
duration: 200,
|
|
72
|
+
useNativeDriver: true,
|
|
73
|
+
}),
|
|
74
|
+
]).start();
|
|
75
|
+
}
|
|
76
|
+
}, [visible, slideAnim, overlayAnim]);
|
|
77
|
+
// Android back button handling
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!visible)
|
|
80
|
+
return;
|
|
81
|
+
const handler = BackHandler.addEventListener('hardwareBackPress', () => {
|
|
82
|
+
onDismiss();
|
|
83
|
+
return true;
|
|
84
|
+
});
|
|
85
|
+
return () => handler.remove();
|
|
86
|
+
}, [visible, onDismiss]);
|
|
87
|
+
const translateX = slideAnim.interpolate({
|
|
88
|
+
inputRange: [0, 1],
|
|
89
|
+
outputRange: [
|
|
90
|
+
position === 'right' ? effectiveWidth : -effectiveWidth,
|
|
91
|
+
0,
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
// Don't render when fully hidden
|
|
95
|
+
const pointerEvents = visible ? 'auto' : 'none';
|
|
96
|
+
return (_jsx(Portal, { children: _jsxs(View, { style: StyleSheet.absoluteFill, pointerEvents: pointerEvents, children: [_jsx(Animated.View, { style: [StyleSheet.absoluteFill, { opacity: overlayAnim }], children: _jsx(Pressable, { style: [StyleSheet.absoluteFill, styles.overlay], onPress: onDismiss }) }), _jsxs(Animated.View, { style: [
|
|
97
|
+
styles.panel,
|
|
98
|
+
position === 'right' ? styles.panelRight : styles.panelLeft,
|
|
99
|
+
{ width: effectiveWidth, transform: [{ translateX }] },
|
|
100
|
+
style,
|
|
101
|
+
], children: [_jsx(View, { style: StyleSheet.absoluteFill, children: _jsxs(Svg, { width: effectiveWidth, height: screenHeight, children: [_jsx(Path, { d: buildDrawerBevelPath(effectiveWidth, screenHeight, bevelSize, position), fill: headerColor }), _jsx(Path, { d: buildDrawerBevelPath(effectiveWidth - borderWidth * 2, screenHeight - borderWidth * 2, bevelSize - borderWidth, position), fill: DTColors.dark, transform: `translate(${borderWidth}, ${borderWidth})` })] }) }), _jsxs(View, { style: [styles.header, { backgroundColor: headerColor, paddingTop: insets.top + 16 }], children: [_jsx(Text, { style: styles.headerText, children: heading }), _jsx(Pressable, { onPress: onDismiss, style: ({ pressed }) => ({ opacity: pressed ? 0.7 : 1 }), children: _jsx(Text, { style: styles.closeButton, children: "\u2715" }) })] }), _jsx(ScrollView, { style: styles.content, contentContainerStyle: [styles.contentContainer, { paddingBottom: insets.bottom + 16 }], children: children })] })] }) }));
|
|
102
|
+
}
|
|
103
|
+
const styles = StyleSheet.create({
|
|
104
|
+
overlay: {
|
|
105
|
+
backgroundColor: DTColors.overlay,
|
|
106
|
+
},
|
|
107
|
+
panel: {
|
|
108
|
+
position: 'absolute',
|
|
109
|
+
top: 0,
|
|
110
|
+
bottom: 0,
|
|
111
|
+
},
|
|
112
|
+
panelRight: {
|
|
113
|
+
right: 0,
|
|
114
|
+
},
|
|
115
|
+
panelLeft: {
|
|
116
|
+
left: 0,
|
|
117
|
+
},
|
|
118
|
+
header: {
|
|
119
|
+
flexDirection: 'row',
|
|
120
|
+
justifyContent: 'space-between',
|
|
121
|
+
alignItems: 'center',
|
|
122
|
+
paddingHorizontal: 16,
|
|
123
|
+
paddingVertical: 16,
|
|
124
|
+
zIndex: 1,
|
|
125
|
+
},
|
|
126
|
+
headerText: {
|
|
127
|
+
color: DTColors.dark,
|
|
128
|
+
fontWeight: '700',
|
|
129
|
+
fontSize: 18,
|
|
130
|
+
letterSpacing: 0.5,
|
|
131
|
+
},
|
|
132
|
+
closeButton: {
|
|
133
|
+
color: DTColors.dark,
|
|
134
|
+
fontSize: 20,
|
|
135
|
+
fontWeight: '700',
|
|
136
|
+
paddingHorizontal: 8,
|
|
137
|
+
},
|
|
138
|
+
content: {
|
|
139
|
+
flex: 1,
|
|
140
|
+
zIndex: 1,
|
|
141
|
+
},
|
|
142
|
+
contentContainer: {
|
|
143
|
+
padding: 16,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=DTDrawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTDrawer.js","sourceRoot":"","sources":["../../src/components/DTDrawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DT Gallery Component
|
|
3
|
+
*
|
|
4
|
+
* Custom-built image gallery with thumbnail navigation following
|
|
5
|
+
* the Dangerous Things design language. No RNP equivalent.
|
|
6
|
+
*
|
|
7
|
+
* Uses the dual-SVG-path technique for the main image frame,
|
|
8
|
+
* consistent with DTCard/DTMediaFrame.
|
|
9
|
+
*
|
|
10
|
+
* Web CSS reference (CyberGallery):
|
|
11
|
+
* - Horizontal thumbnail strip with arrow navigation
|
|
12
|
+
* - Active thumbnail with glow effect (box-shadow: 0 0 8px)
|
|
13
|
+
* - Beveled arrow buttons
|
|
14
|
+
* - Main image in beveled media frame
|
|
15
|
+
*/
|
|
16
|
+
import { ViewStyle, StyleProp } from 'react-native';
|
|
17
|
+
import { type DTVariant } from '../utils/variantColors';
|
|
18
|
+
export interface DTGalleryItem {
|
|
19
|
+
/**
|
|
20
|
+
* Unique identifier
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
/**
|
|
24
|
+
* Image URI
|
|
25
|
+
*/
|
|
26
|
+
uri: string;
|
|
27
|
+
/**
|
|
28
|
+
* Accessibility label
|
|
29
|
+
*/
|
|
30
|
+
alt?: string;
|
|
31
|
+
}
|
|
32
|
+
interface DTGalleryProps {
|
|
33
|
+
/**
|
|
34
|
+
* Gallery items
|
|
35
|
+
*/
|
|
36
|
+
items: DTGalleryItem[];
|
|
37
|
+
/**
|
|
38
|
+
* Currently active item index
|
|
39
|
+
*/
|
|
40
|
+
activeIndex: number;
|
|
41
|
+
/**
|
|
42
|
+
* Called when an item is selected
|
|
43
|
+
*/
|
|
44
|
+
onSelect: (index: number) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Visual variant
|
|
47
|
+
* @default 'normal'
|
|
48
|
+
*/
|
|
49
|
+
variant?: DTVariant;
|
|
50
|
+
/**
|
|
51
|
+
* Thumbnail size in pixels
|
|
52
|
+
* @default 64
|
|
53
|
+
*/
|
|
54
|
+
thumbnailSize?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Bevel size for the main image frame
|
|
57
|
+
* @default 24
|
|
58
|
+
*/
|
|
59
|
+
bevelSize?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Border width for the main image frame
|
|
62
|
+
* @default 3
|
|
63
|
+
*/
|
|
64
|
+
borderWidth?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Additional styles
|
|
67
|
+
*/
|
|
68
|
+
style?: StyleProp<ViewStyle>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* DT-styled Gallery with thumbnail strip and arrow navigation
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* <DTGallery
|
|
75
|
+
* items={images}
|
|
76
|
+
* activeIndex={activeIdx}
|
|
77
|
+
* onSelect={setActiveIdx}
|
|
78
|
+
* variant="normal"
|
|
79
|
+
* />
|
|
80
|
+
*/
|
|
81
|
+
export declare function DTGallery({ items, activeIndex, onSelect, variant, thumbnailSize, bevelSize, borderWidth, style, }: DTGalleryProps): import("react/jsx-runtime").JSX.Element | null;
|
|
82
|
+
export {};
|
|
83
|
+
//# sourceMappingURL=DTGallery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DTGallery.d.ts","sourceRoot":"","sources":["../../src/components/DTGallery.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAGL,SAAS,EACT,SAAS,EAKV,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,wBAAwB,CAAC;AAIvE,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,cAAc;IACtB;;OAEG;IACH,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,OAAkB,EAClB,aAAkB,EAClB,SAAc,EACd,WAAe,EACf,KAAK,GACN,EAAE,cAAc,kDA6MhB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* DT Gallery Component
|
|
4
|
+
*
|
|
5
|
+
* Custom-built image gallery with thumbnail navigation following
|
|
6
|
+
* the Dangerous Things design language. No RNP equivalent.
|
|
7
|
+
*
|
|
8
|
+
* Uses the dual-SVG-path technique for the main image frame,
|
|
9
|
+
* consistent with DTCard/DTMediaFrame.
|
|
10
|
+
*
|
|
11
|
+
* Web CSS reference (CyberGallery):
|
|
12
|
+
* - Horizontal thumbnail strip with arrow navigation
|
|
13
|
+
* - Active thumbnail with glow effect (box-shadow: 0 0 8px)
|
|
14
|
+
* - Beveled arrow buttons
|
|
15
|
+
* - Main image in beveled media frame
|
|
16
|
+
*/
|
|
17
|
+
import { useRef, useCallback } from 'react';
|
|
18
|
+
import { StyleSheet, View, Pressable, Image, FlatList, Platform, } from 'react-native';
|
|
19
|
+
import Svg, { Path } from 'react-native-svg';
|
|
20
|
+
import { DTColors } from '../theme/colors';
|
|
21
|
+
import { getVariantColor } from '../utils/variantColors';
|
|
22
|
+
import { buildButtonBevelPath, buildMediaFrameBevelPath } from '../utils/bevelPaths';
|
|
23
|
+
import { useComponentLayout } from '../utils/useComponentLayout';
|
|
24
|
+
const ARROW_SIZE = 32;
|
|
25
|
+
const ARROW_BEVEL = 4;
|
|
26
|
+
const ARROW_BORDER = 2;
|
|
27
|
+
/**
|
|
28
|
+
* DT-styled Gallery with thumbnail strip and arrow navigation
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* <DTGallery
|
|
32
|
+
* items={images}
|
|
33
|
+
* activeIndex={activeIdx}
|
|
34
|
+
* onSelect={setActiveIdx}
|
|
35
|
+
* variant="normal"
|
|
36
|
+
* />
|
|
37
|
+
*/
|
|
38
|
+
export function DTGallery({ items, activeIndex, onSelect, variant = 'normal', thumbnailSize = 64, bevelSize = 24, borderWidth = 3, style, }) {
|
|
39
|
+
const flatListRef = useRef(null);
|
|
40
|
+
const { dimensions, onLayout, hasDimensions } = useComponentLayout();
|
|
41
|
+
const accentColor = getVariantColor(variant);
|
|
42
|
+
const atStart = activeIndex <= 0;
|
|
43
|
+
const atEnd = activeIndex >= items.length - 1;
|
|
44
|
+
const handlePrev = useCallback(() => {
|
|
45
|
+
if (activeIndex > 0) {
|
|
46
|
+
onSelect(activeIndex - 1);
|
|
47
|
+
}
|
|
48
|
+
}, [activeIndex, onSelect]);
|
|
49
|
+
const handleNext = useCallback(() => {
|
|
50
|
+
if (activeIndex < items.length - 1) {
|
|
51
|
+
onSelect(activeIndex + 1);
|
|
52
|
+
}
|
|
53
|
+
}, [activeIndex, items.length, onSelect]);
|
|
54
|
+
const scrollToActive = useCallback((index) => {
|
|
55
|
+
flatListRef.current?.scrollToIndex({
|
|
56
|
+
index,
|
|
57
|
+
animated: true,
|
|
58
|
+
viewPosition: 0.5,
|
|
59
|
+
});
|
|
60
|
+
}, []);
|
|
61
|
+
const handleSelect = useCallback((index) => {
|
|
62
|
+
onSelect(index);
|
|
63
|
+
scrollToActive(index);
|
|
64
|
+
}, [onSelect, scrollToActive]);
|
|
65
|
+
const getItemLayout = useCallback((_, index) => ({
|
|
66
|
+
length: thumbnailSize + 8,
|
|
67
|
+
offset: (thumbnailSize + 8) * index,
|
|
68
|
+
index,
|
|
69
|
+
}), [thumbnailSize]);
|
|
70
|
+
const renderArrow = (direction, onPress, isDisabled) => {
|
|
71
|
+
const center = ARROW_SIZE / 2;
|
|
72
|
+
const arrowSize = ARROW_SIZE * 0.2;
|
|
73
|
+
const iconPath = direction === 'left'
|
|
74
|
+
? `M ${center + arrowSize} ${center - arrowSize} L ${center - arrowSize} ${center} L ${center + arrowSize} ${center + arrowSize}`
|
|
75
|
+
: `M ${center - arrowSize} ${center - arrowSize} L ${center + arrowSize} ${center} L ${center - arrowSize} ${center + arrowSize}`;
|
|
76
|
+
return (_jsx(Pressable, { onPress: onPress, disabled: isDisabled, style: ({ pressed }) => ({
|
|
77
|
+
opacity: isDisabled ? 0.3 : pressed ? 0.7 : 1,
|
|
78
|
+
}), children: _jsxs(Svg, { width: ARROW_SIZE, height: ARROW_SIZE, viewBox: `0 0 ${ARROW_SIZE} ${ARROW_SIZE}`, children: [_jsx(Path, { d: buildButtonBevelPath(ARROW_SIZE, ARROW_SIZE, ARROW_BEVEL, ARROW_BORDER), fill: "transparent", stroke: accentColor, strokeWidth: ARROW_BORDER }), _jsx(Path, { d: iconPath, fill: "none", stroke: accentColor, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" })] }) }));
|
|
79
|
+
};
|
|
80
|
+
const renderThumbnail = ({ item, index }) => {
|
|
81
|
+
const isActive = index === activeIndex;
|
|
82
|
+
return (_jsx(Pressable, { onPress: () => handleSelect(index), style: ({ pressed }) => ({ opacity: pressed ? 0.7 : 1 }), children: _jsxs(View, { style: [
|
|
83
|
+
styles.thumbnail,
|
|
84
|
+
{
|
|
85
|
+
width: thumbnailSize,
|
|
86
|
+
height: thumbnailSize,
|
|
87
|
+
borderColor: isActive ? accentColor : 'transparent',
|
|
88
|
+
},
|
|
89
|
+
isActive && styles.thumbnailActive,
|
|
90
|
+
], children: [isActive && Platform.OS === 'android' && (_jsx(View, { style: [
|
|
91
|
+
StyleSheet.absoluteFill,
|
|
92
|
+
{
|
|
93
|
+
borderWidth: 3,
|
|
94
|
+
borderColor: accentColor,
|
|
95
|
+
opacity: 0.5,
|
|
96
|
+
margin: -3,
|
|
97
|
+
},
|
|
98
|
+
] })), _jsx(Image, { source: { uri: item.uri }, style: styles.thumbnailImage, accessibilityLabel: item.alt, resizeMode: "cover" })] }) }));
|
|
99
|
+
};
|
|
100
|
+
if (items.length === 0)
|
|
101
|
+
return null;
|
|
102
|
+
const { width, height } = dimensions;
|
|
103
|
+
// Outer and inner bevel paths for frame overlay
|
|
104
|
+
const outerPath = hasDimensions
|
|
105
|
+
? buildMediaFrameBevelPath(width, height, bevelSize)
|
|
106
|
+
: '';
|
|
107
|
+
const innerPath = hasDimensions
|
|
108
|
+
? buildMediaFrameBevelPath(width, height, bevelSize - borderWidth, borderWidth)
|
|
109
|
+
: '';
|
|
110
|
+
return (_jsxs(View, { style: [styles.container, style], children: [_jsxs(View, { style: styles.mainImageContainer, onLayout: onLayout, children: [hasDimensions && (_jsx(Svg, { style: StyleSheet.absoluteFill, width: width, height: height, viewBox: `0 0 ${width} ${height}`, children: _jsx(Path, { d: innerPath, fill: DTColors.surfaceVariant }) })), _jsx(View, { style: [styles.mainImageContent, { padding: borderWidth }], children: _jsx(Image, { source: { uri: items[activeIndex]?.uri }, style: styles.mainImage, accessibilityLabel: items[activeIndex]?.alt, resizeMode: "contain" }) }), hasDimensions && (_jsxs(Svg, { style: [StyleSheet.absoluteFill, styles.frameOverlay], width: width, height: height, viewBox: `0 0 ${width} ${height}`, pointerEvents: "none", children: [_jsx(Path, { d: `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z ` + outerPath, fillRule: "evenodd", fill: DTColors.dark }), _jsx(Path, { d: outerPath + ' ' + innerPath, fillRule: "evenodd", fill: accentColor })] }))] }), items.length > 1 && (_jsxs(View, { style: styles.thumbnailStrip, children: [renderArrow('left', handlePrev, atStart), _jsx(FlatList, { ref: flatListRef, data: items, renderItem: renderThumbnail, keyExtractor: item => item.id, horizontal: true, showsHorizontalScrollIndicator: false, getItemLayout: getItemLayout, contentContainerStyle: styles.thumbnailList, style: styles.thumbnailFlatList, initialNumToRender: 8, maxToRenderPerBatch: 4, windowSize: 5, removeClippedSubviews: Platform.OS === 'android' }), renderArrow('right', handleNext, atEnd)] }))] }));
|
|
111
|
+
}
|
|
112
|
+
const styles = StyleSheet.create({
|
|
113
|
+
container: {
|
|
114
|
+
gap: 12,
|
|
115
|
+
},
|
|
116
|
+
mainImageContainer: {
|
|
117
|
+
aspectRatio: 1,
|
|
118
|
+
position: 'relative',
|
|
119
|
+
},
|
|
120
|
+
mainImageContent: {
|
|
121
|
+
position: 'relative',
|
|
122
|
+
zIndex: 1,
|
|
123
|
+
flex: 1,
|
|
124
|
+
overflow: 'hidden',
|
|
125
|
+
},
|
|
126
|
+
mainImage: {
|
|
127
|
+
flex: 1,
|
|
128
|
+
},
|
|
129
|
+
thumbnailStrip: {
|
|
130
|
+
flexDirection: 'row',
|
|
131
|
+
alignItems: 'center',
|
|
132
|
+
gap: 8,
|
|
133
|
+
},
|
|
134
|
+
thumbnailFlatList: {
|
|
135
|
+
flex: 1,
|
|
136
|
+
},
|
|
137
|
+
thumbnailList: {
|
|
138
|
+
gap: 8,
|
|
139
|
+
},
|
|
140
|
+
thumbnail: {
|
|
141
|
+
borderWidth: 2,
|
|
142
|
+
overflow: 'hidden',
|
|
143
|
+
},
|
|
144
|
+
thumbnailActive: {
|
|
145
|
+
...Platform.select({
|
|
146
|
+
ios: {
|
|
147
|
+
shadowOffset: { width: 0, height: 0 },
|
|
148
|
+
shadowOpacity: 0.8,
|
|
149
|
+
shadowRadius: 8,
|
|
150
|
+
},
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
thumbnailImage: {
|
|
154
|
+
flex: 1,
|
|
155
|
+
},
|
|
156
|
+
frameOverlay: {
|
|
157
|
+
zIndex: 2,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=DTGallery.js.map
|