@echoform/echo-ui 0.1.0 → 0.2.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 (154) hide show
  1. package/README.md +57 -10
  2. package/dist/components/EchoChangeProfileNameModal.d.ts +59 -0
  3. package/dist/components/EchoChangeProfileNameModal.d.ts.map +1 -0
  4. package/dist/components/EchoChangeProfileNameModal.js +317 -0
  5. package/dist/components/EchoChangeProfileNameModal.js.map +1 -0
  6. package/dist/components/EchoColorPicker.d.ts +34 -0
  7. package/dist/components/EchoColorPicker.d.ts.map +1 -0
  8. package/dist/components/EchoColorPicker.js +206 -0
  9. package/dist/components/EchoColorPicker.js.map +1 -0
  10. package/dist/components/EchoConnectedAppsModal.d.ts +40 -0
  11. package/dist/components/EchoConnectedAppsModal.d.ts.map +1 -0
  12. package/dist/components/EchoConnectedAppsModal.js +220 -0
  13. package/dist/components/EchoConnectedAppsModal.js.map +1 -0
  14. package/dist/components/EchoDeleteProfilePanel.d.ts +63 -0
  15. package/dist/components/EchoDeleteProfilePanel.d.ts.map +1 -0
  16. package/dist/components/EchoDeleteProfilePanel.js +286 -0
  17. package/dist/components/EchoDeleteProfilePanel.js.map +1 -0
  18. package/dist/components/EchoDeletionIntercept.d.ts +39 -0
  19. package/dist/components/EchoDeletionIntercept.d.ts.map +1 -0
  20. package/dist/components/EchoDeletionIntercept.js +212 -0
  21. package/dist/components/EchoDeletionIntercept.js.map +1 -0
  22. package/dist/components/EchoDeletionStatusCard.d.ts +35 -0
  23. package/dist/components/EchoDeletionStatusCard.d.ts.map +1 -0
  24. package/dist/components/EchoDeletionStatusCard.js +156 -0
  25. package/dist/components/EchoDeletionStatusCard.js.map +1 -0
  26. package/dist/components/EchoEmblem.d.ts +93 -0
  27. package/dist/components/EchoEmblem.d.ts.map +1 -0
  28. package/dist/components/EchoEmblem.js +308 -0
  29. package/dist/components/EchoEmblem.js.map +1 -0
  30. package/dist/components/EchoEmblemPicker.d.ts +71 -0
  31. package/dist/components/EchoEmblemPicker.d.ts.map +1 -0
  32. package/dist/components/EchoEmblemPicker.js +490 -0
  33. package/dist/components/EchoEmblemPicker.js.map +1 -0
  34. package/dist/components/EchoErrorBanner.d.ts +17 -0
  35. package/dist/components/EchoErrorBanner.d.ts.map +1 -0
  36. package/dist/components/EchoErrorBanner.js +48 -0
  37. package/dist/components/EchoErrorBanner.js.map +1 -0
  38. package/dist/components/EchoFormField.d.ts +27 -0
  39. package/dist/components/EchoFormField.d.ts.map +1 -0
  40. package/dist/components/EchoFormField.js +49 -0
  41. package/dist/components/EchoFormField.js.map +1 -0
  42. package/dist/components/EchoLinkButton.d.ts +16 -0
  43. package/dist/components/EchoLinkButton.d.ts.map +1 -0
  44. package/dist/components/EchoLinkButton.js +37 -0
  45. package/dist/components/EchoLinkButton.js.map +1 -0
  46. package/dist/components/EchoMoreScreen.d.ts +41 -0
  47. package/dist/components/EchoMoreScreen.d.ts.map +1 -0
  48. package/dist/components/EchoMoreScreen.js +94 -0
  49. package/dist/components/EchoMoreScreen.js.map +1 -0
  50. package/dist/components/EchoPasswordField.d.ts +28 -0
  51. package/dist/components/EchoPasswordField.d.ts.map +1 -0
  52. package/dist/components/EchoPasswordField.js +67 -0
  53. package/dist/components/EchoPasswordField.js.map +1 -0
  54. package/dist/components/EchoPrimaryButton.d.ts +23 -0
  55. package/dist/components/EchoPrimaryButton.d.ts.map +1 -0
  56. package/dist/components/EchoPrimaryButton.js +54 -0
  57. package/dist/components/EchoPrimaryButton.js.map +1 -0
  58. package/dist/components/EchoProfileCard.d.ts +35 -0
  59. package/dist/components/EchoProfileCard.d.ts.map +1 -0
  60. package/dist/components/EchoProfileCard.js +206 -0
  61. package/dist/components/EchoProfileCard.js.map +1 -0
  62. package/dist/components/EchoProfileDivider.d.ts +14 -0
  63. package/dist/components/EchoProfileDivider.d.ts.map +1 -0
  64. package/dist/components/EchoProfileDivider.js +31 -0
  65. package/dist/components/EchoProfileDivider.js.map +1 -0
  66. package/dist/components/EchoProfileHero.d.ts +48 -0
  67. package/dist/components/EchoProfileHero.d.ts.map +1 -0
  68. package/dist/components/EchoProfileHero.js +215 -0
  69. package/dist/components/EchoProfileHero.js.map +1 -0
  70. package/dist/components/EchoProfileOverview.d.ts +18 -0
  71. package/dist/components/EchoProfileOverview.d.ts.map +1 -0
  72. package/dist/components/EchoProfileOverview.js +36 -0
  73. package/dist/components/EchoProfileOverview.js.map +1 -0
  74. package/dist/components/EchoProfileRow.d.ts +60 -0
  75. package/dist/components/EchoProfileRow.d.ts.map +1 -0
  76. package/dist/components/EchoProfileRow.js +113 -0
  77. package/dist/components/EchoProfileRow.js.map +1 -0
  78. package/dist/components/EchoProfileSection.d.ts +29 -0
  79. package/dist/components/EchoProfileSection.d.ts.map +1 -0
  80. package/dist/components/EchoProfileSection.js +58 -0
  81. package/dist/components/EchoProfileSection.js.map +1 -0
  82. package/dist/components/EchoRewardNotificationBanner.d.ts +61 -0
  83. package/dist/components/EchoRewardNotificationBanner.d.ts.map +1 -0
  84. package/dist/components/EchoRewardNotificationBanner.js +272 -0
  85. package/dist/components/EchoRewardNotificationBanner.js.map +1 -0
  86. package/dist/components/EchoSettingsRow.d.ts +24 -0
  87. package/dist/components/EchoSettingsRow.d.ts.map +1 -0
  88. package/dist/components/EchoSettingsRow.js +84 -0
  89. package/dist/components/EchoSettingsRow.js.map +1 -0
  90. package/dist/components/EchoSettingsSection.d.ts +16 -0
  91. package/dist/components/EchoSettingsSection.d.ts.map +1 -0
  92. package/dist/components/EchoSettingsSection.js +48 -0
  93. package/dist/components/EchoSettingsSection.js.map +1 -0
  94. package/dist/components/EchoSignOutButton.d.ts +28 -0
  95. package/dist/components/EchoSignOutButton.d.ts.map +1 -0
  96. package/dist/components/EchoSignOutButton.js +67 -0
  97. package/dist/components/EchoSignOutButton.js.map +1 -0
  98. package/dist/components/EchoSuccessBanner.d.ts +17 -0
  99. package/dist/components/EchoSuccessBanner.d.ts.map +1 -0
  100. package/dist/components/EchoSuccessBanner.js +48 -0
  101. package/dist/components/EchoSuccessBanner.js.map +1 -0
  102. package/dist/components/EchoSyncPanel.d.ts +165 -0
  103. package/dist/components/EchoSyncPanel.d.ts.map +1 -0
  104. package/dist/components/EchoSyncPanel.js +913 -0
  105. package/dist/components/EchoSyncPanel.js.map +1 -0
  106. package/dist/components/EchoSyncPromptModal.d.ts +87 -0
  107. package/dist/components/EchoSyncPromptModal.d.ts.map +1 -0
  108. package/dist/components/EchoSyncPromptModal.js +351 -0
  109. package/dist/components/EchoSyncPromptModal.js.map +1 -0
  110. package/dist/components/EchoTitlePicker.d.ts +72 -0
  111. package/dist/components/EchoTitlePicker.d.ts.map +1 -0
  112. package/dist/components/EchoTitlePicker.js +487 -0
  113. package/dist/components/EchoTitlePicker.js.map +1 -0
  114. package/dist/components/EchoVerificationCodeInput.d.ts +40 -0
  115. package/dist/components/EchoVerificationCodeInput.d.ts.map +1 -0
  116. package/dist/components/EchoVerificationCodeInput.js +140 -0
  117. package/dist/components/EchoVerificationCodeInput.js.map +1 -0
  118. package/dist/components/EchoWelcome.d.ts +44 -0
  119. package/dist/components/EchoWelcome.d.ts.map +1 -0
  120. package/dist/components/EchoWelcome.js +289 -0
  121. package/dist/components/EchoWelcome.js.map +1 -0
  122. package/dist/components/EchoWhyBecomeAnEchoModal.d.ts +34 -0
  123. package/dist/components/EchoWhyBecomeAnEchoModal.d.ts.map +1 -0
  124. package/dist/components/EchoWhyBecomeAnEchoModal.js +321 -0
  125. package/dist/components/EchoWhyBecomeAnEchoModal.js.map +1 -0
  126. package/dist/components/EchoformInfoButton.d.ts +27 -0
  127. package/dist/components/EchoformInfoButton.d.ts.map +1 -0
  128. package/dist/components/EchoformInfoButton.js +60 -0
  129. package/dist/components/EchoformInfoButton.js.map +1 -0
  130. package/dist/components/EchoformInfoModal.d.ts +63 -0
  131. package/dist/components/EchoformInfoModal.d.ts.map +1 -0
  132. package/dist/components/EchoformInfoModal.js +347 -0
  133. package/dist/components/EchoformInfoModal.js.map +1 -0
  134. package/dist/echoColors.d.ts +58 -0
  135. package/dist/echoColors.d.ts.map +1 -0
  136. package/dist/echoColors.js +94 -0
  137. package/dist/echoColors.js.map +1 -0
  138. package/dist/index.d.ts +71 -3
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js +86 -4
  141. package/dist/index.js.map +1 -1
  142. package/dist/theme.d.ts +48 -0
  143. package/dist/theme.d.ts.map +1 -0
  144. package/dist/theme.js +51 -0
  145. package/dist/theme.js.map +1 -0
  146. package/dist/titleRarity.d.ts +19 -0
  147. package/dist/titleRarity.d.ts.map +1 -0
  148. package/dist/titleRarity.js +46 -0
  149. package/dist/titleRarity.js.map +1 -0
  150. package/package.json +6 -5
  151. package/dist/components/EchoUITest.d.ts +0 -14
  152. package/dist/components/EchoUITest.d.ts.map +0 -1
  153. package/dist/components/EchoUITest.js +0 -53
  154. package/dist/components/EchoUITest.js.map +0 -1
@@ -0,0 +1,60 @@
1
+ /**
2
+ * EchoProfileRow
3
+ *
4
+ * Presentation-only profile row used throughout the signed-in Echo Profile screen.
5
+ * Extracted from the Echo UI Reference profileRow pattern.
6
+ *
7
+ * Supports an image or Material icon in a 52×52 icon wrapper, title/value
8
+ * typography, optional chevron, pressed state, and both button and text roles.
9
+ *
10
+ * The `loading` prop replaces the value text with a small ActivityIndicator,
11
+ * covering the Echo Coins loading state and similar cases.
12
+ *
13
+ * ACCESSIBILITY
14
+ * ─────────────
15
+ * • `accessibilityRole="button"` when `onPress` is provided.
16
+ * • `accessibilityRole="text"` when non-actionable.
17
+ * • All decorative image/icon content is hidden from screen readers.
18
+ * • The `accessibilityLabel` prop is always required so the host controls
19
+ * the exact announcement without business meaning leaking into this component.
20
+ *
21
+ * No Expo Router, no auth, no contexts, no services, no app-specific code.
22
+ * Canonical shared component for @echoform/echo-ui.
23
+ */
24
+ import React from 'react';
25
+ import type { ImageSource } from 'expo-image';
26
+ export type EchoProfileRowProps = {
27
+ /** Uppercase row category label, e.g. "ECHO PROFILE NAME". */
28
+ title: string;
29
+ /** Value text displayed below the title. Hidden when `loading` is true. */
30
+ value?: string | null;
31
+ /** Optional color override for the value text. */
32
+ valueColor?: string;
33
+ /** expo-image ImageSource for the left icon slot. */
34
+ imageSource?: ImageSource | null;
35
+ /** Size of the rendered image inside the icon wrapper. Defaults to 44. */
36
+ imageSize?: number;
37
+ /** Background color of the 52×52 icon wrapper. */
38
+ iconBackgroundColor?: string;
39
+ /** Material icon name, used when no imageSource is provided. */
40
+ materialIcon?: string;
41
+ /** Color for the materialIcon. Defaults to COLORS.neonCyan. */
42
+ materialIconColor?: string;
43
+ /** When provided, the row becomes a pressable button. */
44
+ onPress?: () => void;
45
+ /** Required: announcement text for VoiceOver / TalkBack. */
46
+ accessibilityLabel: string;
47
+ /** Optional hint appended after the label. */
48
+ accessibilityHint?: string;
49
+ /** When true, shows a spinner in place of the value text. */
50
+ loading?: boolean;
51
+ /** Color of the loading spinner. Defaults to COLORS.textMuted. */
52
+ loadingColor?: string;
53
+ /**
54
+ * When true, shows a right-side chevron.
55
+ * Defaults to `true` when `onPress` is provided, `false` otherwise.
56
+ */
57
+ showChevron?: boolean;
58
+ };
59
+ export declare function EchoProfileRow({ title, value, valueColor, imageSource, imageSize, iconBackgroundColor, materialIcon, materialIconColor, onPress, accessibilityLabel, accessibilityHint, loading, loadingColor, showChevron, }: EchoProfileRowProps): React.JSX.Element;
60
+ //# sourceMappingURL=EchoProfileRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoProfileRow.d.ts","sourceRoot":"","sources":["../../src/components/EchoProfileRow.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQ9C,MAAM,MAAM,mBAAmB,GAAG;IAChC,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,4DAA4D;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAMF,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,UAAU,EACV,WAAW,EACX,SAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,iBAAmC,EACnC,OAAO,EACP,kBAAkB,EAClB,iBAAiB,EACjB,OAAe,EACf,YAA+B,EAC/B,WAAW,GACZ,EAAE,mBAAmB,qBAoGrB"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * EchoProfileRow
4
+ *
5
+ * Presentation-only profile row used throughout the signed-in Echo Profile screen.
6
+ * Extracted from the Echo UI Reference profileRow pattern.
7
+ *
8
+ * Supports an image or Material icon in a 52×52 icon wrapper, title/value
9
+ * typography, optional chevron, pressed state, and both button and text roles.
10
+ *
11
+ * The `loading` prop replaces the value text with a small ActivityIndicator,
12
+ * covering the Echo Coins loading state and similar cases.
13
+ *
14
+ * ACCESSIBILITY
15
+ * ─────────────
16
+ * • `accessibilityRole="button"` when `onPress` is provided.
17
+ * • `accessibilityRole="text"` when non-actionable.
18
+ * • All decorative image/icon content is hidden from screen readers.
19
+ * • The `accessibilityLabel` prop is always required so the host controls
20
+ * the exact announcement without business meaning leaking into this component.
21
+ *
22
+ * No Expo Router, no auth, no contexts, no services, no app-specific code.
23
+ * Canonical shared component for @echoform/echo-ui.
24
+ */
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.EchoProfileRow = EchoProfileRow;
30
+ const react_1 = __importDefault(require("react"));
31
+ const react_native_1 = require("react-native");
32
+ const expo_image_1 = require("expo-image");
33
+ const vector_icons_1 = require("@expo/vector-icons");
34
+ const theme_1 = require("../theme");
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+ // Component
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ function EchoProfileRow({ title, value, valueColor, imageSource, imageSize = 44, iconBackgroundColor, materialIcon, materialIconColor = theme_1.COLORS.neonCyan, onPress, accessibilityLabel, accessibilityHint, loading = false, loadingColor = theme_1.COLORS.textMuted, showChevron, }) {
39
+ const chevron = showChevron !== undefined ? showChevron : !!onPress;
40
+ // ── Icon slot ─────────────────────────────────────────────────────────────
41
+ const iconSlot = (<react_native_1.View style={[
42
+ styles.iconWrapper,
43
+ iconBackgroundColor ? { backgroundColor: iconBackgroundColor } : null,
44
+ ]} importantForAccessibility="no" accessibilityElementsHidden>
45
+ {imageSource ? (<expo_image_1.Image source={imageSource} style={{ width: imageSize, height: imageSize }} contentFit="contain" importantForAccessibility="no" accessibilityElementsHidden/>) : materialIcon ? (<vector_icons_1.MaterialIcons name={materialIcon} size={18} color={materialIconColor} importantForAccessibility="no" accessibilityElementsHidden/>) : null}
46
+ </react_native_1.View>);
47
+ // ── Content ───────────────────────────────────────────────────────────────
48
+ const content = (<>
49
+ {iconSlot}
50
+ <react_native_1.View style={styles.textArea}>
51
+ <react_native_1.Text style={styles.rowTitle} importantForAccessibility="no" accessibilityElementsHidden>
52
+ {title}
53
+ </react_native_1.Text>
54
+ {loading ? (<react_native_1.ActivityIndicator size="small" color={loadingColor} style={styles.loadingIndicator} importantForAccessibility="no"/>) : value !== undefined && value !== null ? (<react_native_1.Text style={[styles.rowValue, valueColor ? { color: valueColor } : null]} numberOfLines={1} importantForAccessibility="no" accessibilityElementsHidden>
55
+ {value}
56
+ </react_native_1.Text>) : null}
57
+ </react_native_1.View>
58
+ {chevron ? (<vector_icons_1.MaterialIcons name="chevron-right" size={20} color={theme_1.COLORS.textMuted} importantForAccessibility="no" accessibilityElementsHidden/>) : null}
59
+ </>);
60
+ // ── Render ────────────────────────────────────────────────────────────────
61
+ if (onPress) {
62
+ return (<react_native_1.Pressable onPress={onPress} style={({ pressed }) => [styles.row, pressed ? styles.rowPressed : null]} accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityRole="button">
63
+ {content}
64
+ </react_native_1.Pressable>);
65
+ }
66
+ return (<react_native_1.View style={styles.row} accessible accessibilityLabel={accessibilityLabel} accessibilityRole="text">
67
+ {content}
68
+ </react_native_1.View>);
69
+ }
70
+ // ─────────────────────────────────────────────────────────────────────────────
71
+ // Styles
72
+ // ─────────────────────────────────────────────────────────────────────────────
73
+ const styles = react_native_1.StyleSheet.create({
74
+ row: {
75
+ flexDirection: 'row',
76
+ alignItems: 'center',
77
+ gap: theme_1.SPACING.md,
78
+ paddingHorizontal: theme_1.SPACING.lg,
79
+ paddingVertical: theme_1.SPACING.md,
80
+ minHeight: 56,
81
+ },
82
+ rowPressed: {
83
+ backgroundColor: theme_1.COLORS.surfaceHigh,
84
+ },
85
+ iconWrapper: {
86
+ width: 52,
87
+ height: 52,
88
+ borderRadius: theme_1.RADIUS.md,
89
+ alignItems: 'center',
90
+ justifyContent: 'center',
91
+ },
92
+ textArea: {
93
+ flex: 1,
94
+ },
95
+ rowTitle: {
96
+ fontSize: theme_1.FONTS.xs,
97
+ color: theme_1.COLORS.textMuted,
98
+ fontWeight: '600',
99
+ textTransform: 'uppercase',
100
+ letterSpacing: 0.8,
101
+ },
102
+ rowValue: {
103
+ fontSize: theme_1.FONTS.md,
104
+ color: theme_1.COLORS.textPrimary,
105
+ fontWeight: '500',
106
+ marginTop: 2,
107
+ },
108
+ loadingIndicator: {
109
+ alignSelf: 'flex-start',
110
+ marginTop: 4,
111
+ },
112
+ });
113
+ //# sourceMappingURL=EchoProfileRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoProfileRow.js","sourceRoot":"","sources":["../../src/components/EchoProfileRow.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * EchoProfileSection
3
+ *
4
+ * Presentation-only section card used in the signed-in Echo Profile screen.
5
+ * Extracted from the Echo UI Reference sectionCard pattern.
6
+ *
7
+ * Renders a dark surface card with XL radius, 1px border, hidden overflow,
8
+ * and an uppercase section header label above the supplied children.
9
+ *
10
+ * When `accentColor` is supplied, the border uses `${accentColor}33`,
11
+ * matching the signed-in profile's per-section Echo Color treatment.
12
+ *
13
+ * No Expo Router, no auth, no contexts, no services, no app-specific code.
14
+ * Canonical shared component for @echoform/echo-ui.
15
+ */
16
+ import React from 'react';
17
+ export type EchoProfileSectionProps = {
18
+ /** Section heading displayed in uppercase above the children. */
19
+ title: string;
20
+ /**
21
+ * Echo Color hex used for border tinting.
22
+ * When supplied, border becomes `${accentColor}33`.
23
+ * When omitted, falls back to `COLORS.border`.
24
+ */
25
+ accentColor?: string;
26
+ children: React.ReactNode;
27
+ };
28
+ export declare function EchoProfileSection({ title, accentColor, children, }: EchoProfileSectionProps): React.JSX.Element;
29
+ //# sourceMappingURL=EchoProfileSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoProfileSection.d.ts","sourceRoot":"","sources":["../../src/components/EchoProfileSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,MAAM,MAAM,uBAAuB,GAAG;IACpC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAMF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,QAAQ,GACT,EAAE,uBAAuB,qBAWzB"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * EchoProfileSection
4
+ *
5
+ * Presentation-only section card used in the signed-in Echo Profile screen.
6
+ * Extracted from the Echo UI Reference sectionCard pattern.
7
+ *
8
+ * Renders a dark surface card with XL radius, 1px border, hidden overflow,
9
+ * and an uppercase section header label above the supplied children.
10
+ *
11
+ * When `accentColor` is supplied, the border uses `${accentColor}33`,
12
+ * matching the signed-in profile's per-section Echo Color treatment.
13
+ *
14
+ * No Expo Router, no auth, no contexts, no services, no app-specific code.
15
+ * Canonical shared component for @echoform/echo-ui.
16
+ */
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.EchoProfileSection = EchoProfileSection;
22
+ const react_1 = __importDefault(require("react"));
23
+ const react_native_1 = require("react-native");
24
+ const theme_1 = require("../theme");
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+ // Component
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+ function EchoProfileSection({ title, accentColor, children, }) {
29
+ const borderColor = accentColor ? accentColor + '33' : theme_1.COLORS.border;
30
+ return (<react_native_1.View style={[styles.card, { borderColor }]}>
31
+ <react_native_1.Text style={styles.label} accessibilityRole="header">
32
+ {title}
33
+ </react_native_1.Text>
34
+ {children}
35
+ </react_native_1.View>);
36
+ }
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ // Styles
39
+ // ─────────────────────────────────────────────────────────────────────────────
40
+ const styles = react_native_1.StyleSheet.create({
41
+ card: {
42
+ backgroundColor: theme_1.COLORS.surface,
43
+ borderRadius: theme_1.RADIUS.xl,
44
+ borderWidth: 1,
45
+ overflow: 'hidden',
46
+ },
47
+ label: {
48
+ fontSize: theme_1.FONTS.xs,
49
+ fontWeight: '700',
50
+ color: theme_1.COLORS.textMuted,
51
+ letterSpacing: 1.2,
52
+ textTransform: 'uppercase',
53
+ paddingHorizontal: theme_1.SPACING.lg,
54
+ paddingTop: theme_1.SPACING.md,
55
+ paddingBottom: theme_1.SPACING.xs,
56
+ },
57
+ });
58
+ //# sourceMappingURL=EchoProfileSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoProfileSection.js","sourceRoot":"","sources":["../../src/components/EchoProfileSection.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;;;AA0BH,gDAeC;AAvCD,kDAA0B;AAC1B,+CAAsD;AACtD,oCAA0D;AAkB1D,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,SAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,QAAQ,GACgB;IACxB,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,cAAM,CAAC,MAAM,CAAC;IAErE,OAAO,CACL,CAAC,mBAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAC1C;MAAA,CAAC,mBAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CACnD;QAAA,CAAC,KAAK,CACR;MAAA,EAAE,mBAAI,CACN;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAS;AACT,gFAAgF;AAEhF,MAAM,MAAM,GAAG,yBAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,eAAe,EAAE,cAAM,CAAC,OAAO;QAC/B,YAAY,EAAK,cAAM,CAAC,EAAE;QAC1B,WAAW,EAAM,CAAC;QAClB,QAAQ,EAAS,QAAQ;KAC1B;IACD,KAAK,EAAE;QACL,QAAQ,EAAW,aAAK,CAAC,EAAE;QAC3B,UAAU,EAAS,KAAK;QACxB,KAAK,EAAc,cAAM,CAAC,SAAS;QACnC,aAAa,EAAM,GAAG;QACtB,aAAa,EAAM,WAAW;QAC9B,iBAAiB,EAAE,eAAO,CAAC,EAAE;QAC7B,UAAU,EAAS,eAAO,CAAC,EAAE;QAC7B,aAAa,EAAM,eAAO,CAAC,EAAE;KAC9B;CACF,CAAC,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * EchoRewardNotificationBanner
3
+ *
4
+ * Generic Echo Profile reward modal. Shown whenever new Echo Titles or
5
+ * Emblems are unlocked during a session.
6
+ *
7
+ * Extracted from RewardNotificationBanner in the Echo UI Reference.
8
+ *
9
+ * DESIGN PHILOSOPHY
10
+ * ─────────────────
11
+ * The dialog uses a purple Echo-ecosystem treatment and communicates the
12
+ * *category* of reward unlocked (Title / Emblem / both) without revealing
13
+ * specific names, individual reward counts, or badge details. Discovery of
14
+ * the exact reward happens by opening the Echo Profile. This keeps the
15
+ * component generic and suitable for reuse across any Echoform app that
16
+ * grants Echo Profile rewards.
17
+ *
18
+ * MESSAGE LOGIC
19
+ * ─────────────
20
+ * Title-only → "New Echo Reward Unlocked!" / "You unlocked a new Echo Title."
21
+ * Emblem-only → "New Echo Reward Unlocked!" / "You unlocked a new Echo Emblem."
22
+ * Both → "New Echo Rewards Unlocked!" / "You unlocked new Echo Titles and Echo Emblems."
23
+ * Fallback → "New Echo Reward Unlocked!" / "Something new has been added to your Echo Profile."
24
+ *
25
+ * BEHAVIOR
26
+ * ────────
27
+ * • Renders as a centered transparent Modal with a dark backdrop.
28
+ * • Remains visible until the user explicitly taps Continue.
29
+ * • Backdrop taps, Android Back, and auto-dismiss timers are all disabled.
30
+ * • Host supplies the artwork image source.
31
+ *
32
+ * ACCESSIBILITY
33
+ * ─────────────
34
+ * • AccessibilityInfo.announceForAccessibility() fires once per reward event
35
+ * with a 350ms delay, combining heading and subtitle.
36
+ * • Each unique reward payload is announced exactly once.
37
+ * • accessibilityViewIsModal prevents VoiceOver/TalkBack from leaving the dialog.
38
+ * • Heading uses accessibilityRole="header".
39
+ * • Continue uses accessibilityRole="button" with label + hint.
40
+ * • Decorative artwork is hidden from accessibility trees.
41
+ *
42
+ * No app aliases, EchoCosmeticsContext, services, auth, Router, storage,
43
+ * or Supabase imports.
44
+ * Canonical shared component for @echoform/echo-ui.
45
+ */
46
+ import React from 'react';
47
+ import { ImageSource } from 'expo-image';
48
+ export type EchoRewardNotificationPayload = {
49
+ /** Number of newly granted Echo Titles (0 if none). */
50
+ newTitles: number;
51
+ /** Number of newly granted Echo Emblems (0 if none). */
52
+ newEmblems: number;
53
+ };
54
+ export type EchoRewardNotificationBannerProps = {
55
+ notification: EchoRewardNotificationPayload | null;
56
+ /** Host-supplied artwork rendered inside the glow area. */
57
+ artworkSource: ImageSource;
58
+ onDismiss: () => void;
59
+ };
60
+ export declare function EchoRewardNotificationBanner({ notification, artworkSource, onDismiss, }: EchoRewardNotificationBannerProps): React.JSX.Element | null;
61
+ //# sourceMappingURL=EchoRewardNotificationBanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoRewardNotificationBanner.d.ts","sourceRoot":"","sources":["../../src/components/EchoRewardNotificationBanner.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AASjD,OAAO,EAAS,WAAW,EAAE,MAAM,YAAY,CAAC;AAgBhD,MAAM,MAAM,6BAA6B,GAAG;IAC1C,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,YAAY,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACnD,2DAA2D;IAC3D,aAAa,EAAE,WAAW,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AA+CF,wBAAgB,4BAA4B,CAAC,EAC3C,YAAY,EACZ,aAAa,EACb,SAAS,GACV,EAAE,iCAAiC,4BAyFnC"}
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ /**
3
+ * EchoRewardNotificationBanner
4
+ *
5
+ * Generic Echo Profile reward modal. Shown whenever new Echo Titles or
6
+ * Emblems are unlocked during a session.
7
+ *
8
+ * Extracted from RewardNotificationBanner in the Echo UI Reference.
9
+ *
10
+ * DESIGN PHILOSOPHY
11
+ * ─────────────────
12
+ * The dialog uses a purple Echo-ecosystem treatment and communicates the
13
+ * *category* of reward unlocked (Title / Emblem / both) without revealing
14
+ * specific names, individual reward counts, or badge details. Discovery of
15
+ * the exact reward happens by opening the Echo Profile. This keeps the
16
+ * component generic and suitable for reuse across any Echoform app that
17
+ * grants Echo Profile rewards.
18
+ *
19
+ * MESSAGE LOGIC
20
+ * ─────────────
21
+ * Title-only → "New Echo Reward Unlocked!" / "You unlocked a new Echo Title."
22
+ * Emblem-only → "New Echo Reward Unlocked!" / "You unlocked a new Echo Emblem."
23
+ * Both → "New Echo Rewards Unlocked!" / "You unlocked new Echo Titles and Echo Emblems."
24
+ * Fallback → "New Echo Reward Unlocked!" / "Something new has been added to your Echo Profile."
25
+ *
26
+ * BEHAVIOR
27
+ * ────────
28
+ * • Renders as a centered transparent Modal with a dark backdrop.
29
+ * • Remains visible until the user explicitly taps Continue.
30
+ * • Backdrop taps, Android Back, and auto-dismiss timers are all disabled.
31
+ * • Host supplies the artwork image source.
32
+ *
33
+ * ACCESSIBILITY
34
+ * ─────────────
35
+ * • AccessibilityInfo.announceForAccessibility() fires once per reward event
36
+ * with a 350ms delay, combining heading and subtitle.
37
+ * • Each unique reward payload is announced exactly once.
38
+ * • accessibilityViewIsModal prevents VoiceOver/TalkBack from leaving the dialog.
39
+ * • Heading uses accessibilityRole="header".
40
+ * • Continue uses accessibilityRole="button" with label + hint.
41
+ * • Decorative artwork is hidden from accessibility trees.
42
+ *
43
+ * No app aliases, EchoCosmeticsContext, services, auth, Router, storage,
44
+ * or Supabase imports.
45
+ * Canonical shared component for @echoform/echo-ui.
46
+ */
47
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
48
+ if (k2 === undefined) k2 = k;
49
+ var desc = Object.getOwnPropertyDescriptor(m, k);
50
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
51
+ desc = { enumerable: true, get: function() { return m[k]; } };
52
+ }
53
+ Object.defineProperty(o, k2, desc);
54
+ }) : (function(o, m, k, k2) {
55
+ if (k2 === undefined) k2 = k;
56
+ o[k2] = m[k];
57
+ }));
58
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
59
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
60
+ }) : function(o, v) {
61
+ o["default"] = v;
62
+ });
63
+ var __importStar = (this && this.__importStar) || (function () {
64
+ var ownKeys = function(o) {
65
+ ownKeys = Object.getOwnPropertyNames || function (o) {
66
+ var ar = [];
67
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
68
+ return ar;
69
+ };
70
+ return ownKeys(o);
71
+ };
72
+ return function (mod) {
73
+ if (mod && mod.__esModule) return mod;
74
+ var result = {};
75
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
76
+ __setModuleDefault(result, mod);
77
+ return result;
78
+ };
79
+ })();
80
+ Object.defineProperty(exports, "__esModule", { value: true });
81
+ exports.EchoRewardNotificationBanner = EchoRewardNotificationBanner;
82
+ const react_1 = __importStar(require("react"));
83
+ const react_native_1 = require("react-native");
84
+ const expo_image_1 = require("expo-image");
85
+ const theme_1 = require("../theme");
86
+ // ─────────────────────────────────────────────────────────────────────────────
87
+ // Purple palette — local to this component.
88
+ // ─────────────────────────────────────────────────────────────────────────────
89
+ const PURPLE = '#a855f7';
90
+ const PURPLE_LIGHT = '#c084fc';
91
+ const PURPLE_DIM = 'rgba(168, 85, 247, 0.18)';
92
+ const PURPLE_BORDER = 'rgba(168, 85, 247, 0.55)';
93
+ // ─────────────────────────────────────────────────────────────────────────────
94
+ // Message helpers
95
+ // ─────────────────────────────────────────────────────────────────────────────
96
+ /**
97
+ * Derives the heading and subtitle from the reward payload.
98
+ * Designed for extensibility: new reward categories can be wired in here
99
+ * without touching the modal shell or changing its accessibility behavior.
100
+ */
101
+ function buildRewardInfo(payload) {
102
+ const hasTitle = payload.newTitles > 0;
103
+ const hasEmblem = payload.newEmblems > 0;
104
+ if (hasTitle && hasEmblem) {
105
+ return {
106
+ heading: 'New Echo Rewards Unlocked!',
107
+ subtitle: 'You unlocked new Echo Titles and Echo Emblems.',
108
+ };
109
+ }
110
+ if (hasTitle) {
111
+ return {
112
+ heading: 'New Echo Reward Unlocked!',
113
+ subtitle: 'You unlocked a new Echo Title.',
114
+ };
115
+ }
116
+ if (hasEmblem) {
117
+ return {
118
+ heading: 'New Echo Reward Unlocked!',
119
+ subtitle: 'You unlocked a new Echo Emblem.',
120
+ };
121
+ }
122
+ // Fallback — should not be reached when the host guards newTitles + newEmblems > 0.
123
+ return {
124
+ heading: 'New Echo Reward Unlocked!',
125
+ subtitle: 'Something new has been added to your Echo Profile.',
126
+ };
127
+ }
128
+ // ─────────────────────────────────────────────────────────────────────────────
129
+ // Component
130
+ // ─────────────────────────────────────────────────────────────────────────────
131
+ function EchoRewardNotificationBanner({ notification, artworkSource, onDismiss, }) {
132
+ // Guard: announce each unique reward event exactly once.
133
+ // Key on the raw counts so merged payloads don't re-announce on re-renders.
134
+ const announcedKeyRef = (0, react_1.useRef)(null);
135
+ (0, react_1.useEffect)(() => {
136
+ if (!notification)
137
+ return;
138
+ const key = `${notification.newTitles}:${notification.newEmblems}`;
139
+ if (announcedKeyRef.current === key)
140
+ return;
141
+ announcedKeyRef.current = key;
142
+ const { heading, subtitle } = buildRewardInfo(notification);
143
+ // Brief delay lets the Modal finish its fade-in before the announcement.
144
+ const timer = setTimeout(() => {
145
+ react_native_1.AccessibilityInfo.announceForAccessibility(`${heading} ${subtitle}`);
146
+ }, 350);
147
+ return () => clearTimeout(timer);
148
+ }, [notification]);
149
+ if (!notification)
150
+ return null;
151
+ const { heading, subtitle } = buildRewardInfo(notification);
152
+ return (<react_native_1.Modal visible transparent animationType="fade" statusBarTranslucent onRequestClose={() => {
153
+ // Intentional no-op.
154
+ // Android hardware/software Back must not dismiss the dialog —
155
+ // the user is required to activate the Continue button.
156
+ }}>
157
+ {/* Backdrop — absorbs taps so they cannot reach background content. */}
158
+ <react_native_1.View style={styles.backdrop}>
159
+ {/* Reward card */}
160
+ <react_native_1.View style={styles.card} accessibilityViewIsModal>
161
+
162
+ {/* Echo Profile artwork — decorative, hidden from accessibility trees. */}
163
+ <react_native_1.View style={styles.logoGlow} accessible={false} importantForAccessibility="no-hide-descendants">
164
+ <expo_image_1.Image source={artworkSource} style={styles.logoImage} contentFit="contain" accessible={false} importantForAccessibility="no-hide-descendants"/>
165
+ </react_native_1.View>
166
+
167
+ {/* Heading */}
168
+ <react_native_1.Text style={styles.heading} accessibilityRole="header" accessibilityLabel={heading}>
169
+ {heading}
170
+ </react_native_1.Text>
171
+
172
+ {/* Category-specific subtitle */}
173
+ <react_native_1.Text style={styles.subtitle}>
174
+ {subtitle}
175
+ </react_native_1.Text>
176
+
177
+ {/* Continue — only way to dismiss the dialog. */}
178
+ <react_native_1.Pressable onPress={onDismiss} style={({ pressed }) => [
179
+ styles.continueBtn,
180
+ pressed && styles.continueBtnPressed,
181
+ ]} accessibilityRole="button" accessibilityLabel="Continue" accessibilityHint="Dismisses the reward notification and returns to the app">
182
+ <react_native_1.Text style={styles.continueBtnText}>Continue</react_native_1.Text>
183
+ </react_native_1.Pressable>
184
+ </react_native_1.View>
185
+ </react_native_1.View>
186
+ </react_native_1.Modal>);
187
+ }
188
+ // ─────────────────────────────────────────────────────────────────────────────
189
+ // Styles
190
+ // ─────────────────────────────────────────────────────────────────────────────
191
+ const styles = react_native_1.StyleSheet.create({
192
+ backdrop: {
193
+ flex: 1,
194
+ backgroundColor: 'rgba(0, 0, 0, 0.78)',
195
+ alignItems: 'center',
196
+ justifyContent: 'center',
197
+ paddingHorizontal: theme_1.SPACING.lg,
198
+ },
199
+ card: {
200
+ width: '100%',
201
+ maxWidth: 380,
202
+ backgroundColor: theme_1.COLORS.surface,
203
+ borderRadius: theme_1.RADIUS.xl,
204
+ borderWidth: 1.5,
205
+ borderColor: PURPLE_BORDER,
206
+ paddingVertical: theme_1.SPACING.xxl,
207
+ paddingHorizontal: theme_1.SPACING.xl,
208
+ alignItems: 'center',
209
+ gap: theme_1.SPACING.md,
210
+ // iOS glow
211
+ shadowColor: PURPLE,
212
+ shadowOffset: { width: 0, height: 0 },
213
+ shadowOpacity: 0.45,
214
+ shadowRadius: 28,
215
+ // Android
216
+ elevation: 18,
217
+ },
218
+ logoGlow: {
219
+ width: 88,
220
+ height: 88,
221
+ borderRadius: 44,
222
+ alignItems: 'center',
223
+ justifyContent: 'center',
224
+ overflow: 'hidden',
225
+ backgroundColor: PURPLE_DIM,
226
+ marginBottom: theme_1.SPACING.xs,
227
+ // iOS inner glow
228
+ shadowColor: PURPLE,
229
+ shadowOffset: { width: 0, height: 0 },
230
+ shadowOpacity: 0.55,
231
+ shadowRadius: 18,
232
+ // Android
233
+ elevation: 0,
234
+ },
235
+ logoImage: {
236
+ width: 104,
237
+ height: 104,
238
+ transform: [{ translateX: -1.5 }],
239
+ },
240
+ heading: {
241
+ fontSize: theme_1.FONTS.xl,
242
+ fontWeight: '700',
243
+ color: PURPLE_LIGHT,
244
+ textAlign: 'center',
245
+ letterSpacing: 0.3,
246
+ },
247
+ subtitle: {
248
+ fontSize: theme_1.FONTS.sm,
249
+ color: theme_1.COLORS.neonCyan,
250
+ textAlign: 'center',
251
+ lineHeight: 20,
252
+ },
253
+ continueBtn: {
254
+ width: '100%',
255
+ minHeight: 52,
256
+ borderRadius: theme_1.RADIUS.md,
257
+ alignItems: 'center',
258
+ justifyContent: 'center',
259
+ marginTop: theme_1.SPACING.md,
260
+ backgroundColor: PURPLE,
261
+ },
262
+ continueBtnPressed: {
263
+ opacity: 0.8,
264
+ },
265
+ continueBtnText: {
266
+ fontSize: theme_1.FONTS.md,
267
+ fontWeight: '700',
268
+ color: '#fff',
269
+ letterSpacing: 0.5,
270
+ },
271
+ });
272
+ //# sourceMappingURL=EchoRewardNotificationBanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EchoRewardNotificationBanner.js","sourceRoot":"","sources":["../../src/components/EchoRewardNotificationBanner.tsx"],"names":[],"mappings":"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"}