@cloudgrid-io/ui 0.35.0 → 0.36.0
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/badge/css-base.d.ts +4 -0
- package/dist/badge/css-base.d.ts.map +1 -1
- package/dist/badge/css-base.js +6 -2
- package/dist/badge/css-base.js.map +1 -1
- package/dist/badge/css-fan.d.ts +30 -0
- package/dist/badge/css-fan.d.ts.map +1 -0
- package/dist/badge/css-fan.js +90 -0
- package/dist/badge/css-fan.js.map +1 -0
- package/dist/badge/css-live.d.ts.map +1 -1
- package/dist/badge/css-live.js +8 -0
- package/dist/badge/css-live.js.map +1 -1
- package/dist/badge/css-owner.d.ts +4 -0
- package/dist/badge/css-owner.d.ts.map +1 -1
- package/dist/badge/css-owner.js +16 -12
- package/dist/badge/css-owner.js.map +1 -1
- package/dist/badge/css-visitor.d.ts +5 -1
- package/dist/badge/css-visitor.d.ts.map +1 -1
- package/dist/badge/css-visitor.js +7 -2
- package/dist/badge/css-visitor.js.map +1 -1
- package/dist/badge/fan-geometry.d.ts +27 -0
- package/dist/badge/fan-geometry.d.ts.map +1 -0
- package/dist/badge/fan-geometry.js +24 -0
- package/dist/badge/fan-geometry.js.map +1 -0
- package/dist/badge/fan.d.ts +211 -0
- package/dist/badge/fan.d.ts.map +1 -0
- package/dist/badge/fan.js +585 -0
- package/dist/badge/fan.js.map +1 -0
- package/dist/badge/index.d.ts +4 -1
- package/dist/badge/index.d.ts.map +1 -1
- package/dist/badge/index.js +8 -4
- package/dist/badge/index.js.map +1 -1
- package/dist/badge/marks.d.ts +2 -0
- package/dist/badge/marks.d.ts.map +1 -1
- package/dist/badge/marks.js +5 -0
- package/dist/badge/marks.js.map +1 -1
- package/dist/badge/owner.d.ts +1 -0
- package/dist/badge/owner.d.ts.map +1 -1
- package/dist/badge/owner.js +13 -10
- package/dist/badge/owner.js.map +1 -1
- package/dist/badge/reactions.d.ts +20 -0
- package/dist/badge/reactions.d.ts.map +1 -0
- package/dist/badge/reactions.js +26 -0
- package/dist/badge/reactions.js.map +1 -0
- package/dist/badge/visitor.d.ts +6 -12
- package/dist/badge/visitor.d.ts.map +1 -1
- package/dist/badge/visitor.js +11 -18
- package/dist/badge/visitor.js.map +1 -1
- package/dist/blocks/icons.d.ts +8 -0
- package/dist/blocks/icons.d.ts.map +1 -1
- package/dist/blocks/icons.js +8 -0
- package/dist/blocks/icons.js.map +1 -1
- package/dist/blocks/phosphor-marks.d.ts +2 -0
- package/dist/blocks/phosphor-marks.d.ts.map +1 -1
- package/dist/blocks/phosphor-marks.js +3 -0
- package/dist/blocks/phosphor-marks.js.map +1 -1
- package/dist/claim-banner/css.d.ts +4 -3
- package/dist/claim-banner/css.d.ts.map +1 -1
- package/dist/claim-banner/css.js +8 -12
- package/dist/claim-banner/css.js.map +1 -1
- package/dist/claim-banner/index.d.ts +21 -14
- package/dist/claim-banner/index.d.ts.map +1 -1
- package/dist/claim-banner/index.js +25 -24
- package/dist/claim-banner/index.js.map +1 -1
- package/package.json +1 -1
package/dist/badge/css-base.d.ts
CHANGED
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
*
|
|
20
20
|
* `data-cgb-layout="desktop"` pins the desktop answer on a narrow screen.
|
|
21
21
|
*
|
|
22
|
+
* Stacking (ui issue 351): a panel and the phone's scrim sit at z-index 2, over
|
|
23
|
+
* the close x (z-index 1) and the fan's icon, so nothing on the page shows
|
|
24
|
+
* through an open panel. The prototype did the same.
|
|
25
|
+
*
|
|
22
26
|
* Motion (ui issue 322): `cgb-rise` is the arrival the live badge and the bubble
|
|
23
27
|
* share, and where the browser draws `linear()` easing the root swaps
|
|
24
28
|
* `--cg-ease-spring` for the real damped spring. Reduced motion stops every
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-base.d.ts","sourceRoot":"","sources":["../../src/badge/css-base.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-base.d.ts","sourceRoot":"","sources":["../../src/badge/css-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAE/D;AAED,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAE/D;AAyCD,eAAO,MAAM,cAAc,EAAE,MA8EyC,CAAA"}
|
package/dist/badge/css-base.js
CHANGED
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
*
|
|
20
20
|
* `data-cgb-layout="desktop"` pins the desktop answer on a narrow screen.
|
|
21
21
|
*
|
|
22
|
+
* Stacking (ui issue 351): a panel and the phone's scrim sit at z-index 2, over
|
|
23
|
+
* the close x (z-index 1) and the fan's icon, so nothing on the page shows
|
|
24
|
+
* through an open panel. The prototype did the same.
|
|
25
|
+
*
|
|
22
26
|
* Motion (ui issue 322): `cgb-rise` is the arrival the live badge and the bubble
|
|
23
27
|
* share, and where the browser draws `linear()` easing the root swaps
|
|
24
28
|
* `--cg-ease-spring` for the real damped spring. Reduced motion stops every
|
|
@@ -90,7 +94,7 @@ export const BADGE_BASE_CSS = /* @__PURE__ */ (() => `.cgb{all:initial;${BADGE_T
|
|
|
90
94
|
.cgb-wordmark{display:block;height:22px;width:auto;color:var(--cg-text-accent)}
|
|
91
95
|
.cgb-panel{position:absolute;width:340px;max-height:calc(100% - 32px);overflow:auto;display:grid;grid-template-columns:minmax(0,1fr);gap:14px;align-content:start;` +
|
|
92
96
|
`padding:18px 18px 16px;background:var(--cg-surface-card);color:var(--cg-text-primary);border:1px solid var(--cg-border-hairline);` +
|
|
93
|
-
`border-radius:var(--cg-radius-container);box-shadow:var(--cg-shadow-panel),var(--cg-shadow-hover);animation:cgb-in var(--cg-duration-slow) var(--cg-ease-out)}
|
|
97
|
+
`border-radius:var(--cg-radius-container);box-shadow:var(--cg-shadow-panel),var(--cg-shadow-hover);animation:cgb-in var(--cg-duration-slow) var(--cg-ease-out);z-index:2}
|
|
94
98
|
.cgb-panel[data-side=right]{right:16px;top:50%;transform:translateY(-50%)}
|
|
95
99
|
.cgb-panel[data-side=left]{left:16px;top:50%;transform:translateY(-50%)}
|
|
96
100
|
.cgb-panel[data-side=corner]{right:16px;bottom:16px}
|
|
@@ -136,7 +140,7 @@ export const BADGE_BASE_CSS = /* @__PURE__ */ (() => `.cgb{all:initial;${BADGE_T
|
|
|
136
140
|
touchRules((r) => `${r} .cgb-x{opacity:1;scale:1}`) +
|
|
137
141
|
"\n" +
|
|
138
142
|
phoneRules((r) => `${r} .cgb-panel{left:0;right:0;top:auto;bottom:0;width:auto;max-height:88%;transform:none;border-radius:var(--cg-radius-container) var(--cg-radius-container) 0 0;border-bottom:0;animation-name:cgb-up}` +
|
|
139
|
-
`${r} .cgb-scrim{display:block;position:absolute;inset:0;background:var(--cg-scrim)}` +
|
|
143
|
+
`${r} .cgb-scrim{display:block;position:absolute;inset:0;z-index:2;background:var(--cg-scrim)}` +
|
|
140
144
|
`${r} .cgb-panel textarea{font-size:var(--cg-body-md)}` +
|
|
141
145
|
// Phone only, and tighter (founder: no step may scroll). The sheet is
|
|
142
146
|
// capped at 88% of the viewport, 587px on a 375x667 phone, so every step
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-base.js","sourceRoot":"","sources":["../../src/badge/css-base.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-base.js","sourceRoot":"","sources":["../../src/badge/css-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEvD,4FAA4F;AAC5F,MAAM,WAAW,GAAG,qCAAqC,CAAA;AACzD,MAAM,YAAY,GAAG,6BAA6B,CAAA;AAElD,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CAAC,KAA4B;IACrD,OAAO,4BAA4B,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAA;AAChF,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,UAAU,CAAC,KAA4B;IACrD,OAAO,uBAAuB,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,EAAE,CAAA;AAChF,CAAC;AAED,MAAM,KAAK,GAAG,2DAA2D,CAAA;AAEzE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,GACX;;2HAEyH;IACzH,wFAAwF;IACxF;;;;;;;;;;;;;CAaD,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE,CAC1D,oBAAoB,wBAAwB,8EAA8E;IAC1H,mIAAmI;IACnI;;;;;;;;;;sBAUoB,KAAK;;;;mKAIwI;IACjK,mIAAmI;IACnI;;;;;;;;;;6IAU2I;IAC3I,4LAA4L;IAC5L;;;;;;;;;4IAS0I;IAC1I;;;+IAG6I;IAC7I;;;;;;;;;;;;;;;CAeD;IACC,OAAO;IACP,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC;IACnD,IAAI;IACJ,UAAU,CACR,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,sMAAsM;QAC1M,GAAG,CAAC,2FAA2F;QAC/F,GAAG,CAAC,mDAAmD;QACvD,sEAAsE;QACtE,yEAAyE;QACzE,yDAAyD;QACzD,GAAG,CAAC,6CAA6C;QACjD,GAAG,CAAC,6BAA6B;QACjC,GAAG,CAAC,wCAAwC;QAC5C,GAAG,CAAC,0CAA0C;QAC9C,GAAG,CAAC,wBAAwB,CAC/B;IACD,iEAAiE,CAAC,EAAE,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reaction fan's stylesheet (ui issue 351), after `BADGE_BASE_CSS`. It is
|
|
3
|
+
* part of both `BADGE_VISITOR_CSS` (the fan itself) and `BADGE_OWNER_CSS` (the
|
|
4
|
+
* owner's small working copy in the "Ask visitors for feedback" explanation),
|
|
5
|
+
* so each of the badge's two files carries it once.
|
|
6
|
+
*
|
|
7
|
+
* The icon: a drop, round with one sharp corner at the bottom left, holding
|
|
8
|
+
* the plug. Light system: purple with a white plug. Dark system: white with a
|
|
9
|
+
* purple plug and a purple hairline. `data-theme` on `.cgf` pins either one.
|
|
10
|
+
* It rises in like the bubble did, 600ms after insertion (`--cgb-start`).
|
|
11
|
+
*
|
|
12
|
+
* The options: white discs on a quarter circle, up and to the left. Opening
|
|
13
|
+
* springs each out from under the icon, 30ms apart; the one under a finger
|
|
14
|
+
* grows to 1.28. A press pops the disc and fills it purple with a check; taking
|
|
15
|
+
* it back shrinks it. A chosen reaction leaves a small mark on the icon, which
|
|
16
|
+
* pops in only when it is new (`data-new`).
|
|
17
|
+
*
|
|
18
|
+
* Sizes: a 40px icon, 40px options on a 98px radius; on a touch screen a 44px
|
|
19
|
+
* icon and 48px options on 114px, so every target is 44px or more. Touch is
|
|
20
|
+
* `hover: none`, the root's `data-cgb-touch`, or `data-touch` on the fan, which
|
|
21
|
+
* `wireFan()` sets on the first touch.
|
|
22
|
+
*
|
|
23
|
+
* The hover zone: while the fan is open on a mouse, a transparent quarter disc
|
|
24
|
+
* behind the options keeps the pointer "on" the fan as it crosses the gaps.
|
|
25
|
+
*
|
|
26
|
+
* Reduced motion: the base stylesheet stops every animation and transition in
|
|
27
|
+
* the root, so the fan opens without the spread and a press has no pop.
|
|
28
|
+
*/
|
|
29
|
+
export declare const BADGE_FAN_CSS: string;
|
|
30
|
+
//# sourceMappingURL=css-fan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-fan.d.ts","sourceRoot":"","sources":["../../src/badge/css-fan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAcH,eAAO,MAAM,aAAa,EAAE,MAqDxB,CAAA"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reaction fan's stylesheet (ui issue 351), after `BADGE_BASE_CSS`. It is
|
|
3
|
+
* part of both `BADGE_VISITOR_CSS` (the fan itself) and `BADGE_OWNER_CSS` (the
|
|
4
|
+
* owner's small working copy in the "Ask visitors for feedback" explanation),
|
|
5
|
+
* so each of the badge's two files carries it once.
|
|
6
|
+
*
|
|
7
|
+
* The icon: a drop, round with one sharp corner at the bottom left, holding
|
|
8
|
+
* the plug. Light system: purple with a white plug. Dark system: white with a
|
|
9
|
+
* purple plug and a purple hairline. `data-theme` on `.cgf` pins either one.
|
|
10
|
+
* It rises in like the bubble did, 600ms after insertion (`--cgb-start`).
|
|
11
|
+
*
|
|
12
|
+
* The options: white discs on a quarter circle, up and to the left. Opening
|
|
13
|
+
* springs each out from under the icon, 30ms apart; the one under a finger
|
|
14
|
+
* grows to 1.28. A press pops the disc and fills it purple with a check; taking
|
|
15
|
+
* it back shrinks it. A chosen reaction leaves a small mark on the icon, which
|
|
16
|
+
* pops in only when it is new (`data-new`).
|
|
17
|
+
*
|
|
18
|
+
* Sizes: a 40px icon, 40px options on a 98px radius; on a touch screen a 44px
|
|
19
|
+
* icon and 48px options on 114px, so every target is 44px or more. Touch is
|
|
20
|
+
* `hover: none`, the root's `data-cgb-touch`, or `data-touch` on the fan, which
|
|
21
|
+
* `wireFan()` sets on the first touch.
|
|
22
|
+
*
|
|
23
|
+
* The hover zone: while the fan is open on a mouse, a transparent quarter disc
|
|
24
|
+
* behind the options keeps the pointer "on" the fan as it crosses the gaps.
|
|
25
|
+
*
|
|
26
|
+
* Reduced motion: the base stylesheet stops every animation and transition in
|
|
27
|
+
* the root, so the fan opens without the spread and a press has no pop.
|
|
28
|
+
*/
|
|
29
|
+
import { touchRules } from "./css-base.js";
|
|
30
|
+
import { FAN_DIRECTIONS, FAN_HOT_SCALE, FAN_SIZE } from "./fan-geometry.js";
|
|
31
|
+
const P = FAN_SIZE.pointer;
|
|
32
|
+
const T = FAN_SIZE.touch;
|
|
33
|
+
/** The white icon: on a dark system, or pinned with `data-theme="dark"`. */
|
|
34
|
+
const WHITE_ICON = "background:var(--cg-surface-card);color:var(--cg-text-accent);border:1px solid var(--cg-border-accent)";
|
|
35
|
+
/** The touch sizes, never for the owner's preview, which is drawn small on purpose. */
|
|
36
|
+
const TOUCH_SIZES = `{--cgb-fan-i:${T.icon}px;--cgb-fan-o:${T.option}px;--cgb-fan-r:${T.radius}px}`;
|
|
37
|
+
export const BADGE_FAN_CSS = /* @__PURE__ */ (() => `.cgf{--cgb-fan-i:${P.icon}px;--cgb-fan-o:${P.option}px;--cgb-fan-r:${P.radius}px;--cgb-t0:var(--cgb-start,600ms);position:absolute;` +
|
|
38
|
+
`right:calc(12px + env(safe-area-inset-right,0px));bottom:calc(12px + env(safe-area-inset-bottom,0px));width:var(--cgb-fan-i);height:var(--cgb-fan-i)}
|
|
39
|
+
` +
|
|
40
|
+
touchRules((r) => `${r} .cgf:not([data-mini])${TOUCH_SIZES}`) +
|
|
41
|
+
`.cgf[data-touch]:not([data-mini])${TOUCH_SIZES}
|
|
42
|
+
.cgf-icon{position:absolute;inset:0;z-index:2;display:grid;place-items:center;border-radius:50% 50% 50% 0;background:var(--cg-primary);color:var(--cg-text-on-primary);` +
|
|
43
|
+
`box-shadow:var(--cg-shadow-card);cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;` +
|
|
44
|
+
`animation:cgb-rise 640ms var(--cg-ease-out-expo) var(--cgb-t0) both;transition:box-shadow 240ms ease,scale 320ms var(--cg-ease-spring)}
|
|
45
|
+
.cgf[data-theme=dark] .cgf-icon{${WHITE_ICON}}
|
|
46
|
+
@media (prefers-color-scheme:dark){.cgf:not([data-theme]) .cgf-icon{${WHITE_ICON}}}
|
|
47
|
+
.cgf-plug{width:calc(var(--cgb-fan-i) / 2);height:calc(var(--cgb-fan-i) / 2)}
|
|
48
|
+
@media (hover:hover){.cgf-icon:hover{box-shadow:var(--cg-shadow-card-hover)}}
|
|
49
|
+
.cgf-icon:active{scale:.94;transition:scale var(--cg-duration-fast) ease}
|
|
50
|
+
.cgf-icon:focus-visible{outline:2px solid var(--cg-primary);outline-offset:2px}
|
|
51
|
+
.cgf-opts{position:absolute;left:50%;top:50%;width:0;height:0;z-index:1}
|
|
52
|
+
.cgf-opt{--cgb-c:1;--cgb-s:0;--cgb-i:0;position:absolute;left:calc(var(--cgb-fan-o) / -2);top:calc(var(--cgb-fan-o) / -2);width:var(--cgb-fan-o);height:var(--cgb-fan-o);padding:0;border-radius:50%;` +
|
|
53
|
+
`translate:0 0;opacity:0;visibility:hidden;pointer-events:none;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;` +
|
|
54
|
+
`transition:translate 200ms var(--cg-ease-in),opacity 160ms var(--cg-ease-out),visibility 0s linear 200ms}
|
|
55
|
+
` +
|
|
56
|
+
FAN_DIRECTIONS.map(([c, s], i) => `.cgf-opt[data-i="${i}"]{--cgb-c:${c};--cgb-s:${s};--cgb-i:${i}}`).join("\n") +
|
|
57
|
+
`
|
|
58
|
+
.cgf[data-open] .cgf-opt{translate:calc(var(--cgb-fan-r) * var(--cgb-c) * -1) calc(var(--cgb-fan-r) * var(--cgb-s) * -1);opacity:1;visibility:visible;pointer-events:auto;` +
|
|
59
|
+
`transition:translate 460ms var(--cg-ease-spring) calc(var(--cgb-i) * 30ms),opacity 160ms var(--cg-ease-out) calc(var(--cgb-i) * 30ms),visibility 0s}
|
|
60
|
+
.cgf-face{display:grid;place-items:center;width:100%;height:100%;border-radius:50%;background:var(--cg-surface-card);color:var(--cg-text-primary);border:1px solid var(--cg-border-hairline);` +
|
|
61
|
+
`box-shadow:var(--cg-shadow-card),var(--cg-shadow-hover);scale:.5;` +
|
|
62
|
+
`transition:scale 300ms var(--cg-ease-spring),background-color var(--cg-duration) var(--cg-ease-out),color var(--cg-duration) var(--cg-ease-out),border-color var(--cg-duration) var(--cg-ease-out)}
|
|
63
|
+
.cgf[data-open] .cgf-face{scale:1;transition:scale 460ms var(--cg-ease-spring) calc(var(--cgb-i) * 30ms),background-color var(--cg-duration) var(--cg-ease-out),color var(--cg-duration) var(--cg-ease-out),border-color var(--cg-duration) var(--cg-ease-out)}
|
|
64
|
+
@media (hover:hover){.cgf[data-open] .cgf-opt:hover .cgf-face{scale:1.08;transition-delay:0s}}
|
|
65
|
+
.cgf[data-open] .cgf-opt[data-hot] .cgf-face{scale:${FAN_HOT_SCALE};transition-delay:0s}
|
|
66
|
+
.cgf-opt:focus-visible{outline:none}
|
|
67
|
+
.cgf-opt:focus-visible .cgf-face{outline:2px solid var(--cg-primary);outline-offset:2px}
|
|
68
|
+
.cgf-opt[aria-pressed=true] .cgf-face{background:var(--cg-primary);color:var(--cg-text-on-primary);border-color:var(--cg-primary)}
|
|
69
|
+
.cgf[data-open] .cgf-opt[data-pop] .cgf-face{animation:cgf-pop 440ms var(--cg-ease-out)}
|
|
70
|
+
.cgf[data-open] .cgf-opt[data-unpop] .cgf-face{animation:cgf-unpop 300ms var(--cg-ease-out)}
|
|
71
|
+
@keyframes cgf-pop{0%{scale:1}35%{scale:1.24}70%{scale:.96}100%{scale:1}}
|
|
72
|
+
@keyframes cgf-unpop{40%{scale:.86}}
|
|
73
|
+
.cgf-g,.cgf-ck{grid-area:1/1;display:grid;place-items:center;transition:opacity 140ms var(--cg-ease-out),scale 300ms var(--cg-ease-spring)}
|
|
74
|
+
.cgf-g svg,.cgf-ck svg{width:calc(var(--cgb-fan-o) / 2);height:calc(var(--cgb-fan-o) / 2)}
|
|
75
|
+
.cgf-ck{opacity:0;scale:.4}
|
|
76
|
+
.cgf-opt[data-flash] .cgf-ck{opacity:1;scale:1}
|
|
77
|
+
.cgf-opt[data-flash] .cgf-g{opacity:0;scale:.6}
|
|
78
|
+
.cgf-zone{position:absolute;right:0;bottom:0;z-index:0;display:none;width:calc(var(--cgb-fan-r) + var(--cgb-fan-o) / 2 + var(--cgb-fan-i) / 2 + 16px);` +
|
|
79
|
+
`height:calc(var(--cgb-fan-r) + var(--cgb-fan-o) / 2 + var(--cgb-fan-i) / 2 + 16px);border-top-left-radius:100%}
|
|
80
|
+
@media (hover:hover) and (pointer:fine){.cgb:not([data-cgb-touch]) .cgf:not([data-touch]):is([data-open],[data-lock]) .cgf-zone{display:block}}
|
|
81
|
+
.cgf-marks{position:absolute;right:calc(100% - 13px);top:-8px;display:flex;flex-direction:row-reverse;pointer-events:none}
|
|
82
|
+
.cgf-mark{display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--cg-surface-card);color:var(--cg-text-accent);border:1px solid var(--cg-border-accent);box-shadow:var(--cg-shadow-card)}
|
|
83
|
+
.cgf-mark[data-new]{animation:cgb-pop 420ms var(--cg-ease-spring) both}
|
|
84
|
+
.cgf-mark+.cgf-mark{margin-right:-7px}
|
|
85
|
+
.cgf-mark svg{width:12px;height:12px}
|
|
86
|
+
.cgf[data-mini]{right:22px;bottom:22px}
|
|
87
|
+
.cgf[data-mini] .cgf-icon{animation:none}
|
|
88
|
+
@starting-style{.cgf[data-mini][data-open] .cgf-opt{translate:0 0;opacity:0}.cgf[data-mini][data-open] .cgf-face{scale:.5}}
|
|
89
|
+
`)();
|
|
90
|
+
//# sourceMappingURL=css-fan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-fan.js","sourceRoot":"","sources":["../../src/badge/css-fan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3E,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAA;AAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAA;AAExB,4EAA4E;AAC5E,MAAM,UAAU,GAAG,wGAAwG,CAAA;AAE3H,uFAAuF;AACvF,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,MAAM,kBAAkB,CAAC,CAAC,MAAM,KAAK,CAAA;AAEnG,MAAM,CAAC,MAAM,aAAa,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE,CACzD,oBAAoB,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,MAAM,kBAAkB,CAAC,CAAC,MAAM,uDAAuD;IACrI;CACD;IACC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,yBAAyB,WAAW,EAAE,CAAC;IAC7D,oCAAoC,WAAW;wKACuH;IACtK,yIAAyI;IACzI;kCACgC,UAAU;sEAC0B,UAAU;;;;;;sMAMsH;IACpM,uJAAuJ;IACvJ;CACD;IACC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,cAAc,CAAC,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAC/G;2KACyK;IACzK;8LAC4L;IAC5L,mEAAmE;IACnE;;;qDAGmD,aAAa;;;;;;;;;;;;;uJAaqF;IACrJ;;;;;;;;;;CAUD,CAAC,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-live.d.ts","sourceRoot":"","sources":["../../src/badge/css-live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAoBH,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"css-live.d.ts","sourceRoot":"","sources":["../../src/badge/css-live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAoBH,eAAO,MAAM,cAAc,EAAE,MAgCpB,CAAA"}
|
package/dist/badge/css-live.js
CHANGED
|
@@ -61,7 +61,15 @@ export const BADGE_LIVE_CSS = /* @__PURE__ */ (() => `.cgb-live-wrap{--cgb-t0:va
|
|
|
61
61
|
@keyframes cgb-grow{from{grid-template-columns:0fr}}
|
|
62
62
|
@keyframes cgb-label{from{opacity:0;translate:-8px 0}}
|
|
63
63
|
@media (prefers-reduced-motion:reduce){.cgb-live:hover .cgb-live-icon,.cgb-live:focus-visible .cgb-live-icon,.cgb-live:active .cgb-live-icon{transform:none}}
|
|
64
|
+
` +
|
|
65
|
+
// The pill's close x (founder, 2026-10-21, ui issue 351): 18px with an 11px
|
|
66
|
+
// x, overlapping the pill's top-right edge by 6px down and 5px out. It
|
|
67
|
+
// keeps the base x's look and its hover and focus rules; on touch its hit
|
|
68
|
+
// area is 44px square.
|
|
69
|
+
`.cgb-live-x{width:18px;height:18px;top:10px;right:-5px}
|
|
70
|
+
.cgb-live-x svg{width:11px;height:11px}
|
|
64
71
|
` +
|
|
65
72
|
touchRules((r) => `${r} .cgb-live-x{animation:cgb-pop 520ms var(--cg-ease-spring) calc(var(--cgb-t0) + 1020ms) both}`) +
|
|
73
|
+
touchRules((r) => `${r} .cgb-live-x::before{inset:-13px}`) +
|
|
66
74
|
"\n")();
|
|
67
75
|
//# sourceMappingURL=css-live.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-live.js","sourceRoot":"","sources":["../../src/badge/css-live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C;;;;GAIG;AACH,MAAM,UAAU,GACd,0BAA0B;IAC1B,kBAAkB,CAChB,qGAAqG,eAAe,WAAW,CAChI;IACD,IAAI,CAAA;AAEN,6EAA6E;AAC7E,MAAM,IAAI,GAAG,GAAG,UAAU,yJAAyJ,CAAA;AAEnL,MAAM,CAAC,MAAM,cAAc,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE,CAC1D;wMACsM;IACtM;;sFAEoF;IACpF,sBAAsB,IAAI,eAAe,IAAI,+IAA+I;IAC5L,gKAAgK;IAChK,+JAA+J;IAC/J;;;;;;qLAMmL;IACnL;;;;;;CAMD;IACC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,+FAA+F,CAAC;IACtH,IAAI,CAAC,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"css-live.js","sourceRoot":"","sources":["../../src/badge/css-live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C;;;;GAIG;AACH,MAAM,UAAU,GACd,0BAA0B;IAC1B,kBAAkB,CAChB,qGAAqG,eAAe,WAAW,CAChI;IACD,IAAI,CAAA;AAEN,6EAA6E;AAC7E,MAAM,IAAI,GAAG,GAAG,UAAU,yJAAyJ,CAAA;AAEnL,MAAM,CAAC,MAAM,cAAc,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE,CAC1D;wMACsM;IACtM;;sFAEoF;IACpF,sBAAsB,IAAI,eAAe,IAAI,+IAA+I;IAC5L,gKAAgK;IAChK,+JAA+J;IAC/J;;;;;;qLAMmL;IACnL;;;;;;CAMD;IACC,4EAA4E;IAC5E,uEAAuE;IACvE,0EAA0E;IAC1E,uBAAuB;IACvB;;CAED;IACC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,+FAA+F,CAAC;IACtH,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAA"}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* The owner half of the badge stylesheet: the tab on the edge and the owner
|
|
3
3
|
* panel's three steps. Ships in the owner file the badge lazy-loads for the
|
|
4
4
|
* app's owner only, and assumes `BADGE_BASE_CSS` is already in the shadow root.
|
|
5
|
+
* It carries the reaction fan's stylesheet (`BADGE_FAN_CSS`, ui issue 351) for
|
|
6
|
+
* the working copy the "Ask visitors for feedback" explanation shows.
|
|
5
7
|
*/
|
|
8
|
+
/** The owner's own rules, without the fan. `BADGE_CSS` joins it to the visitor's and adds the fan once. */
|
|
9
|
+
export declare const OWNER_ONLY_CSS: string;
|
|
6
10
|
export declare const BADGE_OWNER_CSS: string;
|
|
7
11
|
//# sourceMappingURL=css-owner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-owner.d.ts","sourceRoot":"","sources":["../../src/badge/css-owner.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-owner.d.ts","sourceRoot":"","sources":["../../src/badge/css-owner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,2GAA2G;AAC3G,eAAO,MAAM,cAAc,EAAE,MAyKvB,CAAA;AAEN,eAAO,MAAM,eAAe,EAAE,MAAuC,CAAA"}
|
package/dist/badge/css-owner.js
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* The owner half of the badge stylesheet: the tab on the edge and the owner
|
|
3
3
|
* panel's three steps. Ships in the owner file the badge lazy-loads for the
|
|
4
4
|
* app's owner only, and assumes `BADGE_BASE_CSS` is already in the shadow root.
|
|
5
|
+
* It carries the reaction fan's stylesheet (`BADGE_FAN_CSS`, ui issue 351) for
|
|
6
|
+
* the working copy the "Ask visitors for feedback" explanation shows.
|
|
5
7
|
*/
|
|
6
8
|
import { phoneRules } from "./css-base.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
+
import { BADGE_FAN_CSS } from "./css-fan.js";
|
|
10
|
+
/** The owner's own rules, without the fan. `BADGE_CSS` joins it to the visitor's and adds the fan once. */
|
|
11
|
+
export const OWNER_ONLY_CSS = /* @__PURE__ */ (() =>
|
|
9
12
|
// One length for every step (cloudgrid-console 868): the owner panel is the
|
|
10
13
|
// main step's height on main, Edit and Share alike, so switching steps never
|
|
11
14
|
// resizes it. 506px is the main step measured on desktop (505.1), 415px on a
|
|
@@ -70,16 +73,14 @@ export const BADGE_OWNER_CSS = /* @__PURE__ */ (() =>
|
|
|
70
73
|
`background:var(--cg-surface-card);border:1px solid var(--cg-border-control);border-bottom-color:var(--cg-border-hairline);border-radius:var(--cg-radius-md) var(--cg-radius-md) 0 0;` +
|
|
71
74
|
`box-shadow:var(--cg-shadow-card);font-family:var(--cg-font-body);font-weight:var(--cg-weight-regular);animation:cgb-in var(--cg-duration) var(--cg-ease-out)}
|
|
72
75
|
` +
|
|
73
|
-
// The preview
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`.cgb-info-art{position:relative;flex:none;width:88px;height:70px;overflow:hidden;border-radius:var(--cg-radius-sm);background:var(--cg-surface-raised)}
|
|
82
|
-
` + bubbleLook(".cgb-info-bubble") + `.cgb-info-wrap{position:absolute;left:50%;top:50%;width:max-content;padding-top:22px;transform:translate(-50%,-42px) scale(.8);transform-origin:50% 42px}
|
|
76
|
+
// The preview is a working small copy of the visitor's fan (ui issue 351),
|
|
77
|
+
// drawn open at half size: a 224px stage, the fan in its bottom-right
|
|
78
|
+
// corner as in an app's, scaled into a 112px tile. The explanation's 139px
|
|
79
|
+
// holds the tile and its 10px padding. On a phone the explanation is 112px
|
|
80
|
+
// (see above), so the tile is 92px: the prototype's 96 made it 116 and
|
|
81
|
+
// covered the bottom of the name row, which the explanation must never do.
|
|
82
|
+
`.cgb-info-art{position:relative;flex:none;width:112px;height:112px;overflow:hidden;border-radius:var(--cg-radius-sm);background:var(--cg-surface-raised)}
|
|
83
|
+
.cgb-info-art .cgf-stage{position:absolute;left:0;top:0;display:block;width:224px;height:224px;transform:scale(.5);transform-origin:0 0}
|
|
83
84
|
.cgb-info-copy{min-width:0;font-size:var(--cg-caption);line-height:1.4;color:var(--cg-text-secondary);text-wrap:pretty}
|
|
84
85
|
.cgb-info-copy::before{content:"";float:right;width:22px;height:18px}
|
|
85
86
|
.cgb-info-copy span{color:var(--cg-text-primary)}
|
|
@@ -164,6 +165,8 @@ export const BADGE_OWNER_CSS = /* @__PURE__ */ (() =>
|
|
|
164
165
|
`${r} .cgb-spark{height:18px}` +
|
|
165
166
|
`${r} .cgb-box .cgb-toggle{padding:9px 12px}` +
|
|
166
167
|
`${r} .cgb-info{min-height:112px}` +
|
|
168
|
+
`${r} .cgb-info-art{width:92px;height:92px}` +
|
|
169
|
+
`${r} .cgb-info-art .cgf-stage{transform:scale(.4107)}` +
|
|
167
170
|
`${r} .cgb-seg button{padding:6px 4px;gap:2px}` +
|
|
168
171
|
`${r} .cgb-seg button svg{width:16px;height:16px}` +
|
|
169
172
|
`${r} .cgb-aslot{min-height:40px;margin-top:-2px}` +
|
|
@@ -172,4 +175,5 @@ export const BADGE_OWNER_CSS = /* @__PURE__ */ (() =>
|
|
|
172
175
|
`${r} .cgb-prompt{padding:10px 44px 10px 12px}` +
|
|
173
176
|
`${r} .cgb-prompt-copy{top:8px;right:8px}` +
|
|
174
177
|
`${r} .cgb-link-box{height:40px}`))();
|
|
178
|
+
export const BADGE_OWNER_CSS = OWNER_ONLY_CSS + BADGE_FAN_CSS;
|
|
175
179
|
//# sourceMappingURL=css-owner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-owner.js","sourceRoot":"","sources":["../../src/badge/css-owner.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-owner.js","sourceRoot":"","sources":["../../src/badge/css-owner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,2GAA2G;AAC3G,MAAM,CAAC,MAAM,cAAc,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE;AAC1D,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,2EAA2E;AAC3E,kEAAkE;AAClE;gKAC8J;IAC9J,8JAA8J;IAC9J,mKAAmK;IACnK;;;;;;;;;;;;;qKAamK;IACnK,oOAAoO;IACpO;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BD;IACC,4EAA4E;IAC5E,6EAA6E;IAC7E,oEAAoE;IACpE,2EAA2E;IAC3E,iDAAiD;IACjD;;;;8JAI4J;IAC5J,sLAAsL;IACtL;CACD;IACC,2EAA2E;IAC3E,sEAAsE;IACtE,2EAA2E;IAC3E,2EAA2E;IAC3E,uEAAuE;IACvE,2EAA2E;IAC3E;;;;;;;;;;6JAU2J;IAC3J;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uJA+BqJ;IACrJ;;;;;;;;;;;;;;;;;;;2LAmByL;IACzL;;;;;;;;;CASD;IACC,UAAU,CACR,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,+CAA+C;QACnD,GAAG,CAAC,wBAAwB;QAC5B,GAAG,CAAC,2CAA2C;QAC/C,GAAG,CAAC,kCAAkC;QACtC,GAAG,CAAC,gEAAgE;QACpE,sEAAsE;QACtE,4CAA4C;QAC5C,GAAG,CAAC,gDAAgD;QACpD,GAAG,CAAC,gCAAgC;QACpC,GAAG,CAAC,6BAA6B;QACjC,GAAG,CAAC,0BAA0B;QAC9B,GAAG,CAAC,yCAAyC;QAC7C,GAAG,CAAC,8BAA8B;QAClC,GAAG,CAAC,wCAAwC;QAC5C,GAAG,CAAC,mDAAmD;QACvD,GAAG,CAAC,2CAA2C;QAC/C,GAAG,CAAC,8CAA8C;QAClD,GAAG,CAAC,8CAA8C;QAClD,GAAG,CAAC,gDAAgD;QACpD,GAAG,CAAC,qBAAqB;QACzB,GAAG,CAAC,2CAA2C;QAC/C,GAAG,CAAC,sCAAsC;QAC1C,GAAG,CAAC,6BAA6B,CACpC,CAAC,EAAE,CAAA;AAEN,MAAM,CAAC,MAAM,eAAe,GAAW,cAAc,GAAG,aAAa,CAAA"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The visitor half of the badge stylesheet: the feedback bubble, its close x,
|
|
3
3
|
* the feedback panel and its sign-in step. Ships in the badge's main file,
|
|
4
|
-
* after `BADGE_BASE_CSS`.
|
|
4
|
+
* after `BADGE_BASE_CSS`. Since ui issue 351 it carries the reaction fan's
|
|
5
|
+
* stylesheet too (`BADGE_FAN_CSS`); the bubble's rules stay until the platform
|
|
6
|
+
* has moved to the fan.
|
|
5
7
|
*/
|
|
8
|
+
/** The visitor's own rules, without the fan. `BADGE_CSS` joins it to the owner's and adds the fan once. */
|
|
9
|
+
export declare const VISITOR_ONLY_CSS: string;
|
|
6
10
|
export declare const BADGE_VISITOR_CSS: string;
|
|
7
11
|
//# sourceMappingURL=css-visitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-visitor.d.ts","sourceRoot":"","sources":["../../src/badge/css-visitor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-visitor.d.ts","sourceRoot":"","sources":["../../src/badge/css-visitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,2GAA2G;AAC3G,eAAO,MAAM,gBAAgB,EAAE,MAkEzB,CAAA;AAEN,eAAO,MAAM,iBAAiB,EAAE,MAAyC,CAAA"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The visitor half of the badge stylesheet: the feedback bubble, its close x,
|
|
3
3
|
* the feedback panel and its sign-in step. Ships in the badge's main file,
|
|
4
|
-
* after `BADGE_BASE_CSS`.
|
|
4
|
+
* after `BADGE_BASE_CSS`. Since ui issue 351 it carries the reaction fan's
|
|
5
|
+
* stylesheet too (`BADGE_FAN_CSS`); the bubble's rules stay until the platform
|
|
6
|
+
* has moved to the fan.
|
|
5
7
|
*/
|
|
6
8
|
import { phoneRules, touchRules } from "./css-base.js";
|
|
7
9
|
import { bubbleLook } from "./css-bubble.js";
|
|
8
|
-
|
|
10
|
+
import { BADGE_FAN_CSS } from "./css-fan.js";
|
|
11
|
+
/** The visitor's own rules, without the fan. `BADGE_CSS` joins it to the owner's and adds the fan once. */
|
|
12
|
+
export const VISITOR_ONLY_CSS = /* @__PURE__ */ (() =>
|
|
9
13
|
// The bubble (ui issue 322, the designer's overlay). It rises in 600ms after it is
|
|
10
14
|
// inserted (`--cgb-start`, which `bubble({ delay })` sets), the three discs
|
|
11
15
|
// follow 80ms apart from the left. Hover spreads the discs from an 8px
|
|
@@ -69,4 +73,5 @@ export const BADGE_VISITOR_CSS = /* @__PURE__ */ (() =>
|
|
|
69
73
|
`${r} .cgb-signin{gap:8px}` +
|
|
70
74
|
`${r} .cgb-method{height:40px}` +
|
|
71
75
|
`${r} .cgb-input{height:38px}`))();
|
|
76
|
+
export const BADGE_VISITOR_CSS = VISITOR_ONLY_CSS + BADGE_FAN_CSS;
|
|
72
77
|
//# sourceMappingURL=css-visitor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-visitor.js","sourceRoot":"","sources":["../../src/badge/css-visitor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"css-visitor.js","sourceRoot":"","sources":["../../src/badge/css-visitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,2GAA2G;AAC3G,MAAM,CAAC,MAAM,gBAAgB,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE;AAC5D,mFAAmF;AACnF,4EAA4E;AAC5E,uEAAuE;AACvE,0EAA0E;AAC1E,wEAAwE;AACxE,4EAA4E;AAC5E,iCAAiC;AACjC;CACD;IACC,UAAU,CAAC,aAAa,CAAC;IACzB;;;;;;;;;;;2KAWyK;IACzK,+MAA+M;IAC/M;;;;;;;;;sJASoJ;IACpJ;;;;;;;;;;;;;yLAauL;IACvL;;;;;;;CAOD;IACC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,gGAAgG,CAAC;IACvH,IAAI;IACJ,UAAU,CACR,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,8CAA8C;QAClD,GAAG,CAAC,sCAAsC;QAC1C,GAAG,CAAC,iCAAiC;QACrC,GAAG,CAAC,uBAAuB;QAC3B,GAAG,CAAC,2BAA2B;QAC/B,GAAG,CAAC,0BAA0B,CACjC,CAAC,EAAE,CAAA;AAEN,MAAM,CAAC,MAAM,iBAAiB,GAAW,gBAAgB,GAAG,aAAa,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reaction fan's geometry (ui#351), in CSS pixels: one source for the
|
|
3
|
+
* stylesheet that draws the fan and the hit test that reads a finger on it.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The options sit on a quarter circle centred on the icon. A touch screen gets
|
|
7
|
+
* the larger set: a 44px icon and 48px options, so every target is 44px or more.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FAN_SIZE: {
|
|
10
|
+
readonly pointer: {
|
|
11
|
+
readonly icon: 40;
|
|
12
|
+
readonly option: 40;
|
|
13
|
+
readonly radius: 98;
|
|
14
|
+
};
|
|
15
|
+
readonly touch: {
|
|
16
|
+
readonly icon: 44;
|
|
17
|
+
readonly option: 48;
|
|
18
|
+
readonly radius: 114;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/** Each option's direction from the icon, as (cos, sin) of 0, 30, 60 and 90 degrees from the left: up and to the left. */
|
|
22
|
+
export declare const FAN_DIRECTIONS: ReadonlyArray<readonly [number, number]>;
|
|
23
|
+
/** The option under a finger grows to this, and its hit area with it. */
|
|
24
|
+
export declare const FAN_HOT_SCALE = 1.28;
|
|
25
|
+
/** How far past an option's edge a finger still counts as on it. */
|
|
26
|
+
export declare const FAN_HIT_SLOP = 8;
|
|
27
|
+
//# sourceMappingURL=fan-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-geometry.d.ts","sourceRoot":"","sources":["../../src/badge/fan-geometry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;CAGX,CAAA;AAEV,0HAA0H;AAC1H,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAKnE,CAAA;AAED,yEAAyE;AACzE,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC,oEAAoE;AACpE,eAAO,MAAM,YAAY,IAAI,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reaction fan's geometry (ui#351), in CSS pixels: one source for the
|
|
3
|
+
* stylesheet that draws the fan and the hit test that reads a finger on it.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The options sit on a quarter circle centred on the icon. A touch screen gets
|
|
7
|
+
* the larger set: a 44px icon and 48px options, so every target is 44px or more.
|
|
8
|
+
*/
|
|
9
|
+
export const FAN_SIZE = {
|
|
10
|
+
pointer: { icon: 40, option: 40, radius: 98 },
|
|
11
|
+
touch: { icon: 44, option: 48, radius: 114 },
|
|
12
|
+
};
|
|
13
|
+
/** Each option's direction from the icon, as (cos, sin) of 0, 30, 60 and 90 degrees from the left: up and to the left. */
|
|
14
|
+
export const FAN_DIRECTIONS = [
|
|
15
|
+
[1, 0],
|
|
16
|
+
[0.866, 0.5],
|
|
17
|
+
[0.5, 0.866],
|
|
18
|
+
[0, 1],
|
|
19
|
+
];
|
|
20
|
+
/** The option under a finger grows to this, and its hit area with it. */
|
|
21
|
+
export const FAN_HOT_SCALE = 1.28;
|
|
22
|
+
/** How far past an option's edge a finger still counts as on it. */
|
|
23
|
+
export const FAN_HIT_SLOP = 8;
|
|
24
|
+
//# sourceMappingURL=fan-geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-geometry.js","sourceRoot":"","sources":["../../src/badge/fan-geometry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IAC7C,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;CACpC,CAAA;AAEV,0HAA0H;AAC1H,MAAM,CAAC,MAAM,cAAc,GAA6C;IACtE,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,KAAK,EAAE,GAAG,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,CAAC,EAAE,CAAC,CAAC;CACP,CAAA;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAA;AAEjC,oEAAoE;AACpE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAA"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE REACTION FAN (ui#351): the visitor's way in, replacing the feedback
|
|
3
|
+
* bubble. Vlad's design, as Tamir approved it on 2026-10-21 after trying the
|
|
4
|
+
* prototype on a desktop and an iPhone.
|
|
5
|
+
*
|
|
6
|
+
* At rest it is a small drop in the bottom-right corner, round with one sharp
|
|
7
|
+
* corner at the bottom left, holding the CloudGrid plug. It follows the system
|
|
8
|
+
* theme: purple with a white plug on a light system, white with a purple plug on
|
|
9
|
+
* a dark one. Opened, four options fan out up and to the left: Like, Dislike,
|
|
10
|
+
* Clever idea and Comment. The first three save in one tap; Comment opens the
|
|
11
|
+
* visitor panel, which is unchanged.
|
|
12
|
+
*
|
|
13
|
+
* This module has three parts, in the badge's usual style:
|
|
14
|
+
*
|
|
15
|
+
* markup `fan()`, an HTML string like `bubble()`; the stylesheet is
|
|
16
|
+
* `BADGE_FAN_CSS`, already inside `BADGE_VISITOR_CSS` and
|
|
17
|
+
* `BADGE_OWNER_CSS`
|
|
18
|
+
* helpers pure functions and the approved timings, tested in node
|
|
19
|
+
* behaviour `wireFan()`, which attaches the approved hover, touch and
|
|
20
|
+
* keyboard behaviour to a rendered fan and reports each choice;
|
|
21
|
+
* `wireFanPreview()` does the same for the owner's small copy
|
|
22
|
+
*
|
|
23
|
+
* Unlike the panels, the fan's state is not all in its markup: whether it is
|
|
24
|
+
* open, which option is under a finger and the cue that plays on a press are
|
|
25
|
+
* moment-to-moment, and live on the element. Render `fan()` once, wire it, and
|
|
26
|
+
* from then on update it with the handle (`sync`, `chosen`, `setHidden`), never
|
|
27
|
+
* by re-rendering or morphing it. The pressed state the markup takes is only the
|
|
28
|
+
* first paint.
|
|
29
|
+
*
|
|
30
|
+
* Importing this module does nothing: every DOM call is inside `wireFan()`.
|
|
31
|
+
*/
|
|
32
|
+
import { type ReactionKind } from "./reactions.js";
|
|
33
|
+
export { BADGE_FAN_CSS } from "./css-fan.js";
|
|
34
|
+
/** Desktop: how long the pointer rests on the icon before the fan opens. */
|
|
35
|
+
export declare const FAN_HOVER_OPEN_MS = 120;
|
|
36
|
+
/** Desktop: how long after the pointer leaves the fan before it closes. */
|
|
37
|
+
export declare const FAN_HOVER_CLOSE_MS = 300;
|
|
38
|
+
/**
|
|
39
|
+
* Touch: after every lift the fan stays open this long, then closes by itself.
|
|
40
|
+
* A tap inside the window chooses (founder, 2026-10-21; it was 0.5s).
|
|
41
|
+
*/
|
|
42
|
+
export declare const FAN_RELEASE_MS = 1200;
|
|
43
|
+
/** After Like, Dislike or Clever idea is pressed, the fan closes this long after the cue starts. */
|
|
44
|
+
export declare const FAN_CHOICE_CLOSE_MS = 1000;
|
|
45
|
+
/** How long the check shows in a pressed option before its glyph comes back. */
|
|
46
|
+
export declare const FAN_CHECK_MS = 650;
|
|
47
|
+
/** A click this soon after hover opened the fan is the same intent: it keeps the fan open. */
|
|
48
|
+
export declare const FAN_CLICK_AFTER_HOVER_MS = 700;
|
|
49
|
+
/** A click this soon after a touch is the touch's own echo, and is ignored. */
|
|
50
|
+
export declare const FAN_TOUCH_ECHO_MS = 800;
|
|
51
|
+
/** The haptic tick when a finger slides onto an option, where the browser has one. */
|
|
52
|
+
export declare const FAN_VIBRATE_MS = 10;
|
|
53
|
+
export { FAN_DIRECTIONS, FAN_HIT_SLOP, FAN_HOT_SCALE, FAN_SIZE } from "./fan-geometry.js";
|
|
54
|
+
/** What a fan option does: one of the three one-tap reactions, or Comment. */
|
|
55
|
+
export type FanKind = "like" | "dislike" | "idea" | "comment";
|
|
56
|
+
/**
|
|
57
|
+
* The four options, in order around the fan. The three reactions take the
|
|
58
|
+
* panel's own names, so the fan and the panel never call one thing two names.
|
|
59
|
+
*/
|
|
60
|
+
export declare const FAN_OPTIONS: ReadonlyArray<{
|
|
61
|
+
kind: FanKind;
|
|
62
|
+
label: string;
|
|
63
|
+
paths: readonly string[];
|
|
64
|
+
}>;
|
|
65
|
+
/** The icon's accessible name, the bubble's: the word "React" is never used. */
|
|
66
|
+
export declare const FAN_LABEL = "Leave feedback on this app";
|
|
67
|
+
/**
|
|
68
|
+
* The small marks the icon keeps for what this visitor has chosen, in this
|
|
69
|
+
* order. Rocket and Bug are chosen in the panel only, and still show here.
|
|
70
|
+
*/
|
|
71
|
+
export declare function fanMarkKinds(pressed: readonly ReactionKind[]): ReactionKind[];
|
|
72
|
+
/** The line a screen reader hears after a press: "Like saved", "Like removed". */
|
|
73
|
+
export declare function fanAnnouncement(kind: ReactionKind, on: boolean): string;
|
|
74
|
+
/**
|
|
75
|
+
* What a press on `kind` does to the pressed set, and which cues play: the
|
|
76
|
+
* pressed option pops (or shrinks, when it is taken back), and an option the
|
|
77
|
+
* press cleared (Like and Dislike exclude each other) shrinks too. Comment is
|
|
78
|
+
* not a reaction and changes nothing here.
|
|
79
|
+
*/
|
|
80
|
+
export declare function fanPress(pressed: readonly ReactionKind[], kind: ReactionKind): {
|
|
81
|
+
next: ReactionKind[];
|
|
82
|
+
on: boolean;
|
|
83
|
+
cleared: ReactionKind[];
|
|
84
|
+
};
|
|
85
|
+
export interface FanHitGeometry {
|
|
86
|
+
/** The icon's centre, in client pixels. */
|
|
87
|
+
cx: number;
|
|
88
|
+
cy: number;
|
|
89
|
+
/** Half the icon's drawn width. A point on the icon is never an option. */
|
|
90
|
+
iconHalf: number;
|
|
91
|
+
/** The radius and option size, unscaled (`FAN_SIZE`). */
|
|
92
|
+
radius: number;
|
|
93
|
+
option: number;
|
|
94
|
+
/** The drawn scale: 1 in the corner, 0.5 in the owner's preview. */
|
|
95
|
+
scale?: number;
|
|
96
|
+
/** The option currently under the finger, whose hit area has grown with it. */
|
|
97
|
+
hot?: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The option under a point, or -1. It tests where each option LANDS, not where
|
|
101
|
+
* it is mid-spread, so a quick tap on the icon never picks an option that is
|
|
102
|
+
* still passing under it. A point on the icon is never an option. Of the
|
|
103
|
+
* options whose square (half the option, grown when hot, plus the slop) holds
|
|
104
|
+
* the point, the nearest wins.
|
|
105
|
+
*/
|
|
106
|
+
export declare function fanOptionAt(x: number, y: number, g: FanHitGeometry): number;
|
|
107
|
+
/** `auto` follows the system setting; `light` and `dark` pin the icon, for a frozen frame. */
|
|
108
|
+
export type FanTheme = "auto" | "light" | "dark";
|
|
109
|
+
export interface FanOptions {
|
|
110
|
+
/** The kinds this visitor has already chosen: options drawn pressed, and the marks on the icon. First paint only. */
|
|
111
|
+
pressed?: readonly ReactionKind[];
|
|
112
|
+
/** Render it open, for a frozen frame and for the owner's preview. The badge opens it through the handle. */
|
|
113
|
+
open?: boolean;
|
|
114
|
+
/** Default `auto`. */
|
|
115
|
+
theme?: FanTheme;
|
|
116
|
+
/** The icon's accessible name. Default `FAN_LABEL`. */
|
|
117
|
+
label?: string;
|
|
118
|
+
/**
|
|
119
|
+
* When the arrival starts, in ms after insertion. Default 600, after the
|
|
120
|
+
* live badge's, as the bubble's was. `0` for a re-show.
|
|
121
|
+
*/
|
|
122
|
+
delay?: number;
|
|
123
|
+
/**
|
|
124
|
+
* The owner's small working copy in the "Ask visitors for feedback"
|
|
125
|
+
* explanation: no tab stops, no arrival, no status line, never the touch
|
|
126
|
+
* sizes. It sits inside a decorative (`aria-hidden`) tile.
|
|
127
|
+
*/
|
|
128
|
+
preview?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/** One mark on the icon. `fresh` pops in; the first paint's marks are at rest. */
|
|
131
|
+
export declare function fanMark(kind: ReactionKind, fresh?: boolean): string;
|
|
132
|
+
/**
|
|
133
|
+
* The fan: the drop icon, its marks, and the four options. Closed and at rest
|
|
134
|
+
* unless `open`. Every option is a button with its name and tooltip; the three
|
|
135
|
+
* reactions carry `aria-pressed`, Comment `aria-haspopup="dialog"`. The options
|
|
136
|
+
* are `inert` while the fan is closed.
|
|
137
|
+
*
|
|
138
|
+
* No `data-action` anywhere: `wireFan()` handles every press itself and reports
|
|
139
|
+
* the choice, so a delegated `[data-action]` listener never sees the fan.
|
|
140
|
+
*/
|
|
141
|
+
export declare function fan({ pressed, open, theme, label: name, delay, preview }?: FanOptions): string;
|
|
142
|
+
export interface WireFanOptions {
|
|
143
|
+
/**
|
|
144
|
+
* A press on an option. Like, Dislike and Clever idea: save the reaction, then
|
|
145
|
+
* call `handle.chosen(before, after, kind)` for the cue. Comment: close the
|
|
146
|
+
* fan and open the visitor panel. On an app that needs sign-in, close the fan
|
|
147
|
+
* and open the sign-in step instead.
|
|
148
|
+
*/
|
|
149
|
+
onChoose: (kind: FanKind, handle: FanHandle) => void;
|
|
150
|
+
/**
|
|
151
|
+
* Use the touch sizes from the start. Default: on where the primary pointer
|
|
152
|
+
* is coarse or there is no hover. The first touch turns them on regardless.
|
|
153
|
+
*/
|
|
154
|
+
touch?: boolean;
|
|
155
|
+
/** Close on a press anywhere outside the fan, and on Escape. Default true; the owner's preview turns it off. */
|
|
156
|
+
dismissable?: boolean;
|
|
157
|
+
}
|
|
158
|
+
export interface FanHandle {
|
|
159
|
+
/** The `.cgf` element. */
|
|
160
|
+
readonly el: HTMLElement;
|
|
161
|
+
readonly isOpen: boolean;
|
|
162
|
+
open(): void;
|
|
163
|
+
close(): void;
|
|
164
|
+
toggle(): void;
|
|
165
|
+
/** The pressed state, without a cue: `aria-pressed` on the options and the marks on the icon. Marks already shown are kept, never popped again. */
|
|
166
|
+
sync(pressed: readonly ReactionKind[]): void;
|
|
167
|
+
/**
|
|
168
|
+
* After a press on a reaction: sync to `after`, pop the pressed option (or
|
|
169
|
+
* shrink it, when it was taken back) with a check, shrink any option the
|
|
170
|
+
* press cleared, announce it, and close `FAN_CHOICE_CLOSE_MS` later.
|
|
171
|
+
*/
|
|
172
|
+
chosen(before: readonly ReactionKind[], after: readonly ReactionKind[], kind: ReactionKind): void;
|
|
173
|
+
/** Play one option's cue: `on` pops it (with the check unless `check` is false), otherwise it shrinks. */
|
|
174
|
+
cue(kind: FanKind | ReactionKind, on: boolean, check?: boolean): void;
|
|
175
|
+
/** Close `FAN_CHOICE_CLOSE_MS` from now, as after a choice. The pointer leaving does not cut it short. */
|
|
176
|
+
closeAfterCue(): void;
|
|
177
|
+
/** Hide it while a panel is open; showing it again replays the arrival at once. */
|
|
178
|
+
setHidden(hidden: boolean): void;
|
|
179
|
+
/** Focus the icon without opening the fan, as after a panel closes. */
|
|
180
|
+
focusIcon(): void;
|
|
181
|
+
/** Remove every listener and timer. */
|
|
182
|
+
destroy(): void;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Attach the approved behaviour to a fan rendered by `fan()`.
|
|
186
|
+
*
|
|
187
|
+
* desktop hover opens it after `FAN_HOVER_OPEN_MS`, leaving closes it
|
|
188
|
+
* after `FAN_HOVER_CLOSE_MS`; a quick pass never opens it. A click
|
|
189
|
+
* on the icon toggles (but not one right after hover opened it).
|
|
190
|
+
* Closed while the pointer is still over it (after a choice, a
|
|
191
|
+
* click, Escape), it reopens only once the pointer has left.
|
|
192
|
+
* keyboard focus on the icon opens it, Tab walks the options, Escape closes
|
|
193
|
+
* it, and focus leaving the fan closes it.
|
|
194
|
+
* touch a press opens it; slide onto an option (it grows, and the phone
|
|
195
|
+
* ticks) and lift to choose. After every lift it stays open for
|
|
196
|
+
* `FAN_RELEASE_MS`, then closes; a tap inside that window chooses.
|
|
197
|
+
* A tap on the icon while it is open closes it.
|
|
198
|
+
*
|
|
199
|
+
* The page never scrolls under a finger on the fan: the icon and the options
|
|
200
|
+
* take no touch gestures.
|
|
201
|
+
*/
|
|
202
|
+
export declare function wireFan(el: HTMLElement, { onChoose, touch, dismissable }: WireFanOptions): FanHandle;
|
|
203
|
+
/**
|
|
204
|
+
* Wire the owner's small copy of the fan, in the "Ask visitors for feedback"
|
|
205
|
+
* explanation, so the owner can try exactly what visitors get. Choices are kept
|
|
206
|
+
* in the preview only and saved nowhere; Comment plays its pop and nothing
|
|
207
|
+
* opens. Call it after each render that shows the explanation, on
|
|
208
|
+
* `.cgb-info .cgf`, and `destroy()` the handle when the explanation closes.
|
|
209
|
+
*/
|
|
210
|
+
export declare function wireFanPreview(el: HTMLElement): FanHandle;
|
|
211
|
+
//# sourceMappingURL=fan.d.ts.map
|