@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.
package/dist/index.js CHANGED
@@ -1263,6 +1263,131 @@ function Prose({ className, ...props }) {
1263
1263
  }
1264
1264
  );
1265
1265
  }
1266
+ function prefersStill() {
1267
+ return typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1268
+ }
1269
+ function useInView(rootMargin = "0px 0px -12% 0px") {
1270
+ const ref = react.useRef(null);
1271
+ const [seen, setSeen] = react.useState(false);
1272
+ react.useEffect(() => {
1273
+ const el = ref.current;
1274
+ if (!el || seen) return;
1275
+ if (typeof IntersectionObserver === "undefined") {
1276
+ setSeen(true);
1277
+ return;
1278
+ }
1279
+ const io = new IntersectionObserver(
1280
+ ([e]) => {
1281
+ if (e?.isIntersecting) {
1282
+ setSeen(true);
1283
+ io.disconnect();
1284
+ }
1285
+ },
1286
+ { rootMargin }
1287
+ );
1288
+ io.observe(el);
1289
+ return () => io.disconnect();
1290
+ }, [rootMargin, seen]);
1291
+ return [ref, seen];
1292
+ }
1293
+ function Reveal({
1294
+ as = "div",
1295
+ delay = 0,
1296
+ className,
1297
+ style,
1298
+ children
1299
+ }) {
1300
+ const ref = react.useRef(null);
1301
+ react.useEffect(() => {
1302
+ const el = ref.current;
1303
+ if (!el || prefersStill() || typeof IntersectionObserver === "undefined") return;
1304
+ if (el.getBoundingClientRect().top < window.innerHeight * 0.92) return;
1305
+ el.dataset.reveal = "pending";
1306
+ const io = new IntersectionObserver(
1307
+ ([e]) => {
1308
+ if (e?.isIntersecting) {
1309
+ el.dataset.reveal = "shown";
1310
+ io.disconnect();
1311
+ }
1312
+ },
1313
+ { rootMargin: "0px 0px -10% 0px" }
1314
+ );
1315
+ io.observe(el);
1316
+ return () => io.disconnect();
1317
+ }, []);
1318
+ return react.createElement(
1319
+ as,
1320
+ { ref, className, style: { ...style, "--reveal-delay": `${delay}ms` } },
1321
+ children
1322
+ );
1323
+ }
1324
+ function ScrollStory({
1325
+ length = 2,
1326
+ className,
1327
+ innerClassName,
1328
+ children
1329
+ }) {
1330
+ const ref = react.useRef(null);
1331
+ const [pinned, setPinned] = react.useState(false);
1332
+ react.useEffect(() => {
1333
+ const el = ref.current;
1334
+ if (!el || prefersStill()) return;
1335
+ setPinned(true);
1336
+ let raf = 0;
1337
+ const update = () => {
1338
+ raf = 0;
1339
+ const r = el.getBoundingClientRect();
1340
+ const travel = r.height - window.innerHeight;
1341
+ const p = travel > 0 ? Math.min(1, Math.max(0, -r.top / travel)) : 0;
1342
+ el.style.setProperty("--p", p.toFixed(4));
1343
+ };
1344
+ const on = () => {
1345
+ if (!raf) raf = requestAnimationFrame(update);
1346
+ };
1347
+ update();
1348
+ window.addEventListener("scroll", on, { passive: true });
1349
+ window.addEventListener("resize", on);
1350
+ return () => {
1351
+ cancelAnimationFrame(raf);
1352
+ window.removeEventListener("scroll", on);
1353
+ window.removeEventListener("resize", on);
1354
+ };
1355
+ }, []);
1356
+ 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 }) });
1357
+ }
1358
+ function Ticker({
1359
+ value,
1360
+ duration = 1200,
1361
+ format = (n) => Math.round(n).toLocaleString("en-US"),
1362
+ className
1363
+ }) {
1364
+ const [ref, seen] = useInView();
1365
+ const [shown, setShown] = react.useState(value);
1366
+ const animate = react.useRef(null);
1367
+ react.useEffect(() => {
1368
+ const el = ref.current;
1369
+ if (!el || animate.current !== null) return;
1370
+ animate.current = !prefersStill() && el.getBoundingClientRect().top > window.innerHeight * 0.9;
1371
+ if (animate.current) setShown(0);
1372
+ }, [ref]);
1373
+ react.useEffect(() => {
1374
+ if (!seen) return;
1375
+ if (!animate.current) {
1376
+ setShown(value);
1377
+ return;
1378
+ }
1379
+ let raf = 0;
1380
+ const t0 = performance.now();
1381
+ const step = (now) => {
1382
+ const k = Math.min(1, (now - t0) / duration);
1383
+ setShown(value * (1 - Math.pow(1 - k, 3)));
1384
+ if (k < 1) raf = requestAnimationFrame(step);
1385
+ };
1386
+ raf = requestAnimationFrame(step);
1387
+ return () => cancelAnimationFrame(raf);
1388
+ }, [seen, value, duration]);
1389
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("oca-tabular", className), children: format(shown) });
1390
+ }
1266
1391
  var sectionVariants = classVarianceAuthority.cva("relative w-full overflow-x-clip", {
1267
1392
  variants: {
1268
1393
  tone: {
@@ -1291,19 +1416,12 @@ function Container({ className, ...props }) {
1291
1416
  function SectionIntro({
1292
1417
  className,
1293
1418
  align = "start",
1294
- ...props
1419
+ reveal = true,
1420
+ children,
1421
+ style
1295
1422
  }) {
1296
- return /* @__PURE__ */ jsxRuntime.jsx(
1297
- "div",
1298
- {
1299
- className: cn(
1300
- "flex flex-col gap-4 md:gap-5",
1301
- align === "center" && "mx-auto items-center text-center",
1302
- className
1303
- ),
1304
- ...props
1305
- }
1306
- );
1423
+ const cls = cn("flex flex-col gap-4 md:gap-5", align === "center" && "mx-auto items-center text-center", className);
1424
+ return reveal ? /* @__PURE__ */ jsxRuntime.jsx(Reveal, { className: cls, style, children }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cls, style, children });
1307
1425
  }
1308
1426
  function PageHero({
1309
1427
  eyebrow,
@@ -1322,14 +1440,14 @@ function PageHero({
1322
1440
  }
1323
1441
  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: [
1324
1442
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-start gap-6", art ? "md:col-span-7" : "max-w-[52rem]"), children: [
1325
- eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow", children: eyebrow }) : null,
1326
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: size === "xl" ? "oca-display-1" : "oca-display-2", children: title }),
1327
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead max-w-[38rem]", children: lead }) : null,
1328
- meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: meta }) : null,
1329
- actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3", children: actions }) : null,
1330
- children
1443
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow oca-enter", children: eyebrow }) : null,
1444
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: cn(size === "xl" ? "oca-display-1" : "oca-display-2", "oca-enter [--enter-delay:70ms]"), children: title }),
1445
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead oca-enter max-w-[38rem] [--enter-delay:150ms]", children: lead }) : null,
1446
+ meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-enter text-[0.875rem] text-muted-foreground [--enter-delay:190ms]", children: meta }) : null,
1447
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions }) : null,
1448
+ children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter w-full [--enter-delay:270ms]", children }) : null
1331
1449
  ] }),
1332
- art ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:col-span-5", children: art }) : null
1450
+ art ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter md:col-span-5 [--enter-delay:120ms]", children: art }) : null
1333
1451
  ] }) });
1334
1452
  }
1335
1453
  function DocHeader({
@@ -1342,8 +1460,8 @@ function DocHeader({
1342
1460
  className
1343
1461
  }) {
1344
1462
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
1345
- eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow", children: eyebrow }) : null,
1346
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2", children: title }),
1463
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-eyebrow oca-enter", children: eyebrow }) : null,
1464
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2 oca-enter [--enter-delay:70ms]", children: title }),
1347
1465
  lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead", children: lead }) : null,
1348
1466
  meta ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: meta }) : null,
1349
1467
  actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-3", children: actions }) : null,
@@ -2091,131 +2209,6 @@ function SatsFigure({
2091
2209
  hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] text-muted-foreground", children: hint }) : null
2092
2210
  ] });
2093
2211
  }
2094
- function prefersStill() {
2095
- return typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
2096
- }
2097
- function useInView(rootMargin = "0px 0px -12% 0px") {
2098
- const ref = react.useRef(null);
2099
- const [seen, setSeen] = react.useState(false);
2100
- react.useEffect(() => {
2101
- const el = ref.current;
2102
- if (!el || seen) return;
2103
- if (typeof IntersectionObserver === "undefined") {
2104
- setSeen(true);
2105
- return;
2106
- }
2107
- const io = new IntersectionObserver(
2108
- ([e]) => {
2109
- if (e?.isIntersecting) {
2110
- setSeen(true);
2111
- io.disconnect();
2112
- }
2113
- },
2114
- { rootMargin }
2115
- );
2116
- io.observe(el);
2117
- return () => io.disconnect();
2118
- }, [rootMargin, seen]);
2119
- return [ref, seen];
2120
- }
2121
- function Reveal({
2122
- as = "div",
2123
- delay = 0,
2124
- className,
2125
- style,
2126
- children
2127
- }) {
2128
- const ref = react.useRef(null);
2129
- react.useEffect(() => {
2130
- const el = ref.current;
2131
- if (!el || prefersStill() || typeof IntersectionObserver === "undefined") return;
2132
- if (el.getBoundingClientRect().top < window.innerHeight * 0.92) return;
2133
- el.dataset.reveal = "pending";
2134
- const io = new IntersectionObserver(
2135
- ([e]) => {
2136
- if (e?.isIntersecting) {
2137
- el.dataset.reveal = "shown";
2138
- io.disconnect();
2139
- }
2140
- },
2141
- { rootMargin: "0px 0px -10% 0px" }
2142
- );
2143
- io.observe(el);
2144
- return () => io.disconnect();
2145
- }, []);
2146
- return react.createElement(
2147
- as,
2148
- { ref, className, style: { ...style, "--reveal-delay": `${delay}ms` } },
2149
- children
2150
- );
2151
- }
2152
- function ScrollStory({
2153
- length = 2,
2154
- className,
2155
- innerClassName,
2156
- children
2157
- }) {
2158
- const ref = react.useRef(null);
2159
- const [pinned, setPinned] = react.useState(false);
2160
- react.useEffect(() => {
2161
- const el = ref.current;
2162
- if (!el || prefersStill()) return;
2163
- setPinned(true);
2164
- let raf = 0;
2165
- const update = () => {
2166
- raf = 0;
2167
- const r = el.getBoundingClientRect();
2168
- const travel = r.height - window.innerHeight;
2169
- const p = travel > 0 ? Math.min(1, Math.max(0, -r.top / travel)) : 0;
2170
- el.style.setProperty("--p", p.toFixed(4));
2171
- };
2172
- const on = () => {
2173
- if (!raf) raf = requestAnimationFrame(update);
2174
- };
2175
- update();
2176
- window.addEventListener("scroll", on, { passive: true });
2177
- window.addEventListener("resize", on);
2178
- return () => {
2179
- cancelAnimationFrame(raf);
2180
- window.removeEventListener("scroll", on);
2181
- window.removeEventListener("resize", on);
2182
- };
2183
- }, []);
2184
- 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 }) });
2185
- }
2186
- function Ticker({
2187
- value,
2188
- duration = 1200,
2189
- format = (n) => Math.round(n).toLocaleString("en-US"),
2190
- className
2191
- }) {
2192
- const [ref, seen] = useInView();
2193
- const [shown, setShown] = react.useState(value);
2194
- const animate = react.useRef(null);
2195
- react.useEffect(() => {
2196
- const el = ref.current;
2197
- if (!el || animate.current !== null) return;
2198
- animate.current = !prefersStill() && el.getBoundingClientRect().top > window.innerHeight * 0.9;
2199
- if (animate.current) setShown(0);
2200
- }, [ref]);
2201
- react.useEffect(() => {
2202
- if (!seen) return;
2203
- if (!animate.current) {
2204
- setShown(value);
2205
- return;
2206
- }
2207
- let raf = 0;
2208
- const t0 = performance.now();
2209
- const step = (now) => {
2210
- const k = Math.min(1, (now - t0) / duration);
2211
- setShown(value * (1 - Math.pow(1 - k, 3)));
2212
- if (k < 1) raf = requestAnimationFrame(step);
2213
- };
2214
- raf = requestAnimationFrame(step);
2215
- return () => cancelAnimationFrame(raf);
2216
- }, [seen, value, duration]);
2217
- return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("oca-tabular", className), children: format(shown) });
2218
- }
2219
2212
  function PhoneFrame({ className, style, children }) {
2220
2213
  return /* @__PURE__ */ jsxRuntime.jsx(
2221
2214
  "div",