@chayns-ui/core 0.4.2 → 0.6.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 (60) hide show
  1. package/dist/avatar.css +25 -8
  2. package/dist/badge.css +46 -0
  3. package/dist/combo-box.css +144 -0
  4. package/dist/components/accordion/Accordion.d.ts +1 -1
  5. package/dist/components/accordion/Accordion.d.ts.map +1 -1
  6. package/dist/components/accordion/Accordion.js +8 -5
  7. package/dist/components/accordion/Accordion.js.map +1 -1
  8. package/dist/components/accordion/Accordion.types.d.ts +3 -3
  9. package/dist/components/accordion/Accordion.types.d.ts.map +1 -1
  10. package/dist/components/accordion-group/AccordionGroup.d.ts +1 -1
  11. package/dist/components/accordion-group/AccordionGroup.d.ts.map +1 -1
  12. package/dist/components/accordion-group/AccordionGroup.js +3 -1
  13. package/dist/components/accordion-group/AccordionGroup.js.map +1 -1
  14. package/dist/components/avatar/Avatar.d.ts +1 -1
  15. package/dist/components/avatar/Avatar.d.ts.map +1 -1
  16. package/dist/components/avatar/Avatar.js +6 -5
  17. package/dist/components/avatar/Avatar.js.map +1 -1
  18. package/dist/components/avatar/Avatar.types.d.ts +3 -11
  19. package/dist/components/avatar/Avatar.types.d.ts.map +1 -1
  20. package/dist/components/avatar-group/AvatarGroup.d.ts +1 -1
  21. package/dist/components/avatar-group/AvatarGroup.d.ts.map +1 -1
  22. package/dist/components/avatar-group/AvatarGroup.js +6 -5
  23. package/dist/components/avatar-group/AvatarGroup.js.map +1 -1
  24. package/dist/components/avatar-group/AvatarGroup.types.d.ts +2 -10
  25. package/dist/components/avatar-group/AvatarGroup.types.d.ts.map +1 -1
  26. package/dist/components/badge/Badge.d.ts +4 -0
  27. package/dist/components/badge/Badge.d.ts.map +1 -0
  28. package/dist/components/badge/Badge.js +26 -0
  29. package/dist/components/badge/Badge.js.map +1 -0
  30. package/dist/components/badge/Badge.types.d.ts +13 -0
  31. package/dist/components/badge/Badge.types.d.ts.map +1 -0
  32. package/dist/components/badge/Badge.types.js +13 -0
  33. package/dist/components/badge/Badge.types.js.map +1 -0
  34. package/dist/components/button/Button.types.d.ts +14 -9
  35. package/dist/components/button/Button.types.d.ts.map +1 -1
  36. package/dist/components/button/Button.types.js +15 -0
  37. package/dist/components/button/Button.types.js.map +1 -0
  38. package/dist/components/button/button-icon/ButtonIcon.d.ts.map +1 -1
  39. package/dist/components/button/button-icon/ButtonIcon.js +18 -12
  40. package/dist/components/button/button-icon/ButtonIcon.js.map +1 -1
  41. package/dist/components/combo-box/ComboBox.d.ts +6 -0
  42. package/dist/components/combo-box/ComboBox.d.ts.map +1 -0
  43. package/dist/components/combo-box/ComboBox.js +217 -0
  44. package/dist/components/combo-box/ComboBox.js.map +1 -0
  45. package/dist/components/combo-box/ComboBox.types.d.ts +32 -0
  46. package/dist/components/combo-box/ComboBox.types.d.ts.map +1 -0
  47. package/dist/components/combo-box/ComboBoxContext.d.ts +15 -0
  48. package/dist/components/combo-box/ComboBoxContext.d.ts.map +1 -0
  49. package/dist/components/combo-box/ComboBoxContext.js +16 -0
  50. package/dist/components/combo-box/ComboBoxContext.js.map +1 -0
  51. package/dist/components/icon-button/IconButton.types.d.ts +4 -3
  52. package/dist/components/icon-button/IconButton.types.d.ts.map +1 -1
  53. package/dist/components/split-button/SplitButton.types.d.ts +1 -0
  54. package/dist/components/split-button/SplitButton.types.d.ts.map +1 -1
  55. package/dist/index.d.ts +6 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +5 -1
  58. package/dist/list.css +2 -2
  59. package/dist/styles.css +2 -0
  60. package/package.json +3 -1
package/dist/avatar.css CHANGED
@@ -5,8 +5,8 @@
5
5
  flex: none;
6
6
  align-items: center;
7
7
  justify-content: center;
8
- inline-size: var(--avatar);
9
- block-size: var(--avatar);
8
+ inline-size: var(--k44);
9
+ block-size: var(--k44);
10
10
  overflow: visible;
11
11
  border-radius: 50%;
12
12
  background: var(--accent);
@@ -30,11 +30,22 @@
30
30
  }
31
31
 
32
32
  .chayns-avatar--small {
33
- inline-size: var(--avatar-sm);
34
- block-size: var(--avatar-sm);
33
+ inline-size: var(--k36);
34
+ block-size: var(--k36);
35
35
  font-size: var(--fs-meta);
36
36
  }
37
37
 
38
+ .chayns-avatar--default {
39
+ inline-size: var(--k44);
40
+ block-size: var(--k44);
41
+ }
42
+
43
+ .chayns-avatar--large {
44
+ inline-size: var(--k52);
45
+ block-size: var(--k52);
46
+ font-size: var(--fs-subtitle);
47
+ }
48
+
38
49
  .chayns-avatar__image {
39
50
  display: block;
40
51
  inline-size: 100%;
@@ -86,8 +97,8 @@
86
97
  flex: none;
87
98
  align-items: center;
88
99
  justify-content: center;
89
- inline-size: var(--avatar);
90
- block-size: var(--avatar);
100
+ inline-size: var(--k44);
101
+ block-size: var(--k44);
91
102
  border-radius: 50%;
92
103
  background: var(--surface-alt);
93
104
  color: var(--accent);
@@ -97,8 +108,14 @@
97
108
  }
98
109
 
99
110
  .chayns-avatar-group--small .chayns-avatar-group__overflow {
100
- inline-size: var(--avatar-sm);
101
- block-size: var(--avatar-sm);
111
+ inline-size: var(--k36);
112
+ block-size: var(--k36);
102
113
  font-size: var(--fs-micro);
103
114
  }
115
+
116
+ .chayns-avatar-group--large .chayns-avatar-group__overflow {
117
+ inline-size: var(--k52);
118
+ block-size: var(--k52);
119
+ font-size: var(--fs-body);
120
+ }
104
121
  }
package/dist/badge.css ADDED
@@ -0,0 +1,46 @@
1
+ @layer chayns.components {
2
+ .chayns-badge {
3
+ box-sizing: border-box;
4
+ display: inline-flex;
5
+ align-items: center;
6
+ gap: var(--k5);
7
+ padding: var(--k4) var(--k12);
8
+ border-radius: 999px;
9
+ font-family: inherit;
10
+ font-size: var(--fs-caption);
11
+ font-weight: 500;
12
+ line-height: 1.2;
13
+ }
14
+
15
+ .chayns-badge--md {
16
+ gap: var(--k6);
17
+ padding: var(--k5) var(--k12);
18
+ font-size: var(--fs-meta);
19
+ }
20
+
21
+ .chayns-badge--neutral {
22
+ background: var(--surface-alt);
23
+ color: var(--text-2);
24
+ }
25
+
26
+ .chayns-badge--accent {
27
+ background: var(--accent);
28
+ color: var(--on-accent);
29
+ }
30
+
31
+ .chayns-badge--success {
32
+ /* stylelint-disable-next-line custom-property-pattern */
33
+ background: var(--success-bg);
34
+ color: var(--text);
35
+ }
36
+
37
+ .chayns-badge--warning {
38
+ background: var(--warning-bg);
39
+ color: var(--text);
40
+ }
41
+
42
+ .chayns-badge--danger {
43
+ background: var(--danger-bg);
44
+ color: var(--text);
45
+ }
46
+ }
@@ -0,0 +1,144 @@
1
+ @layer chayns.components {
2
+ .chayns-combo-box {
3
+ position: relative;
4
+ min-inline-size: 0;
5
+ }
6
+
7
+ .chayns-combo-box__input {
8
+ box-sizing: border-box;
9
+ inline-size: 100%;
10
+ min-block-size: calc(1.2em + 2 * var(--input-py) + 3px);
11
+ padding: var(--input-py) var(--input-px);
12
+ border: 1.5px solid var(--input-border);
13
+ border-radius: 10px;
14
+ background: var(--surface);
15
+ color: var(--text);
16
+ font: inherit;
17
+ line-height: 1.2;
18
+ outline: none;
19
+ transition:
20
+ border-color 0.18s ease,
21
+ box-shadow 0.18s ease;
22
+ }
23
+
24
+ .chayns-combo-box__input:focus {
25
+ border-color: var(--accent);
26
+ box-shadow: 0 0 0 var(--focus-ring-size)
27
+ rgb(var(--focus-ring-rgb), var(--focus-ring-alpha-soft));
28
+ }
29
+
30
+ .chayns-combo-box__label {
31
+ position: absolute;
32
+ inset-block-start: 0;
33
+ inset-inline-start: 10px;
34
+ padding-inline: var(--k5);
35
+ background: var(--surface);
36
+ color: var(--text-3);
37
+ font-size: var(--fs-body);
38
+ line-height: 1.2;
39
+ pointer-events: none;
40
+ transform: translateY(calc(var(--input-py) + 1.5px + 0.6em - 50%));
41
+ transform-origin: left center;
42
+ transition:
43
+ transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1),
44
+ color 0.15s ease;
45
+ white-space: nowrap;
46
+ }
47
+
48
+ .chayns-combo-box--open .chayns-combo-box__label,
49
+ .chayns-combo-box__input:not(:placeholder-shown) + .chayns-combo-box__label {
50
+ color: var(--accent);
51
+ transform: translateY(-50%) scale(0.8);
52
+ }
53
+
54
+ .chayns-combo-box__chips {
55
+ position: absolute;
56
+ inset: 1.5px var(--input-px) auto;
57
+ display: flex;
58
+ flex-wrap: wrap;
59
+ gap: var(--k5);
60
+ pointer-events: none;
61
+ transform: translateY(var(--input-py));
62
+ }
63
+
64
+ .chayns-combo-box__chip {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ gap: var(--k5);
68
+ padding: var(--k3) var(--k9);
69
+ border-radius: 999px;
70
+ background: var(--accent);
71
+ color: var(--on-accent);
72
+ font-size: var(--fs-caption);
73
+ font-weight: 500;
74
+ }
75
+
76
+ .chayns-combo-box__popup {
77
+ position: absolute;
78
+ inset-block-start: calc(100% + var(--k4));
79
+ inset-inline: 0;
80
+ z-index: var(--z-popover);
81
+ max-block-size: min(320px, 50vh);
82
+ overflow: auto;
83
+ padding: var(--k6);
84
+ border: 1px solid var(--border);
85
+ border-radius: 12px;
86
+ background: var(--surface);
87
+ box-shadow: var(--shadow-pop);
88
+ }
89
+
90
+ .chayns-combo-box__option {
91
+ display: flex;
92
+ align-items: center;
93
+ min-block-size: var(--k40);
94
+ padding: var(--k9) var(--k12);
95
+ border-radius: 8px;
96
+ color: var(--text);
97
+ cursor: pointer;
98
+ font-size: var(--fs-body);
99
+ }
100
+
101
+ .chayns-combo-box__option:hover,
102
+ .chayns-combo-box__option--active {
103
+ background: var(--surface-alt);
104
+ }
105
+
106
+ .chayns-combo-box__option--selected {
107
+ color: var(--accent);
108
+ font-weight: 600;
109
+ }
110
+
111
+ .chayns-combo-box__checkbox {
112
+ display: inline-flex;
113
+ flex: none;
114
+ align-items: center;
115
+ justify-content: center;
116
+ inline-size: var(--k18);
117
+ block-size: var(--k18);
118
+ margin-inline-end: var(--k8);
119
+ border: 1.5px solid var(--input-border);
120
+ border-radius: var(--k4);
121
+ background: var(--surface);
122
+ }
123
+
124
+ .chayns-combo-box__checkbox[data-checked='true'] {
125
+ border-color: var(--accent);
126
+ background: var(--accent);
127
+ }
128
+
129
+ .chayns-combo-box__checkbox[data-checked='true']::after {
130
+ inline-size: var(--k8);
131
+ block-size: var(--k4);
132
+ border-block-end: 2px solid var(--on-accent);
133
+ border-inline-start: 2px solid var(--on-accent);
134
+ content: '';
135
+ transform: rotate(-45deg) translate(1px, -1px);
136
+ }
137
+
138
+ @media (prefers-reduced-motion: reduce) {
139
+ .chayns-combo-box__input,
140
+ .chayns-combo-box__label {
141
+ transition: none;
142
+ }
143
+ }
144
+ }
@@ -1,4 +1,4 @@
1
1
  import type { AccordionProps } from './Accordion.types.js';
2
- declare const Accordion: ({ children, className, defaultOpen, disabled, id, onOpenChange, open, title, }: AccordionProps) => import("react").JSX.Element;
2
+ declare const Accordion: ({ children, className, defaultOpen, disabled, id, onOpenChange, open, ref, title, ...rootProps }: AccordionProps) => import("react").JSX.Element;
3
3
  export default Accordion;
4
4
  //# sourceMappingURL=Accordion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,QAAA,MAAM,SAAS,GAAI,gFAShB,cAAc,gCAiFhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,QAAA,MAAM,SAAS,GAAI,kGAWhB,cAAc,gCAkFhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -2,7 +2,7 @@ import { AccordionDepthContext, AccordionGroupContext } from "./AccordionContext
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useContext, useId, useState } from "react";
4
4
  //#region src/components/accordion/Accordion.tsx
5
- var Accordion = ({ children, className, defaultOpen = false, disabled = false, id, onOpenChange, open, title }) => {
5
+ var Accordion = ({ children, className, defaultOpen = false, disabled = false, id, onOpenChange, open, ref, title, ...rootProps }) => {
6
6
  const depth = useContext(AccordionDepthContext);
7
7
  const group = useContext(AccordionGroupContext);
8
8
  const generatedId = useId();
@@ -10,12 +10,13 @@ var Accordion = ({ children, className, defaultOpen = false, disabled = false, i
10
10
  const headerId = `${baseId}-header`;
11
11
  const panelId = `${baseId}-panel`;
12
12
  const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
13
+ const isGrouped = group !== null && depth === 0;
13
14
  let isOpen;
14
- if (group) isOpen = group.isOpen(baseId);
15
+ if (isGrouped) isOpen = group.isOpen(baseId);
15
16
  else if (open !== void 0) isOpen = open;
16
17
  else isOpen = uncontrolledOpen;
17
18
  const handleToggle = () => {
18
- if (group) {
19
+ if (isGrouped) {
19
20
  group.toggle(baseId);
20
21
  return;
21
22
  }
@@ -23,16 +24,18 @@ var Accordion = ({ children, className, defaultOpen = false, disabled = false, i
23
24
  if (open === void 0) setUncontrolledOpen(nextOpen);
24
25
  onOpenChange?.(nextOpen);
25
26
  };
26
- const grouped = group !== null;
27
27
  const rootClassName = [
28
28
  "chayns-accordion",
29
- grouped ? "chayns-accordion--grouped" : !grouped && depth > 0 ? "chayns-accordion--wrapped" : "chayns-accordion--standalone",
29
+ isGrouped ? "chayns-accordion--grouped" : depth > 0 ? "chayns-accordion--wrapped" : "chayns-accordion--standalone",
30
30
  isOpen ? "chayns-accordion--open" : null,
31
31
  disabled ? "chayns-accordion--disabled" : null,
32
32
  className
33
33
  ].filter(Boolean).join(" ");
34
34
  return /* @__PURE__ */ jsxs("div", {
35
+ ...rootProps,
35
36
  className: rootClassName,
37
+ id,
38
+ ref,
36
39
  children: [/* @__PURE__ */ jsxs("button", {
37
40
  "aria-controls": panelId,
38
41
  "aria-expanded": isOpen,
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.tsx"],"sourcesContent":["import { useContext, useId, useState } from 'react';\n\nimport { AccordionDepthContext, AccordionGroupContext } from './AccordionContext.js';\nimport type { AccordionProps } from './Accordion.types.js';\n\nconst Accordion = ({\n children,\n className,\n defaultOpen = false,\n disabled = false,\n id,\n onOpenChange,\n open,\n title,\n}: AccordionProps) => {\n const depth = useContext(AccordionDepthContext);\n const group = useContext(AccordionGroupContext);\n const generatedId = useId();\n const baseId = id ?? generatedId;\n const headerId = `${baseId}-header`;\n const panelId = `${baseId}-panel`;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n let isOpen: boolean;\n if (group) {\n isOpen = group.isOpen(baseId);\n } else if (open !== undefined) {\n isOpen = open;\n } else {\n isOpen = uncontrolledOpen;\n }\n\n const handleToggle = () => {\n if (group) {\n group.toggle(baseId);\n return;\n }\n\n const nextOpen = !isOpen;\n if (open === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange?.(nextOpen);\n };\n\n const grouped = group !== null;\n const wrapped = !grouped && depth > 0;\n const variantClassName = grouped\n ? 'chayns-accordion--grouped'\n : wrapped\n ? 'chayns-accordion--wrapped'\n : 'chayns-accordion--standalone';\n\n const rootClassName = [\n 'chayns-accordion',\n variantClassName,\n isOpen ? 'chayns-accordion--open' : null,\n disabled ? 'chayns-accordion--disabled' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={rootClassName}>\n <button\n aria-controls={panelId}\n aria-expanded={isOpen}\n className=\"chayns-accordion__header\"\n disabled={disabled}\n id={headerId}\n onClick={handleToggle}\n type=\"button\"\n >\n <i aria-hidden=\"true\" className=\"chayns-accordion__chevron far fa-chevron-right\" />\n <span className=\"chayns-accordion__title\">{title}</span>\n </button>\n <div\n aria-hidden={!isOpen}\n aria-labelledby={headerId}\n className=\"chayns-accordion__panel\"\n id={panelId}\n inert={!isOpen}\n role=\"region\"\n style={{ gridTemplateRows: isOpen ? '1fr' : '0fr' }}\n >\n <div className=\"chayns-accordion__inner\">\n <div className=\"chayns-accordion__content\">\n <AccordionDepthContext.Provider value={depth + 1}>\n {children}\n </AccordionDepthContext.Provider>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default Accordion;\n"],"mappings":";;;;AAKA,IAAM,aAAa,EACjB,UACA,WACA,cAAc,OACd,WAAW,OACX,IACA,cACA,MACA,YACoB;CACpB,MAAM,QAAQ,WAAW,qBAAqB;CAC9C,MAAM,QAAQ,WAAW,qBAAqB;CAC9C,MAAM,cAAc,MAAM;CAC1B,MAAM,SAAS,MAAM;CACrB,MAAM,WAAW,GAAG,OAAO;CAC3B,MAAM,UAAU,GAAG,OAAO;CAE1B,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,WAAW;CAEpE,IAAI;CACJ,IAAI,OACF,SAAS,MAAM,OAAO,MAAM;MACvB,IAAI,SAAS,KAAA,GAClB,SAAS;MAET,SAAS;CAGX,MAAM,qBAAqB;EACzB,IAAI,OAAO;GACT,MAAM,OAAO,MAAM;GACnB;EACF;EAEA,MAAM,WAAW,CAAC;EAClB,IAAI,SAAS,KAAA,GAAW,oBAAoB,QAAQ;EACpD,eAAe,QAAQ;CACzB;CAEA,MAAM,UAAU,UAAU;CAQ1B,MAAM,gBAAgB;EACpB;EAPuB,UACrB,8BAFY,CAAC,WAAW,QAAQ,IAI9B,8BACA;EAKJ,SAAS,2BAA2B;EACpC,WAAW,+BAA+B;EAC1C;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEX,OACE,qBAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACE,qBAAC,UAAD;GACE,iBAAe;GACf,iBAAe;GACf,WAAU;GACA;GACV,IAAI;GACJ,SAAS;GACT,MAAK;GAPP,UAAA,CASE,oBAAC,KAAD;IAAG,eAAY;IAAO,WAAU;GAAkD,CAAA,GAClF,oBAAC,QAAD;IAAM,WAAU;IAA2B,UAAA;GAAY,CAAA,CACjD;EACR,CAAA,GAAA,oBAAC,OAAD;GACE,eAAa,CAAC;GACd,mBAAiB;GACjB,WAAU;GACV,IAAI;GACJ,OAAO,CAAC;GACR,MAAK;GACL,OAAO,EAAE,kBAAkB,SAAS,QAAQ,MAAM;GAElD,UAAA,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,oBAAC,OAAD;KAAK,WAAU;KACb,UAAA,oBAAC,sBAAsB,UAAvB;MAAgC,OAAO,QAAQ;MAC5C;KAC6B,CAAA;IAC7B,CAAA;GACF,CAAA;EACF,CAAA,CACF;;AAET"}
1
+ {"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.tsx"],"sourcesContent":["import { useContext, useId, useState } from 'react';\n\nimport { AccordionDepthContext, AccordionGroupContext } from './AccordionContext.js';\nimport type { AccordionProps } from './Accordion.types.js';\n\nconst Accordion = ({\n children,\n className,\n defaultOpen = false,\n disabled = false,\n id,\n onOpenChange,\n open,\n ref,\n title,\n ...rootProps\n}: AccordionProps) => {\n const depth = useContext(AccordionDepthContext);\n const group = useContext(AccordionGroupContext);\n const generatedId = useId();\n const baseId = id ?? generatedId;\n const headerId = `${baseId}-header`;\n const panelId = `${baseId}-panel`;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n const isGrouped = group !== null && depth === 0;\n\n let isOpen: boolean;\n if (isGrouped) {\n isOpen = group.isOpen(baseId);\n } else if (open !== undefined) {\n isOpen = open;\n } else {\n isOpen = uncontrolledOpen;\n }\n\n const handleToggle = () => {\n if (isGrouped) {\n group.toggle(baseId);\n return;\n }\n\n const nextOpen = !isOpen;\n if (open === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange?.(nextOpen);\n };\n\n const wrapped = depth > 0;\n const variantClassName = isGrouped\n ? 'chayns-accordion--grouped'\n : wrapped\n ? 'chayns-accordion--wrapped'\n : 'chayns-accordion--standalone';\n\n const rootClassName = [\n 'chayns-accordion',\n variantClassName,\n isOpen ? 'chayns-accordion--open' : null,\n disabled ? 'chayns-accordion--disabled' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div {...rootProps} className={rootClassName} id={id} ref={ref}>\n <button\n aria-controls={panelId}\n aria-expanded={isOpen}\n className=\"chayns-accordion__header\"\n disabled={disabled}\n id={headerId}\n onClick={handleToggle}\n type=\"button\"\n >\n <i aria-hidden=\"true\" className=\"chayns-accordion__chevron far fa-chevron-right\" />\n <span className=\"chayns-accordion__title\">{title}</span>\n </button>\n <div\n aria-hidden={!isOpen}\n aria-labelledby={headerId}\n className=\"chayns-accordion__panel\"\n id={panelId}\n inert={!isOpen}\n role=\"region\"\n style={{ gridTemplateRows: isOpen ? '1fr' : '0fr' }}\n >\n <div className=\"chayns-accordion__inner\">\n <div className=\"chayns-accordion__content\">\n <AccordionDepthContext.Provider value={depth + 1}>\n {children}\n </AccordionDepthContext.Provider>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default Accordion;\n"],"mappings":";;;;AAKA,IAAM,aAAa,EACjB,UACA,WACA,cAAc,OACd,WAAW,OACX,IACA,cACA,MACA,KACA,OACA,GAAG,gBACiB;CACpB,MAAM,QAAQ,WAAW,qBAAqB;CAC9C,MAAM,QAAQ,WAAW,qBAAqB;CAC9C,MAAM,cAAc,MAAM;CAC1B,MAAM,SAAS,MAAM;CACrB,MAAM,WAAW,GAAG,OAAO;CAC3B,MAAM,UAAU,GAAG,OAAO;CAE1B,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,WAAW;CAEpE,MAAM,YAAY,UAAU,QAAQ,UAAU;CAE9C,IAAI;CACJ,IAAI,WACF,SAAS,MAAM,OAAO,MAAM;MACvB,IAAI,SAAS,KAAA,GAClB,SAAS;MAET,SAAS;CAGX,MAAM,qBAAqB;EACzB,IAAI,WAAW;GACb,MAAM,OAAO,MAAM;GACnB;EACF;EAEA,MAAM,WAAW,CAAC;EAClB,IAAI,SAAS,KAAA,GAAW,oBAAoB,QAAQ;EACpD,eAAe,QAAQ;CACzB;CASA,MAAM,gBAAgB;EACpB;EAPuB,YACrB,8BAFY,QAAQ,IAIlB,8BACA;EAKJ,SAAS,2BAA2B;EACpC,WAAW,+BAA+B;EAC1C;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEX,OACE,qBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAmB;EAAS;EAA3D,UAAA,CACE,qBAAC,UAAD;GACE,iBAAe;GACf,iBAAe;GACf,WAAU;GACA;GACV,IAAI;GACJ,SAAS;GACT,MAAK;GAPP,UAAA,CASE,oBAAC,KAAD;IAAG,eAAY;IAAO,WAAU;GAAkD,CAAA,GAClF,oBAAC,QAAD;IAAM,WAAU;IAA2B,UAAA;GAAY,CAAA,CACjD;EACR,CAAA,GAAA,oBAAC,OAAD;GACE,eAAa,CAAC;GACd,mBAAiB;GACjB,WAAU;GACV,IAAI;GACJ,OAAO,CAAC;GACR,MAAK;GACL,OAAO,EAAE,kBAAkB,SAAS,QAAQ,MAAM;GAElD,UAAA,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,oBAAC,OAAD;KAAK,WAAU;KACb,UAAA,oBAAC,sBAAsB,UAAvB;MAAgC,OAAO,QAAQ;MAC5C;KAC6B,CAAA;IAC7B,CAAA;GACF,CAAA;EACF,CAAA,CACF;;AAET"}
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
2
  /**
3
3
  * @description Props for a single disclosure accordion: a header button that
4
4
  * expands and collapses an associated content region. Nesting an `Accordion`
@@ -6,7 +6,7 @@ import type { ReactNode } from 'react';
6
6
  * context and rendered as the "Wrapped" presentation — there is no separate
7
7
  * component or prop for that case.
8
8
  */
9
- export interface AccordionProps {
9
+ export interface AccordionProps extends Omit<ComponentPropsWithRef<'div'>, 'children' | 'id' | 'title'> {
10
10
  /**
11
11
  * @description Visible, localized header label used as the accordion's
12
12
  * accessible name.
@@ -54,7 +54,7 @@ export interface AccordionProps {
54
54
  * one child `Accordion` is open at a time, and the group renders its
55
55
  * children as one joined surface.
56
56
  */
57
- export interface AccordionGroupProps {
57
+ export interface AccordionGroupProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
58
58
  /**
59
59
  * @description `Accordion` items belonging to the group.
60
60
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.types.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAE/C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"Accordion.types.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,GAAG,IAAI,GAAG,OAAO,CAC5B;IACC;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzF;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAE/C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -1,4 +1,4 @@
1
1
  import type { AccordionGroupProps } from '../accordion/Accordion.types.js';
2
- declare const AccordionGroup: ({ children, className, defaultOpenId, onOpenChange, openId, }: AccordionGroupProps) => import("react").JSX.Element;
2
+ declare const AccordionGroup: ({ children, className, defaultOpenId, onOpenChange, openId, ref, ...rootProps }: AccordionGroupProps) => import("react").JSX.Element;
3
3
  export default AccordionGroup;
4
4
  //# sourceMappingURL=AccordionGroup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionGroup.d.ts","sourceRoot":"","sources":["../../../src/components/accordion-group/AccordionGroup.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,QAAA,MAAM,cAAc,GAAI,+DAMrB,mBAAmB,gCA6BrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"AccordionGroup.d.ts","sourceRoot":"","sources":["../../../src/components/accordion-group/AccordionGroup.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,QAAA,MAAM,cAAc,GAAI,iFAQrB,mBAAmB,gCA+BrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -2,7 +2,7 @@ import { AccordionGroupContext } from "../accordion/AccordionContext.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { useCallback, useMemo, useState } from "react";
4
4
  //#region src/components/accordion-group/AccordionGroup.tsx
5
- var AccordionGroup = ({ children, className, defaultOpenId = null, onOpenChange, openId }) => {
5
+ var AccordionGroup = ({ children, className, defaultOpenId = null, onOpenChange, openId, ref, ...rootProps }) => {
6
6
  const [uncontrolledOpenId, setUncontrolledOpenId] = useState(defaultOpenId);
7
7
  const isControlled = openId !== void 0;
8
8
  const currentOpenId = isControlled ? openId : uncontrolledOpenId;
@@ -24,7 +24,9 @@ var AccordionGroup = ({ children, className, defaultOpenId = null, onOpenChange,
24
24
  return /* @__PURE__ */ jsx(AccordionGroupContext.Provider, {
25
25
  value: contextValue,
26
26
  children: /* @__PURE__ */ jsx("div", {
27
+ ...rootProps,
27
28
  className: rootClassName,
29
+ ref,
28
30
  children
29
31
  })
30
32
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionGroup.js","names":[],"sources":["../../../src/components/accordion-group/AccordionGroup.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\n\nimport { AccordionGroupContext } from '../accordion/AccordionContext.js';\nimport type { AccordionGroupContextValue } from '../accordion/AccordionContext.js';\nimport type { AccordionGroupProps } from '../accordion/Accordion.types.js';\n\nconst 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,IAAM,kBAAkB,EACtB,UACA,WACA,gBAAgB,MAChB,cACA,aACyB;CACzB,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
+ {"version":3,"file":"AccordionGroup.js","names":[],"sources":["../../../src/components/accordion-group/AccordionGroup.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\n\nimport { AccordionGroupContext } from '../accordion/AccordionContext.js';\nimport type { AccordionGroupContextValue } from '../accordion/AccordionContext.js';\nimport type { AccordionGroupProps } from '../accordion/Accordion.types.js';\n\nconst AccordionGroup = ({\n children,\n className,\n defaultOpenId = null,\n onOpenChange,\n openId,\n ref,\n ...rootProps\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 {...rootProps} className={rootClassName} ref={ref}>\n {children}\n </div>\n </AccordionGroupContext.Provider>\n );\n};\n\nexport default AccordionGroup;\n"],"mappings":";;;;AAMA,IAAM,kBAAkB,EACtB,UACA,WACA,gBAAgB,MAChB,cACA,QACA,KACA,GAAG,gBACsB;CACzB,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,GAAI;GAAW,WAAW;GAAoB;GAChD;EACE,CAAA;CACyB,CAAA;AAEpC"}
@@ -1,4 +1,4 @@
1
1
  import type { AvatarProps } from './Avatar.types.js';
2
- declare const Avatar: ({ alt, badge, className, id, name, size, src }: AvatarProps) => import("react").JSX.Element;
2
+ declare const Avatar: import("react").ForwardRefExoticComponent<Omit<AvatarProps, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
3
3
  export default Avatar;
4
4
  //# sourceMappingURL=Avatar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAsBrD,QAAA,MAAM,MAAM,GAAI,gDAA4D,WAAW,gCAuCtF,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAsBrD,QAAA,MAAM,MAAM,sHA2CV,CAAC;AAEH,eAAe,MAAM,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { forwardRef, useState } from "react";
3
3
  //#region src/components/avatar/Avatar.tsx
4
4
  var getInitials = (name) => {
5
5
  const words = name.trim().split(/\s+/).filter(Boolean);
@@ -11,21 +11,22 @@ var getTone = (name) => {
11
11
  for (const character of name) hash = hash * 31 + character.codePointAt(0) >>> 0;
12
12
  return hash % 3;
13
13
  };
14
- var Avatar = ({ alt, badge, className, id, name, size = "default", src }) => {
14
+ var Avatar = forwardRef(function Avatar({ alt, badge, className, name, size = "default", src, ...spanProps }, ref) {
15
15
  const [failedSource, setFailedSource] = useState();
16
16
  const showImage = Boolean(src) && failedSource !== src;
17
17
  const initials = getInitials(name);
18
18
  const tone = getTone(name);
19
19
  return /* @__PURE__ */ jsxs("span", {
20
+ ...spanProps,
20
21
  "aria-label": alt ?? name,
21
22
  className: [
22
23
  "chayns-avatar",
23
24
  `chayns-avatar--tone-${tone}`,
24
- size === "small" ? "chayns-avatar--small" : null,
25
+ `chayns-avatar--${size}`,
25
26
  className
26
27
  ].filter(Boolean).join(" "),
27
- id,
28
28
  role: "img",
29
+ ref,
29
30
  children: [showImage ? /* @__PURE__ */ jsx("img", {
30
31
  alt: "",
31
32
  className: "chayns-avatar__image",
@@ -41,7 +42,7 @@ var Avatar = ({ alt, badge, className, id, name, size = "default", src }) => {
41
42
  children: badge
42
43
  }) : null]
43
44
  });
44
- };
45
+ });
45
46
  //#endregion
46
47
  export { Avatar as default };
47
48
 
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","names":[],"sources":["../../../src/components/avatar/Avatar.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport type { AvatarProps } from './Avatar.types.js';\n\nconst getInitials = (name: string) => {\n const words = name.trim().split(/\\s+/).filter(Boolean);\n if (words.length === 0) {\n return '';\n }\n\n const first = words[0]?.charAt(0) ?? '';\n const last = words.length > 1 ? (words.at(-1)?.charAt(0) ?? '') : '';\n return `${first}${last}`.toUpperCase();\n};\n\nconst getTone = (name: string) => {\n let hash = 0;\n for (const character of name) {\n hash = (hash * 31 + character.codePointAt(0)!) >>> 0;\n }\n\n return hash % 3;\n};\n\nconst Avatar = ({ alt, badge, className, id, name, size = 'default', src }: AvatarProps) => {\n const [failedSource, setFailedSource] = useState<string>();\n const showImage = Boolean(src) && failedSource !== src;\n const initials = getInitials(name);\n const tone = getTone(name);\n\n return (\n <span\n aria-label={alt ?? name}\n className={[\n 'chayns-avatar',\n `chayns-avatar--tone-${tone}`,\n size === 'small' ? 'chayns-avatar--small' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n id={id}\n role=\"img\"\n >\n {showImage ? (\n <img\n alt=\"\"\n className=\"chayns-avatar__image\"\n onError={() => setFailedSource(src)}\n src={src}\n />\n ) : (\n <span aria-hidden=\"true\" className=\"chayns-avatar__initials\">\n {initials}\n </span>\n )}\n {badge ? (\n <span aria-hidden=\"true\" className=\"chayns-avatar__badge\">\n {badge}\n </span>\n ) : null}\n </span>\n );\n};\n\nexport default Avatar;\n"],"mappings":";;;AAIA,IAAM,eAAe,SAAiB;CACpC,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CACrD,IAAI,MAAM,WAAW,GACnB,OAAO;CAKT,OAAO,GAFO,MAAM,EAAE,EAAE,OAAO,CAAC,KAAK,KACxB,MAAM,SAAS,IAAK,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,KAAK,KAAM,KACzC,YAAY;AACvC;AAEA,IAAM,WAAW,SAAiB;CAChC,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,MACtB,OAAQ,OAAO,KAAK,UAAU,YAAY,CAAC,MAAQ;CAGrD,OAAO,OAAO;AAChB;AAEA,IAAM,UAAU,EAAE,KAAK,OAAO,WAAW,IAAI,MAAM,OAAO,WAAW,UAAuB;CAC1F,MAAM,CAAC,cAAc,mBAAmB,SAAiB;CACzD,MAAM,YAAY,QAAQ,GAAG,KAAK,iBAAiB;CACnD,MAAM,WAAW,YAAY,IAAI;CACjC,MAAM,OAAO,QAAQ,IAAI;CAEzB,OACE,qBAAC,QAAD;EACE,cAAY,OAAO;EACnB,WAAW;GACT;GACA,uBAAuB;GACvB,SAAS,UAAU,yBAAyB;GAC5C;EACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EACP;EACJ,MAAK;EAXP,UAAA,CAaG,YACC,oBAAC,OAAD;GACE,KAAI;GACJ,WAAU;GACV,eAAe,gBAAgB,GAAG;GAC7B;EACN,CAAA,IAED,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAChC,UAAA;EACG,CAAA,GAEP,QACC,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAChC,UAAA;EACG,CAAA,IACJ,IACA;;AAEV"}
1
+ {"version":3,"file":"Avatar.js","names":[],"sources":["../../../src/components/avatar/Avatar.tsx"],"sourcesContent":["import { forwardRef, useState } from 'react';\n\nimport type { AvatarProps } from './Avatar.types.js';\n\nconst getInitials = (name: string) => {\n const words = name.trim().split(/\\s+/).filter(Boolean);\n if (words.length === 0) {\n return '';\n }\n\n const first = words[0]?.charAt(0) ?? '';\n const last = words.length > 1 ? (words.at(-1)?.charAt(0) ?? '') : '';\n return `${first}${last}`.toUpperCase();\n};\n\nconst getTone = (name: string) => {\n let hash = 0;\n for (const character of name) {\n hash = (hash * 31 + character.codePointAt(0)!) >>> 0;\n }\n\n return hash % 3;\n};\n\nconst Avatar = forwardRef<HTMLSpanElement, AvatarProps>(function Avatar(\n { alt, badge, className, name, size = 'default', src, ...spanProps },\n ref,\n) {\n const [failedSource, setFailedSource] = useState<string>();\n const showImage = Boolean(src) && failedSource !== src;\n const initials = getInitials(name);\n const tone = getTone(name);\n\n return (\n <span\n {...spanProps}\n aria-label={alt ?? name}\n className={[\n 'chayns-avatar',\n `chayns-avatar--tone-${tone}`,\n `chayns-avatar--${size}`,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n role=\"img\"\n ref={ref}\n >\n {showImage ? (\n <img\n alt=\"\"\n className=\"chayns-avatar__image\"\n onError={() => setFailedSource(src)}\n src={src}\n />\n ) : (\n <span aria-hidden=\"true\" className=\"chayns-avatar__initials\">\n {initials}\n </span>\n )}\n {badge ? (\n <span aria-hidden=\"true\" className=\"chayns-avatar__badge\">\n {badge}\n </span>\n ) : null}\n </span>\n );\n});\n\nexport default Avatar;\n"],"mappings":";;;AAIA,IAAM,eAAe,SAAiB;CACpC,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CACrD,IAAI,MAAM,WAAW,GACnB,OAAO;CAKT,OAAO,GAFO,MAAM,EAAE,EAAE,OAAO,CAAC,KAAK,KACxB,MAAM,SAAS,IAAK,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,KAAK,KAAM,KACzC,YAAY;AACvC;AAEA,IAAM,WAAW,SAAiB;CAChC,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,MACtB,OAAQ,OAAO,KAAK,UAAU,YAAY,CAAC,MAAQ;CAGrD,OAAO,OAAO;AAChB;AAEA,IAAM,SAAS,WAAyC,SAAS,OAC/D,EAAE,KAAK,OAAO,WAAW,MAAM,OAAO,WAAW,KAAK,GAAG,aACzD,KACA;CACA,MAAM,CAAC,cAAc,mBAAmB,SAAiB;CACzD,MAAM,YAAY,QAAQ,GAAG,KAAK,iBAAiB;CACnD,MAAM,WAAW,YAAY,IAAI;CACjC,MAAM,OAAO,QAAQ,IAAI;CAEzB,OACE,qBAAC,QAAD;EACE,GAAI;EACJ,cAAY,OAAO;EACnB,WAAW;GACT;GACA,uBAAuB;GACvB,kBAAkB;GAClB;EACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EACX,MAAK;EACA;EAZP,UAAA,CAcG,YACC,oBAAC,OAAD;GACE,KAAI;GACJ,WAAU;GACV,eAAe,gBAAgB,GAAG;GAC7B;EACN,CAAA,IAED,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAChC,UAAA;EACG,CAAA,GAEP,QACC,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAChC,UAAA;EACG,CAAA,IACJ,IACA;;AAEV,CAAC"}
@@ -1,11 +1,11 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
2
  /**
3
3
  * @description Props for a single circular identity avatar: an image with a
4
4
  * deterministic initials-and-tone fallback. `size` is a designer-approved
5
5
  * local geometry variant for this component, not a global S/M/L density
6
6
  * variant.
7
7
  */
8
- export interface AvatarProps {
8
+ export interface AvatarProps extends Omit<ComponentPropsWithRef<'span'>, 'children' | 'role' | 'aria-label'> {
9
9
  /**
10
10
  * @description Full name used to derive both the accessible name (unless
11
11
  * `alt` is given) and the initials fallback shown when no image is
@@ -16,7 +16,7 @@ export interface AvatarProps {
16
16
  * @description Avatar geometry variant.
17
17
  * @default 'default'
18
18
  */
19
- size?: 'default' | 'small';
19
+ size?: 'default' | 'small' | 'large';
20
20
  /**
21
21
  * @description Optional image source. Initials are shown instead when
22
22
  * omitted or when the image fails to load.
@@ -34,13 +34,5 @@ export interface AvatarProps {
34
34
  * `aria-hidden` — any meaning it conveys must also be available elsewhere.
35
35
  */
36
36
  badge?: ReactNode;
37
- /**
38
- * @description Additional class names appended to the avatar root element.
39
- */
40
- className?: string;
41
- /**
42
- * @description Optional id on the avatar root element.
43
- */
44
- id?: string;
45
37
  }
46
38
  //# sourceMappingURL=Avatar.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.types.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAE3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
1
+ {"version":3,"file":"Avatar.types.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,WAAY,SAAQ,IAAI,CACvC,qBAAqB,CAAC,MAAM,CAAC,EAC7B,UAAU,GAAG,MAAM,GAAG,YAAY,CACnC;IACC;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAErC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB"}
@@ -1,4 +1,4 @@
1
1
  import type { AvatarGroupProps } from './AvatarGroup.types.js';
2
- declare const AvatarGroup: ({ children, className, id, max, size }: AvatarGroupProps) => import("react").JSX.Element;
2
+ declare const AvatarGroup: import("react").ForwardRefExoticComponent<Omit<AvatarGroupProps, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
3
3
  export default AvatarGroup;
4
4
  //# sourceMappingURL=AvatarGroup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.d.ts","sourceRoot":"","sources":["../../../src/components/avatar-group/AvatarGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,QAAA,MAAM,WAAW,GAAI,wCAAoD,gBAAgB,gCA6BxF,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"AvatarGroup.d.ts","sourceRoot":"","sources":["../../../src/components/avatar-group/AvatarGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,QAAA,MAAM,WAAW,2HA6Bf,CAAC;AAEH,eAAe,WAAW,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsxs } from "react/jsx-runtime";
2
- import { Children, cloneElement, isValidElement } from "react";
2
+ import { Children, cloneElement, forwardRef, isValidElement } from "react";
3
3
  //#region src/components/avatar-group/AvatarGroup.tsx
4
- var AvatarGroup = ({ children, className, id, max, size = "default" }) => {
4
+ var AvatarGroup = forwardRef(function AvatarGroup({ children, className, max, size = "default", ...spanProps }, ref) {
5
5
  const avatars = Children.toArray(children).filter((child) => isValidElement(child));
6
6
  const limited = typeof max === "number" && max > 0;
7
7
  const visibleCount = limited ? Math.max(max - 1, 0) : avatars.length;
@@ -9,17 +9,18 @@ var AvatarGroup = ({ children, className, id, max, size = "default" }) => {
9
9
  return /* @__PURE__ */ jsxs("span", {
10
10
  className: [
11
11
  "chayns-avatar-group",
12
- size === "small" ? "chayns-avatar-group--small" : null,
12
+ `chayns-avatar-group--${size}`,
13
13
  className
14
14
  ].filter(Boolean).join(" "),
15
- id,
15
+ ...spanProps,
16
+ ref,
16
17
  children: [avatars.slice(0, visibleCount).map((avatar) => cloneElement(avatar, { size })), overflowCount > 0 ? /* @__PURE__ */ jsxs("span", {
17
18
  "aria-hidden": "true",
18
19
  className: "chayns-avatar-group__overflow",
19
20
  children: ["+", overflowCount]
20
21
  }) : null]
21
22
  });
22
- };
23
+ });
23
24
  //#endregion
24
25
  export { AvatarGroup as default };
25
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.js","names":[],"sources":["../../../src/components/avatar-group/AvatarGroup.tsx"],"sourcesContent":["import { Children, cloneElement, isValidElement } from 'react';\n\nimport type { AvatarProps } from '../avatar/Avatar.types.js';\nimport type { AvatarGroupProps } from './AvatarGroup.types.js';\n\nconst AvatarGroup = ({ children, className, id, max, size = 'default' }: AvatarGroupProps) => {\n const avatars = Children.toArray(children).filter((child) => isValidElement<AvatarProps>(child));\n const limited = typeof max === 'number' && max > 0;\n const visibleCount = limited ? Math.max(max - 1, 0) : avatars.length;\n const overflowCount = limited && avatars.length > max ? avatars.length - visibleCount : 0;\n\n return (\n <span\n className={[\n 'chayns-avatar-group',\n size === 'small' ? 'chayns-avatar-group--small' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n id={id}\n >\n {avatars.slice(0, visibleCount).map((avatar) =>\n cloneElement(avatar, {\n size,\n }),\n )}\n {overflowCount > 0 ? (\n <span aria-hidden=\"true\" className=\"chayns-avatar-group__overflow\">\n +{overflowCount}\n </span>\n ) : null}\n </span>\n );\n};\n\nexport default AvatarGroup;\n"],"mappings":";;;AAKA,IAAM,eAAe,EAAE,UAAU,WAAW,IAAI,KAAK,OAAO,gBAAkC;CAC5F,MAAM,UAAU,SAAS,QAAQ,QAAQ,CAAC,CAAC,QAAQ,UAAU,eAA4B,KAAK,CAAC;CAC/F,MAAM,UAAU,OAAO,QAAQ,YAAY,MAAM;CACjD,MAAM,eAAe,UAAU,KAAK,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ;CAC9D,MAAM,gBAAgB,WAAW,QAAQ,SAAS,MAAM,QAAQ,SAAS,eAAe;CAExF,OACE,qBAAC,QAAD;EACE,WAAW;GACT;GACA,SAAS,UAAU,+BAA+B;GAClD;EACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EACP;EARN,UAAA,CAUG,QAAQ,MAAM,GAAG,YAAY,CAAC,CAAC,KAAK,WACnC,aAAa,QAAQ,EACnB,KACF,CAAC,CACH,GACC,gBAAgB,IACf,qBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAAnC,UAAA,CAAmE,KAC/D,aACE;EACJ,CAAA,IAAA,IACA;;AAEV"}
1
+ {"version":3,"file":"AvatarGroup.js","names":[],"sources":["../../../src/components/avatar-group/AvatarGroup.tsx"],"sourcesContent":["import { Children, cloneElement, forwardRef, isValidElement } from 'react';\n\nimport type { AvatarProps } from '../avatar/Avatar.types.js';\nimport type { AvatarGroupProps } from './AvatarGroup.types.js';\n\nconst AvatarGroup = forwardRef<HTMLSpanElement, AvatarGroupProps>(function AvatarGroup(\n { children, className, max, size = 'default', ...spanProps },\n ref,\n) {\n const avatars = Children.toArray(children).filter((child) => isValidElement<AvatarProps>(child));\n const limited = typeof max === 'number' && max > 0;\n const visibleCount = limited ? Math.max(max - 1, 0) : avatars.length;\n const overflowCount = limited && avatars.length > max ? avatars.length - visibleCount : 0;\n\n return (\n <span\n className={['chayns-avatar-group', `chayns-avatar-group--${size}`, className]\n .filter(Boolean)\n .join(' ')}\n {...spanProps}\n ref={ref}\n >\n {avatars.slice(0, visibleCount).map((avatar) =>\n cloneElement(avatar, {\n size,\n }),\n )}\n {overflowCount > 0 ? (\n <span aria-hidden=\"true\" className=\"chayns-avatar-group__overflow\">\n +{overflowCount}\n </span>\n ) : null}\n </span>\n );\n});\n\nexport default AvatarGroup;\n"],"mappings":";;;AAKA,IAAM,cAAc,WAA8C,SAAS,YACzE,EAAE,UAAU,WAAW,KAAK,OAAO,WAAW,GAAG,aACjD,KACA;CACA,MAAM,UAAU,SAAS,QAAQ,QAAQ,CAAC,CAAC,QAAQ,UAAU,eAA4B,KAAK,CAAC;CAC/F,MAAM,UAAU,OAAO,QAAQ,YAAY,MAAM;CACjD,MAAM,eAAe,UAAU,KAAK,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ;CAC9D,MAAM,gBAAgB,WAAW,QAAQ,SAAS,MAAM,QAAQ,SAAS,eAAe;CAExF,OACE,qBAAC,QAAD;EACE,WAAW;GAAC;GAAuB,wBAAwB;GAAQ;EAAS,CAAC,CAC1E,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EACX,GAAI;EACC;EALP,UAAA,CAOG,QAAQ,MAAM,GAAG,YAAY,CAAC,CAAC,KAAK,WACnC,aAAa,QAAQ,EACnB,KACF,CAAC,CACH,GACC,gBAAgB,IACf,qBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAAnC,UAAA,CAAmE,KAC/D,aACE;EACJ,CAAA,IAAA,IACA;;AAEV,CAAC"}
@@ -1,10 +1,10 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
2
  import type { AvatarProps } from '../avatar/Avatar.types.js';
3
3
  /**
4
4
  * @description Props for a compact, overlapping stack of `Avatar` children
5
5
  * with an overflow tile once `max` is exceeded.
6
6
  */
7
- export interface AvatarGroupProps {
7
+ export interface AvatarGroupProps extends Omit<ComponentPropsWithRef<'span'>, 'children'> {
8
8
  /**
9
9
  * @description `Avatar` children displayed with overlap, in order.
10
10
  */
@@ -21,13 +21,5 @@ export interface AvatarGroupProps {
21
21
  * @default 'default'
22
22
  */
23
23
  size?: AvatarProps['size'];
24
- /**
25
- * @description Additional class names appended to the group root element.
26
- */
27
- className?: string;
28
- /**
29
- * @description Optional id on the group root element.
30
- */
31
- id?: string;
32
24
  }
33
25
  //# sourceMappingURL=AvatarGroup.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.types.d.ts","sourceRoot":"","sources":["../../../src/components/avatar-group/AvatarGroup.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
1
+ {"version":3,"file":"AvatarGroup.types.d.ts","sourceRoot":"","sources":["../../../src/components/avatar-group/AvatarGroup.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IACvF;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC5B"}
@@ -0,0 +1,4 @@
1
+ import type { BadgeProps } from './Badge.types.js';
2
+ declare const Badge: import("react").ForwardRefExoticComponent<Omit<BadgeProps, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
3
+ export default Badge;
4
+ //# sourceMappingURL=Badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/badge/Badge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,QAAA,MAAM,KAAK,qHAwBT,CAAC;AAEH,eAAe,KAAK,CAAC"}