@nadicodeai/ui 12.1.136 → 12.1.138
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/components/agent-orb.d.ts +5 -1
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/components/agent-orb.js +5 -1
- package/dist/components/brand.d.ts +5 -5
- package/dist/components/brand.d.ts.map +1 -1
- package/dist/components/brand.js +5 -5
- package/dist/components/catalog-entry.d.ts +5 -4
- package/dist/components/catalog-entry.d.ts.map +1 -1
- package/dist/components/catalog-entry.js +4 -3
- package/dist/components/company-card/renderer.d.ts +8 -0
- package/dist/components/company-card/renderer.d.ts.map +1 -1
- package/dist/components/company-card/renderer.js +122 -53
- package/dist/components/company-card.d.ts.map +1 -1
- package/dist/components/company-card.js +70 -39
- package/dist/components/hive-scene.d.ts.map +1 -1
- package/dist/components/hive-scene.js +46 -8
- package/dist/components/identity-mark.d.ts +4 -4
- package/dist/components/identity-mark.d.ts.map +1 -1
- package/dist/components/identity-mark.js +2 -3
- package/dist/components/scroll-area.js +3 -3
- package/dist/components/settings-section.d.ts +26 -15
- package/dist/components/settings-section.d.ts.map +1 -1
- package/dist/components/settings-section.js +23 -16
- package/dist/components/switch.d.ts +2 -1
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +3 -2
- package/dist/components/theme-mode-switcher.d.ts +1 -1
- package/dist/components/theme-mode-switcher.js +1 -1
- package/dist/internal/agent-orb-motion.d.ts +4 -0
- package/dist/internal/agent-orb-motion.d.ts.map +1 -1
- package/dist/internal/agent-orb-motion.js +1 -0
- package/dist/internal/agent-orb.d.ts +1 -0
- package/dist/internal/agent-orb.d.ts.map +1 -1
- package/dist/internal/agent-orb.js +207 -86
- package/dist/showcase/specimens/compositions.js +1 -1
- package/dist/showcase/specimens/inputs.d.ts.map +1 -1
- package/dist/showcase/specimens/inputs.js +2 -2
- package/dist/showcase/specimens/status.js +2 -2
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +13 -13
- package/dist/standalone/index.js +2 -2
- package/package.json +2 -2
|
@@ -35,7 +35,9 @@ export type AgentOrbProps = AgentOrbBaseProps & ({
|
|
|
35
35
|
* @family Status
|
|
36
36
|
* @when An Agent, anywhere: 20 in the sidebar, 32 in a row, 64 on her Profile card, 96 in an Agent
|
|
37
37
|
* card, 160 on entry. There is no other Agent picture. The sizes are 20, 24, 32, 40, 64, 96 and
|
|
38
|
-
* 160 px, and no other.
|
|
38
|
+
* 160 px, and no other. Detail follows the size the orb is drawn at: up to 32 px it draws the
|
|
39
|
+
* engine's lightest dot profile, at 40 px the middle one and from 64 px the full one, since a small
|
|
40
|
+
* orb cannot show the full profile's dots apart. On a photograph the orb takes the stronger `presence="over-picture"`
|
|
39
41
|
* weight; everywhere else it is `plain`.
|
|
40
42
|
* @instead A person is an `Avatar`. The system's own wait is the waiting line, never an orb. An orb
|
|
41
43
|
* in artwork, such as a sign-in picture, takes `motion="ambient"` and claims no activity. An orb
|
|
@@ -47,6 +49,8 @@ export type AgentOrbProps = AgentOrbBaseProps & ({
|
|
|
47
49
|
* Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath.
|
|
48
50
|
* A state change interrupts the previous gesture; `motionKey` replays it and `paused` freezes it. A surface that only knows a machine checked in draws idle. No state draws
|
|
49
51
|
* a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue.
|
|
52
|
+
* An orb at rest (idle, ambient, or done after its celebration) paints 15 frames a second; every
|
|
53
|
+
* other state, gesture and the celebration paint 30. The pace is the same at either rate.
|
|
50
54
|
* Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45
|
|
51
55
|
* opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep
|
|
52
56
|
* their centered signs without an entrance gesture.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-orb.d.ts","sourceRoot":"","sources":["../../src/components/agent-orb.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAqB,MAAM,OAAO,CAAC;AAE9D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAElB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,KAAK,iBAAiB,GAAG;IACvB,4FAA4F;IAC5F,IAAI,EAAE,cAAc,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,qEAAqE;IACrE,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,CAAC;IAAE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACrF,CAAC;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,UAAU,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEhF
|
|
1
|
+
{"version":3,"file":"agent-orb.d.ts","sourceRoot":"","sources":["../../src/components/agent-orb.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAqB,MAAM,OAAO,CAAC;AAE9D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAElB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,KAAK,iBAAiB,GAAG;IACvB,4FAA4F;IAC5F,IAAI,EAAE,cAAc,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,qEAAqE;IACrE,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,CAAC;IAAE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACrF,CAAC;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,UAAU,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,IAAS,EACT,QAAkB,EAClB,MAAc,EACd,KAAc,EACd,MAAiB,EACjB,SAAa,EACb,UAAkB,EAClB,KAAK,EACL,SAAS,GACV,EAAE,aAAa,+BAyDf"}
|
|
@@ -9,7 +9,9 @@ import { cn } from "../lib/utils.js";
|
|
|
9
9
|
* @family Status
|
|
10
10
|
* @when An Agent, anywhere: 20 in the sidebar, 32 in a row, 64 on her Profile card, 96 in an Agent
|
|
11
11
|
* card, 160 on entry. There is no other Agent picture. The sizes are 20, 24, 32, 40, 64, 96 and
|
|
12
|
-
* 160 px, and no other.
|
|
12
|
+
* 160 px, and no other. Detail follows the size the orb is drawn at: up to 32 px it draws the
|
|
13
|
+
* engine's lightest dot profile, at 40 px the middle one and from 64 px the full one, since a small
|
|
14
|
+
* orb cannot show the full profile's dots apart. On a photograph the orb takes the stronger `presence="over-picture"`
|
|
13
15
|
* weight; everywhere else it is `plain`.
|
|
14
16
|
* @instead A person is an `Avatar`. The system's own wait is the waiting line, never an orb. An orb
|
|
15
17
|
* in artwork, such as a sign-in picture, takes `motion="ambient"` and claims no activity. An orb
|
|
@@ -21,6 +23,8 @@ import { cn } from "../lib/utils.js";
|
|
|
21
23
|
* Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath.
|
|
22
24
|
* A state change interrupts the previous gesture; `motionKey` replays it and `paused` freezes it. A surface that only knows a machine checked in draws idle. No state draws
|
|
23
25
|
* a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue.
|
|
26
|
+
* An orb at rest (idle, ambient, or done after its celebration) paints 15 frames a second; every
|
|
27
|
+
* other state, gesture and the celebration paint 30. The pace is the same at either rate.
|
|
24
28
|
* Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45
|
|
25
29
|
* opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep
|
|
26
30
|
* their centered signs without an entrance gesture.
|
|
@@ -3,15 +3,15 @@ type BrandLogoProps = Omit<React.ComponentProps<"svg">, "aria-hidden" | "aria-la
|
|
|
3
3
|
alt?: string;
|
|
4
4
|
decoding?: React.ComponentProps<"img">["decoding"];
|
|
5
5
|
};
|
|
6
|
-
/** The
|
|
6
|
+
/** The mark: the n, nadicode's logo. Use it where the company is recognised by its sign. */
|
|
7
7
|
declare function BrandMark({ alt, className, width, height, decoding, ...props }: BrandLogoProps): React.JSX.Element;
|
|
8
|
-
/** The company logo: nadicode in full. Use it wherever the company is named. */
|
|
9
8
|
/**
|
|
10
|
-
* The
|
|
9
|
+
* The wordmark: nadicode in full.
|
|
11
10
|
*
|
|
12
11
|
* @family Status
|
|
13
|
-
* @when Wherever the company is named
|
|
14
|
-
*
|
|
12
|
+
* @when Wherever the company is named: the Portal's sidebar, the website's header, a footer.
|
|
13
|
+
* `BrandMark`, the n, where the company is recognised by its sign or the name does not fit; never
|
|
14
|
+
* the two side by side.
|
|
15
15
|
* @instead A product's own mark (Nadia, Alveare) is that product's. A platform's is `PlatformMark`.
|
|
16
16
|
* The company named in a sentence is text.
|
|
17
17
|
* @behaviour The letters take the text colour of what they sit in, so one form serves every ground.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/components/brand.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,KAAK,cAAc,GAAG,IAAI,CACxB,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAC3B,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CACnD,GAAG;IACF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;CACpD,CAAC;AAwCF,
|
|
1
|
+
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/components/brand.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,KAAK,cAAc,GAAG,IAAI,CACxB,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAC3B,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CACnD,GAAG;IACF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;CACpD,CAAC;AAwCF,4FAA4F;AAC5F,iBAAS,SAAS,CAAC,EACjB,GAAgB,EAChB,SAAS,EACT,KAAU,EACV,MAAW,EACX,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,qBAkBhB;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,aAAa,CAAC,EACrB,GAAgB,EAChB,SAAS,EACT,KAAW,EACX,MAAW,EACX,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,qBAkBhB;AAED,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/components/brand.js
CHANGED
|
@@ -28,19 +28,19 @@ const BRAND_PAINTS = { ink: "currentColor", dot: "var(--nc-logo-dot)" };
|
|
|
28
28
|
function resolved(geometry) {
|
|
29
29
|
return resolveLogoGeometry(geometry, { paints: BRAND_PAINTS });
|
|
30
30
|
}
|
|
31
|
-
/** The
|
|
31
|
+
/** The mark: the n, nadicode's logo. Use it where the company is recognised by its sign. */
|
|
32
32
|
function BrandMark({ alt = "nadicode", className, width = 32, height = 32, decoding, ...props }) {
|
|
33
33
|
void decoding;
|
|
34
34
|
const geometry = resolved(logoMarkGeometry);
|
|
35
35
|
return (_jsx("svg", { "data-slot": "brand-mark", xmlns: "http://www.w3.org/2000/svg", viewBox: geometry.viewBox, width: width, height: height, className: cn("block size-6", className), ...accessibilityProps(alt), ...props, children: renderGeometryNodes(geometry.nodes) }));
|
|
36
36
|
}
|
|
37
|
-
/** The company logo: nadicode in full. Use it wherever the company is named. */
|
|
38
37
|
/**
|
|
39
|
-
* The
|
|
38
|
+
* The wordmark: nadicode in full.
|
|
40
39
|
*
|
|
41
40
|
* @family Status
|
|
42
|
-
* @when Wherever the company is named
|
|
43
|
-
*
|
|
41
|
+
* @when Wherever the company is named: the Portal's sidebar, the website's header, a footer.
|
|
42
|
+
* `BrandMark`, the n, where the company is recognised by its sign or the name does not fit; never
|
|
43
|
+
* the two side by side.
|
|
44
44
|
* @instead A product's own mark (Nadia, Alveare) is that product's. A platform's is `PlatformMark`.
|
|
45
45
|
* The company named in a sentence is text.
|
|
46
46
|
* @behaviour The letters take the text colour of what they sit in, so one form serves every ground.
|
|
@@ -6,8 +6,9 @@ import type { PageCommand } from "./page-actions.js";
|
|
|
6
6
|
import type { RowMessage } from "../internal/row-message.js";
|
|
7
7
|
export type { RowMessage };
|
|
8
8
|
/**
|
|
9
|
-
* The line icon a catalog entry names. A name outside `CATALOG_ICONS`,
|
|
10
|
-
*
|
|
9
|
+
* The line icon a catalog entry names. A name outside `CATALOG_ICONS`, none,
|
|
10
|
+
* or the sparkle, which no product draws for an entry, takes its kind's own
|
|
11
|
+
* icon, the one the Skills or Plugins section has.
|
|
11
12
|
*/
|
|
12
13
|
export declare function catalogIcon(name: string | null | undefined, kind: "skill" | "plugin"): LucideIcon;
|
|
13
14
|
export type CatalogEntryAdd = PageCommand & {
|
|
@@ -23,13 +24,13 @@ export type CatalogEntryAdd = PageCommand & {
|
|
|
23
24
|
* @family Data
|
|
24
25
|
* @when A reusable thing a person can add: a skill, a plugin or an app, on a Library shelf (`LibraryShelf`) or in the drawer that adds one to an Agent (`CatalogDrawer`).
|
|
25
26
|
* @instead A record the person already holds is a row of its collection (`CollectionPage`). An Agent template is its `AgentCard`. Figures compared across entries are a `DataTable`.
|
|
26
|
-
* @behaviour The kind's tile at 40:
|
|
27
|
+
* @behaviour The kind's tile at 40: a skill's own icon on the neutral ringed tile, a plugin's on blue, an app's own logo. The name is the link to its own page. One Add control, outline with a leading plus; once held, a muted check and `added`'s word take its place. A menu of one command that is not destructive, with no Add, is that command's outline button; otherwise the three dots. A failed or refused add puts its message in the line's place, with its retry before the entry's own controls.
|
|
27
28
|
* @words The name as the catalogue gives it; one line saying what it does, a sentence: "Classifies incoming requests and prepares the next step." The control is a verb: "Add".
|
|
28
29
|
* @access The tile is decorative; the name is the link's text. A failed add's message is announced as an alert.
|
|
29
30
|
*/
|
|
30
31
|
export type CatalogEntryProps = {
|
|
31
32
|
id: string;
|
|
32
|
-
/** The kind's tile at 40: { kind: "record", icon: catalogIcon(name, "skill")
|
|
33
|
+
/** The kind's tile at 40: { kind: "record", icon: catalogIcon(name, "skill") }, or an app's logo. */
|
|
33
34
|
mark: IdentityMarkProps;
|
|
34
35
|
name: string;
|
|
35
36
|
link?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-entry.d.ts","sourceRoot":"","sources":["../../src/components/catalog-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAaL,KAAK,UAAU,EAiBhB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,CAAC;AAwC3B
|
|
1
|
+
{"version":3,"file":"catalog-entry.d.ts","sourceRoot":"","sources":["../../src/components/catalog-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAaL,KAAK,UAAU,EAiBhB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,CAAC;AAwC3B;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,CAEjG;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C,yFAAyF;IACzF,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,qGAAqG;IACrG,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,KAAK,SAAS,CAAC;KAC3E,CAAC;IACF,WAAW,EAAE,SAAS,CAAC;IACvB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;KAAE,CAAC;IAC3D,4EAA4E;IAC5E,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACvC,CAAC"}
|
|
@@ -32,9 +32,10 @@ function isCatalogIcon(name) {
|
|
|
32
32
|
return Object.hasOwn(ICONS, name);
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* The line icon a catalog entry names. A name outside `CATALOG_ICONS`,
|
|
36
|
-
*
|
|
35
|
+
* The line icon a catalog entry names. A name outside `CATALOG_ICONS`, none,
|
|
36
|
+
* or the sparkle, which no product draws for an entry, takes its kind's own
|
|
37
|
+
* icon, the one the Skills or Plugins section has.
|
|
37
38
|
*/
|
|
38
39
|
export function catalogIcon(name, kind) {
|
|
39
|
-
return name && isCatalogIcon(name) ? ICONS[name] : FALLBACK_ICONS[kind];
|
|
40
|
+
return name && name !== "sparkles" && isCatalogIcon(name) ? ICONS[name] : FALLBACK_ICONS[kind];
|
|
40
41
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import * as webgpu from "vgpu";
|
|
2
|
+
import type { Gpu, Surface, Target } from "vgpu";
|
|
1
3
|
import { type FoilColors } from "./scene.js";
|
|
4
|
+
type Webgpu = Pick<typeof webgpu, "clock" | "frameLoop" | "init"> & {
|
|
5
|
+
surface: (gpu: Gpu, canvas: HTMLCanvasElement, options: {
|
|
6
|
+
dpr: [number, number];
|
|
7
|
+
}) => Target & Pick<Surface, "onResize">;
|
|
8
|
+
};
|
|
2
9
|
type RendererOptions = {
|
|
3
10
|
colors: FoilColors;
|
|
11
|
+
vgpu?: Webgpu;
|
|
4
12
|
/** The card's current turn in radians, for the page to turn the card itself. */
|
|
5
13
|
onTilt: (tiltX: number, tiltY: number) => void;
|
|
6
14
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/components/company-card/renderer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/components/company-card/renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAA0B,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEzE,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AASvD,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC,GAAG;IAClE,OAAO,EAAE,CACP,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE;QAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,KAC/B,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;CACzC,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe;;;;EA+LjF"}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
// nadicode: vgpu's holographic card renderer (MIT, https://github.com/vercel-labs/vgpu,
|
|
2
|
-
// examples/holographic-card, revision 6fa27bb4), with its WebGPU set-up
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// within one card width; the turn it computes is handed to the page, which
|
|
6
|
-
// turns the card and its words together.
|
|
7
|
-
import { clock, frameLoop, init, surface } from "vgpu";
|
|
2
|
+
// examples/holographic-card, revision 6fa27bb4), with its WebGPU set-up and
|
|
3
|
+
// cleanup as they are.
|
|
4
|
+
import * as webgpu from "vgpu";
|
|
8
5
|
import { approach, SWEEP_MS, SWEEP_TURN } from "./approach.js";
|
|
9
6
|
import { createScene } from "./scene.js";
|
|
7
|
+
const AT_REST = 1e-4;
|
|
8
|
+
/**
|
|
9
|
+
* The first frame after the loop starts again counts as one frame of the
|
|
10
|
+
* 60 fps it runs at, not the time it was stopped.
|
|
11
|
+
*/
|
|
12
|
+
const FRAME_SECONDS = 1 / 60;
|
|
10
13
|
export function createRenderer(canvas, options) {
|
|
11
|
-
const { colors, onTilt } = options;
|
|
14
|
+
const { colors, onTilt, vgpu = webgpu } = options;
|
|
15
|
+
const { clock, frameLoop, init, surface } = vgpu;
|
|
12
16
|
let disposed = false;
|
|
13
17
|
let gpu;
|
|
14
18
|
let removeInput = () => { };
|
|
@@ -33,6 +37,7 @@ export function createRenderer(canvas, options) {
|
|
|
33
37
|
if (disposed)
|
|
34
38
|
return;
|
|
35
39
|
const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
40
|
+
const time = clock(context);
|
|
36
41
|
let targetHover = 0;
|
|
37
42
|
let pointerX = 0;
|
|
38
43
|
let pointerY = 0;
|
|
@@ -46,52 +51,32 @@ export function createRenderer(canvas, options) {
|
|
|
46
51
|
// from its top-left corner to its bottom-right, then rests. It tells a
|
|
47
52
|
// person at a glance that this is a card that answers the pointer.
|
|
48
53
|
let sweepStart = null;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return;
|
|
57
|
-
const near = approach(canvas.getBoundingClientRect(), event.clientX, event.clientY);
|
|
58
|
-
// A pointer elsewhere on the page leaves a sweep to finish; one that
|
|
59
|
-
// comes near takes the card over.
|
|
60
|
-
if (near.hover > 0)
|
|
61
|
-
sweepStart = null;
|
|
62
|
-
if (sweepStart !== null)
|
|
63
|
-
return;
|
|
64
|
-
pointerX = near.x;
|
|
65
|
-
pointerY = near.y;
|
|
66
|
-
targetHover = near.hover;
|
|
67
|
-
};
|
|
68
|
-
const leave = () => {
|
|
69
|
-
if (sweepStart === null)
|
|
70
|
-
targetHover = 0;
|
|
71
|
-
};
|
|
72
|
-
const up = (event) => {
|
|
73
|
-
if (event.pointerType !== "mouse")
|
|
74
|
-
leave();
|
|
75
|
-
};
|
|
76
|
-
const root = document.documentElement;
|
|
77
|
-
window.addEventListener("pointermove", move, { passive: true });
|
|
78
|
-
window.addEventListener("pointerdown", move, { passive: true });
|
|
79
|
-
window.addEventListener("pointercancel", leave);
|
|
80
|
-
window.addEventListener("pointerup", up);
|
|
81
|
-
root.addEventListener("pointerleave", leave);
|
|
82
|
-
const unsubscribeResize = output.onResize(() => {
|
|
83
|
-
shader.set({ params: { resolution: output.size } });
|
|
84
|
-
});
|
|
85
|
-
removeInput = () => {
|
|
86
|
-
window.removeEventListener("pointermove", move);
|
|
87
|
-
window.removeEventListener("pointerdown", move);
|
|
88
|
-
window.removeEventListener("pointercancel", leave);
|
|
89
|
-
window.removeEventListener("pointerup", up);
|
|
90
|
-
root.removeEventListener("pointerleave", leave);
|
|
91
|
-
unsubscribeResize();
|
|
54
|
+
let pointer = null;
|
|
55
|
+
let needsDraw = true;
|
|
56
|
+
let onScreen = false;
|
|
57
|
+
let loop = null;
|
|
58
|
+
const stop = () => {
|
|
59
|
+
loop?.stop();
|
|
60
|
+
loop = null;
|
|
92
61
|
};
|
|
93
|
-
const
|
|
94
|
-
|
|
62
|
+
const settled = (targetX, targetY, within) => sweepStart === null &&
|
|
63
|
+
Math.abs(targetX - tiltX) <= within &&
|
|
64
|
+
Math.abs(targetY - tiltY) <= within &&
|
|
65
|
+
Math.abs(targetHover - hover) <= within &&
|
|
66
|
+
(targetHover === 0 ||
|
|
67
|
+
(Math.abs(pointerX - lightX) <= within && Math.abs(pointerY - lightY) <= within));
|
|
68
|
+
const draw = (currentFrame) => {
|
|
69
|
+
if (pointer) {
|
|
70
|
+
const near = approach(canvas.getBoundingClientRect(), pointer.clientX, pointer.clientY);
|
|
71
|
+
pointer = null;
|
|
72
|
+
if (near.hover > 0)
|
|
73
|
+
sweepStart = null;
|
|
74
|
+
if (sweepStart === null) {
|
|
75
|
+
pointerX = near.x;
|
|
76
|
+
pointerY = near.y;
|
|
77
|
+
targetHover = near.hover;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
95
80
|
let turn = null;
|
|
96
81
|
if (sweepStart !== null) {
|
|
97
82
|
const progress = (performance.now() - sweepStart) / SWEEP_MS;
|
|
@@ -116,6 +101,11 @@ export function createRenderer(canvas, options) {
|
|
|
116
101
|
const targetY = motion.matches
|
|
117
102
|
? 0
|
|
118
103
|
: (turn?.[1] ?? -Math.max(-1, Math.min(1, pointerY)) * 0.12 * targetHover);
|
|
104
|
+
if (!needsDraw && settled(targetX, targetY, 0)) {
|
|
105
|
+
currentFrame.cancel();
|
|
106
|
+
stop();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
119
109
|
const blend = motion.matches ? 1 : 1 - Math.exp(-10 * Math.min(time.deltaTime, 0.1));
|
|
120
110
|
tiltX += (targetX - tiltX) * blend;
|
|
121
111
|
tiltY += (targetY - tiltY) * blend;
|
|
@@ -124,10 +114,89 @@ export function createRenderer(canvas, options) {
|
|
|
124
114
|
lightX += (pointerX - lightX) * blend;
|
|
125
115
|
lightY += (pointerY - lightY) * blend;
|
|
126
116
|
}
|
|
117
|
+
const resting = settled(targetX, targetY, AT_REST);
|
|
118
|
+
if (resting) {
|
|
119
|
+
tiltX = targetX;
|
|
120
|
+
tiltY = targetY;
|
|
121
|
+
hover = targetHover;
|
|
122
|
+
if (targetHover > 0) {
|
|
123
|
+
lightX = pointerX;
|
|
124
|
+
lightY = pointerY;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
127
|
onTilt(tiltX, tiltY);
|
|
128
128
|
shader.set({ params: { tilt: [tiltX, tiltY], pointer: [lightX, lightY], hover } });
|
|
129
129
|
currentFrame.pass(output, shader);
|
|
130
|
-
|
|
130
|
+
needsDraw = false;
|
|
131
|
+
if (resting)
|
|
132
|
+
stop();
|
|
133
|
+
};
|
|
134
|
+
const play = () => {
|
|
135
|
+
if (disposed || !onScreen || document.hidden) {
|
|
136
|
+
stop();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (loop)
|
|
140
|
+
return;
|
|
141
|
+
time.advance(FRAME_SECONDS);
|
|
142
|
+
loop = frameLoop(context, draw, { fps: 60 });
|
|
143
|
+
};
|
|
144
|
+
// Under reduced motion the card keeps still: the light moves only with the pointer.
|
|
145
|
+
requestSweep = () => {
|
|
146
|
+
if (motion.matches)
|
|
147
|
+
return;
|
|
148
|
+
sweepStart = performance.now();
|
|
149
|
+
play();
|
|
150
|
+
};
|
|
151
|
+
const move = (event) => {
|
|
152
|
+
if (!event.isPrimary)
|
|
153
|
+
return;
|
|
154
|
+
pointer = { clientX: event.clientX, clientY: event.clientY };
|
|
155
|
+
play();
|
|
156
|
+
};
|
|
157
|
+
const leave = () => {
|
|
158
|
+
pointer = null;
|
|
159
|
+
if (sweepStart === null)
|
|
160
|
+
targetHover = 0;
|
|
161
|
+
play();
|
|
162
|
+
};
|
|
163
|
+
const up = (event) => {
|
|
164
|
+
if (event.pointerType !== "mouse")
|
|
165
|
+
leave();
|
|
166
|
+
};
|
|
167
|
+
const root = document.documentElement;
|
|
168
|
+
window.addEventListener("pointermove", move, { passive: true });
|
|
169
|
+
window.addEventListener("pointerdown", move, { passive: true });
|
|
170
|
+
window.addEventListener("pointercancel", leave);
|
|
171
|
+
window.addEventListener("pointerup", up);
|
|
172
|
+
root.addEventListener("pointerleave", leave);
|
|
173
|
+
document.addEventListener("visibilitychange", play);
|
|
174
|
+
motion.addEventListener("change", play);
|
|
175
|
+
// vgpu sizes the canvas on a frame, so a card whose box changes takes one to be drawn again.
|
|
176
|
+
const unsubscribeResize = output.onResize(() => {
|
|
177
|
+
shader.set({ params: { resolution: output.size } });
|
|
178
|
+
needsDraw = true;
|
|
179
|
+
});
|
|
180
|
+
const box = new ResizeObserver(play);
|
|
181
|
+
box.observe(canvas);
|
|
182
|
+
const visibility = new IntersectionObserver((entries) => {
|
|
183
|
+
onScreen = entries.at(-1)?.isIntersecting ?? false;
|
|
184
|
+
play();
|
|
185
|
+
});
|
|
186
|
+
visibility.observe(canvas);
|
|
187
|
+
removeInput = () => {
|
|
188
|
+
stop();
|
|
189
|
+
window.removeEventListener("pointermove", move);
|
|
190
|
+
window.removeEventListener("pointerdown", move);
|
|
191
|
+
window.removeEventListener("pointercancel", leave);
|
|
192
|
+
window.removeEventListener("pointerup", up);
|
|
193
|
+
root.removeEventListener("pointerleave", leave);
|
|
194
|
+
document.removeEventListener("visibilitychange", play);
|
|
195
|
+
motion.removeEventListener("change", play);
|
|
196
|
+
unsubscribeResize();
|
|
197
|
+
box.disconnect();
|
|
198
|
+
visibility.disconnect();
|
|
199
|
+
};
|
|
131
200
|
})().catch((cause) => {
|
|
132
201
|
if (disposed)
|
|
133
202
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"company-card.d.ts","sourceRoot":"","sources":["../../src/components/company-card.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"company-card.d.ts","sourceRoot":"","sources":["../../src/components/company-card.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AA0BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,OAAO,EACP,MAAM,EACN,MAAM,EACN,IAAI,EACJ,WAAmB,GACpB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,+BAsTA"}
|
|
@@ -17,6 +17,10 @@ const FOIL = {
|
|
|
17
17
|
const STRIPE = 34;
|
|
18
18
|
/** How much of the card must be on screen before it turns, when the caller waits for it. */
|
|
19
19
|
const IN_VIEW = 0.6;
|
|
20
|
+
function setChanged(element, property, value) {
|
|
21
|
+
if (element.style.getPropertyValue(property) !== value)
|
|
22
|
+
element.style.setProperty(property, value);
|
|
23
|
+
}
|
|
20
24
|
function reason(cause) {
|
|
21
25
|
return cause instanceof Error ? cause.message : String(cause);
|
|
22
26
|
}
|
|
@@ -67,7 +71,6 @@ export function CompanyCard({ name, domain, edition, issued, labels, logo, sweep
|
|
|
67
71
|
const cardRef = useRef(null);
|
|
68
72
|
const lightRef = useRef(null);
|
|
69
73
|
const stripesRef = useRef(null);
|
|
70
|
-
const frame = useRef(0);
|
|
71
74
|
const canvasRef = useRef(null);
|
|
72
75
|
const [gpuFoil, setGpuFoil] = useState(false);
|
|
73
76
|
const sweepRef = useRef(() => { });
|
|
@@ -102,8 +105,8 @@ export function CompanyCard({ name, domain, edition, issued, labels, logo, sweep
|
|
|
102
105
|
const created = createRenderer(canvas, {
|
|
103
106
|
colors: foilColors(card, edition),
|
|
104
107
|
onTilt: (tiltX, tiltY) => {
|
|
105
|
-
card
|
|
106
|
-
card
|
|
108
|
+
setChanged(card, "--tilt-x", `${tiltY.toFixed(4)}rad`);
|
|
109
|
+
setChanged(card, "--tilt-y", `${tiltX.toFixed(4)}rad`);
|
|
107
110
|
},
|
|
108
111
|
});
|
|
109
112
|
renderer = created;
|
|
@@ -130,16 +133,17 @@ export function CompanyCard({ name, domain, edition, issued, labels, logo, sweep
|
|
|
130
133
|
setGpuFoil(false);
|
|
131
134
|
};
|
|
132
135
|
}, [edition, seen]);
|
|
133
|
-
// The SVG foil behaves as the shader does: it turns once in the light when it
|
|
134
|
-
// appears and when it is issued, and wakes as the pointer comes within one
|
|
135
|
-
// card width, easing its turn by how near the pointer is.
|
|
136
136
|
useEffect(() => {
|
|
137
137
|
const card = cardRef.current;
|
|
138
138
|
if (!seen || gpuFoil || !card)
|
|
139
139
|
return;
|
|
140
140
|
const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
141
|
+
let onScreen = typeof IntersectionObserver === "undefined";
|
|
142
|
+
let sweepStart = null;
|
|
141
143
|
let sweepFrame = 0;
|
|
142
|
-
let
|
|
144
|
+
let pointer = null;
|
|
145
|
+
let pointerFrame = 0;
|
|
146
|
+
const playing = () => onScreen && !document.hidden;
|
|
143
147
|
const light = (x, y) => {
|
|
144
148
|
lightRef.current?.setAttribute("cx", x.toFixed(3));
|
|
145
149
|
lightRef.current?.setAttribute("cy", y.toFixed(3));
|
|
@@ -162,59 +166,86 @@ export function CompanyCard({ name, domain, edition, issued, labels, logo, sweep
|
|
|
162
166
|
}
|
|
163
167
|
};
|
|
164
168
|
const stopSweep = () => {
|
|
165
|
-
|
|
169
|
+
sweepStart = null;
|
|
166
170
|
cancelAnimationFrame(sweepFrame);
|
|
167
171
|
};
|
|
172
|
+
const step = (now) => {
|
|
173
|
+
if (sweepStart === null)
|
|
174
|
+
return;
|
|
175
|
+
const progress = Math.min(1, (now - sweepStart) / SWEEP_MS);
|
|
176
|
+
const along = progress * progress * (3 - 2 * progress);
|
|
177
|
+
const rise = Math.sin(Math.PI * progress);
|
|
178
|
+
show(-0.05 + along * 1.1, 0.22 + along * 0.56, rise ** 0.6 * 0.95, rise * MAX_TILT_DEGREES * 0.3, -Math.sin(2 * Math.PI * along) * ((SWEEP_TURN * 180) / Math.PI));
|
|
179
|
+
if (progress < 1)
|
|
180
|
+
sweepFrame = requestAnimationFrame(step);
|
|
181
|
+
else {
|
|
182
|
+
sweepStart = null;
|
|
183
|
+
rest();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const follow = () => {
|
|
187
|
+
const at = pointer;
|
|
188
|
+
pointer = null;
|
|
189
|
+
if (!at)
|
|
190
|
+
return;
|
|
191
|
+
const near = approach(card.getBoundingClientRect(), at.clientX, at.clientY);
|
|
192
|
+
if (near.hover > 0)
|
|
193
|
+
stopSweep();
|
|
194
|
+
if (sweepStart !== null)
|
|
195
|
+
return;
|
|
196
|
+
if (near.hover === 0)
|
|
197
|
+
return rest();
|
|
198
|
+
const x = Math.min(1, Math.max(0, (near.x + 1) / 2));
|
|
199
|
+
const y = Math.min(1, Math.max(0, (near.y + 1) / 2));
|
|
200
|
+
show(x, y, near.hover, (0.5 - y) * 2 * MAX_TILT_DEGREES * near.hover, (x - 0.5) * 2 * MAX_TILT_DEGREES * near.hover);
|
|
201
|
+
};
|
|
202
|
+
const play = () => {
|
|
203
|
+
cancelAnimationFrame(sweepFrame);
|
|
204
|
+
cancelAnimationFrame(pointerFrame);
|
|
205
|
+
if (!playing())
|
|
206
|
+
return;
|
|
207
|
+
if (sweepStart !== null)
|
|
208
|
+
sweepFrame = requestAnimationFrame(step);
|
|
209
|
+
if (pointer)
|
|
210
|
+
pointerFrame = requestAnimationFrame(follow);
|
|
211
|
+
};
|
|
168
212
|
const sweep = () => {
|
|
169
213
|
if (motion.matches)
|
|
170
214
|
return;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const start = performance.now();
|
|
174
|
-
const step = (now) => {
|
|
175
|
-
const progress = Math.min(1, (now - start) / SWEEP_MS);
|
|
176
|
-
const along = progress * progress * (3 - 2 * progress);
|
|
177
|
-
const rise = Math.sin(Math.PI * progress);
|
|
178
|
-
show(-0.05 + along * 1.1, 0.22 + along * 0.56, rise ** 0.6 * 0.95, rise * MAX_TILT_DEGREES * 0.3, -Math.sin(2 * Math.PI * along) * ((SWEEP_TURN * 180) / Math.PI));
|
|
179
|
-
if (progress < 1)
|
|
180
|
-
sweepFrame = requestAnimationFrame(step);
|
|
181
|
-
else {
|
|
182
|
-
sweeping = false;
|
|
183
|
-
rest();
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
sweepFrame = requestAnimationFrame(step);
|
|
215
|
+
sweepStart = performance.now();
|
|
216
|
+
play();
|
|
187
217
|
};
|
|
188
218
|
const move = (event) => {
|
|
189
219
|
if (!event.isPrimary)
|
|
190
220
|
return;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return;
|
|
196
|
-
cancelAnimationFrame(frame.current);
|
|
197
|
-
frame.current = requestAnimationFrame(() => {
|
|
198
|
-
if (near.hover === 0)
|
|
199
|
-
return rest();
|
|
200
|
-
const x = Math.min(1, Math.max(0, (near.x + 1) / 2));
|
|
201
|
-
const y = Math.min(1, Math.max(0, (near.y + 1) / 2));
|
|
202
|
-
show(x, y, near.hover, (0.5 - y) * 2 * MAX_TILT_DEGREES * near.hover, (x - 0.5) * 2 * MAX_TILT_DEGREES * near.hover);
|
|
203
|
-
});
|
|
221
|
+
pointer = { clientX: event.clientX, clientY: event.clientY };
|
|
222
|
+
cancelAnimationFrame(pointerFrame);
|
|
223
|
+
if (playing())
|
|
224
|
+
pointerFrame = requestAnimationFrame(follow);
|
|
204
225
|
};
|
|
205
226
|
const leave = () => {
|
|
206
|
-
if (
|
|
227
|
+
if (sweepStart === null)
|
|
207
228
|
rest();
|
|
208
229
|
};
|
|
209
230
|
window.addEventListener("pointermove", move, { passive: true });
|
|
210
231
|
document.documentElement.addEventListener("pointerleave", leave);
|
|
232
|
+
document.addEventListener("visibilitychange", play);
|
|
233
|
+
const visibility = onScreen
|
|
234
|
+
? undefined
|
|
235
|
+
: new IntersectionObserver((entries) => {
|
|
236
|
+
onScreen = entries.at(-1)?.isIntersecting ?? false;
|
|
237
|
+
play();
|
|
238
|
+
});
|
|
239
|
+
visibility?.observe(card);
|
|
211
240
|
sweepRef.current = sweep;
|
|
212
241
|
sweep();
|
|
213
242
|
return () => {
|
|
214
243
|
window.removeEventListener("pointermove", move);
|
|
215
244
|
document.documentElement.removeEventListener("pointerleave", leave);
|
|
245
|
+
document.removeEventListener("visibilitychange", play);
|
|
246
|
+
visibility?.disconnect();
|
|
216
247
|
stopSweep();
|
|
217
|
-
cancelAnimationFrame(
|
|
248
|
+
cancelAnimationFrame(pointerFrame);
|
|
218
249
|
sweepRef.current = () => { };
|
|
219
250
|
rest();
|
|
220
251
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hive-scene.d.ts","sourceRoot":"","sources":["../../src/components/hive-scene.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,mFAAmF;AACnF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E,IAAI,EAAE,aAAa,CAAC;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,kFAAkF;IAClF,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mFAAmF;IACnF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,QAAQ,CAAC;IAC7D,iEAAiE;IACjE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAmLF;;;;;;;;;;;;;GAaG;AACH,iBAAS,SAAS,CAAC,EACjB,IAAI,EACJ,MAAkB,EAClB,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"hive-scene.d.ts","sourceRoot":"","sources":["../../src/components/hive-scene.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,mFAAmF;AACnF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E,IAAI,EAAE,aAAa,CAAC;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,kFAAkF;IAClF,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mFAAmF;IACnF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,QAAQ,CAAC;IAC7D,iEAAiE;IACjE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAmLF;;;;;;;;;;;;;GAaG;AACH,iBAAS,SAAS,CAAC,EACjB,IAAI,EACJ,MAAkB,EAClB,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,qBA8PhB;AAED,2DAA2D;AAC3D,iBAAS,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,qBAM9E;AAED,iEAAiE;AACjE,iBAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,EAAE,EACF,IAAa,GACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB,qBAMA;AAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC"}
|