@cloudgrid-io/ui 0.34.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.
Files changed (72) hide show
  1. package/dist/badge/css-base.d.ts +4 -0
  2. package/dist/badge/css-base.d.ts.map +1 -1
  3. package/dist/badge/css-base.js +6 -2
  4. package/dist/badge/css-base.js.map +1 -1
  5. package/dist/badge/css-fan.d.ts +30 -0
  6. package/dist/badge/css-fan.d.ts.map +1 -0
  7. package/dist/badge/css-fan.js +90 -0
  8. package/dist/badge/css-fan.js.map +1 -0
  9. package/dist/badge/css-live.d.ts.map +1 -1
  10. package/dist/badge/css-live.js +8 -0
  11. package/dist/badge/css-live.js.map +1 -1
  12. package/dist/badge/css-owner.d.ts +4 -0
  13. package/dist/badge/css-owner.d.ts.map +1 -1
  14. package/dist/badge/css-owner.js +16 -12
  15. package/dist/badge/css-owner.js.map +1 -1
  16. package/dist/badge/css-visitor.d.ts +5 -1
  17. package/dist/badge/css-visitor.d.ts.map +1 -1
  18. package/dist/badge/css-visitor.js +7 -2
  19. package/dist/badge/css-visitor.js.map +1 -1
  20. package/dist/badge/fan-geometry.d.ts +27 -0
  21. package/dist/badge/fan-geometry.d.ts.map +1 -0
  22. package/dist/badge/fan-geometry.js +24 -0
  23. package/dist/badge/fan-geometry.js.map +1 -0
  24. package/dist/badge/fan.d.ts +211 -0
  25. package/dist/badge/fan.d.ts.map +1 -0
  26. package/dist/badge/fan.js +585 -0
  27. package/dist/badge/fan.js.map +1 -0
  28. package/dist/badge/index.d.ts +4 -1
  29. package/dist/badge/index.d.ts.map +1 -1
  30. package/dist/badge/index.js +8 -4
  31. package/dist/badge/index.js.map +1 -1
  32. package/dist/badge/marks.d.ts +2 -0
  33. package/dist/badge/marks.d.ts.map +1 -1
  34. package/dist/badge/marks.js +5 -0
  35. package/dist/badge/marks.js.map +1 -1
  36. package/dist/badge/owner.d.ts +1 -0
  37. package/dist/badge/owner.d.ts.map +1 -1
  38. package/dist/badge/owner.js +13 -10
  39. package/dist/badge/owner.js.map +1 -1
  40. package/dist/badge/reactions.d.ts +20 -0
  41. package/dist/badge/reactions.d.ts.map +1 -0
  42. package/dist/badge/reactions.js +26 -0
  43. package/dist/badge/reactions.js.map +1 -0
  44. package/dist/badge/visitor.d.ts +6 -12
  45. package/dist/badge/visitor.d.ts.map +1 -1
  46. package/dist/badge/visitor.js +11 -18
  47. package/dist/badge/visitor.js.map +1 -1
  48. package/dist/blocks/icons.d.ts +8 -0
  49. package/dist/blocks/icons.d.ts.map +1 -1
  50. package/dist/blocks/icons.js +8 -0
  51. package/dist/blocks/icons.js.map +1 -1
  52. package/dist/blocks/invite-popup.d.ts +156 -0
  53. package/dist/blocks/invite-popup.d.ts.map +1 -0
  54. package/dist/blocks/invite-popup.js +99 -0
  55. package/dist/blocks/invite-popup.js.map +1 -0
  56. package/dist/blocks/phosphor-marks.d.ts +2 -0
  57. package/dist/blocks/phosphor-marks.d.ts.map +1 -1
  58. package/dist/blocks/phosphor-marks.js +3 -0
  59. package/dist/blocks/phosphor-marks.js.map +1 -1
  60. package/dist/claim-banner/css.d.ts +4 -3
  61. package/dist/claim-banner/css.d.ts.map +1 -1
  62. package/dist/claim-banner/css.js +8 -12
  63. package/dist/claim-banner/css.js.map +1 -1
  64. package/dist/claim-banner/index.d.ts +21 -14
  65. package/dist/claim-banner/index.d.ts.map +1 -1
  66. package/dist/claim-banner/index.js +25 -24
  67. package/dist/claim-banner/index.js.map +1 -1
  68. package/dist/index.d.ts +1 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +1 -0
  71. package/dist/index.js.map +1 -1
  72. package/package.json +1 -1
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;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"}
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"}
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;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,iFAAiF;QACrF,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"}
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,MAwBpB,CAAA"}
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"}
@@ -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;;;;GAIG;AAKH,eAAO,MAAM,eAAe,EAAE,MAyKxB,CAAA"}
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"}
@@ -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 { bubbleLook } from "./css-bubble.js";
8
- export const BADGE_OWNER_CSS = /* @__PURE__ */ (() =>
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 sits in the middle of its tile, both ways (ui issue 329). The
74
- // wrap is the 22px strip for the x over the 40px pill, so the pill's centre
75
- // is 42px down the wrap: scaling about that point and pulling the wrap back
76
- // by it puts the pill's centre on the tile's. `width:max-content` keeps the
77
- // pill its own 74px, which `left:50%` alone would halve. At .8 the pill is
78
- // 59.2 by 32 and the x 16px, its top 17.6px above the pill's; hovered it
79
- // grows to 17.92 (scale 1.12), so the tile needs 2 x (17.6 + 0.96) + 32 =
80
- // 69.12px to hold it: 70. Gaps: 14.4px left and right, 19px top and bottom.
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;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE;AAC3D,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,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,4EAA4E;IAC5E;CACD,GAAG,UAAU,CAAC,kBAAkB,CAAC,GAAG;;;;;;;;;6JASwH;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,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"}
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;;;;GAIG;AAKH,eAAO,MAAM,iBAAiB,EAAE,MAkE1B,CAAA"}
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
- export const BADGE_VISITOR_CSS = /* @__PURE__ */ (() =>
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;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,MAAM,CAAC,MAAM,iBAAiB,GAAW,eAAe,CAAC,CAAC,GAAG,EAAE;AAC7D,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"}
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