@nadicodeai/ui 12.1.132 → 12.1.134
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 +8 -5
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/components/agent-orb.js +8 -5
- package/dist/components/avatar.d.ts +3 -3
- package/dist/components/avatar.js +3 -3
- package/dist/components/form-dialog.d.ts +8 -4
- package/dist/components/form-dialog.d.ts.map +1 -1
- package/dist/components/form-dialog.js +5 -5
- package/dist/components/identity-mark.d.ts +2 -4
- package/dist/components/identity-mark.d.ts.map +1 -1
- package/dist/components/identity-mark.js +10 -27
- package/dist/components/object-page.d.ts +4 -7
- package/dist/components/object-page.d.ts.map +1 -1
- package/dist/components/object-page.js +2 -2
- package/dist/internal/agent-orb-motion.d.ts +36 -5
- package/dist/internal/agent-orb-motion.d.ts.map +1 -1
- package/dist/internal/agent-orb-motion.js +153 -37
- package/dist/internal/agent-orb.d.ts.map +1 -1
- package/dist/internal/agent-orb.js +38 -20
- package/dist/internal/company-mark.d.ts +13 -0
- package/dist/internal/company-mark.d.ts.map +1 -0
- package/dist/internal/company-mark.js +8 -0
- package/dist/internal/form-submit.d.ts +2 -1
- package/dist/internal/form-submit.d.ts.map +1 -1
- package/dist/internal/form-submit.js +2 -2
- package/dist/showcase/specimens/other.js +1 -1
- package/dist/showcase/specimens/status.d.ts +2 -1
- package/dist/showcase/specimens/status.d.ts.map +1 -1
- package/dist/showcase/specimens/status.js +17 -3
- package/dist/showcase/usage.generated.js +8 -8
- package/dist/standalone/index.js +1 -1
- package/package.json +2 -2
- package/dist/internal/company-logo.d.ts +0 -17
- package/dist/internal/company-logo.d.ts.map +0 -1
- package/dist/internal/company-logo.js +0 -13
|
@@ -40,13 +40,16 @@ export type AgentOrbProps = AgentOrbBaseProps & ({
|
|
|
40
40
|
* @instead A person is an `Avatar`. The system's own wait is the waiting line, never an orb. An orb
|
|
41
41
|
* in artwork, such as a sign-in picture, takes `motion="ambient"` and claims no activity. An orb
|
|
42
42
|
* that stands for an Agent shows her real state.
|
|
43
|
-
* @behaviour The only thing that moves on its own. Idle
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* @behaviour The only thing that moves on its own. Idle particles turn at 86.4% of the form's native pace,
|
|
44
|
+
* with a separate 6.4 s breath. Working sweeps a ribbon every 3.2 s; thinking passes three pulses
|
|
45
|
+
* over 2.4 s. Waiting leans softly as centered pause bars arrive; blocked recoils as a centered
|
|
46
|
+
* stop sign lands. Both entrances settle over 2 s, then waiting breathes and blocked holds still.
|
|
47
|
+
* Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath.
|
|
48
|
+
* 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
|
|
47
49
|
* a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue.
|
|
48
50
|
* Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45
|
|
49
|
-
* opacity so busy still reads as busy,
|
|
51
|
+
* opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep
|
|
52
|
+
* their centered signs without an entrance gesture.
|
|
50
53
|
* An orb is one of seven forms, `ribbon`, `lattice`, `orbit`, `globe`, `network`, `braid` and
|
|
51
54
|
* `morph`, in one colour a person chose: cobalto, verde or arancio, or none, which draws it in the
|
|
52
55
|
* text colour. Giallo is not offered because it fails 3:1 on white; rosso is not offered because it
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;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"}
|
|
@@ -14,13 +14,16 @@ import { cn } from "../lib/utils.js";
|
|
|
14
14
|
* @instead A person is an `Avatar`. The system's own wait is the waiting line, never an orb. An orb
|
|
15
15
|
* in artwork, such as a sign-in picture, takes `motion="ambient"` and claims no activity. An orb
|
|
16
16
|
* that stands for an Agent shows her real state.
|
|
17
|
-
* @behaviour The only thing that moves on its own. Idle
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* @behaviour The only thing that moves on its own. Idle particles turn at 86.4% of the form's native pace,
|
|
18
|
+
* with a separate 6.4 s breath. Working sweeps a ribbon every 3.2 s; thinking passes three pulses
|
|
19
|
+
* over 2.4 s. Waiting leans softly as centered pause bars arrive; blocked recoils as a centered
|
|
20
|
+
* stop sign lands. Both entrances settle over 2 s, then waiting breathes and blocked holds still.
|
|
21
|
+
* Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath.
|
|
22
|
+
* 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
|
|
21
23
|
* a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue.
|
|
22
24
|
* Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45
|
|
23
|
-
* opacity so busy still reads as busy,
|
|
25
|
+
* opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep
|
|
26
|
+
* their centered signs without an entrance gesture.
|
|
24
27
|
* An orb is one of seven forms, `ribbon`, `lattice`, `orbit`, `globe`, `network`, `braid` and
|
|
25
28
|
* `morph`, in one colour a person chose: cobalto, verde or arancio, or none, which draws it in the
|
|
26
29
|
* text colour. Giallo is not offered because it fails 3:1 on white; rosso is not offered because it
|
|
@@ -34,9 +34,9 @@ type AvatarProps = AvatarRootProps & AvatarName & {
|
|
|
34
34
|
* `AvatarWithIcon` puts a status glyph at the corner of a person's avatar; its `name` is required
|
|
35
35
|
* and gives the initials, and, like `Avatar`, the type asks for `label` (naming the person and the
|
|
36
36
|
* state) or `decorative`.
|
|
37
|
-
* @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is
|
|
38
|
-
*
|
|
39
|
-
* draws an `Avatar` for a person. There are no git-provider avatars and no fetch of a picture by
|
|
37
|
+
* @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is never an avatar:
|
|
38
|
+
* it is `IdentityMark`'s company mark, its logo or else its initials on a dark tile. A record's
|
|
39
|
+
* mark, a person's included, is `IdentityMark`, which draws an `Avatar` for a person. There are no git-provider avatars and no fetch of a picture by
|
|
40
40
|
* username.
|
|
41
41
|
* @behaviour "By default the first member sits on top of the stack, so the first credited author stays the most prominent." (https://vercel.com/geist/avatar)
|
|
42
42
|
* "Set `reverse` to flip the order so the last member sits on top instead." (https://vercel.com/geist/avatar)
|
|
@@ -53,9 +53,9 @@ function avatarInitials(name, length = 2) {
|
|
|
53
53
|
* `AvatarWithIcon` puts a status glyph at the corner of a person's avatar; its `name` is required
|
|
54
54
|
* and gives the initials, and, like `Avatar`, the type asks for `label` (naming the person and the
|
|
55
55
|
* state) or `decorative`.
|
|
56
|
-
* @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is
|
|
57
|
-
*
|
|
58
|
-
* draws an `Avatar` for a person. There are no git-provider avatars and no fetch of a picture by
|
|
56
|
+
* @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is never an avatar:
|
|
57
|
+
* it is `IdentityMark`'s company mark, its logo or else its initials on a dark tile. A record's
|
|
58
|
+
* mark, a person's included, is `IdentityMark`, which draws an `Avatar` for a person. There are no git-provider avatars and no fetch of a picture by
|
|
59
59
|
* username.
|
|
60
60
|
* @behaviour "By default the first member sits on top of the stack, so the first credited author stays the most prominent." (https://vercel.com/geist/avatar)
|
|
61
61
|
* "Set `reverse` to flip the order so the last member sits on top instead." (https://vercel.com/geist/avatar)
|
|
@@ -4,16 +4,20 @@ export type FormDialogProps = FormSurfaceProps & {
|
|
|
4
4
|
/** Its form's save is running: the dialog stays open until it settles. */
|
|
5
5
|
pending?: boolean;
|
|
6
6
|
};
|
|
7
|
+
export type FormDialogFormProps = FormProps & {
|
|
8
|
+
/** The primary removes, closes or refuses something, as a decline with a note: it turns red. */
|
|
9
|
+
destructive?: boolean;
|
|
10
|
+
};
|
|
7
11
|
/**
|
|
8
12
|
* A new record, or one or two values from a command, in a modal dialog.
|
|
9
13
|
*
|
|
10
14
|
* @family Compositions
|
|
11
15
|
* @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
|
|
12
|
-
* @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
|
|
13
|
-
* @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close. How long it stays open while work goes on follows DESIGN.md "System activity".
|
|
14
|
-
* @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
|
|
16
|
+
* @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence that asks nothing is confirmed in a `ConfirmDialog`.
|
|
17
|
+
* @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close. A form whose primary takes something away, such as declining a company with a note for the record, sets `destructive` on `FormDialogForm`: the primary turns red, as `ConfirmDialog`'s destructive confirm does, and nothing else changes. How long it stays open while work goes on follows DESIGN.md "System activity".
|
|
18
|
+
* @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox"; a destructive primary names what it takes away, "Decline company", never a bare "Decline".
|
|
15
19
|
* @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
|
|
16
20
|
*/
|
|
17
21
|
export declare function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus, unsaved, pending, }: FormDialogProps): import("react").JSX.Element;
|
|
18
|
-
export declare function FormDialogForm({ cancelLabel, submit, notice, children, ...form }:
|
|
22
|
+
export declare function FormDialogForm({ cancelLabel, submit, notice, destructive, children, ...form }: FormDialogFormProps): import("react").JSX.Element;
|
|
19
23
|
//# sourceMappingURL=form-dialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-dialog.d.ts","sourceRoot":"","sources":["../../src/components/form-dialog.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAG1E,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG;IAC/C,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,YAAY,EACZ,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAiB,EACjB,OAAO,EACP,OAAe,GAChB,EAAE,eAAe,+BAmBjB;AAED,wBAAgB,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"form-dialog.d.ts","sourceRoot":"","sources":["../../src/components/form-dialog.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAG1E,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG;IAC/C,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C,gGAAgG;IAChG,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,YAAY,EACZ,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAiB,EACjB,OAAO,EACP,OAAe,GAChB,EAAE,eAAe,+BAmBjB;AAED,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,MAAM,EACN,MAAM,EACN,WAAmB,EACnB,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAsBrB"}
|
|
@@ -10,9 +10,9 @@ import { guardUnsaved } from "../internal/unsaved-guard.js";
|
|
|
10
10
|
*
|
|
11
11
|
* @family Compositions
|
|
12
12
|
* @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
|
|
13
|
-
* @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
|
|
14
|
-
* @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close. How long it stays open while work goes on follows DESIGN.md "System activity".
|
|
15
|
-
* @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
|
|
13
|
+
* @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence that asks nothing is confirmed in a `ConfirmDialog`.
|
|
14
|
+
* @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close. A form whose primary takes something away, such as declining a company with a note for the record, sets `destructive` on `FormDialogForm`: the primary turns red, as `ConfirmDialog`'s destructive confirm does, and nothing else changes. How long it stays open while work goes on follows DESIGN.md "System activity".
|
|
15
|
+
* @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox"; a destructive primary names what it takes away, "Decline company", never a bare "Decline".
|
|
16
16
|
* @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
|
|
17
17
|
*/
|
|
18
18
|
export function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus = true, unsaved, pending = false, }) {
|
|
@@ -22,7 +22,7 @@ export function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, de
|
|
|
22
22
|
requestOpenChange(next, details);
|
|
23
23
|
}, onOpenChangeComplete: onOpenChangeComplete, children: _jsxs(DialogContent, { closeLabel: closeLabel, initialFocus: initialFocus, finalFocus: finalFocus, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title }), description ? _jsx(DialogDescription, { children: description }) : null] }), children] }) }));
|
|
24
24
|
}
|
|
25
|
-
export function FormDialogForm({ cancelLabel, submit, notice, children, ...form }) {
|
|
25
|
+
export function FormDialogForm({ cancelLabel, submit, notice, destructive = false, children, ...form }) {
|
|
26
26
|
const pending = submit.pending === true;
|
|
27
|
-
return (_jsxs("form", { className: "flex min-h-0 flex-col gap-(--dialog-gap)", "aria-busy": pending || undefined, "data-slot": "form-dialog-form", ...form, children: [_jsx(DialogBody, { children: children }), notice, _jsxs(DialogFooter, { className: "relative", children: [_jsx(DialogClose, { disabled: pending, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancelLabel }), _jsx(FormSubmitButton, { submit: submit }), pending ? (_jsx(WaitingLine, { className: "absolute inset-x-nadicode-sm bottom-1 w-auto", decorative: true })) : null] })] }));
|
|
27
|
+
return (_jsxs("form", { className: "flex min-h-0 flex-col gap-(--dialog-gap)", "aria-busy": pending || undefined, "data-slot": "form-dialog-form", ...form, children: [_jsx(DialogBody, { children: children }), notice, _jsxs(DialogFooter, { className: "relative", children: [_jsx(DialogClose, { disabled: pending, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancelLabel }), _jsx(FormSubmitButton, { destructive: destructive, submit: submit }), pending ? (_jsx(WaitingLine, { className: "absolute inset-x-nadicode-sm bottom-1 w-auto", decorative: true })) : null] })] }));
|
|
28
28
|
}
|
|
@@ -32,8 +32,6 @@ export type IdentityMarkProps = {
|
|
|
32
32
|
* The company's own logo, kept by lookup in its original colours and proportions.
|
|
33
33
|
*/
|
|
34
34
|
logo?: string;
|
|
35
|
-
/** The company's standing, independent of which directory opened it. */
|
|
36
|
-
edition?: "company" | "partner";
|
|
37
35
|
} | {
|
|
38
36
|
kind: "model";
|
|
39
37
|
/** The model maker's author slug, as `ModelMark` takes it: a key held at that maker. */
|
|
@@ -54,13 +52,13 @@ export type IdentityMarkProps = {
|
|
|
54
52
|
/**
|
|
55
53
|
* What says which thing a record is, at a fixed size at the start of its row,
|
|
56
54
|
* its object's head or its feed line: an Agent's orb, an app's logo, a model
|
|
57
|
-
* maker's mark, a company's initials, a person's picture, or a record kind's
|
|
55
|
+
* maker's mark, a company's logo or initials, a person's picture, or a record kind's
|
|
58
56
|
* icon on its tile.
|
|
59
57
|
*
|
|
60
58
|
* @family Status
|
|
61
59
|
* @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
|
|
62
60
|
* @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
|
|
63
|
-
* @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in
|
|
61
|
+
* @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
|
|
64
62
|
* @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
|
|
65
63
|
* @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
|
|
66
64
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,0FAA0F;IAC1F,IAAI,EAAE,aAAa,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AA6DF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CA6DhE"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { AgentOrb, } from "./agent-orb.js";
|
|
3
3
|
import { AppMark } from "./app-mark.js";
|
|
4
|
-
import { Avatar, AvatarFallback, AvatarImage } from "./avatar.js";
|
|
4
|
+
import { Avatar, AvatarFallback, AvatarImage, avatarInitials } from "./avatar.js";
|
|
5
5
|
import { ModelMark } from "./model-mark.js";
|
|
6
|
-
import {
|
|
6
|
+
import { CompanyMark } from "../internal/company-mark.js";
|
|
7
7
|
import { cn } from "../lib/utils.js";
|
|
8
8
|
const MEASURES = {
|
|
9
9
|
20: { orb: 20, icon: 12, initials: 8 },
|
|
@@ -18,18 +18,7 @@ const TONES = {
|
|
|
18
18
|
skill: "bg-category-purple text-category-purple-foreground",
|
|
19
19
|
plugin: "bg-info-soft text-info-soft-foreground",
|
|
20
20
|
teal: "bg-category-teal text-category-teal-foreground",
|
|
21
|
-
company: "bg-nc-identity-cobalto text-nc-identity-white",
|
|
22
|
-
partner: "bg-nc-identity-arancio text-nc-identity-ink",
|
|
23
21
|
};
|
|
24
|
-
function identityInitials(name) {
|
|
25
|
-
return name
|
|
26
|
-
.split(/\s+/)
|
|
27
|
-
.map((word) => word.match(/^[\p{L}\p{N}]/u)?.[0])
|
|
28
|
-
.filter((initial) => initial !== undefined)
|
|
29
|
-
.slice(0, 2)
|
|
30
|
-
.join("")
|
|
31
|
-
.toUpperCase();
|
|
32
|
-
}
|
|
33
22
|
function naming(label) {
|
|
34
23
|
return label
|
|
35
24
|
? { role: "img", "aria-label": label }
|
|
@@ -38,23 +27,19 @@ function naming(label) {
|
|
|
38
27
|
function avatarName(label) {
|
|
39
28
|
return label ? { label } : { decorative: true };
|
|
40
29
|
}
|
|
41
|
-
function
|
|
42
|
-
return (_jsx("span", { className: cn("inline-flex shrink-0 items-center justify-center", kind
|
|
43
|
-
? "rounded-t-full rounded-b-sm"
|
|
44
|
-
: size >= 40
|
|
45
|
-
? "rounded-md"
|
|
46
|
-
: "rounded-sm", TONES[tone]), "data-kind": kind, "data-slot": "identity-mark", style: { width: size, height: size }, ...naming(label), children: children }));
|
|
30
|
+
function RecordTile({ label, size, tone, children, }) {
|
|
31
|
+
return (_jsx("span", { className: cn("inline-flex shrink-0 items-center justify-center", size >= 40 ? "rounded-md" : "rounded-sm", TONES[tone]), "data-kind": "record", "data-slot": "identity-mark", style: { width: size, height: size }, ...naming(label), children: children }));
|
|
47
32
|
}
|
|
48
33
|
/**
|
|
49
34
|
* What says which thing a record is, at a fixed size at the start of its row,
|
|
50
35
|
* its object's head or its feed line: an Agent's orb, an app's logo, a model
|
|
51
|
-
* maker's mark, a company's initials, a person's picture, or a record kind's
|
|
36
|
+
* maker's mark, a company's logo or initials, a person's picture, or a record kind's
|
|
52
37
|
* icon on its tile.
|
|
53
38
|
*
|
|
54
39
|
* @family Status
|
|
55
40
|
* @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
|
|
56
41
|
* @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
|
|
57
|
-
* @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in
|
|
42
|
+
* @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
|
|
58
43
|
* @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
|
|
59
44
|
* @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
|
|
60
45
|
*/
|
|
@@ -71,12 +56,10 @@ export function IdentityMark(props) {
|
|
|
71
56
|
case "model":
|
|
72
57
|
return _jsx(ModelMark, { author: props.author, label: props.label, size: size });
|
|
73
58
|
case "person":
|
|
74
|
-
return (_jsxs(Avatar, { "data-kind": "person", "data-slot": "identity-mark", style: { width: size, height: size }, ...avatarName(props.label), children: [props.image ? _jsx(AvatarImage, { alt: "", src: props.image }) : null, _jsx(AvatarFallback, { style: { fontSize: measures.initials }, children:
|
|
75
|
-
case "company":
|
|
76
|
-
|
|
77
|
-
return props.logo ? (_jsx(CompanyLogo, { fallback: initials, logo: props.logo, naming: naming(props.label), size: size })) : (initials);
|
|
78
|
-
}
|
|
59
|
+
return (_jsxs(Avatar, { "data-kind": "person", "data-slot": "identity-mark", style: { width: size, height: size }, ...avatarName(props.label), children: [props.image ? _jsx(AvatarImage, { alt: "", src: props.image }) : null, _jsx(AvatarFallback, { style: { fontSize: measures.initials }, children: avatarInitials(props.name) })] }));
|
|
60
|
+
case "company":
|
|
61
|
+
return (_jsx(CompanyMark, { initialsSize: measures.initials, logo: props.logo, name: props.name, naming: naming(props.label), size: size }));
|
|
79
62
|
case "record":
|
|
80
|
-
return (_jsx(
|
|
63
|
+
return (_jsx(RecordTile, { label: props.label, size: size, tone: props.tone ?? "neutral", children: props.picture ? (_jsx("img", { alt: "", className: "size-[84%] object-contain", "data-slot": "identity-mark-picture", src: props.picture })) : (_jsx(props.icon, { "aria-hidden": "true", size: measures.icon })) }));
|
|
81
64
|
}
|
|
82
65
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ComponentProps, ReactElement, ReactNode } from "react";
|
|
2
2
|
import { type IdentityMarkProps } from "./identity-mark.js";
|
|
3
|
-
import { type
|
|
3
|
+
import { type PageActionsProps } from "./page-actions.js";
|
|
4
4
|
type ObjectPageFact = {
|
|
5
5
|
label: string;
|
|
6
6
|
value: ReactNode;
|
|
@@ -35,11 +35,8 @@ export type ObjectPageProps = {
|
|
|
35
35
|
description?: ReactNode;
|
|
36
36
|
/** Key facts as labelled values in one row; an object always has at least one. */
|
|
37
37
|
facts: readonly [ObjectPageFact, ...ObjectPageFact[]];
|
|
38
|
-
/** The object's commands on its header bar:
|
|
39
|
-
actions?:
|
|
40
|
-
secondary?: PageCommand;
|
|
41
|
-
menu?: PageMenu;
|
|
42
|
-
};
|
|
38
|
+
/** The object's commands on its header bar: a secondary, the primary, then the three dots. */
|
|
39
|
+
actions?: Omit<PageActionsProps, "period">;
|
|
43
40
|
/** Rows that open under the facts, each one part of the object: settings, logs, checks. */
|
|
44
41
|
entries?: readonly ObjectPageEntry[];
|
|
45
42
|
/** The footer: a hint and one link elsewhere. Left out when the object has no such line. */
|
|
@@ -54,7 +51,7 @@ export type ObjectPageProps = {
|
|
|
54
51
|
* @family Compositions
|
|
55
52
|
* @when One thing a person opened from a list and now reads or acts on: a customer, a partner, an Installation, a Library entry.
|
|
56
53
|
* @instead "Use Context Card to reveal entity metadata on hover or focus: a user, a deployment, a project, an API key." (https://vercel.com/geist/context-card) Ours: that hover is a `HoverCard`, never this page. A list of records is a CollectionPage; a page of settings only is a SettingsPage, whose cards are SettingsSections; an Agent opens on its AgentProfileCard, the documented exception. A card of values a person saves is a setting card, never this one.
|
|
57
|
-
* @behaviour "For a static key/value metadata block on a detail page, use `Description`." (https://vercel.com/geist/entity) "The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`." (https://vercel.com/geist/entity) "Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`)." (https://vercel.com/geist/entity) "Don’t put interactive controls in the title slot. Buttons, menus, and links belong in the content (`<dd>`) or in the parent layout, not the label (`<dt>`)." (https://vercel.com/geist/description) Ours: as Vercel's deployment page (Deployment Details, then its steps), the object card is the first card of the page: a header bar with the name at the start and the object's commands at the end (
|
|
54
|
+
* @behaviour "For a static key/value metadata block on a detail page, use `Description`." (https://vercel.com/geist/entity) "The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`." (https://vercel.com/geist/entity) "Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`)." (https://vercel.com/geist/entity) "Don’t put interactive controls in the title slot. Buttons, menus, and links belong in the content (`<dd>`) or in the parent layout, not the label (`<dt>`)." (https://vercel.com/geist/description) Ours: as Vercel's deployment page (Deployment Details, then its steps), the object card is the first card of the page: a header bar with the name at the start and the object's commands at the end (a secondary, then the primary as the filled button, then the three dots, in `PageActions`' order, on the name's row while the name keeps 128 px, as on a phone, and under it otherwise; the primary is the one thing the object waits on its viewer for, such as approving a company that waits for approval, beside its alternative as the secondary, and an object with nothing waiting has none), for a company, the compact mark at 64 stands beside the name and optional line in the header, followed by full-width facts with four columns from `lg` and two below; other object kinds keep their mark and line beside their facts in the existing preview treatment (at least one fact is required: an object is never shown without what it is), each a muted label over its value in body text, then an optional footer with a hint at the start and one link at the end. Optional `entries` follow in a card of their own 12 px under it: rows that open one by one, each with its chevron first (it turns down when open), its title, and its summary at the trailing edge, as Vercel's Build Logs and Deployment Checks rows. The footer takes a link only, so no Save or other command of the object fits in it; the object's changes live in its sections, each a setting card with its own footer. The sections follow, 24 apart, each drawing its own states. The card is neutral; colour belongs to the company's compact identity, a semantic fact value, or an entry's status summary, with no coloured card ground.
|
|
58
55
|
* @words "Keep right-column buttons Verb + Noun (`Remove Member`, `Resend Invite`). Bare verbs like `Remove` or `Confirm` lose context once the row scrolls offscreen." (https://vercel.com/geist/entity) "Title slot is Title Case noun (`Last Deployed`, `Build Duration`); content is sentence case unless the value is a literal identifier, ID, or timestamp that should be preserved verbatim." (https://vercel.com/geist/description) Ours: sentence case throughout. The name as the object is called everywhere else; the line says what it is and whose ("Customer of Partner Alpha · since 3 August 2026"); a fact's label is a noun ("Plan"), its value the figure; an entry's title is a noun phrase; the hint is one sentence ("To update it, push to the main branch."); the link names where it goes ("Deployments"); the menu's trigger reads "More for {name}".
|
|
59
56
|
* @access "Geist renders `<dl>`/`<dt>`/`<dd>` so screen readers announce each key/value pair as a definition." (https://vercel.com/geist/description) "Don’t wrap the component in extra paragraphs that break the list semantics." (https://vercel.com/geist/description) Ours: with `headingProps` the name is the page's h1; without them it is text, for a product whose chrome already titles the page. The mark is decorative beside the facts. Each entry is a button with `aria-expanded` that controls its panel.
|
|
60
57
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-page.d.ts","sourceRoot":"","sources":["../../src/components/object-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMrE,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"object-page.d.ts","sourceRoot":"","sources":["../../src/components/object-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMrE,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,KAAK,gBAAgB,EAAqC,MAAM,gBAAgB,CAAC;AAE1F,KAAK,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG;IAC5B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,YAAY,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kHAAkH;IAClH,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,wFAAwF;IACxF,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,YAAY,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;IACtD,qFAAqF;IACrF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,kFAAkF;IAClF,KAAK,EAAE,SAAS,CAAC,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;IACtD,8FAA8F;IAC9F,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC3C,2FAA2F;IAC3F,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,4FAA4F;IAC5F,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,+HAA+H;IAC/H,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACT,EAAE,eAAe,GAAG,YAAY,CA8FhC"}
|
|
@@ -12,12 +12,12 @@ import { PageActionsRow, PageCommandButton } from "./page-actions.js";
|
|
|
12
12
|
* @family Compositions
|
|
13
13
|
* @when One thing a person opened from a list and now reads or acts on: a customer, a partner, an Installation, a Library entry.
|
|
14
14
|
* @instead "Use Context Card to reveal entity metadata on hover or focus: a user, a deployment, a project, an API key." (https://vercel.com/geist/context-card) Ours: that hover is a `HoverCard`, never this page. A list of records is a CollectionPage; a page of settings only is a SettingsPage, whose cards are SettingsSections; an Agent opens on its AgentProfileCard, the documented exception. A card of values a person saves is a setting card, never this one.
|
|
15
|
-
* @behaviour "For a static key/value metadata block on a detail page, use `Description`." (https://vercel.com/geist/entity) "The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`." (https://vercel.com/geist/entity) "Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`)." (https://vercel.com/geist/entity) "Don’t put interactive controls in the title slot. Buttons, menus, and links belong in the content (`<dd>`) or in the parent layout, not the label (`<dt>`)." (https://vercel.com/geist/description) Ours: as Vercel's deployment page (Deployment Details, then its steps), the object card is the first card of the page: a header bar with the name at the start and the object's commands at the end (
|
|
15
|
+
* @behaviour "For a static key/value metadata block on a detail page, use `Description`." (https://vercel.com/geist/entity) "The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`." (https://vercel.com/geist/entity) "Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`)." (https://vercel.com/geist/entity) "Don’t put interactive controls in the title slot. Buttons, menus, and links belong in the content (`<dd>`) or in the parent layout, not the label (`<dt>`)." (https://vercel.com/geist/description) Ours: as Vercel's deployment page (Deployment Details, then its steps), the object card is the first card of the page: a header bar with the name at the start and the object's commands at the end (a secondary, then the primary as the filled button, then the three dots, in `PageActions`' order, on the name's row while the name keeps 128 px, as on a phone, and under it otherwise; the primary is the one thing the object waits on its viewer for, such as approving a company that waits for approval, beside its alternative as the secondary, and an object with nothing waiting has none), for a company, the compact mark at 64 stands beside the name and optional line in the header, followed by full-width facts with four columns from `lg` and two below; other object kinds keep their mark and line beside their facts in the existing preview treatment (at least one fact is required: an object is never shown without what it is), each a muted label over its value in body text, then an optional footer with a hint at the start and one link at the end. Optional `entries` follow in a card of their own 12 px under it: rows that open one by one, each with its chevron first (it turns down when open), its title, and its summary at the trailing edge, as Vercel's Build Logs and Deployment Checks rows. The footer takes a link only, so no Save or other command of the object fits in it; the object's changes live in its sections, each a setting card with its own footer. The sections follow, 24 apart, each drawing its own states. The card is neutral; colour belongs to the company's compact identity, a semantic fact value, or an entry's status summary, with no coloured card ground.
|
|
16
16
|
* @words "Keep right-column buttons Verb + Noun (`Remove Member`, `Resend Invite`). Bare verbs like `Remove` or `Confirm` lose context once the row scrolls offscreen." (https://vercel.com/geist/entity) "Title slot is Title Case noun (`Last Deployed`, `Build Duration`); content is sentence case unless the value is a literal identifier, ID, or timestamp that should be preserved verbatim." (https://vercel.com/geist/description) Ours: sentence case throughout. The name as the object is called everywhere else; the line says what it is and whose ("Customer of Partner Alpha · since 3 August 2026"); a fact's label is a noun ("Plan"), its value the figure; an entry's title is a noun phrase; the hint is one sentence ("To update it, push to the main branch."); the link names where it goes ("Deployments"); the menu's trigger reads "More for {name}".
|
|
17
17
|
* @access "Geist renders `<dl>`/`<dt>`/`<dd>` so screen readers announce each key/value pair as a definition." (https://vercel.com/geist/description) "Don’t wrap the component in extra paragraphs that break the list semantics." (https://vercel.com/geist/description) Ours: with `headingProps` the name is the page's h1; without them it is text, for a product whose chrome already titles the page. The mark is decorative beside the facts. Each entry is a button with `aria-expanded` that controls its panel.
|
|
18
18
|
*/
|
|
19
19
|
export function ObjectPage({ mark, name, headingProps, description, facts, actions, entries, footer, children, }) {
|
|
20
20
|
const company = mark.kind === "company";
|
|
21
21
|
const title = headingProps ? (_jsx("h1", { ...headingProps, className: cn("outline-none", headingProps.className), children: name })) : (name);
|
|
22
|
-
return (_jsxs("div", { className: "grid min-w-0 gap-6", "data-slot": "object-page", children: [_jsxs("div", { className: "grid min-w-0 gap-3", children: [_jsxs(Card, { className: "min-w-0", render: _jsx("div", { "data-slot": "object-card" }), size: "sm", children: [_jsxs(CardHeader, { className: "flex flex-wrap items-center justify-between gap-x-4 gap-y-3 border-b", children: [company ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 items-center gap-4", actions?.menu && !actions.secondary ? "basis-0" : "basis-64"), children: [_jsx(IdentityMark, { ...mark, size: 64 }), _jsxs("div", { className: "grid min-w-0 gap-1", children: [_jsx(CardTitle, { className: "min-w-0 break-words group-data-[size=sm]/card:text-heading-sm", children: title }), description ? _jsx(CardDescription, { children: description }) : null] })] })) : (_jsx(CardTitle, { className: "min-w-0 flex-1 basis-32 break-words", children: title })), actions
|
|
22
|
+
return (_jsxs("div", { className: "grid min-w-0 gap-6", "data-slot": "object-page", children: [_jsxs("div", { className: "grid min-w-0 gap-3", children: [_jsxs(Card, { className: "min-w-0", render: _jsx("div", { "data-slot": "object-card" }), size: "sm", children: [_jsxs(CardHeader, { className: "flex flex-wrap items-center justify-between gap-x-4 gap-y-3 border-b", children: [company ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 items-center gap-4", actions?.menu && !actions.secondary && !actions.primary ? "basis-0" : "basis-64"), children: [_jsx(IdentityMark, { ...mark, size: 64 }), _jsxs("div", { className: "grid min-w-0 gap-1", children: [_jsx(CardTitle, { className: "min-w-0 break-words group-data-[size=sm]/card:text-heading-sm", children: title }), description ? _jsx(CardDescription, { children: description }) : null] })] })) : (_jsx(CardTitle, { className: "min-w-0 flex-1 basis-32 break-words", children: title })), actions ? _jsx(PageActionsRow, { ...actions }) : null] }), _jsxs(CardContent, { className: cn("grid min-w-0 gap-x-6 gap-y-5", !company && "md:grid-cols-[minmax(0,18.75rem)_minmax(0,1fr)]"), children: [!company ? (_jsx("div", { className: "flex h-32 min-w-0 items-center md:h-auto md:aspect-[16/10] justify-center rounded-sm border border-border bg-muted", "data-slot": "object-page-tile", children: _jsx(IdentityMark, { ...mark, size: 64 }) })) : null, _jsxs("div", { className: "grid min-w-0 content-start gap-4", children: [!company && description ? (_jsx("div", { className: "min-w-0 text-body-sm text-muted-foreground", children: description })) : null, _jsx("dl", { className: "grid min-w-0 grid-cols-2 gap-x-6 gap-y-4 lg:grid-cols-4", "data-slot": "object-page-facts", children: facts.map((fact) => (_jsxs("div", { className: "grid min-w-0 content-start gap-1", children: [_jsx("dt", { className: "text-label-sm text-muted-foreground", children: fact.label }), _jsx("dd", { className: "min-w-0 text-body-sm break-words text-foreground", children: fact.value })] }, fact.label))) })] })] }), footer ? (_jsx(FooterStrip, { hint: footer.hint, hintSlot: "object-page-hint", children: _jsx(PageCommandButton, { command: footer.link, variant: "outline" }) })) : null] }), entries && entries.length > 0 ? (_jsx(Card, { className: "min-w-0 py-0", render: _jsx("div", { "data-slot": "object-page-entries" }), size: "sm", children: _jsx(Accordion, { className: "[&>:last-child]:border-b-0", multiple: true, size: "small", children: entries.map((entry) => (_jsxs(AccordionItem, { value: entry.title, children: [_jsxs(AccordionTrigger, { className: "justify-start gap-3 px-(--card-spacing) group-data-[size=small]/accordion:text-body-sm focus-visible:-outline-offset-2 [&>[data-slot=accordion-trigger-icon]]:order-first [&>[data-slot=accordion-trigger-icon]]:text-muted-foreground", children: [_jsx("span", { className: "min-w-0 flex-1", children: entry.title }), entry.summary] }), _jsx(AccordionContent, { className: "ps-[calc(var(--card-spacing)+1.75rem)] pe-(--card-spacing)", children: entry.children })] }, entry.title))) }) })) : null] }), children] }));
|
|
23
23
|
}
|
|
@@ -1,23 +1,54 @@
|
|
|
1
1
|
import type { AgentOrbFigure } from "./agent-orb.js";
|
|
2
2
|
export type AgentOrbState = "idle" | "working" | "waiting" | "blocked" | "thinking" | "done";
|
|
3
3
|
export declare function nativeSpeed(form: AgentOrbFigure): number;
|
|
4
|
-
export declare function stateSpeed(state: AgentOrbState, form: AgentOrbFigure
|
|
4
|
+
export declare function stateSpeed(state: AgentOrbState, form: AgentOrbFigure, age?: number, timing?: {
|
|
5
|
+
wait: number;
|
|
6
|
+
confirm: number;
|
|
7
|
+
transition: number;
|
|
8
|
+
doneDuration: number;
|
|
9
|
+
blockedDuration: number;
|
|
10
|
+
gestureAge: (age: number) => number;
|
|
11
|
+
settle: (age: number, delay?: number) => number;
|
|
12
|
+
}): number;
|
|
5
13
|
/**
|
|
6
14
|
* Reduced motion turns movement off and keeps opacity and colour, so a
|
|
7
15
|
* thinking or working orb breathes between full ink and 0.45 over 1.6 s,
|
|
8
16
|
* ease-in-out, and busy still reads as busy. Every other state holds still.
|
|
9
17
|
*/
|
|
10
18
|
export declare function reducedBreath(state: AgentOrbState, seconds: number): number;
|
|
11
|
-
export declare function
|
|
19
|
+
export declare function readOrbTiming(style?: CSSStyleDeclaration): {
|
|
20
|
+
wait: number;
|
|
21
|
+
confirm: number;
|
|
22
|
+
transition: number;
|
|
23
|
+
doneDuration: number;
|
|
24
|
+
blockedDuration: number;
|
|
25
|
+
gestureAge: (age: number) => number;
|
|
26
|
+
settle: (age: number, delay?: number) => number;
|
|
27
|
+
};
|
|
28
|
+
export declare function motionPose(state: AgentOrbState, age: number, timing?: {
|
|
29
|
+
wait: number;
|
|
30
|
+
confirm: number;
|
|
31
|
+
transition: number;
|
|
32
|
+
doneDuration: number;
|
|
33
|
+
blockedDuration: number;
|
|
34
|
+
gestureAge: (age: number) => number;
|
|
35
|
+
settle: (age: number, delay?: number) => number;
|
|
36
|
+
}, reduced?: boolean): {
|
|
12
37
|
sx: number;
|
|
13
38
|
sy: number;
|
|
14
39
|
x: number;
|
|
15
40
|
y: number;
|
|
16
41
|
rotation: number;
|
|
17
|
-
split: number;
|
|
18
|
-
opacity: number;
|
|
19
42
|
};
|
|
20
43
|
export declare function paintOrbCue(context: CanvasRenderingContext2D, state: AgentOrbState, size: number, seconds: number, reduced: boolean, colors: readonly string[], depth: "back" | "front",
|
|
21
44
|
/** The orb's whole ink, so the cue breathes with the body under reduced motion. */
|
|
22
|
-
ink?: number
|
|
45
|
+
ink?: number, timing?: {
|
|
46
|
+
wait: number;
|
|
47
|
+
confirm: number;
|
|
48
|
+
transition: number;
|
|
49
|
+
doneDuration: number;
|
|
50
|
+
blockedDuration: number;
|
|
51
|
+
gestureAge: (age: number) => number;
|
|
52
|
+
settle: (age: number, delay?: number) => number;
|
|
53
|
+
}, statusColor?: string): void;
|
|
23
54
|
//# sourceMappingURL=agent-orb-motion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-orb-motion.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb-motion.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-orb-motion.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb-motion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAc7F,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,UAE/C;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,cAAc,EACpB,GAAG,SAAI,EACP,MAAM;;;;;;sBA2Cc,MAAM;kBACV,MAAM;CA5CA,UAWvB;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAIlE;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,mBAAmB;;;;;;sBAgBnC,MAAM;kBACV,MAAM;EAGvB;AAUD,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,MAAM;;;;;;sBAjBc,MAAM;kBACV,MAAM;CAgBA,EACtB,OAAO,UAAQ;;;;;;EA+ChB;AA6ED,wBAAgB,WAAW,CACzB,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO;AACvB,mFAAmF;AACnF,GAAG,SAAI,EACP,MAAM;;;;;;sBAxJc,MAAM;kBACV,MAAM;CAuJA,EACtB,WAAW,SAA8B,QA4E1C"}
|