@mitcsutt/kiln-ui 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/actions/Button/Button.module.js.map +1 -1
- package/dist/components/actions/ToggleChip/ToggleChip.d.ts +5 -0
- package/dist/components/actions/ToggleChip/ToggleChip.js +10 -6
- package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
- package/dist/components/actions/ToggleChip/chip.module.js +4 -3
- package/dist/components/actions/ToggleChip/chip.module.js.map +1 -1
- package/dist/components/display/AvatarGroup/AvatarGroup.d.ts +2 -2
- package/dist/components/display/AvatarGroup/AvatarGroup.js +1 -1
- package/dist/components/display/AvatarGroup/AvatarGroup.js.map +1 -1
- package/dist/components/display/Card/Card.d.ts +7 -4
- package/dist/components/display/Card/Card.js +8 -7
- package/dist/components/display/Card/Card.js.map +1 -1
- package/dist/components/display/Card/Card.module.js.map +1 -1
- package/dist/components/display/List/List.d.ts +18 -5
- package/dist/components/display/List/List.js +53 -43
- package/dist/components/display/List/List.js.map +1 -1
- package/dist/components/display/List/List.module.js.map +1 -1
- package/dist/components/display/List/index.d.ts +1 -1
- package/dist/components/display/Marquee/Marquee.js +1 -1
- package/dist/components/display/Marquee/Marquee.js.map +1 -1
- package/dist/components/display/Media/Media.d.ts +15 -0
- package/dist/components/display/Media/Media.js +43 -23
- package/dist/components/display/Media/Media.js.map +1 -1
- package/dist/components/display/Media/Media.module.js.map +1 -1
- package/dist/components/display/Media/index.d.ts +1 -1
- package/dist/components/display/Stat/Stat.module.js.map +1 -1
- package/dist/components/display/Table/Table.d.ts +23 -1
- package/dist/components/display/Table/Table.js +19 -14
- package/dist/components/display/Table/Table.js.map +1 -1
- package/dist/components/display/Table/Table.module.js.map +1 -1
- package/dist/components/display/Table/index.d.ts +1 -1
- package/dist/components/display/Tag/Tag.d.ts +3 -0
- package/dist/components/display/Tag/Tag.js +11 -10
- package/dist/components/display/Tag/Tag.js.map +1 -1
- package/dist/components/display/Tag/Tag.module.js.map +1 -1
- package/dist/components/display/Tag/index.d.ts +1 -1
- package/dist/components/feedback/Flash/Flash.d.ts +47 -0
- package/dist/components/feedback/Flash/Flash.js +36 -0
- package/dist/components/feedback/Flash/Flash.js.map +1 -0
- package/dist/components/feedback/Flash/Flash.module.js +10 -0
- package/dist/components/feedback/Flash/Flash.module.js.map +1 -0
- package/dist/components/feedback/Flash/index.d.ts +2 -0
- package/dist/components/feedback/RelativeTime/RelativeTime.d.ts +7 -0
- package/dist/components/feedback/RelativeTime/RelativeTime.js +11 -11
- package/dist/components/feedback/RelativeTime/RelativeTime.js.map +1 -1
- package/dist/components/feedback/StatusDot/StatusDot.d.ts +1 -1
- package/dist/components/feedback/StatusDot/StatusDot.js.map +1 -1
- package/dist/components/inputs/ChoiceCards/ChoiceCards.js +9 -9
- package/dist/components/inputs/Combobox/Combobox.js +5 -5
- package/dist/components/inputs/PasswordInput/PasswordInput.js +4 -4
- package/dist/components/layout/AppShell/AppShell.d.ts +4 -1
- package/dist/components/layout/AppShell/AppShell.js +58 -44
- package/dist/components/layout/AppShell/AppShell.js.map +1 -1
- package/dist/components/layout/AppShell/AppShell.module.js.map +1 -1
- package/dist/components/layout/Box/Box.d.ts +15 -3
- package/dist/components/layout/Box/Box.js +11 -10
- package/dist/components/layout/Box/Box.js.map +1 -1
- package/dist/components/layout/Box/Box.module.js.map +1 -1
- package/dist/components/layout/Divider/Divider.d.ts +7 -1
- package/dist/components/layout/Divider/Divider.js +18 -20
- package/dist/components/layout/Divider/Divider.js.map +1 -1
- package/dist/components/layout/ScrollArea/ScrollArea.d.ts +36 -0
- package/dist/components/layout/ScrollArea/ScrollArea.js +25 -0
- package/dist/components/layout/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/layout/ScrollArea/ScrollArea.module.js +6 -0
- package/dist/components/layout/ScrollArea/ScrollArea.module.js.map +1 -0
- package/dist/components/layout/ScrollArea/index.d.ts +2 -0
- package/dist/components/layout/Section/Section.d.ts +18 -7
- package/dist/components/layout/Section/Section.js +10 -9
- package/dist/components/layout/Section/Section.js.map +1 -1
- package/dist/components/layout/Section/Section.module.js.map +1 -1
- package/dist/components/navigation/Accordion/Accordion.d.ts +6 -1
- package/dist/components/navigation/Accordion/Accordion.js +19 -11
- package/dist/components/navigation/Accordion/Accordion.js.map +1 -1
- package/dist/components/navigation/Accordion/Accordion.module.js +7 -6
- package/dist/components/navigation/Accordion/Accordion.module.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinks.d.ts +4 -1
- package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
- package/dist/components/overlays/Tooltip/Tooltip.d.ts +23 -0
- package/dist/components/overlays/Tooltip/Tooltip.js +77 -31
- package/dist/components/overlays/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/typography/Numeral/Numeral.d.ts +26 -2
- package/dist/components/typography/Numeral/Numeral.js +25 -21
- package/dist/components/typography/Numeral/Numeral.js.map +1 -1
- package/dist/components/typography/Numeral/Numeral.module.js +4 -3
- package/dist/components/typography/Numeral/Numeral.module.js.map +1 -1
- package/dist/components/typography/Text/Text.d.ts +5 -2
- package/dist/components/typography/Text/Text.js.map +1 -1
- package/dist/components/typography/Text/Text.module.js.map +1 -1
- package/dist/icons/Icon.js +1 -0
- package/dist/icons/Icon.js.map +1 -1
- package/dist/icons/icons.d.ts +12 -0
- package/dist/icons/icons.js +63 -13
- package/dist/icons/icons.js.map +1 -1
- package/dist/index.d.ts +19 -24
- package/dist/index.js +114 -112
- package/dist/styles.css +1 -1
- package/dist/themes/fiesta.css +1 -1
- package/dist/utils/tokens.d.ts +2 -0
- package/dist/utils/tokens.js.map +1 -1
- package/package.json +2 -2
- package/skills/custom-theme/SKILL.md +1 -1
- package/skills/design-rules/SKILL.md +8 -4
- package/skills/layout-composition/SKILL.md +2 -0
- package/skills/layout-composition/references/app-shell.md +2 -2
- package/skills/layout-composition/references/box.md +21 -1
- package/skills/layout-composition/references/divider.md +30 -1
- package/skills/layout-composition/references/scroll-area.md +68 -0
- package/skills/layout-composition/references/section.md +24 -2
- package/skills/setup-and-theming/SKILL.md +3 -3
- package/skills/setup-and-theming/references/fiesta.md +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavLinks.js","names":["styles","NavLinks_module_default","NavLinksContext","createContext","NavLinksRoot","forwardRef","rest","label","cx","visibilityClass","className","orientation","size","gap","space","NavLinksItem","useContext","Comp","asChild","Slot","active","NavLinks"],"sources":["../../../../src/components/navigation/NavLinks/NavLinks.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type HTMLAttributes,\n} from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport { space, type Space } from '#utils/tokens'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\nimport styles from './NavLinks.module.css'\n\nexport type NavLinksOrientation = 'horizontal' | 'vertical'\nexport type NavLinksSize = 'sm' | 'md'\n\nexport interface NavLinksProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /** Names the landmark. Required when a page has more than one nav. Default \"Main\". */\n label?: string\n /** `horizontal` (default) for headers; `vertical` for sidebars and footers. */\n orientation?: NavLinksOrientation\n /**\n * Space between links, as a step on the space scale. Default `5` horizontal, `0`\n * vertical (vertical items are already a full control tall).\n */\n gap?: Space\n
|
|
1
|
+
{"version":3,"file":"NavLinks.js","names":["styles","NavLinks_module_default","NavLinksContext","createContext","NavLinksRoot","forwardRef","rest","label","cx","visibilityClass","className","orientation","size","gap","space","NavLinksItem","useContext","Comp","asChild","Slot","active","NavLinks"],"sources":["../../../../src/components/navigation/NavLinks/NavLinks.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type HTMLAttributes,\n} from 'react'\nimport { Slot } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport { space, type Space } from '#utils/tokens'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\nimport styles from './NavLinks.module.css'\n\nexport type NavLinksOrientation = 'horizontal' | 'vertical'\nexport type NavLinksSize = 'sm' | 'md'\n\nexport interface NavLinksProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /** Names the landmark. Required when a page has more than one nav. Default \"Main\". */\n label?: string\n /** `horizontal` (default) for headers; `vertical` for sidebars and footers. */\n orientation?: NavLinksOrientation\n /**\n * Space between links, as a step on the space scale. Default `5` horizontal, `0`\n * vertical (vertical items are already a full control tall).\n */\n gap?: Space\n /**\n * `md` (default), body-size labels for page headers; `sm`, one step smaller, for sidebars,\n * dense toolbars, footers and sub-navs. Neither drops to the caption steps.\n */\n size?: NavLinksSize\n}\n\ninterface NavLinksContextValue {\n orientation: NavLinksOrientation\n size: NavLinksSize\n}\n\nconst NavLinksContext = createContext<NavLinksContextValue>({\n orientation: 'horizontal',\n size: 'md',\n})\n\nconst NavLinksRoot = forwardRef<HTMLElement, NavLinksProps>(function NavLinks(\n {\n label = 'Main',\n orientation = 'horizontal',\n gap,\n size = 'md',\n hideBelow,\n hideAbove,\n className,\n children,\n ...rest\n },\n ref,\n) {\n return (\n <NavLinksContext.Provider value={{ orientation, size }}>\n <nav\n ref={ref}\n aria-label={label}\n className={cx(styles.nav, visibilityClass({ hideBelow, hideAbove }), className)}\n data-orientation={orientation}\n data-size={size}\n {...rest}\n >\n <ul\n className={styles.list}\n role=\"list\"\n style={gap === undefined ? undefined : ({ '--_gap': space(gap) } as CSSProperties)}\n >\n {children}\n </ul>\n </nav>\n </NavLinksContext.Provider>\n )\n})\n\nexport interface NavLinksItemProps\n extends AnchorHTMLAttributes<HTMLAnchorElement>, VisibilityProps {\n /** The current page. Sets `aria-current=\"page\"` and draws the marker. */\n active?: boolean\n /** Render the single child (e.g. a router `<Link>`) instead of an `<a>`. */\n asChild?: boolean\n}\n\n/**\n * One link. For router links: `<NavLinks.Item asChild active={isActive}><Link to=\"/work\">Work</Link></NavLinks.Item>`.\n * `hideBelow`/`hideAbove` hide the whole list item (e.g. a secondary link on phones).\n */\nconst NavLinksItem = forwardRef<HTMLAnchorElement, NavLinksItemProps>(function NavLinksItem(\n { active = false, asChild = false, hideBelow, hideAbove, className, ...rest },\n ref,\n) {\n const { orientation, size } = useContext(NavLinksContext)\n const Comp = asChild ? Slot.Root : 'a'\n return (\n <li className={cx(styles.item, visibilityClass({ hideBelow, hideAbove }))}>\n <Comp\n ref={ref}\n className={cx(styles.link, className)}\n data-orientation={orientation}\n data-size={size}\n data-active={active || undefined}\n aria-current={active ? 'page' : undefined}\n {...rest}\n />\n </li>\n )\n})\n\n/**\n * A labelled navigation landmark with a list of links. Horizontal for headers, vertical for\n * sidebars.\n *\n * @remarks\n * `NavLinks` is a `<nav>` with a list of links. The current page is marked with a short accent bar\n * under the label (horizontal) or an accent dot beside it (vertical), and gets\n * `aria-current=\"page\"`. These docs' header and sidebar are `NavLinks`.\n *\n * @privateRemarks\n * Site / app navigation: a labelled `<nav>` with a list of links. The current page is\n * marked with a short accent bar under the label (horizontal) or an accent dot beside\n * it (vertical) — a mark, not a glowing pill.\n */\nexport const NavLinks = Object.assign(NavLinksRoot, { Item: NavLinksItem })\n"],"mappings":";;;;;;;;AAuCA,IAAME,IAAkBC,EAAoC;CAC1D,aAAa;CACb,MAAM;AACR,CAAC,GAEKC,IAAeC,EAAuC,SAC1D,EACE,WAAQ,QACR,iBAAc,cACd,QACA,UAAO,MACP,cACA,cACA,cACA,aACA,GAAGC,KAEL,GACA;CACA,OACE,kBAACJ,EAAgB,UAAjB;EAA0B,OAAO;GAAE;GAAa;EAAK;EACnD,UAAA,kBAAC,OAAD;GACO;GACL,cAAYK;GACZ,WAAWC,EAAGR,EAAO,KAAKS,EAAgB;IAAE;IAAW;GAAU,CAAC,GAAGC,CAAS;GAC9E,oBAAkBC;GAClB,aAAWC;GACX,GAAIN;GAEJ,UAAA,kBAAC,MAAD;IACE,WAAWN,EAAO;IAClB,MAAK;IACL,OAAOa,MAAQ,KAAA,IAAY,KAAA,IAAa,EAAE,UAAUC,EAAMD,CAAG,EAAE;IAE9D;GACC,CAAA;EACD,CAAA;CACmB,CAAA;AAE9B,CAAC,GAcKE,IAAeV,EAAiD,SACpE,EAAE,YAAS,IAAO,aAAU,IAAO,cAAW,cAAW,cAAW,GAAGC,KACvE,GACA;CACA,IAAM,EAAE,gBAAa,YAASU,EAAWd,CAAe,GAClDe,IAAOC,IAAUC,EAAK,OAAO;CACnC,OACE,kBAAC,MAAD;EAAI,WAAWX,EAAGR,EAAO,MAAMS,EAAgB;GAAE;GAAW;EAAU,CAAC,CAAC;EACtE,UAAA,kBAACQ,GAAD;GACO;GACL,WAAWT,EAAGR,EAAO,MAAMU,CAAS;GACpC,oBAAkBC;GAClB,aAAWC;GACX,eAAaQ,KAAU,KAAA;GACvB,gBAAcA,IAAS,SAAS,KAAA;GAChC,GAAId;EACL,CAAA;CACC,CAAA;AAER,CAAC,GAgBYe,IAAW,OAAO,OAAOjB,GAAc,EAAE,MAAMW,EAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavLinks.module.js","names":["nav","list","item","link","NavLinks_module_default"],"sources":["../../../../src/components/navigation/NavLinks/NavLinks.module.css"],"sourcesContent":["/*\n * Component tokens:\n * --navlinks-marker current-page marker colour, default var(--color-accent)\n * --navlinks-gap space between links, default var(--space-5) horizontal / 0 vertical\n * (the `gap` prop wins over it)\n */\n.nav {\n min-inline-size: 0;\n}\n\n.list {\n /* Defined here so an ancestor's --_gap can never leak in; the `gap` prop overrides inline. */\n --_gap: var(--navlinks-gap, var(--space-5));\n\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n column-gap: var(--_gap);\n row-gap: var(--space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.nav[data-orientation='vertical'] .list {\n --_gap: var(--navlinks-gap, 0px);\n flex-direction: column;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: var(--_gap);\n}\n\n.item {\n display: flex;\n margin: 0;\n padding: 0;\n}\n\n.link {\n --_marker: var(--navlinks-marker, var(--color-accent));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 0.5em;\n min-block-size: var(--control-md);\n padding: 0;\n color: var(--color-ink-muted);\n font-family: var(--font-text);\n font-size: var(--text-
|
|
1
|
+
{"version":3,"file":"NavLinks.module.js","names":["nav","list","item","link","NavLinks_module_default"],"sources":["../../../../src/components/navigation/NavLinks/NavLinks.module.css"],"sourcesContent":["/*\n * Component tokens:\n * --navlinks-marker current-page marker colour, default var(--color-accent)\n * --navlinks-gap space between links, default var(--space-5) horizontal / 0 vertical\n * (the `gap` prop wins over it)\n */\n.nav {\n min-inline-size: 0;\n}\n\n.list {\n /* Defined here so an ancestor's --_gap can never leak in; the `gap` prop overrides inline. */\n --_gap: var(--navlinks-gap, var(--space-5));\n\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n column-gap: var(--_gap);\n row-gap: var(--space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.nav[data-orientation='vertical'] .list {\n --_gap: var(--navlinks-gap, 0px);\n flex-direction: column;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: var(--_gap);\n}\n\n.item {\n display: flex;\n margin: 0;\n padding: 0;\n}\n\n.link {\n --_marker: var(--navlinks-marker, var(--color-accent));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 0.5em;\n min-block-size: var(--control-md);\n padding: 0;\n color: var(--color-ink-muted);\n font-family: var(--font-text);\n /* Body size: people read and scan nav labels, so they never drop to the caption steps. */\n font-size: var(--text-md);\n font-weight: var(--label-weight);\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n line-height: 1.2;\n text-decoration: none;\n white-space: nowrap;\n -webkit-tap-highlight-color: transparent;\n transition: color var(--dur-1) var(--ease-out);\n}\n\n@media (hover: hover) {\n .link:hover {\n color: var(--color-ink);\n }\n}\n\n.link[data-active] {\n color: var(--color-ink);\n}\n\n.link[data-size='sm'] {\n min-block-size: var(--control-sm);\n font-size: var(--text-sm);\n}\n\n.link:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n/* Horizontal: a bar under the label, the width of the word, sitting a little below it. */\n.link[data-orientation='horizontal']::after {\n content: '';\n position: absolute;\n inset-inline: 0;\n inset-block-end: calc(50% - 0.6lh - var(--space-2));\n block-size: max(2px, var(--border-width-strong));\n border-radius: 1px;\n background: var(--_marker);\n scale: 0 1;\n transform-origin: left;\n transition: scale var(--dur-2) var(--ease-spring);\n}\n.link[data-orientation='horizontal'][data-active]::after {\n scale: 1 1;\n}\n\n/* Vertical: a dot in a reserved gutter, so labels never shift. */\n.link[data-orientation='vertical'] {\n inline-size: 100%;\n padding-inline-start: var(--space-4);\n}\n.link[data-orientation='vertical'][data-size='sm'] {\n padding-inline-start: var(--space-3);\n}\n.link[data-orientation='vertical']::before {\n content: '';\n position: absolute;\n inset-inline-start: 0;\n inset-block-start: 50%;\n inline-size: 0.375rem;\n block-size: 0.375rem;\n margin-block-start: -0.1875rem;\n border-radius: 50%;\n background: var(--_marker);\n scale: 0;\n transition: scale var(--dur-2) var(--ease-spring);\n}\n.link[data-orientation='vertical'][data-active]::before {\n scale: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .link::before,\n .link::after {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -7,6 +7,7 @@ export type TooltipProviderProps = ComponentPropsWithoutRef<typeof TooltipPrimit
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function TooltipProvider({ delayDuration, skipDelayDuration, ...rest }: TooltipProviderProps): import("react").JSX.Element;
|
|
9
9
|
export type TooltipSide = 'top' | 'right' | 'bottom' | 'left';
|
|
10
|
+
export type TooltipTouch = 'none' | 'longpress';
|
|
10
11
|
export type TooltipAlign = 'start' | 'center' | 'end';
|
|
11
12
|
export interface TooltipProps extends Omit<ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>, 'content' | 'side' | 'align' | 'children'> {
|
|
12
13
|
/** The hint. Short — a label or one sentence. It's announced as the trigger's description. */
|
|
@@ -20,6 +21,12 @@ export interface TooltipProps extends Omit<ComponentPropsWithoutRef<typeof Toolt
|
|
|
20
21
|
align?: TooltipAlign;
|
|
21
22
|
/** Hover delay before opening, in ms. Keyboard focus opens immediately. */
|
|
22
23
|
delay?: number;
|
|
24
|
+
/**
|
|
25
|
+
* What a touch does. Hover and focus don't exist on a phone, so by default (`none`) a touch
|
|
26
|
+
* never opens a tooltip. `longpress` opens it when the trigger is held for half a second, and
|
|
27
|
+
* swallows the tap that follows, so the press doesn't also act. A tap elsewhere closes it.
|
|
28
|
+
*/
|
|
29
|
+
touch?: TooltipTouch;
|
|
23
30
|
open?: boolean;
|
|
24
31
|
defaultOpen?: boolean;
|
|
25
32
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -34,6 +41,22 @@ export interface TooltipProps extends Omit<ComponentPropsWithoutRef<typeof Toolt
|
|
|
34
41
|
* so an `overflow: hidden` parent never clips it. Keep it to a few words, and never put anything
|
|
35
42
|
* interactive in it: use a {@link Popover | Popover} for that.
|
|
36
43
|
*
|
|
44
|
+
* ## On touch screens
|
|
45
|
+
*
|
|
46
|
+
* A phone has no hover, so a tooltip never opens on a tap. With `touch="longpress"` it opens
|
|
47
|
+
* when the trigger is held for half a second, and the tap that ends the press is swallowed, so
|
|
48
|
+
* holding a button to see who reacted doesn't also press it. Don't hide anything essential in a
|
|
49
|
+
* tooltip: a long press is easy to miss.
|
|
50
|
+
*
|
|
51
|
+
* ## On disabled triggers
|
|
52
|
+
*
|
|
53
|
+
* A disabled button gets no pointer or focus events, so a tooltip on it could never open. When
|
|
54
|
+
* the trigger is `disabled`, `Tooltip` marks it `aria-disabled` instead and blocks its clicks
|
|
55
|
+
* and key presses, so it still looks and announces as disabled, but hover, focus and long press
|
|
56
|
+
* reach it and the reason it's disabled ("You've used all three reactions") reaches every
|
|
57
|
+
* reader. It's the same element either way, so a trigger that's disabled while a request is
|
|
58
|
+
* pending keeps keyboard focus.
|
|
59
|
+
*
|
|
37
60
|
* @privateRemarks
|
|
38
61
|
* A small label that appears on hover and on keyboard focus. Portalled, so it's never
|
|
39
62
|
* clipped by an `overflow: hidden` card. Not for anything interactive — use `Popover`.
|
|
@@ -1,64 +1,110 @@
|
|
|
1
1
|
import { cx as e } from "../../../utils/cx.js";
|
|
2
2
|
import { PortalAnchorContext as t, composeRefs as n, usePortalAnchorRef as r, usePortalTheme as i } from "../usePortalTheme.js";
|
|
3
3
|
import a from "./Tooltip.module.js";
|
|
4
|
-
import {
|
|
5
|
-
import { jsx as
|
|
6
|
-
import { Tooltip as
|
|
4
|
+
import { cloneElement as o, createContext as s, forwardRef as c, isValidElement as l, useContext as u, useEffect as d, useRef as f, useState as p } from "react";
|
|
5
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
6
|
+
import { Tooltip as g } from "radix-ui";
|
|
7
7
|
//#region src/components/overlays/Tooltip/Tooltip.tsx
|
|
8
|
-
var
|
|
9
|
-
function
|
|
10
|
-
return /* @__PURE__ */
|
|
8
|
+
var _ = s(!1);
|
|
9
|
+
function v({ delayDuration: e = 500, skipDelayDuration: t = 300, ...n }) {
|
|
10
|
+
return /* @__PURE__ */ m(_.Provider, {
|
|
11
11
|
value: !0,
|
|
12
|
-
children: /* @__PURE__ */
|
|
12
|
+
children: /* @__PURE__ */ m(g.Provider, {
|
|
13
13
|
delayDuration: e,
|
|
14
14
|
skipDelayDuration: t,
|
|
15
15
|
...n
|
|
16
16
|
})
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
var
|
|
19
|
+
var y = 500, b = 10, x = 1e3, S = c(function({ container: t, className: n, children: r, ...o }, s) {
|
|
20
20
|
let c = i(t);
|
|
21
|
-
return /* @__PURE__ */
|
|
21
|
+
return /* @__PURE__ */ h(g.Content, {
|
|
22
22
|
ref: s,
|
|
23
23
|
className: e(a.content, n),
|
|
24
24
|
collisionPadding: 8,
|
|
25
25
|
...c,
|
|
26
26
|
...o,
|
|
27
|
-
children: [r, /* @__PURE__ */
|
|
27
|
+
children: [r, /* @__PURE__ */ m(g.Arrow, {
|
|
28
28
|
className: a.arrow,
|
|
29
29
|
width: 10,
|
|
30
30
|
height: 5
|
|
31
31
|
})]
|
|
32
32
|
});
|
|
33
|
-
}),
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
}), C = c(function({ content: e, children: i, side: a = "top", align: s = "center", delay: c, touch: d = "none", open: f, defaultOpen: y, onOpenChange: b, container: x, sideOffset: C = 6, ...T }, E) {
|
|
34
|
+
let D = u(_), O = r(), [k, A] = p(y ?? !1), j = f ?? k, M = (e) => {
|
|
35
|
+
f === void 0 && A(e), b?.(e);
|
|
36
|
+
}, N = w(d === "longpress", () => {
|
|
37
|
+
M(!0);
|
|
38
|
+
}), P = l(i) && i.props.disabled === !0, F = P ? o(i, {
|
|
39
|
+
disabled: !1,
|
|
40
|
+
"aria-disabled": !0
|
|
41
|
+
}) : i, I = P ? {
|
|
42
|
+
onClickCapture: (e) => {
|
|
43
|
+
e.preventDefault(), e.stopPropagation();
|
|
44
|
+
},
|
|
45
|
+
onKeyDownCapture: (e) => {
|
|
46
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation());
|
|
47
|
+
}
|
|
48
|
+
} : {}, L = /* @__PURE__ */ m(t.Provider, {
|
|
49
|
+
value: O,
|
|
50
|
+
children: /* @__PURE__ */ h(g.Root, {
|
|
51
|
+
delayDuration: c,
|
|
52
|
+
open: j,
|
|
53
|
+
onOpenChange: M,
|
|
54
|
+
children: [/* @__PURE__ */ m(g.Trigger, {
|
|
42
55
|
asChild: !0,
|
|
43
|
-
ref: n(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
ref: n(O),
|
|
57
|
+
...N,
|
|
58
|
+
...I,
|
|
59
|
+
children: F
|
|
60
|
+
}), /* @__PURE__ */ m(g.Portal, {
|
|
61
|
+
container: x,
|
|
62
|
+
children: /* @__PURE__ */ m(S, {
|
|
63
|
+
ref: E,
|
|
64
|
+
container: x,
|
|
50
65
|
side: a,
|
|
51
|
-
align:
|
|
52
|
-
sideOffset:
|
|
53
|
-
...
|
|
66
|
+
align: s,
|
|
67
|
+
sideOffset: C,
|
|
68
|
+
...T,
|
|
54
69
|
children: e
|
|
55
70
|
})
|
|
56
71
|
})]
|
|
57
72
|
})
|
|
58
73
|
});
|
|
59
|
-
return
|
|
74
|
+
return D ? L : /* @__PURE__ */ m(v, { children: L });
|
|
60
75
|
});
|
|
76
|
+
function w(e, t) {
|
|
77
|
+
let n = f(void 0), r = f(null), i = f(!1), a = f(void 0), o = () => {
|
|
78
|
+
clearTimeout(n.current), r.current = null;
|
|
79
|
+
};
|
|
80
|
+
if (d(() => o, []), !e) return {};
|
|
81
|
+
let s = (e) => {
|
|
82
|
+
o(), i.current && (a.current = e.timeStamp);
|
|
83
|
+
}, c = (e) => {
|
|
84
|
+
if (!i.current) return;
|
|
85
|
+
let t = a.current;
|
|
86
|
+
t !== void 0 && (i.current = !1, e.timeStamp - t > x) || (e.preventDefault(), e.stopPropagation());
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
onPointerDown: (e) => {
|
|
90
|
+
i.current = !1, a.current = void 0, e.pointerType === "touch" && (r.current = {
|
|
91
|
+
x: e.clientX,
|
|
92
|
+
y: e.clientY
|
|
93
|
+
}, clearTimeout(n.current), n.current = setTimeout(() => {
|
|
94
|
+
i.current = !0, r.current = null, t();
|
|
95
|
+
}, y));
|
|
96
|
+
},
|
|
97
|
+
onPointerMove: (e) => {
|
|
98
|
+
let t = r.current;
|
|
99
|
+
t && Math.hypot(e.clientX - t.x, e.clientY - t.y) > b && o();
|
|
100
|
+
},
|
|
101
|
+
onPointerUp: s,
|
|
102
|
+
onPointerCancel: s,
|
|
103
|
+
onClickCapture: c,
|
|
104
|
+
onContextMenu: c
|
|
105
|
+
};
|
|
106
|
+
}
|
|
61
107
|
//#endregion
|
|
62
|
-
export {
|
|
108
|
+
export { C as Tooltip, v as TooltipProvider };
|
|
63
109
|
|
|
64
110
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","names":["TooltipPrimitive","styles","Tooltip","Tooltip_module_default","HasProvider","createContext","TooltipProvider","rest","Tooltip","ContentInner","forwardRef","theme","usePortalTheme","container","cx","className","children","Tooltip$1","hasProvider","useContext","anchor","usePortalAnchorRef","tooltip","PortalAnchorContext","delay","composeRefs","content"],"sources":["../../../../src/components/overlays/Tooltip/Tooltip.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n type ComponentPropsWithoutRef,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { Tooltip as TooltipPrimitive } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport {\n PortalAnchorContext,\n composeRefs,\n usePortalAnchorRef,\n usePortalTheme,\n} from '#components/overlays/usePortalTheme'\nimport styles from './Tooltip.module.css'\n\nconst HasProvider = createContext(false)\n\nexport type TooltipProviderProps = ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>\n\n/**\n * Shares open/skip delays between tooltips, so moving along a toolbar shows each hint\n * instantly after the first. Put one near the app root. Tooltips work without it.\n */\nexport function TooltipProvider({\n delayDuration = 500,\n skipDelayDuration = 300,\n ...rest\n}: TooltipProviderProps) {\n return (\n <HasProvider.Provider value>\n <TooltipPrimitive.Provider\n delayDuration={delayDuration}\n skipDelayDuration={skipDelayDuration}\n {...rest}\n />\n </HasProvider.Provider>\n )\n}\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left'\nexport type TooltipAlign = 'start' | 'center' | 'end'\n\nexport interface TooltipProps extends Omit<\n ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,\n 'content' | 'side' | 'align' | 'children'\n> {\n /** The hint. Short — a label or one sentence. It's announced as the trigger's description. */\n content: ReactNode\n /**\n * The trigger: a single focusable element (a button or link). It receives the ref and\n * event handlers, so custom components must forward both.\n */\n children: ReactElement\n side?: TooltipSide\n align?: TooltipAlign\n /** Hover delay before opening, in ms. Keyboard focus opens immediately. */\n delay?: number\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Portal target. Defaults to `document.body`; its theme scope is also used. */\n container?: HTMLElement | null\n}\n\nconst ContentInner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & { container?: HTMLElement | null }\n>(function ContentInner({ container, className, children, ...rest }, ref) {\n const theme = usePortalTheme(container)\n return (\n <TooltipPrimitive.Content\n ref={ref}\n className={cx(styles.content, className)}\n collisionPadding={8}\n {...theme}\n {...rest}\n >\n {children}\n <TooltipPrimitive.Arrow className={styles.arrow} width={10} height={5} />\n </TooltipPrimitive.Content>\n )\n})\n\n/**\n * A short label that appears on hover and keyboard focus. Never for anything interactive.\n *\n * @remarks\n * `Tooltip` shows a short label beside its trigger on hover and on keyboard focus. It's portalled,\n * so an `overflow: hidden` parent never clips it. Keep it to a few words, and never put anything\n * interactive in it: use a {@link Popover | Popover} for that.\n *\n * @privateRemarks\n * A small label that appears on hover and on keyboard focus. Portalled, so it's never\n * clipped by an `overflow: hidden` card. Not for anything interactive — use `Popover`.\n *\n * <Tooltip content=\"Copy link\"><IconButton … /></Tooltip>\n */\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(function Tooltip(\n {\n content,\n children,\n side = 'top',\n align = 'center',\n delay,\n open,\n defaultOpen,\n onOpenChange,\n container,\n sideOffset = 6,\n ...rest\n },\n ref,\n) {\n const hasProvider = useContext(HasProvider)\n const anchor = usePortalAnchorRef()\n const tooltip = (\n <PortalAnchorContext.Provider value={anchor}>\n <TooltipPrimitive.Root\n delayDuration={delay}\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n >\n <TooltipPrimitive.Trigger asChild ref={composeRefs(anchor)}>\n {children}\n </TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container}>\n <ContentInner\n ref={ref}\n container={container}\n side={side}\n align={align}\n sideOffset={sideOffset}\n {...rest}\n >\n {content}\n </ContentInner>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </PortalAnchorContext.Provider>\n )\n return hasProvider ? tooltip : <TooltipProvider>{tooltip}</TooltipProvider>\n})\n"],"mappings":";;;;;;;AAkBA,IAAMI,IAAcC,EAAc,EAAK;AAQvC,SAAgBC,EAAgB,EAC9B,mBAAgB,KAChB,uBAAoB,KACpB,GAAGC,KACoB;CACvB,OACE,kBAACH,EAAY,UAAb;EAAsB,OAAA;EACpB,UAAA,kBAACJ,EAAiB,UAAlB;GACiB;GACI;GACnB,GAAIO;EACL,CAAA;CACmB,CAAA;AAE1B;AA2BA,IAAME,IAAeC,EAGnB,SAAsB,EAAE,cAAW,cAAW,aAAU,GAAGH,KAAQ,GAAK;CACxE,IAAMI,IAAQC,EAAeC,CAAS;CACtC,OACE,kBAACb,EAAiB,SAAlB;EACO;EACL,WAAWc,EAAGb,EAAO,SAASc,CAAS;EACvC,kBAAkB;EAClB,GAAIJ;EACJ,GAAIJ;EALN,UAAA,CAOGS,GACD,kBAAChB,EAAiB,OAAlB;GAAwB,WAAWC,EAAO;GAAO,OAAO;GAAI,QAAQ;EAAI,CAAA,CAChD;;AAE9B,CAAC,GAgBYC,IAAUQ,EAAyC,SAC9D,EACE,YACA,aACA,UAAO,OACP,WAAQ,UACR,UACA,SACA,gBACA,iBACA,cACA,gBAAa,GACb,GAAGH,KAEL,GACA;CACA,IAAMW,IAAcC,EAAWf,CAAW,GACpCgB,IAASC,EAAmB,GAC5BC,IACJ,kBAACC,EAAoB,UAArB;EAA8B,OAAOH;EACnC,UAAA,kBAACpB,EAAiB,MAAlB;GACE,eAAewB;GACT;GACO;GACC;GAJhB,UAAA,CAME,kBAACxB,EAAiB,SAAlB;IAA0B,SAAA;IAAQ,KAAKyB,EAAYL,CAAM;IACtD;GACuB,CAAA,GAC1B,kBAACpB,EAAiB,QAAlB;IAAoC;IAClC,UAAA,kBAACS,GAAD;KACO;KACM;KACL;KACC;KACK;KACZ,GAAIF;KAEH,UAAAmB;IACW,CAAA;GACS,CAAA,CACJ;;CACK,CAAA;CAEhC,OAAOR,IAAcI,IAAU,kBAAChB,GAAD,EAAA,UAAkBgB,EAAyB,CAAA;AAC5E,CAAC"}
|
|
1
|
+
{"version":3,"file":"Tooltip.js","names":["TooltipPrimitive","styles","Tooltip","Tooltip_module_default","HasProvider","createContext","TooltipProvider","rest","Tooltip","LONG_PRESS","PRESS_SLOP","RELEASE_WINDOW","ContentInner","forwardRef","theme","usePortalTheme","container","cx","className","children","Tooltip$1","hasProvider","useContext","anchor","usePortalAnchorRef","uncontrolled","setUncontrolled","useState","defaultOpen","isOpen","open","setOpen","next","onOpenChange","press","useLongPress","touch","disabled","isValidElement","trigger","cloneElement","block","event","tooltip","PortalAnchorContext","delay","composeRefs","content","timer","useRef","start","fired","releasedAt","cancel","useEffect","enabled","release","swallow","released","onLongPress","from"],"sources":["../../../../src/components/overlays/Tooltip/Tooltip.tsx"],"sourcesContent":["import {\n cloneElement,\n createContext,\n forwardRef,\n isValidElement,\n useContext,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from 'react'\nimport { Tooltip as TooltipPrimitive } from 'radix-ui'\nimport { cx } from '#utils/cx'\nimport {\n PortalAnchorContext,\n composeRefs,\n usePortalAnchorRef,\n usePortalTheme,\n} from '#components/overlays/usePortalTheme'\nimport styles from './Tooltip.module.css'\n\nconst HasProvider = createContext(false)\n\nexport type TooltipProviderProps = ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>\n\n/**\n * Shares open/skip delays between tooltips, so moving along a toolbar shows each hint\n * instantly after the first. Put one near the app root. Tooltips work without it.\n */\nexport function TooltipProvider({\n delayDuration = 500,\n skipDelayDuration = 300,\n ...rest\n}: TooltipProviderProps) {\n return (\n <HasProvider.Provider value>\n <TooltipPrimitive.Provider\n delayDuration={delayDuration}\n skipDelayDuration={skipDelayDuration}\n {...rest}\n />\n </HasProvider.Provider>\n )\n}\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left'\nexport type TooltipTouch = 'none' | 'longpress'\n\n/** How long a touch must be held before a `touch=\"longpress\"` tooltip opens, in ms. */\nconst LONG_PRESS = 500\n/** How far a touch may drift, in px, and still count as a press rather than a scroll. */\nconst PRESS_SLOP = 10\n/** How long after a long press ends its click or context menu is still swallowed, in ms. */\nconst RELEASE_WINDOW = 1000\nexport type TooltipAlign = 'start' | 'center' | 'end'\n\nexport interface TooltipProps extends Omit<\n ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,\n 'content' | 'side' | 'align' | 'children'\n> {\n /** The hint. Short — a label or one sentence. It's announced as the trigger's description. */\n content: ReactNode\n /**\n * The trigger: a single focusable element (a button or link). It receives the ref and\n * event handlers, so custom components must forward both.\n */\n children: ReactElement\n side?: TooltipSide\n align?: TooltipAlign\n /** Hover delay before opening, in ms. Keyboard focus opens immediately. */\n delay?: number\n /**\n * What a touch does. Hover and focus don't exist on a phone, so by default (`none`) a touch\n * never opens a tooltip. `longpress` opens it when the trigger is held for half a second, and\n * swallows the tap that follows, so the press doesn't also act. A tap elsewhere closes it.\n */\n touch?: TooltipTouch\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Portal target. Defaults to `document.body`; its theme scope is also used. */\n container?: HTMLElement | null\n}\n\nconst ContentInner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & { container?: HTMLElement | null }\n>(function ContentInner({ container, className, children, ...rest }, ref) {\n const theme = usePortalTheme(container)\n return (\n <TooltipPrimitive.Content\n ref={ref}\n className={cx(styles.content, className)}\n collisionPadding={8}\n {...theme}\n {...rest}\n >\n {children}\n <TooltipPrimitive.Arrow className={styles.arrow} width={10} height={5} />\n </TooltipPrimitive.Content>\n )\n})\n\n/**\n * A short label that appears on hover and keyboard focus. Never for anything interactive.\n *\n * @remarks\n * `Tooltip` shows a short label beside its trigger on hover and on keyboard focus. It's portalled,\n * so an `overflow: hidden` parent never clips it. Keep it to a few words, and never put anything\n * interactive in it: use a {@link Popover | Popover} for that.\n *\n * ## On touch screens\n *\n * A phone has no hover, so a tooltip never opens on a tap. With `touch=\"longpress\"` it opens\n * when the trigger is held for half a second, and the tap that ends the press is swallowed, so\n * holding a button to see who reacted doesn't also press it. Don't hide anything essential in a\n * tooltip: a long press is easy to miss.\n *\n * ## On disabled triggers\n *\n * A disabled button gets no pointer or focus events, so a tooltip on it could never open. When\n * the trigger is `disabled`, `Tooltip` marks it `aria-disabled` instead and blocks its clicks\n * and key presses, so it still looks and announces as disabled, but hover, focus and long press\n * reach it and the reason it's disabled (\"You've used all three reactions\") reaches every\n * reader. It's the same element either way, so a trigger that's disabled while a request is\n * pending keeps keyboard focus.\n *\n * @privateRemarks\n * A small label that appears on hover and on keyboard focus. Portalled, so it's never\n * clipped by an `overflow: hidden` card. Not for anything interactive — use `Popover`.\n *\n * <Tooltip content=\"Copy link\"><IconButton … /></Tooltip>\n */\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(function Tooltip(\n {\n content,\n children,\n side = 'top',\n align = 'center',\n delay,\n touch = 'none',\n open,\n defaultOpen,\n onOpenChange,\n container,\n sideOffset = 6,\n ...rest\n },\n ref,\n) {\n const hasProvider = useContext(HasProvider)\n const anchor = usePortalAnchorRef()\n const [uncontrolled, setUncontrolled] = useState(defaultOpen ?? false)\n const isOpen = open ?? uncontrolled\n const setOpen = (next: boolean) => {\n if (open === undefined) setUncontrolled(next)\n onOpenChange?.(next)\n }\n const press = useLongPress(touch === 'longpress', () => {\n setOpen(true)\n })\n const disabled =\n isValidElement<{ disabled?: unknown }>(children) && children.props.disabled === true\n // Disabled stays focusable (aria-disabled) and on the same element, so focus survives a\n // disabled toggle and the hint still opens; activation is blocked here instead.\n const trigger = disabled\n ? cloneElement(children as ReactElement<Record<string, unknown>>, {\n disabled: false,\n 'aria-disabled': true,\n })\n : children\n const block = disabled\n ? {\n onClickCapture: (event: SyntheticEvent) => {\n event.preventDefault()\n event.stopPropagation()\n },\n onKeyDownCapture: (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n },\n }\n : {}\n const tooltip = (\n <PortalAnchorContext.Provider value={anchor}>\n <TooltipPrimitive.Root delayDuration={delay} open={isOpen} onOpenChange={setOpen}>\n <TooltipPrimitive.Trigger asChild ref={composeRefs(anchor)} {...press} {...block}>\n {trigger}\n </TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container}>\n <ContentInner\n ref={ref}\n container={container}\n side={side}\n align={align}\n sideOffset={sideOffset}\n {...rest}\n >\n {content}\n </ContentInner>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </PortalAnchorContext.Provider>\n )\n return hasProvider ? tooltip : <TooltipProvider>{tooltip}</TooltipProvider>\n})\n\n/**\n * Long-press handlers for a trigger: a touch held still for LONG_PRESS opens the tooltip, and\n * the click that ends that press (and the phone's context menu) is swallowed.\n */\nfunction useLongPress(enabled: boolean, onLongPress: () => void) {\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const start = useRef<{ x: number; y: number } | null>(null)\n const fired = useRef(false)\n const releasedAt = useRef<number | undefined>(undefined)\n const cancel = () => {\n clearTimeout(timer.current)\n start.current = null\n }\n useEffect(() => cancel, [])\n if (!enabled) return {}\n const release = (event: PointerEvent) => {\n cancel()\n if (fired.current) releasedAt.current = event.timeStamp\n }\n const swallow = (event: SyntheticEvent) => {\n if (!fired.current) return\n const released = releasedAt.current\n if (released !== undefined) {\n fired.current = false\n if (event.timeStamp - released > RELEASE_WINDOW) return\n }\n event.preventDefault()\n event.stopPropagation()\n }\n return {\n onPointerDown: (event: PointerEvent) => {\n fired.current = false\n releasedAt.current = undefined\n if (event.pointerType !== 'touch') return\n start.current = { x: event.clientX, y: event.clientY }\n clearTimeout(timer.current)\n timer.current = setTimeout(() => {\n fired.current = true\n start.current = null\n onLongPress()\n }, LONG_PRESS)\n },\n onPointerMove: (event: PointerEvent) => {\n const from = start.current\n if (from && Math.hypot(event.clientX - from.x, event.clientY - from.y) > PRESS_SLOP) cancel()\n },\n onPointerUp: release,\n onPointerCancel: release,\n onClickCapture: swallow,\n onContextMenu: swallow,\n }\n}\n"],"mappings":";;;;;;;AA0BA,IAAMI,IAAcC,EAAc,EAAK;AAQvC,SAAgBC,EAAgB,EAC9B,mBAAgB,KAChB,uBAAoB,KACpB,GAAGC,KACoB;CACvB,OACE,kBAACH,EAAY,UAAb;EAAsB,OAAA;EACpB,UAAA,kBAACJ,EAAiB,UAAlB;GACiB;GACI;GACnB,GAAIO;EACL,CAAA;CACmB,CAAA;AAE1B;AAMA,IAAME,IAAa,KAEbC,IAAa,IAEbC,IAAiB,KA+BjBC,IAAeC,EAGnB,SAAsB,EAAE,cAAW,cAAW,aAAU,GAAGN,KAAQ,GAAK;CACxE,IAAMO,IAAQC,EAAeC,CAAS;CACtC,OACE,kBAAChB,EAAiB,SAAlB;EACO;EACL,WAAWiB,EAAGhB,EAAO,SAASiB,CAAS;EACvC,kBAAkB;EAClB,GAAIJ;EACJ,GAAIP;EALN,UAAA,CAOGY,GACD,kBAACnB,EAAiB,OAAlB;GAAwB,WAAWC,EAAO;GAAO,OAAO;GAAI,QAAQ;EAAI,CAAA,CAChD;;AAE9B,CAAC,GAgCYC,IAAUW,EAAyC,SAC9D,EACE,YACA,aACA,UAAO,OACP,WAAQ,UACR,UACA,WAAQ,QACR,SACA,gBACA,iBACA,cACA,gBAAa,GACb,GAAGN,KAEL,GACA;CACA,IAAMc,IAAcC,EAAWlB,CAAW,GACpCmB,IAASC,EAAmB,GAC5B,CAACC,GAAcC,KAAmBC,EAASC,KAAe,EAAK,GAC/DC,IAASC,KAAQL,GACjBM,KAAW,MAAkB;EAEjC,AADID,MAAS,KAAA,KAAWJ,EAAgBM,CAAI,GAC5CC,IAAeD,CAAI;CACrB,GACME,IAAQC,EAAaC,MAAU,mBAAmB;EACtD,EAAQ,EAAI;CACd,CAAC,GACKC,IACJC,EAAuCnB,CAAQ,KAAKA,EAAS,MAAM,aAAa,IAG5EoB,IAAUF,IACZG,EAAarB,GAAmD;EAC9D,UAAU;EACV,iBAAiB;CACnB,CAAC,IACDA,GACEsB,IAAQJ,IACV;EACE,iBAAiB,MAA0B;GAEzC,AADAK,EAAM,eAAe,GACrBA,EAAM,gBAAgB;EACxB;EACA,mBAAmB,MAAyB;GAC1C,CAAIA,EAAM,QAAQ,WAAWA,EAAM,QAAQ,SACzCA,EAAM,eAAe,GACrBA,EAAM,gBAAgB;EAE1B;CACF,IACA,CAAC,GACCC,IACJ,kBAACC,EAAoB,UAArB;EAA8B,OAAOrB;EACnC,UAAA,kBAACvB,EAAiB,MAAlB;GAAuB,eAAe6C;GAAO,MAAMhB;GAAQ,cAAcE;GAAzE,UAAA,CACE,kBAAC/B,EAAiB,SAAlB;IAA0B,SAAA;IAAQ,KAAK8C,EAAYvB,CAAM;IAAG,GAAIW;IAAO,GAAIO;IACxE,UAAAF;GACuB,CAAA,GAC1B,kBAACvC,EAAiB,QAAlB;IAAoC;IAClC,UAAA,kBAACY,GAAD;KACO;KACM;KACL;KACC;KACK;KACZ,GAAIL;KAEH,UAAAwC;IACW,CAAA;GACS,CAAA,CACJ;;CACK,CAAA;CAEhC,OAAO1B,IAAcsB,IAAU,kBAACrC,GAAD,EAAA,UAAkBqC,EAAyB,CAAA;AAC5E,CAAC;AAMD,SAASR,EAAa,GAAkB,GAAyB;CAC/D,IAAMa,IAAQC,EAAkD,KAAA,CAAS,GACnEC,IAAQD,EAAwC,IAAI,GACpDE,IAAQF,EAAO,EAAK,GACpBG,IAAaH,EAA2B,KAAA,CAAS,GACjDI,UAAe;EAEnB,AADA,aAAaL,EAAM,OAAO,GAC1B,EAAM,UAAU;CAClB;CAEA,IADAM,QAAgBD,GAAQ,CAAC,CAAC,GACtB,CAACE,GAAS,OAAO,CAAC;CACtB,IAAMC,KAAW,MAAwB;EAEvC,AADAH,EAAO,GACHF,EAAM,YAAS,EAAW,UAAUT,EAAM;CAChD,GACMe,KAAW,MAA0B;EACzC,IAAI,CAACN,EAAM,SAAS;EACpB,IAAMO,IAAWN,EAAW;EAC5B,AAAIM,MAAa,KAAA,MACf,EAAM,UAAU,IACZhB,EAAM,YAAYgB,IAAW/C,OAEnC+B,EAAM,eAAe,GACrBA,EAAM,gBAAgB;CACxB;CACA,OAAO;EACL,gBAAgB,MAAwB;GAGtC,AAFA,EAAM,UAAU,IAChB,EAAW,UAAU,KAAA,GACjBA,EAAM,gBAAgB,YAC1B,EAAM,UAAU;IAAE,GAAGA,EAAM;IAAS,GAAGA,EAAM;GAAQ,GACrD,aAAaM,EAAM,OAAO,GAC1B,EAAM,UAAU,iBAAiB;IAG/B,AAFA,EAAM,UAAU,IAChB,EAAM,UAAU,MAChBW,EAAY;GACd,GAAGlD,CAAU;EACf;EACA,gBAAgB,MAAwB;GACtC,IAAMmD,IAAOV,EAAM;GACnB,AAAIU,KAAQ,KAAK,MAAMlB,EAAM,UAAUkB,EAAK,GAAGlB,EAAM,UAAUkB,EAAK,CAAC,IAAIlD,KAAY2C,EAAO;EAC9F;EACA,aAAaG;EACb,iBAAiBA;EACjB,gBAAgBC;EAChB,eAAeA;CACjB;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DataHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
export type NumeralTone = 'auto' | 'default' | 'muted' | 'accent' | 'positive' | 'caution' | 'critical';
|
|
2
|
+
export type NumeralTone = 'auto' | 'default' | 'muted' | 'accent' | 'positive' | 'caution' | 'critical' | 'highlight';
|
|
3
3
|
export type NumeralSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'display-sm' | 'display-md' | 'display-lg';
|
|
4
4
|
export interface NumeralProps extends Omit<DataHTMLAttributes<HTMLDataElement>, 'value' | 'children' | 'prefix'> {
|
|
5
5
|
value: number;
|
|
@@ -9,7 +9,11 @@ export interface NumeralProps extends Omit<DataHTMLAttributes<HTMLDataElement>,
|
|
|
9
9
|
locale?: string;
|
|
10
10
|
/** Shorthand for `format.signDisplay`. `exceptZero` shows +/− on everything but zero. */
|
|
11
11
|
signDisplay?: Intl.NumberFormatOptions['signDisplay'];
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* `auto` colours by sign: positive → positive tone, negative → critical. `highlight` sets the
|
|
14
|
+
* figure on the theme's highlight, like a marker pen, for the one figure that's "you" or first.
|
|
15
|
+
* Omit to inherit.
|
|
16
|
+
*/
|
|
13
17
|
tone?: NumeralTone;
|
|
14
18
|
/** Step on the type scale. Omit to inherit — figures usually sit inside other text. */
|
|
15
19
|
size?: NumeralSize;
|
|
@@ -17,6 +21,11 @@ export interface NumeralProps extends Omit<DataHTMLAttributes<HTMLDataElement>,
|
|
|
17
21
|
prefix?: ReactNode;
|
|
18
22
|
/** Set after the figures, proportional: " seats", "×", " km". Add your own spacing. */
|
|
19
23
|
suffix?: ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* A small figure after the main one, part of the same reading: the shootout in "1 (4)", the
|
|
26
|
+
* games played beside a total. Set smaller and muted, after a space.
|
|
27
|
+
*/
|
|
28
|
+
annotation?: ReactNode;
|
|
20
29
|
}
|
|
21
30
|
/**
|
|
22
31
|
* A formatted number in tabular figures, with its machine-readable value attached.
|
|
@@ -26,6 +35,21 @@ export interface NumeralProps extends Omit<DataHTMLAttributes<HTMLDataElement>,
|
|
|
26
35
|
* tabular, lining figures, so a column of them lines up and a changing value doesn't jitter. It
|
|
27
36
|
* renders a `<data value>` element, so the raw value travels with the formatted text.
|
|
28
37
|
*
|
|
38
|
+
* ## Testing
|
|
39
|
+
*
|
|
40
|
+
* Signs, decimal marks, separators and affixes are set in their own spans, and Testing Library's
|
|
41
|
+
* `getByText` matches an element's own text only, so `getByText('90.5')` won't find a `Numeral`
|
|
42
|
+
* showing 90.5. Match the `<data>` element's whole text, or its raw `value`:
|
|
43
|
+
*
|
|
44
|
+
* ```tsx
|
|
45
|
+
* import { render } from '@testing-library/react'
|
|
46
|
+
* import { Numeral } from '@mitcsutt/kiln-ui'
|
|
47
|
+
*
|
|
48
|
+
* const { container, getByText } = render(<Numeral value={90.5} signDisplay="always" />)
|
|
49
|
+
* getByText((_, el) => el?.tagName === 'DATA' && el.textContent === '+90.5')
|
|
50
|
+
* container.querySelector('data[value="90.5"]')
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
29
53
|
* @privateRemarks
|
|
30
54
|
* A formatted number. Always tabular, lining figures in the theme's numeric face, and
|
|
31
55
|
* wrapped in <data value> so the machine-readable value travels with it. Separators
|
|
@@ -2,40 +2,44 @@ import { cx as e } from "../../../utils/cx.js";
|
|
|
2
2
|
import { formatNumeralParts as t, signOf as n } from "./format.js";
|
|
3
3
|
import r from "./Numeral.module.js";
|
|
4
4
|
import { Fragment as i, forwardRef as a } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/typography/Numeral/Numeral.tsx
|
|
7
|
-
var
|
|
8
|
-
let
|
|
9
|
-
...
|
|
10
|
-
signDisplay:
|
|
11
|
-
} :
|
|
12
|
-
return /* @__PURE__ */
|
|
13
|
-
ref:
|
|
7
|
+
var l = a(function({ value: a, format: l, locale: u = "en-AU", signDisplay: d, tone: f, size: p, prefix: m, suffix: h, annotation: g, className: _, ...v }, y) {
|
|
8
|
+
let b = n(a), x = t(a, u, d ? {
|
|
9
|
+
...l,
|
|
10
|
+
signDisplay: d
|
|
11
|
+
} : l), S = f === "auto" ? b === "positive" ? "positive" : b === "negative" ? "critical" : void 0 : f;
|
|
12
|
+
return /* @__PURE__ */ c("data", {
|
|
13
|
+
ref: y,
|
|
14
14
|
value: String(a),
|
|
15
|
-
className: e(r.numeral,
|
|
16
|
-
"data-sign":
|
|
17
|
-
"data-tone":
|
|
18
|
-
"data-size":
|
|
19
|
-
...
|
|
15
|
+
className: e(r.numeral, _),
|
|
16
|
+
"data-sign": b,
|
|
17
|
+
"data-tone": S,
|
|
18
|
+
"data-size": p,
|
|
19
|
+
...v,
|
|
20
20
|
children: [
|
|
21
|
-
|
|
21
|
+
m != null && m !== !1 ? /* @__PURE__ */ s("span", {
|
|
22
22
|
className: r.mark,
|
|
23
23
|
"data-affix": "prefix",
|
|
24
|
-
children:
|
|
24
|
+
children: m
|
|
25
25
|
}) : null,
|
|
26
|
-
|
|
26
|
+
x.map((e, t) => e.kind === "mark" ? /* @__PURE__ */ s("span", {
|
|
27
27
|
className: r.mark,
|
|
28
28
|
children: e.value
|
|
29
|
-
}, t) : /* @__PURE__ */
|
|
30
|
-
|
|
29
|
+
}, t) : /* @__PURE__ */ s(i, { children: e.value }, t)),
|
|
30
|
+
h != null && h !== !1 ? /* @__PURE__ */ s("span", {
|
|
31
31
|
className: r.mark,
|
|
32
32
|
"data-affix": "suffix",
|
|
33
|
-
children:
|
|
34
|
-
}) : null
|
|
33
|
+
children: h
|
|
34
|
+
}) : null,
|
|
35
|
+
g != null && g !== !1 ? /* @__PURE__ */ c(o, { children: [" ", /* @__PURE__ */ s("span", {
|
|
36
|
+
className: r.annotation,
|
|
37
|
+
children: g
|
|
38
|
+
})] }) : null
|
|
35
39
|
]
|
|
36
40
|
});
|
|
37
41
|
});
|
|
38
42
|
//#endregion
|
|
39
|
-
export {
|
|
43
|
+
export { l as Numeral };
|
|
40
44
|
|
|
41
45
|
//# sourceMappingURL=Numeral.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Numeral.js","names":["styles","Numeral_module_default","Numeral","forwardRef","rest","sign","signOf","value","parts","formatNumeralParts","locale","signDisplay","format","resolvedTone","tone","cx","className","size","prefix","part","i","Fragment","suffix"],"sources":["../../../../src/components/typography/Numeral/Numeral.tsx"],"sourcesContent":["import { Fragment, forwardRef, type DataHTMLAttributes, type ReactNode } from 'react'\nimport { cx } from '#utils/cx'\nimport { formatNumeralParts, signOf } from './format'\nimport styles from './Numeral.module.css'\n\nexport type NumeralTone =\n 'auto' | 'default' | 'muted' | 'accent' | 'positive' | 'caution' | 'critical'\nexport type NumeralSize =\n 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'display-sm' | 'display-md' | 'display-lg'\n\nexport interface NumeralProps extends Omit<\n DataHTMLAttributes<HTMLDataElement>,\n 'value' | 'children' | 'prefix'\n> {\n value: number\n /** Passed straight to `Intl.NumberFormat` (percent, units, fraction digits, compact…). */\n format?: Intl.NumberFormatOptions\n /** BCP 47 locale. Default `en-AU`. */\n locale?: string\n /** Shorthand for `format.signDisplay`. `exceptZero` shows +/− on everything but zero. */\n signDisplay?: Intl.NumberFormatOptions['signDisplay']\n
|
|
1
|
+
{"version":3,"file":"Numeral.js","names":["styles","_Fragment","Numeral_module_default","Fragment$1","Numeral","forwardRef","rest","sign","signOf","value","parts","formatNumeralParts","locale","signDisplay","format","resolvedTone","tone","cx","className","size","prefix","part","i","Fragment","suffix","annotation"],"sources":["../../../../src/components/typography/Numeral/Numeral.tsx"],"sourcesContent":["import { Fragment, forwardRef, type DataHTMLAttributes, type ReactNode } from 'react'\nimport { cx } from '#utils/cx'\nimport { formatNumeralParts, signOf } from './format'\nimport styles from './Numeral.module.css'\n\nexport type NumeralTone =\n 'auto' | 'default' | 'muted' | 'accent' | 'positive' | 'caution' | 'critical' | 'highlight'\nexport type NumeralSize =\n 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'display-sm' | 'display-md' | 'display-lg'\n\nexport interface NumeralProps extends Omit<\n DataHTMLAttributes<HTMLDataElement>,\n 'value' | 'children' | 'prefix'\n> {\n value: number\n /** Passed straight to `Intl.NumberFormat` (percent, units, fraction digits, compact…). */\n format?: Intl.NumberFormatOptions\n /** BCP 47 locale. Default `en-AU`. */\n locale?: string\n /** Shorthand for `format.signDisplay`. `exceptZero` shows +/− on everything but zero. */\n signDisplay?: Intl.NumberFormatOptions['signDisplay']\n /**\n * `auto` colours by sign: positive → positive tone, negative → critical. `highlight` sets the\n * figure on the theme's highlight, like a marker pen, for the one figure that's \"you\" or first.\n * Omit to inherit.\n */\n tone?: NumeralTone\n /** Step on the type scale. Omit to inherit — figures usually sit inside other text. */\n size?: NumeralSize\n /** Set before the figures, proportional (not tabular): \"≈\", \"#\", \"Rank \". Add your own spacing. */\n prefix?: ReactNode\n /** Set after the figures, proportional: \" seats\", \"×\", \" km\". Add your own spacing. */\n suffix?: ReactNode\n /**\n * A small figure after the main one, part of the same reading: the shootout in \"1 (4)\", the\n * games played beside a total. Set smaller and muted, after a space.\n */\n annotation?: ReactNode\n}\n\n/**\n * A formatted number in tabular figures, with its machine-readable value attached.\n *\n * @remarks\n * `Numeral` formats a number with `Intl.NumberFormat` and sets it in the theme's numeric face with\n * tabular, lining figures, so a column of them lines up and a changing value doesn't jitter. It\n * renders a `<data value>` element, so the raw value travels with the formatted text.\n *\n * ## Testing\n *\n * Signs, decimal marks, separators and affixes are set in their own spans, and Testing Library's\n * `getByText` matches an element's own text only, so `getByText('90.5')` won't find a `Numeral`\n * showing 90.5. Match the `<data>` element's whole text, or its raw `value`:\n *\n * ```tsx\n * import { render } from '@testing-library/react'\n * import { Numeral } from '@mitcsutt/kiln-ui'\n *\n * const { container, getByText } = render(<Numeral value={90.5} signDisplay=\"always\" />)\n * getByText((_, el) => el?.tagName === 'DATA' && el.textContent === '+90.5')\n * container.querySelector('data[value=\"90.5\"]')\n * ```\n *\n * @privateRemarks\n * A formatted number. Always tabular, lining figures in the theme's numeric face, and\n * wrapped in <data value> so the machine-readable value travels with it. Separators\n * and symbols are set proportionally: some faces (Schibsted) make a tabular comma as\n * wide as a digit, which reads as \"1 , 017\". Right-aligned columns still line up.\n *\n * <Numeral value={0.184} format={{ style: 'percent', maximumFractionDigits: 1 }} signDisplay=\"exceptZero\" tone=\"auto\" />\n */\nexport const Numeral = forwardRef<HTMLDataElement, NumeralProps>(function Numeral(\n {\n value,\n format,\n locale = 'en-AU',\n signDisplay,\n tone,\n size,\n prefix,\n suffix,\n annotation,\n className,\n ...rest\n },\n ref,\n) {\n const sign = signOf(value)\n const parts = formatNumeralParts(value, locale, signDisplay ? { ...format, signDisplay } : format)\n const resolvedTone =\n tone === 'auto'\n ? sign === 'positive'\n ? 'positive'\n : sign === 'negative'\n ? 'critical'\n : undefined\n : tone\n return (\n <data\n ref={ref}\n value={String(value)}\n className={cx(styles.numeral, className)}\n data-sign={sign}\n data-tone={resolvedTone}\n data-size={size}\n {...rest}\n >\n {prefix != null && prefix !== false ? (\n <span className={styles.mark} data-affix=\"prefix\">\n {prefix}\n </span>\n ) : null}\n {parts.map((part, i) =>\n part.kind === 'mark' ? (\n <span key={i} className={styles.mark}>\n {part.value}\n </span>\n ) : (\n <Fragment key={i}>{part.value}</Fragment>\n ),\n )}\n {suffix != null && suffix !== false ? (\n <span className={styles.mark} data-affix=\"suffix\">\n {suffix}\n </span>\n ) : null}\n {annotation != null && annotation !== false ? (\n <>\n {' '}\n <span className={styles.annotation}>{annotation}</span>\n </>\n ) : null}\n </data>\n )\n})\n"],"mappings":";;;;;;AAuEA,IAAaI,IAAUC,EAA0C,SAC/D,EACE,UACA,WACA,YAAS,SACT,gBACA,SACA,SACA,WACA,WACA,eACA,cACA,GAAGC,KAEL,GACA;CACA,IAAMC,IAAOC,EAAOC,CAAK,GACnBC,IAAQC,EAAmBF,GAAOG,GAAQC,IAAc;EAAE,GAAGC;EAAQ;CAAY,IAAIA,CAAM,GAC3FC,IACJC,MAAS,SACLT,MAAS,aACP,aACAA,MAAS,aACP,aACA,KAAA,IACJS;CACN,OACE,kBAAC,QAAD;EACO;EACL,OAAO,OAAOP,CAAK;EACnB,WAAWQ,EAAGjB,EAAO,SAASkB,CAAS;EACvC,aAAWX;EACX,aAAWQ;EACX,aAAWI;EACX,GAAIb;EAPN,UAAA;GASGc,KAAU,QAAQA,MAAW,KAC5B,kBAAC,QAAD;IAAM,WAAWpB,EAAO;IAAM,cAAW;IACtC,UAAAoB;GACG,CAAA,IACJ;GACHV,EAAM,KAAK,GAAM,MAChBW,EAAK,SAAS,SACZ,kBAAC,QAAD;IAAc,WAAWrB,EAAO;IAC7B,UAAAqB,EAAK;GACF,GAFKC,CAEL,IAEN,kBAACC,GAAD,EAAA,UAAmBF,EAAK,MAAgB,GAAzBC,CAAyB,CAE5C;GACCE,KAAU,QAAQA,MAAW,KAC5B,kBAAC,QAAD;IAAM,WAAWxB,EAAO;IAAM,cAAW;IACtC,UAAAwB;GACG,CAAA,IACJ;GACHC,KAAc,QAAQA,MAAe,KACpC,kBAAAxB,GAAA,EAAA,UAAA,CACG,KACD,kBAAC,QAAD;IAAM,WAAWD,EAAO;IAAa,UAAAyB;GAAiB,CAAA,CACtD,EAAA,CAAA,IACA;EACA;;AAEV,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//#region src/components/typography/Numeral/Numeral.module.css
|
|
2
|
-
var e = "kiln-Numeral__numeral", t = "kiln-
|
|
2
|
+
var e = "kiln-Numeral__numeral", t = "kiln-Numeral__annotation", n = "kiln-Numeral__mark", r = {
|
|
3
3
|
numeral: e,
|
|
4
|
-
|
|
4
|
+
annotation: t,
|
|
5
|
+
mark: n
|
|
5
6
|
};
|
|
6
7
|
//#endregion
|
|
7
|
-
export {
|
|
8
|
+
export { t as annotation, r as default, n as mark, e as numeral };
|
|
8
9
|
|
|
9
10
|
//# sourceMappingURL=Numeral.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Numeral.module.js","names":["numeral","mark","Numeral_module_default"],"sources":["../../../../src/components/typography/Numeral/Numeral.module.css"],"sourcesContent":["/*\n * Figures: --font-numeric, stretched per theme (Ledger's condensed receipt-tape mono),\n * tabular + lining so columns align and live values don't jiggle.\n *\n * Component tokens:\n * --numeral-display-weight default var(--display-weight)\n * --numeral-tracking default 0 (display sizes tighten slightly)\n * --numeral-weight default inherits (a condensed numeric face may want more)\n * --numeral-scale size relative to surrounding text when no `size`, default 1\n */\n.numeral {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-feature-settings:\n 'tnum' 1,\n 'lnum' 1;\n font-size: calc(1em * var(--numeral-scale, 1));\n /* No fallback on purpose: unset → the inherited weight */\n font-weight: var(--numeral-weight);\n letter-spacing: var(--numeral-tracking, 0);\n white-space: nowrap;\n}\n\n.numeral[data-tone] {\n color: var(--_ink);\n}\n.numeral[data-tone='default'] {\n --_ink: var(--color-ink);\n}\n.numeral[data-tone='muted'] {\n --_ink: var(--color-ink-muted);\n}\n.numeral[data-tone='accent'] {\n --_ink: var(--color-accent-text);\n}\n.numeral[data-tone='positive'] {\n --_ink: var(--tone-positive-text);\n}\n.numeral[data-tone='caution'] {\n --_ink: var(--tone-caution-text);\n}\n.numeral[data-tone='critical'] {\n --_ink: var(--tone-critical-text);\n}\n\n.numeral[data-size] {\n font-size: var(--_fs);\n line-height: var(--leading-snug);\n}\n.numeral[data-size='xs'] {\n --_fs: var(--text-xs);\n}\n.numeral[data-size='sm'] {\n --_fs: var(--text-sm);\n}\n.numeral[data-size='md'] {\n --_fs: var(--text-md);\n}\n.numeral[data-size='lg'] {\n --_fs: var(--text-lg);\n}\n.numeral[data-size='xl'] {\n --_fs: var(--text-xl);\n}\n.numeral[data-size='2xl'] {\n --_fs: var(--text-2xl);\n}\n.numeral[data-size='3xl'] {\n --_fs: var(--text-3xl);\n}\n.numeral[data-size='display-sm'] {\n --_fs: var(--text-display-sm);\n}\n.numeral[data-size='display-md'] {\n --_fs: var(--text-display-md);\n}\n.numeral[data-size='display-lg'] {\n --_fs: var(--text-display-lg);\n}\n\n.numeral:is([data-size='2xl'], [data-size='3xl'], [data-size^='display']) {\n font-weight: var(--numeral-display-weight, var(--display-weight));\n letter-spacing: var(--numeral-tracking, -0.015em);\n line-height: max(var(--leading-tight), 1);\n}\n\n/* Separators, currency and units: proportional, so they don't open gaps between digits */\n.mark {\n font-variant-numeric: proportional-nums lining-nums;\n font-feature-settings:\n 'tnum' 0,\n 'lnum' 1;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Numeral.module.js","names":["numeral","annotation","mark","Numeral_module_default"],"sources":["../../../../src/components/typography/Numeral/Numeral.module.css"],"sourcesContent":["/*\n * Figures: --font-numeric, stretched per theme (Ledger's condensed receipt-tape mono),\n * tabular + lining so columns align and live values don't jiggle.\n *\n * Component tokens:\n * --numeral-display-weight default var(--display-weight)\n * --numeral-tracking default 0 (display sizes tighten slightly)\n * --numeral-weight default inherits (a condensed numeric face may want more)\n * --numeral-scale size relative to surrounding text when no `size`, default 1\n */\n.numeral {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-feature-settings:\n 'tnum' 1,\n 'lnum' 1;\n font-size: calc(1em * var(--numeral-scale, 1));\n /* No fallback on purpose: unset → the inherited weight */\n font-weight: var(--numeral-weight);\n letter-spacing: var(--numeral-tracking, 0);\n white-space: nowrap;\n}\n\n.numeral[data-tone] {\n color: var(--_ink);\n}\n.numeral[data-tone='default'] {\n --_ink: var(--color-ink);\n}\n.numeral[data-tone='muted'] {\n --_ink: var(--color-ink-muted);\n}\n.numeral[data-tone='accent'] {\n --_ink: var(--color-accent-text);\n}\n.numeral[data-tone='positive'] {\n --_ink: var(--tone-positive-text);\n}\n.numeral[data-tone='caution'] {\n --_ink: var(--tone-caution-text);\n}\n.numeral[data-tone='critical'] {\n --_ink: var(--tone-critical-text);\n}\n/* Highlight: the figure on the highlight fill, like a marker pen. Its ink is the fill's own. */\n.numeral[data-tone='highlight'] {\n --_ink: var(--color-highlight-ink);\n\n padding-inline: 0.2em;\n border-radius: var(--radius-chip);\n background: var(--color-highlight);\n box-decoration-break: clone;\n}\n\n/* A small figure after the main one, part of the same reading (\"1 (4)\"). */\n.annotation {\n color: var(--color-ink-muted);\n font-size: 0.72em;\n}\n.numeral[data-tone='highlight'] .annotation {\n color: inherit;\n}\n\n.numeral[data-size] {\n font-size: var(--_fs);\n line-height: var(--leading-snug);\n}\n.numeral[data-size='xs'] {\n --_fs: var(--text-xs);\n}\n.numeral[data-size='sm'] {\n --_fs: var(--text-sm);\n}\n.numeral[data-size='md'] {\n --_fs: var(--text-md);\n}\n.numeral[data-size='lg'] {\n --_fs: var(--text-lg);\n}\n.numeral[data-size='xl'] {\n --_fs: var(--text-xl);\n}\n.numeral[data-size='2xl'] {\n --_fs: var(--text-2xl);\n}\n.numeral[data-size='3xl'] {\n --_fs: var(--text-3xl);\n}\n.numeral[data-size='display-sm'] {\n --_fs: var(--text-display-sm);\n}\n.numeral[data-size='display-md'] {\n --_fs: var(--text-display-md);\n}\n.numeral[data-size='display-lg'] {\n --_fs: var(--text-display-lg);\n}\n\n.numeral:is([data-size='2xl'], [data-size='3xl'], [data-size^='display']) {\n font-weight: var(--numeral-display-weight, var(--display-weight));\n letter-spacing: var(--numeral-tracking, -0.015em);\n line-height: max(var(--leading-tight), 1);\n}\n\n/* Separators, currency and units: proportional, so they don't open gaps between digits */\n.mark {\n font-variant-numeric: proportional-nums lining-nums;\n font-feature-settings:\n 'tnum' 0,\n 'lnum' 1;\n}\n"],"mappings":""}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
2
|
import { type Responsive } from '../../../utils/responsive.js';
|
|
3
3
|
export type TextSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
|
-
export type TextTone = 'default' | 'muted' | 'subtle' | 'accent' | 'positive' | 'caution' | 'critical' | 'inverse';
|
|
4
|
+
export type TextTone = 'default' | 'muted' | 'subtle' | 'accent' | 'positive' | 'caution' | 'critical' | 'inverse' | 'highlight';
|
|
5
5
|
export type TextWeight = 'regular' | 'medium' | 'strong';
|
|
6
6
|
export type TextAlign = 'start' | 'center' | 'end';
|
|
7
7
|
/** Line-length cap from the width tokens: `narrow` 32rem · `text` 42rem · `content` 68rem. */
|
|
@@ -10,7 +10,10 @@ export type TextElement = 'p' | 'span' | 'div' | 'label' | 'strong' | 'em' | 'sm
|
|
|
10
10
|
export interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
11
11
|
/** Step on the type scale. Omit to inherit the surrounding size. Responsive. */
|
|
12
12
|
size?: Responsive<TextSize>;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Colour role. Omit to inherit. Status tones use the AA-safe `-text` variants. `highlight`
|
|
15
|
+
* sets the text on the theme's highlight, like a marker pen.
|
|
16
|
+
*/
|
|
14
17
|
tone?: TextTone;
|
|
15
18
|
/** Omit to inherit (so `as="strong"` stays bold). */
|
|
16
19
|
weight?: TextWeight;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Text.js","names":["styles","Text_module_default","Text","forwardRef","Comp","rest","lines","truncate","responsive","size","cx","className","baseValue","tone","weight","numeric","align","measure","mergeStyles","responsiveVars","s","style"],"sources":["../../../../src/components/typography/Text/Text.tsx"],"sourcesContent":["import { forwardRef, type CSSProperties, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { baseValue, mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport styles from './Text.module.css'\n\nexport type TextSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type TextTone =\n 'default'
|
|
1
|
+
{"version":3,"file":"Text.js","names":["styles","Text_module_default","Text","forwardRef","Comp","rest","lines","truncate","responsive","size","cx","className","baseValue","tone","weight","numeric","align","measure","mergeStyles","responsiveVars","s","style"],"sources":["../../../../src/components/typography/Text/Text.tsx"],"sourcesContent":["import { forwardRef, type CSSProperties, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { baseValue, mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport styles from './Text.module.css'\n\nexport type TextSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type TextTone =\n | 'default'\n | 'muted'\n | 'subtle'\n | 'accent'\n | 'positive'\n | 'caution'\n | 'critical'\n | 'inverse'\n | 'highlight'\nexport type TextWeight = 'regular' | 'medium' | 'strong'\nexport type TextAlign = 'start' | 'center' | 'end'\n/** Line-length cap from the width tokens: `narrow` 32rem · `text` 42rem · `content` 68rem. */\nexport type TextMeasure = 'narrow' | 'text' | 'content'\nexport type TextElement = 'p' | 'span' | 'div' | 'label' | 'strong' | 'em' | 'small' | 'time'\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n /** Step on the type scale. Omit to inherit the surrounding size. Responsive. */\n size?: Responsive<TextSize>\n /**\n * Colour role. Omit to inherit. Status tones use the AA-safe `-text` variants. `highlight`\n * sets the text on the theme's highlight, like a marker pen.\n */\n tone?: TextTone\n /** Omit to inherit (so `as=\"strong\"` stays bold). */\n weight?: TextWeight\n /** Tabular lining figures in the theme's numeric face — for anything that aligns or updates. */\n numeric?: boolean\n /** `true` clips to one line with an ellipsis; a number clamps to that many lines. */\n truncate?: boolean | number\n align?: TextAlign\n /** Cap the line length with a `--width-*` token (`max-inline-size`). Default: none. */\n measure?: TextMeasure\n as?: TextElement\n /** For `as=\"label\"`. */\n htmlFor?: string\n /** For `as=\"time\"`. */\n dateTime?: string\n}\n\n/**\n * Body text in the theme's text face, with a size, tone and weight from the scale.\n *\n * @remarks\n * `Text` is a paragraph by default and any inline element with `as` (`span`, `strong`, `em`,\n * `small`, `label`, `time`). Size, tone, weight and measure are props, so text never needs a\n * class.\n *\n * @privateRemarks\n * Body text. Paragraphs by default; any inline role via `as`.\n *\n * <Text size=\"sm\" tone=\"muted\">Updated 3 minutes ago</Text>\n */\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text(\n {\n size,\n tone,\n weight,\n numeric = false,\n truncate,\n align,\n measure,\n as: Comp = 'p',\n className,\n style,\n ...rest\n },\n ref,\n) {\n const lines =\n truncate === true ? 1 : typeof truncate === 'number' && truncate > 0 ? truncate : undefined\n const responsive = size !== undefined && typeof size !== 'string'\n return (\n <Comp\n // @ts-expect-error — polymorphic ref across a union of intrinsic elements is safe here\n ref={ref}\n className={cx(styles.text, className)}\n data-size={baseValue(size)}\n data-responsive={responsive || undefined}\n data-tone={tone}\n data-weight={weight}\n data-numeric={numeric || undefined}\n data-truncate={lines === undefined ? undefined : lines === 1 ? 'line' : 'lines'}\n data-align={align}\n data-measure={measure}\n style={mergeStyles(\n responsive ? responsiveVars('text-size', size, (s) => `var(--text-${s})`) : undefined,\n lines !== undefined && lines > 1 ? ({ '--text-lines': lines } as CSSProperties) : undefined,\n style,\n )}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;AA2DA,IAAaE,IAAOC,EAAmC,SACrD,EACE,SACA,SACA,WACA,aAAU,IACV,aACA,UACA,YACA,IAAIC,IAAO,KACX,cACA,UACA,GAAGC,KAEL,GACA;CACA,IAAMC,IACJC,MAAa,KAAO,IAAI,OAAOA,KAAa,YAAYA,IAAW,IAAIA,IAAW,KAAA,GAC9EC,IAAaC,MAAS,KAAA,KAAa,OAAOA,KAAS;CACzD,OACE,kBAACL,GAAD;EAEO;EACL,WAAWM,EAAGV,EAAO,MAAMW,CAAS;EACpC,aAAWC,EAAUH,CAAI;EACzB,mBAAiBD,KAAc,KAAA;EAC/B,aAAWK;EACX,eAAaC;EACb,gBAAcC,KAAW,KAAA;EACzB,iBAAeT,MAAU,KAAA,IAAY,KAAA,IAAYA,MAAU,IAAI,SAAS;EACxE,cAAYU;EACZ,gBAAcC;EACd,OAAOC,EACLV,IAAaW,EAAe,aAAaV,IAAO,MAAM,cAAcW,EAAE,EAAE,IAAI,KAAA,GAC5Ed,MAAU,KAAA,KAAaA,IAAQ,IAAK,EAAE,gBAAgBA,EAAM,IAAsB,KAAA,GAClFe,CACF;EACA,GAAIhB;CACL,CAAA;AAEL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Text.module.js","names":["text","Text_module_default"],"sources":["../../../../src/components/typography/Text/Text.module.css"],"sourcesContent":["/*\n * Body text. Everything is opt-in: with no props a <Text> inherits size, colour and\n * weight, so it composes inside buttons, table cells and list rows.\n * Responsive size reads --text-size-{base..xl} (Stack pattern) when data-responsive.\n *\n * Component tokens:\n * --text-weight-medium default 500\n * --text-weight-strong default 650\n */\n.text {\n --_lh: var(--leading-body);\n margin: 0;\n}\n.text[data-tone] {\n color: var(--_ink);\n}\n\n/* Scalar sizes */\n.text[data-size] {\n font-size: var(--_fs);\n line-height: var(--_lh);\n}\n.text[data-size='2xs'] {\n --_fs: var(--text-2xs);\n}\n.text[data-size='xs'] {\n --_fs: var(--text-xs);\n}\n.text[data-size='sm'] {\n --_fs: var(--text-sm);\n}\n.text[data-size='md'] {\n --_fs: var(--text-md);\n}\n.text[data-size='lg'] {\n --_fs: var(--text-lg);\n --_lh: calc((var(--leading-body) + var(--leading-snug)) / 2);\n}\n.text[data-size='xl'] {\n --_fs: var(--text-xl);\n --_lh: var(--leading-snug);\n}\n\n/* Responsive sizes */\n.text[data-responsive] {\n --_fs: var(--text-size-base);\n}\n@media (min-width: 40em) {\n .text[data-responsive] {\n --_fs: var(--text-size-sm);\n }\n}\n@media (min-width: 48em) {\n .text[data-responsive] {\n --_fs: var(--text-size-md);\n }\n}\n@media (min-width: 64em) {\n .text[data-responsive] {\n --_fs: var(--text-size-lg);\n }\n}\n@media (min-width: 80em) {\n .text[data-responsive] {\n --_fs: var(--text-size-xl);\n }\n}\n\n/* Tones */\n.text[data-tone='default'] {\n --_ink: var(--color-ink);\n}\n.text[data-tone='muted'] {\n --_ink: var(--color-ink-muted);\n}\n.text[data-tone='subtle'] {\n --_ink: var(--color-ink-subtle);\n}\n.text[data-tone='accent'] {\n --_ink: var(--color-accent-text);\n}\n.text[data-tone='positive'] {\n --_ink: var(--tone-positive-text);\n}\n.text[data-tone='caution'] {\n --_ink: var(--tone-caution-text);\n}\n.text[data-tone='critical'] {\n --_ink: var(--tone-critical-text);\n}\n.text[data-tone='inverse'] {\n --_ink: var(--color-ink-inverse);\n}\n\n/* Weights */\n.text[data-weight='regular'] {\n font-weight: 400;\n}\n.text[data-weight='medium'] {\n font-weight: var(--text-weight-medium, 500);\n}\n.text[data-weight='strong'] {\n font-weight: var(--text-weight-strong, 650);\n}\n\n/* Numbers: the theme's figure face, always tabular + lining */\n.text[data-numeric] {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-feature-settings:\n 'tnum' 1,\n 'lnum' 1;\n}\n\n/* Alignment */\n.text[data-align='start'] {\n text-align: start;\n}\n.text[data-align='center'] {\n text-align: center;\n}\n.text[data-align='end'] {\n text-align: end;\n}\n\n/* Truncation */\n.text[data-truncate='line'] {\n display: block;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n min-inline-size: 0;\n}\n.text[data-truncate='lines'] {\n display: -webkit-box;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--text-lines);\n line-clamp: var(--text-lines);\n}\n\n/* Measure: cap the line length with the width tokens. */\n.text[data-measure='narrow'] {\n max-inline-size: var(--width-narrow);\n}\n.text[data-measure='text'] {\n max-inline-size: var(--width-text);\n}\n.text[data-measure='content'] {\n max-inline-size: var(--width-content);\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Text.module.js","names":["text","Text_module_default"],"sources":["../../../../src/components/typography/Text/Text.module.css"],"sourcesContent":["/*\n * Body text. Everything is opt-in: with no props a <Text> inherits size, colour and\n * weight, so it composes inside buttons, table cells and list rows.\n * Responsive size reads --text-size-{base..xl} (Stack pattern) when data-responsive.\n *\n * Component tokens:\n * --text-weight-medium default 500\n * --text-weight-strong default 650\n */\n.text {\n --_lh: var(--leading-body);\n margin: 0;\n}\n.text[data-tone] {\n color: var(--_ink);\n}\n\n/* Scalar sizes */\n.text[data-size] {\n font-size: var(--_fs);\n line-height: var(--_lh);\n}\n.text[data-size='2xs'] {\n --_fs: var(--text-2xs);\n}\n.text[data-size='xs'] {\n --_fs: var(--text-xs);\n}\n.text[data-size='sm'] {\n --_fs: var(--text-sm);\n}\n.text[data-size='md'] {\n --_fs: var(--text-md);\n}\n.text[data-size='lg'] {\n --_fs: var(--text-lg);\n --_lh: calc((var(--leading-body) + var(--leading-snug)) / 2);\n}\n.text[data-size='xl'] {\n --_fs: var(--text-xl);\n --_lh: var(--leading-snug);\n}\n\n/* Responsive sizes */\n.text[data-responsive] {\n --_fs: var(--text-size-base);\n}\n@media (min-width: 40em) {\n .text[data-responsive] {\n --_fs: var(--text-size-sm);\n }\n}\n@media (min-width: 48em) {\n .text[data-responsive] {\n --_fs: var(--text-size-md);\n }\n}\n@media (min-width: 64em) {\n .text[data-responsive] {\n --_fs: var(--text-size-lg);\n }\n}\n@media (min-width: 80em) {\n .text[data-responsive] {\n --_fs: var(--text-size-xl);\n }\n}\n\n/* Tones */\n.text[data-tone='default'] {\n --_ink: var(--color-ink);\n}\n.text[data-tone='muted'] {\n --_ink: var(--color-ink-muted);\n}\n.text[data-tone='subtle'] {\n --_ink: var(--color-ink-subtle);\n}\n.text[data-tone='accent'] {\n --_ink: var(--color-accent-text);\n}\n.text[data-tone='positive'] {\n --_ink: var(--tone-positive-text);\n}\n.text[data-tone='caution'] {\n --_ink: var(--tone-caution-text);\n}\n.text[data-tone='critical'] {\n --_ink: var(--tone-critical-text);\n}\n.text[data-tone='inverse'] {\n --_ink: var(--color-ink-inverse);\n}\n/* Highlight: on the highlight fill, like a marker pen. Its ink is the fill's own. */\n.text[data-tone='highlight'] {\n --_ink: var(--color-highlight-ink);\n\n padding-inline: 0.2em;\n border-radius: var(--radius-chip);\n background: var(--color-highlight);\n box-decoration-break: clone;\n}\n\n/* Weights */\n.text[data-weight='regular'] {\n font-weight: 400;\n}\n.text[data-weight='medium'] {\n font-weight: var(--text-weight-medium, 500);\n}\n.text[data-weight='strong'] {\n font-weight: var(--text-weight-strong, 650);\n}\n\n/* Numbers: the theme's figure face, always tabular + lining */\n.text[data-numeric] {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n font-feature-settings:\n 'tnum' 1,\n 'lnum' 1;\n}\n\n/* Alignment */\n.text[data-align='start'] {\n text-align: start;\n}\n.text[data-align='center'] {\n text-align: center;\n}\n.text[data-align='end'] {\n text-align: end;\n}\n\n/* Truncation */\n.text[data-truncate='line'] {\n display: block;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n min-inline-size: 0;\n}\n.text[data-truncate='lines'] {\n display: -webkit-box;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--text-lines);\n line-clamp: var(--text-lines);\n}\n\n/* Measure: cap the line length with the width tokens. */\n.text[data-measure='narrow'] {\n max-inline-size: var(--width-narrow);\n}\n.text[data-measure='text'] {\n max-inline-size: var(--width-text);\n}\n.text[data-measure='content'] {\n max-inline-size: var(--width-content);\n}\n"],"mappings":""}
|
package/dist/icons/Icon.js
CHANGED
|
@@ -3,6 +3,7 @@ import t from "./Icon.module.js";
|
|
|
3
3
|
import { forwardRef as n } from "react";
|
|
4
4
|
import { jsx as r } from "react/jsx-runtime";
|
|
5
5
|
//#region src/icons/Icon.tsx
|
|
6
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
6
7
|
function i(i, a) {
|
|
7
8
|
let o = n(function({ size: n = "inherit", label: i, className: o, ...s }, c) {
|
|
8
9
|
return /* @__PURE__ */ r("svg", {
|
package/dist/icons/Icon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.js","names":["styles","Icon_module_default","createIcon","Component","forwardRef","rest","cx","className","size","label","paths","displayName"],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { forwardRef, type SVGProps } from 'react'\nimport { cx } from '#utils/cx'\nimport styles from './Icon.module.css'\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'inherit'\n\nexport interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {\n /** `inherit` (default) sizes to the surrounding font-size (1em). */\n size?: IconSize\n /** Accessible name. Omit for decorative icons (the default) — they're aria-hidden. */\n label?: string\n}\n\n/**\n * Base for the library's own glyphs. 20×20 grid, stroke weight is a theme token\n * (`--icon-stroke`), so Fiesta icons are chunky and Flightdeck icons are fine-lined.\n * Consumers may pass any SVG/icon node where a component accepts `icon` props.\n */\nexport function createIcon(displayName: string, paths: React.ReactNode) {\n const Component = forwardRef<SVGSVGElement, IconProps>(function Icon(\n { size = 'inherit', label, className, ...rest },\n ref,\n ) {\n return (\n <svg\n ref={ref}\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cx(styles.icon, className)}\n data-size={size}\n aria-hidden={label ? undefined : true}\n aria-label={label}\n role={label ? 'img' : undefined}\n focusable=\"false\"\n {...rest}\n >\n {paths}\n </svg>\n )\n })\n Component.displayName = displayName\n return Component\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Icon.js","names":["styles","Icon_module_default","createIcon","Component","forwardRef","rest","cx","className","size","label","paths","displayName"],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { forwardRef, type SVGProps } from 'react'\nimport { cx } from '#utils/cx'\nimport styles from './Icon.module.css'\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'inherit'\n\nexport interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {\n /** `inherit` (default) sizes to the surrounding font-size (1em). */\n size?: IconSize\n /** Accessible name. Omit for decorative icons (the default) — they're aria-hidden. */\n label?: string\n}\n\n/**\n * Base for the library's own glyphs. 20×20 grid, stroke weight is a theme token\n * (`--icon-stroke`), so Fiesta icons are chunky and Flightdeck icons are fine-lined.\n * Consumers may pass any SVG/icon node where a component accepts `icon` props.\n */\n// Marked side-effect free so a bundler drops every icon an app doesn't import.\n/* @__NO_SIDE_EFFECTS__ */\nexport function createIcon(displayName: string, paths: React.ReactNode) {\n const Component = forwardRef<SVGSVGElement, IconProps>(function Icon(\n { size = 'inherit', label, className, ...rest },\n ref,\n ) {\n return (\n <svg\n ref={ref}\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cx(styles.icon, className)}\n data-size={size}\n aria-hidden={label ? undefined : true}\n aria-label={label}\n role={label ? 'img' : undefined}\n focusable=\"false\"\n {...rest}\n >\n {paths}\n </svg>\n )\n })\n Component.displayName = displayName\n return Component\n}\n"],"mappings":";;;;;;AAoBA,SAAgBE,EAAW,GAAqB,GAAwB;CACtE,IAAMC,IAAYC,EAAqC,SACrD,EAAE,UAAO,WAAW,UAAO,cAAW,GAAGC,KACzC,GACA;EACA,OACE,kBAAC,OAAD;GACO;GACL,SAAQ;GACR,MAAK;GACL,QAAO;GACP,eAAc;GACd,gBAAe;GACf,WAAWC,EAAGN,EAAO,MAAMO,CAAS;GACpC,aAAWC;GACX,eAAa,MAAQ,KAAA;GACrB,cAAYC;GACZ,MAAMA,IAAQ,QAAQ,KAAA;GACtB,WAAU;GACV,GAAIJ;GAEH,UAAAK;EACE,CAAA;CAET,CAAC;CAED,OADA,EAAU,cAAcC,GACjBR;AACT"}
|
package/dist/icons/icons.d.ts
CHANGED
|
@@ -24,3 +24,15 @@ export declare const StarIcon: import("react").ForwardRefExoticComponent<import(
|
|
|
24
24
|
export declare const EyeIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
25
25
|
export declare const EyeOffIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
26
26
|
export declare const UploadIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
27
|
+
export declare const TrophyIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
28
|
+
export declare const CalendarIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
29
|
+
export declare const UsersIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
30
|
+
export declare const SwordsIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
31
|
+
export declare const HelpIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
32
|
+
export declare const ClockIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
33
|
+
export declare const ZapIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
34
|
+
export declare const MessageIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
35
|
+
export declare const RadioIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
36
|
+
export declare const ShieldIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
37
|
+
export declare const TargetIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
38
|
+
export declare const TrendingUpIcon: import("react").ForwardRefExoticComponent<import("./Icon.js").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|