@telefonica/mistica 16.60.0 → 16.62.0-beta.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/css/mistica.css +1 -1
- package/dist/accordion.css-mistica.js +16 -16
- package/dist/align.css-mistica.js +2 -2
- package/dist/autocomplete.css-mistica.js +6 -6
- package/dist/avatar.css-mistica.js +3 -3
- package/dist/badge.css-mistica.js +7 -7
- package/dist/box.css-mistica.js +15 -15
- package/dist/boxed.css-mistica.js +31 -31
- package/dist/button-fixed-footer-layout.d.ts +2 -1
- package/dist/button-fixed-footer-layout.js +4 -3
- package/dist/button-group.css-mistica.js +10 -10
- package/dist/button-layout.css-mistica.js +21 -21
- package/dist/button.css-mistica.js +51 -51
- package/dist/callout.css-mistica.js +16 -16
- package/dist/card-internal.css-mistica.js +38 -38
- package/dist/carousel.css-mistica.js +18 -18
- package/dist/checkbox.css-mistica.js +21 -21
- package/dist/chip.css-mistica.js +30 -30
- package/dist/circle.css-mistica.js +2 -2
- package/dist/community/advanced-data-card.css-mistica.js +26 -26
- package/dist/community/blocks.css-mistica.js +3 -3
- package/dist/community/example-component.css-mistica.js +2 -2
- package/dist/counter.css-mistica.js +12 -12
- package/dist/cover-hero.css-mistica.js +16 -16
- package/dist/credit-card-number-field.css-mistica.js +6 -6
- package/dist/date-field.css-mistica.js +1 -1
- package/dist/date-time-picker.css-mistica.js +2 -2
- package/dist/dialog.css-mistica.js +15 -15
- package/dist/divider.css-mistica.js +5 -5
- package/dist/double-field.css-mistica.js +4 -4
- package/dist/drawer.css-mistica.js +15 -15
- package/dist/empty-state-card.css-mistica.js +4 -4
- package/dist/empty-state.css-mistica.js +14 -14
- package/dist/fade-in.css-mistica.js +1 -1
- package/dist/feedback.css-mistica.js +14 -14
- package/dist/file-upload.css-mistica.js +14 -14
- package/dist/fixed-footer-layout.css-mistica.js +12 -12
- package/dist/fixed-footer-layout.d.ts +6 -1
- package/dist/fixed-footer-layout.js +29 -28
- package/dist/form.css-mistica.js +2 -2
- package/dist/grid-layout.css-mistica.js +9 -9
- package/dist/grid.css-mistica.js +147 -147
- package/dist/header.css-mistica.js +5 -5
- package/dist/hero.css-mistica.js +11 -11
- package/dist/horizontal-scroll.css-mistica.js +3 -3
- package/dist/icon-button.css-mistica.js +66 -66
- package/dist/icons/icon-chevron.css-mistica.js +6 -6
- package/dist/icons/icon-error.css-mistica.js +3 -3
- package/dist/image.css-mistica.js +11 -11
- package/dist/image.js +8 -1
- package/dist/inline.css-mistica.js +16 -16
- package/dist/list.css-mistica.js +15 -15
- package/dist/loading-bar.css-mistica.js +5 -5
- package/dist/loading-screen.css-mistica.js +15 -15
- package/dist/logo.css-mistica.js +9 -9
- package/dist/menu.css-mistica.js +24 -24
- package/dist/mosaic.css-mistica.js +3 -3
- package/dist/navigation-bar.css-mistica.js +45 -45
- package/dist/navigation-breadcrumbs.css-mistica.js +5 -5
- package/dist/package-version.js +2 -2
- package/dist/pin-field.css-mistica.js +10 -10
- package/dist/popover.css-mistica.js +2 -2
- package/dist/progress-bar.css-mistica.js +12 -12
- package/dist/radio-button.css-mistica.js +33 -33
- package/dist/rating.css-mistica.js +12 -12
- package/dist/responsive-layout.css-mistica.js +20 -20
- package/dist/screen-reader-only.css-mistica.js +2 -2
- package/dist/select.css-mistica.js +29 -29
- package/dist/sheet-action-row.css-mistica.js +2 -2
- package/dist/sheet-common.css-mistica.js +16 -16
- package/dist/sheet-info.css-mistica.js +4 -4
- package/dist/skeletons.css-mistica.js +12 -12
- package/dist/skins/skin-contract.css-mistica.js +686 -686
- package/dist/skip-link.css-mistica.js +3 -3
- package/dist/slider.css-mistica.js +28 -28
- package/dist/snackbar.css-mistica.js +16 -16
- package/dist/spinner.css-mistica.js +5 -5
- package/dist/square.css-mistica.js +2 -2
- package/dist/stack.css-mistica.js +9 -9
- package/dist/stacking-group.css-mistica.js +2 -2
- package/dist/stepper.css-mistica.js +16 -16
- package/dist/switch-component.css-mistica.js +53 -53
- package/dist/table.css-mistica.js +24 -24
- package/dist/tabs.css-mistica.js +30 -30
- package/dist/tag.css-mistica.js +5 -5
- package/dist/text-field-base.css-mistica.js +30 -30
- package/dist/text-field-components.css-mistica.js +19 -19
- package/dist/text-link.css-mistica.js +10 -10
- package/dist/text.css-mistica.js +13 -13
- package/dist/theme-context.css-mistica.js +2 -2
- package/dist/timeline.css-mistica.js +18 -18
- package/dist/timer.css-mistica.js +13 -13
- package/dist/tooltip.css-mistica.js +12 -12
- package/dist/touchable.css-mistica.js +5 -5
- package/dist/utils/aspect-ratio-support.css-mistica.js +7 -7
- package/dist/video.css-mistica.js +2 -2
- package/dist/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +3 -3
- package/dist-es/accordion.css-mistica.js +7 -7
- package/dist-es/align.css-mistica.js +2 -2
- package/dist-es/autocomplete.css-mistica.js +2 -2
- package/dist-es/avatar.css-mistica.js +2 -2
- package/dist-es/badge.css-mistica.js +2 -2
- package/dist-es/box.css-mistica.js +15 -15
- package/dist-es/boxed.css-mistica.js +25 -25
- package/dist-es/button-fixed-footer-layout.js +12 -11
- package/dist-es/button-group.css-mistica.js +2 -2
- package/dist-es/button-layout.css-mistica.js +16 -16
- package/dist-es/button.css-mistica.js +38 -38
- package/dist-es/callout.css-mistica.js +12 -12
- package/dist-es/card-internal.css-mistica.js +20 -20
- package/dist-es/carousel.css-mistica.js +10 -10
- package/dist-es/checkbox.css-mistica.js +14 -14
- package/dist-es/chip.css-mistica.js +17 -17
- package/dist-es/circle.css-mistica.js +2 -2
- package/dist-es/community/advanced-data-card.css-mistica.js +7 -7
- package/dist-es/community/blocks.css-mistica.js +2 -2
- package/dist-es/community/example-component.css-mistica.js +2 -2
- package/dist-es/counter.css-mistica.js +2 -2
- package/dist-es/cover-hero.css-mistica.js +4 -4
- package/dist-es/credit-card-number-field.css-mistica.js +4 -4
- package/dist-es/date-field.css-mistica.js +1 -1
- package/dist-es/date-time-picker.css-mistica.js +2 -2
- package/dist-es/dialog.css-mistica.js +5 -5
- package/dist-es/divider.css-mistica.js +5 -5
- package/dist-es/double-field.css-mistica.js +4 -4
- package/dist-es/drawer.css-mistica.js +2 -2
- package/dist-es/empty-state-card.css-mistica.js +2 -2
- package/dist-es/empty-state.css-mistica.js +7 -7
- package/dist-es/fade-in.css-mistica.js +1 -1
- package/dist-es/feedback.css-mistica.js +2 -2
- package/dist-es/file-upload.css-mistica.js +8 -8
- package/dist-es/fixed-footer-layout.css-mistica.js +4 -4
- package/dist-es/fixed-footer-layout.js +57 -56
- package/dist-es/form.css-mistica.js +2 -2
- package/dist-es/grid-layout.css-mistica.js +4 -4
- package/dist-es/grid.css-mistica.js +127 -127
- package/dist-es/header.css-mistica.js +2 -2
- package/dist-es/hero.css-mistica.js +4 -4
- package/dist-es/horizontal-scroll.css-mistica.js +2 -2
- package/dist-es/icon-button.css-mistica.js +56 -56
- package/dist-es/icons/icon-chevron.css-mistica.js +4 -4
- package/dist-es/icons/icon-error.css-mistica.js +2 -2
- package/dist-es/image.css-mistica.js +4 -4
- package/dist-es/image.js +8 -1
- package/dist-es/inline.css-mistica.js +10 -10
- package/dist-es/list.css-mistica.js +2 -2
- package/dist-es/loading-bar.css-mistica.js +2 -2
- package/dist-es/loading-screen.css-mistica.js +5 -5
- package/dist-es/logo.css-mistica.js +7 -7
- package/dist-es/menu.css-mistica.js +15 -15
- package/dist-es/mosaic.css-mistica.js +2 -2
- package/dist-es/navigation-bar.css-mistica.js +20 -20
- package/dist-es/navigation-breadcrumbs.css-mistica.js +2 -2
- package/dist-es/package-version.js +2 -2
- package/dist-es/pin-field.css-mistica.js +2 -2
- package/dist-es/popover.css-mistica.js +2 -2
- package/dist-es/progress-bar.css-mistica.js +8 -8
- package/dist-es/radio-button.css-mistica.js +25 -25
- package/dist-es/rating.css-mistica.js +4 -4
- package/dist-es/responsive-layout.css-mistica.js +7 -7
- package/dist-es/screen-reader-only.css-mistica.js +2 -2
- package/dist-es/select.css-mistica.js +20 -20
- package/dist-es/sheet-action-row.css-mistica.js +2 -2
- package/dist-es/sheet-common.css-mistica.js +2 -2
- package/dist-es/sheet-info.css-mistica.js +2 -2
- package/dist-es/skeletons.css-mistica.js +8 -8
- package/dist-es/skins/skin-contract.css-mistica.js +686 -686
- package/dist-es/skip-link.css-mistica.js +2 -2
- package/dist-es/slider.css-mistica.js +20 -20
- package/dist-es/snackbar.css-mistica.js +5 -5
- package/dist-es/spinner.css-mistica.js +2 -2
- package/dist-es/square.css-mistica.js +2 -2
- package/dist-es/stack.css-mistica.js +7 -7
- package/dist-es/stacking-group.css-mistica.js +2 -2
- package/dist-es/stepper.css-mistica.js +4 -4
- package/dist-es/style.css +1 -1
- package/dist-es/switch-component.css-mistica.js +41 -41
- package/dist-es/table.css-mistica.js +11 -11
- package/dist-es/tabs.css-mistica.js +21 -21
- package/dist-es/tag.css-mistica.js +2 -2
- package/dist-es/text-field-base.css-mistica.js +17 -17
- package/dist-es/text-field-components.css-mistica.js +4 -4
- package/dist-es/text-link.css-mistica.js +9 -9
- package/dist-es/text.css-mistica.js +8 -8
- package/dist-es/theme-context.css-mistica.js +2 -2
- package/dist-es/timeline.css-mistica.js +11 -11
- package/dist-es/timer.css-mistica.js +7 -7
- package/dist-es/tooltip.css-mistica.js +3 -3
- package/dist-es/touchable.css-mistica.js +2 -2
- package/dist-es/utils/aspect-ratio-support.css-mistica.js +4 -4
- package/dist-es/video.css-mistica.js +2 -2
- package/dist-es/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +2 -2
- package/doc/components.md +19 -0
- package/doc/figma-mcp.md +136 -0
- package/doc/layout.md +20 -1
- package/doc/llms.md +18 -0
- package/doc/patterns.md +6 -17
- package/package.json +13 -1
- package/src/accordion.css.ts +121 -0
- package/src/accordion.tsx +366 -0
- package/src/align.css.ts +7 -0
- package/src/align.tsx +32 -0
- package/src/autocomplete.css.ts +62 -0
- package/src/autocomplete.tsx +239 -0
- package/src/avatar.css.ts +14 -0
- package/src/avatar.tsx +120 -0
- package/src/badge.css.ts +51 -0
- package/src/badge.tsx +79 -0
- package/src/box.css.ts +51 -0
- package/src/box.tsx +114 -0
- package/src/boxed.css.ts +132 -0
- package/src/boxed.tsx +153 -0
- package/src/button-fixed-footer-layout.tsx +65 -0
- package/src/button-group.css.ts +75 -0
- package/src/button-group.tsx +91 -0
- package/src/button-layout.css.ts +162 -0
- package/src/button-layout.tsx +91 -0
- package/src/button.css.ts +758 -0
- package/src/button.tsx +632 -0
- package/src/callout.css.ts +50 -0
- package/src/callout.tsx +147 -0
- package/src/card-cover.tsx +242 -0
- package/src/card-data.tsx +152 -0
- package/src/card-internal.css.ts +271 -0
- package/src/card-internal.tsx +1724 -0
- package/src/card-media.tsx +157 -0
- package/src/card-naked.tsx +63 -0
- package/src/carousel.css.ts +522 -0
- package/src/carousel.tsx +1300 -0
- package/src/checkbox.css.ts +94 -0
- package/src/checkbox.tsx +192 -0
- package/src/chip.css.ts +204 -0
- package/src/chip.tsx +191 -0
- package/src/circle.css.ts +14 -0
- package/src/circle.tsx +52 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-and-link-footer-image-false-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-and-link-footer-image-true-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-footer-image-false-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-footer-image-true-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-link-footer-image-false-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-link-footer-image-true-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-none-footer-image-false-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-none-footer-image-true-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-0-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-1-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-3-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-3-no-divider-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-inside-carousel-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-without-stacking-group-with-top-actions-and-too-long-title-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-highlighted-value-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-information-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-progress-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-progress-block-2-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-row-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-simple-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-value-block-1-snap.png +0 -0
- package/src/community/__screenshot_tests__/advanced-data-card-screenshot-test.tsx +84 -0
- package/src/community/__screenshot_tests__/blocks-screenshot-test.tsx +72 -0
- package/src/community/__stories__/advanced-data-card-carousel-story.tsx +66 -0
- package/src/community/__stories__/advanced-data-card-story.tsx +158 -0
- package/src/community/__stories__/blocks-story.tsx +272 -0
- package/src/community/__stories__/example-component-story.tsx +15 -0
- package/src/community/__stories__/index-story.tsx +154 -0
- package/src/community/__type_tests__/advanced-data-card-type-test.tsx +40 -0
- package/src/community/advanced-data-card.css.ts +271 -0
- package/src/community/advanced-data-card.tsx +431 -0
- package/src/community/blocks.css.ts +12 -0
- package/src/community/blocks.tsx +290 -0
- package/src/community/example-component.css.ts +7 -0
- package/src/community/example-component.tsx +17 -0
- package/src/community/index.tsx +10 -0
- package/src/counter.css.ts +150 -0
- package/src/counter.tsx +215 -0
- package/src/cover-hero-media.tsx +39 -0
- package/src/cover-hero.css.ts +133 -0
- package/src/cover-hero.tsx +262 -0
- package/src/credit-card-expiration-field.tsx +187 -0
- package/src/credit-card-fields.tsx +56 -0
- package/src/credit-card-number-field.css.ts +47 -0
- package/src/credit-card-number-field.tsx +245 -0
- package/src/cvv-field.tsx +169 -0
- package/src/date-field.css.ts +14 -0
- package/src/date-field.tsx +130 -0
- package/src/date-time-field.tsx +141 -0
- package/src/date-time-picker.css.ts +126 -0
- package/src/date-time-picker.tsx +188 -0
- package/src/decimal-field.tsx +160 -0
- package/src/desktop-container-type-context.tsx +15 -0
- package/src/dialog-context.tsx +81 -0
- package/src/dialog.css.ts +155 -0
- package/src/dialog.tsx +423 -0
- package/src/divider.css.ts +10 -0
- package/src/divider.tsx +11 -0
- package/src/double-field.css.ts +33 -0
- package/src/double-field.tsx +71 -0
- package/src/drawer.css.ts +123 -0
- package/src/drawer.tsx +304 -0
- package/src/email-field.tsx +76 -0
- package/src/empty-state-card.css.ts +40 -0
- package/src/empty-state-card.tsx +92 -0
- package/src/empty-state.css.ts +119 -0
- package/src/empty-state.tsx +141 -0
- package/src/fade-in.css.ts +12 -0
- package/src/fade-in.tsx +40 -0
- package/src/feedback.css.ts +119 -0
- package/src/feedback.tsx +432 -0
- package/src/file-upload.css.ts +156 -0
- package/src/file-upload.tsx +612 -0
- package/src/fixed-footer-layout.css.ts +96 -0
- package/src/fixed-footer-layout.tsx +227 -0
- package/src/fixed-to-top.tsx +21 -0
- package/src/focus-trap.tsx +17 -0
- package/src/form-context.tsx +198 -0
- package/src/form.css.ts +5 -0
- package/src/form.tsx +287 -0
- package/src/grid-layout.css.ts +68 -0
- package/src/grid-layout.tsx +201 -0
- package/src/grid.css.ts +203 -0
- package/src/grid.tsx +241 -0
- package/src/header.css.ts +30 -0
- package/src/header.tsx +319 -0
- package/src/hero.css.ts +71 -0
- package/src/hero.tsx +318 -0
- package/src/hooks.tsx +313 -0
- package/src/horizontal-scroll.css.ts +43 -0
- package/src/horizontal-scroll.tsx +18 -0
- package/src/iban-field.tsx +218 -0
- package/src/icon-button.css.ts +561 -0
- package/src/icon-button.tsx +221 -0
- package/src/icons/__stories__/mistica-icons-story.tsx +192 -0
- package/src/icons/icon-amex.tsx +40 -0
- package/src/icons/icon-chevron.css.ts +23 -0
- package/src/icons/icon-chevron.tsx +150 -0
- package/src/icons/icon-cvv-amex.tsx +31 -0
- package/src/icons/icon-cvv-visa-mc.tsx +31 -0
- package/src/icons/icon-error.css.ts +27 -0
- package/src/icons/icon-error.tsx +207 -0
- package/src/icons/icon-info.tsx +86 -0
- package/src/icons/icon-mastercard.tsx +36 -0
- package/src/icons/icon-success-vivo-new.tsx +51 -0
- package/src/icons/icon-success-vivo.tsx +36 -0
- package/src/icons/icon-success.tsx +211 -0
- package/src/icons/icon-visa.tsx +32 -0
- package/src/image.css.ts +48 -0
- package/src/image.tsx +352 -0
- package/src/index.tsx +2466 -0
- package/src/inline.css.ts +131 -0
- package/src/inline.tsx +135 -0
- package/src/integer-field.tsx +93 -0
- package/src/list.css.ts +281 -0
- package/src/list.tsx +963 -0
- package/src/loading-bar.css.ts +69 -0
- package/src/loading-bar.tsx +25 -0
- package/src/loading-screen.css.ts +114 -0
- package/src/loading-screen.tsx +376 -0
- package/src/logo-blau-shell.tsx +30 -0
- package/src/logo-blau.tsx +60 -0
- package/src/logo-common.tsx +29 -0
- package/src/logo-esimflag-shell.tsx +30 -0
- package/src/logo-esimflag.tsx +56 -0
- package/src/logo-movistar-new-shell.tsx +30 -0
- package/src/logo-movistar-new.tsx +85 -0
- package/src/logo-movistar-shell.tsx +30 -0
- package/src/logo-movistar.tsx +63 -0
- package/src/logo-o2-new-shell.tsx +26 -0
- package/src/logo-o2-new.tsx +27 -0
- package/src/logo-o2-shell.tsx +26 -0
- package/src/logo-o2.tsx +27 -0
- package/src/logo-telefonica-shell.tsx +30 -0
- package/src/logo-telefonica.tsx +95 -0
- package/src/logo-tu-shell.tsx +26 -0
- package/src/logo-tu.tsx +28 -0
- package/src/logo-vivo-shell.tsx +30 -0
- package/src/logo-vivo.tsx +53 -0
- package/src/logo.css.ts +33 -0
- package/src/logo.tsx +313 -0
- package/src/master-detail-layout.tsx +28 -0
- package/src/maybe-dismissable.css.ts +37 -0
- package/src/maybe-dismissable.tsx +58 -0
- package/src/media-queries.css.ts +67 -0
- package/src/menu.css.ts +132 -0
- package/src/menu.tsx +468 -0
- package/src/meter.tsx +516 -0
- package/src/modal-context-provider.tsx +45 -0
- package/src/month-field.tsx +124 -0
- package/src/mosaic.css.ts +73 -0
- package/src/mosaic.tsx +205 -0
- package/src/navigation-bar.css.ts +558 -0
- package/src/navigation-bar.tsx +1637 -0
- package/src/navigation-breadcrumbs.css.ts +22 -0
- package/src/navigation-breadcrumbs.tsx +69 -0
- package/src/negative-box.tsx +15 -0
- package/src/nestable-context.tsx +139 -0
- package/src/overlay.tsx +86 -0
- package/src/overscroll-color-context.tsx +141 -0
- package/src/package-version.tsx +2 -0
- package/src/password-field.tsx +126 -0
- package/src/phone-number-field-lite.tsx +265 -0
- package/src/phone-number-field.tsx +171 -0
- package/src/pin-field.css.ts +90 -0
- package/src/pin-field.tsx +346 -0
- package/src/placeholder.tsx +41 -0
- package/src/popover.css.ts +8 -0
- package/src/popover.tsx +85 -0
- package/src/portal.tsx +43 -0
- package/src/progress-bar.css.ts +61 -0
- package/src/progress-bar.tsx +174 -0
- package/src/radio-button.css.ts +174 -0
- package/src/radio-button.tsx +322 -0
- package/src/rating.css.ts +128 -0
- package/src/rating.tsx +351 -0
- package/src/responsive-layout.css.ts +162 -0
- package/src/responsive-layout.tsx +106 -0
- package/src/screen-reader-only.css.ts +27 -0
- package/src/screen-reader-only.tsx +33 -0
- package/src/screen-size-context-provider.tsx +96 -0
- package/src/screen-size-context.tsx +23 -0
- package/src/search-field.tsx +126 -0
- package/src/select.css.ts +226 -0
- package/src/select.tsx +513 -0
- package/src/sheet-action-row.css.ts +33 -0
- package/src/sheet-actions-list.tsx +113 -0
- package/src/sheet-actions.tsx +95 -0
- package/src/sheet-common.css.ts +254 -0
- package/src/sheet-common.tsx +402 -0
- package/src/sheet-info.css.ts +19 -0
- package/src/sheet-info.tsx +127 -0
- package/src/sheet-native.tsx +189 -0
- package/src/sheet-radio-list.tsx +118 -0
- package/src/sheet-root.tsx +127 -0
- package/src/sheet-types.tsx +94 -0
- package/src/sheet-web.tsx +140 -0
- package/src/skeleton-base.tsx +38 -0
- package/src/skeletons.css.ts +56 -0
- package/src/skeletons.tsx +133 -0
- package/src/skins/blau.tsx +724 -0
- package/src/skins/constants.tsx +10 -0
- package/src/skins/defaults.tsx +104 -0
- package/src/skins/esimflag.tsx +728 -0
- package/src/skins/movistar-new.tsx +735 -0
- package/src/skins/movistar.tsx +740 -0
- package/src/skins/o2-new.tsx +731 -0
- package/src/skins/o2.tsx +727 -0
- package/src/skins/skin-contract.css.ts +380 -0
- package/src/skins/telefonica.tsx +768 -0
- package/src/skins/tu.tsx +741 -0
- package/src/skins/types/colors.tsx +286 -0
- package/src/skins/types/index.tsx +153 -0
- package/src/skins/utils.tsx +66 -0
- package/src/skins/vivo-new.tsx +745 -0
- package/src/skins/vivo.tsx +720 -0
- package/src/skip-link.css.ts +34 -0
- package/src/skip-link.tsx +52 -0
- package/src/slider.css.ts +181 -0
- package/src/slider.tsx +384 -0
- package/src/snackbar-context.tsx +98 -0
- package/src/snackbar-native.ts +37 -0
- package/src/snackbar.css.ts +176 -0
- package/src/snackbar.tsx +258 -0
- package/src/spinner.css.ts +66 -0
- package/src/spinner.tsx +136 -0
- package/src/sprinkles.css.ts +83 -0
- package/src/square.css.ts +15 -0
- package/src/square.tsx +55 -0
- package/src/stack.css.ts +44 -0
- package/src/stack.tsx +79 -0
- package/src/stacking-group.css.ts +15 -0
- package/src/stacking-group.tsx +82 -0
- package/src/stepper.css.ts +233 -0
- package/src/stepper.tsx +156 -0
- package/src/switch-component.css.ts +181 -0
- package/src/switch-component.tsx +187 -0
- package/src/tab-focus.tsx +68 -0
- package/src/table-actions-header.tsx +21 -0
- package/src/table-cell-text.tsx +35 -0
- package/src/table.css.ts +297 -0
- package/src/table.tsx +398 -0
- package/src/tabs.css.ts +212 -0
- package/src/tabs.tsx +263 -0
- package/src/tag.css.ts +42 -0
- package/src/tag.tsx +161 -0
- package/src/test-utils/environment/setup-ssr.tsx +10 -0
- package/src/test-utils/fail-test-on-console-error.tsx +22 -0
- package/src/test-utils/index.tsx +341 -0
- package/src/test-utils/setup-ssr-test-env.tsx +13 -0
- package/src/test-utils/ssr.tsx +197 -0
- package/src/text-field-base.css.ts +416 -0
- package/src/text-field-base.tsx +628 -0
- package/src/text-field-components.css.ts +165 -0
- package/src/text-field-components.tsx +230 -0
- package/src/text-field.tsx +118 -0
- package/src/text-link.css.ts +83 -0
- package/src/text-link.tsx +85 -0
- package/src/text-tokens.tsx +708 -0
- package/src/text.css.ts +60 -0
- package/src/text.tsx +516 -0
- package/src/theme-context-provider.tsx +370 -0
- package/src/theme-context.css.ts +3 -0
- package/src/theme-context.tsx +8 -0
- package/src/theme-variant-context.tsx +51 -0
- package/src/theme.tsx +184 -0
- package/src/time-field.tsx +99 -0
- package/src/timeline.css.ts +135 -0
- package/src/timeline.tsx +250 -0
- package/src/timer.css.ts +99 -0
- package/src/timer.tsx +420 -0
- package/src/title.tsx +119 -0
- package/src/tooltip-context-provider.tsx +57 -0
- package/src/tooltip.css.ts +106 -0
- package/src/tooltip.tsx +649 -0
- package/src/touchable.css.ts +56 -0
- package/src/touchable.tsx +355 -0
- package/src/types/font-face.d.ts +47 -0
- package/src/types/libs.d.ts +3 -0
- package/src/utils/__tests__/analytics-test.tsx +35 -0
- package/src/utils/__tests__/browser-test.tsx +28 -0
- package/src/utils/__tests__/dom-test.tsx +23 -0
- package/src/utils/__tests__/helpers-test.tsx +166 -0
- package/src/utils/analytics.tsx +28 -0
- package/src/utils/animation.tsx +201 -0
- package/src/utils/aspect-ratio-support.css.ts +28 -0
- package/src/utils/aspect-ratio-support.tsx +141 -0
- package/src/utils/browser.tsx +9 -0
- package/src/utils/color.tsx +46 -0
- package/src/utils/common.tsx +27 -0
- package/src/utils/credit-card.tsx +46 -0
- package/src/utils/css.tsx +25 -0
- package/src/utils/document-visibility.tsx +52 -0
- package/src/utils/dom.tsx +155 -0
- package/src/utils/environment.tsx +6 -0
- package/src/utils/headings.tsx +18 -0
- package/src/utils/helpers.tsx +182 -0
- package/src/utils/keys.tsx +8 -0
- package/src/utils/locale.tsx +27 -0
- package/src/utils/platform.tsx +94 -0
- package/src/utils/region-code.tsx +1 -0
- package/src/utils/renders-element.tsx +6 -0
- package/src/utils/time.tsx +22 -0
- package/src/utils/types.tsx +19 -0
- package/src/utils/utility-types.tsx +8 -0
- package/src/video.css.ts +11 -0
- package/src/video.tsx +355 -0
- package/src/vivinho-loading-animation/in-lottie.json +402 -0
- package/src/vivinho-loading-animation/index.tsx +90 -0
- package/src/vivinho-loading-animation/out-lottie.json +575 -0
- package/src/vivinho-loading-animation/pulse-lottie.json +551 -0
- package/src/vivinho-loading-animation/vivinho-loading-animation.css.ts +15 -0
- package/src/vivinho-loading-animation/wave-lottie.json +2829 -0
package/doc/layout.md
CHANGED
|
@@ -79,7 +79,8 @@ a horizontal `Stack`, and it covers the most common row-layout use cases you mig
|
|
|
79
79
|
It supports:
|
|
80
80
|
|
|
81
81
|
- horizontal distribution via `space={number}` or `space="between" | "around" | "evenly"`
|
|
82
|
-
- vertical alignment of children via
|
|
82
|
+
- vertical alignment of children via
|
|
83
|
+
`alignItems="flex-start" | "flex-end" | "center" | "stretch" | "baseline"`
|
|
83
84
|
- wrapping via `wrap` and row spacing via `verticalSpace`
|
|
84
85
|
|
|
85
86
|
:information_source: Check `Inline` in
|
|
@@ -139,6 +140,24 @@ Distribute items evenly. Items have equal space around them
|
|
|
139
140
|
|
|
140
141
|
<img src="./images/layout/inline-evenly.svg" />
|
|
141
142
|
|
|
143
|
+
### nesting
|
|
144
|
+
|
|
145
|
+
Nest `Inline` components to compose richer rows. A common pattern groups a leading icon and label on the left
|
|
146
|
+
with a value on the right via `space="between"`:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Inline space="between" alignItems="center">
|
|
150
|
+
<Inline space={8} alignItems="center">
|
|
151
|
+
<IconTruckRegular size={24} color={skinVars.colors.neutralHigh} />
|
|
152
|
+
<Text2 regular>Envío:</Text2>
|
|
153
|
+
</Inline>
|
|
154
|
+
<Text2 regular>Mañana, gratis</Text2>
|
|
155
|
+
</Inline>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The outer `Inline` distributes the two groups to opposite ends; the inner `Inline` keeps the icon tightly
|
|
159
|
+
grouped with its label at a fixed gap.
|
|
160
|
+
|
|
142
161
|
## Align
|
|
143
162
|
|
|
144
163
|
Positions its children within a container using CSS grid alignment. Useful for centering content or placing it
|
package/doc/llms.md
CHANGED
|
@@ -15,6 +15,17 @@ This file is the main entry point. All docs live at:
|
|
|
15
15
|
If you cannot find a documentation file in `node_modules`, fetch the equivalent file from the GitHub
|
|
16
16
|
repository at `https://github.com/Telefonica/mistica-web/blob/master/doc/<filename>`.
|
|
17
17
|
|
|
18
|
+
## Source code
|
|
19
|
+
|
|
20
|
+
Source is available at `node_modules/@telefonica/mistica/src/` (fallback:
|
|
21
|
+
`https://github.com/Telefonica/mistica-web/tree/master/src`). Use `src/index.tsx` to map imports to files.
|
|
22
|
+
|
|
23
|
+
Read source only when you need to understand internal behavior that docs and types don't cover — for example
|
|
24
|
+
debugging layout/CSS issues (`*.css.ts` files), understanding event handling, or authoring a custom skin (read
|
|
25
|
+
a real skin in `src/skins/` to see canonical token patterns). Normally you shouldn't read source for
|
|
26
|
+
greenfield UI work — the docs already cover that, and reading source tends to pull toward low-level APIs when
|
|
27
|
+
a documented composite component would be simpler.
|
|
28
|
+
|
|
18
29
|
## Critical Rules
|
|
19
30
|
|
|
20
31
|
1. **NEVER hardcode colors in app/component UI code.** Always use `skinVars.colors.*` design tokens from
|
|
@@ -43,6 +54,11 @@ repository at `https://github.com/Telefonica/mistica-web/blob/master/doc/<filena
|
|
|
43
54
|
```tsx
|
|
44
55
|
<style>{`body { background-color: ${skinVars.colors.background}; }`}</style>
|
|
45
56
|
```
|
|
57
|
+
11. **Re-apply these rules during debugging, reviewing, and fixing — not just while writing new code.**
|
|
58
|
+
TypeScript errors, visual mismatches, and "I just need this to work" pressure are not exceptions. If you
|
|
59
|
+
are about to add `style={{...}}` to a `<div>`, a hex literal, a manual `font-size`, a `margin: auto` /
|
|
60
|
+
`justify-content: center` workaround, or any other escape hatch inside Mistica code, stop and find the
|
|
61
|
+
primitive first — the rule you need is already above.
|
|
46
62
|
|
|
47
63
|
## Install
|
|
48
64
|
|
|
@@ -313,6 +329,7 @@ After reading the minimum set, read any further files that apply to your specifi
|
|
|
313
329
|
| **Testing (read if you have to implement tests)** | `doc/testing.md` |
|
|
314
330
|
| **Migrating from older versions** | `doc/migration-guide.md` |
|
|
315
331
|
| **Optimizing bundle size with lottie** | `doc/lottie.md` |
|
|
332
|
+
| **Implementing a Figma design via Figma MCP** | `doc/figma-mcp.md` |
|
|
316
333
|
|
|
317
334
|
## Docs reference
|
|
318
335
|
|
|
@@ -336,3 +353,4 @@ After reading the minimum set, read any further files that apply to your specifi
|
|
|
336
353
|
- [Testing](./testing.md): NODE_ENV, unit tests, acceptance tests, isRunningAcceptanceTest
|
|
337
354
|
- [Lottie](./lottie.md): optimizing bundle size with lottie-web light build
|
|
338
355
|
- [Migration guide](./migration-guide.md): cards ecosystem migration (v16), v12 to v13 migration
|
|
356
|
+
- [Figma MCP](./figma-mcp.md): mandatory translation rules when implementing from Figma MCP output.
|
package/doc/patterns.md
CHANGED
|
@@ -2,19 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Critical rules
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
2. **NEVER use raw `<div>` for layout.** Use `Box`, `Stack`, `Inline`, `ResponsiveLayout`, `GridLayout`,
|
|
8
|
-
`Grid`.
|
|
9
|
-
3. **NEVER set font sizes manually.** Use text components (`Text1`-`Text10`, `Title1`-`Title4`). If those
|
|
10
|
-
don't cover your necessities you can set custom sizes with `Text` component.
|
|
11
|
-
4. **NEVER set border radius manually.** Use `skinVars.borderRadii.*` or components that handle it (`Boxed`,
|
|
12
|
-
cards, etc.). For theme-level visual customization without a dedicated component prop, use a custom skin.
|
|
13
|
-
5. **Always wrap your app** with `ThemeContextProvider` and import `@telefonica/mistica/css/mistica.css`.
|
|
14
|
-
6. **Always namespace React hooks**: `React.useState`, `React.useEffect`, `React.useRef`, etc.
|
|
15
|
-
7. **Add `'use client';`** directive to client components when using Next.js app router.
|
|
16
|
-
8. **Set `font-family` and `body` background color.** See [llms.md](./llms.md) rules 9–10 and
|
|
17
|
-
[fonts.md](./fonts.md) for the per-skin font table, `@font-face` setup, and the `GlobalStyles` pattern.
|
|
5
|
+
See [Critical Rules in `llms.md`](./llms.md#critical-rules) — the single source of truth. These rules apply
|
|
6
|
+
throughout this document.
|
|
18
7
|
|
|
19
8
|
## Page layout composition
|
|
20
9
|
|
|
@@ -501,10 +490,10 @@ return (
|
|
|
501
490
|
<ResponsiveLayout>
|
|
502
491
|
<Stack space={24}>
|
|
503
492
|
<Stepper currentIndex={currentStep} steps={['Personal', 'Address', 'Payment', 'Confirm']} />
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
493
|
+
{currentStep === 0 && <PersonalInfoForm />}
|
|
494
|
+
{currentStep === 1 && <AddressForm />}
|
|
495
|
+
{currentStep === 2 && <PaymentForm />}
|
|
496
|
+
{currentStep === 3 && <ConfirmationScreen />}
|
|
508
497
|
</Stack>
|
|
509
498
|
</ResponsiveLayout>
|
|
510
499
|
</Stack>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telefonica/mistica",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.62.0-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
"dist-es/**",
|
|
15
15
|
"css/**",
|
|
16
16
|
"doc/**",
|
|
17
|
+
"src/**",
|
|
18
|
+
"!src/generated/**",
|
|
19
|
+
"!src/**/__tests__/**",
|
|
20
|
+
"!src/**/__acceptance_tests__/**",
|
|
21
|
+
"!src/**/__screenshot_tests__/**",
|
|
22
|
+
"!src/**/__type_tests__/**",
|
|
23
|
+
"!src/**/__stories__/**",
|
|
24
|
+
"!src/**/__private_stories__/**",
|
|
25
|
+
"!src/**/*-test.ts",
|
|
26
|
+
"!src/**/*-test.tsx",
|
|
27
|
+
"!src/**/*-story.ts",
|
|
28
|
+
"!src/**/*-story.tsx",
|
|
17
29
|
"community.d.ts",
|
|
18
30
|
"community.js"
|
|
19
31
|
],
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {style} from '@vanilla-extract/css';
|
|
2
|
+
import * as mq from './media-queries.css';
|
|
3
|
+
import {vars} from './skins/skin-contract.css';
|
|
4
|
+
import {sprinkles} from './sprinkles.css';
|
|
5
|
+
|
|
6
|
+
export const itemContent = sprinkles({
|
|
7
|
+
width: '100%',
|
|
8
|
+
border: 'none',
|
|
9
|
+
background: 'transparent',
|
|
10
|
+
display: 'block',
|
|
11
|
+
height: '100%',
|
|
12
|
+
padding: 0,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const boxed = style({});
|
|
16
|
+
|
|
17
|
+
const boxedTouchableBorderRadiusStyles = {
|
|
18
|
+
[`${boxed} &:active`]: {
|
|
19
|
+
// needed because we can't use overflow: hidden on the boxed container for the focus ring to be visible
|
|
20
|
+
borderRadius: `calc(${vars.borderRadii.container} - 1px)`,
|
|
21
|
+
},
|
|
22
|
+
[`${boxed} &:hover`]: {
|
|
23
|
+
// needed because we can't use overflow: hidden on the boxed container for the focus ring to be visible
|
|
24
|
+
borderRadius: `calc(${vars.borderRadii.container} - 1px)`,
|
|
25
|
+
},
|
|
26
|
+
[`${boxed} &[aria-expanded="true"]`]: {
|
|
27
|
+
borderBottomLeftRadius: 0,
|
|
28
|
+
borderBottomRightRadius: 0,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const touchableBackground = style({
|
|
33
|
+
transition: 'background-color 0.1s ease-in-out',
|
|
34
|
+
':active': {
|
|
35
|
+
background: vars.colors.backgroundContainerPressed,
|
|
36
|
+
},
|
|
37
|
+
'@media': {
|
|
38
|
+
[mq.supportsHover]: {
|
|
39
|
+
':hover': {
|
|
40
|
+
background: vars.colors.backgroundContainerHover,
|
|
41
|
+
},
|
|
42
|
+
':active': {
|
|
43
|
+
background: vars.colors.backgroundContainerPressed,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
[mq.touchableOnly]: {
|
|
47
|
+
transition: 'none',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
selectors: boxedTouchableBorderRadiusStyles,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const touchableBackgroundOverBrand = style({
|
|
54
|
+
transition: 'background-color 0.1s ease-in-out',
|
|
55
|
+
':active': {
|
|
56
|
+
background: vars.colors.backgroundContainerBrandPressed,
|
|
57
|
+
},
|
|
58
|
+
'@media': {
|
|
59
|
+
[mq.supportsHover]: {
|
|
60
|
+
':hover': {
|
|
61
|
+
background: vars.colors.backgroundContainerBrandHover,
|
|
62
|
+
},
|
|
63
|
+
':active': {
|
|
64
|
+
background: vars.colors.backgroundContainerBrandPressed,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
[mq.touchableOnly]: {
|
|
68
|
+
transition: 'none',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
selectors: boxedTouchableBorderRadiusStyles,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const rightContentContainer = style({
|
|
75
|
+
height: '100%',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export const chevronContainer = style({
|
|
79
|
+
height: '100%',
|
|
80
|
+
display: 'flex',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const panelContainer = style({
|
|
85
|
+
display: 'grid',
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const panelTransitionClasses = {
|
|
89
|
+
enter: style({
|
|
90
|
+
gridTemplateRows: '0fr',
|
|
91
|
+
}),
|
|
92
|
+
enterActive: style({
|
|
93
|
+
gridTemplateRows: '1fr',
|
|
94
|
+
transition: 'grid-template-rows 0.4s',
|
|
95
|
+
'@media': {
|
|
96
|
+
['(prefers-reduced-motion)']: {
|
|
97
|
+
transition: 'none',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
exit: style({
|
|
102
|
+
gridTemplateRows: '1fr',
|
|
103
|
+
}),
|
|
104
|
+
exitActive: style({
|
|
105
|
+
gridTemplateRows: '0fr',
|
|
106
|
+
transition: 'grid-template-rows 0.4s',
|
|
107
|
+
'@media': {
|
|
108
|
+
['(prefers-reduced-motion)']: {
|
|
109
|
+
transition: 'none',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const panel = style({
|
|
116
|
+
overflow: 'hidden',
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export const accordionItem = sprinkles({
|
|
120
|
+
width: '100%',
|
|
121
|
+
});
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import {Content as HeaderContent} from './list';
|
|
4
|
+
import IconChevron from './icons/icon-chevron';
|
|
5
|
+
import Box from './box';
|
|
6
|
+
import * as styles from './accordion.css';
|
|
7
|
+
import Stack from './stack';
|
|
8
|
+
import {BaseTouchable} from './touchable';
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
import {vars as skinVars} from './skins/skin-contract.css';
|
|
11
|
+
import {getPrefixedDataAttributes} from './utils/dom';
|
|
12
|
+
import Divider from './divider';
|
|
13
|
+
import {InternalBoxed} from './boxed';
|
|
14
|
+
import {useThemeVariant} from './theme-variant-context';
|
|
15
|
+
import {CSSTransition} from 'react-transition-group';
|
|
16
|
+
import {isRunningAcceptanceTest} from './utils/platform';
|
|
17
|
+
import Inline from './inline';
|
|
18
|
+
|
|
19
|
+
import type {ExclusifyUnion} from './utils/utility-types';
|
|
20
|
+
import type {DataAttributes, TrackingEvent} from './utils/types';
|
|
21
|
+
import type {TouchableElement} from './touchable';
|
|
22
|
+
|
|
23
|
+
const ACCORDION_TRANSITION_DURATION_IN_MS = 400;
|
|
24
|
+
|
|
25
|
+
type AccordionContextType = {
|
|
26
|
+
index: ReadonlyArray<number>;
|
|
27
|
+
toggle: (item: number) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const AccordionContext = React.createContext<AccordionContextType>({
|
|
31
|
+
index: [],
|
|
32
|
+
toggle: () => {},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const useAccordionContext = (): AccordionContextType => React.useContext(AccordionContext);
|
|
36
|
+
|
|
37
|
+
interface AccordionItemContentProps {
|
|
38
|
+
children?: void;
|
|
39
|
+
title: string;
|
|
40
|
+
titleAs?: string;
|
|
41
|
+
subtitle?: string;
|
|
42
|
+
asset?: React.ReactNode;
|
|
43
|
+
content: React.ReactNode;
|
|
44
|
+
dataAttributes?: DataAttributes;
|
|
45
|
+
trackingEvent?: TrackingEvent | ReadonlyArray<TrackingEvent>;
|
|
46
|
+
role?: string;
|
|
47
|
+
detail?: string;
|
|
48
|
+
right?: React.ReactNode;
|
|
49
|
+
'aria-label'?: string;
|
|
50
|
+
'aria-labelledby'?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const useAccordionState = ({
|
|
54
|
+
value,
|
|
55
|
+
defaultValue,
|
|
56
|
+
onChange,
|
|
57
|
+
singleOpen,
|
|
58
|
+
}: {
|
|
59
|
+
value?: number | ReadonlyArray<number>;
|
|
60
|
+
defaultValue?: number | ReadonlyArray<number>;
|
|
61
|
+
onChange?: (item: number, value: boolean) => void;
|
|
62
|
+
singleOpen?: boolean;
|
|
63
|
+
}): [ReadonlyArray<number>, (value: number) => void] => {
|
|
64
|
+
const isControlledByParent = value !== undefined;
|
|
65
|
+
|
|
66
|
+
const getValueAsList = (value?: number | ReadonlyArray<number>) => {
|
|
67
|
+
return value === undefined ? [] : typeof value === 'number' ? [value] : value;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const [index, setIndex] = React.useState<ReadonlyArray<number>>(getValueAsList(defaultValue));
|
|
71
|
+
|
|
72
|
+
React.useEffect(() => {
|
|
73
|
+
if (index.length > 1 && singleOpen) {
|
|
74
|
+
const newIndex = [...index];
|
|
75
|
+
newIndex.splice(1);
|
|
76
|
+
setIndex(newIndex);
|
|
77
|
+
}
|
|
78
|
+
}, [singleOpen, index]);
|
|
79
|
+
|
|
80
|
+
const updateIndexOnToggle = (item: number, index?: ReadonlyArray<number>) => {
|
|
81
|
+
if (!index) {
|
|
82
|
+
return [item];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const valueIndex = index.indexOf(item);
|
|
86
|
+
let newIndex = [...index];
|
|
87
|
+
if (valueIndex === -1) {
|
|
88
|
+
if (singleOpen) {
|
|
89
|
+
newIndex = [item];
|
|
90
|
+
} else {
|
|
91
|
+
newIndex.push(item);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
newIndex.splice(valueIndex, 1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return newIndex;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const toggle = (item: number) => {
|
|
101
|
+
if (!isControlledByParent) {
|
|
102
|
+
setIndex(updateIndexOnToggle(item, index));
|
|
103
|
+
}
|
|
104
|
+
if (onChange) {
|
|
105
|
+
const currentItemValue = (isControlledByParent ? getValueAsList(value) : index).includes(item);
|
|
106
|
+
onChange(item, !currentItemValue);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (isControlledByParent) {
|
|
111
|
+
return [getValueAsList(value), toggle];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return [index, toggle];
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const getAccordionItemIndex = (element: Element | null) => {
|
|
118
|
+
const accordionAncestor = element?.closest('[data-accordion]');
|
|
119
|
+
if (!accordionAncestor) return undefined;
|
|
120
|
+
|
|
121
|
+
return Array.from(accordionAncestor.querySelectorAll('[data-accordion-item]'))
|
|
122
|
+
.filter((e) => e.closest('[data-accordion]') === accordionAncestor)
|
|
123
|
+
.findIndex((e) => e === element);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const getAssetText = (asset: React.ReactNode): string => {
|
|
127
|
+
if (!React.isValidElement(asset)) return '';
|
|
128
|
+
|
|
129
|
+
const props = asset.props as {alt?: unknown; 'aria-label'?: unknown};
|
|
130
|
+
|
|
131
|
+
if (typeof props.alt === 'string' && props.alt.trim()) {
|
|
132
|
+
return props.alt.trim();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (typeof props['aria-label'] === 'string' && props['aria-label'].trim()) {
|
|
136
|
+
return props['aria-label'].trim();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return '';
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const AccordionItemContent = React.forwardRef<TouchableElement, AccordionItemContentProps>(
|
|
143
|
+
(
|
|
144
|
+
{
|
|
145
|
+
content,
|
|
146
|
+
dataAttributes,
|
|
147
|
+
trackingEvent,
|
|
148
|
+
right,
|
|
149
|
+
'aria-label': ariaLabel,
|
|
150
|
+
'aria-labelledby': ariaLabelledby,
|
|
151
|
+
...props
|
|
152
|
+
},
|
|
153
|
+
ref
|
|
154
|
+
) => {
|
|
155
|
+
const panelContainerRef = React.useRef<HTMLDivElement | null>(null);
|
|
156
|
+
const itemRef = React.useRef<HTMLDivElement | null>(null);
|
|
157
|
+
const {index, toggle} = useAccordionContext();
|
|
158
|
+
const variant = useThemeVariant();
|
|
159
|
+
const labelId = React.useId();
|
|
160
|
+
const panelId = React.useId();
|
|
161
|
+
|
|
162
|
+
const assetText = getAssetText(props.asset);
|
|
163
|
+
|
|
164
|
+
const computedAriaLabel = ariaLabel ?? [props.title, assetText].filter(Boolean).join(' ');
|
|
165
|
+
|
|
166
|
+
const [itemIndex, setItemIndex] = React.useState<number>();
|
|
167
|
+
const isOpen = itemIndex !== undefined && index?.includes(itemIndex);
|
|
168
|
+
|
|
169
|
+
React.useEffect(() => {
|
|
170
|
+
setItemIndex(getAccordionItemIndex(itemRef.current));
|
|
171
|
+
}, []);
|
|
172
|
+
|
|
173
|
+
const iconColor = {
|
|
174
|
+
default: isOpen ? skinVars.colors.chevronIndicator : skinVars.colors.chevronIndicator,
|
|
175
|
+
alternative: isOpen ? skinVars.colors.chevronIndicator : skinVars.colors.chevronIndicator,
|
|
176
|
+
brand: skinVars.colors.textSecondaryBrand,
|
|
177
|
+
media: skinVars.colors.textSecondaryBrand,
|
|
178
|
+
negative: skinVars.colors.textSecondaryNegative,
|
|
179
|
+
}[variant];
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<div ref={itemRef} {...getPrefixedDataAttributes({...dataAttributes, 'accordion-item': true})}>
|
|
183
|
+
<BaseTouchable
|
|
184
|
+
ref={ref}
|
|
185
|
+
className={classNames(
|
|
186
|
+
styles.itemContent,
|
|
187
|
+
variant === 'brand' || variant === 'media' || variant === 'negative'
|
|
188
|
+
? styles.touchableBackgroundOverBrand
|
|
189
|
+
: styles.touchableBackground
|
|
190
|
+
)}
|
|
191
|
+
onPress={() => {
|
|
192
|
+
if (itemIndex !== undefined) toggle(itemIndex);
|
|
193
|
+
}}
|
|
194
|
+
trackingEvent={trackingEvent}
|
|
195
|
+
aria-expanded={isOpen}
|
|
196
|
+
aria-controls={panelId}
|
|
197
|
+
aria-label={computedAriaLabel}
|
|
198
|
+
aria-labelledby={ariaLabelledby}
|
|
199
|
+
>
|
|
200
|
+
<Box paddingX={16}>
|
|
201
|
+
<HeaderContent
|
|
202
|
+
labelId={labelId}
|
|
203
|
+
{...props}
|
|
204
|
+
right={({centerY}) => (
|
|
205
|
+
<Inline
|
|
206
|
+
space={4}
|
|
207
|
+
alignItems={centerY ? 'center' : undefined}
|
|
208
|
+
className={styles.rightContentContainer}
|
|
209
|
+
>
|
|
210
|
+
{right}
|
|
211
|
+
<div className={styles.chevronContainer}>
|
|
212
|
+
<IconChevron
|
|
213
|
+
size={20}
|
|
214
|
+
transitionDuration={ACCORDION_TRANSITION_DURATION_IN_MS}
|
|
215
|
+
direction={isOpen ? 'up' : 'down'}
|
|
216
|
+
color={iconColor}
|
|
217
|
+
/>
|
|
218
|
+
</div>
|
|
219
|
+
</Inline>
|
|
220
|
+
)}
|
|
221
|
+
/>
|
|
222
|
+
</Box>
|
|
223
|
+
</BaseTouchable>
|
|
224
|
+
<CSSTransition
|
|
225
|
+
in={isOpen}
|
|
226
|
+
timeout={isRunningAcceptanceTest() ? 0 : ACCORDION_TRANSITION_DURATION_IN_MS}
|
|
227
|
+
nodeRef={panelContainerRef}
|
|
228
|
+
classNames={styles.panelTransitionClasses}
|
|
229
|
+
mountOnEnter
|
|
230
|
+
unmountOnExit
|
|
231
|
+
>
|
|
232
|
+
<div className={styles.panelContainer} ref={panelContainerRef}>
|
|
233
|
+
<div className={styles.panel} role="region" aria-labelledby={labelId} id={panelId}>
|
|
234
|
+
<Box paddingX={16} paddingBottom={16}>
|
|
235
|
+
{content}
|
|
236
|
+
</Box>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
</CSSTransition>
|
|
240
|
+
</div>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
export const AccordionItem = React.forwardRef<TouchableElement, AccordionItemContentProps>(
|
|
246
|
+
({dataAttributes, role, ...props}, ref) => (
|
|
247
|
+
<div role={role} className={styles.accordionItem}>
|
|
248
|
+
<AccordionItemContent
|
|
249
|
+
{...props}
|
|
250
|
+
ref={ref}
|
|
251
|
+
dataAttributes={{'component-name': 'AccordionItem', ...dataAttributes}}
|
|
252
|
+
/>
|
|
253
|
+
</div>
|
|
254
|
+
)
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
type AccordionBaseProps = {
|
|
258
|
+
children: React.ReactNode;
|
|
259
|
+
dataAttributes?: DataAttributes;
|
|
260
|
+
onChange?: (index: number, value: boolean) => void;
|
|
261
|
+
role?: string;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
type SingleOpenProps = {
|
|
265
|
+
singleOpen: true;
|
|
266
|
+
index?: number;
|
|
267
|
+
defaultIndex?: number;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
type MultipleOpenProps = {
|
|
271
|
+
singleOpen?: false;
|
|
272
|
+
index?: number | ReadonlyArray<number>;
|
|
273
|
+
defaultIndex?: number | ReadonlyArray<number>;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
type AccordionProps = AccordionBaseProps & ExclusifyUnion<SingleOpenProps | MultipleOpenProps>;
|
|
277
|
+
|
|
278
|
+
export const Accordion = ({
|
|
279
|
+
children,
|
|
280
|
+
dataAttributes,
|
|
281
|
+
index,
|
|
282
|
+
defaultIndex,
|
|
283
|
+
onChange,
|
|
284
|
+
singleOpen,
|
|
285
|
+
role,
|
|
286
|
+
}: AccordionProps): JSX.Element => {
|
|
287
|
+
const [indexList, toggle] = useAccordionState({
|
|
288
|
+
value: index,
|
|
289
|
+
defaultValue: defaultIndex,
|
|
290
|
+
onChange,
|
|
291
|
+
singleOpen,
|
|
292
|
+
});
|
|
293
|
+
const childrenContent = React.Children.toArray(children).filter(Boolean);
|
|
294
|
+
const lastIndex = childrenContent.length - 1;
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<AccordionContext.Provider value={{index: indexList, toggle}}>
|
|
298
|
+
<div
|
|
299
|
+
role={role}
|
|
300
|
+
{...getPrefixedDataAttributes({...dataAttributes, accordion: true}, 'Accordion')}
|
|
301
|
+
>
|
|
302
|
+
{childrenContent.map((child, index) => (
|
|
303
|
+
<React.Fragment key={index}>
|
|
304
|
+
{child}
|
|
305
|
+
{index < lastIndex && (
|
|
306
|
+
<Box paddingX={16}>
|
|
307
|
+
<Divider />
|
|
308
|
+
</Box>
|
|
309
|
+
)}
|
|
310
|
+
</React.Fragment>
|
|
311
|
+
))}
|
|
312
|
+
</div>
|
|
313
|
+
</AccordionContext.Provider>
|
|
314
|
+
);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
interface BoxedAccordionItemProps extends AccordionItemContentProps {
|
|
318
|
+
/**
|
|
319
|
+
* @deprecated Use `variant="brand"` instead.
|
|
320
|
+
*/
|
|
321
|
+
isInverse?: boolean;
|
|
322
|
+
variant?: 'default' | 'brand';
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export const BoxedAccordionItem = React.forwardRef<HTMLDivElement, BoxedAccordionItemProps>(
|
|
326
|
+
({dataAttributes, isInverse, variant, ...props}, ref) => (
|
|
327
|
+
<InternalBoxed
|
|
328
|
+
overflow="visible"
|
|
329
|
+
className={styles.boxed}
|
|
330
|
+
variant={variant ?? (isInverse ? 'brand' : 'default')}
|
|
331
|
+
ref={ref}
|
|
332
|
+
dataAttributes={{'component-name': 'BoxedAccordionItem', ...dataAttributes}}
|
|
333
|
+
>
|
|
334
|
+
<AccordionItemContent {...props} />
|
|
335
|
+
</InternalBoxed>
|
|
336
|
+
)
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
export const BoxedAccordion = ({
|
|
340
|
+
children,
|
|
341
|
+
dataAttributes,
|
|
342
|
+
index,
|
|
343
|
+
defaultIndex,
|
|
344
|
+
onChange,
|
|
345
|
+
singleOpen,
|
|
346
|
+
role,
|
|
347
|
+
}: AccordionProps): JSX.Element => {
|
|
348
|
+
const [indexList, toggle] = useAccordionState({
|
|
349
|
+
value: index,
|
|
350
|
+
defaultValue: defaultIndex,
|
|
351
|
+
onChange,
|
|
352
|
+
singleOpen,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
return (
|
|
356
|
+
<AccordionContext.Provider value={{index: indexList, toggle}}>
|
|
357
|
+
<Stack
|
|
358
|
+
space={16}
|
|
359
|
+
role={role}
|
|
360
|
+
dataAttributes={{'component-name': 'BoxedAccordion', accordion: true, ...dataAttributes}}
|
|
361
|
+
>
|
|
362
|
+
{children}
|
|
363
|
+
</Stack>
|
|
364
|
+
</AccordionContext.Provider>
|
|
365
|
+
);
|
|
366
|
+
};
|
package/src/align.css.ts
ADDED
package/src/align.tsx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {getPrefixedDataAttributes} from './utils/dom';
|
|
3
|
+
import * as styles from './align.css';
|
|
4
|
+
|
|
5
|
+
import type {DataAttributes} from './utils/types';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
x?: 'start' | 'center' | 'end';
|
|
9
|
+
y?: 'start' | 'center' | 'end';
|
|
10
|
+
width?: number | string;
|
|
11
|
+
height?: number | string;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
dataAttributes?: DataAttributes;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const Align = ({x = 'start', y = 'start', width, height, children, dataAttributes}: Props): JSX.Element => {
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
{...getPrefixedDataAttributes(dataAttributes, 'Align')}
|
|
20
|
+
className={styles.container}
|
|
21
|
+
style={{
|
|
22
|
+
placeItems: `${y} ${x}`,
|
|
23
|
+
...(width !== undefined ? {width} : {}),
|
|
24
|
+
...(height !== undefined ? {height} : {}),
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default Align;
|