@mindlogic-ai/logician-ui 3.1.0-alpha.8 → 3.1.0-alpha.9

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.
@@ -1,3 +1,3 @@
1
1
  import { InfoSprinkleProps } from './InfoSprinkle.types';
2
- export declare const InfoSprinkle: ({ children, iconButtonProps, contentProps, baseFontSize, ...rest }: InfoSprinkleProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const InfoSprinkle: ({ children, iconButtonProps, contentProps, baseFontSize, open: openProp, defaultOpen, onOpenChange, ...rest }: InfoSprinkleProps) => import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=InfoSprinkle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InfoSprinkle.d.ts","sourceRoot":"","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,eAAO,MAAM,YAAY,GAAI,oEAM1B,iBAAiB,4CAmCnB,CAAC"}
1
+ {"version":3,"file":"InfoSprinkle.d.ts","sourceRoot":"","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,eAAO,MAAM,YAAY,GAAI,+GAS1B,iBAAiB,4CA4DnB,CAAC"}
@@ -2,14 +2,37 @@
2
2
  'use strict';
3
3
 
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var React = require('react');
5
6
  var react = require('@chakra-ui/react');
7
+ var useHasHover = require('../../hooks/useHasHover.js');
6
8
  var index = require('../Icon/index.js');
7
9
  var IconButton = require('../IconButton/IconButton.js');
8
10
  require('../IconButton/IconButton.styles.js');
9
11
  var ScaledContext = require('../ScaledContext/ScaledContext.js');
10
12
 
11
- const InfoSprinkle = ({ children, iconButtonProps, contentProps, baseFontSize = '14px', ...rest }) => {
12
- return (jsxRuntime.jsxs(react.HoverCard.Root, { positioning: { placement: 'top' }, openDelay: 0, closeDelay: 0, lazyMount: true, ...rest, children: [jsxRuntime.jsx(react.HoverCard.Trigger, { asChild: true, children: jsxRuntime.jsx(IconButton.IconButton, { "aria-label": "Info", opacity: 0.5, transition: "opacity 0.2s", _hover: { opacity: 1, ...iconButtonProps?._hover }, ...iconButtonProps, children: jsxRuntime.jsx(index.LuInfo, { color: iconButtonProps?.color ?? 'fg.muted', boxSize: iconButtonProps?.size ?? 'xs' }) }) }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.HoverCard.Positioner, { children: jsxRuntime.jsxs(react.HoverCard.Content, { p: 2, ...contentProps, children: [jsxRuntime.jsx(react.HoverCard.Arrow, { children: jsxRuntime.jsx(react.HoverCard.ArrowTip, {}) }), jsxRuntime.jsx(ScaledContext.ScaledContext, { fontSize: baseFontSize, children: children })] }) }) })] }));
13
+ const InfoSprinkle = ({ children, iconButtonProps, contentProps, baseFontSize = '14px', open: openProp, defaultOpen, onOpenChange, ...rest }) => {
14
+ // HoverCard (zag-js) opens on mouse hover and on focus, but its pointer
15
+ // handlers ignore `pointerType: 'touch'`. Browsers that focus the trigger on
16
+ // tap (e.g. Android Chrome) therefore open it for free, but those that don't
17
+ // focus buttons on tap (e.g. iOS Safari) never open it. To cover both, on
18
+ // non-hover devices we open the card on tap. Closing stays with the machine's
19
+ // own dismissal (tap-outside / blur), and opening is idempotent with the
20
+ // focus-open path so it doesn't fight devices that already open on tap.
21
+ const hasHover = useHasHover.useHasHover();
22
+ const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
23
+ const isControlled = openProp !== undefined;
24
+ const open = isControlled ? openProp : internalOpen;
25
+ const setOpen = (next) => {
26
+ if (!isControlled)
27
+ setInternalOpen(next);
28
+ onOpenChange?.({ open: next });
29
+ };
30
+ return (jsxRuntime.jsxs(react.HoverCard.Root, { positioning: { placement: 'top' }, openDelay: 0, closeDelay: 0, lazyMount: true, open: open, onOpenChange: (e) => setOpen(e.open), ...rest, children: [jsxRuntime.jsx(react.HoverCard.Trigger, { asChild: true, children: jsxRuntime.jsx(IconButton.IconButton, { "aria-label": "Info", opacity: 0.5, transition: "opacity 0.2s", _hover: { opacity: 1, ...iconButtonProps?._hover }, ...iconButtonProps, onClick: (e) => {
31
+ // On non-hover (touch) devices, tapping opens the card.
32
+ if (!hasHover)
33
+ setOpen(true);
34
+ iconButtonProps?.onClick?.(e);
35
+ }, children: jsxRuntime.jsx(index.LuInfo, { color: iconButtonProps?.color ?? 'fg.muted', boxSize: iconButtonProps?.size ?? 'xs' }) }) }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.HoverCard.Positioner, { children: jsxRuntime.jsxs(react.HoverCard.Content, { p: 2, ...contentProps, children: [jsxRuntime.jsx(react.HoverCard.Arrow, { children: jsxRuntime.jsx(react.HoverCard.ArrowTip, {}) }), jsxRuntime.jsx(ScaledContext.ScaledContext, { fontSize: baseFontSize, children: children })] }) }) })] }));
13
36
  };
14
37
 
15
38
  exports.InfoSprinkle = InfoSprinkle;
@@ -1 +1 @@
1
- {"version":3,"file":"InfoSprinkle.js","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"sourcesContent":[null],"names":["_jsxs","HoverCard","_jsx","IconButton","LuInfo","Portal","ScaledContext"],"mappings":";;;;;;;;;;MAOa,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,YAAY,GAAG,MAAM,EACrB,GAAG,IAAI,EACW,KAAI;AACtB,IAAA,QACEA,eAAA,CAACC,eAAS,CAAC,IAAI,EAAA,EACb,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EACjC,SAAS,EAAE,CAAC,EACZ,UAAU,EAAE,CAAC,EACb,SAAS,EAAA,IAAA,EAAA,GACL,IAAI,EAAA,QAAA,EAAA,CAERC,cAAA,CAACD,eAAS,CAAC,OAAO,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EACxBC,cAAA,CAACC,qBAAU,EAAA,EAAA,YAAA,EACE,MAAM,EACjB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAC,cAAc,EACzB,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAI,eAAe,EAAE,MAAc,EAAE,EAAA,GACvD,eAAe,EAAA,QAAA,EAEnBD,eAACE,YAAM,EAAA,EACL,KAAK,EAAG,eAAe,EAAE,KAAgB,IAAI,UAAU,EACvD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,IAAI,EAAA,CACtC,EAAA,CACS,EAAA,CACK,EACpBF,cAAA,CAACG,YAAM,EAAA,EAAA,QAAA,EACLH,cAAA,CAACD,eAAS,CAAC,UAAU,EAAA,EAAA,QAAA,EACnBD,eAAA,CAACC,eAAS,CAAC,OAAO,EAAA,EAAC,CAAC,EAAE,CAAC,EAAA,GAAM,YAAY,EAAA,QAAA,EAAA,CACvCC,cAAA,CAACD,eAAS,CAAC,KAAK,EAAA,EAAA,QAAA,EACdC,cAAA,CAACD,eAAS,CAAC,QAAQ,EAAA,EAAA,CAAG,EAAA,CACN,EAClBC,cAAA,CAACI,2BAAa,EAAA,EAAC,QAAQ,EAAE,YAAY,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAiB,CAAA,EAAA,CAC/C,EAAA,CACC,EAAA,CAChB,CAAA,EAAA,CACM;AAErB;;;;"}
1
+ {"version":3,"file":"InfoSprinkle.js","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"sourcesContent":[null],"names":["useHasHover","useState","_jsxs","HoverCard","_jsx","IconButton","LuInfo","Portal","ScaledContext"],"mappings":";;;;;;;;;;;;AAWO,MAAM,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,YAAY,GAAG,MAAM,EACrB,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,YAAY,EACZ,GAAG,IAAI,EACW,KAAI;;;;;;;;AAQtB,IAAA,MAAM,QAAQ,GAAGA,uBAAW,EAAE;AAC9B,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAGC,cAAQ,CAAC,WAAW,IAAI,KAAK,CAAC;AAEtE,IAAA,MAAM,YAAY,GAAG,QAAQ,KAAK,SAAS;IAC3C,MAAM,IAAI,GAAG,YAAY,GAAG,QAAQ,GAAG,YAAY;AAEnD,IAAA,MAAM,OAAO,GAAG,CAAC,IAAa,KAAI;AAChC,QAAA,IAAI,CAAC,YAAY;YAAE,eAAe,CAAC,IAAI,CAAC;QACxC,YAAY,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAChC,IAAA,CAAC;AAED,IAAA,QACEC,eAAA,CAACC,eAAS,CAAC,IAAI,EAAA,EACb,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EACjC,SAAS,EAAE,CAAC,EACZ,UAAU,EAAE,CAAC,EACb,SAAS,EAAA,IAAA,EACT,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAA,GAChC,IAAI,EAAA,QAAA,EAAA,CAERC,eAACD,eAAS,CAAC,OAAO,EAAA,EAAC,OAAO,kBACxBC,cAAA,CAACC,qBAAU,EAAA,EAAA,YAAA,EACE,MAAM,EACjB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAC,cAAc,EACzB,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAI,eAAe,EAAE,MAAc,EAAE,EAAA,GACvD,eAAe,EACnB,OAAO,EAAE,CAAC,CAAC,KAAI;;AAEb,wBAAA,IAAI,CAAC,QAAQ;4BAAE,OAAO,CAAC,IAAI,CAAC;AAC5B,wBAAA,eAAe,EAAE,OAAO,GAAG,CAAC,CAAC;AAC/B,oBAAA,CAAC,EAAA,QAAA,EAEDD,cAAA,CAACE,YAAM,EAAA,EACL,KAAK,EAAG,eAAe,EAAE,KAAgB,IAAI,UAAU,EACvD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,IAAI,EAAA,CACtC,EAAA,CACS,EAAA,CACK,EACpBF,cAAA,CAACG,YAAM,EAAA,EAAA,QAAA,EACLH,cAAA,CAACD,eAAS,CAAC,UAAU,EAAA,EAAA,QAAA,EACnBD,gBAACC,eAAS,CAAC,OAAO,EAAA,EAAC,CAAC,EAAE,CAAC,EAAA,GAAM,YAAY,EAAA,QAAA,EAAA,CACvCC,cAAA,CAACD,eAAS,CAAC,KAAK,EAAA,EAAA,QAAA,EACdC,cAAA,CAACD,eAAS,CAAC,QAAQ,EAAA,EAAA,CAAG,EAAA,CACN,EAClBC,cAAA,CAACI,2BAAa,EAAA,EAAC,QAAQ,EAAE,YAAY,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAiB,CAAA,EAAA,CAC/C,EAAA,CACC,EAAA,CAChB,CAAA,EAAA,CACM;AAErB;;;;"}
@@ -1,13 +1,36 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { useState } from 'react';
3
4
  import { HoverCard, Portal } from '@chakra-ui/react';
5
+ import { useHasHover } from '../../hooks/useHasHover.mjs';
4
6
  import { LuInfo } from '../Icon/index.mjs';
5
7
  import { IconButton } from '../IconButton/IconButton.mjs';
6
8
  import '../IconButton/IconButton.styles.mjs';
7
9
  import { ScaledContext } from '../ScaledContext/ScaledContext.mjs';
8
10
 
9
- const InfoSprinkle = ({ children, iconButtonProps, contentProps, baseFontSize = '14px', ...rest }) => {
10
- return (jsxs(HoverCard.Root, { positioning: { placement: 'top' }, openDelay: 0, closeDelay: 0, lazyMount: true, ...rest, children: [jsx(HoverCard.Trigger, { asChild: true, children: jsx(IconButton, { "aria-label": "Info", opacity: 0.5, transition: "opacity 0.2s", _hover: { opacity: 1, ...iconButtonProps?._hover }, ...iconButtonProps, children: jsx(LuInfo, { color: iconButtonProps?.color ?? 'fg.muted', boxSize: iconButtonProps?.size ?? 'xs' }) }) }), jsx(Portal, { children: jsx(HoverCard.Positioner, { children: jsxs(HoverCard.Content, { p: 2, ...contentProps, children: [jsx(HoverCard.Arrow, { children: jsx(HoverCard.ArrowTip, {}) }), jsx(ScaledContext, { fontSize: baseFontSize, children: children })] }) }) })] }));
11
+ const InfoSprinkle = ({ children, iconButtonProps, contentProps, baseFontSize = '14px', open: openProp, defaultOpen, onOpenChange, ...rest }) => {
12
+ // HoverCard (zag-js) opens on mouse hover and on focus, but its pointer
13
+ // handlers ignore `pointerType: 'touch'`. Browsers that focus the trigger on
14
+ // tap (e.g. Android Chrome) therefore open it for free, but those that don't
15
+ // focus buttons on tap (e.g. iOS Safari) never open it. To cover both, on
16
+ // non-hover devices we open the card on tap. Closing stays with the machine's
17
+ // own dismissal (tap-outside / blur), and opening is idempotent with the
18
+ // focus-open path so it doesn't fight devices that already open on tap.
19
+ const hasHover = useHasHover();
20
+ const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);
21
+ const isControlled = openProp !== undefined;
22
+ const open = isControlled ? openProp : internalOpen;
23
+ const setOpen = (next) => {
24
+ if (!isControlled)
25
+ setInternalOpen(next);
26
+ onOpenChange?.({ open: next });
27
+ };
28
+ return (jsxs(HoverCard.Root, { positioning: { placement: 'top' }, openDelay: 0, closeDelay: 0, lazyMount: true, open: open, onOpenChange: (e) => setOpen(e.open), ...rest, children: [jsx(HoverCard.Trigger, { asChild: true, children: jsx(IconButton, { "aria-label": "Info", opacity: 0.5, transition: "opacity 0.2s", _hover: { opacity: 1, ...iconButtonProps?._hover }, ...iconButtonProps, onClick: (e) => {
29
+ // On non-hover (touch) devices, tapping opens the card.
30
+ if (!hasHover)
31
+ setOpen(true);
32
+ iconButtonProps?.onClick?.(e);
33
+ }, children: jsx(LuInfo, { color: iconButtonProps?.color ?? 'fg.muted', boxSize: iconButtonProps?.size ?? 'xs' }) }) }), jsx(Portal, { children: jsx(HoverCard.Positioner, { children: jsxs(HoverCard.Content, { p: 2, ...contentProps, children: [jsx(HoverCard.Arrow, { children: jsx(HoverCard.ArrowTip, {}) }), jsx(ScaledContext, { fontSize: baseFontSize, children: children })] }) }) })] }));
11
34
  };
12
35
 
13
36
  export { InfoSprinkle };
@@ -1 +1 @@
1
- {"version":3,"file":"InfoSprinkle.mjs","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;MAOa,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,YAAY,GAAG,MAAM,EACrB,GAAG,IAAI,EACW,KAAI;AACtB,IAAA,QACEA,IAAA,CAAC,SAAS,CAAC,IAAI,EAAA,EACb,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EACjC,SAAS,EAAE,CAAC,EACZ,UAAU,EAAE,CAAC,EACb,SAAS,EAAA,IAAA,EAAA,GACL,IAAI,EAAA,QAAA,EAAA,CAERC,GAAA,CAAC,SAAS,CAAC,OAAO,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EACxBA,GAAA,CAAC,UAAU,EAAA,EAAA,YAAA,EACE,MAAM,EACjB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAC,cAAc,EACzB,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAI,eAAe,EAAE,MAAc,EAAE,EAAA,GACvD,eAAe,EAAA,QAAA,EAEnBA,IAAC,MAAM,EAAA,EACL,KAAK,EAAG,eAAe,EAAE,KAAgB,IAAI,UAAU,EACvD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,IAAI,EAAA,CACtC,EAAA,CACS,EAAA,CACK,EACpBA,GAAA,CAAC,MAAM,EAAA,EAAA,QAAA,EACLA,GAAA,CAAC,SAAS,CAAC,UAAU,EAAA,EAAA,QAAA,EACnBD,IAAA,CAAC,SAAS,CAAC,OAAO,EAAA,EAAC,CAAC,EAAE,CAAC,EAAA,GAAM,YAAY,EAAA,QAAA,EAAA,CACvCC,GAAA,CAAC,SAAS,CAAC,KAAK,EAAA,EAAA,QAAA,EACdA,GAAA,CAAC,SAAS,CAAC,QAAQ,EAAA,EAAA,CAAG,EAAA,CACN,EAClBA,GAAA,CAAC,aAAa,EAAA,EAAC,QAAQ,EAAE,YAAY,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAiB,CAAA,EAAA,CAC/C,EAAA,CACC,EAAA,CAChB,CAAA,EAAA,CACM;AAErB;;;;"}
1
+ {"version":3,"file":"InfoSprinkle.mjs","sources":["../../../src/components/InfoSprinkle/InfoSprinkle.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;AAWO,MAAM,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,YAAY,GAAG,MAAM,EACrB,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,YAAY,EACZ,GAAG,IAAI,EACW,KAAI;;;;;;;;AAQtB,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE;AAC9B,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,KAAK,CAAC;AAEtE,IAAA,MAAM,YAAY,GAAG,QAAQ,KAAK,SAAS;IAC3C,MAAM,IAAI,GAAG,YAAY,GAAG,QAAQ,GAAG,YAAY;AAEnD,IAAA,MAAM,OAAO,GAAG,CAAC,IAAa,KAAI;AAChC,QAAA,IAAI,CAAC,YAAY;YAAE,eAAe,CAAC,IAAI,CAAC;QACxC,YAAY,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAChC,IAAA,CAAC;AAED,IAAA,QACEA,IAAA,CAAC,SAAS,CAAC,IAAI,EAAA,EACb,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EACjC,SAAS,EAAE,CAAC,EACZ,UAAU,EAAE,CAAC,EACb,SAAS,EAAA,IAAA,EACT,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAA,GAChC,IAAI,EAAA,QAAA,EAAA,CAERC,IAAC,SAAS,CAAC,OAAO,EAAA,EAAC,OAAO,kBACxBA,GAAA,CAAC,UAAU,EAAA,EAAA,YAAA,EACE,MAAM,EACjB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAC,cAAc,EACzB,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAI,eAAe,EAAE,MAAc,EAAE,EAAA,GACvD,eAAe,EACnB,OAAO,EAAE,CAAC,CAAC,KAAI;;AAEb,wBAAA,IAAI,CAAC,QAAQ;4BAAE,OAAO,CAAC,IAAI,CAAC;AAC5B,wBAAA,eAAe,EAAE,OAAO,GAAG,CAAC,CAAC;AAC/B,oBAAA,CAAC,EAAA,QAAA,EAEDA,GAAA,CAAC,MAAM,EAAA,EACL,KAAK,EAAG,eAAe,EAAE,KAAgB,IAAI,UAAU,EACvD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,IAAI,EAAA,CACtC,EAAA,CACS,EAAA,CACK,EACpBA,GAAA,CAAC,MAAM,EAAA,EAAA,QAAA,EACLA,GAAA,CAAC,SAAS,CAAC,UAAU,EAAA,EAAA,QAAA,EACnBD,KAAC,SAAS,CAAC,OAAO,EAAA,EAAC,CAAC,EAAE,CAAC,EAAA,GAAM,YAAY,EAAA,QAAA,EAAA,CACvCC,GAAA,CAAC,SAAS,CAAC,KAAK,EAAA,EAAA,QAAA,EACdA,GAAA,CAAC,SAAS,CAAC,QAAQ,EAAA,EAAA,CAAG,EAAA,CACN,EAClBA,GAAA,CAAC,aAAa,EAAA,EAAC,QAAQ,EAAE,YAAY,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAiB,CAAA,EAAA,CAC/C,EAAA,CACC,EAAA,CAChB,CAAA,EAAA,CACM;AAErB;;;;"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns whether the primary pointing device is capable of hovering
3
+ * (i.e. a mouse/trackpad rather than a touchscreen).
4
+ *
5
+ * Useful for components that rely on hover interactions on desktop but need a
6
+ * tap/click affordance on touch devices, where hover events never fire.
7
+ *
8
+ * Defaults to `true` so server-rendered markup matches the most common
9
+ * (desktop) case, then resolves to the real value after mount.
10
+ */
11
+ export declare const useHasHover: () => boolean;
12
+ export default useHasHover;
13
+ //# sourceMappingURL=useHasHover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasHover.d.ts","sourceRoot":"","sources":["../../src/hooks/useHasHover.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,eAevB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var React = require('react');
7
+
8
+ /**
9
+ * Returns whether the primary pointing device is capable of hovering
10
+ * (i.e. a mouse/trackpad rather than a touchscreen).
11
+ *
12
+ * Useful for components that rely on hover interactions on desktop but need a
13
+ * tap/click affordance on touch devices, where hover events never fire.
14
+ *
15
+ * Defaults to `true` so server-rendered markup matches the most common
16
+ * (desktop) case, then resolves to the real value after mount.
17
+ */
18
+ const useHasHover = () => {
19
+ const [hasHover, setHasHover] = React.useState(true);
20
+ React.useEffect(() => {
21
+ if (typeof window === 'undefined' || !window.matchMedia)
22
+ return;
23
+ const mql = window.matchMedia('(hover: hover)');
24
+ const update = () => setHasHover(mql.matches);
25
+ update();
26
+ mql.addEventListener('change', update);
27
+ return () => mql.removeEventListener('change', update);
28
+ }, []);
29
+ return hasHover;
30
+ };
31
+
32
+ exports.default = useHasHover;
33
+ exports.useHasHover = useHasHover;
34
+ //# sourceMappingURL=useHasHover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasHover.js","sources":["../../src/hooks/useHasHover.ts"],"sourcesContent":[null],"names":["useState","useEffect"],"mappings":";;;;;;;AAIA;;;;;;;;;AASG;AACI,MAAM,WAAW,GAAG,MAAK;IAC9B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAGA,cAAQ,CAAC,IAAI,CAAC;IAE9CC,eAAS,CAAC,MAAK;QACb,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE;QAEzD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC;AAE7C,QAAA,MAAM,EAAE;AACR,QAAA,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;QACtC,OAAO,MAAM,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACxD,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,OAAO,QAAQ;AACjB;;;;;"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { useState, useEffect } from 'react';
3
+
4
+ /**
5
+ * Returns whether the primary pointing device is capable of hovering
6
+ * (i.e. a mouse/trackpad rather than a touchscreen).
7
+ *
8
+ * Useful for components that rely on hover interactions on desktop but need a
9
+ * tap/click affordance on touch devices, where hover events never fire.
10
+ *
11
+ * Defaults to `true` so server-rendered markup matches the most common
12
+ * (desktop) case, then resolves to the real value after mount.
13
+ */
14
+ const useHasHover = () => {
15
+ const [hasHover, setHasHover] = useState(true);
16
+ useEffect(() => {
17
+ if (typeof window === 'undefined' || !window.matchMedia)
18
+ return;
19
+ const mql = window.matchMedia('(hover: hover)');
20
+ const update = () => setHasHover(mql.matches);
21
+ update();
22
+ mql.addEventListener('change', update);
23
+ return () => mql.removeEventListener('change', update);
24
+ }, []);
25
+ return hasHover;
26
+ };
27
+
28
+ export { useHasHover as default, useHasHover };
29
+ //# sourceMappingURL=useHasHover.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasHover.mjs","sources":["../../src/hooks/useHasHover.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAIA;;;;;;;;;AASG;AACI,MAAM,WAAW,GAAG,MAAK;IAC9B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;IAE9C,SAAS,CAAC,MAAK;QACb,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE;QAEzD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC;AAE7C,QAAA,MAAM,EAAE;AACR,QAAA,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;QACtC,OAAO,MAAM,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACxD,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,OAAO,QAAQ;AACjB;;;;"}
package/dist/index.d.ts CHANGED
@@ -61,6 +61,7 @@ export * from './components/Textarea';
61
61
  export * from './components/Toast';
62
62
  export * from './components/Tooltip';
63
63
  export { H1, H2, H3, H4, H5, Link, Subtext, Subtitle, Text, } from './components/Typography';
64
+ export { useHasHover } from './hooks/useHasHover';
64
65
  export type { LanguageContextValue } from './hooks/useLanguage';
65
66
  export { LanguageContext, useLanguage } from './hooks/useLanguage';
66
67
  export { logicianConfig, system, theme } from './theme';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AAGvC,YAAY,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,YAAY,EACV,WAAW,EACX,SAAS,IAAI,eAAe,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAG3E,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AAErC,OAAO,EACL,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,IAAI,GACL,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AAGvC,YAAY,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,YAAY,EACV,WAAW,EACX,SAAS,IAAI,eAAe,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAG3E,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AAErC,OAAO,EACL,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,IAAI,GACL,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -127,6 +127,7 @@ var Link = require('./components/Typography/Link.js');
127
127
  var Subtext = require('./components/Typography/Subtext.js');
128
128
  var Subtitle = require('./components/Typography/Subtitle.js');
129
129
  var Text = require('./components/Typography/Text.js');
130
+ var useHasHover = require('./hooks/useHasHover.js');
130
131
  var useLanguage = require('./hooks/useLanguage.js');
131
132
  var index = require('./theme/index.js');
132
133
 
@@ -299,6 +300,7 @@ exports.Link = Link.Link;
299
300
  exports.Subtext = Subtext.Subtext;
300
301
  exports.Subtitle = Subtitle.Subtitle;
301
302
  exports.Text = Text.Text;
303
+ exports.useHasHover = useHasHover.useHasHover;
302
304
  exports.LanguageContext = useLanguage.LanguageContext;
303
305
  exports.useLanguage = useLanguage.useLanguage;
304
306
  exports.logicianConfig = index.logicianConfig;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -125,6 +125,7 @@ export { Link } from './components/Typography/Link.mjs';
125
125
  export { Subtext } from './components/Typography/Subtext.mjs';
126
126
  export { Subtitle } from './components/Typography/Subtitle.mjs';
127
127
  export { Text } from './components/Typography/Text.mjs';
128
+ export { useHasHover } from './hooks/useHasHover.mjs';
128
129
  export { LanguageContext, useLanguage } from './hooks/useLanguage.mjs';
129
130
  export { logicianConfig, system, theme } from './theme/index.mjs';
130
131
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindlogic-ai/logician-ui",
3
- "version": "3.1.0-alpha.8",
3
+ "version": "3.1.0-alpha.9",
4
4
  "description": "A comprehensive React design system built on Chakra UI",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,5 +1,9 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
1
4
  import { HoverCard, Portal } from '@chakra-ui/react';
2
5
 
6
+ import { useHasHover } from '../../hooks/useHasHover';
3
7
  import { LuInfo } from '../Icon';
4
8
  import { IconButton } from '../IconButton';
5
9
  import { ScaledContext } from '../ScaledContext';
@@ -10,14 +14,37 @@ export const InfoSprinkle = ({
10
14
  iconButtonProps,
11
15
  contentProps,
12
16
  baseFontSize = '14px',
17
+ open: openProp,
18
+ defaultOpen,
19
+ onOpenChange,
13
20
  ...rest
14
21
  }: InfoSprinkleProps) => {
22
+ // HoverCard (zag-js) opens on mouse hover and on focus, but its pointer
23
+ // handlers ignore `pointerType: 'touch'`. Browsers that focus the trigger on
24
+ // tap (e.g. Android Chrome) therefore open it for free, but those that don't
25
+ // focus buttons on tap (e.g. iOS Safari) never open it. To cover both, on
26
+ // non-hover devices we open the card on tap. Closing stays with the machine's
27
+ // own dismissal (tap-outside / blur), and opening is idempotent with the
28
+ // focus-open path so it doesn't fight devices that already open on tap.
29
+ const hasHover = useHasHover();
30
+ const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);
31
+
32
+ const isControlled = openProp !== undefined;
33
+ const open = isControlled ? openProp : internalOpen;
34
+
35
+ const setOpen = (next: boolean) => {
36
+ if (!isControlled) setInternalOpen(next);
37
+ onOpenChange?.({ open: next });
38
+ };
39
+
15
40
  return (
16
41
  <HoverCard.Root
17
42
  positioning={{ placement: 'top' }}
18
43
  openDelay={0}
19
44
  closeDelay={0}
20
45
  lazyMount
46
+ open={open}
47
+ onOpenChange={(e) => setOpen(e.open)}
21
48
  {...rest}
22
49
  >
23
50
  <HoverCard.Trigger asChild>
@@ -27,6 +54,11 @@ export const InfoSprinkle = ({
27
54
  transition="opacity 0.2s"
28
55
  _hover={{ opacity: 1, ...(iconButtonProps?._hover as any) }}
29
56
  {...iconButtonProps}
57
+ onClick={(e) => {
58
+ // On non-hover (touch) devices, tapping opens the card.
59
+ if (!hasHover) setOpen(true);
60
+ iconButtonProps?.onClick?.(e);
61
+ }}
30
62
  >
31
63
  <LuInfo
32
64
  color={(iconButtonProps?.color as string) ?? 'fg.muted'}
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+
5
+ /**
6
+ * Returns whether the primary pointing device is capable of hovering
7
+ * (i.e. a mouse/trackpad rather than a touchscreen).
8
+ *
9
+ * Useful for components that rely on hover interactions on desktop but need a
10
+ * tap/click affordance on touch devices, where hover events never fire.
11
+ *
12
+ * Defaults to `true` so server-rendered markup matches the most common
13
+ * (desktop) case, then resolves to the real value after mount.
14
+ */
15
+ export const useHasHover = () => {
16
+ const [hasHover, setHasHover] = useState(true);
17
+
18
+ useEffect(() => {
19
+ if (typeof window === 'undefined' || !window.matchMedia) return;
20
+
21
+ const mql = window.matchMedia('(hover: hover)');
22
+ const update = () => setHasHover(mql.matches);
23
+
24
+ update();
25
+ mql.addEventListener('change', update);
26
+ return () => mql.removeEventListener('change', update);
27
+ }, []);
28
+
29
+ return hasHover;
30
+ };
31
+
32
+ export default useHasHover;
package/src/index.ts CHANGED
@@ -102,6 +102,7 @@ export {
102
102
  } from './components/Typography';
103
103
 
104
104
  // Hooks
105
+ export { useHasHover } from './hooks/useHasHover';
105
106
  export type { LanguageContextValue } from './hooks/useLanguage';
106
107
  export { LanguageContext, useLanguage } from './hooks/useLanguage';
107
108