kang-components 0.9.6 → 0.9.8

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.
@@ -0,0 +1,16 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ export interface AnimatedHeightProps {
3
+ children: ReactNode;
4
+ }
5
+ /**
6
+ * Wraps children in a container that smoothly animates height changes.
7
+ * Uses ResizeObserver to detect content size changes and react-spring
8
+ * to animate the container height. First measurement is immediate
9
+ * (no animation); subsequent changes animate with SPRING_RESPONSIVE.
10
+ *
11
+ * Domain-free layout primitive — lives in kang so every app animates
12
+ * expand/collapse with the same physics. Falls back to `auto` height where
13
+ * ResizeObserver is unavailable.
14
+ */
15
+ export declare const AnimatedHeight: ({ children }: AnimatedHeightProps) => ReactElement;
16
+ //# sourceMappingURL=animated-height.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animated-height.d.ts","sourceRoot":"","sources":["../src/animated-height.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAA+B,MAAM,OAAO,CAAC;AAI7E,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,SAAS,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,iBAAkB,mBAAmB,KAAG,YAoClE,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState } from 'react';
3
+ import { useSpring, animated } from '@react-spring/web';
4
+ import { SPRING_RESPONSIVE } from './spring.js';
5
+ /**
6
+ * Wraps children in a container that smoothly animates height changes.
7
+ * Uses ResizeObserver to detect content size changes and react-spring
8
+ * to animate the container height. First measurement is immediate
9
+ * (no animation); subsequent changes animate with SPRING_RESPONSIVE.
10
+ *
11
+ * Domain-free layout primitive — lives in kang so every app animates
12
+ * expand/collapse with the same physics. Falls back to `auto` height where
13
+ * ResizeObserver is unavailable.
14
+ */
15
+ export const AnimatedHeight = ({ children }) => {
16
+ const contentRef = useRef(null);
17
+ const initializedRef = useRef(false);
18
+ const [isReady, setIsReady] = useState(false);
19
+ const [spring, api] = useSpring(() => ({ height: 0 }));
20
+ useEffect(() => {
21
+ const el = contentRef.current;
22
+ if (!el || typeof ResizeObserver === 'undefined')
23
+ return;
24
+ const observer = new ResizeObserver((entries) => {
25
+ const entry = entries[0];
26
+ if (!entry)
27
+ return;
28
+ const newHeight = entry.contentRect.height;
29
+ if (!initializedRef.current) {
30
+ initializedRef.current = true;
31
+ api.set({ height: newHeight });
32
+ setIsReady(true);
33
+ return;
34
+ }
35
+ api.start({ height: newHeight, config: SPRING_RESPONSIVE });
36
+ });
37
+ observer.observe(el);
38
+ return () => observer.disconnect();
39
+ }, [api]);
40
+ return (_jsx(animated.div, { style: { overflow: 'hidden', height: isReady ? spring.height : 'auto' }, children: _jsx("div", { ref: contentRef, children: children }) }));
41
+ };
42
+ //# sourceMappingURL=animated-height.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animated-height.js","sourceRoot":"","sources":["../src/animated-height.tsx"],"names":[],"mappings":";AAAA,OAAO,EAA2B,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAMhD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAAuB,EAAgB,EAAE;IACjF,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvD,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,EAAE,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE,OAAO;QAEzD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE;YAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;YAE3C,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC7B,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;gBAC9B,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC/B,UAAU,CAAC,IAAI,CAAC,CAAC;gBACjB,OAAO;YACR,CAAC;YAED,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACpC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,OAAO,CACN,KAAC,QAAQ,CAAC,GAAG,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,YACpF,cAAK,GAAG,EAAE,UAAU,YAClB,QAAQ,GACJ,GACQ,CACf,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface ConfettiProps {
2
+ /** When true, the burst plays once on mount. */
3
+ active: boolean;
4
+ /** Optional text tokens (characters / phonics) sprinkled among the shapes. */
5
+ tokens?: string[];
6
+ /** Total number of pieces. */
7
+ count?: number;
8
+ /** Approximate lifetime of the burst in ms. */
9
+ durationMs?: number;
10
+ }
11
+ /**
12
+ * Lightweight, dependency-free celebratory confetti. Pieces are GPU-animated
13
+ * via a single CSS keyframe; per-piece motion is randomized through inline CSS
14
+ * custom properties (in pixels). Mix in text tokens to rain played
15
+ * characters/phonics.
16
+ *
17
+ * Rendered through a portal to <body> as a viewport-fixed overlay so it lives
18
+ * outside any fixed/overflow/contain subtree — that nesting was freezing the
19
+ * fall mid-viewport on iOS Safari.
20
+ *
21
+ * The burst is computed ONCE when it starts (active false→true) and frozen for
22
+ * its lifetime. Incidental re-renders must not re-roll the pieces: callers may
23
+ * derive `tokens` from objects whose identity churns (e.g. GunJS emits).
24
+ * Recomputing mid-fall would change each piece's animation target
25
+ * (--start/--dx/--dist/duration) while the keyframe is in flight, which
26
+ * stalls/jumps the pieces mid-viewport on iOS.
27
+ */
28
+ export declare function Confetti({ active, tokens, count, durationMs }: ConfettiProps): import("react").ReactPortal | null;
29
+ //# sourceMappingURL=confetti.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti.d.ts","sourceRoot":"","sources":["../src/confetti.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,aAAa;IAC7B,gDAAgD;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAqDD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAU,EAAE,UAAiB,EAAE,EAAE,aAAa,sCA0DxF"}
@@ -0,0 +1,109 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { tilePalette } from './tile-palette.js';
5
+ import { ConfettiLayer, ConfettiPiece } from './confetti.styles.js';
6
+ /** Airy pastel fills for the shape pieces — the shared word-tile palette. */
7
+ const SHAPE_COLORS = tilePalette.map((color) => color.bg);
8
+ /** Saturated tones for text pieces so glyphs stay legible on light surfaces. */
9
+ const TEXT_COLORS = [
10
+ '#1976D2', '#388E3C', '#8E24AA', '#F4511E',
11
+ '#0097A7', '#F9A825', '#5E35B1', '#039BE5',
12
+ ];
13
+ /**
14
+ * Build one immutable burst of pieces. Travel is computed in PIXELS from the
15
+ * current viewport (never vh/vw, which iOS recomputes when its address bar
16
+ * collapses). Called once when a burst starts; the result is frozen for the
17
+ * lifetime of that burst (see the component below).
18
+ */
19
+ function buildPieces(tokens, count, durationMs) {
20
+ const toks = tokens?.filter(Boolean) ?? [];
21
+ const vh = typeof window !== 'undefined' ? window.innerHeight : 800;
22
+ const vw = typeof window !== 'undefined' ? window.innerWidth : 400;
23
+ return Array.from({ length: count }, (_, i) => {
24
+ // Roughly 55% text pieces when tokens are available.
25
+ const useText = toks.length > 0 && i % 9 < 5;
26
+ const text = useText ? toks[i % toks.length] : null;
27
+ return {
28
+ key: i,
29
+ text,
30
+ color: useText
31
+ ? TEXT_COLORS[i % TEXT_COLORS.length]
32
+ : SHAPE_COLORS[i % SHAPE_COLORS.length],
33
+ startX: 50 + (Math.random() * 44 - 22), // start near center, spread out
34
+ start: -vh * 0.12, // above the viewport
35
+ drift: (Math.random() * 2 - 1) * vw * 0.5, // px left/right
36
+ dist: vh * (0.95 + Math.random() * 0.35), // px — comfortably past the bottom
37
+ rot: (Math.random() * 6 - 3) * 360, // deg
38
+ delay: Math.random() * 260, // ms
39
+ dur: durationMs * (0.7 + Math.random() * 0.5),
40
+ size: 7 + Math.random() * 8,
41
+ round: Math.random() > 0.6,
42
+ };
43
+ });
44
+ }
45
+ /**
46
+ * Lightweight, dependency-free celebratory confetti. Pieces are GPU-animated
47
+ * via a single CSS keyframe; per-piece motion is randomized through inline CSS
48
+ * custom properties (in pixels). Mix in text tokens to rain played
49
+ * characters/phonics.
50
+ *
51
+ * Rendered through a portal to <body> as a viewport-fixed overlay so it lives
52
+ * outside any fixed/overflow/contain subtree — that nesting was freezing the
53
+ * fall mid-viewport on iOS Safari.
54
+ *
55
+ * The burst is computed ONCE when it starts (active false→true) and frozen for
56
+ * its lifetime. Incidental re-renders must not re-roll the pieces: callers may
57
+ * derive `tokens` from objects whose identity churns (e.g. GunJS emits).
58
+ * Recomputing mid-fall would change each piece's animation target
59
+ * (--start/--dx/--dist/duration) while the keyframe is in flight, which
60
+ * stalls/jumps the pieces mid-viewport on iOS.
61
+ */
62
+ export function Confetti({ active, tokens, count = 64, durationMs = 2600 }) {
63
+ const [pieces, setPieces] = useState([]);
64
+ const [visible, setVisible] = useState(false);
65
+ // Latest tokens, read only at burst start so token-identity churn during a
66
+ // burst never reaches buildPieces.
67
+ const tokensRef = useRef(tokens);
68
+ tokensRef.current = tokens;
69
+ useEffect(() => {
70
+ if (!active) {
71
+ setVisible(false);
72
+ return;
73
+ }
74
+ setPieces(buildPieces(tokensRef.current, count, durationMs));
75
+ setVisible(true);
76
+ const longest = durationMs * 1.2 + 300;
77
+ const t = setTimeout(() => setVisible(false), longest);
78
+ return () => clearTimeout(t);
79
+ }, [active, count, durationMs]);
80
+ if (!visible || typeof document === 'undefined')
81
+ return null;
82
+ const layer = (_jsx(ConfettiLayer, { "aria-hidden": "true", children: pieces.map((p) => {
83
+ const base = {
84
+ left: `${p.startX}%`,
85
+ animationDelay: `${p.delay}ms`,
86
+ animationDuration: `${p.dur}ms`,
87
+ ['--start']: `${p.start}px`,
88
+ ['--dx']: `${p.drift}px`,
89
+ ['--dist']: `${p.dist}px`,
90
+ ['--rot']: `${p.rot}deg`,
91
+ };
92
+ const visual = p.text
93
+ ? {
94
+ color: p.color,
95
+ fontSize: `${p.size + 8}px`,
96
+ fontWeight: 800,
97
+ lineHeight: 1,
98
+ }
99
+ : {
100
+ background: p.color,
101
+ width: `${p.size}px`,
102
+ height: `${p.size * 1.4}px`,
103
+ borderRadius: p.round ? '50%' : '2px',
104
+ };
105
+ return (_jsx(ConfettiPiece, { style: { ...base, ...visual }, children: p.text }, p.key));
106
+ }) }));
107
+ return createPortal(layer, document.body);
108
+ }
109
+ //# sourceMappingURL=confetti.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti.js","sourceRoot":"","sources":["../src/confetti.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Viewport-fixed overlay. Rendered via a portal to <body> so it sits OUTSIDE
3
+ * any `position: fixed` + `overflow: hidden` + `contain: layout` subtree — that
4
+ * nesting is what froze the piece animations mid-fall on iOS (compositing
5
+ * desync inside a fixed/clipped ancestor during scroll/toolbar settle). At the
6
+ * document root the pieces composite against the viewport and animate to
7
+ * completion.
8
+ */
9
+ export declare const ConfettiLayer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
10
+ export declare const ConfettiPiece: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
11
+ //# sourceMappingURL=confetti.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti.styles.d.ts","sourceRoot":"","sources":["../src/confetti.styles.ts"],"names":[],"mappings":"AA6BA;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,uVAMzB,CAAC;AAEF,eAAO,MAAM,aAAa,2VAkBzB,CAAC"}
@@ -0,0 +1,62 @@
1
+ // Named import (not the default) so styled-components resolves consistently
2
+ // when this file is consumed as a published node_modules ESM module.
3
+ import { styled, keyframes } from 'styled-components';
4
+ /**
5
+ * Falls from just above the top, drifting sideways and rotating, then fades.
6
+ * Per-piece motion comes from CSS custom properties set inline, all in PIXELS
7
+ * (computed once at burst time) — NOT viewport units. iOS Safari recomputes
8
+ * `vh`/`vw` when its address bar collapses, which desynced/stalled the
9
+ * animation mid-fall; fixed pixel targets avoid that entirely.
10
+ * --start starting Y (negative px, above viewport)
11
+ * --dx horizontal drift (px)
12
+ * --dist fall distance (px, comfortably past the bottom edge)
13
+ * --rot rotation (deg)
14
+ */
15
+ const fall = keyframes `
16
+ 0% {
17
+ transform: translate3d(0, var(--start, -120px), 0) rotateZ(0deg);
18
+ opacity: 0;
19
+ }
20
+ 8% {
21
+ opacity: 1;
22
+ }
23
+ 100% {
24
+ transform: translate3d(var(--dx, 0), var(--dist, 900px), 0) rotateZ(var(--rot, 360deg));
25
+ opacity: 0;
26
+ }
27
+ `;
28
+ /**
29
+ * Viewport-fixed overlay. Rendered via a portal to <body> so it sits OUTSIDE
30
+ * any `position: fixed` + `overflow: hidden` + `contain: layout` subtree — that
31
+ * nesting is what froze the piece animations mid-fall on iOS (compositing
32
+ * desync inside a fixed/clipped ancestor during scroll/toolbar settle). At the
33
+ * document root the pieces composite against the viewport and animate to
34
+ * completion.
35
+ */
36
+ export const ConfettiLayer = styled.div `
37
+ position: fixed;
38
+ inset: 0;
39
+ overflow: hidden;
40
+ pointer-events: none;
41
+ z-index: 2147483000;
42
+ `;
43
+ export const ConfettiPiece = styled.span `
44
+ position: absolute;
45
+ top: 0;
46
+ display: block;
47
+ white-space: nowrap;
48
+ user-select: none;
49
+ will-change: transform, opacity;
50
+ animation-name: ${fall};
51
+ animation-timing-function: cubic-bezier(0.25, 0.6, 0.45, 1);
52
+ /* 'both' applies the 0% keyframe during the start delay, so each piece waits
53
+ above the viewport (opacity 0) instead of sitting visibly at the top. */
54
+ animation-fill-mode: both;
55
+ animation-iteration-count: 1;
56
+
57
+ @media (prefers-reduced-motion: reduce) {
58
+ animation: none;
59
+ display: none;
60
+ }
61
+ `;
62
+ //# sourceMappingURL=confetti.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti.styles.js","sourceRoot":"","sources":["../src/confetti.styles.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qEAAqE;AACrE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,IAAI,GAAG,SAAS,CAAA;;;;;;;;;;;;CAYrB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;CAMtC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAA;;;;;;;mBAOrB,IAAI;;;;;;;;;;;CAWtB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
2
+ export interface ErrorBoundaryProps {
3
+ children: ReactNode;
4
+ /**
5
+ * Reporter invoked when a child throws (e.g. a Sentry/GlitchTip capture).
6
+ * Injected so kang stays free of any observability backend. Optional — the
7
+ * fallback still renders without it.
8
+ */
9
+ onError?: (error: Error, info: ErrorInfo) => void;
10
+ /** Recovery action; defaults to a hard reload of the page. */
11
+ onReload?: () => void;
12
+ /** Fallback heading. */
13
+ title?: ReactNode;
14
+ /** Fallback body copy. */
15
+ message?: ReactNode;
16
+ /** Recovery button label. */
17
+ reloadLabel?: string;
18
+ }
19
+ interface ErrorBoundaryState {
20
+ hasError: boolean;
21
+ }
22
+ /**
23
+ * Domain-free root error boundary — the app's last line of defense against a
24
+ * render-time throw white-screening the whole UI. Designed to sit ABOVE the app's
25
+ * Redux/Theme providers, so it is fully self-contained (hard-coded, OS-color-scheme
26
+ * aware styles).
27
+ *
28
+ * The observability backend is injected via `onError`; recovery defaults to a hard
29
+ * reload (override with `onReload`) since persisted state (localStorage/Gun)
30
+ * restores on reload, whereas a soft state reset would just re-render the broken
31
+ * subtree and re-throw.
32
+ */
33
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
34
+ state: ErrorBoundaryState;
35
+ static getDerivedStateFromError(): ErrorBoundaryState;
36
+ componentDidCatch(error: Error, info: ErrorInfo): void;
37
+ private handleReload;
38
+ render(): ReactNode;
39
+ }
40
+ export default ErrorBoundary;
41
+ //# sourceMappingURL=error-boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../src/error-boundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASlE,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAClD,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,wBAAwB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,kBAAkB;IAC3B,QAAQ,EAAE,OAAO,CAAC;CAClB;AAOD;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IACnF,KAAK,EAAE,kBAAkB,CAAuB;IAEhD,MAAM,CAAC,wBAAwB,IAAI,kBAAkB;IAIrD,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAItD,OAAO,CAAC,YAAY,CAMlB;IAEF,MAAM,IAAI,SAAS;CAiBnB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Component } from 'react';
3
+ import { ErrorBoundaryContainer, ErrorCard, ErrorTitle, ErrorMessage, ReloadButton, } from './error-boundary.styles.js';
4
+ const DEFAULT_TITLE = 'Something went wrong';
5
+ const DEFAULT_MESSAGE = 'The app hit an unexpected error. Reloading usually fixes it, and your progress is saved.';
6
+ const DEFAULT_RELOAD_LABEL = 'Reload';
7
+ /**
8
+ * Domain-free root error boundary — the app's last line of defense against a
9
+ * render-time throw white-screening the whole UI. Designed to sit ABOVE the app's
10
+ * Redux/Theme providers, so it is fully self-contained (hard-coded, OS-color-scheme
11
+ * aware styles).
12
+ *
13
+ * The observability backend is injected via `onError`; recovery defaults to a hard
14
+ * reload (override with `onReload`) since persisted state (localStorage/Gun)
15
+ * restores on reload, whereas a soft state reset would just re-render the broken
16
+ * subtree and re-throw.
17
+ */
18
+ export class ErrorBoundary extends Component {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.state = { hasError: false };
22
+ this.handleReload = () => {
23
+ if (this.props.onReload) {
24
+ this.props.onReload();
25
+ return;
26
+ }
27
+ window.location.reload();
28
+ };
29
+ }
30
+ static getDerivedStateFromError() {
31
+ return { hasError: true };
32
+ }
33
+ componentDidCatch(error, info) {
34
+ this.props.onError?.(error, info);
35
+ }
36
+ render() {
37
+ if (this.state.hasError) {
38
+ return (_jsx(ErrorBoundaryContainer, { role: "alert", children: _jsxs(ErrorCard, { children: [_jsx(ErrorTitle, { children: this.props.title ?? DEFAULT_TITLE }), _jsx(ErrorMessage, { children: this.props.message ?? DEFAULT_MESSAGE }), _jsx(ReloadButton, { type: "button", onClick: this.handleReload, children: this.props.reloadLabel ?? DEFAULT_RELOAD_LABEL })] }) }));
39
+ }
40
+ return this.props.children;
41
+ }
42
+ }
43
+ export default ErrorBoundary;
44
+ //# sourceMappingURL=error-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.js","sourceRoot":"","sources":["../src/error-boundary.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAC;AAClE,OAAO,EACN,sBAAsB,EACtB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,YAAY,GACZ,MAAM,4BAA4B,CAAC;AAwBpC,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAC7C,MAAM,eAAe,GACpB,0FAA0F,CAAC;AAC5F,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAiD;IAApF;;QACC,UAAK,GAAuB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAUxC,iBAAY,GAAG,GAAS,EAAE;YACjC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACtB,OAAO;YACR,CAAC;YACD,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC1B,CAAC,CAAC;IAmBH,CAAC;IAjCA,MAAM,CAAC,wBAAwB;QAC9B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,iBAAiB,CAAC,KAAY,EAAE,IAAe;QAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAUD,MAAM;QACL,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,CACN,KAAC,sBAAsB,IAAC,IAAI,EAAC,OAAO,YACnC,MAAC,SAAS,eACT,KAAC,UAAU,cAAE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,aAAa,GAAc,EAC5D,KAAC,YAAY,cAAE,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,eAAe,GAAgB,EACpE,KAAC,YAAY,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,YAAY,YACpD,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,oBAAoB,GACjC,IACJ,GACY,CACzB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5B,CAAC;CACD;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const ErrorBoundaryContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
2
+ export declare const ErrorCard: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
3
+ export declare const ErrorTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>>> & string;
4
+ export declare const ErrorMessage: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>>> & string;
5
+ export declare const ReloadButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>>> & string;
6
+ //# sourceMappingURL=error-boundary.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.styles.d.ts","sourceRoot":"","sources":["../src/error-boundary.styles.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,sBAAsB,uVAiBlC,CAAC;AAEF,eAAO,MAAM,SAAS,uVAQrB,CAAC;AAEF,eAAO,MAAM,UAAU,uWAItB,CAAC;AAEF,eAAO,MAAM,YAAY,+WAKxB,CAAC;AAEF,eAAO,MAAM,YAAY,+WAoBxB,CAAC"}
@@ -0,0 +1,66 @@
1
+ // Named import (not the default) so styled-components resolves consistently
2
+ // when this file is consumed as a published node_modules ESM module.
3
+ import { styled } from 'styled-components';
4
+ // This fallback renders ABOVE the app's ThemeProvider, so it cannot read the
5
+ // styled-components theme. Colors are hard-coded and follow the OS color scheme
6
+ // directly (matching a white light / black dark theme-color).
7
+ export const ErrorBoundaryContainer = styled.div `
8
+ position: fixed;
9
+ inset: 0;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ padding: 24px;
14
+ box-sizing: border-box;
15
+ background: #ffffff;
16
+ color: #1a202c;
17
+ font-family:
18
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
19
+
20
+ @media (prefers-color-scheme: dark) {
21
+ background: #000000;
22
+ color: #f7fafc;
23
+ }
24
+ `;
25
+ export const ErrorCard = styled.div `
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: center;
29
+ gap: 16px;
30
+ width: 100%;
31
+ max-width: 360px;
32
+ text-align: center;
33
+ `;
34
+ export const ErrorTitle = styled.h1 `
35
+ margin: 0;
36
+ font-size: 1.375rem;
37
+ font-weight: 600;
38
+ `;
39
+ export const ErrorMessage = styled.p `
40
+ margin: 0;
41
+ font-size: 0.95rem;
42
+ line-height: 1.5;
43
+ opacity: 0.75;
44
+ `;
45
+ export const ReloadButton = styled.button `
46
+ margin-top: 8px;
47
+ padding: 12px 28px;
48
+ font-size: 1rem;
49
+ font-weight: 600;
50
+ color: #ffffff;
51
+ background: #4db6ac;
52
+ border: none;
53
+ border-radius: 9999px;
54
+ cursor: pointer;
55
+ transition: opacity 0.15s ease;
56
+
57
+ &:hover {
58
+ opacity: 0.9;
59
+ }
60
+
61
+ &:focus-visible {
62
+ outline: 2px solid #4db6ac;
63
+ outline-offset: 3px;
64
+ }
65
+ `;
66
+ //# sourceMappingURL=error-boundary.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.styles.js","sourceRoot":"","sources":["../src/error-boundary.styles.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qEAAqE;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,6EAA6E;AAC7E,gFAAgF;AAChF,8DAA8D;AAE9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;CAiB/C,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;CAQlC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,CAAA;;;;CAIlC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAA;;;;;CAKnC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAA;;;;;;;;;;;;;;;;;;;;CAoBxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -23,6 +23,14 @@ export { default as ToggleSwitch } from './toggle-switch.js';
23
23
  export type { ToggleSwitchProps } from './toggle-switch.js';
24
24
  export { ConfirmDialog } from './confirm-dialog.js';
25
25
  export type { ConfirmDialogProps } from './confirm-dialog.js';
26
+ export { Confetti } from './confetti.js';
27
+ export type { ConfettiProps } from './confetti.js';
28
+ export { ErrorBoundary } from './error-boundary.js';
29
+ export type { ErrorBoundaryProps } from './error-boundary.js';
30
+ export { LongPressTooltip } from './long-press-tooltip.js';
31
+ export type { LongPressTooltipProps } from './long-press-tooltip.js';
32
+ export { AnimatedHeight } from './animated-height.js';
33
+ export type { AnimatedHeightProps } from './animated-height.js';
26
34
  export { BottomSheet } from './bottom-sheet.js';
27
35
  export type { BottomSheetProps } from './bottom-sheet.js';
28
36
  export { SearchField } from './search-field.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -12,6 +12,10 @@ export { default as BannerButton } from './banner-button.js';
12
12
  export { Badge } from './badge.js';
13
13
  export { default as ToggleSwitch } from './toggle-switch.js';
14
14
  export { ConfirmDialog } from './confirm-dialog.js';
15
+ export { Confetti } from './confetti.js';
16
+ export { ErrorBoundary } from './error-boundary.js';
17
+ export { LongPressTooltip } from './long-press-tooltip.js';
18
+ export { AnimatedHeight } from './animated-height.js';
15
19
  export { BottomSheet } from './bottom-sheet.js';
16
20
  export { SearchField } from './search-field.js';
17
21
  export { SearchBar } from './search-bar.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AASjF,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AASjF,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ export interface LongPressTooltipProps {
3
+ /** The row/control this tooltip describes — receives the long-press gesture. */
4
+ children: ReactNode;
5
+ /** Arbitrary content shown in the floating bubble (caller owns i18n/markup). */
6
+ content: ReactNode;
7
+ /** Hold duration before the bubble opens, in ms. */
8
+ longPressMs?: number;
9
+ /** How long the bubble stays up before auto-dismissing, in ms. */
10
+ autoDismissMs?: number;
11
+ }
12
+ /**
13
+ * Domain-free touch-and-hold tooltip. Reveals `content` in a floating bubble on
14
+ * long-press; the bubble is portaled to <body> so it escapes any clipped
15
+ * ancestor, and the completed hold swallows the trailing click so it never
16
+ * triggers the row's tap action. Dismisses on outside tap / scroll / resize /
17
+ * Escape / timeout.
18
+ *
19
+ * Language/character knowledge stays in the consuming app: pass an already-built
20
+ * node (e.g. an AnimatedText) as `content`.
21
+ */
22
+ export declare const LongPressTooltip: ({ children, content, longPressMs, autoDismissMs, }: LongPressTooltipProps) => ReactElement;
23
+ export default LongPressTooltip;
24
+ //# sourceMappingURL=long-press-tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-press-tooltip.d.ts","sourceRoot":"","sources":["../src/long-press-tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,SAAS,EAQT,MAAM,OAAO,CAAC;AAcf,MAAM,WAAW,qBAAqB;IACrC,gFAAgF;IAChF,QAAQ,EAAE,SAAS,CAAC;IACpB,gFAAgF;IAChF,OAAO,EAAE,SAAS,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AASD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,uDAK1B,qBAAqB,KAAG,YA0K1B,CAAC;AAEF,eAAe,gBAAgB,CAAC"}