@chayns-ui/core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +51 -1
  2. package/dist/avatar.css +104 -0
  3. package/dist/components/accordion/Accordion.d.ts +1 -1
  4. package/dist/components/accordion/Accordion.d.ts.map +1 -1
  5. package/dist/components/accordion/Accordion.js +2 -2
  6. package/dist/components/accordion/Accordion.js.map +1 -1
  7. package/dist/components/accordion/Accordion.types.d.ts +61 -16
  8. package/dist/components/accordion/Accordion.types.d.ts.map +1 -1
  9. package/dist/components/accordion-group/AccordionGroup.d.ts +4 -0
  10. package/dist/components/accordion-group/AccordionGroup.d.ts.map +1 -0
  11. package/dist/components/{accordion → accordion-group}/AccordionGroup.js +4 -4
  12. package/dist/components/accordion-group/AccordionGroup.js.map +1 -0
  13. package/dist/components/avatar/Avatar.d.ts +4 -0
  14. package/dist/components/avatar/Avatar.d.ts.map +1 -0
  15. package/dist/components/avatar/Avatar.js +48 -0
  16. package/dist/components/avatar/Avatar.js.map +1 -0
  17. package/dist/components/avatar/Avatar.types.d.ts +46 -0
  18. package/dist/components/avatar/Avatar.types.d.ts.map +1 -0
  19. package/dist/components/avatar-group/AvatarGroup.d.ts +4 -0
  20. package/dist/components/avatar-group/AvatarGroup.d.ts.map +1 -0
  21. package/dist/components/avatar-group/AvatarGroup.js +26 -0
  22. package/dist/components/avatar-group/AvatarGroup.js.map +1 -0
  23. package/dist/components/avatar-group/AvatarGroup.types.d.ts +33 -0
  24. package/dist/components/avatar-group/AvatarGroup.types.d.ts.map +1 -0
  25. package/dist/components/button/Button.d.ts.map +1 -1
  26. package/dist/components/button/Button.js +6 -3
  27. package/dist/components/button/Button.js.map +1 -1
  28. package/dist/components/button/Button.types.d.ts +39 -25
  29. package/dist/components/button/Button.types.d.ts.map +1 -1
  30. package/dist/components/button/button-icon/ButtonIcon.d.ts +7 -0
  31. package/dist/components/button/button-icon/ButtonIcon.d.ts.map +1 -0
  32. package/dist/components/button/button-icon/ButtonIcon.js +17 -0
  33. package/dist/components/button/button-icon/ButtonIcon.js.map +1 -0
  34. package/dist/components/card/Card.d.ts +1 -1
  35. package/dist/components/card/Card.d.ts.map +1 -1
  36. package/dist/components/card/Card.js +2 -2
  37. package/dist/components/card/Card.js.map +1 -1
  38. package/dist/components/card/Card.types.d.ts +16 -3
  39. package/dist/components/card/Card.types.d.ts.map +1 -1
  40. package/dist/components/{button → icon-button}/IconButton.d.ts +1 -1
  41. package/dist/components/icon-button/IconButton.d.ts.map +1 -0
  42. package/dist/components/{button → icon-button}/IconButton.js +7 -4
  43. package/dist/components/icon-button/IconButton.js.map +1 -0
  44. package/dist/components/icon-button/IconButton.types.d.ts +43 -0
  45. package/dist/components/icon-button/IconButton.types.d.ts.map +1 -0
  46. package/dist/components/list/List.d.ts +1 -1
  47. package/dist/components/list/List.d.ts.map +1 -1
  48. package/dist/components/list/List.js +2 -2
  49. package/dist/components/list/List.js.map +1 -1
  50. package/dist/components/list/List.types.d.ts +62 -14
  51. package/dist/components/list/List.types.d.ts.map +1 -1
  52. package/dist/components/list-item/ListItem.d.ts +4 -0
  53. package/dist/components/list-item/ListItem.d.ts.map +1 -0
  54. package/dist/components/list-item/ListItem.js +42 -0
  55. package/dist/components/list-item/ListItem.js.map +1 -0
  56. package/dist/components/list-item/list-item-body/ListItemBody.d.ts +10 -0
  57. package/dist/components/list-item/list-item-body/ListItemBody.d.ts.map +1 -0
  58. package/dist/components/list-item/list-item-body/ListItemBody.js +30 -0
  59. package/dist/components/list-item/list-item-body/ListItemBody.js.map +1 -0
  60. package/dist/components/popup/Popup.d.ts +4 -0
  61. package/dist/components/popup/Popup.d.ts.map +1 -0
  62. package/dist/components/popup/Popup.js +107 -0
  63. package/dist/components/popup/Popup.js.map +1 -0
  64. package/dist/components/popup/Popup.types.d.ts +18 -0
  65. package/dist/components/popup/Popup.types.d.ts.map +1 -0
  66. package/dist/components/popup/PopupList.d.ts +4 -0
  67. package/dist/components/popup/PopupList.d.ts.map +1 -0
  68. package/dist/components/popup/PopupList.js +44 -0
  69. package/dist/components/popup/PopupList.js.map +1 -0
  70. package/dist/components/split-button/SplitButton.d.ts +4 -0
  71. package/dist/components/split-button/SplitButton.d.ts.map +1 -0
  72. package/dist/components/split-button/SplitButton.js +52 -0
  73. package/dist/components/split-button/SplitButton.js.map +1 -0
  74. package/dist/components/split-button/SplitButton.types.d.ts +12 -0
  75. package/dist/components/split-button/SplitButton.types.d.ts.map +1 -0
  76. package/dist/index.d.ts +21 -8
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +9 -4
  79. package/dist/list.css +8 -1
  80. package/dist/popup.css +34 -0
  81. package/dist/split-button.css +128 -0
  82. package/dist/styles.css +3 -0
  83. package/package.json +11 -19
  84. package/dist/components/accordion/AccordionGroup.d.ts +0 -4
  85. package/dist/components/accordion/AccordionGroup.d.ts.map +0 -1
  86. package/dist/components/accordion/AccordionGroup.js.map +0 -1
  87. package/dist/components/accordion/index.d.ts +0 -4
  88. package/dist/components/accordion/index.d.ts.map +0 -1
  89. package/dist/components/accordion/index.js +0 -3
  90. package/dist/components/button/ButtonIcon.d.ts +0 -7
  91. package/dist/components/button/ButtonIcon.d.ts.map +0 -1
  92. package/dist/components/button/ButtonIcon.js +0 -19
  93. package/dist/components/button/ButtonIcon.js.map +0 -1
  94. package/dist/components/button/IconButton.d.ts.map +0 -1
  95. package/dist/components/button/IconButton.js.map +0 -1
  96. package/dist/components/button/buttonClassName.d.ts +0 -3
  97. package/dist/components/button/buttonClassName.d.ts.map +0 -1
  98. package/dist/components/button/buttonClassName.js +0 -9
  99. package/dist/components/button/buttonClassName.js.map +0 -1
  100. package/dist/components/button/index.d.ts +0 -4
  101. package/dist/components/button/index.d.ts.map +0 -1
  102. package/dist/components/button/index.js +0 -3
  103. package/dist/components/card/index.d.ts +0 -3
  104. package/dist/components/card/index.d.ts.map +0 -1
  105. package/dist/components/card/index.js +0 -2
  106. package/dist/components/list/ListItem.d.ts +0 -4
  107. package/dist/components/list/ListItem.d.ts.map +0 -1
  108. package/dist/components/list/ListItem.js +0 -67
  109. package/dist/components/list/ListItem.js.map +0 -1
  110. package/dist/components/list/index.d.ts +0 -4
  111. package/dist/components/list/index.d.ts.map +0 -1
  112. package/dist/components/list/index.js +0 -3
@@ -0,0 +1,107 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { cloneElement, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
3
+ import { createPortal } from "react-dom";
4
+ //#region src/components/popup/Popup.tsx
5
+ var Popup = ({ children, className, trigger }) => {
6
+ const [open, setOpen] = useState(false);
7
+ const [position, setPosition] = useState({
8
+ left: 0,
9
+ top: 0
10
+ });
11
+ const triggerRef = useRef(null);
12
+ const popupRef = useRef(null);
13
+ const popupId = useId();
14
+ const updatePosition = () => {
15
+ const anchor = triggerRef.current;
16
+ if (!anchor) return;
17
+ const rect = anchor.getBoundingClientRect();
18
+ const popup = popupRef.current;
19
+ const popupWidth = popup?.offsetWidth ?? 0;
20
+ const popupHeight = popup?.offsetHeight ?? 0;
21
+ const gap = 8;
22
+ const margin = 8;
23
+ const left = Math.min(Math.max(margin, rect.left), Math.max(margin, window.innerWidth - popupWidth - margin));
24
+ const below = rect.bottom + gap;
25
+ const top = below + popupHeight <= window.innerHeight - margin ? below : Math.max(margin, rect.top - popupHeight - gap);
26
+ setPosition({
27
+ left,
28
+ top
29
+ });
30
+ };
31
+ const close = (restoreFocus) => {
32
+ setOpen(false);
33
+ if (restoreFocus) queueMicrotask(() => triggerRef.current?.focus());
34
+ };
35
+ const setTriggerRef = useCallback((node) => {
36
+ triggerRef.current = node;
37
+ }, []);
38
+ useLayoutEffect(() => {
39
+ if (!open) return;
40
+ updatePosition();
41
+ (popupRef.current?.querySelector("[role=\"menuitem\"]"))?.focus();
42
+ }, [open]);
43
+ useEffect(() => {
44
+ if (!open) return;
45
+ const handlePointerDown = (event) => {
46
+ const target = event.target;
47
+ if (target instanceof Node && !triggerRef.current?.contains(target) && !popupRef.current?.contains(target)) close(false);
48
+ };
49
+ const handleKeyDown = (event) => {
50
+ if (event.key === "Escape") {
51
+ event.preventDefault();
52
+ close(true);
53
+ }
54
+ if (event.key === "Tab") close(false);
55
+ };
56
+ const handleViewportChange = () => updatePosition();
57
+ const handlePopupClick = (event) => {
58
+ if (event.target.closest("[role=\"menuitem\"]")) close(true);
59
+ };
60
+ const popupElement = popupRef.current;
61
+ document.addEventListener("pointerdown", handlePointerDown);
62
+ document.addEventListener("keydown", handleKeyDown);
63
+ window.addEventListener("resize", handleViewportChange);
64
+ window.addEventListener("scroll", handleViewportChange, true);
65
+ popupElement?.addEventListener("click", handlePopupClick);
66
+ return () => {
67
+ document.removeEventListener("pointerdown", handlePointerDown);
68
+ document.removeEventListener("keydown", handleKeyDown);
69
+ window.removeEventListener("resize", handleViewportChange);
70
+ window.removeEventListener("scroll", handleViewportChange, true);
71
+ popupElement?.removeEventListener("click", handlePopupClick);
72
+ };
73
+ }, [open]);
74
+ const triggerElement = trigger;
75
+ const enhancedTrigger = cloneElement(triggerElement, {
76
+ "aria-controls": popupId,
77
+ "aria-expanded": open,
78
+ "aria-haspopup": "menu",
79
+ onClick: (event) => {
80
+ triggerElement.props.onClick?.(event);
81
+ if (!event.defaultPrevented) setOpen((value) => !value);
82
+ },
83
+ onKeyDown: (event) => {
84
+ triggerElement.props.onKeyDown?.(event);
85
+ if (event.defaultPrevented) return;
86
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
87
+ event.preventDefault();
88
+ setOpen(true);
89
+ }
90
+ },
91
+ ref: setTriggerRef
92
+ });
93
+ return /* @__PURE__ */ jsxs(Fragment, { children: [enhancedTrigger, open ? createPortal(/* @__PURE__ */ jsx("div", {
94
+ className: ["chayns-popup", className].filter(Boolean).join(" "),
95
+ id: popupId,
96
+ ref: popupRef,
97
+ style: {
98
+ left: position.left,
99
+ top: position.top
100
+ },
101
+ children
102
+ }), document.body) : null] });
103
+ };
104
+ //#endregion
105
+ export { Popup as default };
106
+
107
+ //# sourceMappingURL=Popup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popup.js","names":[],"sources":["../../../src/components/popup/Popup.tsx"],"sourcesContent":["import {\n cloneElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent,\n type MouseEvent,\n type Ref,\n type ReactElement,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport type { PopupProps } from './Popup.types.js';\n\ninterface PopupTriggerProps {\n 'aria-controls'?: string;\n 'aria-expanded'?: boolean;\n 'aria-haspopup'?: string;\n onClick?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n}\n\ntype PopupTriggerElement = ReactElement<PopupTriggerProps & { ref?: Ref<HTMLElement> }>;\nconst Popup = ({ children, className, trigger }: PopupProps) => {\n const [open, setOpen] = useState(false);\n const [position, setPosition] = useState({ left: 0, top: 0 });\n const triggerRef = useRef<HTMLElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n const popupId = useId();\n\n const updatePosition = () => {\n const anchor = triggerRef.current;\n if (!anchor) return;\n\n const rect = anchor.getBoundingClientRect();\n const popup = popupRef.current;\n const popupWidth = popup?.offsetWidth ?? 0;\n const popupHeight = popup?.offsetHeight ?? 0;\n const gap = 8;\n const margin = 8;\n const left = Math.min(\n Math.max(margin, rect.left),\n Math.max(margin, window.innerWidth - popupWidth - margin),\n );\n const below = rect.bottom + gap;\n const top =\n below + popupHeight <= window.innerHeight - margin\n ? below\n : Math.max(margin, rect.top - popupHeight - gap);\n\n setPosition({ left, top });\n };\n\n const close = (restoreFocus: boolean) => {\n setOpen(false);\n if (restoreFocus) {\n queueMicrotask(() => triggerRef.current?.focus());\n }\n };\n\n const setTriggerRef = useCallback((node: HTMLElement | null) => {\n triggerRef.current = node;\n }, []);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n const firstItem = popupRef.current?.querySelector<HTMLElement>('[role=\"menuitem\"]');\n firstItem?.focus();\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target;\n if (\n target instanceof Node &&\n !triggerRef.current?.contains(target) &&\n !popupRef.current?.contains(target)\n ) {\n close(false);\n }\n };\n const handleKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n close(true);\n }\n if (event.key === 'Tab') close(false);\n };\n const handleViewportChange = () => updatePosition();\n const handlePopupClick = (event: globalThis.MouseEvent) => {\n if ((event.target as HTMLElement).closest('[role=\"menuitem\"]')) {\n close(true);\n }\n };\n\n const popupElement = popupRef.current;\n\n document.addEventListener('pointerdown', handlePointerDown);\n document.addEventListener('keydown', handleKeyDown);\n window.addEventListener('resize', handleViewportChange);\n window.addEventListener('scroll', handleViewportChange, true);\n popupElement?.addEventListener('click', handlePopupClick);\n\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('resize', handleViewportChange);\n window.removeEventListener('scroll', handleViewportChange, true);\n popupElement?.removeEventListener('click', handlePopupClick);\n };\n }, [open]);\n\n const triggerElement = trigger as PopupTriggerElement;\n // cloneElement forwards `ref` as a plain prop to merge it with the trigger's own ref; the ref\n // is never read during this render, only later by React when attaching the trigger DOM node.\n // eslint-disable-next-line react-hooks/refs\n const enhancedTrigger = cloneElement(triggerElement, {\n 'aria-controls': popupId,\n 'aria-expanded': open,\n 'aria-haspopup': 'menu',\n onClick: (event: React.MouseEvent) => {\n triggerElement.props.onClick?.(event);\n if (!event.defaultPrevented) setOpen((value) => !value);\n },\n onKeyDown: (event: KeyboardEvent) => {\n triggerElement.props.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n setOpen(true);\n }\n },\n ref: setTriggerRef,\n });\n\n return (\n <>\n {enhancedTrigger}\n {open\n ? createPortal(\n <div\n className={['chayns-popup', className].filter(Boolean).join(' ')}\n id={popupId}\n ref={popupRef}\n style={{ left: position.left, top: position.top }}\n >\n {children}\n </div>,\n document.body,\n )\n : null}\n </>\n );\n};\n\nexport default Popup;\n"],"mappings":";;;;AA0BA,IAAM,SAAS,EAAE,UAAU,WAAW,cAA0B;CAC9D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,UAAU,eAAe,SAAS;EAAE,MAAM;EAAG,KAAK;CAAE,CAAC;CAC5D,MAAM,aAAa,OAAoB,IAAI;CAC3C,MAAM,WAAW,OAAuB,IAAI;CAC5C,MAAM,UAAU,MAAM;CAEtB,MAAM,uBAAuB;EAC3B,MAAM,SAAS,WAAW;EAC1B,IAAI,CAAC,QAAQ;EAEb,MAAM,OAAO,OAAO,sBAAsB;EAC1C,MAAM,QAAQ,SAAS;EACvB,MAAM,aAAa,OAAO,eAAe;EACzC,MAAM,cAAc,OAAO,gBAAgB;EAC3C,MAAM,MAAM;EACZ,MAAM,SAAS;EACf,MAAM,OAAO,KAAK,IAChB,KAAK,IAAI,QAAQ,KAAK,IAAI,GAC1B,KAAK,IAAI,QAAQ,OAAO,aAAa,aAAa,MAAM,CAC1D;EACA,MAAM,QAAQ,KAAK,SAAS;EAC5B,MAAM,MACJ,QAAQ,eAAe,OAAO,cAAc,SACxC,QACA,KAAK,IAAI,QAAQ,KAAK,MAAM,cAAc,GAAG;EAEnD,YAAY;GAAE;GAAM;EAAI,CAAC;CAC3B;CAEA,MAAM,SAAS,iBAA0B;EACvC,QAAQ,KAAK;EACb,IAAI,cACF,qBAAqB,WAAW,SAAS,MAAM,CAAC;CAEpD;CAEA,MAAM,gBAAgB,aAAa,SAA6B;EAC9D,WAAW,UAAU;CACvB,GAAG,CAAC,CAAC;CAEL,sBAAsB;EACpB,IAAI,CAAC,MAAM;EACX,eAAe;EAEf,CADkB,SAAS,SAAS,cAA2B,qBAAmB,EAAA,EACvE,MAAM;CACnB,GAAG,CAAC,IAAI,CAAC;CAET,gBAAgB;EACd,IAAI,CAAC,MAAM;EAEX,MAAM,qBAAqB,UAAwB;GACjD,MAAM,SAAS,MAAM;GACrB,IACE,kBAAkB,QAClB,CAAC,WAAW,SAAS,SAAS,MAAM,KACpC,CAAC,SAAS,SAAS,SAAS,MAAM,GAElC,MAAM,KAAK;EAEf;EACA,MAAM,iBAAiB,UAAoC;GACzD,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,MAAM,IAAI;GACZ;GACA,IAAI,MAAM,QAAQ,OAAO,MAAM,KAAK;EACtC;EACA,MAAM,6BAA6B,eAAe;EAClD,MAAM,oBAAoB,UAAiC;GACzD,IAAK,MAAM,OAAuB,QAAQ,qBAAmB,GAC3D,MAAM,IAAI;EAEd;EAEA,MAAM,eAAe,SAAS;EAE9B,SAAS,iBAAiB,eAAe,iBAAiB;EAC1D,SAAS,iBAAiB,WAAW,aAAa;EAClD,OAAO,iBAAiB,UAAU,oBAAoB;EACtD,OAAO,iBAAiB,UAAU,sBAAsB,IAAI;EAC5D,cAAc,iBAAiB,SAAS,gBAAgB;EAExD,aAAa;GACX,SAAS,oBAAoB,eAAe,iBAAiB;GAC7D,SAAS,oBAAoB,WAAW,aAAa;GACrD,OAAO,oBAAoB,UAAU,oBAAoB;GACzD,OAAO,oBAAoB,UAAU,sBAAsB,IAAI;GAC/D,cAAc,oBAAoB,SAAS,gBAAgB;EAC7D;CACF,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,iBAAiB;CAIvB,MAAM,kBAAkB,aAAa,gBAAgB;EACnD,iBAAiB;EACjB,iBAAiB;EACjB,iBAAiB;EACjB,UAAU,UAA4B;GACpC,eAAe,MAAM,UAAU,KAAK;GACpC,IAAI,CAAC,MAAM,kBAAkB,SAAS,UAAU,CAAC,KAAK;EACxD;EACA,YAAY,UAAyB;GACnC,eAAe,MAAM,YAAY,KAAK;GACtC,IAAI,MAAM,kBAAkB;GAC5B,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;IACxD,MAAM,eAAe;IACrB,QAAQ,IAAI;GACd;EACF;EACA,KAAK;CACP,CAAC;CAED,OACE,qBAAA,UAAA,EAAA,UAAA,CACG,iBACA,OACG,aACE,oBAAC,OAAD;EACE,WAAW,CAAC,gBAAgB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAC/D,IAAI;EACJ,KAAK;EACL,OAAO;GAAE,MAAM,SAAS;GAAM,KAAK,SAAS;EAAI;EAE/C;CACE,CAAA,GACL,SAAS,IACX,IACA,IACJ,EAAA,CAAA;AAEN"}
@@ -0,0 +1,18 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ import type { ButtonIcon } from '../button/Button.types.js';
3
+ export interface PopupListItem {
4
+ icon: ButtonIcon;
5
+ text: string;
6
+ onClick: () => void;
7
+ }
8
+ export interface PopupProps {
9
+ trigger: ReactElement;
10
+ children: ReactNode;
11
+ className?: string;
12
+ }
13
+ export interface PopupListProps {
14
+ trigger: ReactElement;
15
+ items: PopupListItem[];
16
+ className?: string;
17
+ }
18
+ //# sourceMappingURL=Popup.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popup.types.d.ts","sourceRoot":"","sources":["../../../src/components/popup/Popup.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,4 @@
1
+ import type { PopupListProps } from './Popup.types.js';
2
+ declare const PopupList: ({ className, items, trigger }: PopupListProps) => import("react").JSX.Element;
3
+ export default PopupList;
4
+ //# sourceMappingURL=PopupList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PopupList.d.ts","sourceRoot":"","sources":["../../../src/components/popup/PopupList.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,QAAA,MAAM,SAAS,GAAI,+BAA+B,cAAc,gCAwC/D,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,44 @@
1
+ import ButtonIcon from "../button/button-icon/ButtonIcon.js";
2
+ import Popup from "./Popup.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useRef } from "react";
5
+ //#region src/components/popup/PopupList.tsx
6
+ var PopupList = ({ className, items, trigger }) => {
7
+ const itemRefs = useRef([]);
8
+ const handleKeyDown = (event) => {
9
+ const index = itemRefs.current.indexOf(document.activeElement);
10
+ if (index < 0 || items.length === 0) return;
11
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
12
+ event.preventDefault();
13
+ const nextIndex = (index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length;
14
+ itemRefs.current[nextIndex]?.focus();
15
+ }
16
+ if (event.key === "Home" || event.key === "End") {
17
+ event.preventDefault();
18
+ itemRefs.current[event.key === "Home" ? 0 : items.length - 1]?.focus();
19
+ }
20
+ };
21
+ return /* @__PURE__ */ jsx(Popup, {
22
+ ...className ? { className } : {},
23
+ trigger,
24
+ children: /* @__PURE__ */ jsx("div", {
25
+ onKeyDown: handleKeyDown,
26
+ role: "menu",
27
+ tabIndex: -1,
28
+ children: items.map((item, index) => /* @__PURE__ */ jsxs("button", {
29
+ className: "chayns-popup-list__item",
30
+ onClick: item.onClick,
31
+ ref: (element) => {
32
+ itemRefs.current[index] = element;
33
+ },
34
+ role: "menuitem",
35
+ type: "button",
36
+ children: [/* @__PURE__ */ jsx(ButtonIcon, { icon: item.icon }), /* @__PURE__ */ jsx("span", { children: item.text })]
37
+ }, `${item.text}-${index}`))
38
+ })
39
+ });
40
+ };
41
+ //#endregion
42
+ export { PopupList as default };
43
+
44
+ //# sourceMappingURL=PopupList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PopupList.js","names":[],"sources":["../../../src/components/popup/PopupList.tsx"],"sourcesContent":["import { useRef, type KeyboardEvent } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport Popup from './Popup.js';\nimport type { PopupListProps } from './Popup.types.js';\n\nconst PopupList = ({ className, items, trigger }: PopupListProps) => {\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const index = itemRefs.current.indexOf(document.activeElement as HTMLButtonElement);\n if (index < 0 || items.length === 0) return;\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n const direction = event.key === 'ArrowDown' ? 1 : -1;\n const nextIndex = (index + direction + items.length) % items.length;\n itemRefs.current[nextIndex]?.focus();\n }\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n itemRefs.current[event.key === 'Home' ? 0 : items.length - 1]?.focus();\n }\n };\n\n return (\n <Popup {...(className ? { className } : {})} trigger={trigger}>\n <div onKeyDown={handleKeyDown} role=\"menu\" tabIndex={-1}>\n {items.map((item, index) => (\n <button\n className=\"chayns-popup-list__item\"\n key={`${item.text}-${index}`}\n onClick={item.onClick}\n ref={(element) => {\n itemRefs.current[index] = element;\n }}\n role=\"menuitem\"\n type=\"button\"\n >\n <ButtonIcon icon={item.icon} />\n <span>{item.text}</span>\n </button>\n ))}\n </div>\n </Popup>\n );\n};\n\nexport default PopupList;\n"],"mappings":";;;;;AAMA,IAAM,aAAa,EAAE,WAAW,OAAO,cAA8B;CACnE,MAAM,WAAW,OAAqC,CAAC,CAAC;CAExD,MAAM,iBAAiB,UAAyC;EAC9D,MAAM,QAAQ,SAAS,QAAQ,QAAQ,SAAS,aAAkC;EAClF,IAAI,QAAQ,KAAK,MAAM,WAAW,GAAG;EAErC,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;GACxD,MAAM,eAAe;GAErB,MAAM,aAAa,SADD,MAAM,QAAQ,cAAc,IAAI,MACX,MAAM,UAAU,MAAM;GAC7D,SAAS,QAAQ,UAAU,EAAE,MAAM;EACrC;EACA,IAAI,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAAO;GAC/C,MAAM,eAAe;GACrB,SAAS,QAAQ,MAAM,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE,EAAE,MAAM;EACvE;CACF;CAEA,OACE,oBAAC,OAAD;EAAO,GAAK,YAAY,EAAE,UAAU,IAAI,CAAC;EAAa;EACpD,UAAA,oBAAC,OAAD;GAAK,WAAW;GAAe,MAAK;GAAO,UAAU;GAClD,UAAA,MAAM,KAAK,MAAM,UAChB,qBAAC,UAAD;IACE,WAAU;IAEV,SAAS,KAAK;IACd,MAAM,YAAY;KAChB,SAAS,QAAQ,SAAS;IAC5B;IACA,MAAK;IACL,MAAK;IARP,UAAA,CAUE,oBAAC,YAAD,EAAY,MAAM,KAAK,KAAO,CAAA,GAC9B,oBAAC,QAAD,EAAA,UAAO,KAAK,KAAW,CAAA,CACjB;GAVD,GAAA,GAAG,KAAK,KAAK,GAAG,OAUf,CACT;EACE,CAAA;CACA,CAAA;AAEX"}
@@ -0,0 +1,4 @@
1
+ import type { SplitButtonProps } from './SplitButton.types.js';
2
+ declare const SplitButton: ({ children, className, disabled, icon, items, onClick, variant, ...containerProps }: SplitButtonProps) => import("react").JSX.Element;
3
+ export default SplitButton;
4
+ //# sourceMappingURL=SplitButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SplitButton.d.ts","sourceRoot":"","sources":["../../../src/components/split-button/SplitButton.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,QAAA,MAAM,WAAW,GAAI,qFASlB,gBAAgB,gCA+ClB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,52 @@
1
+ import ButtonIcon from "../button/button-icon/ButtonIcon.js";
2
+ import Button from "../button/Button.js";
3
+ import PopupList from "../popup/PopupList.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useId } from "react";
6
+ //#region src/components/split-button/SplitButton.tsx
7
+ var SplitButton = ({ children, className, disabled, icon, items, onClick, variant, ...containerProps }) => {
8
+ const labelId = useId();
9
+ return /* @__PURE__ */ jsxs("div", {
10
+ ...containerProps,
11
+ className: ["chayns-split-button", className].filter(Boolean).join(" "),
12
+ children: [icon ? /* @__PURE__ */ jsx(Button, {
13
+ "aria-labelledby": labelId,
14
+ className: "chayns-split-button__primary",
15
+ ...disabled ? { disabled: true } : {},
16
+ icon,
17
+ ...onClick ? { onClick } : {},
18
+ variant,
19
+ children: /* @__PURE__ */ jsx("span", {
20
+ id: labelId,
21
+ children
22
+ })
23
+ }) : /* @__PURE__ */ jsx(Button, {
24
+ "aria-labelledby": labelId,
25
+ className: "chayns-split-button__primary",
26
+ ...disabled ? { disabled: true } : {},
27
+ ...onClick ? { onClick } : {},
28
+ variant,
29
+ children: /* @__PURE__ */ jsx("span", {
30
+ id: labelId,
31
+ children
32
+ })
33
+ }), /* @__PURE__ */ jsx(PopupList, {
34
+ items,
35
+ trigger: /* @__PURE__ */ jsx("button", {
36
+ "aria-labelledby": labelId,
37
+ className: `chayns-split-button__trigger chayns-button--${variant}`,
38
+ ...disabled ? { disabled: true } : {},
39
+ type: "button",
40
+ children: /* @__PURE__ */ jsx("span", {
41
+ "aria-hidden": "true",
42
+ className: "chayns-split-button__chevron",
43
+ children: /* @__PURE__ */ jsx(ButtonIcon, { icon: "fa-chevron-down" })
44
+ })
45
+ })
46
+ })]
47
+ });
48
+ };
49
+ //#endregion
50
+ export { SplitButton as default };
51
+
52
+ //# sourceMappingURL=SplitButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SplitButton.js","names":[],"sources":["../../../src/components/split-button/SplitButton.tsx"],"sourcesContent":["import { useId } from 'react';\n\nimport Button from '../button/Button.js';\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport PopupList from '../popup/PopupList.js';\nimport type { SplitButtonProps } from './SplitButton.types.js';\n\nconst SplitButton = ({\n children,\n className,\n disabled,\n icon,\n items,\n onClick,\n variant,\n ...containerProps\n}: SplitButtonProps) => {\n const labelId = useId();\n\n return (\n <div\n {...containerProps}\n className={['chayns-split-button', className].filter(Boolean).join(' ')}\n >\n {icon ? (\n <Button\n aria-labelledby={labelId}\n className=\"chayns-split-button__primary\"\n {...(disabled ? { disabled: true } : {})}\n icon={icon}\n {...(onClick ? { onClick } : {})}\n variant={variant}\n >\n <span id={labelId}>{children}</span>\n </Button>\n ) : (\n <Button\n aria-labelledby={labelId}\n className=\"chayns-split-button__primary\"\n {...(disabled ? { disabled: true } : {})}\n {...(onClick ? { onClick } : {})}\n variant={variant}\n >\n <span id={labelId}>{children}</span>\n </Button>\n )}\n <PopupList\n items={items}\n trigger={\n <button\n aria-labelledby={labelId}\n className={`chayns-split-button__trigger chayns-button--${variant}`}\n {...(disabled ? { disabled: true } : {})}\n type=\"button\"\n >\n <span aria-hidden=\"true\" className=\"chayns-split-button__chevron\">\n <ButtonIcon icon=\"fa-chevron-down\" />\n </span>\n </button>\n }\n />\n </div>\n );\n};\n\nexport default SplitButton;\n"],"mappings":";;;;;;AAOA,IAAM,eAAe,EACnB,UACA,WACA,UACA,MACA,OACA,SACA,SACA,GAAG,qBACmB;CACtB,MAAM,UAAU,MAAM;CAEtB,OACE,qBAAC,OAAD;EACE,GAAI;EACJ,WAAW,CAAC,uBAAuB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAFxE,UAAA,CAIG,OACC,oBAAC,QAAD;GACE,mBAAiB;GACjB,WAAU;GACV,GAAK,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;GAChC;GACN,GAAK,UAAU,EAAE,QAAQ,IAAI,CAAC;GACrB;GAET,UAAA,oBAAC,QAAD;IAAM,IAAI;IAAU;GAAe,CAAA;EAC7B,CAAA,IAER,oBAAC,QAAD;GACE,mBAAiB;GACjB,WAAU;GACV,GAAK,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;GACtC,GAAK,UAAU,EAAE,QAAQ,IAAI,CAAC;GACrB;GAET,UAAA,oBAAC,QAAD;IAAM,IAAI;IAAU;GAAe,CAAA;EAC7B,CAAA,GAEV,oBAAC,WAAD;GACS;GACP,SACE,oBAAC,UAAD;IACE,mBAAiB;IACjB,WAAW,+CAA+C;IAC1D,GAAK,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAK;IAEL,UAAA,oBAAC,QAAD;KAAM,eAAY;KAAO,WAAU;KACjC,UAAA,oBAAC,YAAD,EAAY,MAAK,kBAAmB,CAAA;IAChC,CAAA;GACA,CAAA;EAEX,CAAA,CACE;;AAET"}
@@ -0,0 +1,12 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import type { ButtonContent, ButtonIcon, ButtonVariant } from '../button/Button.types.js';
3
+ import type { PopupListItem } from '../popup/Popup.types.js';
4
+ export interface SplitButtonProps extends Omit<ComponentPropsWithRef<'div'>, 'children' | 'onClick'> {
5
+ variant: ButtonVariant;
6
+ children: ButtonContent;
7
+ items: PopupListItem[];
8
+ icon?: ButtonIcon;
9
+ onClick?: ComponentPropsWithRef<'button'>['onClick'];
10
+ disabled?: boolean;
11
+ }
12
+ //# sourceMappingURL=SplitButton.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SplitButton.types.d.ts","sourceRoot":"","sources":["../../../src/components/split-button/SplitButton.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,GAAG,SAAS,CACvB;IACC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,22 @@
1
- export { Button, IconButton } from './components/button/index.js';
2
- export type { ButtonContent, ButtonIcon, ButtonProps, ButtonVariant, IconButtonProps, } from './components/button/index.js';
3
- export { Card } from './components/card/index.js';
4
- export type { CardProps } from './components/card/index.js';
5
- export { List, ListItem } from './components/list/index.js';
6
- export type { ListItemProps, ListProps } from './components/list/index.js';
7
- export { Accordion, AccordionGroup } from './components/accordion/index.js';
8
- export type { AccordionGroupProps, AccordionProps } from './components/accordion/index.js';
1
+ export { default as Button } from './components/button/Button.js';
2
+ export { default as IconButton } from './components/icon-button/IconButton.js';
3
+ export type { ButtonContent, ButtonIcon, ButtonProps, ButtonVariant, } from './components/button/Button.types.js';
4
+ export type { IconButtonProps } from './components/icon-button/IconButton.types.js';
5
+ export { default as Popup } from './components/popup/Popup.js';
6
+ export { default as PopupList } from './components/popup/PopupList.js';
7
+ export type { PopupListItem, PopupListProps, PopupProps } from './components/popup/Popup.types.js';
8
+ export { default as SplitButton } from './components/split-button/SplitButton.js';
9
+ export type { SplitButtonProps } from './components/split-button/SplitButton.types.js';
10
+ export { default as Card } from './components/card/Card.js';
11
+ export type { CardProps } from './components/card/Card.types.js';
12
+ export { default as Avatar } from './components/avatar/Avatar.js';
13
+ export { default as AvatarGroup } from './components/avatar-group/AvatarGroup.js';
14
+ export type { AvatarProps } from './components/avatar/Avatar.types.js';
15
+ export type { AvatarGroupProps } from './components/avatar-group/AvatarGroup.types.js';
16
+ export { default as List } from './components/list/List.js';
17
+ export { default as ListItem } from './components/list-item/ListItem.js';
18
+ export type { ListProps, ListItemProps } from './components/list/List.types.js';
19
+ export { default as Accordion } from './components/accordion/Accordion.js';
20
+ export { default as AccordionGroup } from './components/accordion-group/AccordionGroup.js';
21
+ export type { AccordionProps, AccordionGroupProps, } from './components/accordion/Accordion.types.js';
9
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,aAAa,EACb,eAAe,GAChB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAC/E,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,aAAa,GACd,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAEpF,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACvE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEnG,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAClF,YAAY,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAEvF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AACvE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAEvF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACzE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAC3F,YAAY,EACV,cAAc,EACd,mBAAmB,GACpB,MAAM,2CAA2C,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,13 @@
1
1
  import Button from "./components/button/Button.js";
2
- import IconButton from "./components/button/IconButton.js";
2
+ import IconButton from "./components/icon-button/IconButton.js";
3
+ import Popup from "./components/popup/Popup.js";
4
+ import PopupList from "./components/popup/PopupList.js";
5
+ import SplitButton from "./components/split-button/SplitButton.js";
3
6
  import Card from "./components/card/Card.js";
7
+ import Avatar from "./components/avatar/Avatar.js";
8
+ import AvatarGroup from "./components/avatar-group/AvatarGroup.js";
4
9
  import List from "./components/list/List.js";
5
- import ListItem from "./components/list/ListItem.js";
10
+ import ListItem from "./components/list-item/ListItem.js";
6
11
  import Accordion from "./components/accordion/Accordion.js";
7
- import AccordionGroup from "./components/accordion/AccordionGroup.js";
8
- export { Accordion, AccordionGroup, Button, Card, IconButton, List, ListItem };
12
+ import AccordionGroup from "./components/accordion-group/AccordionGroup.js";
13
+ export { Accordion, AccordionGroup, Avatar, AvatarGroup, Button, Card, IconButton, List, ListItem, Popup, PopupList, SplitButton };
package/dist/list.css CHANGED
@@ -89,10 +89,17 @@
89
89
 
90
90
  .chayns-list-item__trailing {
91
91
  flex: none;
92
+ align-self: flex-start;
92
93
  display: flex;
93
- align-items: center;
94
+ align-items: flex-start;
95
+ justify-content: flex-end;
94
96
  gap: var(--k8);
97
+ padding-block-start: var(--k10);
95
98
  padding-inline-end: var(--k16);
99
+ color: var(--text-3);
100
+ font-size: var(--fs-meta);
101
+ text-align: end;
102
+ white-space: nowrap;
96
103
  }
97
104
 
98
105
  .chayns-visually-hidden {
package/dist/popup.css ADDED
@@ -0,0 +1,34 @@
1
+ @layer chayns.components {
2
+ .chayns-popup {
3
+ position: fixed;
4
+ z-index: var(--z-popover);
5
+ min-inline-size: 14rem;
6
+ padding: var(--sp-2);
7
+ border: 1px solid var(--disabled-border);
8
+ border-radius: 12px;
9
+ background: var(--surface);
10
+ box-shadow: var(--shadow-pop);
11
+ }
12
+
13
+ .chayns-popup-list__item {
14
+ display: flex;
15
+ inline-size: 100%;
16
+ align-items: center;
17
+ gap: var(--sp-2);
18
+ min-block-size: var(--ctrl-h);
19
+ padding: var(--sp-2) var(--sp-4);
20
+ border: 0;
21
+ border-radius: 8px;
22
+ background: transparent;
23
+ color: var(--text);
24
+ font: inherit;
25
+ text-align: start;
26
+ cursor: pointer;
27
+ }
28
+
29
+ .chayns-popup-list__item:hover,
30
+ .chayns-popup-list__item:focus-visible {
31
+ background: var(--surface-alt);
32
+ outline: none;
33
+ }
34
+ }
@@ -0,0 +1,128 @@
1
+ @layer chayns.components {
2
+ .chayns-split-button {
3
+ display: inline-flex;
4
+ align-items: stretch;
5
+ max-inline-size: 100%;
6
+ }
7
+
8
+ .chayns-split-button__primary {
9
+ border-start-end-radius: 0;
10
+ border-end-end-radius: 0;
11
+ }
12
+
13
+ .chayns-split-button__trigger {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ min-inline-size: var(--ctrl-h);
18
+ padding: 0 var(--sp-2);
19
+ border: 0;
20
+ border-inline-start: 1px solid color-mix(in srgb, currentcolor 30%, transparent);
21
+ border-start-end-radius: 999px;
22
+ border-end-end-radius: 999px;
23
+ font: inherit;
24
+ cursor: pointer;
25
+ }
26
+
27
+ .chayns-split-button__trigger.chayns-button--primary {
28
+ background: var(--accent);
29
+ color: var(--on-accent);
30
+ }
31
+
32
+ .chayns-split-button__trigger.chayns-button--outline {
33
+ border-block: 1.5px solid var(--accent);
34
+ border-inline-end: 1.5px solid var(--accent);
35
+ background: var(--surface);
36
+ color: var(--accent);
37
+ }
38
+
39
+ .chayns-split-button__trigger.chayns-button--ghost {
40
+ background: transparent;
41
+ color: var(--text-2);
42
+ }
43
+
44
+ .chayns-split-button__trigger.chayns-button--danger {
45
+ background: var(--danger-bg);
46
+ color: var(--danger);
47
+ }
48
+
49
+ .chayns-split-button__trigger:disabled {
50
+ background: var(--disabled-bg);
51
+ border-inline-start-color: var(--disabled-border);
52
+ border-inline-end-color: var(--disabled-border);
53
+ color: var(--disabled-fg);
54
+ cursor: not-allowed;
55
+ }
56
+
57
+ .chayns-split-button__trigger.chayns-button--outline:disabled {
58
+ border-block-color: var(--disabled-border);
59
+ background: var(--surface);
60
+ }
61
+
62
+ .chayns-split-button__trigger:focus-visible {
63
+ outline: none;
64
+ box-shadow: 0 0 0 var(--focus-ring-size)
65
+ rgb(var(--focus-ring-rgb), var(--focus-ring-alpha-strong));
66
+ }
67
+
68
+ .chayns-split-button__trigger:active:not(:disabled) {
69
+ transform: scale(0.97);
70
+ }
71
+
72
+ .chayns-split-button__trigger.chayns-button--primary:active:not(:disabled) {
73
+ background: var(--accent-active);
74
+ }
75
+
76
+ .chayns-split-button__trigger.chayns-button--outline:active:not(:disabled) {
77
+ background: var(--accent);
78
+ color: var(--on-accent);
79
+ }
80
+
81
+ .chayns-split-button__trigger.chayns-button--ghost:active:not(:disabled) {
82
+ background: var(--surface-alt);
83
+ color: var(--accent);
84
+ }
85
+
86
+ .chayns-split-button__trigger.chayns-button--danger:active:not(:disabled) {
87
+ background: var(--danger-bg-hover);
88
+ }
89
+
90
+ .chayns-split-button__trigger:active:not(:disabled)
91
+ .chayns-button-icon__weight:not(.chayns-button-icon__weight--active),
92
+ .chayns-split-button__trigger:hover:not(:disabled)
93
+ .chayns-button-icon__weight:not(.chayns-button-icon__weight--active) {
94
+ display: none;
95
+ }
96
+
97
+ .chayns-split-button__trigger:active:not(:disabled) .chayns-button-icon__weight--active,
98
+ .chayns-split-button__trigger:hover:not(:disabled) .chayns-button-icon__weight--active {
99
+ display: inline-flex;
100
+ }
101
+
102
+ @media (hover: hover) {
103
+ .chayns-split-button__trigger.chayns-button--primary:hover:not(:disabled) {
104
+ background: var(--accent-hover);
105
+ box-shadow: var(--shadow-btn-hover);
106
+ }
107
+
108
+ .chayns-split-button__trigger.chayns-button--outline:hover:not(:disabled) {
109
+ background: var(--accent);
110
+ color: var(--on-accent);
111
+ box-shadow: var(--shadow-btn-hover);
112
+ }
113
+
114
+ .chayns-split-button__trigger.chayns-button--ghost:hover:not(:disabled) {
115
+ background: var(--surface-alt);
116
+ color: var(--accent);
117
+ }
118
+
119
+ .chayns-split-button__trigger.chayns-button--danger:hover:not(:disabled) {
120
+ background: var(--danger-bg-hover);
121
+ }
122
+ }
123
+
124
+ .chayns-split-button__chevron .chayns-button-icon {
125
+ inline-size: 1em;
126
+ block-size: 1em;
127
+ }
128
+ }
package/dist/styles.css CHANGED
@@ -1,4 +1,7 @@
1
1
  @import url('./button.css');
2
2
  @import url('./card.css');
3
+ @import url('./avatar.css');
3
4
  @import url('./list.css');
4
5
  @import url('./accordion.css');
6
+ @import url('./popup.css');
7
+ @import url('./split-button.css');
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@chayns-ui/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Accessible React core components for chayns UI",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/TobitSoftware/chayns-ui.git",
10
+ "directory": "packages/core"
11
+ },
7
12
  "sideEffects": [
8
13
  "**/*.css"
9
14
  ],
@@ -17,34 +22,21 @@
17
22
  "types": "./dist/index.d.ts",
18
23
  "import": "./dist/index.js"
19
24
  },
20
- "./button": {
21
- "types": "./dist/components/button/index.d.ts",
22
- "import": "./dist/components/button/index.js"
23
- },
24
25
  "./button.css": "./dist/button.css",
25
- "./card": {
26
- "types": "./dist/components/card/index.d.ts",
27
- "import": "./dist/components/card/index.js"
28
- },
29
26
  "./card.css": "./dist/card.css",
30
- "./list": {
31
- "types": "./dist/components/list/index.d.ts",
32
- "import": "./dist/components/list/index.js"
33
- },
27
+ "./avatar.css": "./dist/avatar.css",
34
28
  "./list.css": "./dist/list.css",
35
- "./accordion": {
36
- "types": "./dist/components/accordion/index.d.ts",
37
- "import": "./dist/components/accordion/index.js"
38
- },
39
29
  "./accordion.css": "./dist/accordion.css",
30
+ "./popup.css": "./dist/popup.css",
31
+ "./split-button.css": "./dist/split-button.css",
40
32
  "./styles.css": "./dist/styles.css",
41
33
  "./package.json": "./package.json"
42
34
  },
43
35
  "peerDependencies": {
44
- "react": ">=19.2 <20"
36
+ "react": ">=18 <20"
45
37
  },
46
38
  "engines": {
47
- "node": ">=24"
39
+ "node": ">=18"
48
40
  },
49
41
  "publishConfig": {
50
42
  "access": "public"
@@ -1,4 +0,0 @@
1
- import type { AccordionGroupProps } from './Accordion.types.js';
2
- declare function AccordionGroup({ children, className, defaultOpenId, onOpenChange, openId, }: AccordionGroupProps): import("react").JSX.Element;
3
- export default AccordionGroup;
4
- //# sourceMappingURL=AccordionGroup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AccordionGroup.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/AccordionGroup.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,aAAoB,EACpB,YAAY,EACZ,MAAM,GACP,EAAE,mBAAmB,+BA6BrB;AAED,eAAe,cAAc,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AccordionGroup.js","names":[],"sources":["../../../src/components/accordion/AccordionGroup.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\n\nimport { AccordionGroupContext } from './AccordionContext.js';\nimport type { AccordionGroupContextValue } from './AccordionContext.js';\nimport type { AccordionGroupProps } from './Accordion.types.js';\n\nfunction AccordionGroup({\n children,\n className,\n defaultOpenId = null,\n onOpenChange,\n openId,\n}: AccordionGroupProps) {\n const [uncontrolledOpenId, setUncontrolledOpenId] = useState<string | null>(defaultOpenId);\n\n const isControlled = openId !== undefined;\n const currentOpenId = isControlled ? openId : uncontrolledOpenId;\n\n const isOpen = useCallback((id: string) => currentOpenId === id, [currentOpenId]);\n\n const toggle = useCallback(\n (id: string) => {\n const nextOpenId = currentOpenId === id ? null : id;\n if (!isControlled) setUncontrolledOpenId(nextOpenId);\n onOpenChange?.(nextOpenId);\n },\n [currentOpenId, isControlled, onOpenChange],\n );\n\n const contextValue = useMemo<AccordionGroupContextValue>(\n () => ({ isOpen, toggle }),\n [isOpen, toggle],\n );\n\n const rootClassName = ['chayns-accordion-group', className].filter(Boolean).join(' ');\n\n return (\n <AccordionGroupContext.Provider value={contextValue}>\n <div className={rootClassName}>{children}</div>\n </AccordionGroupContext.Provider>\n );\n}\n\nexport default AccordionGroup;\n"],"mappings":";;;;AAMA,SAAS,eAAe,EACtB,UACA,WACA,gBAAgB,MAChB,cACA,UACsB;CACtB,MAAM,CAAC,oBAAoB,yBAAyB,SAAwB,aAAa;CAEzF,MAAM,eAAe,WAAW,KAAA;CAChC,MAAM,gBAAgB,eAAe,SAAS;CAE9C,MAAM,SAAS,aAAa,OAAe,kBAAkB,IAAI,CAAC,aAAa,CAAC;CAEhF,MAAM,SAAS,aACZ,OAAe;EACd,MAAM,aAAa,kBAAkB,KAAK,OAAO;EACjD,IAAI,CAAC,cAAc,sBAAsB,UAAU;EACnD,eAAe,UAAU;CAC3B,GACA;EAAC;EAAe;EAAc;CAAY,CAC5C;CAEA,MAAM,eAAe,eACZ;EAAE;EAAQ;CAAO,IACxB,CAAC,QAAQ,MAAM,CACjB;CAEA,MAAM,gBAAgB,CAAC,0BAA0B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAEpF,OACE,oBAAC,sBAAsB,UAAvB;EAAgC,OAAO;EACrC,UAAA,oBAAC,OAAD;GAAK,WAAW;GAAgB;EAAc,CAAA;CAChB,CAAA;AAEpC"}
@@ -1,4 +0,0 @@
1
- export { default as Accordion } from './Accordion.js';
2
- export { default as AccordionGroup } from './AccordionGroup.js';
3
- export type { AccordionGroupProps, AccordionProps } from './Accordion.types.js';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,3 +0,0 @@
1
- import Accordion from "./Accordion.js";
2
- import AccordionGroup from "./AccordionGroup.js";
3
- export { Accordion, AccordionGroup };