@chayns-ui/core 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card.css +8 -6
- package/dist/components/accordion/Accordion.d.ts.map +1 -1
- package/dist/components/accordion/Accordion.js +12 -9
- package/dist/components/accordion/Accordion.js.map +1 -1
- package/dist/components/accordion/Accordion.types.d.ts +4 -1
- package/dist/components/accordion/Accordion.types.d.ts.map +1 -1
- package/dist/components/accordion/Accordion.types.js.map +1 -1
- package/dist/components/accordion/AccordionContext.d.ts +3 -0
- package/dist/components/accordion/AccordionContext.d.ts.map +1 -1
- package/dist/components/accordion/AccordionContext.js.map +1 -1
- package/dist/components/card/Card.d.ts.map +1 -1
- package/dist/components/card/Card.js +6 -2
- package/dist/components/card/Card.js.map +1 -1
- package/dist/components/card/Card.types.d.ts +5 -0
- package/dist/components/card/Card.types.d.ts.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.js +32 -4
- package/dist/components/date-time-picker/DateTimePicker.js.map +1 -1
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.d.ts.map +1 -1
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js +20 -1
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js.map +1 -1
- package/dist/components/date-time-picker/wheel/Wheel.d.ts.map +1 -1
- package/dist/components/date-time-picker/wheel/Wheel.js +11 -4
- package/dist/components/date-time-picker/wheel/Wheel.js.map +1 -1
- package/dist/date-time-picker.css +20 -5
- package/dist/hooks/useOverlayPosition.d.ts +1 -1
- package/dist/hooks/useOverlayPosition.d.ts.map +1 -1
- package/dist/hooks/useOverlayPosition.js +3 -1
- package/dist/hooks/useOverlayPosition.js.map +1 -1
- package/package.json +1 -1
package/dist/card.css
CHANGED
|
@@ -43,24 +43,26 @@
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
@media (hover: hover) {
|
|
46
|
-
.chayns-card:hover {
|
|
46
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover {
|
|
47
47
|
box-shadow: var(--shadow-hover);
|
|
48
48
|
transform: translateY(-4px);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
.chayns-card:hover .chayns-card__header-icon {
|
|
51
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover .chayns-card__header-icon {
|
|
52
52
|
transform: scale(1.08);
|
|
53
53
|
background: var(--accent);
|
|
54
54
|
color: var(--on-accent);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
.chayns-card:hover
|
|
57
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover
|
|
58
58
|
.chayns-card__header-icon
|
|
59
59
|
.chayns-button-icon__weight:not(.chayns-button-icon__weight--active) {
|
|
60
60
|
display: none;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
.chayns-card:
|
|
63
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover
|
|
64
|
+
.chayns-card__header-icon
|
|
65
|
+
.chayns-button-icon__weight--active {
|
|
64
66
|
display: inline-flex;
|
|
65
67
|
}
|
|
66
68
|
}
|
|
@@ -71,8 +73,8 @@
|
|
|
71
73
|
transition: none;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
.chayns-card:hover,
|
|
75
|
-
.chayns-card:hover .chayns-card__header-icon {
|
|
76
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover,
|
|
77
|
+
.chayns-card:not(.chayns-card--hover-disabled):hover .chayns-card__header-icon {
|
|
76
78
|
transform: none;
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACf,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/Accordion.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAsN9B,QAAA,MAAM,SAAS;;;;;;;CAOb,CAAC;AASH,eAAe,SAAS,CAAC"}
|
|
@@ -58,7 +58,7 @@ var AccordionHead = forwardRef(function AccordionHead({ children, className, onC
|
|
|
58
58
|
});
|
|
59
59
|
var AccordionContent = forwardRef(function AccordionContent({ children, className, ...panelProps }, ref) {
|
|
60
60
|
const depth = useContext(AccordionDepthContext);
|
|
61
|
-
const { headerId, isOpen, panelId } = useAccordionItemContext("Content");
|
|
61
|
+
const { hasContentPadding, headerId, isOpen, nestedContent, panelId } = useAccordionItemContext("Content");
|
|
62
62
|
return /* @__PURE__ */ jsx("div", {
|
|
63
63
|
...panelProps,
|
|
64
64
|
"aria-hidden": !isOpen,
|
|
@@ -74,14 +74,14 @@ var AccordionContent = forwardRef(function AccordionContent({ children, classNam
|
|
|
74
74
|
},
|
|
75
75
|
children: /* @__PURE__ */ jsx("div", {
|
|
76
76
|
className: "chayns-accordion__inner",
|
|
77
|
-
children: /* @__PURE__ */ jsx(
|
|
78
|
-
|
|
79
|
-
children: /* @__PURE__ */
|
|
80
|
-
value:
|
|
81
|
-
children: /* @__PURE__ */ jsx(
|
|
82
|
-
|
|
77
|
+
children: /* @__PURE__ */ jsx(AccordionGroupContext.Provider, {
|
|
78
|
+
value: null,
|
|
79
|
+
children: /* @__PURE__ */ jsxs(AccordionDepthContext.Provider, {
|
|
80
|
+
value: depth + 1,
|
|
81
|
+
children: [hasContentPadding ? /* @__PURE__ */ jsx("div", {
|
|
82
|
+
className: "chayns-accordion__content",
|
|
83
83
|
children
|
|
84
|
-
})
|
|
84
|
+
}) : children, nestedContent]
|
|
85
85
|
})
|
|
86
86
|
})
|
|
87
87
|
})
|
|
@@ -125,7 +125,8 @@ var AccordionRoot = forwardRef(function Accordion({ appearance = "default", chil
|
|
|
125
125
|
const hasCompoundHead = compoundHead !== void 0;
|
|
126
126
|
const compoundContent = directChildren.find((child) => isValidElement(child) && child.type === AccordionContent);
|
|
127
127
|
const hasCompoundContent = compoundContent !== void 0;
|
|
128
|
-
const panelChildren =
|
|
128
|
+
const panelChildren = directChildren.filter((child) => child !== compoundHead);
|
|
129
|
+
const nestedContent = hasCompoundContent ? panelChildren.filter((child) => child !== compoundContent) : null;
|
|
129
130
|
return /* @__PURE__ */ jsx("div", {
|
|
130
131
|
...rootProps,
|
|
131
132
|
className: rootClassName,
|
|
@@ -134,8 +135,10 @@ var AccordionRoot = forwardRef(function Accordion({ appearance = "default", chil
|
|
|
134
135
|
children: /* @__PURE__ */ jsxs(AccordionItemContext.Provider, {
|
|
135
136
|
value: {
|
|
136
137
|
disabled,
|
|
138
|
+
hasContentPadding: hasCompoundContent,
|
|
137
139
|
headerId,
|
|
138
140
|
isOpen,
|
|
141
|
+
nestedContent,
|
|
139
142
|
onToggle: handleToggle,
|
|
140
143
|
panelId
|
|
141
144
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.tsx"],"sourcesContent":["import ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport {\n Children,\n createElement,\n forwardRef,\n isValidElement,\n useContext,\n useId,\n useState,\n} from 'react';\nimport type { MouseEvent, ReactElement } from 'react';\n\nimport {\n AccordionDepthContext,\n AccordionGroupContext,\n AccordionItemContext,\n useAccordionItemContext,\n} from './AccordionContext.js';\nimport type {\n AccordionContentProps,\n AccordionHeadContentProps,\n AccordionHeadProps,\n AccordionPartProps,\n AccordionProps,\n} from './Accordion.types.js';\n\nfunction createHeadPart(name: 'Leading' | 'Trailing') {\n const HeadPart = forwardRef<HTMLSpanElement, AccordionPartProps>(function HeadPart(\n { children, className, ...spanProps },\n ref,\n ) {\n useAccordionItemContext(`Head.${name}`);\n return (\n <span\n {...spanProps}\n className={[`chayns-accordion__${name.toLowerCase()}`, className].filter(Boolean).join(' ')}\n ref={ref}\n >\n {children}\n </span>\n );\n });\n HeadPart.displayName = `Accordion.Head.${name}`;\n return HeadPart;\n}\n\nconst HeadLeading = createHeadPart('Leading');\nconst HeadTrailing = createHeadPart('Trailing');\n\nconst HeadContent = forwardRef<HTMLSpanElement, AccordionHeadContentProps>(function HeadContent(\n { className, subtitle, title, ...spanProps },\n ref,\n) {\n useAccordionItemContext('Head.Content');\n return (\n <span\n {...spanProps}\n className={['chayns-accordion__head-content', className].filter(Boolean).join(' ')}\n ref={ref}\n >\n <span className=\"chayns-accordion__title\">{title}</span>\n {subtitle ? <span className=\"chayns-accordion__subtitle\">{subtitle}</span> : null}\n </span>\n );\n});\n\nconst AccordionHead = forwardRef<HTMLButtonElement, AccordionHeadProps>(function AccordionHead(\n { children, className, onClick, ...buttonProps },\n ref,\n) {\n const { disabled, headerId, isOpen, onToggle, panelId } = useAccordionItemContext('Head');\n\n function handleClick(event: MouseEvent<HTMLButtonElement>) {\n onClick?.(event);\n if (!event.defaultPrevented) onToggle();\n }\n\n return (\n <button\n {...buttonProps}\n aria-controls={panelId}\n aria-expanded={isOpen}\n className={['chayns-accordion__header', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={headerId}\n onClick={handleClick}\n ref={ref}\n type=\"button\"\n >\n <span aria-hidden=\"true\" className=\"chayns-accordion__chevron\">\n <ButtonIcon icon=\"fa-chevron-right\" />\n </span>\n {children}\n </button>\n );\n});\n\nconst AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(\n function AccordionContent({ children, className, ...panelProps }, ref) {\n const depth = useContext(AccordionDepthContext);\n const { headerId, isOpen, panelId } = useAccordionItemContext('Content');\n\n return (\n <div\n {...panelProps}\n aria-hidden={!isOpen}\n aria-labelledby={headerId}\n className={['chayns-accordion__panel', className].filter(Boolean).join(' ')}\n id={panelId}\n inert={!isOpen}\n ref={ref}\n role=\"region\"\n style={{ ...panelProps.style, gridTemplateRows: isOpen ? '1fr' : '0fr' }}\n >\n <div className=\"chayns-accordion__inner\">\n <div className=\"chayns-accordion__content\">\n <AccordionGroupContext.Provider value={null}>\n <AccordionDepthContext.Provider value={depth + 1}>\n {children}\n </AccordionDepthContext.Provider>\n </AccordionGroupContext.Provider>\n </div>\n </div>\n </div>\n );\n },\n);\n\nconst AccordionRoot = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n {\n appearance = 'default',\n children,\n className,\n defaultOpen = false,\n disabled = false,\n id,\n leading,\n onOpenChange,\n open,\n subtitle,\n title,\n ...rootProps\n },\n ref,\n) {\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 const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isGrouped = group !== null;\n const isOpen = isGrouped ? group.isOpen(baseId) : (open ?? uncontrolledOpen);\n const wrapped = depth > 0;\n const isList = appearance === 'list';\n\n function 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 directChildren = Children.toArray(children);\n const compoundHead = directChildren.find(\n (child) => isValidElement(child) && child.type === AccordionHead,\n );\n const hasCompoundLeading =\n isValidElement(compoundHead) &&\n Children.toArray((compoundHead as ReactElement<AccordionHeadProps>).props.children).some(\n (child) => isValidElement(child) && child.type === HeadLeading,\n );\n const rootClassName = [\n 'chayns-accordion',\n isGrouped ? 'chayns-accordion--grouped' : null,\n wrapped ? 'chayns-accordion--wrapped' : null,\n !isGrouped && !wrapped ? 'chayns-accordion--standalone' : null,\n isOpen ? 'chayns-accordion--open' : null,\n disabled ? 'chayns-accordion--disabled' : null,\n leading || hasCompoundLeading ? 'chayns-accordion--has-leading' : null,\n isList ? 'chayns-accordion--list' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const hasCompoundHead = compoundHead !== undefined;\n const compoundContent = directChildren.find(\n (child) => isValidElement(child) && child.type === AccordionContent,\n );\n const hasCompoundContent = compoundContent !== undefined;\n const panelChildren = children;\n\n return (\n <div {...rootProps} className={rootClassName} id={id} ref={ref}>\n <AccordionItemContext.Provider\n value={{ disabled, headerId, isOpen, onToggle: handleToggle, panelId }}\n >\n {hasCompoundHead ? (\n compoundHead\n ) : (\n <AccordionHead>\n {leading ? <HeadLeading>{leading}</HeadLeading> : null}\n <HeadContent title={title} subtitle={subtitle} />\n </AccordionHead>\n )}\n {hasCompoundContent ? (\n createElement(AccordionContent, {\n ...(compoundContent as ReactElement<AccordionContentProps>).props,\n })\n ) : (\n <AccordionContent>{panelChildren}</AccordionContent>\n )}\n </AccordionItemContext.Provider>\n </div>\n );\n});\n\nconst Accordion = Object.assign(AccordionRoot, {\n Content: AccordionContent,\n Head: Object.assign(AccordionHead, {\n Content: HeadContent,\n Leading: HeadLeading,\n Trailing: HeadTrailing,\n }),\n});\n\nObject.assign(HeadLeading, { displayName: 'Accordion.Head.Leading' });\nObject.assign(HeadTrailing, { displayName: 'Accordion.Head.Trailing' });\nObject.assign(HeadContent, { displayName: 'Accordion.Head.Content' });\nAccordionHead.displayName = 'Accordion.Head';\nAccordionContent.displayName = 'Accordion.Content';\nAccordionRoot.displayName = 'Accordion';\n\nexport default Accordion;\n"],"mappings":";;;;;AA0BA,SAAS,eAAe,MAA8B;CACpD,MAAM,WAAW,WAAgD,SAAS,SACxE,EAAE,UAAU,WAAW,GAAG,aAC1B,KACA;EACA,wBAAwB,QAAQ,MAAM;EACtC,OACE,oBAAC,QAAD;GACE,GAAI;GACJ,WAAW,CAAC,qBAAqB,KAAK,YAAY,KAAK,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;GACrF;GAEJ;EACG,CAAA;CAEV,CAAC;CACD,SAAS,cAAc,kBAAkB;CACzC,OAAO;AACT;AAEA,IAAM,cAAc,eAAe,SAAS;AAC5C,IAAM,eAAe,eAAe,UAAU;AAE9C,IAAM,cAAc,WAAuD,SAAS,YAClF,EAAE,WAAW,UAAU,OAAO,GAAG,aACjC,KACA;CACA,wBAAwB,cAAc;CACtC,OACE,qBAAC,QAAD;EACE,GAAI;EACJ,WAAW,CAAC,kCAAkC,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAC5E;EAHP,UAAA,CAKE,oBAAC,QAAD;GAAM,WAAU;GAA2B,UAAA;EAAY,CAAA,GACtD,WAAW,oBAAC,QAAD;GAAM,WAAU;GAA8B,UAAA;EAAe,CAAA,IAAI,IACzE;;AAEV,CAAC;AAED,IAAM,gBAAgB,WAAkD,SAAS,cAC/E,EAAE,UAAU,WAAW,SAAS,GAAG,eACnC,KACA;CACA,MAAM,EAAE,UAAU,UAAU,QAAQ,UAAU,YAAY,wBAAwB,MAAM;CAExF,SAAS,YAAY,OAAsC;EACzD,UAAU,KAAK;EACf,IAAI,CAAC,MAAM,kBAAkB,SAAS;CACxC;CAEA,OACE,qBAAC,UAAD;EACE,GAAI;EACJ,iBAAe;EACf,iBAAe;EACf,WAAW,CAAC,4BAA4B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACjE;EACV,IAAI;EACJ,SAAS;EACJ;EACL,MAAK;EATP,UAAA,CAWE,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GACjC,UAAA,oBAAC,YAAD,EAAY,MAAK,mBAAoB,CAAA;EACjC,CAAA,GACL,QACK;;AAEZ,CAAC;AAED,IAAM,mBAAmB,WACvB,SAAS,iBAAiB,EAAE,UAAU,WAAW,GAAG,cAAc,KAAK;CACrE,MAAM,QAAQ,WAAW,qBAAqB;CAC9C,MAAM,EAAE,UAAU,QAAQ,YAAY,wBAAwB,SAAS;CAEvE,OACE,oBAAC,OAAD;EACE,GAAI;EACJ,eAAa,CAAC;EACd,mBAAiB;EACjB,WAAW,CAAC,2BAA2B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAC1E,IAAI;EACJ,OAAO,CAAC;EACH;EACL,MAAK;EACL,OAAO;GAAE,GAAG,WAAW;GAAO,kBAAkB,SAAS,QAAQ;EAAM;EAEvE,UAAA,oBAAC,OAAD;GAAK,WAAU;GACb,UAAA,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,oBAAC,sBAAsB,UAAvB;KAAgC,OAAO;KACrC,UAAA,oBAAC,sBAAsB,UAAvB;MAAgC,OAAO,QAAQ;MAC5C;KAC6B,CAAA;IACF,CAAA;GAC7B,CAAA;EACF,CAAA;CACF,CAAA;AAET,CACF;AAEA,IAAM,gBAAgB,WAA2C,SAAS,UACxE,EACE,aAAa,WACb,UACA,WACA,cAAc,OACd,WAAW,OACX,IACA,SACA,cACA,MACA,UACA,OACA,GAAG,aAEL,KACA;CACA,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;CAC1B,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,WAAW;CACpE,MAAM,YAAY,UAAU;CAC5B,MAAM,SAAS,YAAY,MAAM,OAAO,MAAM,IAAK,QAAQ;CAC3D,MAAM,UAAU,QAAQ;CACxB,MAAM,SAAS,eAAe;CAE9B,SAAS,eAAe;EACtB,IAAI,WAAW;GACb,MAAM,OAAO,MAAM;GACnB;EACF;EAEA,MAAM,WAAW,CAAC;EAClB,IAAI,SAAS,KAAA,GAAW,oBAAoB,QAAQ;EACpD,eAAe,QAAQ;CACzB;CAEA,MAAM,iBAAiB,SAAS,QAAQ,QAAQ;CAChD,MAAM,eAAe,eAAe,MACjC,UAAU,eAAe,KAAK,KAAK,MAAM,SAAS,aACrD;CACA,MAAM,qBACJ,eAAe,YAAY,KAC3B,SAAS,QAAS,aAAkD,MAAM,QAAQ,CAAC,CAAC,MACjF,UAAU,eAAe,KAAK,KAAK,MAAM,SAAS,WACrD;CACF,MAAM,gBAAgB;EACpB;EACA,YAAY,8BAA8B;EAC1C,UAAU,8BAA8B;EACxC,CAAC,aAAa,CAAC,UAAU,iCAAiC;EAC1D,SAAS,2BAA2B;EACpC,WAAW,+BAA+B;EAC1C,WAAW,qBAAqB,kCAAkC;EAClE,SAAS,2BAA2B;EACpC;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEX,MAAM,kBAAkB,iBAAiB,KAAA;CACzC,MAAM,kBAAkB,eAAe,MACpC,UAAU,eAAe,KAAK,KAAK,MAAM,SAAS,gBACrD;CACA,MAAM,qBAAqB,oBAAoB,KAAA;CAC/C,MAAM,gBAAgB;CAEtB,OACE,oBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAmB;EAAS;EACzD,UAAA,qBAAC,qBAAqB,UAAtB;GACE,OAAO;IAAE;IAAU;IAAU;IAAQ,UAAU;IAAc;GAAQ;GADvE,UAAA,CAGG,kBACC,eAEA,qBAAC,eAAD,EAAA,UAAA,CACG,UAAU,oBAAC,aAAD,EAAA,UAAc,QAAqB,CAAA,IAAI,MAClD,oBAAC,aAAD;IAAoB;IAAiB;GAAW,CAAA,CACnC,EAAA,CAAA,GAEhB,qBACC,cAAc,kBAAkB,EAC9B,GAAI,gBAAwD,MAC9D,CAAC,IAED,oBAAC,kBAAD,EAAA,UAAmB,cAAgC,CAAA,CAExB;;CAC5B,CAAA;AAET,CAAC;AAED,IAAM,YAAY,OAAO,OAAO,eAAe;CAC7C,SAAS;CACT,MAAM,OAAO,OAAO,eAAe;EACjC,SAAS;EACT,SAAS;EACT,UAAU;CACZ,CAAC;AACH,CAAC;AAED,OAAO,OAAO,aAAa,EAAE,aAAa,yBAAyB,CAAC;AACpE,OAAO,OAAO,cAAc,EAAE,aAAa,0BAA0B,CAAC;AACtE,OAAO,OAAO,aAAa,EAAE,aAAa,yBAAyB,CAAC;AACpE,cAAc,cAAc;AAC5B,iBAAiB,cAAc;AAC/B,cAAc,cAAc"}
|
|
1
|
+
{"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.tsx"],"sourcesContent":["import ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport {\n Children,\n createElement,\n forwardRef,\n isValidElement,\n useContext,\n useId,\n useState,\n} from 'react';\nimport type { MouseEvent, ReactElement } from 'react';\n\nimport {\n AccordionDepthContext,\n AccordionGroupContext,\n AccordionItemContext,\n useAccordionItemContext,\n} from './AccordionContext.js';\nimport type {\n AccordionContentProps,\n AccordionHeadContentProps,\n AccordionHeadProps,\n AccordionPartProps,\n AccordionProps,\n} from './Accordion.types.js';\n\nfunction createHeadPart(name: 'Leading' | 'Trailing') {\n const HeadPart = forwardRef<HTMLSpanElement, AccordionPartProps>(function HeadPart(\n { children, className, ...spanProps },\n ref,\n ) {\n useAccordionItemContext(`Head.${name}`);\n return (\n <span\n {...spanProps}\n className={[`chayns-accordion__${name.toLowerCase()}`, className].filter(Boolean).join(' ')}\n ref={ref}\n >\n {children}\n </span>\n );\n });\n HeadPart.displayName = `Accordion.Head.${name}`;\n return HeadPart;\n}\n\nconst HeadLeading = createHeadPart('Leading');\nconst HeadTrailing = createHeadPart('Trailing');\n\nconst HeadContent = forwardRef<HTMLSpanElement, AccordionHeadContentProps>(function HeadContent(\n { className, subtitle, title, ...spanProps },\n ref,\n) {\n useAccordionItemContext('Head.Content');\n return (\n <span\n {...spanProps}\n className={['chayns-accordion__head-content', className].filter(Boolean).join(' ')}\n ref={ref}\n >\n <span className=\"chayns-accordion__title\">{title}</span>\n {subtitle ? <span className=\"chayns-accordion__subtitle\">{subtitle}</span> : null}\n </span>\n );\n});\n\nconst AccordionHead = forwardRef<HTMLButtonElement, AccordionHeadProps>(function AccordionHead(\n { children, className, onClick, ...buttonProps },\n ref,\n) {\n const { disabled, headerId, isOpen, onToggle, panelId } = useAccordionItemContext('Head');\n\n function handleClick(event: MouseEvent<HTMLButtonElement>) {\n onClick?.(event);\n if (!event.defaultPrevented) onToggle();\n }\n\n return (\n <button\n {...buttonProps}\n aria-controls={panelId}\n aria-expanded={isOpen}\n className={['chayns-accordion__header', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={headerId}\n onClick={handleClick}\n ref={ref}\n type=\"button\"\n >\n <span aria-hidden=\"true\" className=\"chayns-accordion__chevron\">\n <ButtonIcon icon=\"fa-chevron-right\" />\n </span>\n {children}\n </button>\n );\n});\n\nconst AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(\n function AccordionContent({ children, className, ...panelProps }, ref) {\n const depth = useContext(AccordionDepthContext);\n const { hasContentPadding, headerId, isOpen, nestedContent, panelId } =\n useAccordionItemContext('Content');\n\n return (\n <div\n {...panelProps}\n aria-hidden={!isOpen}\n aria-labelledby={headerId}\n className={['chayns-accordion__panel', className].filter(Boolean).join(' ')}\n id={panelId}\n inert={!isOpen}\n ref={ref}\n role=\"region\"\n style={{ ...panelProps.style, gridTemplateRows: isOpen ? '1fr' : '0fr' }}\n >\n <div className=\"chayns-accordion__inner\">\n <AccordionGroupContext.Provider value={null}>\n <AccordionDepthContext.Provider value={depth + 1}>\n {hasContentPadding ? (\n <div className=\"chayns-accordion__content\">{children}</div>\n ) : (\n children\n )}\n {nestedContent}\n </AccordionDepthContext.Provider>\n </AccordionGroupContext.Provider>\n </div>\n </div>\n );\n },\n);\n\nconst AccordionRoot = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n {\n appearance = 'default',\n children,\n className,\n defaultOpen = false,\n disabled = false,\n id,\n leading,\n onOpenChange,\n open,\n subtitle,\n title,\n ...rootProps\n },\n ref,\n) {\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 const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isGrouped = group !== null;\n const isOpen = isGrouped ? group.isOpen(baseId) : (open ?? uncontrolledOpen);\n const wrapped = depth > 0;\n const isList = appearance === 'list';\n\n function 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 directChildren = Children.toArray(children);\n const compoundHead = directChildren.find(\n (child) => isValidElement(child) && child.type === AccordionHead,\n );\n const hasCompoundLeading =\n isValidElement(compoundHead) &&\n Children.toArray((compoundHead as ReactElement<AccordionHeadProps>).props.children).some(\n (child) => isValidElement(child) && child.type === HeadLeading,\n );\n const rootClassName = [\n 'chayns-accordion',\n isGrouped ? 'chayns-accordion--grouped' : null,\n wrapped ? 'chayns-accordion--wrapped' : null,\n !isGrouped && !wrapped ? 'chayns-accordion--standalone' : null,\n isOpen ? 'chayns-accordion--open' : null,\n disabled ? 'chayns-accordion--disabled' : null,\n leading || hasCompoundLeading ? 'chayns-accordion--has-leading' : null,\n isList ? 'chayns-accordion--list' : null,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const hasCompoundHead = compoundHead !== undefined;\n const compoundContent = directChildren.find(\n (child) => isValidElement(child) && child.type === AccordionContent,\n );\n const hasCompoundContent = compoundContent !== undefined;\n const panelChildren = directChildren.filter((child) => child !== compoundHead);\n const nestedContent = hasCompoundContent\n ? panelChildren.filter((child) => child !== compoundContent)\n : null;\n\n return (\n <div {...rootProps} className={rootClassName} id={id} ref={ref}>\n <AccordionItemContext.Provider\n value={{\n disabled,\n hasContentPadding: hasCompoundContent,\n headerId,\n isOpen,\n nestedContent,\n onToggle: handleToggle,\n panelId,\n }}\n >\n {hasCompoundHead ? (\n compoundHead\n ) : (\n <AccordionHead>\n {leading ? <HeadLeading>{leading}</HeadLeading> : null}\n <HeadContent title={title} subtitle={subtitle} />\n </AccordionHead>\n )}\n {hasCompoundContent ? (\n createElement(AccordionContent, {\n ...(compoundContent as ReactElement<AccordionContentProps>).props,\n })\n ) : (\n <AccordionContent>{panelChildren}</AccordionContent>\n )}\n </AccordionItemContext.Provider>\n </div>\n );\n});\n\nconst Accordion = Object.assign(AccordionRoot, {\n Content: AccordionContent,\n Head: Object.assign(AccordionHead, {\n Content: HeadContent,\n Leading: HeadLeading,\n Trailing: HeadTrailing,\n }),\n});\n\nObject.assign(HeadLeading, { displayName: 'Accordion.Head.Leading' });\nObject.assign(HeadTrailing, { displayName: 'Accordion.Head.Trailing' });\nObject.assign(HeadContent, { displayName: 'Accordion.Head.Content' });\nAccordionHead.displayName = 'Accordion.Head';\nAccordionContent.displayName = 'Accordion.Content';\nAccordionRoot.displayName = 'Accordion';\n\nexport default Accordion;\n"],"mappings":"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"}
|
|
@@ -26,7 +26,9 @@ export interface AccordionProps extends Omit<ComponentPropsWithRef<'div'>, 'chil
|
|
|
26
26
|
/** Selects the compact two-line list presentation from Bodywork. */
|
|
27
27
|
appearance?: AccordionAppearance;
|
|
28
28
|
/**
|
|
29
|
-
* @description Panel content revealed when the accordion is open.
|
|
29
|
+
* @description Panel content revealed when the accordion is open. Ordinary
|
|
30
|
+
* content uses one explicit Accordion.Content for its inset. Nested Accordions,
|
|
31
|
+
* AccordionGroups and Lists are direct children without an extra content wrapper.
|
|
30
32
|
*/
|
|
31
33
|
children?: ReactNode;
|
|
32
34
|
/**
|
|
@@ -104,6 +106,7 @@ export interface AccordionPartProps extends ComponentPropsWithRef<'span'> {
|
|
|
104
106
|
children?: ReactNode;
|
|
105
107
|
className?: string;
|
|
106
108
|
}
|
|
109
|
+
/** Owns panel native props/ref and the padding of ordinary content; nested structures may be siblings. */
|
|
107
110
|
export interface AccordionContentProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
|
|
108
111
|
children?: ReactNode;
|
|
109
112
|
}
|
|
@@ -1 +1 @@
|
|
|
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,2FAA2F;AAC3F,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,qBAAqB,8BAA+B,CAAC;AAClE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,GAAG,IAAI,GAAG,OAAO,CAC5B;IACC;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB,oEAAoE;IACpE,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAEjC
|
|
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,2FAA2F;AAC3F,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,qBAAqB,8BAA+B,CAAC;AAClE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,GAAG,IAAI,GAAG,OAAO,CAC5B;IACC;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB,oEAAoE;IACpE,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAEjC;;;;OAIG;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;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC3F,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CACrD,qBAAqB,CAAC,MAAM,CAAC,EAC7B,OAAO,GAAG,UAAU,CACrB;IACC,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB,CAAC,MAAM,CAAC;IACvE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,0GAA0G;AAC1G,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3F,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Accordion.types.js","names":[],"sources":["../../../src/components/accordion/Accordion.types.ts"],"sourcesContent":["import type { ComponentPropsWithRef, ReactNode } from 'react';\n\n/** Named configuration values; existing literal props and value lists remain supported. */\nexport enum AccordionAppearances {\n Default = 'default',\n List = 'list',\n}\n\nexport const ACCORDION_APPEARANCES = ['default', 'list'] as const;\nexport type AccordionAppearance = (typeof ACCORDION_APPEARANCES)[number];\n\n/**\n * @description Props for a single disclosure accordion: a header button that\n * expands and collapses an associated content region. Nesting an `Accordion`\n * inside another `Accordion`'s content is automatically detected via React\n * context and rendered as the \"Wrapped\" presentation — there is no separate\n * component or prop for that case.\n */\nexport interface AccordionProps extends Omit<\n ComponentPropsWithRef<'div'>,\n 'children' | 'id' | 'title'\n> {\n /**\n * @description Visible, localized header label used as the accordion's\n * accessible name.\n */\n title?: ReactNode;\n\n /** Optional second line used by the list presentation. */\n subtitle?: ReactNode;\n\n /** Optional leading image or icon used by list-style accordion rows. */\n leading?: ReactNode;\n\n /** Selects the compact two-line list presentation from Bodywork. */\n appearance?: AccordionAppearance;\n\n /**\n * @description Panel content revealed when the accordion is open.\n */\n children?: ReactNode;\n\n /**\n * @description Controlled open state. Ignored when the accordion is\n * rendered inside an `AccordionGroup`, which owns exclusivity instead.\n */\n open?: boolean;\n\n /**\n * @description Uncontrolled initial open state. Ignored when inside an\n * `AccordionGroup`.\n * @default false\n */\n defaultOpen?: boolean;\n\n /**\n * @description Called with the next open state on user toggle, for both\n * the controlled and uncontrolled usage.\n */\n onOpenChange?: (open: boolean) => void;\n\n /**\n * @description Disables the header trigger, preventing toggling.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * @description Stable id used to wire the header and panel via ARIA and,\n * inside an `AccordionGroup`, to identify this item. Falls back to a\n * generated id when omitted.\n */\n id?: string;\n\n /**\n * @description Additional class names appended to the accordion root\n * element.\n */\n className?: string;\n}\n\n/**\n * @description Props for a group of mutually exclusive accordions: at most\n * one child `Accordion` is open at a time, and the group renders its\n * children as one joined surface.\n */\nexport interface AccordionGroupProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {\n /**\n * @description `Accordion` items belonging to the group.\n */\n children?: ReactNode;\n\n /**\n * @description Controlled id of the currently open item, or `null` when\n * all items are closed.\n */\n openId?: string | null;\n\n /**\n * @description Uncontrolled id of the initially open item.\n * @default null\n */\n defaultOpenId?: string | null;\n\n /**\n * @description Called with the next open item id, or `null` when the group\n * closes entirely, for both the controlled and uncontrolled usage.\n */\n onOpenChange?: (openId: string | null) => void;\n\n /**\n * @description Additional class names appended to the group root element.\n */\n className?: string;\n}\n\nexport interface AccordionHeadProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {\n children?: ReactNode;\n}\n\nexport interface AccordionHeadContentProps extends Omit<\n ComponentPropsWithRef<'span'>,\n 'title' | 'children'\n> {\n title: ReactNode;\n subtitle?: ReactNode;\n className?: string;\n}\n\nexport interface AccordionPartProps extends ComponentPropsWithRef<'span'> {\n children?: ReactNode;\n className?: string;\n}\n\nexport interface AccordionContentProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {\n children?: ReactNode;\n}\n"],"mappings":";;AAGA,IAAY,uBAAL,yBAAA,sBAAA;CACL,qBAAA,aAAA;CACA,qBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,wBAAwB,CAAC,WAAW,MAAM"}
|
|
1
|
+
{"version":3,"file":"Accordion.types.js","names":[],"sources":["../../../src/components/accordion/Accordion.types.ts"],"sourcesContent":["import type { ComponentPropsWithRef, ReactNode } from 'react';\n\n/** Named configuration values; existing literal props and value lists remain supported. */\nexport enum AccordionAppearances {\n Default = 'default',\n List = 'list',\n}\n\nexport const ACCORDION_APPEARANCES = ['default', 'list'] as const;\nexport type AccordionAppearance = (typeof ACCORDION_APPEARANCES)[number];\n\n/**\n * @description Props for a single disclosure accordion: a header button that\n * expands and collapses an associated content region. Nesting an `Accordion`\n * inside another `Accordion`'s content is automatically detected via React\n * context and rendered as the \"Wrapped\" presentation — there is no separate\n * component or prop for that case.\n */\nexport interface AccordionProps extends Omit<\n ComponentPropsWithRef<'div'>,\n 'children' | 'id' | 'title'\n> {\n /**\n * @description Visible, localized header label used as the accordion's\n * accessible name.\n */\n title?: ReactNode;\n\n /** Optional second line used by the list presentation. */\n subtitle?: ReactNode;\n\n /** Optional leading image or icon used by list-style accordion rows. */\n leading?: ReactNode;\n\n /** Selects the compact two-line list presentation from Bodywork. */\n appearance?: AccordionAppearance;\n\n /**\n * @description Panel content revealed when the accordion is open. Ordinary\n * content uses one explicit Accordion.Content for its inset. Nested Accordions,\n * AccordionGroups and Lists are direct children without an extra content wrapper.\n */\n children?: ReactNode;\n\n /**\n * @description Controlled open state. Ignored when the accordion is\n * rendered inside an `AccordionGroup`, which owns exclusivity instead.\n */\n open?: boolean;\n\n /**\n * @description Uncontrolled initial open state. Ignored when inside an\n * `AccordionGroup`.\n * @default false\n */\n defaultOpen?: boolean;\n\n /**\n * @description Called with the next open state on user toggle, for both\n * the controlled and uncontrolled usage.\n */\n onOpenChange?: (open: boolean) => void;\n\n /**\n * @description Disables the header trigger, preventing toggling.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * @description Stable id used to wire the header and panel via ARIA and,\n * inside an `AccordionGroup`, to identify this item. Falls back to a\n * generated id when omitted.\n */\n id?: string;\n\n /**\n * @description Additional class names appended to the accordion root\n * element.\n */\n className?: string;\n}\n\n/**\n * @description Props for a group of mutually exclusive accordions: at most\n * one child `Accordion` is open at a time, and the group renders its\n * children as one joined surface.\n */\nexport interface AccordionGroupProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {\n /**\n * @description `Accordion` items belonging to the group.\n */\n children?: ReactNode;\n\n /**\n * @description Controlled id of the currently open item, or `null` when\n * all items are closed.\n */\n openId?: string | null;\n\n /**\n * @description Uncontrolled id of the initially open item.\n * @default null\n */\n defaultOpenId?: string | null;\n\n /**\n * @description Called with the next open item id, or `null` when the group\n * closes entirely, for both the controlled and uncontrolled usage.\n */\n onOpenChange?: (openId: string | null) => void;\n\n /**\n * @description Additional class names appended to the group root element.\n */\n className?: string;\n}\n\nexport interface AccordionHeadProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {\n children?: ReactNode;\n}\n\nexport interface AccordionHeadContentProps extends Omit<\n ComponentPropsWithRef<'span'>,\n 'title' | 'children'\n> {\n title: ReactNode;\n subtitle?: ReactNode;\n className?: string;\n}\n\nexport interface AccordionPartProps extends ComponentPropsWithRef<'span'> {\n children?: ReactNode;\n className?: string;\n}\n\n/** Owns panel native props/ref and the padding of ordinary content; nested structures may be siblings. */\nexport interface AccordionContentProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {\n children?: ReactNode;\n}\n"],"mappings":";;AAGA,IAAY,uBAAL,yBAAA,sBAAA;CACL,qBAAA,aAAA;CACA,qBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,wBAAwB,CAAC,WAAW,MAAM"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
/**
|
|
2
3
|
* Nesting depth of the current accordion subtree. Depth 0 is a top-level
|
|
3
4
|
* accordion; any depth greater than 0 renders as an automatically detected
|
|
@@ -19,6 +20,8 @@ export interface AccordionGroupContextValue {
|
|
|
19
20
|
export declare const AccordionGroupContext: import("react").Context<AccordionGroupContextValue | null>;
|
|
20
21
|
export interface AccordionItemContextValue {
|
|
21
22
|
disabled: boolean;
|
|
23
|
+
hasContentPadding: boolean;
|
|
24
|
+
nestedContent: ReactNode;
|
|
22
25
|
headerId: string;
|
|
23
26
|
isOpen: boolean;
|
|
24
27
|
panelId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccordionContext.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/AccordionContext.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AccordionContext.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/AccordionContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,iCAA2B,CAAC;AAE9D,gFAAgF;AAChF,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IAEhC,kEAAkE;IAClE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,4DAAyD,CAAC;AAE5F,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,SAAS,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,2DAAwD,CAAC;AAE1F,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,6BAQnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccordionContext.js","names":[],"sources":["../../../src/components/accordion/AccordionContext.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\n\n/**\n * Nesting depth of the current accordion subtree. Depth 0 is a top-level\n * accordion; any depth greater than 0 renders as an automatically detected\n * wrapped (nested) accordion. Each open panel provides an incremented depth to\n * its content.\n */\nexport const AccordionDepthContext = createContext<number>(0);\n\n/** Exclusive open-state contract shared by an AccordionGroup with its items. */\nexport interface AccordionGroupContextValue {\n /** Whether the item registered under this id is the open one. */\n isOpen: (id: string) => boolean;\n\n /** Toggles the item registered under this id within the group. */\n toggle: (id: string) => void;\n}\n\n/**\n * Present when an Accordion is rendered inside an AccordionGroup. Items then\n * share the group's exclusive open state instead of owning local state.\n */\nexport const AccordionGroupContext = createContext<AccordionGroupContextValue | null>(null);\n\nexport interface AccordionItemContextValue {\n disabled: boolean;\n headerId: string;\n isOpen: boolean;\n panelId: string;\n onToggle: () => void;\n}\n\nexport const AccordionItemContext = createContext<AccordionItemContextValue | null>(null);\n\nexport function useAccordionItemContext(part: string) {\n const context = useContext(AccordionItemContext);\n\n if (context === null) {\n throw new Error(`Accordion.${part} must be used inside Accordion`);\n }\n\n return context;\n}\n"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"AccordionContext.js","names":[],"sources":["../../../src/components/accordion/AccordionContext.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport type { ReactNode } from 'react';\n\n/**\n * Nesting depth of the current accordion subtree. Depth 0 is a top-level\n * accordion; any depth greater than 0 renders as an automatically detected\n * wrapped (nested) accordion. Each open panel provides an incremented depth to\n * its content.\n */\nexport const AccordionDepthContext = createContext<number>(0);\n\n/** Exclusive open-state contract shared by an AccordionGroup with its items. */\nexport interface AccordionGroupContextValue {\n /** Whether the item registered under this id is the open one. */\n isOpen: (id: string) => boolean;\n\n /** Toggles the item registered under this id within the group. */\n toggle: (id: string) => void;\n}\n\n/**\n * Present when an Accordion is rendered inside an AccordionGroup. Items then\n * share the group's exclusive open state instead of owning local state.\n */\nexport const AccordionGroupContext = createContext<AccordionGroupContextValue | null>(null);\n\nexport interface AccordionItemContextValue {\n disabled: boolean;\n hasContentPadding: boolean;\n nestedContent: ReactNode;\n headerId: string;\n isOpen: boolean;\n panelId: string;\n onToggle: () => void;\n}\n\nexport const AccordionItemContext = createContext<AccordionItemContextValue | null>(null);\n\nexport function useAccordionItemContext(part: string) {\n const context = useContext(AccordionItemContext);\n\n if (context === null) {\n throw new Error(`Accordion.${part} must be used inside Accordion`);\n }\n\n return context;\n}\n"],"mappings":";;;;;;;;AASA,IAAa,wBAAwB,cAAsB,CAAC;;;;;AAe5D,IAAa,wBAAwB,cAAiD,IAAI;AAY1F,IAAa,uBAAuB,cAAgD,IAAI;AAExF,SAAgB,wBAAwB,MAAc;CACpD,MAAM,UAAU,WAAW,oBAAoB;CAE/C,IAAI,YAAY,MACd,MAAM,IAAI,MAAM,aAAa,KAAK,+BAA+B;CAGnE,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAuClE,QAAA,MAAM,IAAI;;CAAkD,CAAC;AAK7D,eAAe,IAAI,CAAC"}
|
|
@@ -18,8 +18,12 @@ var CardHeader = forwardRef(function CardHeader({ children, className, icon, ...
|
|
|
18
18
|
})]
|
|
19
19
|
});
|
|
20
20
|
});
|
|
21
|
-
var CardRoot = forwardRef(function Card({ children, className, ...cardProps }, ref) {
|
|
22
|
-
const resolvedClassName = [
|
|
21
|
+
var CardRoot = forwardRef(function Card({ children, className, disableHover = false, ...cardProps }, ref) {
|
|
22
|
+
const resolvedClassName = [
|
|
23
|
+
"chayns-card",
|
|
24
|
+
disableHover && "chayns-card--hover-disabled",
|
|
25
|
+
className
|
|
26
|
+
].filter(Boolean).join(" ");
|
|
23
27
|
return /* @__PURE__ */ jsx("div", {
|
|
24
28
|
...cardProps,
|
|
25
29
|
className: resolvedClassName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.js","names":[],"sources":["../../../src/components/card/Card.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport type { CardHeaderProps, CardProps } from './Card.types.js';\n\nconst CardHeader = forwardRef<HTMLElement, CardHeaderProps>(function CardHeader(\n { children, className, icon, ...headerProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card__header', className].filter(Boolean).join(' ');\n\n return (\n <header {...headerProps} className={resolvedClassName} ref={ref}>\n {icon ? (\n <span aria-hidden=\"true\" className=\"chayns-card__header-icon\">\n <ButtonIcon icon={icon} />\n </span>\n ) : null}\n <span className=\"chayns-card__header-content\">{children}</span>\n </header>\n );\n});\n\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n { children, className, ...cardProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card'
|
|
1
|
+
{"version":3,"file":"Card.js","names":[],"sources":["../../../src/components/card/Card.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport type { CardHeaderProps, CardProps } from './Card.types.js';\n\nconst CardHeader = forwardRef<HTMLElement, CardHeaderProps>(function CardHeader(\n { children, className, icon, ...headerProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card__header', className].filter(Boolean).join(' ');\n\n return (\n <header {...headerProps} className={resolvedClassName} ref={ref}>\n {icon ? (\n <span aria-hidden=\"true\" className=\"chayns-card__header-icon\">\n <ButtonIcon icon={icon} />\n </span>\n ) : null}\n <span className=\"chayns-card__header-content\">{children}</span>\n </header>\n );\n});\n\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n { children, className, disableHover = false, ...cardProps },\n ref,\n) {\n const resolvedClassName = [\n 'chayns-card',\n disableHover && 'chayns-card--hover-disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div {...cardProps} className={resolvedClassName} ref={ref}>\n {children}\n </div>\n );\n});\n\nconst Card = Object.assign(CardRoot, { Header: CardHeader });\n\nCardHeader.displayName = 'Card.Header';\nCardRoot.displayName = 'Card';\n\nexport default Card;\n"],"mappings":";;;;AAKA,IAAM,aAAa,WAAyC,SAAS,WACnE,EAAE,UAAU,WAAW,MAAM,GAAG,eAChC,KACA;CACA,MAAM,oBAAoB,CAAC,uBAAuB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAErF,OACE,qBAAC,UAAD;EAAQ,GAAI;EAAa,WAAW;EAAwB;EAA5D,UAAA,CACG,OACC,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GACjC,UAAA,oBAAC,YAAD,EAAkB,KAAO,CAAA;EACrB,CAAA,IACJ,MACJ,oBAAC,QAAD;GAAM,WAAU;GAA+B;EAAe,CAAA,CACxD;;AAEZ,CAAC;AAED,IAAM,WAAW,WAAsC,SAAS,KAC9D,EAAE,UAAU,WAAW,eAAe,OAAO,GAAG,aAChD,KACA;CACA,MAAM,oBAAoB;EACxB;EACA,gBAAgB;EAChB;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEX,OACE,oBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAwB;EACpD;CACE,CAAA;AAET,CAAC;AAED,IAAM,OAAO,OAAO,OAAO,UAAU,EAAE,QAAQ,WAAW,CAAC;AAE3D,WAAW,cAAc;AACzB,SAAS,cAAc"}
|
|
@@ -6,6 +6,11 @@ import type { ButtonIcon } from '../button/Button.types.js';
|
|
|
6
6
|
* all remaining native `div` props, `className` and `ref`.
|
|
7
7
|
*/
|
|
8
8
|
export interface CardProps extends ComponentPropsWithRef<'div'> {
|
|
9
|
+
/**
|
|
10
|
+
* @description Suppresses the decorative Card hover treatment, keeping the
|
|
11
|
+
* surface visually flat while preserving its non-interactive semantics.
|
|
12
|
+
*/
|
|
13
|
+
disableHover?: boolean;
|
|
9
14
|
/**
|
|
10
15
|
* @description Content rendered inside the card surface. Card owns the
|
|
11
16
|
* standard Design System inner spacing around this content.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.types.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,WAAW,SAAU,SAAQ,qBAAqB,CAAC,KAAK,CAAC;IAC7D;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,qBAAqB,CAAC,QAAQ,CAAC;IACtE,kEAAkE;IAClE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"Card.types.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,WAAW,SAAU,SAAQ,qBAAqB,CAAC,KAAK,CAAC;IAC7D;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,qBAAqB,CAAC,QAAQ,CAAC;IACtE,kEAAkE;IAClE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAiC,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEpG,QAAA,MAAM,cAAc,gIA6NlB,CAAC;AAIH,eAAe,cAAc,CAAC"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { composeNativeRefs } from "../../utils/native-ref.js";
|
|
2
|
+
import { useOverlayPosition } from "../../hooks/useOverlayPosition.js";
|
|
2
3
|
import { dateAtMidnight } from "./date-time-picker-utils.js";
|
|
3
4
|
import { useDateTimePickerValue } from "./hooks/useDateTimePickerValue.js";
|
|
4
5
|
import Wheel from "./wheel/Wheel.js";
|
|
5
6
|
import PickerSizer from "./sizer/PickerSizer.js";
|
|
6
7
|
import { DATE_TIME_PICKER_MINUTE_STEPS } from "./DateTimePicker.types.js";
|
|
7
|
-
import { forwardRef, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
8
|
+
import { forwardRef, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { createPortal } from "react-dom";
|
|
9
11
|
//#region src/components/date-time-picker/DateTimePicker.tsx
|
|
10
12
|
var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, id, label, locale, maxDate, minDate, minuteStep = 1, mode = "time", onChange, onClick, onKeyDown, placeholder, value, wheelLabels, ...buttonProps }, ref) {
|
|
11
13
|
if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) throw new Error("DateTimePicker minuteStep must be one of: 1, 5, 15, 30.");
|
|
@@ -14,6 +16,7 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
|
|
|
14
16
|
const triggerId = id ?? generatedId;
|
|
15
17
|
const popupId = `${triggerId}-popup`;
|
|
16
18
|
const rootRef = useRef(null);
|
|
19
|
+
const popupRef = useRef(null);
|
|
17
20
|
const triggerRef = useRef(null);
|
|
18
21
|
const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);
|
|
19
22
|
const [open, setOpen] = useState(false);
|
|
@@ -32,10 +35,34 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
|
|
|
32
35
|
setOpen(false);
|
|
33
36
|
triggerRef.current?.focus();
|
|
34
37
|
}
|
|
38
|
+
useLayoutEffect(() => {
|
|
39
|
+
const popup = popupRef.current;
|
|
40
|
+
const trigger = triggerRef.current;
|
|
41
|
+
if (!open || popup === null || trigger === null) return;
|
|
42
|
+
const popupStyle = window.getComputedStyle(popup);
|
|
43
|
+
const popupFrameWidth = Number.parseFloat(popupStyle.borderInlineStartWidth) + Number.parseFloat(popupStyle.borderInlineEndWidth) + Number.parseFloat(popupStyle.paddingInlineStart) + Number.parseFloat(popupStyle.paddingInlineEnd);
|
|
44
|
+
const wheels = Array.from(popup.querySelectorAll(".chayns-date-time-picker__wheel"));
|
|
45
|
+
for (const wheel of wheels) {
|
|
46
|
+
const contentWidth = Math.max(...Array.from(wheel.querySelectorAll(".chayns-date-time-picker__wheel-sizer-option")).map((option) => option.getBoundingClientRect().width), wheel.scrollWidth);
|
|
47
|
+
wheel.style.inlineSize = `${contentWidth}px`;
|
|
48
|
+
wheel.style.flex = `0 0 ${contentWidth}px`;
|
|
49
|
+
}
|
|
50
|
+
const wheelsWidth = popup.querySelector(".chayns-date-time-picker__wheels")?.scrollWidth ?? 0;
|
|
51
|
+
const triggerWidth = trigger.getBoundingClientRect().width;
|
|
52
|
+
if (wheelsWidth === 0 && triggerWidth === 0) return;
|
|
53
|
+
popup.style.inlineSize = `${Math.max(triggerWidth, wheelsWidth + popupFrameWidth)}px`;
|
|
54
|
+
}, [
|
|
55
|
+
locale,
|
|
56
|
+
maxDate,
|
|
57
|
+
minDate,
|
|
58
|
+
mode,
|
|
59
|
+
open
|
|
60
|
+
]);
|
|
61
|
+
useOverlayPosition(popupRef, triggerRef.current, open, "bottom", 4, true);
|
|
35
62
|
useEffect(() => {
|
|
36
63
|
if (!open) return void 0;
|
|
37
64
|
function closeOnOutsidePress(event) {
|
|
38
|
-
if (event.target instanceof Node && !rootRef.current?.contains(event.target)) close();
|
|
65
|
+
if (event.target instanceof Node && !rootRef.current?.contains(event.target) && !popupRef.current?.contains(event.target)) close();
|
|
39
66
|
}
|
|
40
67
|
document.addEventListener("pointerdown", closeOnOutsidePress);
|
|
41
68
|
return () => document.removeEventListener("pointerdown", closeOnOutsidePress);
|
|
@@ -83,10 +110,11 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
|
|
|
83
110
|
htmlFor: triggerId,
|
|
84
111
|
children: label
|
|
85
112
|
}) : null,
|
|
86
|
-
open && !disabled ? /* @__PURE__ */ jsxs("div", {
|
|
113
|
+
open && !disabled && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsxs("div", {
|
|
87
114
|
"aria-label": label,
|
|
88
115
|
className: "chayns-date-time-picker__popup",
|
|
89
116
|
id: popupId,
|
|
117
|
+
ref: popupRef,
|
|
90
118
|
role: "dialog",
|
|
91
119
|
children: [/* @__PURE__ */ jsx("div", { className: "chayns-date-time-picker__selection" }), /* @__PURE__ */ jsx("div", {
|
|
92
120
|
className: "chayns-date-time-picker__wheels",
|
|
@@ -120,7 +148,7 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
|
|
|
120
148
|
selected: dateValue(part)
|
|
121
149
|
}, part))
|
|
122
150
|
})]
|
|
123
|
-
}) : null
|
|
151
|
+
}), document.body) : null
|
|
124
152
|
]
|
|
125
153
|
});
|
|
126
154
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { composeNativeRefs } from '../../utils/native-ref.js';\nimport { dateAtMidnight } from './date-time-picker-utils.js';\nimport { useDateTimePickerValue } from './hooks/useDateTimePickerValue.js';\nimport Wheel from './wheel/Wheel.js';\nimport PickerSizer from './sizer/PickerSizer.js';\nimport { DATE_TIME_PICKER_MINUTE_STEPS, type DateTimePickerProps } from './DateTimePicker.types.js';\n\nconst DateTimePicker = forwardRef<HTMLButtonElement, DateTimePickerProps>(function DateTimePicker(\n {\n className,\n disabled,\n id,\n label,\n locale,\n maxDate,\n minDate,\n minuteStep = 1,\n mode = 'time',\n onChange,\n onClick,\n onKeyDown,\n placeholder,\n value,\n wheelLabels,\n ...buttonProps\n },\n ref,\n) {\n if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) {\n throw new Error('DateTimePicker minuteStep must be one of: 1, 5, 15, 30.');\n }\n\n if (\n minDate !== undefined &&\n maxDate !== undefined &&\n dateAtMidnight(minDate) > dateAtMidnight(maxDate)\n ) {\n throw new Error('DateTimePicker requires minDate to be earlier than or equal to maxDate.');\n }\n\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const popupId = `${triggerId}-popup`;\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);\n const [open, setOpen] = useState(false);\n const {\n displayValue,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n sizingValues,\n } = useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n });\n function close() {\n setOpen(false);\n triggerRef.current?.focus();\n }\n useEffect(() => {\n if (!open) return undefined;\n function closeOnOutsidePress(event: PointerEvent) {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) close();\n }\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => document.removeEventListener('pointerdown', closeOnOutsidePress);\n });\n const resolvedClassName = [\n 'chayns-date-time-picker',\n `chayns-date-time-picker--${mode}`,\n open ? 'chayns-date-time-picker--open' : '',\n displayValue !== null ? 'chayns-date-time-picker--filled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={resolvedClassName} ref={rootRef}>\n <PickerSizer values={sizingValues} placeholder={displayValue === null ? placeholder : null} />\n <button\n {...buttonProps}\n aria-controls={open ? popupId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={label}\n className={['chayns-date-time-picker__trigger', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={triggerId}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((current) => !current);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key === 'Escape' && open && !event.defaultPrevented) {\n event.preventDefault();\n close();\n }\n }}\n ref={setTriggerElement}\n type=\"button\"\n >\n {formattedValue}\n </button>\n {displayValue === null ? (\n <label className=\"chayns-date-time-picker__label\" htmlFor={triggerId}>\n {label}\n </label>\n ) : null}\n {open && !disabled ? (\n <div\n aria-label={label}\n className=\"chayns-date-time-picker__popup\"\n id={popupId}\n role=\"dialog\"\n >\n <div className=\"chayns-date-time-picker__selection\" />\n <div className=\"chayns-date-time-picker__wheels\">\n {mode === 'time' ? (\n <>\n <Wheel\n ariaLabel={wheelLabels.hour}\n onEscape={close}\n onSelect={(hour) => updateTime('hours', hour)}\n options={hours}\n selected={\n isTwelveHour ? activeValue.getHours() % 12 || 12 : activeValue.getHours()\n }\n />\n <Wheel\n ariaLabel={wheelLabels.minute}\n onEscape={close}\n onSelect={(minute) => updateTime('minutes', minute)}\n options={minutes}\n selected={activeValue.getMinutes()}\n />\n {isTwelveHour ? (\n <Wheel\n ariaLabel={wheelLabels.dayPeriod}\n onEscape={close}\n onSelect={updatePeriod}\n options={dayPeriods}\n selected={activeValue.getHours() >= 12 ? 1 : 0}\n />\n ) : null}\n </>\n ) : (\n datePartOrder.map((part) => (\n <Wheel\n ariaLabel={dateLabel(part)}\n key={part}\n onEscape={close}\n onSelect={(nextValue) => updateDate(part, nextValue)}\n options={dateOptions(part)}\n selected={dateValue(part)}\n />\n ))\n )}\n </div>\n </div>\n ) : null}\n </div>\n );\n});\n\nDateTimePicker.displayName = 'DateTimePicker';\n\nexport default DateTimePicker;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { composeNativeRefs } from '../../utils/native-ref.js';\nimport { useOverlayPosition } from '../../hooks/useOverlayPosition.js';\nimport { dateAtMidnight } from './date-time-picker-utils.js';\nimport { useDateTimePickerValue } from './hooks/useDateTimePickerValue.js';\nimport Wheel from './wheel/Wheel.js';\nimport PickerSizer from './sizer/PickerSizer.js';\nimport { DATE_TIME_PICKER_MINUTE_STEPS, type DateTimePickerProps } from './DateTimePicker.types.js';\n\nconst DateTimePicker = forwardRef<HTMLButtonElement, DateTimePickerProps>(function DateTimePicker(\n {\n className,\n disabled,\n id,\n label,\n locale,\n maxDate,\n minDate,\n minuteStep = 1,\n mode = 'time',\n onChange,\n onClick,\n onKeyDown,\n placeholder,\n value,\n wheelLabels,\n ...buttonProps\n },\n ref,\n) {\n if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) {\n throw new Error('DateTimePicker minuteStep must be one of: 1, 5, 15, 30.');\n }\n\n if (\n minDate !== undefined &&\n maxDate !== undefined &&\n dateAtMidnight(minDate) > dateAtMidnight(maxDate)\n ) {\n throw new Error('DateTimePicker requires minDate to be earlier than or equal to maxDate.');\n }\n\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const popupId = `${triggerId}-popup`;\n const rootRef = useRef<HTMLDivElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);\n const [open, setOpen] = useState(false);\n const {\n displayValue,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n sizingValues,\n } = useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n });\n function close() {\n setOpen(false);\n triggerRef.current?.focus();\n }\n\n useLayoutEffect(() => {\n const popup = popupRef.current;\n const trigger = triggerRef.current;\n if (!open || popup === null || trigger === null) return;\n\n const popupStyle = window.getComputedStyle(popup);\n const popupFrameWidth =\n Number.parseFloat(popupStyle.borderInlineStartWidth) +\n Number.parseFloat(popupStyle.borderInlineEndWidth) +\n Number.parseFloat(popupStyle.paddingInlineStart) +\n Number.parseFloat(popupStyle.paddingInlineEnd);\n const wheels = Array.from(\n popup.querySelectorAll<HTMLElement>('.chayns-date-time-picker__wheel'),\n );\n for (const wheel of wheels) {\n const contentWidth = Math.max(\n ...Array.from(\n wheel.querySelectorAll<HTMLElement>('.chayns-date-time-picker__wheel-sizer-option'),\n ).map((option) => option.getBoundingClientRect().width),\n wheel.scrollWidth,\n );\n wheel.style.inlineSize = `${contentWidth}px`;\n wheel.style.flex = `0 0 ${contentWidth}px`;\n }\n const wheelsWidth =\n popup.querySelector<HTMLElement>('.chayns-date-time-picker__wheels')?.scrollWidth ?? 0;\n const triggerWidth = trigger.getBoundingClientRect().width;\n\n if (wheelsWidth === 0 && triggerWidth === 0) return;\n popup.style.inlineSize = `${Math.max(triggerWidth, wheelsWidth + popupFrameWidth)}px`;\n }, [locale, maxDate, minDate, mode, open]);\n\n useOverlayPosition(popupRef, triggerRef.current, open, 'bottom', 4, true);\n\n useEffect(() => {\n if (!open) return undefined;\n function closeOnOutsidePress(event: PointerEvent) {\n if (\n event.target instanceof Node &&\n !rootRef.current?.contains(event.target) &&\n !popupRef.current?.contains(event.target)\n ) {\n close();\n }\n }\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => document.removeEventListener('pointerdown', closeOnOutsidePress);\n });\n const resolvedClassName = [\n 'chayns-date-time-picker',\n `chayns-date-time-picker--${mode}`,\n open ? 'chayns-date-time-picker--open' : '',\n displayValue !== null ? 'chayns-date-time-picker--filled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={resolvedClassName} ref={rootRef}>\n <PickerSizer values={sizingValues} placeholder={displayValue === null ? placeholder : null} />\n <button\n {...buttonProps}\n aria-controls={open ? popupId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={label}\n className={['chayns-date-time-picker__trigger', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={triggerId}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((current) => !current);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key === 'Escape' && open && !event.defaultPrevented) {\n event.preventDefault();\n close();\n }\n }}\n ref={setTriggerElement}\n type=\"button\"\n >\n {formattedValue}\n </button>\n {displayValue === null ? (\n <label className=\"chayns-date-time-picker__label\" htmlFor={triggerId}>\n {label}\n </label>\n ) : null}\n {open && !disabled && typeof document !== 'undefined'\n ? createPortal(\n <div\n aria-label={label}\n className=\"chayns-date-time-picker__popup\"\n id={popupId}\n ref={popupRef}\n role=\"dialog\"\n >\n <div className=\"chayns-date-time-picker__selection\" />\n <div className=\"chayns-date-time-picker__wheels\">\n {mode === 'time' ? (\n <>\n <Wheel\n ariaLabel={wheelLabels.hour}\n onEscape={close}\n onSelect={(hour) => updateTime('hours', hour)}\n options={hours}\n selected={\n isTwelveHour ? activeValue.getHours() % 12 || 12 : activeValue.getHours()\n }\n />\n <Wheel\n ariaLabel={wheelLabels.minute}\n onEscape={close}\n onSelect={(minute) => updateTime('minutes', minute)}\n options={minutes}\n selected={activeValue.getMinutes()}\n />\n {isTwelveHour ? (\n <Wheel\n ariaLabel={wheelLabels.dayPeriod}\n onEscape={close}\n onSelect={updatePeriod}\n options={dayPeriods}\n selected={activeValue.getHours() >= 12 ? 1 : 0}\n />\n ) : null}\n </>\n ) : (\n datePartOrder.map((part) => (\n <Wheel\n ariaLabel={dateLabel(part)}\n key={part}\n onEscape={close}\n onSelect={(nextValue) => updateDate(part, nextValue)}\n options={dateOptions(part)}\n selected={dateValue(part)}\n />\n ))\n )}\n </div>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n});\n\nDateTimePicker.displayName = 'DateTimePicker';\n\nexport default DateTimePicker;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDateTimePickerValue.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,KAAK,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAC9C,KAAK,UAAU,GAAG,IAAI,CACpB,mBAAmB,EACnB,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAChE,GACC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC,GAAG;IAC3D,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEJ,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,IAAI,GACL,EAAE,UAAU;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"useDateTimePickerValue.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,KAAK,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAC9C,KAAK,UAAU,GAAG,IAAI,CACpB,mBAAmB,EACnB,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAChE,GACC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC,GAAG;IAC3D,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEJ,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,IAAI,GACL,EAAE,UAAU;;;;;;;;;;;;;;;;;;;wBAsJgB,QAAQ;;;;sBAMV,QAAQ;sBAYR,QAAQ;uBAhHP,QAAQ,aAAa,MAAM;uBAjB3B,OAAO,GAAG,SAAS,aAAa,MAAM;2BAWlC,MAAM;EA4IrC"}
|
|
@@ -75,7 +75,26 @@ function useDateTimePickerValue({ value, locale, maxDate, minDate, onChange, pla
|
|
|
75
75
|
mode,
|
|
76
76
|
timeFormatter
|
|
77
77
|
]);
|
|
78
|
-
const dateSizingValues = useMemo(() =>
|
|
78
|
+
const dateSizingValues = useMemo(() => {
|
|
79
|
+
if (mode !== "date") return [];
|
|
80
|
+
return years.flatMap((year) => {
|
|
81
|
+
return Array.from({ length: 12 }, (_, month) => {
|
|
82
|
+
const first = new Date(year, month, 1);
|
|
83
|
+
const last = new Date(year, month + 1, 0);
|
|
84
|
+
if (minDate !== void 0 && last < dateAtMidnight(minDate) || maxDate !== void 0 && first > dateAtMidnight(maxDate)) return;
|
|
85
|
+
const candidate = new Date(last);
|
|
86
|
+
if (minDate !== void 0 && candidate < dateAtMidnight(minDate)) candidate.setDate(minDate.getDate());
|
|
87
|
+
if (maxDate !== void 0 && candidate > dateAtMidnight(maxDate)) candidate.setDate(maxDate.getDate());
|
|
88
|
+
return dateFormatter.format(candidate);
|
|
89
|
+
}).filter((value) => value !== void 0);
|
|
90
|
+
});
|
|
91
|
+
}, [
|
|
92
|
+
dateFormatter,
|
|
93
|
+
maxDate,
|
|
94
|
+
minDate,
|
|
95
|
+
mode,
|
|
96
|
+
years
|
|
97
|
+
]);
|
|
79
98
|
const sizingValues = mode === "time" ? timeSizingValues : dateSizingValues;
|
|
80
99
|
const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) => isTwelveHour ? index + 1 : index).map((hour) => ({
|
|
81
100
|
label: String(hour).padStart(2, "0"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDateTimePickerValue.js","names":[],"sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { clampDate, dateAtMidnight, normalizeMinute } from '../date-time-picker-utils.js';\nimport type { DateTimePickerProps } from '../DateTimePicker.types.js';\ntype DatePart = 'date' | 'fullYear' | 'month';\ntype ValueProps = Pick<\n DateTimePickerProps,\n 'value' | 'locale' | 'onChange' | 'placeholder' | 'wheelLabels'\n> &\n Required<Pick<DateTimePickerProps, 'minuteStep' | 'mode'>> & {\n minDate: Date | undefined;\n maxDate: Date | undefined;\n };\n\nexport function useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n}: ValueProps) {\n const { hourFormatter, monthFormatter, timeFormatter, dateFormatter, dateOrderFormatter } =\n useMemo(\n () => ({\n hourFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric' }),\n monthFormatter: new Intl.DateTimeFormat(locale, { month: 'long' }),\n timeFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' }),\n dateFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }),\n dateOrderFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n }),\n }),\n [locale],\n );\n let displayValue = value;\n if (value !== null) {\n displayValue =\n mode === 'date' ? clampDate(value, minDate, maxDate) : normalizeMinute(value, minuteStep);\n }\n const activeValue = displayValue ?? new Date();\n const isTwelveHour = hourFormatter.resolvedOptions().hour12 === true;\n\n const years = useMemo(() => {\n const today = new Date().getFullYear();\n const first = minDate?.getFullYear() ?? today - 100;\n const last = maxDate?.getFullYear() ?? today + 100;\n return Array.from({ length: last - first + 1 }, (_, index) => first + index);\n }, [maxDate, minDate]);\n\n function emit(nextValue: Date) {\n onChange(mode === 'date' ? clampDate(nextValue, minDate, maxDate) : nextValue);\n }\n\n function updateTime(part: 'hours' | 'minutes', nextValue: number) {\n const next = new Date(activeValue);\n if (part === 'hours') {\n const hour = isTwelveHour ? (nextValue % 12) + (next.getHours() >= 12 ? 12 : 0) : nextValue;\n next.setHours(hour);\n } else {\n next.setMinutes(nextValue);\n }\n emit(next);\n }\n\n function updatePeriod(period: number) {\n const next = new Date(activeValue);\n next.setHours((next.getHours() % 12) + period * 12);\n emit(next);\n }\n\n function updateDate(part: DatePart, nextValue: number) {\n const next = new Date(activeValue);\n const originalDay = next.getDate();\n next.setDate(1);\n if (part === 'fullYear') next.setFullYear(nextValue);\n if (part === 'month') next.setMonth(nextValue);\n if (part === 'date') next.setDate(nextValue);\n if (part !== 'date') {\n next.setDate(\n Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()),\n );\n }\n emit(next);\n }\n\n let formattedValue = placeholder;\n if (displayValue !== null) {\n if (mode === 'time')\n formattedValue = `${timeFormatter.format(displayValue)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n else formattedValue = dateFormatter.format(displayValue);\n }\n const timeSizingValues = useMemo(() => {\n if (mode !== 'time') return [];\n return Array.from({ length: 24 * (60 / minuteStep) }, (_, index) => {\n const candidate = new Date(2026, 0, 1);\n candidate.setHours(Math.floor(index / (60 / minuteStep)));\n candidate.setMinutes((index % (60 / minuteStep)) * minuteStep);\n return `${timeFormatter.format(candidate)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n });\n }, [locale, minuteStep, mode, timeFormatter]);\n const dateSizingValues = useMemo(() => [formattedValue], [formattedValue]);\n const sizingValues = mode === 'time' ? timeSizingValues : dateSizingValues;\n\n const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) =>\n isTwelveHour ? index + 1 : index,\n ).map((hour) => ({ label: String(hour).padStart(2, '0'), value: hour }));\n const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {\n const minute = index * minuteStep;\n return { label: String(minute).padStart(2, '0'), value: minute };\n });\n const months = Array.from({ length: 12 }, (_, month) => ({\n label: monthFormatter.format(new Date(2026, month, 1)),\n value: month,\n })).filter((month) => {\n const first = new Date(activeValue.getFullYear(), month.value, 1);\n const last = new Date(activeValue.getFullYear(), month.value + 1, 0);\n return (\n (minDate === undefined || last >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || first <= dateAtMidnight(maxDate))\n );\n });\n const days = Array.from(\n { length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() },\n (_, index) => ({ label: String(index + 1).padStart(2, '0'), value: index + 1 }),\n ).filter((day) => {\n const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);\n return (\n (minDate === undefined || candidate >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || candidate <= dateAtMidnight(maxDate))\n );\n });\n const datePartOrder = dateOrderFormatter.formatToParts(activeValue).flatMap<DatePart>((part) => {\n if (part.type === 'day') return ['date'];\n if (part.type === 'month') return ['month'];\n if (part.type === 'year') return ['fullYear'];\n return [];\n });\n const yearOptions = years.map((year) => ({ label: String(year), value: year }));\n\n function dateOptions(part: DatePart) {\n if (part === 'date') return days;\n if (part === 'month') return months;\n return yearOptions;\n }\n\n function dateValue(part: DatePart) {\n if (part === 'date') return activeValue.getDate();\n if (part === 'month') return activeValue.getMonth();\n return activeValue.getFullYear();\n }\n const dayPeriods = [0, 1].map((period) => ({\n label:\n hourFormatter\n .formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13))\n .find((part) => part.type === 'dayPeriod')?.value ?? (period === 0 ? 'AM' : 'PM'),\n value: period,\n }));\n function dateLabel(part: DatePart) {\n if (part === 'date') return wheelLabels.day;\n if (part === 'month') return wheelLabels.month;\n return wheelLabels.year;\n }\n return {\n displayValue,\n sizingValues,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useDateTimePickerValue.js","names":[],"sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { clampDate, dateAtMidnight, normalizeMinute } from '../date-time-picker-utils.js';\nimport type { DateTimePickerProps } from '../DateTimePicker.types.js';\ntype DatePart = 'date' | 'fullYear' | 'month';\ntype ValueProps = Pick<\n DateTimePickerProps,\n 'value' | 'locale' | 'onChange' | 'placeholder' | 'wheelLabels'\n> &\n Required<Pick<DateTimePickerProps, 'minuteStep' | 'mode'>> & {\n minDate: Date | undefined;\n maxDate: Date | undefined;\n };\n\nexport function useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n}: ValueProps) {\n const { hourFormatter, monthFormatter, timeFormatter, dateFormatter, dateOrderFormatter } =\n useMemo(\n () => ({\n hourFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric' }),\n monthFormatter: new Intl.DateTimeFormat(locale, { month: 'long' }),\n timeFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' }),\n dateFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }),\n dateOrderFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n }),\n }),\n [locale],\n );\n let displayValue = value;\n if (value !== null) {\n displayValue =\n mode === 'date' ? clampDate(value, minDate, maxDate) : normalizeMinute(value, minuteStep);\n }\n const activeValue = displayValue ?? new Date();\n const isTwelveHour = hourFormatter.resolvedOptions().hour12 === true;\n\n const years = useMemo(() => {\n const today = new Date().getFullYear();\n const first = minDate?.getFullYear() ?? today - 100;\n const last = maxDate?.getFullYear() ?? today + 100;\n return Array.from({ length: last - first + 1 }, (_, index) => first + index);\n }, [maxDate, minDate]);\n\n function emit(nextValue: Date) {\n onChange(mode === 'date' ? clampDate(nextValue, minDate, maxDate) : nextValue);\n }\n\n function updateTime(part: 'hours' | 'minutes', nextValue: number) {\n const next = new Date(activeValue);\n if (part === 'hours') {\n const hour = isTwelveHour ? (nextValue % 12) + (next.getHours() >= 12 ? 12 : 0) : nextValue;\n next.setHours(hour);\n } else {\n next.setMinutes(nextValue);\n }\n emit(next);\n }\n\n function updatePeriod(period: number) {\n const next = new Date(activeValue);\n next.setHours((next.getHours() % 12) + period * 12);\n emit(next);\n }\n\n function updateDate(part: DatePart, nextValue: number) {\n const next = new Date(activeValue);\n const originalDay = next.getDate();\n next.setDate(1);\n if (part === 'fullYear') next.setFullYear(nextValue);\n if (part === 'month') next.setMonth(nextValue);\n if (part === 'date') next.setDate(nextValue);\n if (part !== 'date') {\n next.setDate(\n Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()),\n );\n }\n emit(next);\n }\n\n let formattedValue = placeholder;\n if (displayValue !== null) {\n if (mode === 'time')\n formattedValue = `${timeFormatter.format(displayValue)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n else formattedValue = dateFormatter.format(displayValue);\n }\n const timeSizingValues = useMemo(() => {\n if (mode !== 'time') return [];\n return Array.from({ length: 24 * (60 / minuteStep) }, (_, index) => {\n const candidate = new Date(2026, 0, 1);\n candidate.setHours(Math.floor(index / (60 / minuteStep)));\n candidate.setMinutes((index % (60 / minuteStep)) * minuteStep);\n return `${timeFormatter.format(candidate)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n });\n }, [locale, minuteStep, mode, timeFormatter]);\n const dateSizingValues = useMemo(() => {\n if (mode !== 'date') return [];\n\n return years.flatMap((year) => {\n const values = Array.from({ length: 12 }, (_, month) => {\n const first = new Date(year, month, 1);\n const last = new Date(year, month + 1, 0);\n if (\n (minDate !== undefined && last < dateAtMidnight(minDate)) ||\n (maxDate !== undefined && first > dateAtMidnight(maxDate))\n ) {\n return undefined;\n }\n\n const candidate = new Date(last);\n if (minDate !== undefined && candidate < dateAtMidnight(minDate)) {\n candidate.setDate(minDate.getDate());\n }\n if (maxDate !== undefined && candidate > dateAtMidnight(maxDate)) {\n candidate.setDate(maxDate.getDate());\n }\n return dateFormatter.format(candidate);\n });\n return values.filter((value): value is string => value !== undefined);\n });\n }, [dateFormatter, maxDate, minDate, mode, years]);\n const sizingValues = mode === 'time' ? timeSizingValues : dateSizingValues;\n\n const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) =>\n isTwelveHour ? index + 1 : index,\n ).map((hour) => ({ label: String(hour).padStart(2, '0'), value: hour }));\n const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {\n const minute = index * minuteStep;\n return { label: String(minute).padStart(2, '0'), value: minute };\n });\n const months = Array.from({ length: 12 }, (_, month) => ({\n label: monthFormatter.format(new Date(2026, month, 1)),\n value: month,\n })).filter((month) => {\n const first = new Date(activeValue.getFullYear(), month.value, 1);\n const last = new Date(activeValue.getFullYear(), month.value + 1, 0);\n return (\n (minDate === undefined || last >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || first <= dateAtMidnight(maxDate))\n );\n });\n const days = Array.from(\n { length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() },\n (_, index) => ({ label: String(index + 1).padStart(2, '0'), value: index + 1 }),\n ).filter((day) => {\n const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);\n return (\n (minDate === undefined || candidate >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || candidate <= dateAtMidnight(maxDate))\n );\n });\n const datePartOrder = dateOrderFormatter.formatToParts(activeValue).flatMap<DatePart>((part) => {\n if (part.type === 'day') return ['date'];\n if (part.type === 'month') return ['month'];\n if (part.type === 'year') return ['fullYear'];\n return [];\n });\n const yearOptions = years.map((year) => ({ label: String(year), value: year }));\n\n function dateOptions(part: DatePart) {\n if (part === 'date') return days;\n if (part === 'month') return months;\n return yearOptions;\n }\n\n function dateValue(part: DatePart) {\n if (part === 'date') return activeValue.getDate();\n if (part === 'month') return activeValue.getMonth();\n return activeValue.getFullYear();\n }\n const dayPeriods = [0, 1].map((period) => ({\n label:\n hourFormatter\n .formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13))\n .find((part) => part.type === 'dayPeriod')?.value ?? (period === 0 ? 'AM' : 'PM'),\n value: period,\n }));\n function dateLabel(part: DatePart) {\n if (part === 'date') return wheelLabels.day;\n if (part === 'month') return wheelLabels.month;\n return wheelLabels.year;\n }\n return {\n displayValue,\n sizingValues,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n };\n}\n"],"mappings":";;;AAaA,SAAgB,uBAAuB,EACrC,OACA,QACA,SACA,SACA,UACA,aACA,aACA,YACA,QACa;CACb,MAAM,EAAE,eAAe,gBAAgB,eAAe,eAAe,uBACnE,eACS;EACL,eAAe,IAAI,KAAK,eAAe,QAAQ,EAAE,MAAM,UAAU,CAAC;EAClE,gBAAgB,IAAI,KAAK,eAAe,QAAQ,EAAE,OAAO,OAAO,CAAC;EACjE,eAAe,IAAI,KAAK,eAAe,QAAQ;GAAE,MAAM;GAAW,QAAQ;EAAU,CAAC;EACrF,eAAe,IAAI,KAAK,eAAe,QAAQ;GAC7C,KAAK;GACL,OAAO;GACP,MAAM;EACR,CAAC;EACD,oBAAoB,IAAI,KAAK,eAAe,QAAQ;GAClD,KAAK;GACL,OAAO;GACP,MAAM;EACR,CAAC;CACH,IACA,CAAC,MAAM,CACT;CACF,IAAI,eAAe;CACnB,IAAI,UAAU,MACZ,eACE,SAAS,SAAS,UAAU,OAAO,SAAS,OAAO,IAAI,gBAAgB,OAAO,UAAU;CAE5F,MAAM,cAAc,gCAAgB,IAAI,KAAK;CAC7C,MAAM,eAAe,cAAc,gBAAgB,CAAC,CAAC,WAAW;CAEhE,MAAM,QAAQ,cAAc;EAC1B,MAAM,yBAAQ,IAAI,KAAK,EAAA,CAAE,YAAY;EACrC,MAAM,QAAQ,SAAS,YAAY,KAAK,QAAQ;EAChD,MAAM,OAAO,SAAS,YAAY,KAAK,QAAQ;EAC/C,OAAO,MAAM,KAAK,EAAE,QAAQ,OAAO,QAAQ,EAAE,IAAI,GAAG,UAAU,QAAQ,KAAK;CAC7E,GAAG,CAAC,SAAS,OAAO,CAAC;CAErB,SAAS,KAAK,WAAiB;EAC7B,SAAS,SAAS,SAAS,UAAU,WAAW,SAAS,OAAO,IAAI,SAAS;CAC/E;CAEA,SAAS,WAAW,MAA2B,WAAmB;EAChE,MAAM,OAAO,IAAI,KAAK,WAAW;EACjC,IAAI,SAAS,SAAS;GACpB,MAAM,OAAO,eAAgB,YAAY,MAAO,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK;GAClF,KAAK,SAAS,IAAI;EACpB,OACE,KAAK,WAAW,SAAS;EAE3B,KAAK,IAAI;CACX;CAEA,SAAS,aAAa,QAAgB;EACpC,MAAM,OAAO,IAAI,KAAK,WAAW;EACjC,KAAK,SAAU,KAAK,SAAS,IAAI,KAAM,SAAS,EAAE;EAClD,KAAK,IAAI;CACX;CAEA,SAAS,WAAW,MAAgB,WAAmB;EACrD,MAAM,OAAO,IAAI,KAAK,WAAW;EACjC,MAAM,cAAc,KAAK,QAAQ;EACjC,KAAK,QAAQ,CAAC;EACd,IAAI,SAAS,YAAY,KAAK,YAAY,SAAS;EACnD,IAAI,SAAS,SAAS,KAAK,SAAS,SAAS;EAC7C,IAAI,SAAS,QAAQ,KAAK,QAAQ,SAAS;EAC3C,IAAI,SAAS,QACX,KAAK,QACH,KAAK,IAAI,aAAa,IAAI,KAAK,KAAK,YAAY,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CACtF;EAEF,KAAK,IAAI;CACX;CAEA,IAAI,iBAAiB;CACrB,IAAI,iBAAiB,MAAM;EACzB,IAAI,SAAS,QACX,iBAAiB,GAAG,cAAc,OAAO,YAAY,IAAI,OAAO,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,SAAS;OACvG,iBAAiB,cAAc,OAAO,YAAY;CACzD;CACA,MAAM,mBAAmB,cAAc;EACrC,IAAI,SAAS,QAAQ,OAAO,CAAC;EAC7B,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,KAAK,YAAY,IAAI,GAAG,UAAU;GAClE,MAAM,YAAY,IAAI,KAAK,MAAM,GAAG,CAAC;GACrC,UAAU,SAAS,KAAK,MAAM,SAAS,KAAK,WAAW,CAAC;GACxD,UAAU,WAAY,SAAS,KAAK,cAAe,UAAU;GAC7D,OAAO,GAAG,cAAc,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,SAAS;EAC/F,CAAC;CACH,GAAG;EAAC;EAAQ;EAAY;EAAM;CAAa,CAAC;CAC5C,MAAM,mBAAmB,cAAc;EACrC,IAAI,SAAS,QAAQ,OAAO,CAAC;EAE7B,OAAO,MAAM,SAAS,SAAS;GAoB7B,OAnBe,MAAM,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU;IACtD,MAAM,QAAQ,IAAI,KAAK,MAAM,OAAO,CAAC;IACrC,MAAM,OAAO,IAAI,KAAK,MAAM,QAAQ,GAAG,CAAC;IACxC,IACG,YAAY,KAAA,KAAa,OAAO,eAAe,OAAO,KACtD,YAAY,KAAA,KAAa,QAAQ,eAAe,OAAO,GAExD;IAGF,MAAM,YAAY,IAAI,KAAK,IAAI;IAC/B,IAAI,YAAY,KAAA,KAAa,YAAY,eAAe,OAAO,GAC7D,UAAU,QAAQ,QAAQ,QAAQ,CAAC;IAErC,IAAI,YAAY,KAAA,KAAa,YAAY,eAAe,OAAO,GAC7D,UAAU,QAAQ,QAAQ,QAAQ,CAAC;IAErC,OAAO,cAAc,OAAO,SAAS;GACvC,CACO,CAAA,CAAO,QAAQ,UAA2B,UAAU,KAAA,CAAS;EACtE,CAAC;CACH,GAAG;EAAC;EAAe;EAAS;EAAS;EAAM;CAAK,CAAC;CACjD,MAAM,eAAe,SAAS,SAAS,mBAAmB;CAE1D,MAAM,QAAQ,MAAM,KAAK,EAAE,QAAQ,eAAe,KAAK,GAAG,IAAI,GAAG,UAC/D,eAAe,QAAQ,IAAI,KAC7B,CAAC,CAAC,KAAK,UAAU;EAAE,OAAO,OAAO,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;EAAG,OAAO;CAAK,EAAE;CACvE,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,WAAW,IAAI,GAAG,UAAU;EACpE,MAAM,SAAS,QAAQ;EACvB,OAAO;GAAE,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,GAAG,GAAG;GAAG,OAAO;EAAO;CACjE,CAAC;CACD,MAAM,SAAS,MAAM,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW;EACvD,OAAO,eAAe,OAAO,IAAI,KAAK,MAAM,OAAO,CAAC,CAAC;EACrD,OAAO;CACT,EAAE,CAAC,CAAC,QAAQ,UAAU;EACpB,MAAM,QAAQ,IAAI,KAAK,YAAY,YAAY,GAAG,MAAM,OAAO,CAAC;EAChE,MAAM,OAAO,IAAI,KAAK,YAAY,YAAY,GAAG,MAAM,QAAQ,GAAG,CAAC;EACnE,QACG,YAAY,KAAA,KAAa,QAAQ,eAAe,OAAO,OACvD,YAAY,KAAA,KAAa,SAAS,eAAe,OAAO;CAE7D,CAAC;CACD,MAAM,OAAO,MAAM,KACjB,EAAE,QAAQ,IAAI,KAAK,YAAY,YAAY,GAAG,YAAY,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IACtF,GAAG,WAAW;EAAE,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EAAG,OAAO,QAAQ;CAAE,EAC/E,CAAC,CAAC,QAAQ,QAAQ;EAChB,MAAM,YAAY,IAAI,KAAK,YAAY,YAAY,GAAG,YAAY,SAAS,GAAG,IAAI,KAAK;EACvF,QACG,YAAY,KAAA,KAAa,aAAa,eAAe,OAAO,OAC5D,YAAY,KAAA,KAAa,aAAa,eAAe,OAAO;CAEjE,CAAC;CACD,MAAM,gBAAgB,mBAAmB,cAAc,WAAW,CAAC,CAAC,SAAmB,SAAS;EAC9F,IAAI,KAAK,SAAS,OAAO,OAAO,CAAC,MAAM;EACvC,IAAI,KAAK,SAAS,SAAS,OAAO,CAAC,OAAO;EAC1C,IAAI,KAAK,SAAS,QAAQ,OAAO,CAAC,UAAU;EAC5C,OAAO,CAAC;CACV,CAAC;CACD,MAAM,cAAc,MAAM,KAAK,UAAU;EAAE,OAAO,OAAO,IAAI;EAAG,OAAO;CAAK,EAAE;CAE9E,SAAS,YAAY,MAAgB;EACnC,IAAI,SAAS,QAAQ,OAAO;EAC5B,IAAI,SAAS,SAAS,OAAO;EAC7B,OAAO;CACT;CAEA,SAAS,UAAU,MAAgB;EACjC,IAAI,SAAS,QAAQ,OAAO,YAAY,QAAQ;EAChD,IAAI,SAAS,SAAS,OAAO,YAAY,SAAS;EAClD,OAAO,YAAY,YAAY;CACjC;CACA,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,YAAY;EACzC,OACE,cACG,cAAc,IAAI,KAAK,MAAM,GAAG,GAAG,WAAW,IAAI,IAAI,EAAE,CAAC,CAAC,CAC1D,MAAM,SAAS,KAAK,SAAS,WAAW,CAAC,EAAE,UAAU,WAAW,IAAI,OAAO;EAChF,OAAO;CACT,EAAE;CACF,SAAS,UAAU,MAAgB;EACjC,IAAI,SAAS,QAAQ,OAAO,YAAY;EACxC,IAAI,SAAS,SAAS,OAAO,YAAY;EACzC,OAAO,YAAY;CACrB;CACA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Wheel.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,+
|
|
1
|
+
{"version":3,"file":"Wheel.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,+BA0K9E;AAGD,eAAe,KAAK,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useId, useLayoutEffect, useRef } from "react";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/date-time-picker/wheel/Wheel.tsx
|
|
4
4
|
var WHEEL_LOOP_CYCLES = 11;
|
|
5
5
|
var WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);
|
|
@@ -93,7 +93,7 @@ function Wheel({ ariaLabel, onEscape, onSelect, options, selected }) {
|
|
|
93
93
|
if (typeof event.currentTarget.releasePointerCapture === "function") event.currentTarget.releasePointerCapture(event.pointerId);
|
|
94
94
|
selectCenteredValue();
|
|
95
95
|
}
|
|
96
|
-
return /* @__PURE__ */
|
|
96
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
97
97
|
"aria-activedescendant": `${wheelId}-${selected}`,
|
|
98
98
|
"aria-label": ariaLabel,
|
|
99
99
|
className: "chayns-date-time-picker__wheel",
|
|
@@ -106,7 +106,14 @@ function Wheel({ ariaLabel, onEscape, onSelect, options, selected }) {
|
|
|
106
106
|
ref: wheelRef,
|
|
107
107
|
role: "listbox",
|
|
108
108
|
tabIndex: 0,
|
|
109
|
-
children:
|
|
109
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
110
|
+
"aria-hidden": "true",
|
|
111
|
+
className: "chayns-date-time-picker__wheel-sizer",
|
|
112
|
+
children: options.map((option) => /* @__PURE__ */ jsx("span", {
|
|
113
|
+
className: "chayns-date-time-picker__wheel-sizer-option",
|
|
114
|
+
children: option.label
|
|
115
|
+
}, option.value))
|
|
116
|
+
}), Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) => options.map((option, optionIndex) => /* @__PURE__ */ jsx("button", {
|
|
110
117
|
"aria-hidden": cycle !== WHEEL_CENTER_CYCLE || void 0,
|
|
111
118
|
"aria-selected": option.value === selected,
|
|
112
119
|
id: cycle === WHEEL_CENTER_CYCLE ? `${wheelId}-${option.value}` : void 0,
|
|
@@ -126,7 +133,7 @@ function Wheel({ ariaLabel, onEscape, onSelect, options, selected }) {
|
|
|
126
133
|
tabIndex: -1,
|
|
127
134
|
type: "button",
|
|
128
135
|
children: option.label
|
|
129
|
-
}, `${cycle}-${option.value}`)))
|
|
136
|
+
}, `${cycle}-${option.value}`)))]
|
|
130
137
|
});
|
|
131
138
|
}
|
|
132
139
|
Object.assign(Wheel, { displayName: "DateTimePicker.Wheel" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Wheel.js","names":[],"sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"sourcesContent":["import { useLayoutEffect, useId, useRef } from 'react';\nimport type { KeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\n\nconst WHEEL_LOOP_CYCLES = 11;\nconst WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);\n\ninterface WheelOption {\n label: string;\n value: number;\n}\n\ninterface WheelProps {\n ariaLabel: string;\n onEscape: () => void;\n onSelect: (value: number) => void;\n options: readonly WheelOption[];\n selected: number;\n}\n\nfunction Wheel({ ariaLabel, onEscape, onSelect, options, selected }: WheelProps) {\n const wheelId = useId();\n const wheelRef = useRef<HTMLDivElement>(null);\n const selectedRef = useRef<HTMLButtonElement>(null);\n const dragRef = useRef<{ pointerId: number; scrollTop: number; startY: number } | undefined>(\n undefined,\n );\n const ignoreClickRef = useRef(false);\n\n useLayoutEffect(() => {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n const selectedIndex = options.findIndex((option) => option.value === selected);\n if (!wheel || !itemHeight || selectedIndex < 0) return;\n\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + selectedIndex) * itemHeight;\n applyPerspective();\n }, [options, selected]);\n\n function applyPerspective() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const position = wheel.scrollTop / itemHeight;\n for (const option of wheel.querySelectorAll<HTMLButtonElement>(\n '.chayns-date-time-picker__wheel-option',\n )) {\n const index = Number(option.dataset.wheelIndex);\n const distance = Math.max(-2.5, Math.min(2.5, index - position));\n const progress = Math.min(1, Math.abs(distance) / 2.5);\n\n option.style.color = progress < 0.2 ? 'var(--text)' : 'var(--text-3)';\n option.style.fontWeight = progress < 0.2 ? '600' : '400';\n option.style.opacity = String(1 - progress * 0.7);\n option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * 0.24})`;\n }\n }\n\n function selectCenteredValue() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const option = options[((index % options.length) + options.length) % options.length];\n if (option !== undefined && option.value !== selected) onSelect(option.value);\n }\n\n function handleScroll() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const normalizedIndex = ((index % options.length) + options.length) % options.length;\n if (index < options.length * 2 || index >= options.length * (WHEEL_LOOP_CYCLES - 2)) {\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;\n }\n\n applyPerspective();\n selectCenteredValue();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onEscape();\n return;\n }\n\n const index = options.findIndex((option) => option.value === selected);\n let nextIndex = index;\n if (event.key === 'ArrowDown') nextIndex = Math.min(index + 1, options.length - 1);\n if (event.key === 'ArrowUp') nextIndex = Math.max(index - 1, 0);\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = options.length - 1;\n const nextOption = options[nextIndex];\n if (nextIndex !== index && nextOption !== undefined) {\n event.preventDefault();\n onSelect(nextOption.value);\n }\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n if (event.button !== 0) return;\n event.preventDefault();\n if (typeof event.currentTarget.setPointerCapture === 'function') {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n dragRef.current = {\n pointerId: event.pointerId,\n scrollTop: event.currentTarget.scrollTop,\n startY: event.clientY,\n };\n ignoreClickRef.current = false;\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (drag?.pointerId !== event.pointerId) return;\n const distance = event.clientY - drag.startY;\n if (Math.abs(distance) > 3) {\n ignoreClickRef.current = true;\n event.currentTarget.scrollTop = drag.scrollTop - distance;\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>) {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = undefined;\n if (typeof event.currentTarget.releasePointerCapture === 'function') {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n selectCenteredValue();\n }\n\n return (\n <div\n aria-activedescendant={`${wheelId}-${selected}`}\n aria-label={ariaLabel}\n className=\"chayns-date-time-picker__wheel\"\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerCancel={handlePointerUp}\n onPointerUp={handlePointerUp}\n onScroll={handleScroll}\n ref={wheelRef}\n role=\"listbox\"\n tabIndex={0}\n >\n {Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) =>\n options.map((option, optionIndex) => (\n <button\n aria-hidden={cycle !== WHEEL_CENTER_CYCLE || undefined}\n aria-selected={option.value === selected}\n id={cycle === WHEEL_CENTER_CYCLE ? `${wheelId}-${option.value}` : undefined}\n className=\"chayns-date-time-picker__wheel-option\"\n data-wheel-index={cycle * options.length + optionIndex}\n key={`${cycle}-${option.value}`}\n onClick={(event) => {\n if (ignoreClickRef.current) {\n event.preventDefault();\n event.stopPropagation();\n ignoreClickRef.current = false;\n return;\n }\n onSelect(option.value);\n }}\n ref={\n cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : undefined\n }\n role=\"option\"\n tabIndex={-1}\n type=\"button\"\n >\n {option.label}\n </button>\n )),\n )}\n </div>\n );\n}\n\nObject.assign(Wheel, { displayName: 'DateTimePicker.Wheel' });\nexport default Wheel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Wheel.js","names":[],"sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"sourcesContent":["import { useLayoutEffect, useId, useRef } from 'react';\nimport type { KeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\n\nconst WHEEL_LOOP_CYCLES = 11;\nconst WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);\n\ninterface WheelOption {\n label: string;\n value: number;\n}\n\ninterface WheelProps {\n ariaLabel: string;\n onEscape: () => void;\n onSelect: (value: number) => void;\n options: readonly WheelOption[];\n selected: number;\n}\n\nfunction Wheel({ ariaLabel, onEscape, onSelect, options, selected }: WheelProps) {\n const wheelId = useId();\n const wheelRef = useRef<HTMLDivElement>(null);\n const selectedRef = useRef<HTMLButtonElement>(null);\n const dragRef = useRef<{ pointerId: number; scrollTop: number; startY: number } | undefined>(\n undefined,\n );\n const ignoreClickRef = useRef(false);\n\n useLayoutEffect(() => {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n const selectedIndex = options.findIndex((option) => option.value === selected);\n if (!wheel || !itemHeight || selectedIndex < 0) return;\n\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + selectedIndex) * itemHeight;\n applyPerspective();\n }, [options, selected]);\n\n function applyPerspective() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const position = wheel.scrollTop / itemHeight;\n for (const option of wheel.querySelectorAll<HTMLButtonElement>(\n '.chayns-date-time-picker__wheel-option',\n )) {\n const index = Number(option.dataset.wheelIndex);\n const distance = Math.max(-2.5, Math.min(2.5, index - position));\n const progress = Math.min(1, Math.abs(distance) / 2.5);\n\n option.style.color = progress < 0.2 ? 'var(--text)' : 'var(--text-3)';\n option.style.fontWeight = progress < 0.2 ? '600' : '400';\n option.style.opacity = String(1 - progress * 0.7);\n option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * 0.24})`;\n }\n }\n\n function selectCenteredValue() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const option = options[((index % options.length) + options.length) % options.length];\n if (option !== undefined && option.value !== selected) onSelect(option.value);\n }\n\n function handleScroll() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const normalizedIndex = ((index % options.length) + options.length) % options.length;\n if (index < options.length * 2 || index >= options.length * (WHEEL_LOOP_CYCLES - 2)) {\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;\n }\n\n applyPerspective();\n selectCenteredValue();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onEscape();\n return;\n }\n\n const index = options.findIndex((option) => option.value === selected);\n let nextIndex = index;\n if (event.key === 'ArrowDown') nextIndex = Math.min(index + 1, options.length - 1);\n if (event.key === 'ArrowUp') nextIndex = Math.max(index - 1, 0);\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = options.length - 1;\n const nextOption = options[nextIndex];\n if (nextIndex !== index && nextOption !== undefined) {\n event.preventDefault();\n onSelect(nextOption.value);\n }\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n if (event.button !== 0) return;\n event.preventDefault();\n if (typeof event.currentTarget.setPointerCapture === 'function') {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n dragRef.current = {\n pointerId: event.pointerId,\n scrollTop: event.currentTarget.scrollTop,\n startY: event.clientY,\n };\n ignoreClickRef.current = false;\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (drag?.pointerId !== event.pointerId) return;\n const distance = event.clientY - drag.startY;\n if (Math.abs(distance) > 3) {\n ignoreClickRef.current = true;\n event.currentTarget.scrollTop = drag.scrollTop - distance;\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>) {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = undefined;\n if (typeof event.currentTarget.releasePointerCapture === 'function') {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n selectCenteredValue();\n }\n\n return (\n <div\n aria-activedescendant={`${wheelId}-${selected}`}\n aria-label={ariaLabel}\n className=\"chayns-date-time-picker__wheel\"\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerCancel={handlePointerUp}\n onPointerUp={handlePointerUp}\n onScroll={handleScroll}\n ref={wheelRef}\n role=\"listbox\"\n tabIndex={0}\n >\n <span aria-hidden=\"true\" className=\"chayns-date-time-picker__wheel-sizer\">\n {options.map((option) => (\n <span className=\"chayns-date-time-picker__wheel-sizer-option\" key={option.value}>\n {option.label}\n </span>\n ))}\n </span>\n {Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) =>\n options.map((option, optionIndex) => (\n <button\n aria-hidden={cycle !== WHEEL_CENTER_CYCLE || undefined}\n aria-selected={option.value === selected}\n id={cycle === WHEEL_CENTER_CYCLE ? `${wheelId}-${option.value}` : undefined}\n className=\"chayns-date-time-picker__wheel-option\"\n data-wheel-index={cycle * options.length + optionIndex}\n key={`${cycle}-${option.value}`}\n onClick={(event) => {\n if (ignoreClickRef.current) {\n event.preventDefault();\n event.stopPropagation();\n ignoreClickRef.current = false;\n return;\n }\n onSelect(option.value);\n }}\n ref={\n cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : undefined\n }\n role=\"option\"\n tabIndex={-1}\n type=\"button\"\n >\n {option.label}\n </button>\n )),\n )}\n </div>\n );\n}\n\nObject.assign(Wheel, { displayName: 'DateTimePicker.Wheel' });\nexport default Wheel;\n"],"mappings":";;;AAGA,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB,KAAK,MAAM,oBAAoB,CAAC;AAe3D,SAAS,MAAM,EAAE,WAAW,UAAU,UAAU,SAAS,YAAwB;CAC/E,MAAM,UAAU,MAAM;CACtB,MAAM,WAAW,OAAuB,IAAI;CAC5C,MAAM,cAAc,OAA0B,IAAI;CAClD,MAAM,UAAU,OACd,KAAA,CACF;CACA,MAAM,iBAAiB,OAAO,KAAK;CAEnC,sBAAsB;EACpB,MAAM,QAAQ,SAAS;EACvB,MAAM,aAAa,YAAY,SAAS;EACxC,MAAM,gBAAgB,QAAQ,WAAW,WAAW,OAAO,UAAU,QAAQ;EAC7E,IAAI,CAAC,SAAS,CAAC,cAAc,gBAAgB,GAAG;EAEhD,MAAM,aAAa,qBAAqB,QAAQ,SAAS,iBAAiB;EAC1E,iBAAiB;CACnB,GAAG,CAAC,SAAS,QAAQ,CAAC;CAEtB,SAAS,mBAAmB;EAC1B,MAAM,QAAQ,SAAS;EACvB,MAAM,aAAa,YAAY,SAAS;EACxC,IAAI,CAAC,SAAS,CAAC,YAAY;EAE3B,MAAM,WAAW,MAAM,YAAY;EACnC,KAAK,MAAM,UAAU,MAAM,iBACzB,wCACF,GAAG;GACD,MAAM,QAAQ,OAAO,OAAO,QAAQ,UAAU;GAC9C,MAAM,WAAW,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,QAAQ,QAAQ,CAAC;GAC/D,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,IAAI,GAAG;GAErD,OAAO,MAAM,QAAQ,WAAW,KAAM,gBAAgB;GACtD,OAAO,MAAM,aAAa,WAAW,KAAM,QAAQ;GACnD,OAAO,MAAM,UAAU,OAAO,IAAI,WAAW,EAAG;GAChD,OAAO,MAAM,YAAY,WAAW,WAAW,GAAG,aAAa,IAAI,WAAW,IAAK;EACrF;CACF;CAEA,SAAS,sBAAsB;EAC7B,MAAM,QAAQ,SAAS;EACvB,MAAM,aAAa,YAAY,SAAS;EACxC,IAAI,CAAC,SAAS,CAAC,YAAY;EAG3B,MAAM,SAAS,SADD,KAAK,MAAM,MAAM,YAAY,UAClB,IAAQ,QAAQ,SAAU,QAAQ,UAAU,QAAQ;EAC7E,IAAI,WAAW,KAAA,KAAa,OAAO,UAAU,UAAU,SAAS,OAAO,KAAK;CAC9E;CAEA,SAAS,eAAe;EACtB,MAAM,QAAQ,SAAS;EACvB,MAAM,aAAa,YAAY,SAAS;EACxC,IAAI,CAAC,SAAS,CAAC,YAAY;EAE3B,MAAM,QAAQ,KAAK,MAAM,MAAM,YAAY,UAAU;EACrD,MAAM,mBAAoB,QAAQ,QAAQ,SAAU,QAAQ,UAAU,QAAQ;EAC9E,IAAI,QAAQ,QAAQ,SAAS,KAAK,SAAS,QAAQ,SAAU,GAC3D,MAAM,aAAa,qBAAqB,QAAQ,SAAS,mBAAmB;EAG9E,iBAAiB;EACjB,oBAAoB;CACtB;CAEA,SAAS,cAAc,OAAsC;EAC3D,IAAI,MAAM,QAAQ,UAAU;GAC1B,MAAM,eAAe;GACrB,SAAS;GACT;EACF;EAEA,MAAM,QAAQ,QAAQ,WAAW,WAAW,OAAO,UAAU,QAAQ;EACrE,IAAI,YAAY;EAChB,IAAI,MAAM,QAAQ,aAAa,YAAY,KAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,CAAC;EACjF,IAAI,MAAM,QAAQ,WAAW,YAAY,KAAK,IAAI,QAAQ,GAAG,CAAC;EAC9D,IAAI,MAAM,QAAQ,QAAQ,YAAY;EACtC,IAAI,MAAM,QAAQ,OAAO,YAAY,QAAQ,SAAS;EACtD,MAAM,aAAa,QAAQ;EAC3B,IAAI,cAAc,SAAS,eAAe,KAAA,GAAW;GACnD,MAAM,eAAe;GACrB,SAAS,WAAW,KAAK;EAC3B;CACF;CAEA,SAAS,kBAAkB,OAA0C;EACnE,IAAI,MAAM,WAAW,GAAG;EACxB,MAAM,eAAe;EACrB,IAAI,OAAO,MAAM,cAAc,sBAAsB,YACnD,MAAM,cAAc,kBAAkB,MAAM,SAAS;EAEvD,QAAQ,UAAU;GAChB,WAAW,MAAM;GACjB,WAAW,MAAM,cAAc;GAC/B,QAAQ,MAAM;EAChB;EACA,eAAe,UAAU;CAC3B;CAEA,SAAS,kBAAkB,OAA0C;EACnE,MAAM,OAAO,QAAQ;EACrB,IAAI,MAAM,cAAc,MAAM,WAAW;EACzC,MAAM,WAAW,MAAM,UAAU,KAAK;EACtC,IAAI,KAAK,IAAI,QAAQ,IAAI,GAAG;GAC1B,eAAe,UAAU;GACzB,MAAM,cAAc,YAAY,KAAK,YAAY;EACnD;CACF;CAEA,SAAS,gBAAgB,OAA0C;EACjE,IAAI,QAAQ,SAAS,cAAc,MAAM,WAAW;EACpD,QAAQ,UAAU,KAAA;EAClB,IAAI,OAAO,MAAM,cAAc,0BAA0B,YACvD,MAAM,cAAc,sBAAsB,MAAM,SAAS;EAE3D,oBAAoB;CACtB;CAEA,OACE,qBAAC,OAAD;EACE,yBAAuB,GAAG,QAAQ,GAAG;EACrC,cAAY;EACZ,WAAU;EACV,WAAW;EACX,eAAe;EACf,eAAe;EACf,iBAAiB;EACjB,aAAa;EACb,UAAU;EACV,KAAK;EACL,MAAK;EACL,UAAU;EAZZ,UAAA,CAcE,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GAChC,UAAA,QAAQ,KAAK,WACZ,oBAAC,QAAD;IAAM,WAAU;IACb,UAAA,OAAO;GACJ,GAF6D,OAAO,KAEpE,CACP;EACG,CAAA,GACL,MAAM,KAAK,EAAE,QAAQ,kBAAkB,IAAI,GAAG,UAC7C,QAAQ,KAAK,QAAQ,gBACnB,oBAAC,UAAD;GACE,eAAa,UAAU,sBAAsB,KAAA;GAC7C,iBAAe,OAAO,UAAU;GAChC,IAAI,UAAU,qBAAqB,GAAG,QAAQ,GAAG,OAAO,UAAU,KAAA;GAClE,WAAU;GACV,oBAAkB,QAAQ,QAAQ,SAAS;GAE3C,UAAU,UAAU;IAClB,IAAI,eAAe,SAAS;KAC1B,MAAM,eAAe;KACrB,MAAM,gBAAgB;KACtB,eAAe,UAAU;KACzB;IACF;IACA,SAAS,OAAO,KAAK;GACvB;GACA,KACE,UAAU,sBAAsB,OAAO,UAAU,WAAW,cAAc,KAAA;GAE5E,MAAK;GACL,UAAU;GACV,MAAK;GAEJ,UAAA,OAAO;EACF,GAlBD,GAAG,MAAM,GAAG,OAAO,OAkBlB,CACT,CACH,CACG;;AAET;AAEA,OAAO,OAAO,OAAO,EAAE,aAAa,uBAAuB,CAAC"}
|
|
@@ -71,12 +71,9 @@
|
|
|
71
71
|
|
|
72
72
|
.chayns-date-time-picker__popup {
|
|
73
73
|
box-sizing: border-box;
|
|
74
|
-
position:
|
|
75
|
-
inset-block-start: calc(100% + var(--k4));
|
|
76
|
-
inset-inline-start: 0;
|
|
74
|
+
position: fixed;
|
|
77
75
|
z-index: var(--z-popover);
|
|
78
76
|
inline-size: max-content;
|
|
79
|
-
min-inline-size: 100%;
|
|
80
77
|
overflow: hidden;
|
|
81
78
|
padding: var(--k8);
|
|
82
79
|
border: 1px solid var(--border);
|
|
@@ -116,6 +113,24 @@
|
|
|
116
113
|
user-select: none;
|
|
117
114
|
}
|
|
118
115
|
|
|
116
|
+
.chayns-date-time-picker__wheel-sizer {
|
|
117
|
+
display: block;
|
|
118
|
+
position: fixed;
|
|
119
|
+
inset-block-start: 0;
|
|
120
|
+
inset-inline-start: -10000px;
|
|
121
|
+
inline-size: max-content;
|
|
122
|
+
pointer-events: none;
|
|
123
|
+
visibility: hidden;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.chayns-date-time-picker__wheel-sizer-option {
|
|
128
|
+
display: block;
|
|
129
|
+
font: inherit;
|
|
130
|
+
font-weight: 600;
|
|
131
|
+
padding-inline: var(--k8);
|
|
132
|
+
}
|
|
133
|
+
|
|
119
134
|
.chayns-date-time-picker__wheel:focus-visible {
|
|
120
135
|
outline: var(--focus-ring-size) solid rgb(var(--focus-ring-rgb), var(--focus-ring-alpha-strong));
|
|
121
136
|
outline-offset: 2px;
|
|
@@ -141,7 +156,7 @@
|
|
|
141
156
|
|
|
142
157
|
.chayns-date-time-picker--date .chayns-date-time-picker__wheel {
|
|
143
158
|
flex: 0 0 auto;
|
|
144
|
-
|
|
159
|
+
inline-size: max-content;
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
.chayns-date-time-picker--date .chayns-date-time-picker__wheel-option {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
2
|
/** Positions a non-modal surface at its trigger and keeps it inside the viewport. */
|
|
3
|
-
export declare function useOverlayPosition(surfaceRef: RefObject<HTMLElement | null>, trigger: HTMLElement | null, open: boolean, placement?: 'bottom' | 'top', gap?: number): void;
|
|
3
|
+
export declare function useOverlayPosition(surfaceRef: RefObject<HTMLElement | null>, trigger: HTMLElement | null, open: boolean, placement?: 'bottom' | 'top', gap?: number, matchTriggerWidth?: boolean): void;
|
|
4
4
|
//# sourceMappingURL=useOverlayPosition.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOverlayPosition.d.ts","sourceRoot":"","sources":["../../src/hooks/useOverlayPosition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACzC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,IAAI,EAAE,OAAO,EACb,SAAS,GAAE,QAAQ,GAAG,KAAgB,EACtC,GAAG,SAAI,
|
|
1
|
+
{"version":3,"file":"useOverlayPosition.d.ts","sourceRoot":"","sources":["../../src/hooks/useOverlayPosition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACzC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,IAAI,EAAE,OAAO,EACb,SAAS,GAAE,QAAQ,GAAG,KAAgB,EACtC,GAAG,SAAI,EACP,iBAAiB,UAAQ,QA0D1B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
//#region src/hooks/useOverlayPosition.ts
|
|
3
3
|
/** Positions a non-modal surface at its trigger and keeps it inside the viewport. */
|
|
4
|
-
function useOverlayPosition(surfaceRef, trigger, open, placement = "bottom", gap = 0) {
|
|
4
|
+
function useOverlayPosition(surfaceRef, trigger, open, placement = "bottom", gap = 0, matchTriggerWidth = false) {
|
|
5
5
|
useEffect(() => {
|
|
6
6
|
const surface = surfaceRef.current;
|
|
7
7
|
if (!open || surface === null || trigger === null) return void 0;
|
|
@@ -11,6 +11,7 @@ function useOverlayPosition(surfaceRef, trigger, open, placement = "bottom", gap
|
|
|
11
11
|
const anchor = trigger.getBoundingClientRect();
|
|
12
12
|
surface.style.maxWidth = `${window.innerWidth}px`;
|
|
13
13
|
surface.style.maxHeight = `${window.innerHeight}px`;
|
|
14
|
+
if (matchTriggerWidth) surface.style.minWidth = `${anchor.width}px`;
|
|
14
15
|
const size = surface.getBoundingClientRect();
|
|
15
16
|
const above = anchor.top - gap - size.height;
|
|
16
17
|
const below = anchor.bottom + gap;
|
|
@@ -48,6 +49,7 @@ function useOverlayPosition(surfaceRef, trigger, open, placement = "bottom", gap
|
|
|
48
49
|
};
|
|
49
50
|
}, [
|
|
50
51
|
gap,
|
|
52
|
+
matchTriggerWidth,
|
|
51
53
|
open,
|
|
52
54
|
placement,
|
|
53
55
|
surfaceRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOverlayPosition.js","names":[],"sources":["../../src/hooks/useOverlayPosition.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\n/** Positions a non-modal surface at its trigger and keeps it inside the viewport. */\nexport function useOverlayPosition(\n surfaceRef: RefObject<HTMLElement | null>,\n trigger: HTMLElement | null,\n open: boolean,\n placement: 'bottom' | 'top' = 'bottom',\n gap = 0,\n) {\n useEffect(() => {\n const surface = surfaceRef.current;\n if (!open || surface === null || trigger === null) return undefined;\n\n let frame: number | undefined;\n function update() {\n if (surface === null || trigger === null) return;\n const anchor = trigger.getBoundingClientRect();\n surface.style.maxWidth = `${window.innerWidth}px`;\n surface.style.maxHeight = `${window.innerHeight}px`;\n const size = surface.getBoundingClientRect();\n const above = anchor.top - gap - size.height;\n const below = anchor.bottom + gap;\n const fitsAbove = above >= 0;\n const fitsBelow = below + size.height <= window.innerHeight;\n let top = below;\n if (placement === 'top') {\n if (fitsAbove || !fitsBelow) top = above;\n } else if (!fitsBelow && fitsAbove) {\n top = above;\n }\n const left =\n placement === 'top' ? anchor.left + (anchor.width - size.width) / 2 : anchor.left;\n surface.style.top = `${Math.max(0, Math.min(top, window.innerHeight - size.height))}px`;\n const resolvedLeft = Math.max(0, Math.min(left, window.innerWidth - size.width));\n surface.style.left = `${resolvedLeft}px`;\n surface.style.setProperty(\n '--chayns-overlay-anchor-x',\n `${anchor.left + anchor.width / 2 - resolvedLeft}px`,\n );\n surface.dataset.placement = top === above ? 'top' : 'bottom';\n }\n\n function scheduleUpdate() {\n if (frame !== undefined) return;\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n update();\n });\n }\n\n update();\n const observer =\n typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(scheduleUpdate);\n observer?.observe(surface);\n observer?.observe(trigger);\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n return () => {\n if (frame !== undefined) window.cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n };\n }, [gap, open, placement, surfaceRef, trigger]);\n}\n"],"mappings":";;;AAIA,SAAgB,mBACd,YACA,SACA,MACA,YAA8B,UAC9B,MAAM,GACN;CACA,gBAAgB;EACd,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,YAAY,QAAQ,YAAY,MAAM,OAAO,KAAA;EAE1D,IAAI;EACJ,SAAS,SAAS;GAChB,IAAI,YAAY,QAAQ,YAAY,MAAM;GAC1C,MAAM,SAAS,QAAQ,sBAAsB;GAC7C,QAAQ,MAAM,WAAW,GAAG,OAAO,WAAW;GAC9C,QAAQ,MAAM,YAAY,GAAG,OAAO,YAAY;GAChD,MAAM,OAAO,QAAQ,sBAAsB;GAC3C,MAAM,QAAQ,OAAO,MAAM,MAAM,KAAK;GACtC,MAAM,QAAQ,OAAO,SAAS;GAC9B,MAAM,YAAY,SAAS;GAC3B,MAAM,YAAY,QAAQ,KAAK,UAAU,OAAO;GAChD,IAAI,MAAM;GACV,IAAI,cAAc,OACZ;QAAA,aAAa,CAAC,WAAW,MAAM;GAAA,OAC9B,IAAI,CAAC,aAAa,WACvB,MAAM;GAER,MAAM,OACJ,cAAc,QAAQ,OAAO,QAAQ,OAAO,QAAQ,KAAK,SAAS,IAAI,OAAO;GAC/E,QAAQ,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,cAAc,KAAK,MAAM,CAAC,EAAE;GACpF,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,OAAO,aAAa,KAAK,KAAK,CAAC;GAC/E,QAAQ,MAAM,OAAO,GAAG,aAAa;GACrC,QAAQ,MAAM,YACZ,6BACA,GAAG,OAAO,OAAO,OAAO,QAAQ,IAAI,aAAa,GACnD;GACA,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ;EACtD;EAEA,SAAS,iBAAiB;GACxB,IAAI,UAAU,KAAA,GAAW;GACzB,QAAQ,OAAO,4BAA4B;IACzC,QAAQ,KAAA;IACR,OAAO;GACT,CAAC;EACH;EAEA,OAAO;EACP,MAAM,WACJ,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,cAAc;EACvF,UAAU,QAAQ,OAAO;EACzB,UAAU,QAAQ,OAAO;EACzB,OAAO,iBAAiB,UAAU,cAAc;EAChD,OAAO,iBAAiB,UAAU,gBAAgB,IAAI;EACtD,aAAa;GACX,IAAI,UAAU,KAAA,GAAW,OAAO,qBAAqB,KAAK;GAC1D,UAAU,WAAW;GACrB,OAAO,oBAAoB,UAAU,cAAc;GACnD,OAAO,oBAAoB,UAAU,gBAAgB,IAAI;EAC3D;CACF,GAAG;EAAC;EAAK;EAAM;EAAW;EAAY;CAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useOverlayPosition.js","names":[],"sources":["../../src/hooks/useOverlayPosition.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\n/** Positions a non-modal surface at its trigger and keeps it inside the viewport. */\nexport function useOverlayPosition(\n surfaceRef: RefObject<HTMLElement | null>,\n trigger: HTMLElement | null,\n open: boolean,\n placement: 'bottom' | 'top' = 'bottom',\n gap = 0,\n matchTriggerWidth = false,\n) {\n useEffect(() => {\n const surface = surfaceRef.current;\n if (!open || surface === null || trigger === null) return undefined;\n\n let frame: number | undefined;\n function update() {\n if (surface === null || trigger === null) return;\n const anchor = trigger.getBoundingClientRect();\n surface.style.maxWidth = `${window.innerWidth}px`;\n surface.style.maxHeight = `${window.innerHeight}px`;\n if (matchTriggerWidth) surface.style.minWidth = `${anchor.width}px`;\n const size = surface.getBoundingClientRect();\n const above = anchor.top - gap - size.height;\n const below = anchor.bottom + gap;\n const fitsAbove = above >= 0;\n const fitsBelow = below + size.height <= window.innerHeight;\n let top = below;\n if (placement === 'top') {\n if (fitsAbove || !fitsBelow) top = above;\n } else if (!fitsBelow && fitsAbove) {\n top = above;\n }\n const left =\n placement === 'top' ? anchor.left + (anchor.width - size.width) / 2 : anchor.left;\n surface.style.top = `${Math.max(0, Math.min(top, window.innerHeight - size.height))}px`;\n const resolvedLeft = Math.max(0, Math.min(left, window.innerWidth - size.width));\n surface.style.left = `${resolvedLeft}px`;\n surface.style.setProperty(\n '--chayns-overlay-anchor-x',\n `${anchor.left + anchor.width / 2 - resolvedLeft}px`,\n );\n surface.dataset.placement = top === above ? 'top' : 'bottom';\n }\n\n function scheduleUpdate() {\n if (frame !== undefined) return;\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n update();\n });\n }\n\n update();\n const observer =\n typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(scheduleUpdate);\n observer?.observe(surface);\n observer?.observe(trigger);\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n return () => {\n if (frame !== undefined) window.cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n };\n }, [gap, matchTriggerWidth, open, placement, surfaceRef, trigger]);\n}\n"],"mappings":";;;AAIA,SAAgB,mBACd,YACA,SACA,MACA,YAA8B,UAC9B,MAAM,GACN,oBAAoB,OACpB;CACA,gBAAgB;EACd,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,YAAY,QAAQ,YAAY,MAAM,OAAO,KAAA;EAE1D,IAAI;EACJ,SAAS,SAAS;GAChB,IAAI,YAAY,QAAQ,YAAY,MAAM;GAC1C,MAAM,SAAS,QAAQ,sBAAsB;GAC7C,QAAQ,MAAM,WAAW,GAAG,OAAO,WAAW;GAC9C,QAAQ,MAAM,YAAY,GAAG,OAAO,YAAY;GAChD,IAAI,mBAAmB,QAAQ,MAAM,WAAW,GAAG,OAAO,MAAM;GAChE,MAAM,OAAO,QAAQ,sBAAsB;GAC3C,MAAM,QAAQ,OAAO,MAAM,MAAM,KAAK;GACtC,MAAM,QAAQ,OAAO,SAAS;GAC9B,MAAM,YAAY,SAAS;GAC3B,MAAM,YAAY,QAAQ,KAAK,UAAU,OAAO;GAChD,IAAI,MAAM;GACV,IAAI,cAAc,OACZ;QAAA,aAAa,CAAC,WAAW,MAAM;GAAA,OAC9B,IAAI,CAAC,aAAa,WACvB,MAAM;GAER,MAAM,OACJ,cAAc,QAAQ,OAAO,QAAQ,OAAO,QAAQ,KAAK,SAAS,IAAI,OAAO;GAC/E,QAAQ,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,cAAc,KAAK,MAAM,CAAC,EAAE;GACpF,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,OAAO,aAAa,KAAK,KAAK,CAAC;GAC/E,QAAQ,MAAM,OAAO,GAAG,aAAa;GACrC,QAAQ,MAAM,YACZ,6BACA,GAAG,OAAO,OAAO,OAAO,QAAQ,IAAI,aAAa,GACnD;GACA,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ;EACtD;EAEA,SAAS,iBAAiB;GACxB,IAAI,UAAU,KAAA,GAAW;GACzB,QAAQ,OAAO,4BAA4B;IACzC,QAAQ,KAAA;IACR,OAAO;GACT,CAAC;EACH;EAEA,OAAO;EACP,MAAM,WACJ,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,cAAc;EACvF,UAAU,QAAQ,OAAO;EACzB,UAAU,QAAQ,OAAO;EACzB,OAAO,iBAAiB,UAAU,cAAc;EAChD,OAAO,iBAAiB,UAAU,gBAAgB,IAAI;EACtD,aAAa;GACX,IAAI,UAAU,KAAA,GAAW,OAAO,qBAAqB,KAAK;GAC1D,UAAU,WAAW;GACrB,OAAO,oBAAoB,UAAU,cAAc;GACnD,OAAO,oBAAoB,UAAU,gBAAgB,IAAI;EAC3D;CACF,GAAG;EAAC;EAAK;EAAmB;EAAM;EAAW;EAAY;CAAO,CAAC;AACnE"}
|