@orangecheck/app-design 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -310,8 +310,9 @@ interface SectionProps extends HTMLAttributes<HTMLElement>, VariantProps<typeof
310
310
  }
311
311
  declare function Section({ tone, space, contained, className, children, ...props }: SectionProps): react.JSX.Element;
312
312
  declare function Container({ className, ...props }: HTMLAttributes<HTMLDivElement>): react.JSX.Element;
313
- declare function SectionIntro({ className, align, ...props }: HTMLAttributes<HTMLDivElement> & {
313
+ declare function SectionIntro({ className, align, reveal, children, style, }: Pick<HTMLAttributes<HTMLDivElement>, 'className' | 'style' | 'children'> & {
314
314
  align?: 'start' | 'center';
315
+ reveal?: boolean;
315
316
  }): react.JSX.Element;
316
317
 
317
318
  interface PageHeroProps {
@@ -310,8 +310,9 @@ interface SectionProps extends HTMLAttributes<HTMLElement>, VariantProps<typeof
310
310
  }
311
311
  declare function Section({ tone, space, contained, className, children, ...props }: SectionProps): react.JSX.Element;
312
312
  declare function Container({ className, ...props }: HTMLAttributes<HTMLDivElement>): react.JSX.Element;
313
- declare function SectionIntro({ className, align, ...props }: HTMLAttributes<HTMLDivElement> & {
313
+ declare function SectionIntro({ className, align, reveal, children, style, }: Pick<HTMLAttributes<HTMLDivElement>, 'className' | 'style' | 'children'> & {
314
314
  align?: 'start' | 'center';
315
+ reveal?: boolean;
315
316
  }): react.JSX.Element;
316
317
 
317
318
  interface PageHeroProps {
@@ -83,6 +83,131 @@ function Prose({ className, ...props }) {
83
83
  }
84
84
  );
85
85
  }
86
+ function prefersStill() {
87
+ return typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
88
+ }
89
+ function useInView(rootMargin = "0px 0px -12% 0px") {
90
+ const ref = react.useRef(null);
91
+ const [seen, setSeen] = react.useState(false);
92
+ react.useEffect(() => {
93
+ const el = ref.current;
94
+ if (!el || seen) return;
95
+ if (typeof IntersectionObserver === "undefined") {
96
+ setSeen(true);
97
+ return;
98
+ }
99
+ const io = new IntersectionObserver(
100
+ ([e]) => {
101
+ if (e?.isIntersecting) {
102
+ setSeen(true);
103
+ io.disconnect();
104
+ }
105
+ },
106
+ { rootMargin }
107
+ );
108
+ io.observe(el);
109
+ return () => io.disconnect();
110
+ }, [rootMargin, seen]);
111
+ return [ref, seen];
112
+ }
113
+ function Reveal({
114
+ as = "div",
115
+ delay = 0,
116
+ className,
117
+ style,
118
+ children
119
+ }) {
120
+ const ref = react.useRef(null);
121
+ react.useEffect(() => {
122
+ const el = ref.current;
123
+ if (!el || prefersStill() || typeof IntersectionObserver === "undefined") return;
124
+ if (el.getBoundingClientRect().top < window.innerHeight * 0.92) return;
125
+ el.dataset.reveal = "pending";
126
+ const io = new IntersectionObserver(
127
+ ([e]) => {
128
+ if (e?.isIntersecting) {
129
+ el.dataset.reveal = "shown";
130
+ io.disconnect();
131
+ }
132
+ },
133
+ { rootMargin: "0px 0px -10% 0px" }
134
+ );
135
+ io.observe(el);
136
+ return () => io.disconnect();
137
+ }, []);
138
+ return react.createElement(
139
+ as,
140
+ { ref, className, style: { ...style, "--reveal-delay": `${delay}ms` } },
141
+ children
142
+ );
143
+ }
144
+ function ScrollStory({
145
+ length = 2,
146
+ className,
147
+ innerClassName,
148
+ children
149
+ }) {
150
+ const ref = react.useRef(null);
151
+ const [pinned, setPinned] = react.useState(false);
152
+ react.useEffect(() => {
153
+ const el = ref.current;
154
+ if (!el || prefersStill()) return;
155
+ setPinned(true);
156
+ let raf = 0;
157
+ const update = () => {
158
+ raf = 0;
159
+ const r = el.getBoundingClientRect();
160
+ const travel = r.height - window.innerHeight;
161
+ const p = travel > 0 ? Math.min(1, Math.max(0, -r.top / travel)) : 0;
162
+ el.style.setProperty("--p", p.toFixed(4));
163
+ };
164
+ const on = () => {
165
+ if (!raf) raf = requestAnimationFrame(update);
166
+ };
167
+ update();
168
+ window.addEventListener("scroll", on, { passive: true });
169
+ window.addEventListener("resize", on);
170
+ return () => {
171
+ cancelAnimationFrame(raf);
172
+ window.removeEventListener("scroll", on);
173
+ window.removeEventListener("resize", on);
174
+ };
175
+ }, []);
176
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative", className), style: pinned ? { height: `${length * 100}svh` } : void 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(pinned && "sticky top-0 flex min-h-svh items-center", innerClassName), children }) });
177
+ }
178
+ function Ticker({
179
+ value,
180
+ duration = 1200,
181
+ format = (n) => Math.round(n).toLocaleString("en-US"),
182
+ className
183
+ }) {
184
+ const [ref, seen] = useInView();
185
+ const [shown, setShown] = react.useState(value);
186
+ const animate = react.useRef(null);
187
+ react.useEffect(() => {
188
+ const el = ref.current;
189
+ if (!el || animate.current !== null) return;
190
+ animate.current = !prefersStill() && el.getBoundingClientRect().top > window.innerHeight * 0.9;
191
+ if (animate.current) setShown(0);
192
+ }, [ref]);
193
+ react.useEffect(() => {
194
+ if (!seen) return;
195
+ if (!animate.current) {
196
+ setShown(value);
197
+ return;
198
+ }
199
+ let raf = 0;
200
+ const t0 = performance.now();
201
+ const step = (now) => {
202
+ const k = Math.min(1, (now - t0) / duration);
203
+ setShown(value * (1 - Math.pow(1 - k, 3)));
204
+ if (k < 1) raf = requestAnimationFrame(step);
205
+ };
206
+ raf = requestAnimationFrame(step);
207
+ return () => cancelAnimationFrame(raf);
208
+ }, [seen, value, duration]);
209
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("oca-tabular", className), children: format(shown) });
210
+ }
86
211
  var sectionVariants = classVarianceAuthority.cva("relative w-full overflow-x-clip", {
87
212
  variants: {
88
213
  tone: {
@@ -111,19 +236,12 @@ function Container({ className, ...props }) {
111
236
  function SectionIntro({
112
237
  className,
113
238
  align = "start",
114
- ...props
239
+ reveal = true,
240
+ children,
241
+ style
115
242
  }) {
116
- return /* @__PURE__ */ jsxRuntime.jsx(
117
- "div",
118
- {
119
- className: cn(
120
- "flex flex-col gap-4 md:gap-5",
121
- align === "center" && "mx-auto items-center text-center",
122
- className
123
- ),
124
- ...props
125
- }
126
- );
243
+ const cls = cn("flex flex-col gap-4 md:gap-5", align === "center" && "mx-auto items-center text-center", className);
244
+ return reveal ? /* @__PURE__ */ jsxRuntime.jsx(Reveal, { className: cls, style, children }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cls, style, children });
127
245
  }
128
246
  function PageHero({
129
247
  eyebrow,
@@ -142,14 +260,14 @@ function PageHero({
142
260
  }
143
261
  return /* @__PURE__ */ jsxRuntime.jsx(Section, { space: "none", className: cn("pb-14 pt-12 md:pb-20 md:pt-20", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid grid-cols-1 gap-10", art && "items-center md:grid-cols-12"), children: [
144
262
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-start gap-6", art ? "md:col-span-7" : "max-w-[52rem]"), children: [
145
- eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow", children: eyebrow }) : null,
146
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: size === "xl" ? "oca-display-1" : "oca-display-2", children: title }),
147
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead max-w-[38rem]", children: lead }) : null,
148
- meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: meta }) : null,
149
- actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3", children: actions }) : null,
150
- children
263
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow oca-enter", children: eyebrow }) : null,
264
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: cn(size === "xl" ? "oca-display-1" : "oca-display-2", "oca-enter [--enter-delay:70ms]"), children: title }),
265
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead oca-enter max-w-[38rem] [--enter-delay:150ms]", children: lead }) : null,
266
+ meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-enter text-[0.875rem] text-muted-foreground [--enter-delay:190ms]", children: meta }) : null,
267
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions }) : null,
268
+ children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter w-full [--enter-delay:270ms]", children }) : null
151
269
  ] }),
152
- art ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:col-span-5", children: art }) : null
270
+ art ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter md:col-span-5 [--enter-delay:120ms]", children: art }) : null
153
271
  ] }) });
154
272
  }
155
273
  function DocHeader({
@@ -162,8 +280,8 @@ function DocHeader({
162
280
  className
163
281
  }) {
164
282
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
165
- eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow", children: eyebrow }) : null,
166
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2", children: title }),
283
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow oca-enter", children: eyebrow }) : null,
284
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2 oca-enter [--enter-delay:70ms]", children: title }),
167
285
  lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead", children: lead }) : null,
168
286
  meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: meta }) : null,
169
287
  actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-3", children: actions }) : null,
@@ -1118,131 +1236,6 @@ function SatsFigure({
1118
1236
  hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] text-muted-foreground", children: hint }) : null
1119
1237
  ] });
1120
1238
  }
1121
- function prefersStill() {
1122
- return typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1123
- }
1124
- function useInView(rootMargin = "0px 0px -12% 0px") {
1125
- const ref = react.useRef(null);
1126
- const [seen, setSeen] = react.useState(false);
1127
- react.useEffect(() => {
1128
- const el = ref.current;
1129
- if (!el || seen) return;
1130
- if (typeof IntersectionObserver === "undefined") {
1131
- setSeen(true);
1132
- return;
1133
- }
1134
- const io = new IntersectionObserver(
1135
- ([e]) => {
1136
- if (e?.isIntersecting) {
1137
- setSeen(true);
1138
- io.disconnect();
1139
- }
1140
- },
1141
- { rootMargin }
1142
- );
1143
- io.observe(el);
1144
- return () => io.disconnect();
1145
- }, [rootMargin, seen]);
1146
- return [ref, seen];
1147
- }
1148
- function Reveal({
1149
- as = "div",
1150
- delay = 0,
1151
- className,
1152
- style,
1153
- children
1154
- }) {
1155
- const ref = react.useRef(null);
1156
- react.useEffect(() => {
1157
- const el = ref.current;
1158
- if (!el || prefersStill() || typeof IntersectionObserver === "undefined") return;
1159
- if (el.getBoundingClientRect().top < window.innerHeight * 0.92) return;
1160
- el.dataset.reveal = "pending";
1161
- const io = new IntersectionObserver(
1162
- ([e]) => {
1163
- if (e?.isIntersecting) {
1164
- el.dataset.reveal = "shown";
1165
- io.disconnect();
1166
- }
1167
- },
1168
- { rootMargin: "0px 0px -10% 0px" }
1169
- );
1170
- io.observe(el);
1171
- return () => io.disconnect();
1172
- }, []);
1173
- return react.createElement(
1174
- as,
1175
- { ref, className, style: { ...style, "--reveal-delay": `${delay}ms` } },
1176
- children
1177
- );
1178
- }
1179
- function ScrollStory({
1180
- length = 2,
1181
- className,
1182
- innerClassName,
1183
- children
1184
- }) {
1185
- const ref = react.useRef(null);
1186
- const [pinned, setPinned] = react.useState(false);
1187
- react.useEffect(() => {
1188
- const el = ref.current;
1189
- if (!el || prefersStill()) return;
1190
- setPinned(true);
1191
- let raf = 0;
1192
- const update = () => {
1193
- raf = 0;
1194
- const r = el.getBoundingClientRect();
1195
- const travel = r.height - window.innerHeight;
1196
- const p = travel > 0 ? Math.min(1, Math.max(0, -r.top / travel)) : 0;
1197
- el.style.setProperty("--p", p.toFixed(4));
1198
- };
1199
- const on = () => {
1200
- if (!raf) raf = requestAnimationFrame(update);
1201
- };
1202
- update();
1203
- window.addEventListener("scroll", on, { passive: true });
1204
- window.addEventListener("resize", on);
1205
- return () => {
1206
- cancelAnimationFrame(raf);
1207
- window.removeEventListener("scroll", on);
1208
- window.removeEventListener("resize", on);
1209
- };
1210
- }, []);
1211
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative", className), style: pinned ? { height: `${length * 100}svh` } : void 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(pinned && "sticky top-0 flex min-h-svh items-center", innerClassName), children }) });
1212
- }
1213
- function Ticker({
1214
- value,
1215
- duration = 1200,
1216
- format = (n) => Math.round(n).toLocaleString("en-US"),
1217
- className
1218
- }) {
1219
- const [ref, seen] = useInView();
1220
- const [shown, setShown] = react.useState(value);
1221
- const animate = react.useRef(null);
1222
- react.useEffect(() => {
1223
- const el = ref.current;
1224
- if (!el || animate.current !== null) return;
1225
- animate.current = !prefersStill() && el.getBoundingClientRect().top > window.innerHeight * 0.9;
1226
- if (animate.current) setShown(0);
1227
- }, [ref]);
1228
- react.useEffect(() => {
1229
- if (!seen) return;
1230
- if (!animate.current) {
1231
- setShown(value);
1232
- return;
1233
- }
1234
- let raf = 0;
1235
- const t0 = performance.now();
1236
- const step = (now) => {
1237
- const k = Math.min(1, (now - t0) / duration);
1238
- setShown(value * (1 - Math.pow(1 - k, 3)));
1239
- if (k < 1) raf = requestAnimationFrame(step);
1240
- };
1241
- raf = requestAnimationFrame(step);
1242
- return () => cancelAnimationFrame(raf);
1243
- }, [seen, value, duration]);
1244
- return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("oca-tabular", className), children: format(shown) });
1245
- }
1246
1239
  function PhoneFrame({ className, style, children }) {
1247
1240
  return /* @__PURE__ */ jsxRuntime.jsx(
1248
1241
  "div",