@cairntale/chimeling-react 1.0.0-alpha.5 → 1.0.0-alpha.7

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 (37) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/components/index.d.ts +2 -2
  3. package/dist/components/playground/panel.js +142 -10
  4. package/dist/components/playground/panel.js.map +1 -1
  5. package/dist/components/playground/playground.d.ts +3 -1
  6. package/dist/components/playground/playground.js +45 -18
  7. package/dist/components/playground/playground.js.map +1 -1
  8. package/dist/components/playground/store.js +49 -8
  9. package/dist/components/playground/store.js.map +1 -1
  10. package/dist/components/popover.d.ts +9 -2
  11. package/dist/components/popover.js +117 -15
  12. package/dist/components/popover.js.map +1 -1
  13. package/dist/components/provider.d.ts +8 -1
  14. package/dist/components/provider.js +46 -11
  15. package/dist/components/provider.js.map +1 -1
  16. package/dist/components/root.js +8 -4
  17. package/dist/components/root.js.map +1 -1
  18. package/dist/components/trigger.d.ts +7 -2
  19. package/dist/components/trigger.js +67 -5
  20. package/dist/components/trigger.js.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/lib/use-client-committed.js +14 -0
  23. package/dist/lib/use-client-committed.js.map +1 -0
  24. package/dist/lib/widget-context.d.ts +3 -1
  25. package/dist/lib/widget-context.js.map +1 -1
  26. package/dist/theme/color-system.d.ts +1 -0
  27. package/dist/theme/color-system.js +96 -0
  28. package/dist/theme/color-system.js.map +1 -0
  29. package/dist/theme/context.d.ts +2 -0
  30. package/dist/theme/context.js +15 -0
  31. package/dist/theme/context.js.map +1 -0
  32. package/dist/theme/index.d.ts +4 -0
  33. package/dist/theme/index.js +4 -0
  34. package/dist/theme/tokens.d.ts +6 -0
  35. package/dist/theme/tokens.js +69 -0
  36. package/dist/theme/tokens.js.map +1 -0
  37. package/package.json +2 -1
@@ -3,34 +3,136 @@ import { useWidgetContext } from "../lib/widget-context.js";
3
3
  import { formatActivityDuration } from "../lib/format-activity-duration.js";
4
4
  import { iconImageUrl } from "../lib/icon-url.js";
5
5
  import Logo from "./logo.js";
6
+ import { ClassNames } from "@emotion/react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  import { Popover } from "@base-ui/react/popover";
8
9
  //#region src/components/popover.tsx
9
- function ChimelingPopover({ className, style }) {
10
+ const DEFAULT_POPOVER = {
11
+ ring: true,
12
+ shadow: "elevated",
13
+ minWidth: 320,
14
+ gerundCapitalize: true,
15
+ gerundEllipsis: true
16
+ };
17
+ const iconSize = "calc(22px * var(--chl-font-size-scaling, 1))";
18
+ function ChimelingPopover({ className, style, ring = DEFAULT_POPOVER.ring, shadow = DEFAULT_POPOVER.shadow, minWidth = DEFAULT_POPOVER.minWidth, gerundCapitalize = DEFAULT_POPOVER.gerundCapitalize, gerundEllipsis = DEFAULT_POPOVER.gerundEllipsis }) {
10
19
  const { showable, now, poweredBy, placement, baseUrl } = useWidgetContext();
11
20
  if (!showable) return null;
12
21
  const { gerund, appName, iconHash, startedAt } = showable.activity;
13
- return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
22
+ return /* @__PURE__ */ jsx(ClassNames, { children: ({ css, cx }) => /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
14
23
  side: placement.side,
15
24
  align: placement.align,
16
25
  sideOffset: placement.sideOffset,
17
26
  children: /* @__PURE__ */ jsxs(Popover.Popup, {
18
- className,
27
+ className: cx("chl-popover", css({
28
+ boxSizing: "border-box",
29
+ display: "flex",
30
+ flexDirection: "column",
31
+ minWidth,
32
+ overflow: "clip",
33
+ padding: 0,
34
+ margin: 0,
35
+ outline: "none",
36
+ color: "var(--chl-color-text-primary)",
37
+ backgroundColor: "var(--chl-color-background-primary)",
38
+ borderRadius: "var(--chl-border-radius-lg)",
39
+ border: "none",
40
+ boxShadow: [
41
+ ...shadow === "subtle" ? ["var(--chl-shadow-subtle)"] : [],
42
+ ...shadow === "elevated" ? ["var(--chl-shadow-elevated)"] : [],
43
+ ...ring ? ["var(--chl-ring)"] : []
44
+ ].join(", ") || "none"
45
+ }), className),
19
46
  style,
20
- children: [
21
- /* @__PURE__ */ jsx(Popover.Description, { children: gerund }),
22
- /* @__PURE__ */ jsx(Popover.Title, { children: appName }),
23
- /* @__PURE__ */ jsx("span", { children: formatActivityDuration(startedAt, now) }),
24
- iconHash ? /* @__PURE__ */ jsx("img", {
25
- src: iconImageUrl(baseUrl, iconHash),
26
- alt: ""
27
- }) : null,
28
- poweredBy ? /* @__PURE__ */ jsxs("div", { children: ["Powered by ", /* @__PURE__ */ jsx(Logo, {})] }) : null
29
- ]
47
+ "data-ring": ring ? "true" : "false",
48
+ "data-shadow": shadow,
49
+ "data-gerund-capitalize": gerundCapitalize ? "true" : "false",
50
+ "data-gerund-ellipsis": gerundEllipsis ? "true" : "false",
51
+ children: [/* @__PURE__ */ jsxs("div", {
52
+ className: css({
53
+ display: "flex",
54
+ flexDirection: "column",
55
+ gap: "var(--chl-spacing-2xs)",
56
+ padding: "var(--chl-spacing-sm)"
57
+ }),
58
+ children: [
59
+ /* @__PURE__ */ jsx(Popover.Description, {
60
+ className: css({
61
+ margin: 0,
62
+ fontSize: "var(--chl-font-size-sm)",
63
+ fontWeight: 400,
64
+ color: "var(--chl-color-text-tertiary)",
65
+ "[data-gerund-capitalize=\"true\"] &::first-letter": { textTransform: "uppercase" },
66
+ "[data-gerund-ellipsis=\"true\"] &::after": { content: "\"...\"" }
67
+ }),
68
+ children: gerund
69
+ }),
70
+ /* @__PURE__ */ jsxs("div", {
71
+ className: css({
72
+ display: "flex",
73
+ alignItems: "center",
74
+ gap: "var(--chl-spacing-2xs)",
75
+ minWidth: 0
76
+ }),
77
+ children: [iconHash ? /* @__PURE__ */ jsx("img", {
78
+ src: iconImageUrl(baseUrl, iconHash),
79
+ alt: "",
80
+ width: 24,
81
+ height: 24,
82
+ className: css({
83
+ display: "block",
84
+ flex: "0 0 auto",
85
+ inlineSize: iconSize,
86
+ blockSize: iconSize,
87
+ aspectRatio: "1",
88
+ objectFit: "contain",
89
+ margin: `calc(${iconSize} * -0.1)`
90
+ })
91
+ }) : null, /* @__PURE__ */ jsx(Popover.Title, {
92
+ className: css({
93
+ margin: 0,
94
+ minWidth: 0,
95
+ fontSize: "var(--chl-font-size-md)",
96
+ fontWeight: 450,
97
+ color: "var(--chl-color-text-primary)",
98
+ textBox: "trim-both cap alphabetic"
99
+ }),
100
+ children: appName
101
+ })]
102
+ }),
103
+ /* @__PURE__ */ jsx("span", {
104
+ className: css({
105
+ fontSize: "var(--chl-font-size-xs)",
106
+ color: "var(--chl-color-text-tertiary)"
107
+ }),
108
+ children: formatActivityDuration(startedAt, now)
109
+ })
110
+ ]
111
+ }), poweredBy ? /* @__PURE__ */ jsxs("a", {
112
+ href: "https://chimeling.app",
113
+ target: "_blank",
114
+ rel: "noopener noreferrer",
115
+ "aria-label": "Powered by Chimeling",
116
+ className: css({
117
+ display: "flex",
118
+ alignItems: "center",
119
+ gap: "var(--chl-spacing-2xs)",
120
+ paddingBlock: "var(--chl-spacing-xs)",
121
+ paddingInline: "var(--chl-spacing-sm)",
122
+ fontSize: "var(--chl-font-size-xs)",
123
+ color: "var(--chl-color-text-tertiary)",
124
+ backgroundColor: "var(--chl-color-background-secondary)",
125
+ textDecoration: "none",
126
+ outline: "none",
127
+ "&:hover, &:focus-visible": { backgroundColor: "var(--chl-color-background-secondary-focus)" },
128
+ "&:active": { backgroundColor: "var(--chl-color-background-secondary-active)" }
129
+ }),
130
+ children: ["Powered by ", /* @__PURE__ */ jsx(Logo, {})]
131
+ }) : null]
30
132
  })
31
- }) });
133
+ }) }) });
32
134
  }
33
135
  //#endregion
34
- export { ChimelingPopover };
136
+ export { ChimelingPopover, DEFAULT_POPOVER };
35
137
 
36
138
  //# sourceMappingURL=popover.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","names":[],"sources":["../../src/components/popover.tsx"],"sourcesContent":["'use client'\n\nimport { Popover } from '@base-ui/react/popover'\nimport type { PopoverPopupProps } from '@base-ui/react/popover'\nimport { formatActivityDuration } from '../lib/format-activity-duration'\nimport { iconImageUrl } from '../lib/icon-url'\nimport { useWidgetContext } from '../lib/widget-context'\nimport Logo from './logo'\n\n// TODO: decide whether to expose the rest of Base UI Popup props.\nexport type ChimelingPopoverProps = Pick<PopoverPopupProps, 'className' | 'style'>\n\nexport function ChimelingPopover({ className, style }: ChimelingPopoverProps) {\n const { showable, now, poweredBy, placement, baseUrl } = useWidgetContext()\n\n if (!showable) {\n return null\n }\n\n const { gerund, appName, iconHash, startedAt } = showable.activity\n\n return (\n <Popover.Portal>\n {/* TODO: decide whether to expose the rest of Base UI Positioner props. */}\n <Popover.Positioner\n side={placement.side}\n align={placement.align}\n sideOffset={placement.sideOffset}\n >\n <Popover.Popup className={className} style={style}>\n <Popover.Description>{gerund}</Popover.Description>\n <Popover.Title>{appName}</Popover.Title>\n <span>{formatActivityDuration(startedAt, now)}</span>\n {iconHash ? <img src={iconImageUrl(baseUrl, iconHash)} alt=\"\" /> : null}\n {poweredBy ? (\n <div>\n Powered by <Logo />\n </div>\n ) : null}\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,iBAAiB,EAAE,WAAW,SAAgC;CAC5E,MAAM,EAAE,UAAU,KAAK,WAAW,WAAW,YAAY,iBAAiB;CAE1E,IAAI,CAAC,UACH,OAAO;CAGT,MAAM,EAAE,QAAQ,SAAS,UAAU,cAAc,SAAS;CAE1D,OACE,oBAAC,QAAQ,QAAT,EAAA,UAEE,oBAAC,QAAQ,YAAT;EACE,MAAM,UAAU;EAChB,OAAO,UAAU;EACjB,YAAY,UAAU;EAEtB,UAAA,qBAAC,QAAQ,OAAT;GAA0B;GAAkB;GAA5C,UAAA;IACE,oBAAC,QAAQ,aAAT,EAAA,UAAsB,OAA4B,CAAA;IAClD,oBAAC,QAAQ,OAAT,EAAA,UAAgB,QAAuB,CAAA;IACvC,oBAAC,QAAD,EAAA,UAAO,uBAAuB,WAAW,GAAG,EAAQ,CAAA;IACnD,WAAW,oBAAC,OAAD;KAAK,KAAK,aAAa,SAAS,QAAQ;KAAG,KAAI;IAAI,CAAA,IAAI;IAClE,YACC,qBAAC,OAAD,EAAA,UAAA,CAAK,eACQ,oBAAC,MAAD,CAAO,CAAA,CACf,EAAA,CAAA,IACH;GACS;;CACG,CAAA,EACN,CAAA;AAEpB"}
1
+ {"version":3,"file":"popover.js","names":[],"sources":["../../src/components/popover.tsx"],"sourcesContent":["'use client'\n\nimport { ClassNames } from '@emotion/react'\nimport { Popover } from '@base-ui/react/popover'\nimport type { PopoverPopupProps } from '@base-ui/react/popover'\nimport { formatActivityDuration } from '../lib/format-activity-duration'\nimport { iconImageUrl } from '../lib/icon-url'\nimport { useWidgetContext } from '../lib/widget-context'\nimport Logo from './logo'\n\n// TODO: decide whether to expose the rest of Base UI Popup props.\nexport type ChimelingPopoverProps = Pick<PopoverPopupProps, 'style'> & {\n className?: string\n ring?: boolean\n shadow?: 'none' | 'subtle' | 'elevated'\n minWidth?: number\n gerundCapitalize?: boolean\n gerundEllipsis?: boolean\n}\n\nexport const DEFAULT_POPOVER = {\n ring: true,\n shadow: 'elevated',\n minWidth: 320,\n gerundCapitalize: true,\n gerundEllipsis: true,\n} as const\n\nconst iconSize = 'calc(22px * var(--chl-font-size-scaling, 1))'\n\nexport function ChimelingPopover({\n className,\n style,\n ring = DEFAULT_POPOVER.ring,\n shadow = DEFAULT_POPOVER.shadow,\n minWidth = DEFAULT_POPOVER.minWidth,\n gerundCapitalize = DEFAULT_POPOVER.gerundCapitalize,\n gerundEllipsis = DEFAULT_POPOVER.gerundEllipsis,\n}: ChimelingPopoverProps) {\n const { showable, now, poweredBy, placement, baseUrl } = useWidgetContext()\n\n if (!showable) {\n return null\n }\n\n const { gerund, appName, iconHash, startedAt } = showable.activity\n\n return (\n <ClassNames>\n {({ css, cx }) => (\n <Popover.Portal>\n {/* TODO: decide whether to expose the rest of Base UI Positioner props. */}\n <Popover.Positioner\n side={placement.side}\n align={placement.align}\n sideOffset={placement.sideOffset}\n >\n <Popover.Popup\n className={cx(\n 'chl-popover',\n css({\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n minWidth,\n overflow: 'clip',\n padding: 0,\n margin: 0,\n outline: 'none',\n color: 'var(--chl-color-text-primary)',\n backgroundColor: 'var(--chl-color-background-primary)',\n borderRadius: 'var(--chl-border-radius-lg)',\n border: 'none',\n boxShadow:\n [\n ...(shadow === 'subtle' ? ['var(--chl-shadow-subtle)'] : []),\n ...(shadow === 'elevated' ? ['var(--chl-shadow-elevated)'] : []),\n ...(ring ? ['var(--chl-ring)'] : []),\n ].join(', ') || 'none',\n }),\n className,\n )}\n style={style}\n data-ring={ring ? 'true' : 'false'}\n data-shadow={shadow}\n data-gerund-capitalize={gerundCapitalize ? 'true' : 'false'}\n data-gerund-ellipsis={gerundEllipsis ? 'true' : 'false'}\n >\n <div\n className={css({\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--chl-spacing-2xs)',\n padding: 'var(--chl-spacing-sm)',\n })}\n >\n <Popover.Description\n className={css({\n margin: 0,\n fontSize: 'var(--chl-font-size-sm)',\n fontWeight: 400,\n color: 'var(--chl-color-text-tertiary)',\n '[data-gerund-capitalize=\"true\"] &::first-letter': {\n textTransform: 'uppercase',\n },\n '[data-gerund-ellipsis=\"true\"] &::after': {\n content: '\"...\"',\n },\n })}\n >\n {gerund}\n </Popover.Description>\n <div\n className={css({\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--chl-spacing-2xs)',\n minWidth: 0,\n })}\n >\n {iconHash ? (\n <img\n src={iconImageUrl(baseUrl, iconHash)}\n alt=\"\"\n width={24}\n height={24}\n className={css({\n display: 'block',\n flex: '0 0 auto',\n inlineSize: iconSize,\n blockSize: iconSize,\n aspectRatio: '1',\n objectFit: 'contain',\n margin: `calc(${iconSize} * -0.1)`,\n })}\n />\n ) : null}\n <Popover.Title\n className={css({\n margin: 0,\n minWidth: 0,\n fontSize: 'var(--chl-font-size-md)',\n fontWeight: 450,\n color: 'var(--chl-color-text-primary)',\n textBox: 'trim-both cap alphabetic',\n })}\n >\n {appName}\n </Popover.Title>\n </div>\n <span\n className={css({\n fontSize: 'var(--chl-font-size-xs)',\n color: 'var(--chl-color-text-tertiary)',\n })}\n >\n {formatActivityDuration(startedAt, now)}\n </span>\n </div>\n {poweredBy ? (\n <a\n href=\"https://chimeling.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Powered by Chimeling\"\n className={css({\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--chl-spacing-2xs)',\n paddingBlock: 'var(--chl-spacing-xs)',\n paddingInline: 'var(--chl-spacing-sm)',\n fontSize: 'var(--chl-font-size-xs)',\n color: 'var(--chl-color-text-tertiary)',\n backgroundColor: 'var(--chl-color-background-secondary)',\n textDecoration: 'none',\n outline: 'none',\n '&:hover, &:focus-visible': {\n backgroundColor: 'var(--chl-color-background-secondary-focus)',\n },\n '&:active': {\n backgroundColor: 'var(--chl-color-background-secondary-active)',\n },\n })}\n >\n Powered by <Logo />\n </a>\n ) : null}\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n )}\n </ClassNames>\n )\n}\n"],"mappings":";;;;;;;;;AAoBA,MAAa,kBAAkB;CAC7B,MAAM;CACN,QAAQ;CACR,UAAU;CACV,kBAAkB;CAClB,gBAAgB;AAClB;AAEA,MAAM,WAAW;AAEjB,SAAgB,iBAAiB,EAC/B,WACA,OACA,OAAO,gBAAgB,MACvB,SAAS,gBAAgB,QACzB,WAAW,gBAAgB,UAC3B,mBAAmB,gBAAgB,kBACnC,iBAAiB,gBAAgB,kBACT;CACxB,MAAM,EAAE,UAAU,KAAK,WAAW,WAAW,YAAY,iBAAiB;CAE1E,IAAI,CAAC,UACH,OAAO;CAGT,MAAM,EAAE,QAAQ,SAAS,UAAU,cAAc,SAAS;CAE1D,OACE,oBAAC,YAAD,EAAA,WACI,EAAE,KAAK,SACP,oBAAC,QAAQ,QAAT,EAAA,UAEE,oBAAC,QAAQ,YAAT;EACE,MAAM,UAAU;EAChB,OAAO,UAAU;EACjB,YAAY,UAAU;EAEtB,UAAA,qBAAC,QAAQ,OAAT;GACE,WAAW,GACT,eACA,IAAI;IACF,WAAW;IACX,SAAS;IACT,eAAe;IACf;IACA,UAAU;IACV,SAAS;IACT,QAAQ;IACR,SAAS;IACT,OAAO;IACP,iBAAiB;IACjB,cAAc;IACd,QAAQ;IACR,WACE;KACE,GAAI,WAAW,WAAW,CAAC,0BAA0B,IAAI,CAAC;KAC1D,GAAI,WAAW,aAAa,CAAC,4BAA4B,IAAI,CAAC;KAC9D,GAAI,OAAO,CAAC,iBAAiB,IAAI,CAAC;IACpC,CAAC,CAAC,KAAK,IAAI,KAAK;GACpB,CAAC,GACD,SACF;GACO;GACP,aAAW,OAAO,SAAS;GAC3B,eAAa;GACb,0BAAwB,mBAAmB,SAAS;GACpD,wBAAsB,iBAAiB,SAAS;GA7BlD,UAAA,CA+BE,qBAAC,OAAD;IACE,WAAW,IAAI;KACb,SAAS;KACT,eAAe;KACf,KAAK;KACL,SAAS;IACX,CAAC;IANH,UAAA;KAQE,oBAAC,QAAQ,aAAT;MACE,WAAW,IAAI;OACb,QAAQ;OACR,UAAU;OACV,YAAY;OACZ,OAAO;OACP,qDAAmD,EACjD,eAAe,YACjB;OACA,4CAA0C,EACxC,SAAS,UACX;MACF,CAAC;MAEA,UAAA;KACkB,CAAA;KACrB,qBAAC,OAAD;MACE,WAAW,IAAI;OACb,SAAS;OACT,YAAY;OACZ,KAAK;OACL,UAAU;MACZ,CAAC;MANH,UAAA,CAQG,WACC,oBAAC,OAAD;OACE,KAAK,aAAa,SAAS,QAAQ;OACnC,KAAI;OACJ,OAAO;OACP,QAAQ;OACR,WAAW,IAAI;QACb,SAAS;QACT,MAAM;QACN,YAAY;QACZ,WAAW;QACX,aAAa;QACb,WAAW;QACX,QAAQ,QAAQ,SAAS;OAC3B,CAAC;MACF,CAAA,IACC,MACJ,oBAAC,QAAQ,OAAT;OACE,WAAW,IAAI;QACb,QAAQ;QACR,UAAU;QACV,UAAU;QACV,YAAY;QACZ,OAAO;QACP,SAAS;OACX,CAAC;OAEA,UAAA;MACY,CAAA,CACZ;;KACL,oBAAC,QAAD;MACE,WAAW,IAAI;OACb,UAAU;OACV,OAAO;MACT,CAAC;MAEA,UAAA,uBAAuB,WAAW,GAAG;KAClC,CAAA;IACH;GACJ,CAAA,GAAA,YACC,qBAAC,KAAD;IACE,MAAK;IACL,QAAO;IACP,KAAI;IACJ,cAAW;IACX,WAAW,IAAI;KACb,SAAS;KACT,YAAY;KACZ,KAAK;KACL,cAAc;KACd,eAAe;KACf,UAAU;KACV,OAAO;KACP,iBAAiB;KACjB,gBAAgB;KAChB,SAAS;KACT,4BAA4B,EAC1B,iBAAiB,8CACnB;KACA,YAAY,EACV,iBAAiB,+CACnB;IACF,CAAC;IAtBH,UAAA,CAuBC,eACY,oBAAC,MAAD,CAAO,CAAA,CACjB;GACD,CAAA,IAAA,IACS;;CACG,CAAA,EACN,CAAA,EAER,CAAA;AAEhB"}
@@ -1,3 +1,5 @@
1
+ import { ChimelingColorScheme } from "../theme/tokens.js";
2
+ import "../theme/index.js";
1
3
  import { ReactNode } from "react";
2
4
  //#region src/components/provider.d.ts
3
5
  type ChimelingProviderProps = {
@@ -5,8 +7,13 @@ type ChimelingProviderProps = {
5
7
  refreshInterval?: number;
6
8
  children?: ReactNode;
7
9
  nonce?: string;
10
+ accentColor?: string;
11
+ colorScheme?: ChimelingColorScheme;
12
+ spacingScaling?: number;
13
+ fontSizeScaling?: number;
14
+ borderRadiusScaling?: number;
8
15
  };
9
- declare function ChimelingProvider({ baseUrl, refreshInterval, children, nonce }: ChimelingProviderProps): import("react").JSX.Element;
16
+ declare function ChimelingProvider({ baseUrl, refreshInterval, children, nonce, accentColor, colorScheme, spacingScaling, fontSizeScaling, borderRadiusScaling }: ChimelingProviderProps): import("react").JSX.Element;
10
17
  //#endregion
11
18
  export { ChimelingProvider, ChimelingProviderProps };
12
19
  //# sourceMappingURL=provider.d.ts.map
@@ -1,36 +1,71 @@
1
1
  "use client";
2
2
  import { DEFAULT_PRESENCE_REFRESH_INTERVAL } from "../lib/config.js";
3
3
  import { ChimelingContext } from "../lib/context.js";
4
+ import { useClientCommitted } from "../lib/use-client-committed.js";
5
+ import { generateContrastColor } from "../theme/color-system.js";
6
+ import { rootStyle } from "../theme/tokens.js";
7
+ import { ThemeProvider } from "../theme/context.js";
8
+ import "../theme/index.js";
4
9
  import { useMemo } from "react";
5
10
  import { createClient, createConfig } from "@cairntale/chimeling-js/client";
6
11
  import createCache from "@emotion/cache";
7
- import { CacheProvider } from "@emotion/react";
8
- import { jsx } from "react/jsx-runtime";
12
+ import { CacheProvider, Global } from "@emotion/react";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
9
14
  //#region src/components/provider.tsx
10
- function ChimelingProvider({ baseUrl, refreshInterval = DEFAULT_PRESENCE_REFRESH_INTERVAL, children, nonce }) {
15
+ const DEFAULT_BASE_URL = "https://chimeling.app";
16
+ function ChimelingProvider({ baseUrl, refreshInterval = DEFAULT_PRESENCE_REFRESH_INTERVAL, children, nonce, accentColor, colorScheme, spacingScaling, fontSizeScaling, borderRadiusScaling }) {
17
+ const committed = useClientCommitted();
11
18
  const client = useMemo(() => createClient(createConfig({ baseUrl: baseUrl ?? "https://chimeling.app" })), [baseUrl]);
12
19
  const value = useMemo(() => ({
13
20
  client,
14
21
  refreshInterval
15
22
  }), [client, refreshInterval]);
23
+ const theme = useMemo(() => {
24
+ if (accentColor !== void 0) generateContrastColor(accentColor);
25
+ return {
26
+ accentColor,
27
+ colorScheme,
28
+ spacingScaling,
29
+ fontSizeScaling,
30
+ borderRadiusScaling
31
+ };
32
+ }, [
33
+ accentColor,
34
+ colorScheme,
35
+ spacingScaling,
36
+ fontSizeScaling,
37
+ borderRadiusScaling
38
+ ]);
16
39
  const emotionCache = useMemo(() => {
17
- const insertionPoint = typeof document !== "undefined" ? document.querySelector(`style#chl-style-insertion-point`) ?? void 0 : void 0;
40
+ if (!committed) return;
41
+ const insertionPoint = document.querySelector(`style#chl-style-insertion-point`) ?? void 0;
18
42
  return createCache({
19
43
  key: "chl-internal",
20
44
  prepend: !insertionPoint,
21
45
  insertionPoint,
22
46
  nonce
23
47
  });
24
- }, [nonce]);
25
- return /* @__PURE__ */ jsx(CacheProvider, {
26
- value: emotionCache,
27
- children: /* @__PURE__ */ jsx(ChimelingContext.Provider, {
28
- value,
29
- children
48
+ }, [committed, nonce]);
49
+ const tree = /* @__PURE__ */ jsx(ChimelingContext.Provider, {
50
+ value,
51
+ children: /* @__PURE__ */ jsx(ThemeProvider, {
52
+ value: theme,
53
+ children: committed ? children : null
30
54
  })
31
55
  });
56
+ if (!emotionCache) return tree;
57
+ return /* @__PURE__ */ jsxs(CacheProvider, {
58
+ value: emotionCache,
59
+ children: [/* @__PURE__ */ jsx(Global, { styles: {
60
+ ":root": rootStyle(theme),
61
+ ".chl-trigger, .chl-popover": {
62
+ fontFamily: "var(--chl-font-family)",
63
+ ...theme.colorScheme === "light" || theme.colorScheme === "dark" ? { colorScheme: theme.colorScheme } : {}
64
+ }
65
+ } }), tree]
66
+ });
32
67
  }
33
68
  //#endregion
34
- export { ChimelingProvider };
69
+ export { ChimelingProvider, DEFAULT_BASE_URL };
35
70
 
36
71
  //# sourceMappingURL=provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":[],"sources":["../../src/components/provider.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, type ReactNode } from 'react'\nimport { createClient, createConfig } from '@cairntale/chimeling-js/client'\nimport { DEFAULT_PRESENCE_REFRESH_INTERVAL } from '../lib/config'\nimport { ChimelingContext } from '../lib/context'\nimport createCache from '@emotion/cache'\nimport { CacheProvider } from '@emotion/react'\n\nexport type ChimelingProviderProps = {\n baseUrl?: string\n refreshInterval?: number\n children?: ReactNode\n nonce?: string\n}\n\nexport function ChimelingProvider({\n baseUrl,\n refreshInterval = DEFAULT_PRESENCE_REFRESH_INTERVAL,\n children,\n nonce,\n}: ChimelingProviderProps) {\n const client = useMemo(\n () => createClient(createConfig({ baseUrl: baseUrl ?? 'https://chimeling.app' })),\n [baseUrl],\n )\n const value = useMemo(() => ({ client, refreshInterval }), [client, refreshInterval])\n\n const emotionCache = useMemo(() => {\n const insertionPoint =\n typeof document !== 'undefined'\n ? (document.querySelector<HTMLElement>(`style#chl-style-insertion-point`) ?? undefined)\n : undefined\n\n return createCache({\n key: 'chl-internal',\n prepend: !insertionPoint,\n insertionPoint,\n nonce,\n })\n }, [nonce])\n\n return (\n <CacheProvider value={emotionCache}>\n <ChimelingContext.Provider value={value}>{children}</ChimelingContext.Provider>\n </CacheProvider>\n )\n}\n"],"mappings":";;;;;;;;;AAgBA,SAAgB,kBAAkB,EAChC,SACA,kBAAkB,mCAClB,UACA,SACyB;CACzB,MAAM,SAAS,cACP,aAAa,aAAa,EAAE,SAAS,WAAW,wBAAwB,CAAC,CAAC,GAChF,CAAC,OAAO,CACV;CACA,MAAM,QAAQ,eAAe;EAAE;EAAQ;CAAgB,IAAI,CAAC,QAAQ,eAAe,CAAC;CAEpF,MAAM,eAAe,cAAc;EACjC,MAAM,iBACJ,OAAO,aAAa,cACf,SAAS,cAA2B,iCAAiC,KAAK,KAAA,IAC3E,KAAA;EAEN,OAAO,YAAY;GACjB,KAAK;GACL,SAAS,CAAC;GACV;GACA;EACF,CAAC;CACH,GAAG,CAAC,KAAK,CAAC;CAEV,OACE,oBAAC,eAAD;EAAe,OAAO;EACpB,UAAA,oBAAC,iBAAiB,UAAlB;GAAkC;GAAQ;EAAoC,CAAA;CACjE,CAAA;AAEnB"}
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../../src/components/provider.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, type ReactNode } from 'react'\nimport { createClient, createConfig } from '@cairntale/chimeling-js/client'\nimport { DEFAULT_PRESENCE_REFRESH_INTERVAL } from '../lib/config'\nimport { ChimelingContext } from '../lib/context'\nimport { useClientCommitted } from '../lib/use-client-committed'\nimport createCache from '@emotion/cache'\nimport { CacheProvider, Global } from '@emotion/react'\nimport {\n ThemeProvider,\n generateContrastColor,\n rootStyle,\n type ChimelingColorScheme,\n} from '../theme'\n\nexport type ChimelingProviderProps = {\n baseUrl?: string\n refreshInterval?: number\n children?: ReactNode\n nonce?: string\n accentColor?: string\n colorScheme?: ChimelingColorScheme\n spacingScaling?: number\n fontSizeScaling?: number\n borderRadiusScaling?: number\n}\n\nexport const DEFAULT_BASE_URL = 'https://chimeling.app'\n\nexport function ChimelingProvider({\n baseUrl,\n refreshInterval = DEFAULT_PRESENCE_REFRESH_INTERVAL,\n children,\n nonce,\n accentColor,\n colorScheme,\n spacingScaling,\n fontSizeScaling,\n borderRadiusScaling,\n}: ChimelingProviderProps) {\n const committed = useClientCommitted()\n const client = useMemo(\n () => createClient(createConfig({ baseUrl: baseUrl ?? DEFAULT_BASE_URL })),\n [baseUrl],\n )\n const value = useMemo(() => ({ client, refreshInterval }), [client, refreshInterval])\n const theme = useMemo(() => {\n if (accentColor !== undefined) {\n generateContrastColor(accentColor)\n }\n return { accentColor, colorScheme, spacingScaling, fontSizeScaling, borderRadiusScaling }\n }, [accentColor, colorScheme, spacingScaling, fontSizeScaling, borderRadiusScaling])\n\n const emotionCache = useMemo(() => {\n if (!committed) {\n return undefined\n }\n\n const insertionPoint =\n document.querySelector<HTMLElement>(`style#chl-style-insertion-point`) ?? undefined\n\n return createCache({\n key: 'chl-internal',\n prepend: !insertionPoint,\n insertionPoint,\n nonce,\n })\n }, [committed, nonce])\n\n const tree = (\n <ChimelingContext.Provider value={value}>\n <ThemeProvider value={theme}>{committed ? children : null}</ThemeProvider>\n </ChimelingContext.Provider>\n )\n\n if (!emotionCache) {\n return tree\n }\n\n return (\n <CacheProvider value={emotionCache}>\n <Global\n styles={{\n ':root': rootStyle(theme),\n '.chl-trigger, .chl-popover': {\n fontFamily: 'var(--chl-font-family)',\n ...(theme.colorScheme === 'light' || theme.colorScheme === 'dark'\n ? { colorScheme: theme.colorScheme }\n : {}),\n },\n }}\n />\n {tree}\n </CacheProvider>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAa,mBAAmB;AAEhC,SAAgB,kBAAkB,EAChC,SACA,kBAAkB,mCAClB,UACA,OACA,aACA,aACA,gBACA,iBACA,uBACyB;CACzB,MAAM,YAAY,mBAAmB;CACrC,MAAM,SAAS,cACP,aAAa,aAAa,EAAE,SAAS,WAAA,wBAA4B,CAAC,CAAC,GACzE,CAAC,OAAO,CACV;CACA,MAAM,QAAQ,eAAe;EAAE;EAAQ;CAAgB,IAAI,CAAC,QAAQ,eAAe,CAAC;CACpF,MAAM,QAAQ,cAAc;EAC1B,IAAI,gBAAgB,KAAA,GAClB,sBAAsB,WAAW;EAEnC,OAAO;GAAE;GAAa;GAAa;GAAgB;GAAiB;EAAoB;CAC1F,GAAG;EAAC;EAAa;EAAa;EAAgB;EAAiB;CAAmB,CAAC;CAEnF,MAAM,eAAe,cAAc;EACjC,IAAI,CAAC,WACH;EAGF,MAAM,iBACJ,SAAS,cAA2B,iCAAiC,KAAK,KAAA;EAE5E,OAAO,YAAY;GACjB,KAAK;GACL,SAAS,CAAC;GACV;GACA;EACF,CAAC;CACH,GAAG,CAAC,WAAW,KAAK,CAAC;CAErB,MAAM,OACJ,oBAAC,iBAAiB,UAAlB;EAAkC;EAChC,UAAA,oBAAC,eAAD;GAAe,OAAO;GAAQ,UAAA,YAAY,WAAW;EAAoB,CAAA;CAChD,CAAA;CAG7B,IAAI,CAAC,cACH,OAAO;CAGT,OACE,qBAAC,eAAD;EAAe,OAAO;EAAtB,UAAA,CACE,oBAAC,QAAD,EACE,QAAQ;GACN,SAAS,UAAU,KAAK;GACxB,8BAA8B;IAC5B,YAAY;IACZ,GAAI,MAAM,gBAAgB,WAAW,MAAM,gBAAgB,SACvD,EAAE,aAAa,MAAM,YAAY,IACjC,CAAC;GACP;EACF,EACD,CAAA,GACA,IACY;;AAEnB"}
@@ -7,9 +7,13 @@ import { useEffect, useMemo, useRef, useState } from "react";
7
7
  import { jsx } from "react/jsx-runtime";
8
8
  import { Popover } from "@base-ui/react/popover";
9
9
  //#region src/components/root.tsx
10
- const DEFAULT_HOVER_OPEN_DELAY = 300;
11
- const DEFAULT_HOVER_CLOSE_DELAY = 0;
12
- function ChimelingRoot({ userId, children, poweredBy = true, openOnHover = false, hoverOpenDelay = DEFAULT_HOVER_OPEN_DELAY, hoverCloseDelay = DEFAULT_HOVER_CLOSE_DELAY, onReady, presence: presenceOverride, refreshInterval, side, align, sideOffset }) {
10
+ const DEFAULT_ROOT = {
11
+ openOnHover: false,
12
+ hoverOpenDelay: 300,
13
+ hoverCloseDelay: 0,
14
+ sideOffset: 6
15
+ };
16
+ function ChimelingRoot({ userId, children, poweredBy = true, openOnHover = DEFAULT_ROOT.openOnHover, hoverOpenDelay = DEFAULT_ROOT.hoverOpenDelay, hoverCloseDelay = DEFAULT_ROOT.hoverCloseDelay, onReady, presence: presenceOverride, refreshInterval, side, align, sideOffset = DEFAULT_ROOT.sideOffset }) {
13
17
  const { client } = useChimelingContext();
14
18
  const fetched = useResolvedUserPresence(presenceOverride === void 0 ? userId : "", { refreshInterval });
15
19
  const presence = presenceOverride ?? fetched.data;
@@ -61,6 +65,6 @@ function ChimelingRoot({ userId, children, poweredBy = true, openOnHover = false
61
65
  });
62
66
  }
63
67
  //#endregion
64
- export { ChimelingRoot };
68
+ export { ChimelingRoot, DEFAULT_ROOT };
65
69
 
66
70
  //# sourceMappingURL=root.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","names":[],"sources":["../../src/components/root.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { Popover } from '@base-ui/react/popover'\nimport type { GetResolvedUserPresenceResponse } from '@cairntale/chimeling-js'\nimport { useResolvedUserPresence } from '../hooks/use-resolved-user-presence'\nimport { useChimelingContext } from '../lib/context'\nimport { getShowablePresence, type ShowablePresence } from '../lib/showable-presence'\nimport { WidgetContext, type WidgetPlacement } from '../lib/widget-context'\n\nconst DEFAULT_HOVER_OPEN_DELAY = 300\nconst DEFAULT_HOVER_CLOSE_DELAY = 0\n\nexport type ChimelingRootProps = WidgetPlacement & {\n userId: string\n children: ReactNode\n poweredBy?: boolean\n openOnHover?: boolean\n hoverOpenDelay?: number\n hoverCloseDelay?: number\n onReady?: (presence: ShowablePresence) => void\n presence?: GetResolvedUserPresenceResponse\n refreshInterval?: number\n}\n\nexport function ChimelingRoot({\n userId,\n children,\n poweredBy = true,\n openOnHover = false,\n hoverOpenDelay = DEFAULT_HOVER_OPEN_DELAY,\n hoverCloseDelay = DEFAULT_HOVER_CLOSE_DELAY,\n onReady,\n presence: presenceOverride,\n refreshInterval,\n side,\n align,\n sideOffset,\n}: ChimelingRootProps) {\n const { client } = useChimelingContext()\n const fetched = useResolvedUserPresence(presenceOverride === undefined ? userId : '', {\n refreshInterval,\n })\n const presence = presenceOverride ?? fetched.data\n const showable = useMemo(() => getShowablePresence(presence), [presence])\n\n const [now, setNow] = useState(() => new Date())\n const readyRef = useRef(false)\n\n useEffect(() => {\n if (!showable) {\n return\n }\n\n const id = setInterval(() => setNow(new Date()), 1000)\n return () => clearInterval(id)\n }, [showable])\n\n useEffect(() => {\n if (readyRef.current || !showable) {\n return\n }\n\n readyRef.current = true\n onReady?.(showable)\n }, [showable, onReady])\n\n const baseUrl = client.getConfig().baseUrl ?? ''\n const placement = useMemo(() => ({ side, align, sideOffset }), [side, align, sideOffset])\n\n const value = useMemo(\n () => ({\n showable,\n now,\n poweredBy,\n openOnHover,\n hoverOpenDelay,\n hoverCloseDelay,\n placement,\n baseUrl,\n }),\n [showable, now, poweredBy, openOnHover, hoverOpenDelay, hoverCloseDelay, placement, baseUrl],\n )\n\n return (\n <WidgetContext.Provider value={value}>\n {/* TODO: decide whether to expose Base UI Root props (open, onOpenChange, …). */}\n {showable ? <Popover.Root>{children}</Popover.Root> : children}\n </WidgetContext.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAclC,SAAgB,cAAc,EAC5B,QACA,UACA,YAAY,MACZ,cAAc,OACd,iBAAiB,0BACjB,kBAAkB,2BAClB,SACA,UAAU,kBACV,iBACA,MACA,OACA,cACqB;CACrB,MAAM,EAAE,WAAW,oBAAoB;CACvC,MAAM,UAAU,wBAAwB,qBAAqB,KAAA,IAAY,SAAS,IAAI,EACpF,gBACF,CAAC;CACD,MAAM,WAAW,oBAAoB,QAAQ;CAC7C,MAAM,WAAW,cAAc,oBAAoB,QAAQ,GAAG,CAAC,QAAQ,CAAC;CAExE,MAAM,CAAC,KAAK,UAAU,+BAAe,IAAI,KAAK,CAAC;CAC/C,MAAM,WAAW,OAAO,KAAK;CAE7B,gBAAgB;EACd,IAAI,CAAC,UACH;EAGF,MAAM,KAAK,kBAAkB,uBAAO,IAAI,KAAK,CAAC,GAAG,GAAI;EACrD,aAAa,cAAc,EAAE;CAC/B,GAAG,CAAC,QAAQ,CAAC;CAEb,gBAAgB;EACd,IAAI,SAAS,WAAW,CAAC,UACvB;EAGF,SAAS,UAAU;EACnB,UAAU,QAAQ;CACpB,GAAG,CAAC,UAAU,OAAO,CAAC;CAEtB,MAAM,UAAU,OAAO,UAAU,CAAC,CAAC,WAAW;CAC9C,MAAM,YAAY,eAAe;EAAE;EAAM;EAAO;CAAW,IAAI;EAAC;EAAM;EAAO;CAAU,CAAC;CAExF,MAAM,QAAQ,eACL;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EAAC;EAAU;EAAK;EAAW;EAAa;EAAgB;EAAiB;EAAW;CAAO,CAC7F;CAEA,OACE,oBAAC,cAAc,UAAf;EAA+B;EAE5B,UAAA,WAAW,oBAAC,QAAQ,MAAT,EAAe,SAAuB,CAAA,IAAI;CAChC,CAAA;AAE5B"}
1
+ {"version":3,"file":"root.js","names":[],"sources":["../../src/components/root.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { Popover } from '@base-ui/react/popover'\nimport type { GetResolvedUserPresenceResponse } from '@cairntale/chimeling-js'\nimport { useResolvedUserPresence } from '../hooks/use-resolved-user-presence'\nimport { useChimelingContext } from '../lib/context'\nimport { getShowablePresence, type ShowablePresence } from '../lib/showable-presence'\nimport { WidgetContext, type WidgetPlacement } from '../lib/widget-context'\n\nexport const DEFAULT_ROOT = {\n openOnHover: false,\n hoverOpenDelay: 300,\n hoverCloseDelay: 0,\n sideOffset: 6,\n} as const\n\nexport type ChimelingRootProps = WidgetPlacement & {\n userId: string\n children: ReactNode\n poweredBy?: boolean\n openOnHover?: boolean\n hoverOpenDelay?: number\n hoverCloseDelay?: number\n onReady?: (presence: ShowablePresence) => void\n presence?: GetResolvedUserPresenceResponse\n refreshInterval?: number\n}\n\nexport function ChimelingRoot({\n userId,\n children,\n poweredBy = true,\n openOnHover = DEFAULT_ROOT.openOnHover,\n hoverOpenDelay = DEFAULT_ROOT.hoverOpenDelay,\n hoverCloseDelay = DEFAULT_ROOT.hoverCloseDelay,\n onReady,\n presence: presenceOverride,\n refreshInterval,\n side,\n align,\n sideOffset = DEFAULT_ROOT.sideOffset,\n}: ChimelingRootProps) {\n const { client } = useChimelingContext()\n const fetched = useResolvedUserPresence(presenceOverride === undefined ? userId : '', {\n refreshInterval,\n })\n const presence = presenceOverride ?? fetched.data\n const showable = useMemo(() => getShowablePresence(presence), [presence])\n\n const [now, setNow] = useState(() => new Date())\n const readyRef = useRef(false)\n\n useEffect(() => {\n if (!showable) {\n return\n }\n\n const id = setInterval(() => setNow(new Date()), 1000)\n return () => clearInterval(id)\n }, [showable])\n\n useEffect(() => {\n if (readyRef.current || !showable) {\n return\n }\n\n readyRef.current = true\n onReady?.(showable)\n }, [showable, onReady])\n\n const baseUrl = client.getConfig().baseUrl ?? ''\n const placement = useMemo(() => ({ side, align, sideOffset }), [side, align, sideOffset])\n\n const value = useMemo(\n () => ({\n showable,\n now,\n poweredBy,\n openOnHover,\n hoverOpenDelay,\n hoverCloseDelay,\n placement,\n baseUrl,\n }),\n [showable, now, poweredBy, openOnHover, hoverOpenDelay, hoverCloseDelay, placement, baseUrl],\n )\n\n return (\n <WidgetContext.Provider value={value}>\n {showable ? <Popover.Root>{children}</Popover.Root> : children}\n </WidgetContext.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAUA,MAAa,eAAe;CAC1B,aAAa;CACb,gBAAgB;CAChB,iBAAiB;CACjB,YAAY;AACd;AAcA,SAAgB,cAAc,EAC5B,QACA,UACA,YAAY,MACZ,cAAc,aAAa,aAC3B,iBAAiB,aAAa,gBAC9B,kBAAkB,aAAa,iBAC/B,SACA,UAAU,kBACV,iBACA,MACA,OACA,aAAa,aAAa,cACL;CACrB,MAAM,EAAE,WAAW,oBAAoB;CACvC,MAAM,UAAU,wBAAwB,qBAAqB,KAAA,IAAY,SAAS,IAAI,EACpF,gBACF,CAAC;CACD,MAAM,WAAW,oBAAoB,QAAQ;CAC7C,MAAM,WAAW,cAAc,oBAAoB,QAAQ,GAAG,CAAC,QAAQ,CAAC;CAExE,MAAM,CAAC,KAAK,UAAU,+BAAe,IAAI,KAAK,CAAC;CAC/C,MAAM,WAAW,OAAO,KAAK;CAE7B,gBAAgB;EACd,IAAI,CAAC,UACH;EAGF,MAAM,KAAK,kBAAkB,uBAAO,IAAI,KAAK,CAAC,GAAG,GAAI;EACrD,aAAa,cAAc,EAAE;CAC/B,GAAG,CAAC,QAAQ,CAAC;CAEb,gBAAgB;EACd,IAAI,SAAS,WAAW,CAAC,UACvB;EAGF,SAAS,UAAU;EACnB,UAAU,QAAQ;CACpB,GAAG,CAAC,UAAU,OAAO,CAAC;CAEtB,MAAM,UAAU,OAAO,UAAU,CAAC,CAAC,WAAW;CAC9C,MAAM,YAAY,eAAe;EAAE;EAAM;EAAO;CAAW,IAAI;EAAC;EAAM;EAAO;CAAU,CAAC;CAExF,MAAM,QAAQ,eACL;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EAAC;EAAU;EAAK;EAAW;EAAa;EAAgB;EAAiB;EAAW;CAAO,CAC7F;CAEA,OACE,oBAAC,cAAc,UAAf;EAA+B;EAC5B,UAAA,WAAW,oBAAC,QAAQ,MAAT,EAAe,SAAuB,CAAA,IAAI;CAChC,CAAA;AAE5B"}
@@ -1,7 +1,12 @@
1
1
  import { PopoverTriggerProps } from "@base-ui/react/popover";
2
2
  //#region src/components/trigger.d.ts
3
- type ChimelingTriggerProps = Pick<PopoverTriggerProps, 'className' | 'style' | 'nativeButton' | 'id'>;
4
- declare function ChimelingTrigger({ className, style, nativeButton, id }: ChimelingTriggerProps): import("react").JSX.Element | null;
3
+ type ChimelingTriggerProps = Pick<PopoverTriggerProps, 'style' | 'nativeButton' | 'id'> & {
4
+ className?: string;
5
+ variant?: 'inline' | 'pill';
6
+ shimmer?: boolean;
7
+ gradient?: boolean;
8
+ };
9
+ declare function ChimelingTrigger({ className, style, nativeButton, id, variant, shimmer, gradient }: ChimelingTriggerProps): import("react").JSX.Element | null;
5
10
  //#endregion
6
11
  export { ChimelingTrigger, ChimelingTriggerProps };
7
12
  //# sourceMappingURL=trigger.d.ts.map
@@ -1,23 +1,85 @@
1
1
  "use client";
2
2
  import { useWidgetContext } from "../lib/widget-context.js";
3
+ import { ClassNames, keyframes } from "@emotion/react";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  import { Popover } from "@base-ui/react/popover";
5
6
  //#region src/components/trigger.tsx
6
- function ChimelingTrigger({ className, style, nativeButton, id }) {
7
+ const shimmerAnimation = keyframes({
8
+ from: { backgroundPosition: "200% 0" },
9
+ to: { backgroundPosition: "-200% 0" }
10
+ });
11
+ const triggerReset = {
12
+ border: "none",
13
+ outline: "none",
14
+ margin: 0,
15
+ padding: 0,
16
+ backgroundColor: "unset",
17
+ fontWeight: 450
18
+ };
19
+ const DEFAULT_TRIGGER = {
20
+ variant: "inline",
21
+ shimmer: true,
22
+ gradient: true
23
+ };
24
+ function ChimelingTrigger({ className, style, nativeButton, id, variant = DEFAULT_TRIGGER.variant, shimmer = DEFAULT_TRIGGER.shimmer, gradient = DEFAULT_TRIGGER.gradient }) {
7
25
  const { showable, openOnHover, hoverOpenDelay, hoverCloseDelay } = useWidgetContext();
8
26
  if (!showable) return null;
9
- return /* @__PURE__ */ jsx(Popover.Trigger, {
10
- className,
27
+ return /* @__PURE__ */ jsx(ClassNames, { children: ({ css, cx }) => /* @__PURE__ */ jsx(Popover.Trigger, {
28
+ className: cx("chl-trigger", css({
29
+ ...triggerReset,
30
+ "&[data-variant=\"inline\"]": {
31
+ display: "inline",
32
+ fontSize: "inherit",
33
+ ...shimmer ? {
34
+ backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent) 0%, color-mix(in oklch, var(--chl-color-background-accent) 60%, #fff) 50%, var(--chl-color-background-accent) 100%)`,
35
+ backgroundSize: "200% 100%",
36
+ backgroundClip: "text",
37
+ WebkitBackgroundClip: "text",
38
+ color: "transparent",
39
+ animation: `${shimmerAnimation} 4s linear infinite`,
40
+ "@media (prefers-reduced-motion: reduce)": { animation: "none" },
41
+ "&:hover, &:focus-visible": { backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent-focus) 0%, color-mix(in oklch, var(--chl-color-background-accent-focus) 60%, #fff) 50%, var(--chl-color-background-accent-focus) 100%)` },
42
+ "&:active": { backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent-active) 0%, color-mix(in oklch, var(--chl-color-background-accent-active) 60%, #fff) 50%, var(--chl-color-background-accent-active) 100%)` }
43
+ } : {
44
+ color: "var(--chl-color-background-accent)",
45
+ "&:hover, &:focus-visible": { color: "var(--chl-color-background-accent-focus)" },
46
+ "&:active": { color: "var(--chl-color-background-accent-active)" }
47
+ }
48
+ },
49
+ "&[data-variant=\"pill\"]": {
50
+ display: "block",
51
+ padding: "var(--chl-spacing-2xs) var(--chl-spacing-xs)",
52
+ borderRadius: "var(--chl-border-radius-full)",
53
+ fontSize: "var(--chl-font-size-sm)",
54
+ color: "var(--chl-color-background-accent-contrast)",
55
+ backgroundImage: gradient ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent) 80%, #fff), var(--chl-color-background-accent))` : void 0,
56
+ backgroundColor: gradient ? void 0 : "var(--chl-color-background-accent)",
57
+ "&::first-letter": { textTransform: "uppercase" },
58
+ "&:hover, &:focus-visible": {
59
+ color: "var(--chl-color-background-accent-contrast-focus)",
60
+ backgroundImage: gradient ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent-focus) 80%, #fff), var(--chl-color-background-accent-focus))` : void 0,
61
+ backgroundColor: gradient ? void 0 : "var(--chl-color-background-accent-focus)"
62
+ },
63
+ "&:active": {
64
+ color: "var(--chl-color-background-accent-contrast-active)",
65
+ backgroundImage: gradient ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent-active) 80%, #fff), var(--chl-color-background-accent-active))` : void 0,
66
+ backgroundColor: gradient ? void 0 : "var(--chl-color-background-accent-active)"
67
+ }
68
+ }
69
+ }), className),
11
70
  style,
12
71
  nativeButton,
13
72
  id,
73
+ "data-variant": variant,
74
+ "data-shimmer": shimmer ? "true" : "false",
75
+ "data-gradient": gradient ? "true" : "false",
14
76
  openOnHover,
15
77
  delay: hoverOpenDelay,
16
78
  closeDelay: hoverCloseDelay,
17
79
  children: showable.activity.gerund
18
- });
80
+ }) });
19
81
  }
20
82
  //#endregion
21
- export { ChimelingTrigger };
83
+ export { ChimelingTrigger, DEFAULT_TRIGGER };
22
84
 
23
85
  //# sourceMappingURL=trigger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trigger.js","names":[],"sources":["../../src/components/trigger.tsx"],"sourcesContent":["'use client'\n\nimport { Popover } from '@base-ui/react/popover'\nimport type { PopoverTriggerProps } from '@base-ui/react/popover'\nimport { useWidgetContext } from '../lib/widget-context'\n\n// TODO: decide whether to expose the rest of Base UI Trigger props.\nexport type ChimelingTriggerProps = Pick<\n PopoverTriggerProps,\n 'className' | 'style' | 'nativeButton' | 'id'\n>\n\nexport function ChimelingTrigger({ className, style, nativeButton, id }: ChimelingTriggerProps) {\n const { showable, openOnHover, hoverOpenDelay, hoverCloseDelay } = useWidgetContext()\n\n if (!showable) {\n return null\n }\n\n return (\n <Popover.Trigger\n className={className}\n style={style}\n nativeButton={nativeButton}\n id={id}\n openOnHover={openOnHover}\n delay={hoverOpenDelay}\n closeDelay={hoverCloseDelay}\n >\n {showable.activity.gerund}\n </Popover.Trigger>\n )\n}\n"],"mappings":";;;;;AAYA,SAAgB,iBAAiB,EAAE,WAAW,OAAO,cAAc,MAA6B;CAC9F,MAAM,EAAE,UAAU,aAAa,gBAAgB,oBAAoB,iBAAiB;CAEpF,IAAI,CAAC,UACH,OAAO;CAGT,OACE,oBAAC,QAAQ,SAAT;EACa;EACJ;EACO;EACV;EACS;EACb,OAAO;EACP,YAAY;EAEX,UAAA,SAAS,SAAS;CACJ,CAAA;AAErB"}
1
+ {"version":3,"file":"trigger.js","names":[],"sources":["../../src/components/trigger.tsx"],"sourcesContent":["'use client'\n\nimport { ClassNames, keyframes } from '@emotion/react'\nimport { Popover } from '@base-ui/react/popover'\nimport type { PopoverTriggerProps } from '@base-ui/react/popover'\nimport { useWidgetContext } from '../lib/widget-context'\n\nconst shimmerAnimation = keyframes({\n from: { backgroundPosition: '200% 0' },\n to: { backgroundPosition: '-200% 0' },\n})\n\nconst triggerReset = {\n border: 'none',\n outline: 'none',\n margin: 0,\n padding: 0,\n backgroundColor: 'unset',\n fontWeight: 450,\n} as const\n\nexport type ChimelingTriggerProps = Pick<PopoverTriggerProps, 'style' | 'nativeButton' | 'id'> & {\n className?: string\n variant?: 'inline' | 'pill'\n shimmer?: boolean\n gradient?: boolean\n}\n\nexport const DEFAULT_TRIGGER = {\n variant: 'inline',\n shimmer: true,\n gradient: true,\n} as const\n\nexport function ChimelingTrigger({\n className,\n style,\n nativeButton,\n id,\n variant = DEFAULT_TRIGGER.variant,\n shimmer = DEFAULT_TRIGGER.shimmer,\n gradient = DEFAULT_TRIGGER.gradient,\n}: ChimelingTriggerProps) {\n const { showable, openOnHover, hoverOpenDelay, hoverCloseDelay } = useWidgetContext()\n\n if (!showable) {\n return null\n }\n\n return (\n <ClassNames>\n {({ css, cx }) => (\n <Popover.Trigger\n className={cx(\n 'chl-trigger',\n css({\n ...triggerReset,\n '&[data-variant=\"inline\"]': {\n display: 'inline',\n fontSize: 'inherit',\n ...(shimmer\n ? {\n backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent) 0%, color-mix(in oklch, var(--chl-color-background-accent) 60%, #fff) 50%, var(--chl-color-background-accent) 100%)`,\n backgroundSize: '200% 100%',\n backgroundClip: 'text',\n WebkitBackgroundClip: 'text',\n color: 'transparent',\n animation: `${shimmerAnimation} 4s linear infinite`,\n '@media (prefers-reduced-motion: reduce)': {\n animation: 'none',\n },\n '&:hover, &:focus-visible': {\n backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent-focus) 0%, color-mix(in oklch, var(--chl-color-background-accent-focus) 60%, #fff) 50%, var(--chl-color-background-accent-focus) 100%)`,\n },\n '&:active': {\n backgroundImage: `linear-gradient(to right, var(--chl-color-background-accent-active) 0%, color-mix(in oklch, var(--chl-color-background-accent-active) 60%, #fff) 50%, var(--chl-color-background-accent-active) 100%)`,\n },\n }\n : {\n color: 'var(--chl-color-background-accent)',\n '&:hover, &:focus-visible': {\n color: 'var(--chl-color-background-accent-focus)',\n },\n '&:active': {\n color: 'var(--chl-color-background-accent-active)',\n },\n }),\n },\n '&[data-variant=\"pill\"]': {\n display: 'block',\n padding: 'var(--chl-spacing-2xs) var(--chl-spacing-xs)',\n borderRadius: 'var(--chl-border-radius-full)',\n fontSize: 'var(--chl-font-size-sm)',\n color: 'var(--chl-color-background-accent-contrast)',\n backgroundImage: gradient\n ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent) 80%, #fff), var(--chl-color-background-accent))`\n : undefined,\n backgroundColor: gradient ? undefined : 'var(--chl-color-background-accent)',\n '&::first-letter': {\n textTransform: 'uppercase',\n },\n '&:hover, &:focus-visible': {\n color: 'var(--chl-color-background-accent-contrast-focus)',\n backgroundImage: gradient\n ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent-focus) 80%, #fff), var(--chl-color-background-accent-focus))`\n : undefined,\n backgroundColor: gradient\n ? undefined\n : 'var(--chl-color-background-accent-focus)',\n },\n '&:active': {\n color: 'var(--chl-color-background-accent-contrast-active)',\n backgroundImage: gradient\n ? `linear-gradient(to bottom, color-mix(in oklch, var(--chl-color-background-accent-active) 80%, #fff), var(--chl-color-background-accent-active))`\n : undefined,\n backgroundColor: gradient\n ? undefined\n : 'var(--chl-color-background-accent-active)',\n },\n },\n }),\n className,\n )}\n style={style}\n nativeButton={nativeButton}\n id={id}\n data-variant={variant}\n data-shimmer={shimmer ? 'true' : 'false'}\n data-gradient={gradient ? 'true' : 'false'}\n openOnHover={openOnHover}\n delay={hoverOpenDelay}\n closeDelay={hoverCloseDelay}\n >\n {showable.activity.gerund}\n </Popover.Trigger>\n )}\n </ClassNames>\n )\n}\n"],"mappings":";;;;;;AAOA,MAAM,mBAAmB,UAAU;CACjC,MAAM,EAAE,oBAAoB,SAAS;CACrC,IAAI,EAAE,oBAAoB,UAAU;AACtC,CAAC;AAED,MAAM,eAAe;CACnB,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,iBAAiB;CACjB,YAAY;AACd;AASA,MAAa,kBAAkB;CAC7B,SAAS;CACT,SAAS;CACT,UAAU;AACZ;AAEA,SAAgB,iBAAiB,EAC/B,WACA,OACA,cACA,IACA,UAAU,gBAAgB,SAC1B,UAAU,gBAAgB,SAC1B,WAAW,gBAAgB,YACH;CACxB,MAAM,EAAE,UAAU,aAAa,gBAAgB,oBAAoB,iBAAiB;CAEpF,IAAI,CAAC,UACH,OAAO;CAGT,OACE,oBAAC,YAAD,EAAA,WACI,EAAE,KAAK,SACP,oBAAC,QAAQ,SAAT;EACE,WAAW,GACT,eACA,IAAI;GACF,GAAG;GACH,8BAA4B;IAC1B,SAAS;IACT,UAAU;IACV,GAAI,UACA;KACE,iBAAiB;KACjB,gBAAgB;KAChB,gBAAgB;KAChB,sBAAsB;KACtB,OAAO;KACP,WAAW,GAAG,iBAAiB;KAC/B,2CAA2C,EACzC,WAAW,OACb;KACA,4BAA4B,EAC1B,iBAAiB,qMACnB;KACA,YAAY,EACV,iBAAiB,wMACnB;IACF,IACA;KACE,OAAO;KACP,4BAA4B,EAC1B,OAAO,2CACT;KACA,YAAY,EACV,OAAO,4CACT;IACF;GACN;GACA,4BAA0B;IACxB,SAAS;IACT,SAAS;IACT,cAAc;IACd,UAAU;IACV,OAAO;IACP,iBAAiB,WACb,sIACA,KAAA;IACJ,iBAAiB,WAAW,KAAA,IAAY;IACxC,mBAAmB,EACjB,eAAe,YACjB;IACA,4BAA4B;KAC1B,OAAO;KACP,iBAAiB,WACb,kJACA,KAAA;KACJ,iBAAiB,WACb,KAAA,IACA;IACN;IACA,YAAY;KACV,OAAO;KACP,iBAAiB,WACb,oJACA,KAAA;KACJ,iBAAiB,WACb,KAAA,IACA;IACN;GACF;EACF,CAAC,GACD,SACF;EACO;EACO;EACV;EACJ,gBAAc;EACd,gBAAc,UAAU,SAAS;EACjC,iBAAe,WAAW,SAAS;EACtB;EACb,OAAO;EACP,YAAY;EAEX,UAAA,SAAS,SAAS;CACJ,CAAA,EAET,CAAA;AAEhB"}
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { ChimelingRoot, ChimelingRootProps } from "./components/root.js";
4
4
  import { ChimelingTrigger, ChimelingTriggerProps } from "./components/trigger.js";
5
5
  import { ChimelingPopover, ChimelingPopoverProps } from "./components/popover.js";
6
6
  import { Chimeling } from "./components/chimeling.js";
7
- import { ChimelingPlayground } from "./components/playground/playground.js";
7
+ import { ChimelingPlayground, ChimelingPlaygroundProps } from "./components/playground/playground.js";
8
8
  import "./components/index.js";
9
9
  import { useChimelingClient } from "./hooks/use-client.js";
10
10
  import { useResolvedUserPresence } from "./hooks/use-resolved-user-presence.js";
@@ -12,4 +12,4 @@ import "./hooks/index.js";
12
12
  import { formatActivityDuration } from "./lib/format-activity-duration.js";
13
13
  import { iconImageUrl } from "./lib/icon-url.js";
14
14
  import "./lib/index.js";
15
- export { Chimeling, ChimelingPlayground, ChimelingPopover, type ChimelingPopoverProps, ChimelingProvider, type ChimelingProviderProps, ChimelingRoot, type ChimelingRootProps, ChimelingTrigger, type ChimelingTriggerProps, type PresenceActivity, type ShowablePresence, formatActivityDuration, getShowablePresence, iconImageUrl, useChimelingClient, useResolvedUserPresence };
15
+ export { Chimeling, ChimelingPlayground, type ChimelingPlaygroundProps, ChimelingPopover, type ChimelingPopoverProps, ChimelingProvider, type ChimelingProviderProps, ChimelingRoot, type ChimelingRootProps, ChimelingTrigger, type ChimelingTriggerProps, type PresenceActivity, type ShowablePresence, formatActivityDuration, getShowablePresence, iconImageUrl, useChimelingClient, useResolvedUserPresence };
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { useSyncExternalStore } from "react";
3
+ //#region src/lib/use-client-committed.ts
4
+ const subscribe = () => () => {};
5
+ const getSnapshot = () => true;
6
+ const getServerSnapshot = () => false;
7
+ /** False on the server and during hydration; true after the client commits. */
8
+ function useClientCommitted() {
9
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
10
+ }
11
+ //#endregion
12
+ export { useClientCommitted };
13
+
14
+ //# sourceMappingURL=use-client-committed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-client-committed.js","names":[],"sources":["../../src/lib/use-client-committed.ts"],"sourcesContent":["'use client'\n\nimport { useSyncExternalStore } from 'react'\n\nconst subscribe = () => () => {}\nconst getSnapshot = () => true\nconst getServerSnapshot = () => false\n\n/** False on the server and during hydration; true after the client commits. */\nexport function useClientCommitted() {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n"],"mappings":";;;AAIA,MAAM,wBAAwB,CAAC;AAC/B,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;;AAGhC,SAAgB,qBAAqB;CACnC,OAAO,qBAAqB,WAAW,aAAa,iBAAiB;AACvE"}
@@ -1,7 +1,9 @@
1
1
  import "./showable-presence.js";
2
2
  import { PopoverPositionerProps } from "@base-ui/react/popover";
3
3
  //#region src/lib/widget-context.d.ts
4
- type WidgetPlacement = Pick<PopoverPositionerProps, 'side' | 'align' | 'sideOffset'>;
4
+ type WidgetPlacement = Pick<PopoverPositionerProps, 'side' | 'align'> & {
5
+ sideOffset?: number;
6
+ };
5
7
  //#endregion
6
8
  export { WidgetPlacement };
7
9
  //# sourceMappingURL=widget-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"widget-context.js","names":[],"sources":["../../src/lib/widget-context.ts"],"sourcesContent":["'use client'\n\nimport { createContext, useContext } from 'react'\nimport type { PopoverPositionerProps } from '@base-ui/react/popover'\nimport { packageErrorMessage } from './config'\nimport type { ShowablePresence } from './showable-presence'\n\nexport type WidgetPlacement = Pick<PopoverPositionerProps, 'side' | 'align' | 'sideOffset'>\n\nexport type WidgetContextValue = {\n showable: ShowablePresence | null\n now: Date\n poweredBy: boolean\n openOnHover: boolean\n hoverOpenDelay: number\n hoverCloseDelay: number\n placement: WidgetPlacement\n baseUrl: string\n}\n\nexport const WidgetContext = createContext<WidgetContextValue | null>(null)\n\nexport function useWidgetContext(): WidgetContextValue {\n const context = useContext(WidgetContext)\n if (!context) {\n throw new Error(\n packageErrorMessage(\n 'This component can only be used within the <Chimeling.Root /> component.',\n ),\n )\n }\n return context\n}\n"],"mappings":";;;;AAoBA,MAAa,gBAAgB,cAAyC,IAAI;AAE1E,SAAgB,mBAAuC;CACrD,MAAM,UAAU,WAAW,aAAa;CACxC,IAAI,CAAC,SACH,MAAM,IAAI,MACR,oBACE,0EACF,CACF;CAEF,OAAO;AACT"}
1
+ {"version":3,"file":"widget-context.js","names":[],"sources":["../../src/lib/widget-context.ts"],"sourcesContent":["'use client'\n\nimport { createContext, useContext } from 'react'\nimport type { PopoverPositionerProps } from '@base-ui/react/popover'\nimport { packageErrorMessage } from './config'\nimport type { ShowablePresence } from './showable-presence'\n\nexport type WidgetPlacement = Pick<PopoverPositionerProps, 'side' | 'align'> & {\n sideOffset?: number\n}\n\nexport type WidgetContextValue = {\n showable: ShowablePresence | null\n now: Date\n poweredBy: boolean\n openOnHover: boolean\n hoverOpenDelay: number\n hoverCloseDelay: number\n placement: WidgetPlacement\n baseUrl: string\n}\n\nexport const WidgetContext = createContext<WidgetContextValue | null>(null)\n\nexport function useWidgetContext(): WidgetContextValue {\n const context = useContext(WidgetContext)\n if (!context) {\n throw new Error(\n packageErrorMessage(\n 'This component can only be used within the <Chimeling.Root /> component.',\n ),\n )\n }\n return context\n}\n"],"mappings":";;;;AAsBA,MAAa,gBAAgB,cAAyC,IAAI;AAE1E,SAAgB,mBAAuC;CACrD,MAAM,UAAU,WAAW,aAAa;CACxC,IAAI,CAAC,SACH,MAAM,IAAI,MACR,oBACE,0EACF,CACF;CAEF,OAAO;AACT"}
@@ -0,0 +1 @@
1
+ import "@emotion/react";