@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.
Files changed (105) hide show
  1. package/dist/components/DTAccordion.d.ts +75 -0
  2. package/dist/components/DTAccordion.d.ts.map +1 -0
  3. package/dist/components/DTAccordion.js +147 -0
  4. package/dist/components/DTAccordion.js.map +1 -0
  5. package/dist/components/DTButton.d.ts +68 -0
  6. package/dist/components/DTButton.d.ts.map +1 -0
  7. package/dist/components/DTButton.js +59 -0
  8. package/dist/components/DTButton.js.map +1 -0
  9. package/dist/components/DTCard.d.ts +97 -0
  10. package/dist/components/DTCard.d.ts.map +1 -0
  11. package/dist/components/DTCard.js +81 -0
  12. package/dist/components/DTCard.js.map +1 -0
  13. package/dist/components/DTCheckbox.d.ts +63 -0
  14. package/dist/components/DTCheckbox.d.ts.map +1 -0
  15. package/dist/components/DTCheckbox.js +55 -0
  16. package/dist/components/DTCheckbox.js.map +1 -0
  17. package/dist/components/DTChip.d.ts +40 -0
  18. package/dist/components/DTChip.d.ts.map +1 -0
  19. package/dist/components/DTChip.js +55 -0
  20. package/dist/components/DTChip.js.map +1 -0
  21. package/dist/components/DTDrawer.d.ts +82 -0
  22. package/dist/components/DTDrawer.d.ts.map +1 -0
  23. package/dist/components/DTDrawer.js +146 -0
  24. package/dist/components/DTDrawer.js.map +1 -0
  25. package/dist/components/DTGallery.d.ts +83 -0
  26. package/dist/components/DTGallery.d.ts.map +1 -0
  27. package/dist/components/DTGallery.js +160 -0
  28. package/dist/components/DTGallery.js.map +1 -0
  29. package/dist/components/DTHexagon.d.ts +81 -0
  30. package/dist/components/DTHexagon.d.ts.map +1 -0
  31. package/dist/components/DTHexagon.js +110 -0
  32. package/dist/components/DTHexagon.js.map +1 -0
  33. package/dist/components/DTLabel.d.ts +100 -0
  34. package/dist/components/DTLabel.d.ts.map +1 -0
  35. package/dist/components/DTLabel.js +189 -0
  36. package/dist/components/DTLabel.js.map +1 -0
  37. package/dist/components/DTMediaFrame.d.ts +77 -0
  38. package/dist/components/DTMediaFrame.d.ts.map +1 -0
  39. package/dist/components/DTMediaFrame.js +84 -0
  40. package/dist/components/DTMediaFrame.js.map +1 -0
  41. package/dist/components/DTMenu.d.ts +119 -0
  42. package/dist/components/DTMenu.d.ts.map +1 -0
  43. package/dist/components/DTMenu.js +188 -0
  44. package/dist/components/DTMenu.js.map +1 -0
  45. package/dist/components/DTModal.d.ts +64 -0
  46. package/dist/components/DTModal.d.ts.map +1 -0
  47. package/dist/components/DTModal.js +45 -0
  48. package/dist/components/DTModal.js.map +1 -0
  49. package/dist/components/DTProgressBar.d.ts +66 -0
  50. package/dist/components/DTProgressBar.d.ts.map +1 -0
  51. package/dist/components/DTProgressBar.js +82 -0
  52. package/dist/components/DTProgressBar.js.map +1 -0
  53. package/dist/components/DTQuantityStepper.d.ts +76 -0
  54. package/dist/components/DTQuantityStepper.d.ts.map +1 -0
  55. package/dist/components/DTQuantityStepper.js +108 -0
  56. package/dist/components/DTQuantityStepper.js.map +1 -0
  57. package/dist/components/DTRadioGroup.d.ts +79 -0
  58. package/dist/components/DTRadioGroup.d.ts.map +1 -0
  59. package/dist/components/DTRadioGroup.js +107 -0
  60. package/dist/components/DTRadioGroup.js.map +1 -0
  61. package/dist/components/DTSearchInput.d.ts +72 -0
  62. package/dist/components/DTSearchInput.d.ts.map +1 -0
  63. package/dist/components/DTSearchInput.js +71 -0
  64. package/dist/components/DTSearchInput.js.map +1 -0
  65. package/dist/components/DTSwitch.d.ts +52 -0
  66. package/dist/components/DTSwitch.d.ts.map +1 -0
  67. package/dist/components/DTSwitch.js +85 -0
  68. package/dist/components/DTSwitch.js.map +1 -0
  69. package/dist/components/DTTextInput.d.ts +58 -0
  70. package/dist/components/DTTextInput.d.ts.map +1 -0
  71. package/dist/components/DTTextInput.js +85 -0
  72. package/dist/components/DTTextInput.js.map +1 -0
  73. package/dist/index.d.ts +40 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +40 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/theme/DTThemeProvider.d.ts +49 -0
  78. package/dist/theme/DTThemeProvider.d.ts.map +1 -0
  79. package/dist/theme/DTThemeProvider.js +52 -0
  80. package/dist/theme/DTThemeProvider.js.map +1 -0
  81. package/dist/theme/colors.d.ts +42 -0
  82. package/dist/theme/colors.d.ts.map +1 -0
  83. package/dist/theme/colors.js +59 -0
  84. package/dist/theme/colors.js.map +1 -0
  85. package/dist/theme/paperTheme.d.ts +39 -0
  86. package/dist/theme/paperTheme.d.ts.map +1 -0
  87. package/dist/theme/paperTheme.js +116 -0
  88. package/dist/theme/paperTheme.js.map +1 -0
  89. package/dist/theme/typography.d.ts +57 -0
  90. package/dist/theme/typography.d.ts.map +1 -0
  91. package/dist/theme/typography.js +170 -0
  92. package/dist/theme/typography.js.map +1 -0
  93. package/dist/utils/bevelPaths.d.ts +42 -0
  94. package/dist/utils/bevelPaths.d.ts.map +1 -0
  95. package/dist/utils/bevelPaths.js +105 -0
  96. package/dist/utils/bevelPaths.js.map +1 -0
  97. package/dist/utils/useComponentLayout.d.ts +18 -0
  98. package/dist/utils/useComponentLayout.d.ts.map +1 -0
  99. package/dist/utils/useComponentLayout.js +24 -0
  100. package/dist/utils/useComponentLayout.js.map +1 -0
  101. package/dist/utils/variantColors.d.ts +12 -0
  102. package/dist/utils/variantColors.d.ts.map +1 -0
  103. package/dist/utils/variantColors.js +20 -0
  104. package/dist/utils/variantColors.js.map +1 -0
  105. 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