@purpur/library 9.10.0 → 9.10.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/CHANGELOG.json +18 -0
- package/CHANGELOG.md +10 -1
- package/dist/LICENSE.txt +40 -0
- package/dist/{RichText-D4vznH1B.mjs → RichText-2_z57EYi.mjs} +2 -2
- package/dist/{RichText-D4vznH1B.mjs.map → RichText-2_z57EYi.mjs.map} +1 -1
- package/dist/{RichText-BAVZadzi.js → RichText-IejAKqm2.js} +2 -2
- package/dist/{RichText-BAVZadzi.js.map → RichText-IejAKqm2.js.map} +1 -1
- package/dist/{autocomplete-CmLzmWp4.mjs → autocomplete-C6AqdYaZ.mjs} +2 -2
- package/dist/{autocomplete-CmLzmWp4.mjs.map → autocomplete-C6AqdYaZ.mjs.map} +1 -1
- package/dist/{autocomplete-BX1KDZqL.js → autocomplete-yrPbF5gq.js} +2 -2
- package/dist/{autocomplete-BX1KDZqL.js.map → autocomplete-yrPbF5gq.js.map} +1 -1
- package/dist/autocomplete.cjs.js +1 -1
- package/dist/autocomplete.es.js +1 -1
- package/dist/button-DZgtrGqN.js +2 -0
- package/dist/{button-DmybVApa.js.map → button-DZgtrGqN.js.map} +1 -1
- package/dist/button-EVRfctR8.mjs +109 -0
- package/dist/{button-4-yWOgtD.mjs.map → button-EVRfctR8.mjs.map} +1 -1
- package/dist/button.cjs.js +1 -1
- package/dist/button.es.js +1 -1
- package/dist/{calendar-Cru-p6gC.mjs → calendar-CTWhxuS4.mjs} +2 -2
- package/dist/{calendar-Cru-p6gC.mjs.map → calendar-CTWhxuS4.mjs.map} +1 -1
- package/dist/{calendar-DDR8CQYo.js → calendar-Cwzqytai.js} +2 -2
- package/dist/{calendar-DDR8CQYo.js.map → calendar-Cwzqytai.js.map} +1 -1
- package/dist/calendar.cjs.js +1 -1
- package/dist/calendar.es.js +1 -1
- package/dist/{carousel-BIKcwvYz.mjs → carousel-DiKGSL-7.mjs} +2 -2
- package/dist/{carousel-BIKcwvYz.mjs.map → carousel-DiKGSL-7.mjs.map} +1 -1
- package/dist/{carousel-DnSaLDZf.js → carousel-Dz_bUGo4.js} +2 -2
- package/dist/{carousel-DnSaLDZf.js.map → carousel-Dz_bUGo4.js.map} +1 -1
- package/dist/carousel.cjs.js +1 -1
- package/dist/carousel.es.js +1 -1
- package/dist/{chat-field-CVF4DooY.mjs → chat-field-8cKqYcKi.mjs} +2 -2
- package/dist/{chat-field-CVF4DooY.mjs.map → chat-field-8cKqYcKi.mjs.map} +1 -1
- package/dist/{chat-field-Wjvh2J6C.js → chat-field-B2jmpVNr.js} +2 -2
- package/dist/{chat-field-Wjvh2J6C.js.map → chat-field-B2jmpVNr.js.map} +1 -1
- package/dist/chat-field.cjs.js +1 -1
- package/dist/chat-field.es.js +1 -1
- package/dist/{comparison-table-D1evE0ri.mjs → comparison-table-CmtSOUfK.mjs} +2 -2
- package/dist/{comparison-table-D1evE0ri.mjs.map → comparison-table-CmtSOUfK.mjs.map} +1 -1
- package/dist/{comparison-table-Dtqxz8vL.js → comparison-table-N5G3k2kr.js} +2 -2
- package/dist/{comparison-table-Dtqxz8vL.js.map → comparison-table-N5G3k2kr.js.map} +1 -1
- package/dist/comparison-table.cjs.js +1 -1
- package/dist/comparison-table.es.js +1 -1
- package/dist/components/accordion/src/accordion-item.d.ts +2 -2
- package/dist/components/accordion/src/accordion.d.ts +2 -2
- package/dist/components/avatar/src/avatar.d.ts +1 -1
- package/dist/components/button/src/button.d.ts +5 -5
- package/dist/components/card/src/card-badge.d.ts +1 -1
- package/dist/components/card/src/card-cta.d.ts +1 -1
- package/dist/components/card/src/card-heading.d.ts +1 -1
- package/dist/components/card/src/card-media-layout.d.ts +1 -1
- package/dist/components/card/src/card-media.d.ts +1 -1
- package/dist/components/checkbox/src/checkbox.d.ts +1 -1
- package/dist/components/comparison-table/src/components/OptionCard/option-card.d.ts +1 -1
- package/dist/components/content-block/src/content-block.d.ts +2 -2
- package/dist/components/counter-badge/src/counter-badge.d.ts +1 -1
- package/dist/components/country-flag-icon/src/country-flag-icon.d.ts +1 -1
- package/dist/components/date-field/src/date-field.d.ts +1 -1
- package/dist/components/date-picker/src/date-picker.d.ts +4 -4
- package/dist/components/dismissable-chip-group/src/dismissable-chip-group-item.d.ts +1 -1
- package/dist/components/dismissable-chip-group/src/dismissable-chip-group.d.ts +2 -2
- package/dist/components/drawer/src/drawer-content.d.ts +2 -2
- package/dist/components/drawer/src/drawer-frame.d.ts +1 -1
- package/dist/components/drawer/src/drawer-trigger.d.ts +1 -1
- package/dist/components/field-error-text/src/field-error-text.d.ts +2 -2
- package/dist/components/field-helper-text/src/field-helper-text.d.ts +1 -1
- package/dist/components/footer/src/footer-navigation.d.ts +1 -1
- package/dist/components/footer/src/footer-social-link.d.ts +3 -3
- package/dist/components/footer/src/footer.d.ts +3 -3
- package/dist/components/grid/src/grid.item.d.ts +1 -1
- package/dist/components/heading/src/heading.d.ts +2 -2
- package/dist/components/hero-banner/src/hero-banner-actions.d.ts +1 -1
- package/dist/components/hero-banner/src/hero-banner-media.d.ts +1 -1
- package/dist/components/hero-banner/src/hero-banner-types.d.ts +2 -2
- package/dist/components/illustrative-icon/src/static-illustrative-icon.d.ts +2 -2
- package/dist/components/listbox/src/listbox-item.d.ts +1 -1
- package/dist/components/listbox/src/listbox.d.ts +1 -1
- package/dist/components/logo/src/logo.types.d.ts +1 -1
- package/dist/components/notification-banner/src/notification-banner.d.ts +2 -2
- package/dist/components/pagination/src/pagination-page-selector.d.ts +2 -2
- package/dist/components/pagination/src/pagination-page-size-selector.d.ts +2 -2
- package/dist/components/pagination/src/pagination-pages.d.ts +2 -2
- package/dist/components/pagination/src/use-page-options.hook.d.ts +2 -2
- package/dist/components/pagination/src/use-page-size-options.hook.d.ts +2 -2
- package/dist/components/paragraph/src/paragraph.d.ts +1 -1
- package/dist/components/password-field/src/password-strength-indicator.d.ts +2 -2
- package/dist/components/password-field/src/password-strength.d.ts +2 -2
- package/dist/components/popover/src/popover-button.d.ts +2 -2
- package/dist/components/product-card/src/product-card.d.ts +1 -1
- package/dist/components/promotion-card/src/promotion-card.d.ts +1 -1
- package/dist/components/quantity-selector/src/quantity-selector.d.ts +1 -1
- package/dist/components/radio-button-group/src/radio-button-group-root.d.ts +1 -1
- package/dist/components/radio-card-group/src/radio-card-group.d.ts +2 -2
- package/dist/components/search-field/src/search-field-autocomplete.d.ts +1 -1
- package/dist/components/search-field/src/search-field-base.d.ts +1 -1
- package/dist/components/search-field/src/search-field.d.ts +6 -6
- package/dist/components/select/src/select.d.ts +1 -1
- package/dist/components/spacer/src/spacer.d.ts +2 -2
- package/dist/components/spinner/src/spinner.d.ts +1 -1
- package/dist/components/stepper/src/stepper-content.d.ts +1 -1
- package/dist/components/stepper/src/stepper.d.ts +2 -2
- package/dist/components/table/src/cell-types/button-group-cell.d.ts +1 -1
- package/dist/components/table/src/empty-table.d.ts +2 -2
- package/dist/components/table/src/table-content.d.ts +2 -2
- package/dist/components/table/src/table.d.ts +1 -1
- package/dist/components/table/src/test-utils/table-data.d.ts +3 -3
- package/dist/components/tabs/src/tab-content.d.ts +1 -1
- package/dist/components/text-area/src/text-area.d.ts +1 -1
- package/dist/components/text-spacing/src/text-spacing.d.ts +1 -1
- package/dist/components/toggle/src/toggle.d.ts +1 -1
- package/dist/{date-field-DVp_RMNm.mjs → date-field-ChYx0N2j.mjs} +2 -2
- package/dist/{date-field-DVp_RMNm.mjs.map → date-field-ChYx0N2j.mjs.map} +1 -1
- package/dist/{date-field-hA79n6mP.js → date-field-CwZ64buh.js} +2 -2
- package/dist/{date-field-hA79n6mP.js.map → date-field-CwZ64buh.js.map} +1 -1
- package/dist/date-field.cjs.js +1 -1
- package/dist/date-field.es.js +1 -1
- package/dist/{date-picker-Dzoo_hhQ.js → date-picker-BWMKTOq6.js} +2 -2
- package/dist/{date-picker-Dzoo_hhQ.js.map → date-picker-BWMKTOq6.js.map} +1 -1
- package/dist/{date-picker-B8ta-Q8V.mjs → date-picker-CTyqgBRB.mjs} +5 -5
- package/dist/{date-picker-B8ta-Q8V.mjs.map → date-picker-CTyqgBRB.mjs.map} +1 -1
- package/dist/date-picker.cjs.js +1 -1
- package/dist/date-picker.es.js +1 -1
- package/dist/{date-range-field-Dqqgj41u.js → date-range-field-CvzOl-eC.js} +2 -2
- package/dist/{date-range-field-Dqqgj41u.js.map → date-range-field-CvzOl-eC.js.map} +1 -1
- package/dist/{date-range-field-BZUjfftV.mjs → date-range-field-DDr-qEGX.mjs} +2 -2
- package/dist/{date-range-field-BZUjfftV.mjs.map → date-range-field-DDr-qEGX.mjs.map} +1 -1
- package/dist/date-range-field.cjs.js +1 -1
- package/dist/date-range-field.es.js +1 -1
- package/dist/{drawer-DyLQfvEh.js → drawer-BnqxUIPM.js} +2 -2
- package/dist/{drawer-DyLQfvEh.js.map → drawer-BnqxUIPM.js.map} +1 -1
- package/dist/{drawer-cIUx6WSZ.mjs → drawer-Cnk2OKgi.mjs} +2 -2
- package/dist/{drawer-cIUx6WSZ.mjs.map → drawer-Cnk2OKgi.mjs.map} +1 -1
- package/dist/drawer.cjs.js +1 -1
- package/dist/drawer.es.js +1 -1
- package/dist/{footer-Cn1-zG1v.js → footer-B8rzVSrZ.js} +2 -2
- package/dist/{footer-Cn1-zG1v.js.map → footer-B8rzVSrZ.js.map} +1 -1
- package/dist/{footer-D-2b7UIB.mjs → footer-D5YkHmCo.mjs} +2 -2
- package/dist/{footer-D-2b7UIB.mjs.map → footer-D5YkHmCo.mjs.map} +1 -1
- package/dist/footer.cjs.js +1 -1
- package/dist/footer.es.js +1 -1
- package/dist/{hero-banner-n9K-Jsdz.mjs → hero-banner-BXRArPWP.mjs} +2 -2
- package/dist/{hero-banner-n9K-Jsdz.mjs.map → hero-banner-BXRArPWP.mjs.map} +1 -1
- package/dist/{hero-banner--v-ezYMr.js → hero-banner-CW7DIEZe.js} +2 -2
- package/dist/{hero-banner--v-ezYMr.js.map → hero-banner-CW7DIEZe.js.map} +1 -1
- package/dist/hero-banner.cjs.js +1 -1
- package/dist/hero-banner.es.js +1 -1
- package/dist/libraries/library/src/library.d.ts +1 -0
- package/dist/libraries/library/src/library.d.ts.map +1 -1
- package/dist/libraries/library/src/password-field.d.ts +6 -2
- package/dist/libraries/library/src/password-field.d.ts.map +1 -1
- package/dist/libraries/library/src/radio-button-group.d.ts +1 -1
- package/dist/libraries/library/src/radio-card-group.d.ts +1 -1
- package/dist/libraries/library/src/spinner.d.ts +1 -1
- package/dist/libraries/library/src/stepper.d.ts +1 -1
- package/dist/libraries/library/src/tooltip.d.ts +1 -1
- package/dist/libraries/library/src/visually-hidden.d.ts +1 -1
- package/dist/libraries/theme/src/ThemeProvider.d.ts +2 -2
- package/dist/library.cjs.js +1 -1
- package/dist/library.es.js +546 -543
- package/dist/library.es.js.map +1 -1
- package/dist/link-Dzqd0QuD.js +2 -0
- package/dist/{link-DhWVrkTz.js.map → link-Dzqd0QuD.js.map} +1 -1
- package/dist/link-ccCdDvBc.mjs +72 -0
- package/dist/{link-DY5WLpyc.mjs.map → link-ccCdDvBc.mjs.map} +1 -1
- package/dist/link.cjs.js +1 -1
- package/dist/link.es.js +1 -1
- package/dist/main-B501z9Ql.js +2 -0
- package/dist/main-B501z9Ql.js.map +1 -0
- package/dist/main-L71Sqg3s.mjs +1016 -0
- package/dist/main-L71Sqg3s.mjs.map +1 -0
- package/dist/{modal-Bu1Zv5Ic.mjs → modal-BuUQrUYJ.mjs} +2 -2
- package/dist/{modal-Bu1Zv5Ic.mjs.map → modal-BuUQrUYJ.mjs.map} +1 -1
- package/dist/{modal-D0Qxrvx5.js → modal-CnC4Zyjk.js} +2 -2
- package/dist/{modal-D0Qxrvx5.js.map → modal-CnC4Zyjk.js.map} +1 -1
- package/dist/modal.cjs.js +1 -1
- package/dist/modal.es.js +1 -1
- package/dist/{notification-DiVdy6E_.mjs → notification-C3f3N1K1.mjs} +2 -2
- package/dist/{notification-DiVdy6E_.mjs.map → notification-C3f3N1K1.mjs.map} +1 -1
- package/dist/{notification-D2oClkX2.js → notification-CeoAXDXq.js} +2 -2
- package/dist/{notification-D2oClkX2.js.map → notification-CeoAXDXq.js.map} +1 -1
- package/dist/{notification-banner-CZTQZ5Le.mjs → notification-banner-BvAy8dlg.mjs} +2 -2
- package/dist/{notification-banner-CZTQZ5Le.mjs.map → notification-banner-BvAy8dlg.mjs.map} +1 -1
- package/dist/{notification-banner-BxHwTFnH.js → notification-banner-DUe4fT1r.js} +2 -2
- package/dist/{notification-banner-BxHwTFnH.js.map → notification-banner-DUe4fT1r.js.map} +1 -1
- package/dist/notification-banner.cjs.js +1 -1
- package/dist/notification-banner.es.js +1 -1
- package/dist/notification.cjs.js +1 -1
- package/dist/notification.es.js +1 -1
- package/dist/password-field-BjKdBoIK.js +2 -0
- package/dist/password-field-BjKdBoIK.js.map +1 -0
- package/dist/password-field-C_E4563x.mjs +200 -0
- package/dist/password-field-C_E4563x.mjs.map +1 -0
- package/dist/password-field.cjs.js +2 -0
- package/dist/password-field.cjs.js.map +1 -0
- package/dist/password-field.es.js +6 -0
- package/dist/password-field.es.js.map +1 -0
- package/dist/{popover-CY75TnbA.js → popover-4phnhJLj.js} +2 -2
- package/dist/{popover-CY75TnbA.js.map → popover-4phnhJLj.js.map} +1 -1
- package/dist/{popover-wiiwtqWE.mjs → popover-DhObSx97.mjs} +2 -2
- package/dist/{popover-wiiwtqWE.mjs.map → popover-DhObSx97.mjs.map} +1 -1
- package/dist/popover.cjs.js +1 -1
- package/dist/popover.es.js +1 -1
- package/dist/purpur.css +1 -1
- package/dist/{quantity-selector-BEYMDsBM.js → quantity-selector-Ds7d4MnV.js} +2 -2
- package/dist/{quantity-selector-BEYMDsBM.js.map → quantity-selector-Ds7d4MnV.js.map} +1 -1
- package/dist/{quantity-selector-Cp-e5xKJ.mjs → quantity-selector-DwkKKmFy.mjs} +3 -3
- package/dist/{quantity-selector-Cp-e5xKJ.mjs.map → quantity-selector-DwkKKmFy.mjs.map} +1 -1
- package/dist/quantity-selector.cjs.js +1 -1
- package/dist/quantity-selector.es.js +1 -1
- package/dist/rich-text.cjs.js +1 -1
- package/dist/rich-text.es.js +1 -1
- package/dist/{search-field-afhtC6q5.mjs → search-field-BTqVE1-l.mjs} +3 -3
- package/dist/{search-field-afhtC6q5.mjs.map → search-field-BTqVE1-l.mjs.map} +1 -1
- package/dist/{search-field-WJBtiK0K.js → search-field-DkJrwzJB.js} +2 -2
- package/dist/{search-field-WJBtiK0K.js.map → search-field-DkJrwzJB.js.map} +1 -1
- package/dist/search-field.cjs.js +1 -1
- package/dist/search-field.es.js +1 -1
- package/dist/{stepper-VDiR2I8F.js → stepper-5rQ3cK18.js} +2 -2
- package/dist/{stepper-VDiR2I8F.js.map → stepper-5rQ3cK18.js.map} +1 -1
- package/dist/{stepper-20s8dnPA.mjs → stepper-B3p9r3gv.mjs} +3 -3
- package/dist/{stepper-20s8dnPA.mjs.map → stepper-B3p9r3gv.mjs.map} +1 -1
- package/dist/stepper.cjs.js +1 -1
- package/dist/stepper.es.js +1 -1
- package/dist/{table-B5ZitZoL.js → table-BIyaTsOh.js} +2 -2
- package/dist/{table-B5ZitZoL.js.map → table-BIyaTsOh.js.map} +1 -1
- package/dist/{table-CNIL-60s.mjs → table-BtymEUG4.mjs} +6 -6
- package/dist/{table-CNIL-60s.mjs.map → table-BtymEUG4.mjs.map} +1 -1
- package/dist/table.cjs.js +1 -1
- package/dist/table.es.js +1 -1
- package/dist/{text-field-D0e-cRbG.mjs → text-field-C9LX7LBf.mjs} +2 -2
- package/dist/{text-field-D0e-cRbG.mjs.map → text-field-C9LX7LBf.mjs.map} +1 -1
- package/dist/{text-field-VW8ObP83.js → text-field-CS0PT5T6.js} +2 -2
- package/dist/{text-field-VW8ObP83.js.map → text-field-CS0PT5T6.js.map} +1 -1
- package/dist/text-field.cjs.js +1 -1
- package/dist/text-field.es.js +1 -1
- package/dist/{tooltip-B-11qk-0.js → tooltip-COFCRUKv.js} +2 -2
- package/dist/{tooltip-B-11qk-0.js.map → tooltip-COFCRUKv.js.map} +1 -1
- package/dist/{tooltip-DngYHn5W.mjs → tooltip-FH9R2MAA.mjs} +2 -2
- package/dist/{tooltip-DngYHn5W.mjs.map → tooltip-FH9R2MAA.mjs.map} +1 -1
- package/dist/tooltip.cjs.js +1 -1
- package/dist/tooltip.es.js +1 -1
- package/package.json +24 -29
- package/scripts/generate.mts +1 -4
- package/src/aliases.ts +4 -0
- package/src/entries.js +1 -0
- package/src/library.ts +1 -1
- package/src/password-field.ts +0 -1
- package/dist/button-4-yWOgtD.mjs +0 -109
- package/dist/button-DmybVApa.js +0 -2
- package/dist/link-DY5WLpyc.mjs +0 -72
- package/dist/link-DhWVrkTz.js +0 -2
package/dist/carousel.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./carousel-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./carousel-Dz_bUGo4.js");exports.Carousel=e.Carousel;
|
|
2
2
|
//# sourceMappingURL=carousel.cjs.js.map
|
package/dist/carousel.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as J, jsx as o } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as Q, useRef as W, useState as X, useCallback as q, useEffect as T } from "react";
|
|
3
|
-
import { b as I } from "./button-
|
|
3
|
+
import { b as I } from "./button-EVRfctR8.mjs";
|
|
4
4
|
import { b as V } from "./icon.es-CZcKxTaM.mjs";
|
|
5
5
|
import { c as ee } from "./bind-CU-R61T-.mjs";
|
|
6
6
|
const te = {
|
|
@@ -146,4 +146,4 @@ ie.displayName = "ChatField";
|
|
|
146
146
|
export {
|
|
147
147
|
ie as C
|
|
148
148
|
};
|
|
149
|
-
//# sourceMappingURL=chat-field-
|
|
149
|
+
//# sourceMappingURL=chat-field-8cKqYcKi.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-field-CVF4DooY.mjs","sources":["../../../components/icon/dist/assets/send.es.js","../../../components/icon/dist/assets/tv-stop.es.js","../../../components/chat-field/src/chat-field.tsx"],"sourcesContent":["const e = {\n name: \"send\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M1.54 2.149a.9.9 0 0 1 .97-.131l19.514 9.212a.9.9 0 0 1 0 1.628L2.51 22.071A.9.9 0 0 1 1.263 21l2.664-8.957-2.664-8.956a.9.9 0 0 1 .277-.94Zm3.997 10.795-1.974 6.64 14.062-6.64H5.537Zm12.088-1.8H5.537L3.563 4.505l14.062 6.64Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"send\"],\n category: \"action\"\n};\nexport {\n e as send\n};\n//# sourceMappingURL=send.es.js.map\n","const t = {\n name: \"tv-stop\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19 19H5V5h14v14Z\"/><path fill-rule=\"evenodd\" d=\"M19.9 19a.9.9 0 0 1-.9.9H5a.9.9 0 0 1-.9-.9V5a.9.9 0 0 1 .9-.9h14a.9.9 0 0 1 .9.9v14Zm-1.8-.9V5.9H5.9v12.2h12.2Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"tv-stop\"],\n category: \"action\"\n};\nexport {\n t as tvStop\n};\n//# sourceMappingURL=tv-stop.es.js.map\n","import React, {\n type ChangeEvent,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type TextareaHTMLAttributes,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { Icon } from \"@purpur/icon\";\nimport { send } from \"@purpur/icon/assets/send\";\nimport { tvStop } from \"@purpur/icon/assets/tv-stop\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./chat-field.module.scss\";\nconst cx = c.bind(styles);\n\nconst mergeRefs = <T,>(...inputRefs: (Ref<T> | undefined)[]): Ref<T> | React.RefCallback<T> => {\n const filteredInputRefs = inputRefs.filter(Boolean);\n\n if (filteredInputRefs.length <= 1) {\n return filteredInputRefs[0] || null;\n }\n\n return (ref: T | null) => {\n for (const inputRef of filteredInputRefs) {\n if (typeof inputRef === \"function\") {\n inputRef(ref);\n } else if (inputRef) {\n (inputRef as React.RefObject<T | null>).current = ref;\n }\n }\n };\n};\n\nexport type ChatFieldProps = {\n [\"data-testid\"]?: string;\n /**\n * Current value of the textarea in controlled mode.\n * When omitted, the component handles textarea state internally.\n * */\n value?: string;\n /**\n * Placeholder text shown when the textarea is empty.\n * */\n placeholder: string;\n /**\n * Accessible label for the textarea when no aria-label/aria-labelledby\n * is provided via `textareaProps`.\n * */\n textareaAriaLabel?: string;\n /**\n * Changes the action icon from send to stop.\n * */\n generating?: boolean;\n /**\n * Renders the field with negative appearance.\n * */\n negative?: boolean;\n /**\n * Accessible label for the send action icon.\n * */\n sendAriaLabel: string;\n /**\n * Custom icon for the default action button state.\n * The custom icon should still visually communicate a send action.\n * Falls back to the standard send icon when omitted.\n * */\n sendIcon?: ReactNode;\n /**\n * Accessible label for the stop action icon.\n * */\n stopAriaLabel: string;\n /**\n * Number of visible text rows. Defaults to 1.\n * */\n rows?: number;\n /**\n * Maximum number of rows before the textarea scrolls. Defaults to 4.\n * */\n maxRows?: number;\n /**\n * Callback for textarea value changes.\n * */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /**\n * Callback fired when the send action is triggered (Enter key or send button click).\n * */\n onSend: () => void;\n /**\n * Callback fired when the stop button is clicked during generating state.\n * */\n onStopClick: () => void;\n /**\n * HTML type attribute for the action button. Use `\"submit\"` when ChatField\n * is placed inside a `<form>`. Defaults to `\"button\"`.\n * */\n actionButtonType?: \"button\" | \"submit\";\n /**\n * Additional props forwarded to the textarea element.\n * */\n textareaProps?: Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"value\" | \"placeholder\" | \"disabled\" | \"onChange\" | \"rows\"\n >;\n className?: string;\n};\n\nconst rootClassName = \"purpur-chat-field\";\n\nexport const ChatField = forwardRef<HTMLTextAreaElement, ChatFieldProps>(\n (\n {\n [\"data-testid\"]: dataTestId,\n value,\n placeholder,\n textareaAriaLabel: textareaAriaLabelProp,\n generating = false,\n negative = false,\n sendAriaLabel,\n sendIcon,\n stopAriaLabel,\n rows = 1,\n maxRows = 4,\n onChange,\n onSend,\n onStopClick,\n actionButtonType = \"button\",\n textareaProps,\n className,\n },\n ref\n ) => {\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const {\n [\"aria-label\"]: textareaPropsAriaLabel,\n [\"aria-labelledby\"]: textareaPropsAriaLabelledBy,\n defaultValue: textareaDefaultValue,\n ...textareaRestProps\n } = textareaProps ?? {};\n\n const [uncontrolledValue, setUncontrolledValue] = useState(() => {\n if (typeof textareaDefaultValue === \"string\" || typeof textareaDefaultValue === \"number\") {\n return String(textareaDefaultValue);\n }\n return \"\";\n });\n\n const textareaValue = value ?? uncontrolledValue;\n const hasValue = Boolean(textareaValue.length);\n\n const resolvedTextareaAriaLabel =\n textareaPropsAriaLabel ??\n (textareaPropsAriaLabelledBy ? undefined : textareaAriaLabelProp ?? placeholder);\n\n const adjustTextareaHeight = useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n textarea.style.height = \"auto\";\n textarea.style.overflowY = \"hidden\";\n\n const computed = getComputedStyle(textarea);\n const lineHeight = parseFloat(computed.lineHeight) || 20;\n const paddingTop = parseFloat(computed.paddingTop) || 0;\n const paddingBottom = parseFloat(computed.paddingBottom) || 0;\n const naturalHeight = lineHeight * rows + paddingTop + paddingBottom;\n const maxHeight = lineHeight * maxRows + paddingTop + paddingBottom;\n\n if (textarea.scrollHeight > maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else if (textarea.scrollHeight > naturalHeight) {\n textarea.style.height = `${textarea.scrollHeight}px`;\n }\n }, [rows, maxRows]);\n\n useEffect(() => {\n adjustTextareaHeight();\n }, [textareaValue, adjustTextareaHeight]);\n\n const triggerSend = useCallback(\n (source: \"button\" | \"keyboard\") => {\n if (!hasValue) return;\n\n if (actionButtonType === \"submit\") {\n const parentForm = internalRef.current?.form;\n\n if (source === \"keyboard\" && parentForm) {\n parentForm.requestSubmit();\n return;\n }\n\n if (source === \"button\" && parentForm) {\n return;\n }\n }\n\n onSend();\n },\n [actionButtonType, hasValue, onSend]\n );\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n\n onChange(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n triggerSend(\"keyboard\");\n }\n };\n\n const handleActionClick = () => {\n if (generating) {\n onStopClick();\n return;\n }\n\n triggerSend(\"button\");\n };\n\n const resolvedActionButtonType: \"button\" | \"submit\" =\n generating || !hasValue ? \"button\" : actionButtonType;\n\n const classes = cx([\n className,\n rootClassName,\n {\n [`${rootClassName}--filled`]: hasValue,\n [`${rootClassName}--negative`]: negative,\n },\n ]);\n\n const actionIcon = generating ? (\n <Icon size=\"xs\" svg={tvStop} />\n ) : (\n sendIcon ?? <Icon size=\"xs\" svg={send} />\n );\n\n return (\n <div className={classes} data-testid={dataTestId}>\n <textarea\n {...textareaRestProps}\n ref={mergeRefs(ref, internalRef)}\n className={cx(`${rootClassName}__textarea`, {\n [`${rootClassName}__textarea--negative`]: negative,\n })}\n aria-label={resolvedTextareaAriaLabel}\n aria-labelledby={textareaPropsAriaLabelledBy}\n data-testid={dataTestId ? `${dataTestId}-textarea` : undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={rows}\n value={textareaValue}\n />\n <div className={cx(`${rootClassName}__action`)}>\n <Button\n aria-label={generating ? stopAriaLabel : sendAriaLabel}\n data-testid={dataTestId ? `${dataTestId}-action` : undefined}\n iconOnly\n negative={negative}\n size=\"xs\"\n type={resolvedActionButtonType}\n variant=\"primary\"\n onClick={handleActionClick}\n >\n {actionIcon}\n </Button>\n </div>\n <span\n className={cx(`${rootClassName}__frame`, {\n [`${rootClassName}__frame--negative`]: negative,\n })}\n aria-hidden=\"true\"\n />\n </div>\n );\n }\n);\n\nChatField.displayName = \"ChatField\";\n"],"names":["e","t","cx","c","styles","mergeRefs","inputRefs","filteredInputRefs","ref","inputRef","rootClassName","ChatField","forwardRef","dataTestId","value","placeholder","textareaAriaLabelProp","generating","negative","sendAriaLabel","sendIcon","stopAriaLabel","rows","maxRows","onChange","onSend","onStopClick","actionButtonType","textareaProps","className","internalRef","useRef","textareaPropsAriaLabel","textareaPropsAriaLabelledBy","textareaDefaultValue","textareaRestProps","uncontrolledValue","setUncontrolledValue","useState","textareaValue","hasValue","resolvedTextareaAriaLabel","adjustTextareaHeight","useCallback","textarea","computed","lineHeight","paddingTop","paddingBottom","naturalHeight","maxHeight","useEffect","triggerSend","source","parentForm","handleChange","event","handleKeyDown","handleActionClick","resolvedActionButtonType","classes","actionIcon","jsx","Icon","tvStop","send","jsxs","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-field-8cKqYcKi.mjs","sources":["../../../components/icon/dist/assets/send.es.js","../../../components/icon/dist/assets/tv-stop.es.js","../../../components/chat-field/src/chat-field.tsx"],"sourcesContent":["const e = {\n name: \"send\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M1.54 2.149a.9.9 0 0 1 .97-.131l19.514 9.212a.9.9 0 0 1 0 1.628L2.51 22.071A.9.9 0 0 1 1.263 21l2.664-8.957-2.664-8.956a.9.9 0 0 1 .277-.94Zm3.997 10.795-1.974 6.64 14.062-6.64H5.537Zm12.088-1.8H5.537L3.563 4.505l14.062 6.64Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"send\"],\n category: \"action\"\n};\nexport {\n e as send\n};\n//# sourceMappingURL=send.es.js.map\n","const t = {\n name: \"tv-stop\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19 19H5V5h14v14Z\"/><path fill-rule=\"evenodd\" d=\"M19.9 19a.9.9 0 0 1-.9.9H5a.9.9 0 0 1-.9-.9V5a.9.9 0 0 1 .9-.9h14a.9.9 0 0 1 .9.9v14Zm-1.8-.9V5.9H5.9v12.2h12.2Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"tv-stop\"],\n category: \"action\"\n};\nexport {\n t as tvStop\n};\n//# sourceMappingURL=tv-stop.es.js.map\n","import React, {\n type ChangeEvent,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type TextareaHTMLAttributes,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { Icon } from \"@purpur/icon\";\nimport { send } from \"@purpur/icon/assets/send\";\nimport { tvStop } from \"@purpur/icon/assets/tv-stop\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./chat-field.module.scss\";\nconst cx = c.bind(styles);\n\nconst mergeRefs = <T,>(...inputRefs: (Ref<T> | undefined)[]): Ref<T> | React.RefCallback<T> => {\n const filteredInputRefs = inputRefs.filter(Boolean);\n\n if (filteredInputRefs.length <= 1) {\n return filteredInputRefs[0] || null;\n }\n\n return (ref: T | null) => {\n for (const inputRef of filteredInputRefs) {\n if (typeof inputRef === \"function\") {\n inputRef(ref);\n } else if (inputRef) {\n (inputRef as React.RefObject<T | null>).current = ref;\n }\n }\n };\n};\n\nexport type ChatFieldProps = {\n [\"data-testid\"]?: string;\n /**\n * Current value of the textarea in controlled mode.\n * When omitted, the component handles textarea state internally.\n * */\n value?: string;\n /**\n * Placeholder text shown when the textarea is empty.\n * */\n placeholder: string;\n /**\n * Accessible label for the textarea when no aria-label/aria-labelledby\n * is provided via `textareaProps`.\n * */\n textareaAriaLabel?: string;\n /**\n * Changes the action icon from send to stop.\n * */\n generating?: boolean;\n /**\n * Renders the field with negative appearance.\n * */\n negative?: boolean;\n /**\n * Accessible label for the send action icon.\n * */\n sendAriaLabel: string;\n /**\n * Custom icon for the default action button state.\n * The custom icon should still visually communicate a send action.\n * Falls back to the standard send icon when omitted.\n * */\n sendIcon?: ReactNode;\n /**\n * Accessible label for the stop action icon.\n * */\n stopAriaLabel: string;\n /**\n * Number of visible text rows. Defaults to 1.\n * */\n rows?: number;\n /**\n * Maximum number of rows before the textarea scrolls. Defaults to 4.\n * */\n maxRows?: number;\n /**\n * Callback for textarea value changes.\n * */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /**\n * Callback fired when the send action is triggered (Enter key or send button click).\n * */\n onSend: () => void;\n /**\n * Callback fired when the stop button is clicked during generating state.\n * */\n onStopClick: () => void;\n /**\n * HTML type attribute for the action button. Use `\"submit\"` when ChatField\n * is placed inside a `<form>`. Defaults to `\"button\"`.\n * */\n actionButtonType?: \"button\" | \"submit\";\n /**\n * Additional props forwarded to the textarea element.\n * */\n textareaProps?: Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"value\" | \"placeholder\" | \"disabled\" | \"onChange\" | \"rows\"\n >;\n className?: string;\n};\n\nconst rootClassName = \"purpur-chat-field\";\n\nexport const ChatField = forwardRef<HTMLTextAreaElement, ChatFieldProps>(\n (\n {\n [\"data-testid\"]: dataTestId,\n value,\n placeholder,\n textareaAriaLabel: textareaAriaLabelProp,\n generating = false,\n negative = false,\n sendAriaLabel,\n sendIcon,\n stopAriaLabel,\n rows = 1,\n maxRows = 4,\n onChange,\n onSend,\n onStopClick,\n actionButtonType = \"button\",\n textareaProps,\n className,\n },\n ref\n ) => {\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const {\n [\"aria-label\"]: textareaPropsAriaLabel,\n [\"aria-labelledby\"]: textareaPropsAriaLabelledBy,\n defaultValue: textareaDefaultValue,\n ...textareaRestProps\n } = textareaProps ?? {};\n\n const [uncontrolledValue, setUncontrolledValue] = useState(() => {\n if (typeof textareaDefaultValue === \"string\" || typeof textareaDefaultValue === \"number\") {\n return String(textareaDefaultValue);\n }\n return \"\";\n });\n\n const textareaValue = value ?? uncontrolledValue;\n const hasValue = Boolean(textareaValue.length);\n\n const resolvedTextareaAriaLabel =\n textareaPropsAriaLabel ??\n (textareaPropsAriaLabelledBy ? undefined : textareaAriaLabelProp ?? placeholder);\n\n const adjustTextareaHeight = useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n textarea.style.height = \"auto\";\n textarea.style.overflowY = \"hidden\";\n\n const computed = getComputedStyle(textarea);\n const lineHeight = parseFloat(computed.lineHeight) || 20;\n const paddingTop = parseFloat(computed.paddingTop) || 0;\n const paddingBottom = parseFloat(computed.paddingBottom) || 0;\n const naturalHeight = lineHeight * rows + paddingTop + paddingBottom;\n const maxHeight = lineHeight * maxRows + paddingTop + paddingBottom;\n\n if (textarea.scrollHeight > maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else if (textarea.scrollHeight > naturalHeight) {\n textarea.style.height = `${textarea.scrollHeight}px`;\n }\n }, [rows, maxRows]);\n\n useEffect(() => {\n adjustTextareaHeight();\n }, [textareaValue, adjustTextareaHeight]);\n\n const triggerSend = useCallback(\n (source: \"button\" | \"keyboard\") => {\n if (!hasValue) return;\n\n if (actionButtonType === \"submit\") {\n const parentForm = internalRef.current?.form;\n\n if (source === \"keyboard\" && parentForm) {\n parentForm.requestSubmit();\n return;\n }\n\n if (source === \"button\" && parentForm) {\n return;\n }\n }\n\n onSend();\n },\n [actionButtonType, hasValue, onSend]\n );\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n\n onChange(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n triggerSend(\"keyboard\");\n }\n };\n\n const handleActionClick = () => {\n if (generating) {\n onStopClick();\n return;\n }\n\n triggerSend(\"button\");\n };\n\n const resolvedActionButtonType: \"button\" | \"submit\" =\n generating || !hasValue ? \"button\" : actionButtonType;\n\n const classes = cx([\n className,\n rootClassName,\n {\n [`${rootClassName}--filled`]: hasValue,\n [`${rootClassName}--negative`]: negative,\n },\n ]);\n\n const actionIcon = generating ? (\n <Icon size=\"xs\" svg={tvStop} />\n ) : (\n sendIcon ?? <Icon size=\"xs\" svg={send} />\n );\n\n return (\n <div className={classes} data-testid={dataTestId}>\n <textarea\n {...textareaRestProps}\n ref={mergeRefs(ref, internalRef)}\n className={cx(`${rootClassName}__textarea`, {\n [`${rootClassName}__textarea--negative`]: negative,\n })}\n aria-label={resolvedTextareaAriaLabel}\n aria-labelledby={textareaPropsAriaLabelledBy}\n data-testid={dataTestId ? `${dataTestId}-textarea` : undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={rows}\n value={textareaValue}\n />\n <div className={cx(`${rootClassName}__action`)}>\n <Button\n aria-label={generating ? stopAriaLabel : sendAriaLabel}\n data-testid={dataTestId ? `${dataTestId}-action` : undefined}\n iconOnly\n negative={negative}\n size=\"xs\"\n type={resolvedActionButtonType}\n variant=\"primary\"\n onClick={handleActionClick}\n >\n {actionIcon}\n </Button>\n </div>\n <span\n className={cx(`${rootClassName}__frame`, {\n [`${rootClassName}__frame--negative`]: negative,\n })}\n aria-hidden=\"true\"\n />\n </div>\n );\n }\n);\n\nChatField.displayName = \"ChatField\";\n"],"names":["e","t","cx","c","styles","mergeRefs","inputRefs","filteredInputRefs","ref","inputRef","rootClassName","ChatField","forwardRef","dataTestId","value","placeholder","textareaAriaLabelProp","generating","negative","sendAriaLabel","sendIcon","stopAriaLabel","rows","maxRows","onChange","onSend","onStopClick","actionButtonType","textareaProps","className","internalRef","useRef","textareaPropsAriaLabel","textareaPropsAriaLabelledBy","textareaDefaultValue","textareaRestProps","uncontrolledValue","setUncontrolledValue","useState","textareaValue","hasValue","resolvedTextareaAriaLabel","adjustTextareaHeight","useCallback","textarea","computed","lineHeight","paddingTop","paddingBottom","naturalHeight","maxHeight","useEffect","triggerSend","source","parentForm","handleChange","event","handleKeyDown","handleActionClick","resolvedActionButtonType","classes","actionIcon","jsx","Icon","tvStop","send","jsxs","Button"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const l=require("react/jsx-runtime"),s=require("react"),Q=require("./button-
|
|
2
|
-
//# sourceMappingURL=chat-field-
|
|
1
|
+
"use strict";const l=require("react/jsx-runtime"),s=require("react"),Q=require("./button-DZgtrGqN.js"),j=require("./icon.es-j3eRib6d.js"),W=require("./bind-DeUYJ6m9.js"),X={name:"send",svg:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M1.54 2.149a.9.9 0 0 1 .97-.131l19.514 9.212a.9.9 0 0 1 0 1.628L2.51 22.071A.9.9 0 0 1 1.263 21l2.664-8.957-2.664-8.956a.9.9 0 0 1 .277-.94Zm3.997 10.795-1.974 6.64 14.062-6.64H5.537Zm12.088-1.8H5.537L3.563 4.505l14.062 6.64Z" clip-rule="evenodd"/></svg>',keywords:["send"],category:"action"},T={name:"tv-stop",svg:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19 19H5V5h14v14Z"/><path fill-rule="evenodd" d="M19.9 19a.9.9 0 0 1-.9.9H5a.9.9 0 0 1-.9-.9V5a.9.9 0 0 1 .9-.9h14a.9.9 0 0 1 .9.9v14Zm-1.8-.9V5.9H5.9v12.2h12.2Z" clip-rule="evenodd"/></svg>',keywords:["tv-stop"],category:"action"},I={"purpur-chat-field":"_purpur-chat-field_16tq2_1","purpur-chat-field--negative":"_purpur-chat-field--negative_16tq2_13","purpur-chat-field__frame":"_purpur-chat-field__frame_16tq2_16","purpur-chat-field__frame--negative":"_purpur-chat-field__frame--negative_16tq2_20","purpur-chat-field--filled":"_purpur-chat-field--filled_16tq2_34","purpur-chat-field__textarea":"_purpur-chat-field__textarea_16tq2_34","purpur-chat-field__textarea--negative":"_purpur-chat-field__textarea--negative_16tq2_37","purpur-chat-field__action":"_purpur-chat-field__action_16tq2_80"},f=W.c.bind(I),ee=(...a)=>{const i=a.filter(Boolean);return i.length<=1?i[0]||null:o=>{for(const n of i)typeof n=="function"?n(o):n&&(n.current=o)}},t="purpur-chat-field",k=s.forwardRef(({["data-testid"]:a,value:i,placeholder:o,textareaAriaLabel:n,generating:u=!1,negative:c=!1,sendAriaLabel:V,sendIcon:R,stopAriaLabel:A,rows:p=1,maxRows:x=4,onChange:B,onSend:m,onStopClick:F,actionButtonType:h="button",textareaProps:L,className:N},Z)=>{const _=s.useRef(null),{["aria-label"]:D,["aria-labelledby"]:b,defaultValue:g,...S}=L??{},[z,E]=s.useState(()=>typeof g=="string"||typeof g=="number"?String(g):""),v=i??z,d=!!v.length,K=D??(b?void 0:n??o),y=s.useCallback(()=>{const e=_.current;if(!e)return;e.style.height="auto",e.style.overflowY="hidden";const r=getComputedStyle(e),w=parseFloat(r.lineHeight)||20,C=parseFloat(r.paddingTop)||0,H=parseFloat(r.paddingBottom)||0,J=w*p+C+H,$=w*x+C+H;e.scrollHeight>$?(e.style.height=`${$}px`,e.style.overflowY="auto"):e.scrollHeight>J&&(e.style.height=`${e.scrollHeight}px`)},[p,x]);s.useEffect(()=>{y()},[v,y]);const q=s.useCallback(e=>{if(d){if(h==="submit"){const r=_.current?.form;if(e==="keyboard"&&r){r.requestSubmit();return}if(e==="button"&&r)return}m()}},[h,d,m]),M=e=>{i===void 0&&E(e.target.value),B(e)},P=e=>{e.key==="Enter"&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),q("keyboard"))},Y=()=>{if(u){F();return}q("button")},O=u||!d?"button":h,U=f([N,t,{[`${t}--filled`]:d,[`${t}--negative`]:c}]),G=u?l.jsx(j.b,{size:"xs",svg:T}):R??l.jsx(j.b,{size:"xs",svg:X});return l.jsxs("div",{className:U,"data-testid":a,children:[l.jsx("textarea",{...S,ref:ee(Z,_),className:f(`${t}__textarea`,{[`${t}__textarea--negative`]:c}),"aria-label":K,"aria-labelledby":b,"data-testid":a?`${a}-textarea`:void 0,onChange:M,onKeyDown:P,placeholder:o,rows:p,value:v}),l.jsx("div",{className:f(`${t}__action`),children:l.jsx(Q.Button,{"aria-label":u?A:V,"data-testid":a?`${a}-action`:void 0,iconOnly:!0,negative:c,size:"xs",type:O,variant:"primary",onClick:Y,children:G})}),l.jsx("span",{className:f(`${t}__frame`,{[`${t}__frame--negative`]:c}),"aria-hidden":"true"})]})});k.displayName="ChatField";exports.ChatField=k;
|
|
2
|
+
//# sourceMappingURL=chat-field-B2jmpVNr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-field-Wjvh2J6C.js","sources":["../../../components/icon/dist/assets/send.es.js","../../../components/icon/dist/assets/tv-stop.es.js","../../../components/chat-field/src/chat-field.tsx"],"sourcesContent":["const e = {\n name: \"send\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M1.54 2.149a.9.9 0 0 1 .97-.131l19.514 9.212a.9.9 0 0 1 0 1.628L2.51 22.071A.9.9 0 0 1 1.263 21l2.664-8.957-2.664-8.956a.9.9 0 0 1 .277-.94Zm3.997 10.795-1.974 6.64 14.062-6.64H5.537Zm12.088-1.8H5.537L3.563 4.505l14.062 6.64Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"send\"],\n category: \"action\"\n};\nexport {\n e as send\n};\n//# sourceMappingURL=send.es.js.map\n","const t = {\n name: \"tv-stop\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19 19H5V5h14v14Z\"/><path fill-rule=\"evenodd\" d=\"M19.9 19a.9.9 0 0 1-.9.9H5a.9.9 0 0 1-.9-.9V5a.9.9 0 0 1 .9-.9h14a.9.9 0 0 1 .9.9v14Zm-1.8-.9V5.9H5.9v12.2h12.2Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"tv-stop\"],\n category: \"action\"\n};\nexport {\n t as tvStop\n};\n//# sourceMappingURL=tv-stop.es.js.map\n","import React, {\n type ChangeEvent,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type TextareaHTMLAttributes,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { Icon } from \"@purpur/icon\";\nimport { send } from \"@purpur/icon/assets/send\";\nimport { tvStop } from \"@purpur/icon/assets/tv-stop\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./chat-field.module.scss\";\nconst cx = c.bind(styles);\n\nconst mergeRefs = <T,>(...inputRefs: (Ref<T> | undefined)[]): Ref<T> | React.RefCallback<T> => {\n const filteredInputRefs = inputRefs.filter(Boolean);\n\n if (filteredInputRefs.length <= 1) {\n return filteredInputRefs[0] || null;\n }\n\n return (ref: T | null) => {\n for (const inputRef of filteredInputRefs) {\n if (typeof inputRef === \"function\") {\n inputRef(ref);\n } else if (inputRef) {\n (inputRef as React.RefObject<T | null>).current = ref;\n }\n }\n };\n};\n\nexport type ChatFieldProps = {\n [\"data-testid\"]?: string;\n /**\n * Current value of the textarea in controlled mode.\n * When omitted, the component handles textarea state internally.\n * */\n value?: string;\n /**\n * Placeholder text shown when the textarea is empty.\n * */\n placeholder: string;\n /**\n * Accessible label for the textarea when no aria-label/aria-labelledby\n * is provided via `textareaProps`.\n * */\n textareaAriaLabel?: string;\n /**\n * Changes the action icon from send to stop.\n * */\n generating?: boolean;\n /**\n * Renders the field with negative appearance.\n * */\n negative?: boolean;\n /**\n * Accessible label for the send action icon.\n * */\n sendAriaLabel: string;\n /**\n * Custom icon for the default action button state.\n * The custom icon should still visually communicate a send action.\n * Falls back to the standard send icon when omitted.\n * */\n sendIcon?: ReactNode;\n /**\n * Accessible label for the stop action icon.\n * */\n stopAriaLabel: string;\n /**\n * Number of visible text rows. Defaults to 1.\n * */\n rows?: number;\n /**\n * Maximum number of rows before the textarea scrolls. Defaults to 4.\n * */\n maxRows?: number;\n /**\n * Callback for textarea value changes.\n * */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /**\n * Callback fired when the send action is triggered (Enter key or send button click).\n * */\n onSend: () => void;\n /**\n * Callback fired when the stop button is clicked during generating state.\n * */\n onStopClick: () => void;\n /**\n * HTML type attribute for the action button. Use `\"submit\"` when ChatField\n * is placed inside a `<form>`. Defaults to `\"button\"`.\n * */\n actionButtonType?: \"button\" | \"submit\";\n /**\n * Additional props forwarded to the textarea element.\n * */\n textareaProps?: Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"value\" | \"placeholder\" | \"disabled\" | \"onChange\" | \"rows\"\n >;\n className?: string;\n};\n\nconst rootClassName = \"purpur-chat-field\";\n\nexport const ChatField = forwardRef<HTMLTextAreaElement, ChatFieldProps>(\n (\n {\n [\"data-testid\"]: dataTestId,\n value,\n placeholder,\n textareaAriaLabel: textareaAriaLabelProp,\n generating = false,\n negative = false,\n sendAriaLabel,\n sendIcon,\n stopAriaLabel,\n rows = 1,\n maxRows = 4,\n onChange,\n onSend,\n onStopClick,\n actionButtonType = \"button\",\n textareaProps,\n className,\n },\n ref\n ) => {\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const {\n [\"aria-label\"]: textareaPropsAriaLabel,\n [\"aria-labelledby\"]: textareaPropsAriaLabelledBy,\n defaultValue: textareaDefaultValue,\n ...textareaRestProps\n } = textareaProps ?? {};\n\n const [uncontrolledValue, setUncontrolledValue] = useState(() => {\n if (typeof textareaDefaultValue === \"string\" || typeof textareaDefaultValue === \"number\") {\n return String(textareaDefaultValue);\n }\n return \"\";\n });\n\n const textareaValue = value ?? uncontrolledValue;\n const hasValue = Boolean(textareaValue.length);\n\n const resolvedTextareaAriaLabel =\n textareaPropsAriaLabel ??\n (textareaPropsAriaLabelledBy ? undefined : textareaAriaLabelProp ?? placeholder);\n\n const adjustTextareaHeight = useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n textarea.style.height = \"auto\";\n textarea.style.overflowY = \"hidden\";\n\n const computed = getComputedStyle(textarea);\n const lineHeight = parseFloat(computed.lineHeight) || 20;\n const paddingTop = parseFloat(computed.paddingTop) || 0;\n const paddingBottom = parseFloat(computed.paddingBottom) || 0;\n const naturalHeight = lineHeight * rows + paddingTop + paddingBottom;\n const maxHeight = lineHeight * maxRows + paddingTop + paddingBottom;\n\n if (textarea.scrollHeight > maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else if (textarea.scrollHeight > naturalHeight) {\n textarea.style.height = `${textarea.scrollHeight}px`;\n }\n }, [rows, maxRows]);\n\n useEffect(() => {\n adjustTextareaHeight();\n }, [textareaValue, adjustTextareaHeight]);\n\n const triggerSend = useCallback(\n (source: \"button\" | \"keyboard\") => {\n if (!hasValue) return;\n\n if (actionButtonType === \"submit\") {\n const parentForm = internalRef.current?.form;\n\n if (source === \"keyboard\" && parentForm) {\n parentForm.requestSubmit();\n return;\n }\n\n if (source === \"button\" && parentForm) {\n return;\n }\n }\n\n onSend();\n },\n [actionButtonType, hasValue, onSend]\n );\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n\n onChange(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n triggerSend(\"keyboard\");\n }\n };\n\n const handleActionClick = () => {\n if (generating) {\n onStopClick();\n return;\n }\n\n triggerSend(\"button\");\n };\n\n const resolvedActionButtonType: \"button\" | \"submit\" =\n generating || !hasValue ? \"button\" : actionButtonType;\n\n const classes = cx([\n className,\n rootClassName,\n {\n [`${rootClassName}--filled`]: hasValue,\n [`${rootClassName}--negative`]: negative,\n },\n ]);\n\n const actionIcon = generating ? (\n <Icon size=\"xs\" svg={tvStop} />\n ) : (\n sendIcon ?? <Icon size=\"xs\" svg={send} />\n );\n\n return (\n <div className={classes} data-testid={dataTestId}>\n <textarea\n {...textareaRestProps}\n ref={mergeRefs(ref, internalRef)}\n className={cx(`${rootClassName}__textarea`, {\n [`${rootClassName}__textarea--negative`]: negative,\n })}\n aria-label={resolvedTextareaAriaLabel}\n aria-labelledby={textareaPropsAriaLabelledBy}\n data-testid={dataTestId ? `${dataTestId}-textarea` : undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={rows}\n value={textareaValue}\n />\n <div className={cx(`${rootClassName}__action`)}>\n <Button\n aria-label={generating ? stopAriaLabel : sendAriaLabel}\n data-testid={dataTestId ? `${dataTestId}-action` : undefined}\n iconOnly\n negative={negative}\n size=\"xs\"\n type={resolvedActionButtonType}\n variant=\"primary\"\n onClick={handleActionClick}\n >\n {actionIcon}\n </Button>\n </div>\n <span\n className={cx(`${rootClassName}__frame`, {\n [`${rootClassName}__frame--negative`]: negative,\n })}\n aria-hidden=\"true\"\n />\n </div>\n );\n }\n);\n\nChatField.displayName = \"ChatField\";\n"],"names":["e","t","cx","c","styles","mergeRefs","inputRefs","filteredInputRefs","ref","inputRef","rootClassName","ChatField","forwardRef","dataTestId","value","placeholder","textareaAriaLabelProp","generating","negative","sendAriaLabel","sendIcon","stopAriaLabel","rows","maxRows","onChange","onSend","onStopClick","actionButtonType","textareaProps","className","internalRef","useRef","textareaPropsAriaLabel","textareaPropsAriaLabelledBy","textareaDefaultValue","textareaRestProps","uncontrolledValue","setUncontrolledValue","useState","textareaValue","hasValue","resolvedTextareaAriaLabel","adjustTextareaHeight","useCallback","textarea","computed","lineHeight","paddingTop","paddingBottom","naturalHeight","maxHeight","useEffect","triggerSend","source","parentForm","handleChange","event","handleKeyDown","handleActionClick","resolvedActionButtonType","classes","actionIcon","jsx","Icon","tvStop","send","jsxs","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-field-B2jmpVNr.js","sources":["../../../components/icon/dist/assets/send.es.js","../../../components/icon/dist/assets/tv-stop.es.js","../../../components/chat-field/src/chat-field.tsx"],"sourcesContent":["const e = {\n name: \"send\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M1.54 2.149a.9.9 0 0 1 .97-.131l19.514 9.212a.9.9 0 0 1 0 1.628L2.51 22.071A.9.9 0 0 1 1.263 21l2.664-8.957-2.664-8.956a.9.9 0 0 1 .277-.94Zm3.997 10.795-1.974 6.64 14.062-6.64H5.537Zm12.088-1.8H5.537L3.563 4.505l14.062 6.64Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"send\"],\n category: \"action\"\n};\nexport {\n e as send\n};\n//# sourceMappingURL=send.es.js.map\n","const t = {\n name: \"tv-stop\",\n svg: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19 19H5V5h14v14Z\"/><path fill-rule=\"evenodd\" d=\"M19.9 19a.9.9 0 0 1-.9.9H5a.9.9 0 0 1-.9-.9V5a.9.9 0 0 1 .9-.9h14a.9.9 0 0 1 .9.9v14Zm-1.8-.9V5.9H5.9v12.2h12.2Z\" clip-rule=\"evenodd\"/></svg>',\n keywords: [\"tv-stop\"],\n category: \"action\"\n};\nexport {\n t as tvStop\n};\n//# sourceMappingURL=tv-stop.es.js.map\n","import React, {\n type ChangeEvent,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type TextareaHTMLAttributes,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { Icon } from \"@purpur/icon\";\nimport { send } from \"@purpur/icon/assets/send\";\nimport { tvStop } from \"@purpur/icon/assets/tv-stop\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./chat-field.module.scss\";\nconst cx = c.bind(styles);\n\nconst mergeRefs = <T,>(...inputRefs: (Ref<T> | undefined)[]): Ref<T> | React.RefCallback<T> => {\n const filteredInputRefs = inputRefs.filter(Boolean);\n\n if (filteredInputRefs.length <= 1) {\n return filteredInputRefs[0] || null;\n }\n\n return (ref: T | null) => {\n for (const inputRef of filteredInputRefs) {\n if (typeof inputRef === \"function\") {\n inputRef(ref);\n } else if (inputRef) {\n (inputRef as React.RefObject<T | null>).current = ref;\n }\n }\n };\n};\n\nexport type ChatFieldProps = {\n [\"data-testid\"]?: string;\n /**\n * Current value of the textarea in controlled mode.\n * When omitted, the component handles textarea state internally.\n * */\n value?: string;\n /**\n * Placeholder text shown when the textarea is empty.\n * */\n placeholder: string;\n /**\n * Accessible label for the textarea when no aria-label/aria-labelledby\n * is provided via `textareaProps`.\n * */\n textareaAriaLabel?: string;\n /**\n * Changes the action icon from send to stop.\n * */\n generating?: boolean;\n /**\n * Renders the field with negative appearance.\n * */\n negative?: boolean;\n /**\n * Accessible label for the send action icon.\n * */\n sendAriaLabel: string;\n /**\n * Custom icon for the default action button state.\n * The custom icon should still visually communicate a send action.\n * Falls back to the standard send icon when omitted.\n * */\n sendIcon?: ReactNode;\n /**\n * Accessible label for the stop action icon.\n * */\n stopAriaLabel: string;\n /**\n * Number of visible text rows. Defaults to 1.\n * */\n rows?: number;\n /**\n * Maximum number of rows before the textarea scrolls. Defaults to 4.\n * */\n maxRows?: number;\n /**\n * Callback for textarea value changes.\n * */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /**\n * Callback fired when the send action is triggered (Enter key or send button click).\n * */\n onSend: () => void;\n /**\n * Callback fired when the stop button is clicked during generating state.\n * */\n onStopClick: () => void;\n /**\n * HTML type attribute for the action button. Use `\"submit\"` when ChatField\n * is placed inside a `<form>`. Defaults to `\"button\"`.\n * */\n actionButtonType?: \"button\" | \"submit\";\n /**\n * Additional props forwarded to the textarea element.\n * */\n textareaProps?: Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"value\" | \"placeholder\" | \"disabled\" | \"onChange\" | \"rows\"\n >;\n className?: string;\n};\n\nconst rootClassName = \"purpur-chat-field\";\n\nexport const ChatField = forwardRef<HTMLTextAreaElement, ChatFieldProps>(\n (\n {\n [\"data-testid\"]: dataTestId,\n value,\n placeholder,\n textareaAriaLabel: textareaAriaLabelProp,\n generating = false,\n negative = false,\n sendAriaLabel,\n sendIcon,\n stopAriaLabel,\n rows = 1,\n maxRows = 4,\n onChange,\n onSend,\n onStopClick,\n actionButtonType = \"button\",\n textareaProps,\n className,\n },\n ref\n ) => {\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const {\n [\"aria-label\"]: textareaPropsAriaLabel,\n [\"aria-labelledby\"]: textareaPropsAriaLabelledBy,\n defaultValue: textareaDefaultValue,\n ...textareaRestProps\n } = textareaProps ?? {};\n\n const [uncontrolledValue, setUncontrolledValue] = useState(() => {\n if (typeof textareaDefaultValue === \"string\" || typeof textareaDefaultValue === \"number\") {\n return String(textareaDefaultValue);\n }\n return \"\";\n });\n\n const textareaValue = value ?? uncontrolledValue;\n const hasValue = Boolean(textareaValue.length);\n\n const resolvedTextareaAriaLabel =\n textareaPropsAriaLabel ??\n (textareaPropsAriaLabelledBy ? undefined : textareaAriaLabelProp ?? placeholder);\n\n const adjustTextareaHeight = useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n textarea.style.height = \"auto\";\n textarea.style.overflowY = \"hidden\";\n\n const computed = getComputedStyle(textarea);\n const lineHeight = parseFloat(computed.lineHeight) || 20;\n const paddingTop = parseFloat(computed.paddingTop) || 0;\n const paddingBottom = parseFloat(computed.paddingBottom) || 0;\n const naturalHeight = lineHeight * rows + paddingTop + paddingBottom;\n const maxHeight = lineHeight * maxRows + paddingTop + paddingBottom;\n\n if (textarea.scrollHeight > maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else if (textarea.scrollHeight > naturalHeight) {\n textarea.style.height = `${textarea.scrollHeight}px`;\n }\n }, [rows, maxRows]);\n\n useEffect(() => {\n adjustTextareaHeight();\n }, [textareaValue, adjustTextareaHeight]);\n\n const triggerSend = useCallback(\n (source: \"button\" | \"keyboard\") => {\n if (!hasValue) return;\n\n if (actionButtonType === \"submit\") {\n const parentForm = internalRef.current?.form;\n\n if (source === \"keyboard\" && parentForm) {\n parentForm.requestSubmit();\n return;\n }\n\n if (source === \"button\" && parentForm) {\n return;\n }\n }\n\n onSend();\n },\n [actionButtonType, hasValue, onSend]\n );\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n\n onChange(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n triggerSend(\"keyboard\");\n }\n };\n\n const handleActionClick = () => {\n if (generating) {\n onStopClick();\n return;\n }\n\n triggerSend(\"button\");\n };\n\n const resolvedActionButtonType: \"button\" | \"submit\" =\n generating || !hasValue ? \"button\" : actionButtonType;\n\n const classes = cx([\n className,\n rootClassName,\n {\n [`${rootClassName}--filled`]: hasValue,\n [`${rootClassName}--negative`]: negative,\n },\n ]);\n\n const actionIcon = generating ? (\n <Icon size=\"xs\" svg={tvStop} />\n ) : (\n sendIcon ?? <Icon size=\"xs\" svg={send} />\n );\n\n return (\n <div className={classes} data-testid={dataTestId}>\n <textarea\n {...textareaRestProps}\n ref={mergeRefs(ref, internalRef)}\n className={cx(`${rootClassName}__textarea`, {\n [`${rootClassName}__textarea--negative`]: negative,\n })}\n aria-label={resolvedTextareaAriaLabel}\n aria-labelledby={textareaPropsAriaLabelledBy}\n data-testid={dataTestId ? `${dataTestId}-textarea` : undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={rows}\n value={textareaValue}\n />\n <div className={cx(`${rootClassName}__action`)}>\n <Button\n aria-label={generating ? stopAriaLabel : sendAriaLabel}\n data-testid={dataTestId ? `${dataTestId}-action` : undefined}\n iconOnly\n negative={negative}\n size=\"xs\"\n type={resolvedActionButtonType}\n variant=\"primary\"\n onClick={handleActionClick}\n >\n {actionIcon}\n </Button>\n </div>\n <span\n className={cx(`${rootClassName}__frame`, {\n [`${rootClassName}__frame--negative`]: negative,\n })}\n aria-hidden=\"true\"\n />\n </div>\n );\n }\n);\n\nChatField.displayName = \"ChatField\";\n"],"names":["e","t","cx","c","styles","mergeRefs","inputRefs","filteredInputRefs","ref","inputRef","rootClassName","ChatField","forwardRef","dataTestId","value","placeholder","textareaAriaLabelProp","generating","negative","sendAriaLabel","sendIcon","stopAriaLabel","rows","maxRows","onChange","onSend","onStopClick","actionButtonType","textareaProps","className","internalRef","useRef","textareaPropsAriaLabel","textareaPropsAriaLabelledBy","textareaDefaultValue","textareaRestProps","uncontrolledValue","setUncontrolledValue","useState","textareaValue","hasValue","resolvedTextareaAriaLabel","adjustTextareaHeight","useCallback","textarea","computed","lineHeight","paddingTop","paddingBottom","naturalHeight","maxHeight","useEffect","triggerSend","source","parentForm","handleChange","event","handleKeyDown","handleActionClick","resolvedActionButtonType","classes","actionIcon","jsx","Icon","tvStop","send","jsxs","Button"],"mappings":"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"}
|
package/dist/chat-field.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chat-field-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chat-field-B2jmpVNr.js");exports.ChatField=e.ChatField;
|
|
2
2
|
//# sourceMappingURL=chat-field.cjs.js.map
|
package/dist/chat-field.es.js
CHANGED
|
@@ -6,7 +6,7 @@ import { e as U } from "./minus.es-BK9qA9iJ.mjs";
|
|
|
6
6
|
import { l as F } from "./chevron-down.es-PCIIj6oG.mjs";
|
|
7
7
|
import { P as q } from "./paragraph-CwAdFoIm.mjs";
|
|
8
8
|
import { a as X } from "./badge-DalD-yqG.mjs";
|
|
9
|
-
import { b as P } from "./button-
|
|
9
|
+
import { b as P } from "./button-EVRfctR8.mjs";
|
|
10
10
|
import { H as Y } from "./heading-xwBuT_-9.mjs";
|
|
11
11
|
import { l as Z } from "./arrow-left.es-DU-PX-Il.mjs";
|
|
12
12
|
import { i as rr } from "./arrow-right.es-C7SkjAB6.mjs";
|
|
@@ -290,4 +290,4 @@ _r.displayName = "ComparisonTable";
|
|
|
290
290
|
export {
|
|
291
291
|
_r as C
|
|
292
292
|
};
|
|
293
|
-
//# sourceMappingURL=comparison-table-
|
|
293
|
+
//# sourceMappingURL=comparison-table-CmtSOUfK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparison-table-D1evE0ri.mjs","sources":["../../../components/comparison-table/src/components/Cell/cell.tsx","../../../components/comparison-table/src/components/LeadCell/lead-cell.tsx","../../../components/comparison-table/src/components/OptionCard/option-card.tsx","../../../components/comparison-table/src/components/ScrollProgress/scroll-progress.tsx","../../../components/comparison-table/src/comparison-table.tsx"],"sourcesContent":["import React, { isValidElement, type ReactNode } from \"react\";\nimport { IconCheckmark } from \"@purpur/icon/checkmark\";\nimport { IconMinus } from \"@purpur/icon/minus\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./cell.module.scss\";\n\ntype CellProps = {\n value: boolean | ReactNode;\n};\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-cell\";\n\nexport const Cell = ({ value }: CellProps) => {\n const isReactNode = isValidElement(value) || [\"string\", \"number\"].includes(typeof value);\n\n const getClassName = () => {\n if (isReactNode) return \"\";\n return `${rootClassName}--${value ? \"check\" : \"minus\"}`;\n };\n\n const classes = cx(rootClassName, [getClassName()]);\n\n const Icon = value ? IconCheckmark : IconMinus;\n\n return (\n <span className={cx(classes)}>\n {isReactNode ? value : <Icon size=\"xs\" className={cx(`${rootClassName}__icon`)} />}\n </span>\n );\n};\n","import React, { type ReactNode } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Paragraph } from \"@purpur/paragraph\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./lead-cell.module.scss\";\n\ntype LeadCellProps = {\n title: string;\n description?: ReactNode;\n};\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-lead-cell\";\n\nexport const LeadCell = ({ title, description }: LeadCellProps) => {\n const isExpandable = typeof description === \"string\";\n const classes = cx(rootClassName);\n\n return (\n <details className={classes} data-is-expandable={isExpandable}>\n <summary className={cx(`${rootClassName}__summary`)} tabIndex={isExpandable ? 0 : -1}>\n <Paragraph className={cx(`${rootClassName}__summary-title`)} variant=\"paragraph-100-bold\">\n {title}\n </Paragraph>\n <IconChevronDown className={cx(`${rootClassName}__summary-icon`)} size=\"sm\" />\n </summary>\n {description && (\n <Paragraph variant=\"paragraph-100\" className={cx(`${rootClassName}__description`)}>\n {description}\n </Paragraph>\n )}\n </details>\n );\n};\n","import React, { type ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { Badge, type BadgeProps } from \"@purpur/badge\";\nimport { Button } from \"@purpur/button\";\nimport { Heading } from \"@purpur/heading\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Paragraph } from \"@purpur/paragraph\";\nimport c from \"classnames/bind\";\n\nimport { type ComparisonTableProps } from \"../../comparison-table\";\nimport styles from \"./option-card.module.scss\";\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-option-card\";\n\nexport type OptionCardProps = {\n image: {\n src: string;\n alt: string;\n };\n\n title: string;\n description: ReactNode;\n variablePriceText: string;\n price: string;\n\n actions: ReactNode;\n\n badge?: BadgeProps;\n isHighlighted?: boolean;\n};\n\ntype OptionCardPropsAdditions = {\n id: string;\n cardIndex: number;\n isFirstCard: boolean;\n ariaLabels: ComparisonTableProps[\"ariaLabels\"];\n\n showFullDescriptions: boolean;\n toggleShowFullDescriptions: () => void;\n};\n\nexport const OptionCard = ({\n id,\n cardIndex,\n description,\n variablePriceText,\n price,\n isHighlighted,\n ariaLabels,\n badge,\n actions,\n isFirstCard,\n image,\n title,\n showFullDescriptions,\n toggleShowFullDescriptions,\n}: OptionCardProps & OptionCardPropsAdditions) => {\n const descriptionRef = useRef<HTMLDivElement | HTMLParagraphElement>(null);\n const descriptionContentRef = useRef<HTMLDivElement | null>(null);\n const showFullDescriptionsRef = useRef(showFullDescriptions);\n const [descriptionOverflows, setDescriptionOverflows] = useState(false);\n\n const classes = cx(rootClassName, {\n [`${rootClassName}--highlighted`]: isHighlighted,\n [`${rootClassName}--first-card`]: isFirstCard,\n [`${rootClassName}--show-full-descriptions`]: showFullDescriptions,\n });\n\n useEffect(() => {\n showFullDescriptionsRef.current = showFullDescriptions;\n }, [showFullDescriptions]);\n\n const checkDescriptionOverflow = useCallback(() => {\n if (showFullDescriptionsRef.current) {\n return;\n }\n\n const description = descriptionRef.current;\n const descriptionContent = descriptionContentRef.current;\n\n if (!description || !descriptionContent) {\n setDescriptionOverflows(false);\n return;\n }\n\n const descriptionHeight = description.clientHeight;\n const contentHeight = descriptionContent.offsetHeight;\n\n setDescriptionOverflows(contentHeight > descriptionHeight + 1);\n }, []);\n\n useEffect(() => {\n const descriptionElement = descriptionRef.current;\n\n checkDescriptionOverflow();\n\n if (!descriptionElement || typeof ResizeObserver === \"undefined\") {\n return undefined;\n }\n\n const resizeObserver = new ResizeObserver(checkDescriptionOverflow);\n resizeObserver.observe(descriptionElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [checkDescriptionOverflow, description]);\n\n const renderDescription = () => {\n if (!description) return null;\n\n return (\n <div className={cx(`${rootClassName}__description`)}>\n {typeof description === \"string\" ? (\n <Paragraph ref={descriptionRef} className={cx(`${rootClassName}__description-text`)}>\n <span ref={descriptionContentRef}>{description}</span>\n </Paragraph>\n ) : (\n <div ref={descriptionRef} className={cx(`${rootClassName}__description-text`)}>\n <div ref={descriptionContentRef} className={cx(`${rootClassName}__description-inner`)}>\n {description}\n </div>\n </div>\n )}\n <Button\n variant=\"text\"\n size=\"xs\"\n className={cx(`${rootClassName}__read-more`, {\n [`${rootClassName}__read-more--hidden`]: !descriptionOverflows,\n })}\n onClick={toggleShowFullDescriptions}\n aria-hidden={!descriptionOverflows}\n tabIndex={descriptionOverflows ? undefined : -1}\n >\n <span className={cx(`${rootClassName}__read-more-text`)}>\n {showFullDescriptions ? ariaLabels.readLess : ariaLabels.readMore}\n </span>\n <IconChevronDown className={cx(`${rootClassName}__read-more-icon`)} size=\"xs\" />\n </Button>\n </div>\n );\n };\n\n return (\n <article className={classes} data-card-id={id} data-card-index={cardIndex}>\n {badge && <Badge {...badge} className={cx(`${rootClassName}__badge`)} />}\n\n <section className={cx(`${rootClassName}__main-content`)}>\n <img src={image.src} alt={image.alt} className={cx(`${rootClassName}__image`)} />\n\n <div className={cx(`${rootClassName}__body`)}>\n <Heading tag=\"h3\" variant=\"title-200\" className={cx(`${rootClassName}__title`)}>\n {title}\n </Heading>\n {renderDescription()}\n </div>\n </section>\n\n <footer className={cx(`${rootClassName}__footer`)}>\n <span className={cx(`${rootClassName}__price`)} id={id}>\n <Paragraph variant=\"paragraph-100\">{variablePriceText}</Paragraph>\n <Paragraph variant=\"paragraph-100-bold\">{price}</Paragraph>\n </span>\n\n {actions}\n </footer>\n </article>\n );\n};\n","import React, { type RefObject, useCallback, useEffect, useState } from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { IconArrowLeft } from \"@purpur/icon/arrow-left\";\nimport { IconArrowRight } from \"@purpur/icon/arrow-right\";\nimport c from \"classnames/bind\";\n\nimport { type ComparisonTableProps, type Features, type Item } from \"../../comparison-table\";\nimport styles from \"./scroll-progress.module.scss\";\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-comparison-table-scroll-progress\";\n\ntype ScrollProgressProps = {\n items: Array<Item<Features>>;\n container: RefObject<HTMLUListElement | null>;\n ariaLabels: ComparisonTableProps[\"ariaLabels\"];\n};\n\nexport const ScrollProgress = ({ items, container, ariaLabels }: ScrollProgressProps) => {\n const [inViewSet, setInViewSet] = useState<Set<number>>(new Set());\n\n const scrollToCard = useCallback(\n (index: number) => {\n const reduceMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n const card = container.current?.querySelector(\n `[data-card-index=\"${index}\"]`\n ) as HTMLElement | null;\n card?.scrollIntoView({ behavior: reduceMotion ? \"instant\" : \"smooth\", block: \"nearest\" });\n },\n [container]\n );\n\n const previousCard = useCallback(() => {\n if (inViewSet.size === 0) return;\n\n const leftmostactiveIndex = Math.min(...Array.from(inViewSet));\n const targetIndex = leftmostactiveIndex - 1;\n\n if (targetIndex < 0) return;\n\n scrollToCard(targetIndex);\n }, [inViewSet, scrollToCard]);\n\n const nextCard = useCallback(() => {\n if (inViewSet.size === 0) return;\n\n const rightmostactiveIndex = Math.max(...Array.from(inViewSet));\n const targetIndex = rightmostactiveIndex + 1;\n\n if (targetIndex >= items.length) return;\n\n scrollToCard(targetIndex);\n }, [inViewSet, items.length, scrollToCard]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") {\n e.preventDefault();\n\n if (e.key === \"ArrowRight\") nextCard();\n else if (e.key === \"ArrowLeft\") previousCard();\n }\n },\n [nextCard, previousCard]\n );\n\n useEffect(() => {\n const root = container.current;\n\n if (!root) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n setInViewSet((prev) => {\n const next = new Set(prev);\n\n entries.forEach((entry) => {\n const index = Number(entry.target.getAttribute(\"data-card-index\"));\n\n if (Number.isNaN(index)) return;\n\n if (entry.isIntersecting) {\n next.add(index);\n } else {\n next.delete(index);\n }\n });\n return next;\n });\n },\n { root, threshold: 0.5 }\n );\n\n items.forEach((_, index) => {\n const card = root.querySelector(`[data-card-index=\"${index}\"]`) as HTMLElement | null;\n\n if (card) observer.observe(card);\n });\n\n return () => observer.disconnect();\n }, [container, items]);\n\n useEffect(() => {\n const root = container.current;\n\n if (!root) return;\n\n root.addEventListener(\"keydown\", handleKeyDown);\n\n return () => root.removeEventListener(\"keydown\", handleKeyDown);\n }, [container, handleKeyDown]);\n\n const renderIndicators = () => {\n if (inViewSet.size === 0) return;\n\n const indicators = [];\n const viewCapacity = inViewSet.size;\n const leftmostActiveIndex = Math.min(...Array.from(inViewSet));\n const head = items.slice(0, leftmostActiveIndex).length;\n const trail = items.slice(leftmostActiveIndex + viewCapacity).length;\n\n let key = 0;\n\n for (let i = 0; i < items.length; i++) {\n if (head + 1 !== i && head <= i && i < items.length - trail) continue;\n\n let status = \"active\";\n\n if (i < head || i > items.length - 1 - trail) status = \"\";\n\n indicators.push(\n <li key={`indicator-${key++}`} className={cx(`${rootClassName}__indicator`, status)} />\n );\n }\n\n if (indicators.length < 2) return null;\n\n return indicators;\n };\n\n return (\n <li className={cx(rootClassName)}>\n <ul className={cx(`${rootClassName}__indicators`)}>{renderIndicators()}</ul>\n\n <div className={cx(`${rootClassName}__buttons`)}>\n <Button\n aria-label={ariaLabels.previous}\n variant=\"secondary\"\n iconOnly\n className={cx(`${rootClassName}__button`)}\n disabled={inViewSet.has(0)}\n onClick={previousCard}\n >\n <IconArrowLeft className={cx(`${rootClassName}__button-icon`)} size=\"xs\" />\n </Button>\n <Button\n aria-label={ariaLabels.next}\n variant=\"secondary\"\n iconOnly\n className={cx(`${rootClassName}__button`)}\n disabled={inViewSet.has(items.length - 1)}\n onClick={nextCard}\n >\n <IconArrowRight className={cx(`${rootClassName}__button-icon`)} size=\"xs\" />\n </Button>\n </div>\n </li>\n );\n};\n","import React, { type ReactNode, type UIEvent, useCallback, useId, useRef, useState } from \"react\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./comparison-table.module.scss\";\nimport { Cell } from \"./components/Cell/cell\";\nimport { LeadCell } from \"./components/LeadCell/lead-cell\";\nimport { OptionCard, type OptionCardProps } from \"./components/OptionCard/option-card\";\nimport { ScrollProgress } from \"./components/ScrollProgress/scroll-progress\";\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table\";\n\nexport type Features = Record<string, ReactNode | null>;\n\nexport type Item<TFeatures extends Features = Features> = OptionCardProps & {\n features: Partial<Record<keyof TFeatures, ReactNode | string | boolean>>;\n};\n\nexport type ComparisonTableProps<TFeatures extends Features = Features> = {\n /** List of features that can be supported by the comparison table\n *\n * string = description of the feature that can be viewed by expanding cell.\n *\n * null = no description\n *\n {\n [featureName]: ReactNode | null\n }\n */\n features: TFeatures;\n\n /** List of items to be displayed in the comparison table\n *\n *\n Item = {\n image: {\n src: string;\n alt: string;\n };\n\n title: string;\n description: string;\n variablePriceText: string;\n price: string;\n actions: ReactNode;\n badge?: BadgeProps;\n isHighlighted?: boolean;\n\n features: {\n [featureName in keyof Features]?: string | boolean;\n };\n }\n */\n items: Array<Item<TFeatures>>;\n\n /** Aria labels for the comparison table and various components\n *\n {\n previous: string;\n next: string;\n readMore: string;\n readLess: string;\n }\n */\n ariaLabels: {\n previous: string;\n next: string;\n readMore: string;\n readLess: string;\n };\n variant?: \"primary\" | \"secondary\";\n classname?: string;\n};\n\nexport const ComparisonTable = <TFeatures extends Features>({\n classname,\n features,\n items,\n ariaLabels,\n variant = \"primary\",\n}: ComparisonTableProps<TFeatures>) => {\n const id = useId();\n const classes = cx(classname, rootClassName, `${rootClassName}--${variant}`);\n const containerRef = useRef<HTMLUListElement>(null);\n const [showFullDescriptions, setShowFullDescriptions] = useState(false);\n\n const handleToggleShowFullDescriptions = useCallback(() => {\n setShowFullDescriptions((prev) => !prev);\n }, []);\n\n const renderCards = () => {\n return (\n <li className={cx(`${rootClassName}__cards`)}>\n <div className={cx(`${rootClassName}__separator`)} />\n {items.map((item, index) => (\n <OptionCard\n {...item}\n showFullDescriptions={showFullDescriptions}\n toggleShowFullDescriptions={handleToggleShowFullDescriptions}\n key={index}\n isFirstCard={index === 0}\n ariaLabels={ariaLabels}\n cardIndex={index}\n id={`${index}-${id}`}\n />\n ))}\n </li>\n );\n };\n\n const renderFeatures = () => {\n return Object.entries(features).map(([title, description], i) => (\n <li key={i} className={cx(`${rootClassName}__feature-row`)}>\n <LeadCell title={title} description={description} />\n {items.map((item, index) => (\n <Cell key={index} value={item.features[title as keyof TFeatures] ?? false} />\n ))}\n </li>\n ));\n };\n\n const deltaTime = useRef(0);\n\n const handleScrollEnd = (e: UIEvent<HTMLUListElement>) => {\n /**\n * This function makes sure that the scroll position is never stuck between two cards, since scroll snap is not fully reliable.\n */\n\n const target = e.currentTarget;\n const cardwidth = target.querySelector(\"[data-card-id]\")?.clientWidth ?? 0;\n const cardPos = Math.round(target.scrollLeft / cardwidth);\n const scrollTarget = cardPos * cardwidth + cardPos;\n const timeDiff = e.timeStamp - deltaTime.current;\n const scrollDiff = Math.abs(target.scrollLeft - scrollTarget);\n\n if (deltaTime.current && timeDiff < 200) return;\n if (scrollDiff < 10) return;\n\n deltaTime.current = e.timeStamp;\n\n target.scrollTo({ left: scrollTarget, behavior: \"smooth\" });\n };\n\n return (\n <div className={cx(rootClassName + \"__wrapper\")}>\n <ul\n id={rootClassName + `-${id}`}\n ref={containerRef}\n className={classes}\n // eslint-disable-next-line react/no-unknown-property\n onScrollEnd={handleScrollEnd}\n style={{\n // @ts-expect-error | Typescript doesn't recognize the CSS variable, but it works as intended\n [\"--initial-columns\"]: items.length + 1,\n }}\n >\n <ScrollProgress items={items} container={containerRef} ariaLabels={ariaLabels} />\n {renderCards()}\n {renderFeatures()}\n </ul>\n </div>\n );\n};\n\nComparisonTable.displayName = \"ComparisonTable\";\n"],"names":["cx","c","styles","rootClassName","Cell","value","isReactNode","isValidElement","classes","Icon","IconCheckmark","IconMinus","jsx","LeadCell","title","description","isExpandable","jsxs","Paragraph","IconChevronDown","OptionCard","id","cardIndex","variablePriceText","price","isHighlighted","ariaLabels","badge","actions","isFirstCard","image","showFullDescriptions","toggleShowFullDescriptions","descriptionRef","useRef","descriptionContentRef","showFullDescriptionsRef","descriptionOverflows","setDescriptionOverflows","useState","useEffect","checkDescriptionOverflow","useCallback","descriptionContent","descriptionHeight","contentHeight","descriptionElement","resizeObserver","renderDescription","Button","Badge","Heading","ScrollProgress","items","container","inViewSet","setInViewSet","scrollToCard","index","reduceMotion","previousCard","targetIndex","nextCard","handleKeyDown","root","observer","entries","prev","next","entry","_","card","renderIndicators","indicators","viewCapacity","leftmostActiveIndex","head","trail","key","i","status","IconArrowLeft","IconArrowRight","ComparisonTable","classname","features","variant","useId","containerRef","setShowFullDescriptions","handleToggleShowFullDescriptions","renderCards","item","createElement","renderFeatures","deltaTime","handleScrollEnd","e","target","cardwidth","cardPos","scrollTarget","timeDiff","scrollDiff"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"comparison-table-CmtSOUfK.mjs","sources":["../../../components/comparison-table/src/components/Cell/cell.tsx","../../../components/comparison-table/src/components/LeadCell/lead-cell.tsx","../../../components/comparison-table/src/components/OptionCard/option-card.tsx","../../../components/comparison-table/src/components/ScrollProgress/scroll-progress.tsx","../../../components/comparison-table/src/comparison-table.tsx"],"sourcesContent":["import React, { isValidElement, type ReactNode } from \"react\";\nimport { IconCheckmark } from \"@purpur/icon/checkmark\";\nimport { IconMinus } from \"@purpur/icon/minus\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./cell.module.scss\";\n\ntype CellProps = {\n value: boolean | ReactNode;\n};\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-cell\";\n\nexport const Cell = ({ value }: CellProps) => {\n const isReactNode = isValidElement(value) || [\"string\", \"number\"].includes(typeof value);\n\n const getClassName = () => {\n if (isReactNode) return \"\";\n return `${rootClassName}--${value ? \"check\" : \"minus\"}`;\n };\n\n const classes = cx(rootClassName, [getClassName()]);\n\n const Icon = value ? IconCheckmark : IconMinus;\n\n return (\n <span className={cx(classes)}>\n {isReactNode ? value : <Icon size=\"xs\" className={cx(`${rootClassName}__icon`)} />}\n </span>\n );\n};\n","import React, { type ReactNode } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Paragraph } from \"@purpur/paragraph\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./lead-cell.module.scss\";\n\ntype LeadCellProps = {\n title: string;\n description?: ReactNode;\n};\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-lead-cell\";\n\nexport const LeadCell = ({ title, description }: LeadCellProps) => {\n const isExpandable = typeof description === \"string\";\n const classes = cx(rootClassName);\n\n return (\n <details className={classes} data-is-expandable={isExpandable}>\n <summary className={cx(`${rootClassName}__summary`)} tabIndex={isExpandable ? 0 : -1}>\n <Paragraph className={cx(`${rootClassName}__summary-title`)} variant=\"paragraph-100-bold\">\n {title}\n </Paragraph>\n <IconChevronDown className={cx(`${rootClassName}__summary-icon`)} size=\"sm\" />\n </summary>\n {description && (\n <Paragraph variant=\"paragraph-100\" className={cx(`${rootClassName}__description`)}>\n {description}\n </Paragraph>\n )}\n </details>\n );\n};\n","import React, { type ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { Badge, type BadgeProps } from \"@purpur/badge\";\nimport { Button } from \"@purpur/button\";\nimport { Heading } from \"@purpur/heading\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Paragraph } from \"@purpur/paragraph\";\nimport c from \"classnames/bind\";\n\nimport { type ComparisonTableProps } from \"../../comparison-table\";\nimport styles from \"./option-card.module.scss\";\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table-option-card\";\n\nexport type OptionCardProps = {\n image: {\n src: string;\n alt: string;\n };\n\n title: string;\n description: ReactNode;\n variablePriceText: string;\n price: string;\n\n actions: ReactNode;\n\n badge?: BadgeProps;\n isHighlighted?: boolean;\n};\n\ntype OptionCardPropsAdditions = {\n id: string;\n cardIndex: number;\n isFirstCard: boolean;\n ariaLabels: ComparisonTableProps[\"ariaLabels\"];\n\n showFullDescriptions: boolean;\n toggleShowFullDescriptions: () => void;\n};\n\nexport const OptionCard = ({\n id,\n cardIndex,\n description,\n variablePriceText,\n price,\n isHighlighted,\n ariaLabels,\n badge,\n actions,\n isFirstCard,\n image,\n title,\n showFullDescriptions,\n toggleShowFullDescriptions,\n}: OptionCardProps & OptionCardPropsAdditions) => {\n const descriptionRef = useRef<HTMLDivElement | HTMLParagraphElement>(null);\n const descriptionContentRef = useRef<HTMLDivElement | null>(null);\n const showFullDescriptionsRef = useRef(showFullDescriptions);\n const [descriptionOverflows, setDescriptionOverflows] = useState(false);\n\n const classes = cx(rootClassName, {\n [`${rootClassName}--highlighted`]: isHighlighted,\n [`${rootClassName}--first-card`]: isFirstCard,\n [`${rootClassName}--show-full-descriptions`]: showFullDescriptions,\n });\n\n useEffect(() => {\n showFullDescriptionsRef.current = showFullDescriptions;\n }, [showFullDescriptions]);\n\n const checkDescriptionOverflow = useCallback(() => {\n if (showFullDescriptionsRef.current) {\n return;\n }\n\n const description = descriptionRef.current;\n const descriptionContent = descriptionContentRef.current;\n\n if (!description || !descriptionContent) {\n setDescriptionOverflows(false);\n return;\n }\n\n const descriptionHeight = description.clientHeight;\n const contentHeight = descriptionContent.offsetHeight;\n\n setDescriptionOverflows(contentHeight > descriptionHeight + 1);\n }, []);\n\n useEffect(() => {\n const descriptionElement = descriptionRef.current;\n\n checkDescriptionOverflow();\n\n if (!descriptionElement || typeof ResizeObserver === \"undefined\") {\n return undefined;\n }\n\n const resizeObserver = new ResizeObserver(checkDescriptionOverflow);\n resizeObserver.observe(descriptionElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [checkDescriptionOverflow, description]);\n\n const renderDescription = () => {\n if (!description) return null;\n\n return (\n <div className={cx(`${rootClassName}__description`)}>\n {typeof description === \"string\" ? (\n <Paragraph ref={descriptionRef} className={cx(`${rootClassName}__description-text`)}>\n <span ref={descriptionContentRef}>{description}</span>\n </Paragraph>\n ) : (\n <div ref={descriptionRef} className={cx(`${rootClassName}__description-text`)}>\n <div ref={descriptionContentRef} className={cx(`${rootClassName}__description-inner`)}>\n {description}\n </div>\n </div>\n )}\n <Button\n variant=\"text\"\n size=\"xs\"\n className={cx(`${rootClassName}__read-more`, {\n [`${rootClassName}__read-more--hidden`]: !descriptionOverflows,\n })}\n onClick={toggleShowFullDescriptions}\n aria-hidden={!descriptionOverflows}\n tabIndex={descriptionOverflows ? undefined : -1}\n >\n <span className={cx(`${rootClassName}__read-more-text`)}>\n {showFullDescriptions ? ariaLabels.readLess : ariaLabels.readMore}\n </span>\n <IconChevronDown className={cx(`${rootClassName}__read-more-icon`)} size=\"xs\" />\n </Button>\n </div>\n );\n };\n\n return (\n <article className={classes} data-card-id={id} data-card-index={cardIndex}>\n {badge && <Badge {...badge} className={cx(`${rootClassName}__badge`)} />}\n\n <section className={cx(`${rootClassName}__main-content`)}>\n <img src={image.src} alt={image.alt} className={cx(`${rootClassName}__image`)} />\n\n <div className={cx(`${rootClassName}__body`)}>\n <Heading tag=\"h3\" variant=\"title-200\" className={cx(`${rootClassName}__title`)}>\n {title}\n </Heading>\n {renderDescription()}\n </div>\n </section>\n\n <footer className={cx(`${rootClassName}__footer`)}>\n <span className={cx(`${rootClassName}__price`)} id={id}>\n <Paragraph variant=\"paragraph-100\">{variablePriceText}</Paragraph>\n <Paragraph variant=\"paragraph-100-bold\">{price}</Paragraph>\n </span>\n\n {actions}\n </footer>\n </article>\n );\n};\n","import React, { type RefObject, useCallback, useEffect, useState } from \"react\";\nimport { Button } from \"@purpur/button\";\nimport { IconArrowLeft } from \"@purpur/icon/arrow-left\";\nimport { IconArrowRight } from \"@purpur/icon/arrow-right\";\nimport c from \"classnames/bind\";\n\nimport { type ComparisonTableProps, type Features, type Item } from \"../../comparison-table\";\nimport styles from \"./scroll-progress.module.scss\";\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-comparison-table-scroll-progress\";\n\ntype ScrollProgressProps = {\n items: Array<Item<Features>>;\n container: RefObject<HTMLUListElement | null>;\n ariaLabels: ComparisonTableProps[\"ariaLabels\"];\n};\n\nexport const ScrollProgress = ({ items, container, ariaLabels }: ScrollProgressProps) => {\n const [inViewSet, setInViewSet] = useState<Set<number>>(new Set());\n\n const scrollToCard = useCallback(\n (index: number) => {\n const reduceMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n const card = container.current?.querySelector(\n `[data-card-index=\"${index}\"]`\n ) as HTMLElement | null;\n card?.scrollIntoView({ behavior: reduceMotion ? \"instant\" : \"smooth\", block: \"nearest\" });\n },\n [container]\n );\n\n const previousCard = useCallback(() => {\n if (inViewSet.size === 0) return;\n\n const leftmostactiveIndex = Math.min(...Array.from(inViewSet));\n const targetIndex = leftmostactiveIndex - 1;\n\n if (targetIndex < 0) return;\n\n scrollToCard(targetIndex);\n }, [inViewSet, scrollToCard]);\n\n const nextCard = useCallback(() => {\n if (inViewSet.size === 0) return;\n\n const rightmostactiveIndex = Math.max(...Array.from(inViewSet));\n const targetIndex = rightmostactiveIndex + 1;\n\n if (targetIndex >= items.length) return;\n\n scrollToCard(targetIndex);\n }, [inViewSet, items.length, scrollToCard]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") {\n e.preventDefault();\n\n if (e.key === \"ArrowRight\") nextCard();\n else if (e.key === \"ArrowLeft\") previousCard();\n }\n },\n [nextCard, previousCard]\n );\n\n useEffect(() => {\n const root = container.current;\n\n if (!root) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n setInViewSet((prev) => {\n const next = new Set(prev);\n\n entries.forEach((entry) => {\n const index = Number(entry.target.getAttribute(\"data-card-index\"));\n\n if (Number.isNaN(index)) return;\n\n if (entry.isIntersecting) {\n next.add(index);\n } else {\n next.delete(index);\n }\n });\n return next;\n });\n },\n { root, threshold: 0.5 }\n );\n\n items.forEach((_, index) => {\n const card = root.querySelector(`[data-card-index=\"${index}\"]`) as HTMLElement | null;\n\n if (card) observer.observe(card);\n });\n\n return () => observer.disconnect();\n }, [container, items]);\n\n useEffect(() => {\n const root = container.current;\n\n if (!root) return;\n\n root.addEventListener(\"keydown\", handleKeyDown);\n\n return () => root.removeEventListener(\"keydown\", handleKeyDown);\n }, [container, handleKeyDown]);\n\n const renderIndicators = () => {\n if (inViewSet.size === 0) return;\n\n const indicators = [];\n const viewCapacity = inViewSet.size;\n const leftmostActiveIndex = Math.min(...Array.from(inViewSet));\n const head = items.slice(0, leftmostActiveIndex).length;\n const trail = items.slice(leftmostActiveIndex + viewCapacity).length;\n\n let key = 0;\n\n for (let i = 0; i < items.length; i++) {\n if (head + 1 !== i && head <= i && i < items.length - trail) continue;\n\n let status = \"active\";\n\n if (i < head || i > items.length - 1 - trail) status = \"\";\n\n indicators.push(\n <li key={`indicator-${key++}`} className={cx(`${rootClassName}__indicator`, status)} />\n );\n }\n\n if (indicators.length < 2) return null;\n\n return indicators;\n };\n\n return (\n <li className={cx(rootClassName)}>\n <ul className={cx(`${rootClassName}__indicators`)}>{renderIndicators()}</ul>\n\n <div className={cx(`${rootClassName}__buttons`)}>\n <Button\n aria-label={ariaLabels.previous}\n variant=\"secondary\"\n iconOnly\n className={cx(`${rootClassName}__button`)}\n disabled={inViewSet.has(0)}\n onClick={previousCard}\n >\n <IconArrowLeft className={cx(`${rootClassName}__button-icon`)} size=\"xs\" />\n </Button>\n <Button\n aria-label={ariaLabels.next}\n variant=\"secondary\"\n iconOnly\n className={cx(`${rootClassName}__button`)}\n disabled={inViewSet.has(items.length - 1)}\n onClick={nextCard}\n >\n <IconArrowRight className={cx(`${rootClassName}__button-icon`)} size=\"xs\" />\n </Button>\n </div>\n </li>\n );\n};\n","import React, { type ReactNode, type UIEvent, useCallback, useId, useRef, useState } from \"react\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./comparison-table.module.scss\";\nimport { Cell } from \"./components/Cell/cell\";\nimport { LeadCell } from \"./components/LeadCell/lead-cell\";\nimport { OptionCard, type OptionCardProps } from \"./components/OptionCard/option-card\";\nimport { ScrollProgress } from \"./components/ScrollProgress/scroll-progress\";\n\nconst cx = c.bind(styles);\n\nconst rootClassName = \"purpur-comparison-table\";\n\nexport type Features = Record<string, ReactNode | null>;\n\nexport type Item<TFeatures extends Features = Features> = OptionCardProps & {\n features: Partial<Record<keyof TFeatures, ReactNode | string | boolean>>;\n};\n\nexport type ComparisonTableProps<TFeatures extends Features = Features> = {\n /** List of features that can be supported by the comparison table\n *\n * string = description of the feature that can be viewed by expanding cell.\n *\n * null = no description\n *\n {\n [featureName]: ReactNode | null\n }\n */\n features: TFeatures;\n\n /** List of items to be displayed in the comparison table\n *\n *\n Item = {\n image: {\n src: string;\n alt: string;\n };\n\n title: string;\n description: string;\n variablePriceText: string;\n price: string;\n actions: ReactNode;\n badge?: BadgeProps;\n isHighlighted?: boolean;\n\n features: {\n [featureName in keyof Features]?: string | boolean;\n };\n }\n */\n items: Array<Item<TFeatures>>;\n\n /** Aria labels for the comparison table and various components\n *\n {\n previous: string;\n next: string;\n readMore: string;\n readLess: string;\n }\n */\n ariaLabels: {\n previous: string;\n next: string;\n readMore: string;\n readLess: string;\n };\n variant?: \"primary\" | \"secondary\";\n classname?: string;\n};\n\nexport const ComparisonTable = <TFeatures extends Features>({\n classname,\n features,\n items,\n ariaLabels,\n variant = \"primary\",\n}: ComparisonTableProps<TFeatures>) => {\n const id = useId();\n const classes = cx(classname, rootClassName, `${rootClassName}--${variant}`);\n const containerRef = useRef<HTMLUListElement>(null);\n const [showFullDescriptions, setShowFullDescriptions] = useState(false);\n\n const handleToggleShowFullDescriptions = useCallback(() => {\n setShowFullDescriptions((prev) => !prev);\n }, []);\n\n const renderCards = () => {\n return (\n <li className={cx(`${rootClassName}__cards`)}>\n <div className={cx(`${rootClassName}__separator`)} />\n {items.map((item, index) => (\n <OptionCard\n {...item}\n showFullDescriptions={showFullDescriptions}\n toggleShowFullDescriptions={handleToggleShowFullDescriptions}\n key={index}\n isFirstCard={index === 0}\n ariaLabels={ariaLabels}\n cardIndex={index}\n id={`${index}-${id}`}\n />\n ))}\n </li>\n );\n };\n\n const renderFeatures = () => {\n return Object.entries(features).map(([title, description], i) => (\n <li key={i} className={cx(`${rootClassName}__feature-row`)}>\n <LeadCell title={title} description={description} />\n {items.map((item, index) => (\n <Cell key={index} value={item.features[title as keyof TFeatures] ?? false} />\n ))}\n </li>\n ));\n };\n\n const deltaTime = useRef(0);\n\n const handleScrollEnd = (e: UIEvent<HTMLUListElement>) => {\n /**\n * This function makes sure that the scroll position is never stuck between two cards, since scroll snap is not fully reliable.\n */\n\n const target = e.currentTarget;\n const cardwidth = target.querySelector(\"[data-card-id]\")?.clientWidth ?? 0;\n const cardPos = Math.round(target.scrollLeft / cardwidth);\n const scrollTarget = cardPos * cardwidth + cardPos;\n const timeDiff = e.timeStamp - deltaTime.current;\n const scrollDiff = Math.abs(target.scrollLeft - scrollTarget);\n\n if (deltaTime.current && timeDiff < 200) return;\n if (scrollDiff < 10) return;\n\n deltaTime.current = e.timeStamp;\n\n target.scrollTo({ left: scrollTarget, behavior: \"smooth\" });\n };\n\n return (\n <div className={cx(rootClassName + \"__wrapper\")}>\n <ul\n id={rootClassName + `-${id}`}\n ref={containerRef}\n className={classes}\n // eslint-disable-next-line react/no-unknown-property\n onScrollEnd={handleScrollEnd}\n style={{\n // @ts-expect-error | Typescript doesn't recognize the CSS variable, but it works as intended\n [\"--initial-columns\"]: items.length + 1,\n }}\n >\n <ScrollProgress items={items} container={containerRef} ariaLabels={ariaLabels} />\n {renderCards()}\n {renderFeatures()}\n </ul>\n </div>\n );\n};\n\nComparisonTable.displayName = \"ComparisonTable\";\n"],"names":["cx","c","styles","rootClassName","Cell","value","isReactNode","isValidElement","classes","Icon","IconCheckmark","IconMinus","jsx","LeadCell","title","description","isExpandable","jsxs","Paragraph","IconChevronDown","OptionCard","id","cardIndex","variablePriceText","price","isHighlighted","ariaLabels","badge","actions","isFirstCard","image","showFullDescriptions","toggleShowFullDescriptions","descriptionRef","useRef","descriptionContentRef","showFullDescriptionsRef","descriptionOverflows","setDescriptionOverflows","useState","useEffect","checkDescriptionOverflow","useCallback","descriptionContent","descriptionHeight","contentHeight","descriptionElement","resizeObserver","renderDescription","Button","Badge","Heading","ScrollProgress","items","container","inViewSet","setInViewSet","scrollToCard","index","reduceMotion","previousCard","targetIndex","nextCard","handleKeyDown","root","observer","entries","prev","next","entry","_","card","renderIndicators","indicators","viewCapacity","leftmostActiveIndex","head","trail","key","i","status","IconArrowLeft","IconArrowRight","ComparisonTable","classname","features","variant","useId","containerRef","setShowFullDescriptions","handleToggleShowFullDescriptions","renderCards","item","createElement","renderFeatures","deltaTime","handleScrollEnd","e","target","cardwidth","cardPos","scrollTarget","timeDiff","scrollDiff"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const r=require("react/jsx-runtime"),a=require("react"),O=require("./bind-DeUYJ6m9.js"),V=require("./checkmark.es-lYntWFA3.js"),F=require("./minus.es-DtXArdKK.js"),P=require("./chevron-down.es-BMjgiS3F.js"),E=require("./paragraph-B8HFdNne.js"),K=require("./badge-CQ0SS_t8.js"),M=require("./button-DmybVApa.js"),W=require("./heading-drD5ugCC.js"),G=require("./arrow-left.es-CCWJyrcQ.js"),J=require("./arrow-right.es-eH-IgGi9.js"),Q={"purpur-comparison-table__wrapper":"_purpur-comparison-table__wrapper_1udkj_1","purpur-comparison-table":"_purpur-comparison-table_1udkj_1","purpur-comparison-table--primary":"_purpur-comparison-table--primary_1udkj_11","purpur-comparison-table--secondary":"_purpur-comparison-table--secondary_1udkj_15","purpur-comparison-table__feature-row":"_purpur-comparison-table__feature-row_1udkj_32","purpur-comparison-table__cards":"_purpur-comparison-table__cards_1udkj_32","purpur-comparison-table__separator":"_purpur-comparison-table__separator_1udkj_49"},U={"purpur-comparison-table-cell":"_purpur-comparison-table-cell_glb5z_1","purpur-comparison-table-cell--check":"_purpur-comparison-table-cell--check_glb5z_17","purpur-comparison-table-cell--minus":"_purpur-comparison-table-cell--minus_glb5z_20","purpur-comparison-table-cell__icon":"_purpur-comparison-table-cell__icon_glb5z_23"},D=O.c.bind(U),T="purpur-comparison-table-cell",X=({value:o})=>{const i=a.isValidElement(o)||["string","number"].includes(typeof o),t=D(T,[i?"":`${T}--${o?"check":"minus"}`]),j=o?V.a:F.e;return r.jsx("span",{className:D(t),children:i?o:r.jsx(j,{size:"xs",className:D(`${T}__icon`)})})},Y={"purpur-comparison-table-lead-cell":"_purpur-comparison-table-lead-cell_rqs9w_1","purpur-comparison-table-lead-cell__description":"_purpur-comparison-table-lead-cell__description_rqs9w_5","purpur-comparison-table-lead-cell__summary":"_purpur-comparison-table-lead-cell__summary_rqs9w_40","purpur-comparison-table-lead-cell__summary-title":"_purpur-comparison-table-lead-cell__summary-title_rqs9w_48","purpur-comparison-table-lead-cell__summary-icon":"_purpur-comparison-table-lead-cell__summary-icon_rqs9w_51"},S=O.c.bind(Y),I="purpur-comparison-table-lead-cell",Z=({title:o,description:i})=>{const l=typeof i=="string",t=S(I);return r.jsxs("details",{className:t,"data-is-expandable":l,children:[r.jsxs("summary",{className:S(`${I}__summary`),tabIndex:l?0:-1,children:[r.jsx(E.Paragraph,{className:S(`${I}__summary-title`),variant:"paragraph-100-bold",children:o}),r.jsx(P.l,{className:S(`${I}__summary-icon`),size:"sm"})]}),i&&r.jsx(E.Paragraph,{variant:"paragraph-100",className:S(`${I}__description`),children:i})]})},rr={"purpur-comparison-table-option-card":"_purpur-comparison-table-option-card_zggg8_1","purpur-comparison-table-option-card--highlighted":"_purpur-comparison-table-option-card--highlighted_zggg8_11","purpur-comparison-table-option-card__badge":"_purpur-comparison-table-option-card__badge_zggg8_14","purpur-comparison-table-option-card__main-content":"_purpur-comparison-table-option-card__main-content_zggg8_19","purpur-comparison-table-option-card__image":"_purpur-comparison-table-option-card__image_zggg8_25","purpur-comparison-table-option-card__body":"_purpur-comparison-table-option-card__body_zggg8_31","purpur-comparison-table-option-card__description":"_purpur-comparison-table-option-card__description_zggg8_36","purpur-comparison-table-option-card__description-text":"_purpur-comparison-table-option-card__description-text_zggg8_41","purpur-comparison-table-option-card__description-inner":"_purpur-comparison-table-option-card__description-inner_zggg8_50","purpur-comparison-table-option-card__read-more":"_purpur-comparison-table-option-card__read-more_zggg8_56","purpur-comparison-table-option-card__read-more--hidden":"_purpur-comparison-table-option-card__read-more--hidden_zggg8_60","purpur-comparison-table-option-card__read-more-icon":"_purpur-comparison-table-option-card__read-more-icon_zggg8_63","purpur-comparison-table-option-card__footer":"_purpur-comparison-table-option-card__footer_zggg8_71","purpur-comparison-table-option-card__price":"_purpur-comparison-table-option-card__price_zggg8_76","purpur-comparison-table-option-card--show-full-descriptions":"_purpur-comparison-table-option-card--show-full-descriptions_zggg8_83","purpur-comparison-table-option-card--first-card":"_purpur-comparison-table-option-card--first-card_zggg8_126"},_=O.c.bind(rr),c="purpur-comparison-table-option-card",er=({id:o,cardIndex:i,description:l,variablePriceText:t,price:j,isHighlighted:g,ariaLabels:f,badge:h,actions:v,isFirstCard:k,image:e,title:p,showFullDescriptions:d,toggleShowFullDescriptions:m})=>{const u=a.useRef(null),n=a.useRef(null),s=a.useRef(d),[b,y]=a.useState(!1),w=_(c,{[`${c}--highlighted`]:g,[`${c}--first-card`]:k,[`${c}--show-full-descriptions`]:d});a.useEffect(()=>{s.current=d},[d]);const z=a.useCallback(()=>{if(s.current)return;const C=u.current,q=n.current;if(!C||!q){y(!1);return}const H=C.clientHeight,B=q.offsetHeight;y(B>H+1)},[]);a.useEffect(()=>{const C=u.current;if(z(),!C||typeof ResizeObserver>"u")return;const q=new ResizeObserver(z);return q.observe(C),()=>{q.disconnect()}},[z,l]);const A=()=>l?r.jsxs("div",{className:_(`${c}__description`),children:[typeof l=="string"?r.jsx(E.Paragraph,{ref:u,className:_(`${c}__description-text`),children:r.jsx("span",{ref:n,children:l})}):r.jsx("div",{ref:u,className:_(`${c}__description-text`),children:r.jsx("div",{ref:n,className:_(`${c}__description-inner`),children:l})}),r.jsxs(M.Button,{variant:"text",size:"xs",className:_(`${c}__read-more`,{[`${c}__read-more--hidden`]:!b}),onClick:m,"aria-hidden":!b,tabIndex:b?void 0:-1,children:[r.jsx("span",{className:_(`${c}__read-more-text`),children:d?f.readLess:f.readMore}),r.jsx(P.l,{className:_(`${c}__read-more-icon`),size:"xs"})]})]}):null;return r.jsxs("article",{className:w,"data-card-id":o,"data-card-index":i,children:[h&&r.jsx(K.Badge,{...h,className:_(`${c}__badge`)}),r.jsxs("section",{className:_(`${c}__main-content`),children:[r.jsx("img",{src:e.src,alt:e.alt,className:_(`${c}__image`)}),r.jsxs("div",{className:_(`${c}__body`),children:[r.jsx(W.Heading,{tag:"h3",variant:"title-200",className:_(`${c}__title`),children:p}),A()]})]}),r.jsxs("footer",{className:_(`${c}__footer`),children:[r.jsxs("span",{className:_(`${c}__price`),id:o,children:[r.jsx(E.Paragraph,{variant:"paragraph-100",children:t}),r.jsx(E.Paragraph,{variant:"paragraph-100-bold",children:j})]}),v]})]})},sr="_active_kvsnm_44",or={"purpur-comparison-table-scroll-progress":"_purpur-comparison-table-scroll-progress_kvsnm_1","purpur-comparison-table-scroll-progress__indicators":"_purpur-comparison-table-scroll-progress__indicators_kvsnm_15","purpur-comparison-table-scroll-progress__indicator":"_purpur-comparison-table-scroll-progress__indicator_kvsnm_15",active:sr,"purpur-comparison-table-scroll-progress__buttons":"_purpur-comparison-table-scroll-progress__buttons_kvsnm_48","purpur-comparison-table-scroll-progress__button":"_purpur-comparison-table-scroll-progress__button_kvsnm_48","purpur-comparison-table-scroll-progress__button-icon":"_purpur-comparison-table-scroll-progress__button-icon_kvsnm_57"},x=O.c.bind(or),$="purpur-comparison-table-scroll-progress",ar=({items:o,container:i,ariaLabels:l})=>{const[t,j]=a.useState(new Set),g=a.useCallback(e=>{const p=window.matchMedia("(prefers-reduced-motion: reduce)").matches;i.current?.querySelector(`[data-card-index="${e}"]`)?.scrollIntoView({behavior:p?"instant":"smooth",block:"nearest"})},[i]),f=a.useCallback(()=>{if(t.size===0)return;const p=Math.min(...Array.from(t))-1;p<0||g(p)},[t,g]),h=a.useCallback(()=>{if(t.size===0)return;const p=Math.max(...Array.from(t))+1;p>=o.length||g(p)},[t,o.length,g]),v=a.useCallback(e=>{(e.key==="ArrowRight"||e.key==="ArrowLeft")&&(e.preventDefault(),e.key==="ArrowRight"?h():e.key==="ArrowLeft"&&f())},[h,f]);a.useEffect(()=>{const e=i.current;if(!e)return;const p=new IntersectionObserver(d=>{j(m=>{const u=new Set(m);return d.forEach(n=>{const s=Number(n.target.getAttribute("data-card-index"));Number.isNaN(s)||(n.isIntersecting?u.add(s):u.delete(s))}),u})},{root:e,threshold:.5});return o.forEach((d,m)=>{const u=e.querySelector(`[data-card-index="${m}"]`);u&&p.observe(u)}),()=>p.disconnect()},[i,o]),a.useEffect(()=>{const e=i.current;if(e)return e.addEventListener("keydown",v),()=>e.removeEventListener("keydown",v)},[i,v]);const k=()=>{if(t.size===0)return;const e=[],p=t.size,d=Math.min(...Array.from(t)),m=o.slice(0,d).length,u=o.slice(d+p).length;let n=0;for(let s=0;s<o.length;s++){if(m+1!==s&&m<=s&&s<o.length-u)continue;let b="active";(s<m||s>o.length-1-u)&&(b=""),e.push(r.jsx("li",{className:x(`${$}__indicator`,b)},`indicator-${n++}`))}return e.length<2?null:e};return r.jsxs("li",{className:x($),children:[r.jsx("ul",{className:x(`${$}__indicators`),children:k()}),r.jsxs("div",{className:x(`${$}__buttons`),children:[r.jsx(M.Button,{"aria-label":l.previous,variant:"secondary",iconOnly:!0,className:x(`${$}__button`),disabled:t.has(0),onClick:f,children:r.jsx(G.l,{className:x(`${$}__button-icon`),size:"xs"})}),r.jsx(M.Button,{"aria-label":l.next,variant:"secondary",iconOnly:!0,className:x(`${$}__button`),disabled:t.has(o.length-1),onClick:h,children:r.jsx(J.i,{className:x(`${$}__button-icon`),size:"xs"})})]})]})},R=O.c.bind(Q),N="purpur-comparison-table",L=({classname:o,features:i,items:l,ariaLabels:t,variant:j="primary"})=>{const g=a.useId(),f=R(o,N,`${N}--${j}`),h=a.useRef(null),[v,k]=a.useState(!1),e=a.useCallback(()=>{k(n=>!n)},[]),p=()=>r.jsxs("li",{className:R(`${N}__cards`),children:[r.jsx("div",{className:R(`${N}__separator`)}),l.map((n,s)=>a.createElement(er,{...n,showFullDescriptions:v,toggleShowFullDescriptions:e,key:s,isFirstCard:s===0,ariaLabels:t,cardIndex:s,id:`${s}-${g}`}))]}),d=()=>Object.entries(i).map(([n,s],b)=>r.jsxs("li",{className:R(`${N}__feature-row`),children:[r.jsx(Z,{title:n,description:s}),l.map((y,w)=>r.jsx(X,{value:y.features[n]??!1},w))]},b)),m=a.useRef(0),u=n=>{const s=n.currentTarget,b=s.querySelector("[data-card-id]")?.clientWidth??0,y=Math.round(s.scrollLeft/b),w=y*b+y,z=n.timeStamp-m.current,A=Math.abs(s.scrollLeft-w);m.current&&z<200||A<10||(m.current=n.timeStamp,s.scrollTo({left:w,behavior:"smooth"}))};return r.jsx("div",{className:R(N+"__wrapper"),children:r.jsxs("ul",{id:N+`-${g}`,ref:h,className:f,onScrollEnd:u,style:{"--initial-columns":l.length+1},children:[r.jsx(ar,{items:l,container:h,ariaLabels:t}),p(),d()]})})};L.displayName="ComparisonTable";exports.ComparisonTable=L;
|
|
2
|
-
//# sourceMappingURL=comparison-table-
|
|
1
|
+
"use strict";const r=require("react/jsx-runtime"),a=require("react"),O=require("./bind-DeUYJ6m9.js"),V=require("./checkmark.es-lYntWFA3.js"),F=require("./minus.es-DtXArdKK.js"),P=require("./chevron-down.es-BMjgiS3F.js"),E=require("./paragraph-B8HFdNne.js"),K=require("./badge-CQ0SS_t8.js"),M=require("./button-DZgtrGqN.js"),W=require("./heading-drD5ugCC.js"),G=require("./arrow-left.es-CCWJyrcQ.js"),J=require("./arrow-right.es-eH-IgGi9.js"),Q={"purpur-comparison-table__wrapper":"_purpur-comparison-table__wrapper_1udkj_1","purpur-comparison-table":"_purpur-comparison-table_1udkj_1","purpur-comparison-table--primary":"_purpur-comparison-table--primary_1udkj_11","purpur-comparison-table--secondary":"_purpur-comparison-table--secondary_1udkj_15","purpur-comparison-table__feature-row":"_purpur-comparison-table__feature-row_1udkj_32","purpur-comparison-table__cards":"_purpur-comparison-table__cards_1udkj_32","purpur-comparison-table__separator":"_purpur-comparison-table__separator_1udkj_49"},U={"purpur-comparison-table-cell":"_purpur-comparison-table-cell_glb5z_1","purpur-comparison-table-cell--check":"_purpur-comparison-table-cell--check_glb5z_17","purpur-comparison-table-cell--minus":"_purpur-comparison-table-cell--minus_glb5z_20","purpur-comparison-table-cell__icon":"_purpur-comparison-table-cell__icon_glb5z_23"},D=O.c.bind(U),T="purpur-comparison-table-cell",X=({value:o})=>{const i=a.isValidElement(o)||["string","number"].includes(typeof o),t=D(T,[i?"":`${T}--${o?"check":"minus"}`]),j=o?V.a:F.e;return r.jsx("span",{className:D(t),children:i?o:r.jsx(j,{size:"xs",className:D(`${T}__icon`)})})},Y={"purpur-comparison-table-lead-cell":"_purpur-comparison-table-lead-cell_rqs9w_1","purpur-comparison-table-lead-cell__description":"_purpur-comparison-table-lead-cell__description_rqs9w_5","purpur-comparison-table-lead-cell__summary":"_purpur-comparison-table-lead-cell__summary_rqs9w_40","purpur-comparison-table-lead-cell__summary-title":"_purpur-comparison-table-lead-cell__summary-title_rqs9w_48","purpur-comparison-table-lead-cell__summary-icon":"_purpur-comparison-table-lead-cell__summary-icon_rqs9w_51"},S=O.c.bind(Y),I="purpur-comparison-table-lead-cell",Z=({title:o,description:i})=>{const l=typeof i=="string",t=S(I);return r.jsxs("details",{className:t,"data-is-expandable":l,children:[r.jsxs("summary",{className:S(`${I}__summary`),tabIndex:l?0:-1,children:[r.jsx(E.Paragraph,{className:S(`${I}__summary-title`),variant:"paragraph-100-bold",children:o}),r.jsx(P.l,{className:S(`${I}__summary-icon`),size:"sm"})]}),i&&r.jsx(E.Paragraph,{variant:"paragraph-100",className:S(`${I}__description`),children:i})]})},rr={"purpur-comparison-table-option-card":"_purpur-comparison-table-option-card_zggg8_1","purpur-comparison-table-option-card--highlighted":"_purpur-comparison-table-option-card--highlighted_zggg8_11","purpur-comparison-table-option-card__badge":"_purpur-comparison-table-option-card__badge_zggg8_14","purpur-comparison-table-option-card__main-content":"_purpur-comparison-table-option-card__main-content_zggg8_19","purpur-comparison-table-option-card__image":"_purpur-comparison-table-option-card__image_zggg8_25","purpur-comparison-table-option-card__body":"_purpur-comparison-table-option-card__body_zggg8_31","purpur-comparison-table-option-card__description":"_purpur-comparison-table-option-card__description_zggg8_36","purpur-comparison-table-option-card__description-text":"_purpur-comparison-table-option-card__description-text_zggg8_41","purpur-comparison-table-option-card__description-inner":"_purpur-comparison-table-option-card__description-inner_zggg8_50","purpur-comparison-table-option-card__read-more":"_purpur-comparison-table-option-card__read-more_zggg8_56","purpur-comparison-table-option-card__read-more--hidden":"_purpur-comparison-table-option-card__read-more--hidden_zggg8_60","purpur-comparison-table-option-card__read-more-icon":"_purpur-comparison-table-option-card__read-more-icon_zggg8_63","purpur-comparison-table-option-card__footer":"_purpur-comparison-table-option-card__footer_zggg8_71","purpur-comparison-table-option-card__price":"_purpur-comparison-table-option-card__price_zggg8_76","purpur-comparison-table-option-card--show-full-descriptions":"_purpur-comparison-table-option-card--show-full-descriptions_zggg8_83","purpur-comparison-table-option-card--first-card":"_purpur-comparison-table-option-card--first-card_zggg8_126"},_=O.c.bind(rr),c="purpur-comparison-table-option-card",er=({id:o,cardIndex:i,description:l,variablePriceText:t,price:j,isHighlighted:g,ariaLabels:f,badge:h,actions:v,isFirstCard:k,image:e,title:p,showFullDescriptions:d,toggleShowFullDescriptions:m})=>{const u=a.useRef(null),n=a.useRef(null),s=a.useRef(d),[b,y]=a.useState(!1),w=_(c,{[`${c}--highlighted`]:g,[`${c}--first-card`]:k,[`${c}--show-full-descriptions`]:d});a.useEffect(()=>{s.current=d},[d]);const z=a.useCallback(()=>{if(s.current)return;const C=u.current,q=n.current;if(!C||!q){y(!1);return}const H=C.clientHeight,B=q.offsetHeight;y(B>H+1)},[]);a.useEffect(()=>{const C=u.current;if(z(),!C||typeof ResizeObserver>"u")return;const q=new ResizeObserver(z);return q.observe(C),()=>{q.disconnect()}},[z,l]);const A=()=>l?r.jsxs("div",{className:_(`${c}__description`),children:[typeof l=="string"?r.jsx(E.Paragraph,{ref:u,className:_(`${c}__description-text`),children:r.jsx("span",{ref:n,children:l})}):r.jsx("div",{ref:u,className:_(`${c}__description-text`),children:r.jsx("div",{ref:n,className:_(`${c}__description-inner`),children:l})}),r.jsxs(M.Button,{variant:"text",size:"xs",className:_(`${c}__read-more`,{[`${c}__read-more--hidden`]:!b}),onClick:m,"aria-hidden":!b,tabIndex:b?void 0:-1,children:[r.jsx("span",{className:_(`${c}__read-more-text`),children:d?f.readLess:f.readMore}),r.jsx(P.l,{className:_(`${c}__read-more-icon`),size:"xs"})]})]}):null;return r.jsxs("article",{className:w,"data-card-id":o,"data-card-index":i,children:[h&&r.jsx(K.Badge,{...h,className:_(`${c}__badge`)}),r.jsxs("section",{className:_(`${c}__main-content`),children:[r.jsx("img",{src:e.src,alt:e.alt,className:_(`${c}__image`)}),r.jsxs("div",{className:_(`${c}__body`),children:[r.jsx(W.Heading,{tag:"h3",variant:"title-200",className:_(`${c}__title`),children:p}),A()]})]}),r.jsxs("footer",{className:_(`${c}__footer`),children:[r.jsxs("span",{className:_(`${c}__price`),id:o,children:[r.jsx(E.Paragraph,{variant:"paragraph-100",children:t}),r.jsx(E.Paragraph,{variant:"paragraph-100-bold",children:j})]}),v]})]})},sr="_active_kvsnm_44",or={"purpur-comparison-table-scroll-progress":"_purpur-comparison-table-scroll-progress_kvsnm_1","purpur-comparison-table-scroll-progress__indicators":"_purpur-comparison-table-scroll-progress__indicators_kvsnm_15","purpur-comparison-table-scroll-progress__indicator":"_purpur-comparison-table-scroll-progress__indicator_kvsnm_15",active:sr,"purpur-comparison-table-scroll-progress__buttons":"_purpur-comparison-table-scroll-progress__buttons_kvsnm_48","purpur-comparison-table-scroll-progress__button":"_purpur-comparison-table-scroll-progress__button_kvsnm_48","purpur-comparison-table-scroll-progress__button-icon":"_purpur-comparison-table-scroll-progress__button-icon_kvsnm_57"},x=O.c.bind(or),$="purpur-comparison-table-scroll-progress",ar=({items:o,container:i,ariaLabels:l})=>{const[t,j]=a.useState(new Set),g=a.useCallback(e=>{const p=window.matchMedia("(prefers-reduced-motion: reduce)").matches;i.current?.querySelector(`[data-card-index="${e}"]`)?.scrollIntoView({behavior:p?"instant":"smooth",block:"nearest"})},[i]),f=a.useCallback(()=>{if(t.size===0)return;const p=Math.min(...Array.from(t))-1;p<0||g(p)},[t,g]),h=a.useCallback(()=>{if(t.size===0)return;const p=Math.max(...Array.from(t))+1;p>=o.length||g(p)},[t,o.length,g]),v=a.useCallback(e=>{(e.key==="ArrowRight"||e.key==="ArrowLeft")&&(e.preventDefault(),e.key==="ArrowRight"?h():e.key==="ArrowLeft"&&f())},[h,f]);a.useEffect(()=>{const e=i.current;if(!e)return;const p=new IntersectionObserver(d=>{j(m=>{const u=new Set(m);return d.forEach(n=>{const s=Number(n.target.getAttribute("data-card-index"));Number.isNaN(s)||(n.isIntersecting?u.add(s):u.delete(s))}),u})},{root:e,threshold:.5});return o.forEach((d,m)=>{const u=e.querySelector(`[data-card-index="${m}"]`);u&&p.observe(u)}),()=>p.disconnect()},[i,o]),a.useEffect(()=>{const e=i.current;if(e)return e.addEventListener("keydown",v),()=>e.removeEventListener("keydown",v)},[i,v]);const k=()=>{if(t.size===0)return;const e=[],p=t.size,d=Math.min(...Array.from(t)),m=o.slice(0,d).length,u=o.slice(d+p).length;let n=0;for(let s=0;s<o.length;s++){if(m+1!==s&&m<=s&&s<o.length-u)continue;let b="active";(s<m||s>o.length-1-u)&&(b=""),e.push(r.jsx("li",{className:x(`${$}__indicator`,b)},`indicator-${n++}`))}return e.length<2?null:e};return r.jsxs("li",{className:x($),children:[r.jsx("ul",{className:x(`${$}__indicators`),children:k()}),r.jsxs("div",{className:x(`${$}__buttons`),children:[r.jsx(M.Button,{"aria-label":l.previous,variant:"secondary",iconOnly:!0,className:x(`${$}__button`),disabled:t.has(0),onClick:f,children:r.jsx(G.l,{className:x(`${$}__button-icon`),size:"xs"})}),r.jsx(M.Button,{"aria-label":l.next,variant:"secondary",iconOnly:!0,className:x(`${$}__button`),disabled:t.has(o.length-1),onClick:h,children:r.jsx(J.i,{className:x(`${$}__button-icon`),size:"xs"})})]})]})},R=O.c.bind(Q),N="purpur-comparison-table",L=({classname:o,features:i,items:l,ariaLabels:t,variant:j="primary"})=>{const g=a.useId(),f=R(o,N,`${N}--${j}`),h=a.useRef(null),[v,k]=a.useState(!1),e=a.useCallback(()=>{k(n=>!n)},[]),p=()=>r.jsxs("li",{className:R(`${N}__cards`),children:[r.jsx("div",{className:R(`${N}__separator`)}),l.map((n,s)=>a.createElement(er,{...n,showFullDescriptions:v,toggleShowFullDescriptions:e,key:s,isFirstCard:s===0,ariaLabels:t,cardIndex:s,id:`${s}-${g}`}))]}),d=()=>Object.entries(i).map(([n,s],b)=>r.jsxs("li",{className:R(`${N}__feature-row`),children:[r.jsx(Z,{title:n,description:s}),l.map((y,w)=>r.jsx(X,{value:y.features[n]??!1},w))]},b)),m=a.useRef(0),u=n=>{const s=n.currentTarget,b=s.querySelector("[data-card-id]")?.clientWidth??0,y=Math.round(s.scrollLeft/b),w=y*b+y,z=n.timeStamp-m.current,A=Math.abs(s.scrollLeft-w);m.current&&z<200||A<10||(m.current=n.timeStamp,s.scrollTo({left:w,behavior:"smooth"}))};return r.jsx("div",{className:R(N+"__wrapper"),children:r.jsxs("ul",{id:N+`-${g}`,ref:h,className:f,onScrollEnd:u,style:{"--initial-columns":l.length+1},children:[r.jsx(ar,{items:l,container:h,ariaLabels:t}),p(),d()]})})};L.displayName="ComparisonTable";exports.ComparisonTable=L;
|
|
2
|
+
//# sourceMappingURL=comparison-table-N5G3k2kr.js.map
|