playbook_ui 15.0.0.pre.alpha.PLAY2473rowhighlightfix10512 → 15.0.0.pre.alpha.PLAY2511playbookiconsupgrade10731
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +2 -0
- data/app/pb_kits/playbook/pb_card/_card.scss +12 -4
- data/app/pb_kits/playbook/pb_card/_card.tsx +3 -3
- data/app/pb_kits/playbook/pb_card/_card_mixin.scss +10 -0
- data/app/pb_kits/playbook/pb_card/docs/_card_highlight.html.erb +3 -0
- data/app/pb_kits/playbook/pb_card/docs/_card_highlight.jsx +8 -0
- data/app/pb_kits/playbook/pb_contact/_contact.tsx +5 -0
- data/app/pb_kits/playbook/pb_contact/contact.rb +4 -0
- data/app/pb_kits/playbook/pb_contact/contact.test.js +21 -1
- data/app/pb_kits/playbook/pb_contact/docs/_contact_default.html.erb +16 -1
- data/app/pb_kits/playbook/pb_contact/docs/_contact_default.jsx +15 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_default.md +5 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.html.erb +6 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.jsx +6 -0
- data/app/pb_kits/playbook/pb_icon_button/_icon_button.tsx +1 -0
- data/app/pb_kits/playbook/pb_icon_button/icon_button.html.erb +2 -1
- data/app/pb_kits/playbook/pb_nav/_item.tsx +19 -5
- data/app/pb_kits/playbook/pb_nav/item.html.erb +6 -2
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +3 -3
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +3 -3
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.html.erb +3 -3
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +3 -3
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +3 -3
- data/app/pb_kits/playbook/pb_pb_circle_chart/_pb_circle_chart.scss +3 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/_pb_circle_chart.tsx +62 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_block_content.html.erb +31 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_block_content.jsx +81 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_color_overrides.html.erb +25 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_color_overrides.jsx +40 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_color_overrides.md +5 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_custom_tooltip.html.erb +27 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_custom_tooltip.jsx +39 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_custom_tooltip.md +5 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_legend_position.html.erb +93 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_legend_position.jsx +131 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_legend_position.md +14 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_labels.html.erb +42 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_labels.jsx +58 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_legend.html.erb +24 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_legend.jsx +38 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.html.erb +22 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.jsx +33 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_inner_sizes.html.erb +118 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_inner_sizes.jsx +144 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_live_data.jsx +60 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_rounded.html.erb +24 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_rounded.jsx +42 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_with_title.html.erb +38 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_with_title.jsx +52 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/example.yml +29 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/index.js +11 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/pbCircleChartTheme.ts +88 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/pb_circle_chart.html.erb +1 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/pb_circle_chart.rb +28 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/pb_circle_chart.test.jsx +51 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.html.erb +2 -2
- data/app/pb_kits/playbook/pb_section_separator/_section_separator.scss +13 -5
- data/app/pb_kits/playbook/pb_section_separator/docs/_section_separator_children.html.erb +23 -0
- data/app/pb_kits/playbook/pb_section_separator/docs/_section_separator_children.jsx +45 -7
- data/app/pb_kits/playbook/pb_section_separator/section_separator.html.erb +4 -1
- data/app/pb_kits/playbook/pb_section_separator/section_separator.test.js +165 -0
- data/app/pb_kits/playbook/pb_timestamp/_timestamp.tsx +24 -8
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_align.html.erb +0 -10
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_align.jsx +0 -9
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_align.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_default.html.erb +3 -17
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_default.jsx +0 -15
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_default.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.html.erb +0 -2
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.jsx +0 -2
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.md +5 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_current_year.html.erb +12 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_current_year.jsx +25 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_date.html.erb +4 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_date.jsx +17 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_date.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_time.html.erb +18 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_time.jsx +44 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_show_time.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_timezones.html.erb +0 -14
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_timezones.jsx +0 -14
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_timezones.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.html.erb +0 -4
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.jsx +0 -4
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated.jsx +0 -1
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated.md +5 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_current_year.html.erb +16 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_current_year.jsx +30 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_date.html.erb +16 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_date.jsx +30 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_date.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_time.html.erb +26 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_time.jsx +41 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_updated_show_time.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/example.yml +18 -6
- data/app/pb_kits/playbook/pb_timestamp/docs/index.js +6 -0
- data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +29 -7
- data/app/pb_kits/playbook/pb_timestamp/timestamp.test.js +69 -4
- data/dist/chunks/{_line_graph-BBny-YYZ.js → _line_graph-DeH7NK-i.js} +1 -1
- data/dist/chunks/{_typeahead-CeyJ6-GF.js → _typeahead-CCGp0OQe.js} +2 -2
- data/dist/chunks/{_weekday_stacked-BZw0f9oB.js → _weekday_stacked-DhJzB115.js} +3 -3
- data/dist/chunks/componentRegistry-DzmmLR2x.js +1 -0
- data/dist/chunks/{lib-BTs5acfO.js → lib-QZuu1ltS.js} +1 -1
- data/dist/chunks/{pb_form_validation-CKkaQFX3.js → pb_form_validation-CleM960_.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +6 -0
- data/dist/playbook-doc.js +2 -2
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/engine.rb +0 -1
- data/lib/playbook/forms/builder/form_field_builder.rb +28 -1
- data/lib/playbook/kit_base.rb +23 -2
- data/lib/playbook/version.rb +1 -1
- metadata +70 -27
- data/app/pb_kits/playbook/pb_timestamp/docs/_time_stamp_default.md +0 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e0fa8d212d2700d1331521287bd3d7480759f1e08851d2533757ee6ee74b44af
         | 
| 4 | 
            +
              data.tar.gz: 73202aa6795a41a3bf3bf497aa1440ee508b57b503e68d6046ea28189f9b3650
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e2fa036695412b196e097f9348e175b7cfc5cce92241fab063ae0432e29badd97b324fe450fb0fc158bab2e387f73271b4f186112af830fa65b6b2d9be7bb5e9
         | 
| 7 | 
            +
              data.tar.gz: 48778a9daa9da274e8778e17c161b3907140be2279be8ed1319fb29ee8c5eba0ddfed0a218804e173a8e0b714fdcf753744368e836c4c81fd2f0c39c4aa0b481
         | 
| @@ -1,5 +1,6 @@ | |
| 1 1 |  | 
| 2 2 |  | 
| 3 | 
            +
             | 
| 3 4 | 
             
            @import 'pb_advanced_table/advanced_table';
         | 
| 4 5 | 
             
            @import 'pb_avatar/avatar';
         | 
| 5 6 | 
             
            @import 'pb_background/background';
         | 
| @@ -109,6 +110,7 @@ | |
| 109 110 | 
             
            @import 'pb_weekday_stacked/weekday_stacked';
         | 
| 110 111 | 
             
            @import 'pb_empty_state/empty_state';
         | 
| 111 112 | 
             
            @import 'pb_pb_bar_graph/pb_bar_graph';
         | 
| 113 | 
            +
            @import 'pb_pb_circle_chart/pb_circle_chart';
         | 
| 112 114 | 
             
            @import 'utilities/mixins';
         | 
| 113 115 | 
             
            @import 'utilities/spacing';
         | 
| 114 116 | 
             
            @import 'utilities/cursor';
         | 
| @@ -20,7 +20,7 @@ | |
| 20 20 | 
             
            // Dark mode
         | 
| 21 21 | 
             
            .pb_card_kit.dark {
         | 
| 22 22 | 
             
              @include pb_card_dark;
         | 
| 23 | 
            -
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
              &.pb_card_kit_selected {
         | 
| 25 25 | 
             
                @include pb_card_selected_dark;
         | 
| 26 26 | 
             
              }
         | 
| @@ -33,7 +33,8 @@ | |
| 33 33 |  | 
| 34 34 | 
             
            // Highlight styles
         | 
| 35 35 | 
             
            .pb_card_kit_highlight_top,
         | 
| 36 | 
            -
            .pb_card_kit_highlight_side | 
| 36 | 
            +
            .pb_card_kit_highlight_side,
         | 
| 37 | 
            +
            .pb_card_kit_highlight_right_side {
         | 
| 37 38 | 
             
              overflow: hidden;
         | 
| 38 39 | 
             
            }
         | 
| 39 40 |  | 
| @@ -52,13 +53,20 @@ | |
| 52 53 | 
             
              }
         | 
| 53 54 | 
             
            }
         | 
| 54 55 |  | 
| 55 | 
            -
            // Highlight side variants | 
| 56 | 
            +
            // Highlight side variants
         | 
| 56 57 | 
             
            @each $color_name, $color_value in $pb_card_highlight_colors {
         | 
| 57 58 | 
             
              .pb_card_kit_highlight_side.pb_card_kit_highlight_#{$color_name}::before {
         | 
| 58 59 | 
             
                @include pb_card_highlight($pb_card_highlight_size, 100%, $color_value);
         | 
| 59 60 | 
             
              }
         | 
| 60 61 | 
             
            }
         | 
| 61 62 |  | 
| 63 | 
            +
            // Highlight side right variants
         | 
| 64 | 
            +
            @each $color_name, $color_value in $pb_card_highlight_colors {
         | 
| 65 | 
            +
              .pb_card_kit_highlight_right_side.pb_card_kit_highlight_#{$color_name}::before {
         | 
| 66 | 
            +
                @include pb_card_right_highlight($pb_card_highlight_size, 100%, $color_value);
         | 
| 67 | 
            +
              }
         | 
| 68 | 
            +
            }
         | 
| 69 | 
            +
             | 
| 62 70 | 
             
            // Card Header
         | 
| 63 71 | 
             
            .pb_card_header_kit {
         | 
| 64 72 | 
             
              flex-grow: 0;
         | 
| @@ -68,7 +76,7 @@ | |
| 68 76 | 
             
              padding: $space_sm;
         | 
| 69 77 | 
             
              border: 0;
         | 
| 70 78 | 
             
              border-radius: $pb_card_header_border_radius $pb_card_header_border_radius 0px 0px;
         | 
| 71 | 
            -
             | 
| 79 | 
            +
             | 
| 72 80 | 
             
              // Inherit border radius from parent card
         | 
| 73 81 | 
             
              .pb_card_kit_border_radius_xs & {
         | 
| 74 82 | 
             
                border-radius: $border_radius_xs $border_radius_xs 0px 0px;
         | 
| @@ -26,7 +26,7 @@ type CardPropTypes = { | |
| 26 26 | 
             
              dragHandle?: boolean,
         | 
| 27 27 | 
             
              htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
         | 
| 28 28 | 
             
              highlight?: {
         | 
| 29 | 
            -
                position?: "side" | "top",
         | 
| 29 | 
            +
                position?: "side" | "right_side" | "top",
         | 
| 30 30 | 
             
                color?: string,
         | 
| 31 31 | 
             
              },
         | 
| 32 32 | 
             
              id?: string,
         | 
| @@ -56,7 +56,7 @@ const Header = (props: CardHeaderProps) => { | |
| 56 56 | 
             
              const { children, className, headerColor = 'category_1', headerColorStriped = false } = props
         | 
| 57 57 | 
             
              const headerColorCSS = `pb_card_header_kit_${headerColor}`
         | 
| 58 58 | 
             
              const headerStripedCSS = headerColorStriped ? `pb_card_header_kit_${headerColor}_striped` : ''
         | 
| 59 | 
            -
             | 
| 59 | 
            +
             | 
| 60 60 | 
             
              const headerCSS = classnames(
         | 
| 61 61 | 
             
                'pb_card_header_kit',
         | 
| 62 62 | 
             
                headerColorCSS,
         | 
| @@ -108,7 +108,7 @@ const Card = (props: CardPropTypes): React.ReactElement => { | |
| 108 108 | 
             
              const borderRadiusCSS = borderRadius !== 'md' ? `pb_card_kit_border_radius_${borderRadius}` : ''
         | 
| 109 109 | 
             
              const highlightPositionCSS = highlight.position ? `pb_card_kit_highlight_${highlight.position}` : ''
         | 
| 110 110 | 
             
              const highlightColorCSS = highlight.color ? `pb_card_kit_highlight_${highlight.color}` : ''
         | 
| 111 | 
            -
             | 
| 111 | 
            +
             | 
| 112 112 | 
             
              const cardCss = classnames(
         | 
| 113 113 | 
             
                'pb_card_kit', // Base class
         | 
| 114 114 | 
             
                selectedCSS,
         | 
| @@ -87,6 +87,16 @@ $pb_card_header_colors: map-merge(map-merge(map-merge($product_colors, $addition | |
| 87 87 | 
             
              background: $background;
         | 
| 88 88 | 
             
            }
         | 
| 89 89 |  | 
| 90 | 
            +
            @mixin pb_card_right_highlight($width, $height, $background){
         | 
| 91 | 
            +
              content: "";
         | 
| 92 | 
            +
              position: absolute;
         | 
| 93 | 
            +
              top: 0;
         | 
| 94 | 
            +
              right: 0;
         | 
| 95 | 
            +
              width: $width;
         | 
| 96 | 
            +
              height: $height;
         | 
| 97 | 
            +
              background: $background;
         | 
| 98 | 
            +
            }
         | 
| 99 | 
            +
             | 
| 90 100 | 
             
            @mixin pb_card_header_color($header_color) {
         | 
| 91 101 | 
             
              background: $header_color;
         | 
| 92 102 | 
             
            }
         | 
| @@ -4,6 +4,9 @@ | |
| 4 4 | 
             
            <%= pb_rails("card", props: {highlight: {position: "top", color:"warning"}, margin_bottom: "sm"}) do %>
         | 
| 5 5 | 
             
              Top Position & Warning Color
         | 
| 6 6 | 
             
            <% end %>
         | 
| 7 | 
            +
            <%= pb_rails("card", props: {highlight: {position: "right_side", color:"product_5_highlight"}, margin_bottom: "sm"}) do %>
         | 
| 8 | 
            +
              Right Side Position & Product 5 Highlight Color
         | 
| 9 | 
            +
            <% end %>
         | 
| 7 10 | 
             
            <%= pb_rails("card", props: {highlight: {position: "side", color:"category_2"}, margin_bottom: "sm"}) do %>
         | 
| 8 11 | 
             
              Side Position & Category 2 Color
         | 
| 9 12 | 
             
            <% end %>
         | 
| @@ -21,6 +21,14 @@ const CardHighlight = (props) => { | |
| 21 21 | 
             
                    {'Top Position & Warning Color'}
         | 
| 22 22 | 
             
                  </Card>
         | 
| 23 23 |  | 
| 24 | 
            +
                  <Card
         | 
| 25 | 
            +
                      {...props}
         | 
| 26 | 
            +
                      highlight={{ position: 'right_side', color: 'product_5_highlight' }}
         | 
| 27 | 
            +
                      marginBottom="sm"
         | 
| 28 | 
            +
                  >
         | 
| 29 | 
            +
                    {'Right Side Position & Product 5 Highlight Color'}
         | 
| 30 | 
            +
                  </Card>
         | 
| 31 | 
            +
             | 
| 24 32 | 
             
                  <Card
         | 
| 25 33 | 
             
                      {...props}
         | 
| 26 34 | 
             
                      highlight={{ position: 'side', color: 'category_2' }}
         | 
| @@ -17,6 +17,7 @@ const contactTypeMap: { [key: string]: string } = { | |
| 17 17 | 
             
              'work': 'phone-office',
         | 
| 18 18 | 
             
              'work-cell': 'phone-laptop',
         | 
| 19 19 | 
             
              'wrong-phone': 'phone-slash',
         | 
| 20 | 
            +
              'international': 'globe',
         | 
| 20 21 | 
             
            }
         | 
| 21 22 |  | 
| 22 23 | 
             
            const envelopeIcon = getAllIcons()["envelope"].icon as unknown as { [key: string]: SVGElement }
         | 
| @@ -24,6 +25,10 @@ const envelopeIcon = getAllIcons()["envelope"].icon as unknown as { [key: string | |
| 24 25 | 
             
            const formatContact = (contactString: string, contactType: string) => {
         | 
| 25 26 | 
             
              if (contactType === 'email') return contactString
         | 
| 26 27 |  | 
| 28 | 
            +
              // International phone numbers are unformatted
         | 
| 29 | 
            +
              if (contactType === 'international') return contactString
         | 
| 30 | 
            +
              
         | 
| 31 | 
            +
              // Format US numbers
         | 
| 27 32 | 
             
              const cleaned = contactString.replace(/\D/g, '')
         | 
| 28 33 | 
             
              const phoneNumber = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/)
         | 
| 29 34 |  | 
| @@ -29,6 +29,8 @@ module Playbook | |
| 29 29 | 
             
                      "phone-slash"
         | 
| 30 30 | 
             
                    when "extension"
         | 
| 31 31 | 
             
                      "phone-plus"
         | 
| 32 | 
            +
                    when "international"
         | 
| 33 | 
            +
                      "globe"
         | 
| 32 34 | 
             
                    else # "unknown" || "other"
         | 
| 33 35 | 
             
                      "phone"
         | 
| 34 36 | 
             
                    end
         | 
| @@ -39,6 +41,8 @@ module Playbook | |
| 39 41 | 
             
                      contact_value
         | 
| 40 42 | 
             
                    elsif contact_type == "extension" && contact_value.match(/^\d{4}$/)
         | 
| 41 43 | 
             
                      contact_value
         | 
| 44 | 
            +
                    elsif contact_type == "international"
         | 
| 45 | 
            +
                      contact_value
         | 
| 42 46 | 
             
                    else
         | 
| 43 47 | 
             
                      number_to_phone(formatted_value, area_code: true)
         | 
| 44 48 | 
             
                    end
         | 
| @@ -66,6 +66,12 @@ test('returns correct icon', () => { | |
| 66 66 | 
             
                      contactValue="1234"
         | 
| 67 67 | 
             
                      data={{ testid: 'test-extension' }}
         | 
| 68 68 | 
             
                  />
         | 
| 69 | 
            +
                  <Contact
         | 
| 70 | 
            +
                      contactDetail="International"
         | 
| 71 | 
            +
                      contactType="international"
         | 
| 72 | 
            +
                      contactValue="+44 20 7946 0958"
         | 
| 73 | 
            +
                      data={{ testid: 'test-international' }}
         | 
| 74 | 
            +
                  />
         | 
| 69 75 | 
             
                  <Contact
         | 
| 70 76 | 
             
                      contactDetail=""
         | 
| 71 77 | 
             
                      contactType=""
         | 
| @@ -83,10 +89,11 @@ test('returns correct icon', () => { | |
| 83 89 | 
             
              expect(screen.getByTestId('test-wrong-phone').querySelector('.pb_custom_icon')).toBeInTheDocument()
         | 
| 84 90 | 
             
              expect(screen.getByTestId('test-wrong-type').querySelector('.pb_custom_icon')).toBeInTheDocument()
         | 
| 85 91 | 
             
              expect(screen.getByTestId('test-extension').querySelector('.pb_custom_icon')).toBeInTheDocument()
         | 
| 92 | 
            +
              expect(screen.getByTestId('test-international').querySelector('.pb_custom_icon')).toBeInTheDocument()
         | 
| 86 93 | 
             
              expect(screen.getByTestId('test-empty').querySelector('.pb_custom_icon')).toBeInTheDocument()
         | 
| 87 94 | 
             
            })
         | 
| 88 95 |  | 
| 89 | 
            -
            test("not compliant values return null in phone related contact types", () => {
         | 
| 96 | 
            +
            test("not compliant values return null in US phone related contact types", () => {
         | 
| 90 97 | 
             
              const notCompliantValues = [
         | 
| 91 98 | 
             
                "349-185-998223",
         | 
| 92 99 | 
             
                "349-1858",
         | 
| @@ -129,3 +136,16 @@ test("not compliant values return null in phone related contact types", () => { | |
| 129 136 | 
             
                )
         | 
| 130 137 | 
             
              })
         | 
| 131 138 | 
             
            })
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            test('international contact type preserves original format', () => {
         | 
| 141 | 
            +
              render(
         | 
| 142 | 
            +
                <Contact
         | 
| 143 | 
            +
                    contactType="international"
         | 
| 144 | 
            +
                    contactValue="+44 20 7946 0958"
         | 
| 145 | 
            +
                    data={{ testid: 'test-international-format' }}
         | 
| 146 | 
            +
                />
         | 
| 147 | 
            +
              )
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              const kit = screen.getByTestId('test-international-format')
         | 
| 150 | 
            +
              expect(kit).toHaveTextContent('+44 20 7946 0958')
         | 
| 151 | 
            +
            })
         | 
| @@ -13,7 +13,7 @@ | |
| 13 13 | 
             
            }) %>
         | 
| 14 14 |  | 
| 15 15 | 
             
            <%= pb_rails("contact", props: {
         | 
| 16 | 
            -
              contact_type: " | 
| 16 | 
            +
              contact_type: "work",
         | 
| 17 17 | 
             
              contact_value: "3245627482",
         | 
| 18 18 | 
             
            }) %>
         | 
| 19 19 |  | 
| @@ -21,3 +21,18 @@ | |
| 21 21 | 
             
              contact_type: "work-cell",
         | 
| 22 22 | 
             
              contact_value: "349-185-9988",
         | 
| 23 23 | 
             
            }) %>
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            <%= pb_rails("contact", props: {
         | 
| 26 | 
            +
              contact_type: "wrong-phone",
         | 
| 27 | 
            +
              contact_value: "2124396666",
         | 
| 28 | 
            +
            }) %>
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            <%= pb_rails("contact", props: {
         | 
| 31 | 
            +
              contact_type: "extension",
         | 
| 32 | 
            +
              contact_value: "1233",
         | 
| 33 | 
            +
            }) %>
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            <%= pb_rails("contact", props: {
         | 
| 36 | 
            +
              contact_type: "international",
         | 
| 37 | 
            +
              contact_value: "+44 7700 900461",
         | 
| 38 | 
            +
            }) %>
         | 
| @@ -28,6 +28,21 @@ const ContactDefault = (props) => { | |
| 28 28 | 
             
                      contactValue="3245627482"
         | 
| 29 29 | 
             
                      {...props}
         | 
| 30 30 | 
             
                  />
         | 
| 31 | 
            +
                  <Contact
         | 
| 32 | 
            +
                      contactType="wrong-phone"
         | 
| 33 | 
            +
                      contactValue="2124396666"
         | 
| 34 | 
            +
                      {...props}
         | 
| 35 | 
            +
                  />
         | 
| 36 | 
            +
                  <Contact
         | 
| 37 | 
            +
                      contactType='extension'
         | 
| 38 | 
            +
                      contactValue="1234"
         | 
| 39 | 
            +
                      {...props}
         | 
| 40 | 
            +
                  />
         | 
| 41 | 
            +
                  <Contact
         | 
| 42 | 
            +
                      contactType="international"
         | 
| 43 | 
            +
                      contactValue="+44 7700 900461"
         | 
| 44 | 
            +
                      {...props}
         | 
| 45 | 
            +
                  />
         | 
| 31 46 | 
             
                </div>
         | 
| 32 47 | 
             
              )
         | 
| 33 48 | 
             
            }
         | 
| @@ -0,0 +1,5 @@ | |
| 1 | 
            +
            The Contact kit automatically formats US phone numbers when the `contactType` / `contact_type` is one of: `home` (default), `work`, `cell`, `work-cell`, `wrong-phone`.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            - Use `email` to display emails.
         | 
| 4 | 
            +
            - Use `international` to display International phone numbers exactly as provided (no formatting applied).
         | 
| 5 | 
            +
            - Use `extension` to display four digit phone extensions.
         | 
| @@ -140,7 +140,8 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing); | |
| 140 140 | 
             
              delete filteredProps?.marginLeft;
         | 
| 141 141 |  | 
| 142 142 |  | 
| 143 | 
            -
              const  | 
| 143 | 
            +
              const isLink = !!link
         | 
| 144 | 
            +
              const Tag = isLink ? "a" : "div"
         | 
| 144 145 | 
             
              const activeClass = active === true ? "active" : "";
         | 
| 145 146 | 
             
              const highlightedBorderClass = active === true && highlighted_border === false ? "highlighted_border_none" : "";
         | 
| 146 147 | 
             
              const collapsibleTrailClass = collapsible && collapsibleTrail ? "collapsible_trail" : "";
         | 
| @@ -200,6 +201,13 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing); | |
| 200 201 |  | 
| 201 202 | 
             
              const collapsibleClasses = buildCss("collapsible_nav_wrapper", activeClass, highlightedBorderClass, collapsibleTrailClass)
         | 
| 202 203 |  | 
| 204 | 
            +
              const handleKeyDown = (e: React.KeyboardEvent) => {
         | 
| 205 | 
            +
                if (!isLink && (e.key === "Enter" || e.key === " ")) {
         | 
| 206 | 
            +
                  e.preventDefault()
         | 
| 207 | 
            +
                  onClick?.()
         | 
| 208 | 
            +
                }
         | 
| 209 | 
            +
              }
         | 
| 210 | 
            +
             | 
| 203 211 | 
             
              return (
         | 
| 204 212 | 
             
                <>
         | 
| 205 213 | 
             
                  {collapsible ? (
         | 
| @@ -222,15 +230,18 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing); | |
| 222 230 | 
             
                              {...dataProps}
         | 
| 223 231 | 
             
                              {...htmlProps}
         | 
| 224 232 | 
             
                              className={classes}
         | 
| 225 | 
            -
                              href={link}
         | 
| 233 | 
            +
                              href={isLink ? link : undefined}
         | 
| 226 234 | 
             
                              id={id}
         | 
| 227 | 
            -
                               | 
| 235 | 
            +
                              role={!isLink ? "button" : undefined}
         | 
| 236 | 
            +
                              tabIndex={!isLink ? 0 : undefined}
         | 
| 237 | 
            +
                              target={isLink ? target : undefined}
         | 
| 228 238 | 
             
                          >
         | 
| 229 239 | 
             
                            {imageUrl && (
         | 
| 230 240 | 
             
                              <div
         | 
| 231 241 | 
             
                                  className="pb_nav_list_item_icon_section_collapsible"
         | 
| 232 242 | 
             
                                  key={imageUrl}
         | 
| 233 243 | 
             
                                  onClick={(e) => handleIconClick(e)}
         | 
| 244 | 
            +
                                  onKeyDown={!isLink ? handleKeyDown : undefined}
         | 
| 234 245 | 
             
                              >
         | 
| 235 246 | 
             
                                <Image className="pb_nav_img_wrapper"
         | 
| 236 247 | 
             
                                    url={imageUrl}
         | 
| @@ -265,10 +276,13 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing); | |
| 265 276 | 
             
                        {...dataProps}
         | 
| 266 277 | 
             
                        {...htmlProps}
         | 
| 267 278 | 
             
                        className={classes}
         | 
| 268 | 
            -
                        href={link}
         | 
| 279 | 
            +
                        href={isLink ? link : undefined}
         | 
| 269 280 | 
             
                        id={id}
         | 
| 270 281 | 
             
                        onClick={onClick}
         | 
| 271 | 
            -
                         | 
| 282 | 
            +
                        onKeyDown={!isLink ? handleKeyDown : undefined}
         | 
| 283 | 
            +
                        role={!isLink ? "button" : undefined}
         | 
| 284 | 
            +
                        tabIndex={!isLink ? 0 : undefined}
         | 
| 285 | 
            +
                        target={isLink ? target : undefined}
         | 
| 272 286 | 
             
                    >
         | 
| 273 287 | 
             
                      {imageUrl && (
         | 
| 274 288 | 
             
                        <div className="pb_nav_list_item_icon_section"
         | 
| @@ -3,7 +3,9 @@ | |
| 3 3 | 
             
                  <%= pb_rails("collapsible/collapsible_main", props: { name: "default-collapsible-nav", icon: object.collapsible_icons, size: "xs", dark: object.dark, classname:object.margin_classes }) do %>
         | 
| 4 4 | 
             
                    <%= pb_content_tag( object.tag,
         | 
| 5 5 | 
             
                        href: object.link && object.link,
         | 
| 6 | 
            -
                        target: object.link && object.target
         | 
| 6 | 
            +
                        target: object.link && object.target,
         | 
| 7 | 
            +
                        onkeydown: !object.link ? "if(event.key==='Enter'||event.key===' '){event.preventDefault(); this.click();}" : nil,
         | 
| 8 | 
            +
                        tabindex: object.link ? nil : 0,
         | 
| 7 9 | 
             
                      ) do %>
         | 
| 8 10 | 
             
                      <% if object.image_url %>
         | 
| 9 11 | 
             
                        <%= pb_rails("image", props: { url: object.image_url, classname: "pb_nav_img_wrapper_collapsible" }) %>
         | 
| @@ -23,7 +25,9 @@ | |
| 23 25 | 
             
              <% else %>
         | 
| 24 26 | 
             
                <%= pb_content_tag( object.tag,
         | 
| 25 27 | 
             
                    href: object.link && object.link,
         | 
| 26 | 
            -
                    target: object.link && object.target
         | 
| 28 | 
            +
                    target: object.link && object.target,
         | 
| 29 | 
            +
                    onkeydown: !object.link ? "if(event.key==='Enter'||event.key===' '){event.preventDefault(); this.click();}" : nil,
         | 
| 30 | 
            +
                    tabindex: object.link ? nil : 0,
         | 
| 27 31 | 
             
                  ) do %>
         | 
| 28 32 | 
             
                  <% if object.image_url %>
         | 
| 29 33 | 
             
                    <%= pb_rails("image", props: { url: object.image_url, classname: "pb_nav_img_wrapper" }) %>
         | 
| @@ -4,8 +4,8 @@ | |
| 4 4 |  | 
| 5 5 | 
             
            <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "caption_breached" }) %>
         | 
| 6 6 |  | 
| 7 | 
            -
             | 
| 8 | 
            -
                window.addEventListener(" | 
| 7 | 
            +
            <script>
         | 
| 8 | 
            +
                window.addEventListener("load", () => {
         | 
| 9 9 |  | 
| 10 10 | 
             
                // variables for the kits you are targeting 
         | 
| 11 11 | 
             
                const passphrase = document.querySelector(".passphrase_breached").querySelector("input")
         | 
| @@ -142,4 +142,4 @@ | |
| 142 142 | 
             
                });
         | 
| 143 143 |  | 
| 144 144 | 
             
              })
         | 
| 145 | 
            -
             | 
| 145 | 
            +
            </script>
         | 
| @@ -10,8 +10,8 @@ | |
| 10 10 | 
             
            <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "caption_common" }) %>
         | 
| 11 11 |  | 
| 12 12 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
                window.addEventListener(" | 
| 13 | 
            +
            <script>
         | 
| 14 | 
            +
                window.addEventListener("load", () => {
         | 
| 15 15 |  | 
| 16 16 | 
             
                const commonText = document.querySelector("#body_common")
         | 
| 17 17 |  | 
| @@ -133,4 +133,4 @@ | |
| 133 133 | 
             
                });
         | 
| 134 134 |  | 
| 135 135 | 
             
              })
         | 
| 136 | 
            -
             | 
| 136 | 
            +
            </script>
         | 
| @@ -4,8 +4,8 @@ | |
| 4 4 |  | 
| 5 5 | 
             
            <div id="match"> </div>
         | 
| 6 6 |  | 
| 7 | 
            -
             | 
| 8 | 
            -
                window.addEventListener(" | 
| 7 | 
            +
            <script>
         | 
| 8 | 
            +
                window.addEventListener("load", () => {   
         | 
| 9 9 |  | 
| 10 10 | 
             
                  const useState = (defaultValue) => {
         | 
| 11 11 | 
             
                      let value = defaultValue;
         | 
| @@ -48,4 +48,4 @@ | |
| 48 48 |  | 
| 49 49 | 
             
                  }
         | 
| 50 50 | 
             
                })
         | 
| 51 | 
            -
             | 
| 51 | 
            +
            </script>
         | 
| @@ -32,8 +32,8 @@ | |
| 32 32 |  | 
| 33 33 |  | 
| 34 34 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
                window.addEventListener(" | 
| 35 | 
            +
            <script>
         | 
| 36 | 
            +
                window.addEventListener("load", () => {
         | 
| 37 37 |  | 
| 38 38 |  | 
| 39 39 | 
             
                // variables for the passphrase kits you are targeting 
         | 
| @@ -320,4 +320,4 @@ | |
| 320 320 |  | 
| 321 321 |  | 
| 322 322 | 
             
              })
         | 
| 323 | 
            -
             | 
| 323 | 
            +
            </script>
         | 
| @@ -7,8 +7,8 @@ | |
| 7 7 | 
             
            <%= pb_rails("text_input", props: { label: "Passphrase Strength", value: "0", disabled: true, id: "calc_strength_change" }) %>
         | 
| 8 8 |  | 
| 9 9 |  | 
| 10 | 
            -
             | 
| 11 | 
            -
                window.addEventListener(" | 
| 10 | 
            +
            <script>
         | 
| 11 | 
            +
                window.addEventListener("load", () => {
         | 
| 12 12 |  | 
| 13 13 | 
             
                // variables for the kits you are targeting 
         | 
| 14 14 | 
             
                const passphrase = document.querySelector(".passphrase_change").querySelector("input")
         | 
| @@ -120,4 +120,4 @@ | |
| 120 120 | 
             
                });
         | 
| 121 121 |  | 
| 122 122 | 
             
              })
         | 
| 123 | 
            -
             | 
| 123 | 
            +
            </script>
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            import React, { useMemo } from 'react'
         | 
| 3 | 
            +
            import classnames from 'classnames'
         | 
| 4 | 
            +
            import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
         | 
| 5 | 
            +
            import Highcharts from "highcharts"
         | 
| 6 | 
            +
            import HighchartsReact from "highcharts-react-official"
         | 
| 7 | 
            +
            import pbCircleGraphTheme from './pbCircleChartTheme'
         | 
| 8 | 
            +
            import { globalProps } from '../utilities/globalProps'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            type PbCircleChartProps = {
         | 
| 11 | 
            +
              aria?: { [key: string]: string },
         | 
| 12 | 
            +
              className?: string,
         | 
| 13 | 
            +
              data?: { [key: string]: string },
         | 
| 14 | 
            +
              id?: string,
         | 
| 15 | 
            +
              htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
         | 
| 16 | 
            +
              options: Record<string, unknown>
         | 
| 17 | 
            +
            }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            const PbCircleChart = (props: PbCircleChartProps) => {
         | 
| 20 | 
            +
              const {
         | 
| 21 | 
            +
                aria = {},
         | 
| 22 | 
            +
              className,
         | 
| 23 | 
            +
              data = {},
         | 
| 24 | 
            +
              id,
         | 
| 25 | 
            +
              htmlOptions = {},
         | 
| 26 | 
            +
              options
         | 
| 27 | 
            +
              } = props
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              const ariaProps = buildAriaProps(aria)
         | 
| 30 | 
            +
              const dataProps = buildDataProps(data)
         | 
| 31 | 
            +
              const htmlProps = buildHtmlProps(htmlOptions);
         | 
| 32 | 
            +
              const classes = classnames(buildCss('pb_pb_circle_chart'), globalProps(props), className)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              const mergedOptions = useMemo(() => {
         | 
| 35 | 
            +
                if (!options || typeof options !== "object") {
         | 
| 36 | 
            +
                  // eslint-disable-next-line no-console
         | 
| 37 | 
            +
                  console.error("❌ Invalid options passed to <PbCircleChart />", options)
         | 
| 38 | 
            +
                  return {}
         | 
| 39 | 
            +
                }
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                return Highcharts.merge({}, pbCircleGraphTheme, options)
         | 
| 42 | 
            +
              }, [options])
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              return (
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                <div>
         | 
| 47 | 
            +
                  <HighchartsReact
         | 
| 48 | 
            +
                      containerProps={{
         | 
| 49 | 
            +
                              className: classnames(globalProps, className),
         | 
| 50 | 
            +
                              id: id,
         | 
| 51 | 
            +
                              ...ariaProps,
         | 
| 52 | 
            +
                              ...dataProps,
         | 
| 53 | 
            +
                              ...htmlProps
         | 
| 54 | 
            +
                            }}
         | 
| 55 | 
            +
                      highcharts={Highcharts}
         | 
| 56 | 
            +
                      options={mergedOptions}
         | 
| 57 | 
            +
                  />
         | 
| 58 | 
            +
                </div>
         | 
| 59 | 
            +
              )
         | 
| 60 | 
            +
            }
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            export default PbCircleChart
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            <% data = [
         | 
| 2 | 
            +
                    {
         | 
| 3 | 
            +
                      name: "Waiting for Calls",
         | 
| 4 | 
            +
                      y: 41,
         | 
| 5 | 
            +
                    },
         | 
| 6 | 
            +
                    {
         | 
| 7 | 
            +
                      name: "On Call",
         | 
| 8 | 
            +
                      y: 49,
         | 
| 9 | 
            +
                    },
         | 
| 10 | 
            +
                    {
         | 
| 11 | 
            +
                      name: "After Call",
         | 
| 12 | 
            +
                      y: 10,
         | 
| 13 | 
            +
                    },
         | 
| 14 | 
            +
                  ] %>
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            <% chart_options = {
         | 
| 17 | 
            +
                series: [{
         | 
| 18 | 
            +
                  data: data,
         | 
| 19 | 
            +
                  innerSize: '100%',
         | 
| 20 | 
            +
                  borderWidth: '20',
         | 
| 21 | 
            +
                }],
         | 
| 22 | 
            +
              } %>
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            <div style="position: relative;">
         | 
| 25 | 
            +
              <%= pb_rails("pb_circle_chart", props: { options: chart_options }) %>
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              <div class="pb-circle-chart-block"
         | 
| 28 | 
            +
                   style="position: absolute; inset: 0; display: flex; justify-content: center; align-items: center; z-index: 1; text-align: center; pointer-events: none;">
         | 
| 29 | 
            +
                <%= pb_rails("title", props: { size: 1, tag: "div", text: "83" }) %>
         | 
| 30 | 
            +
              </div>
         | 
| 31 | 
            +
            </div>
         |