playbook_ui 13.2.0 → 13.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +1 -0
- data/app/pb_kits/playbook/pb_body/_body.scss +5 -0
- data/app/pb_kits/playbook/pb_body/_body.tsx +4 -1
- data/app/pb_kits/playbook/pb_body/_body_mixins.scss +19 -0
- data/app/pb_kits/playbook/pb_body/body.rb +8 -1
- data/app/pb_kits/playbook/pb_button/button.html.erb +2 -2
- data/app/pb_kits/playbook/pb_button/button.rb +3 -0
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleMain.tsx +5 -1
- data/app/pb_kits/playbook/pb_kit/dateTime.ts +54 -23
- data/app/pb_kits/playbook/pb_table/docs/_table_header.html.erb +54 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_header.md +1 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_two_actions.jsx +3 -3
- data/app/pb_kits/playbook/pb_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_all.scss +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_table_header.scss +31 -0
- data/app/pb_kits/playbook/pb_table/table_header.html.erb +64 -0
- data/app/pb_kits/playbook/pb_table/table_header.rb +53 -0
- data/app/pb_kits/playbook/pb_timestamp/_timestamp.tsx +14 -7
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.html.erb +21 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.jsx +36 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_timestamp/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_timestamp/timestamp.html.erb +5 -1
- data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +3 -1
- data/app/pb_kits/playbook/pb_title/_title.scss +8 -4
- data/app/pb_kits/playbook/pb_title/_title.tsx +4 -1
- data/app/pb_kits/playbook/pb_title/_title_mixin.scss +19 -0
- data/app/pb_kits/playbook/pb_title/title.rb +9 -2
- data/app/pb_kits/playbook/tokens/_spacing.scss +1 -1
- data/app/pb_kits/playbook/tokens/_text_align.scss +18 -0
- data/app/pb_kits/playbook/utilities/_hover.scss +4 -0
- data/app/pb_kits/playbook/utilities/_max_width.scss +4 -0
- data/app/pb_kits/playbook/utilities/_spacing.scss +92 -49
- data/app/pb_kits/playbook/utilities/_text_align.scss +3 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +30 -2
- data/dist/playbook-rails.js +5 -5
- data/lib/playbook/classnames.rb +1 -0
- data/lib/playbook/hover.rb +6 -2
- data/lib/playbook/kit_base.rb +2 -0
- data/lib/playbook/spacing.rb +13 -4
- data/lib/playbook/text_align.rb +37 -0
- data/lib/playbook/version.rb +2 -2
- metadata +13 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4de8135dcb47909b6c71e27192382cc5ab8890bc54c6e1d5cb4c624553cc65a2
         | 
| 4 | 
            +
              data.tar.gz: c3dd0cd17ad4319288dc8c7b16f2d93147ed8b5a04d33b8ecd8876bebc97f221
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a20fc82e7400098302e5e929cb70ad54a4c2360db26f42f2e38fdacb4bec2625528838b043695a6ba3c133c8f23553ccebeda91ab0f551b5d5032335cac1f682
         | 
| 7 | 
            +
              data.tar.gz: 4554d268f82cf779641860ea89b2ceebb194b407dc6a30374e762e207b9e2094c9d63dee0669494be80815d4ec663d0e503ef3b58138c9bf8923090aa6bdfc03
         | 
| @@ -37,10 +37,15 @@ | |
| 37 37 | 
             
                font-size: $font_smaller;
         | 
| 38 38 | 
             
                letter-spacing: $lspace_loose;
         | 
| 39 39 | 
             
              }
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              &[class*=_truncate] {
         | 
| 42 | 
            +
                @include body_truncate;
         | 
| 43 | 
            +
              }
         | 
| 40 44 |  | 
| 41 45 | 
             
              @each $status_name, $status_value in $pb_body_status {
         | 
| 42 46 | 
             
                &[class*=#{$status_name}] {
         | 
| 43 47 | 
             
                  @include pb_body($status_value);
         | 
| 48 | 
            +
                  @include body_truncate;
         | 
| 44 49 | 
             
                }
         | 
| 45 50 | 
             
              }
         | 
| 46 51 |  | 
| @@ -19,6 +19,7 @@ type BodyProps = { | |
| 19 19 | 
             
              status?: 'neutral' | 'negative' | 'positive',
         | 
| 20 20 | 
             
              tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div',
         | 
| 21 21 | 
             
              text?: string,
         | 
| 22 | 
            +
              truncate?: null | '1' | '2' | '3' | '4' | '5',
         | 
| 22 23 | 
             
              variant?: null | 'link',
         | 
| 23 24 | 
             
            } & GlobalProps
         | 
| 24 25 |  | 
| @@ -36,13 +37,15 @@ const Body = (props: BodyProps): React.ReactElement => { | |
| 36 37 | 
             
                status = null,
         | 
| 37 38 | 
             
                tag = 'div',
         | 
| 38 39 | 
             
                text = '',
         | 
| 40 | 
            +
                truncate = null,
         | 
| 39 41 | 
             
                variant = null,
         | 
| 40 42 | 
             
              } = props
         | 
| 41 43 |  | 
| 42 44 | 
             
              const ariaProps: {[key: string]: any} = buildAriaProps(aria)
         | 
| 43 45 | 
             
              const dataProps: {[key: string]: any} = buildDataProps(data)
         | 
| 46 | 
            +
              const isTruncated = truncate ? `truncate_${truncate}` : ''
         | 
| 44 47 | 
             
              const classes = classnames(
         | 
| 45 | 
            -
                buildCss('pb_body_kit', color, variant, status),
         | 
| 48 | 
            +
                buildCss('pb_body_kit', color, variant, status, isTruncated),
         | 
| 46 49 | 
             
                globalProps(props),
         | 
| 47 50 | 
             
                className
         | 
| 48 51 | 
             
              )
         | 
| @@ -36,6 +36,25 @@ $pb_body_status: ( | |
| 36 36 | 
             
              font-family: $font-family-base;
         | 
| 37 37 | 
             
            }
         | 
| 38 38 |  | 
| 39 | 
            +
            $pb_body_truncate: (
         | 
| 40 | 
            +
              truncate_1: 1,
         | 
| 41 | 
            +
              truncate_2: 2,
         | 
| 42 | 
            +
              truncate_3: 3,
         | 
| 43 | 
            +
              truncate_4: 4,
         | 
| 44 | 
            +
              truncate_5: 5
         | 
| 45 | 
            +
            );
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            @mixin body_truncate {
         | 
| 48 | 
            +
              @each $name, $number in $pb_body_truncate {
         | 
| 49 | 
            +
                &[class*=_#{$name}] {
         | 
| 50 | 
            +
                  overflow: hidden;
         | 
| 51 | 
            +
                  display: -webkit-box;
         | 
| 52 | 
            +
                  -webkit-line-clamp: $number;
         | 
| 53 | 
            +
                  -webkit-box-orient: vertical; 
         | 
| 54 | 
            +
                }
         | 
| 55 | 
            +
              }
         | 
| 56 | 
            +
            }
         | 
| 57 | 
            +
             | 
| 39 58 |  | 
| 40 59 | 
             
            // Colors ======================
         | 
| 41 60 | 
             
            @mixin pb_body_light {
         | 
| @@ -18,9 +18,12 @@ module Playbook | |
| 18 18 | 
             
                                      default: false
         | 
| 19 19 | 
             
                  prop :highlighted_text, type: Playbook::Props::Array,
         | 
| 20 20 | 
             
                                          default: []
         | 
| 21 | 
            +
                  prop :truncate, type: Playbook::Props::Enum,
         | 
| 22 | 
            +
                                  values: [nil, "1", "2", "3", "4", "5"],
         | 
| 23 | 
            +
                                  default: nil
         | 
| 21 24 |  | 
| 22 25 | 
             
                  def classname
         | 
| 23 | 
            -
                    generate_classname("pb_body_kit", color_class, status_class)
         | 
| 26 | 
            +
                    generate_classname("pb_body_kit", color_class, status_class, is_truncated)
         | 
| 24 27 | 
             
                  end
         | 
| 25 28 |  | 
| 26 29 | 
             
                  def content
         | 
| @@ -28,6 +31,10 @@ module Playbook | |
| 28 31 | 
             
                    highlighting ? apply_highlight(body_text) : body_text
         | 
| 29 32 | 
             
                  end
         | 
| 30 33 |  | 
| 34 | 
            +
                  def is_truncated
         | 
| 35 | 
            +
                    truncate ? "truncate_#{truncate}" : nil
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 31 38 | 
             
                private
         | 
| 32 39 |  | 
| 33 40 | 
             
                  def apply_highlight(text)
         | 
| @@ -18,14 +18,14 @@ | |
| 18 18 | 
             
                <% else %>
         | 
| 19 19 | 
             
                <% if object.icon && !object.icon_right %>
         | 
| 20 20 | 
             
                    <span>
         | 
| 21 | 
            -
                        <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_right: "xs" }) %>
         | 
| 21 | 
            +
                        <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_right: "xs", font_style: object.icon_font_family }) %>
         | 
| 22 22 | 
             
                    </span>
         | 
| 23 23 | 
             
                <% end %>
         | 
| 24 24 | 
             
                <%= pb_rails("icon", props: { icon: "spinner", pulse: true, fixed_width: true, classname: "loading-icon" }) %>
         | 
| 25 25 | 
             
                <span class="pb_button_content"><%= content.presence || object.text %></span>
         | 
| 26 26 | 
             
                <% if object.icon && object.icon_right %>
         | 
| 27 27 | 
             
                    <span>
         | 
| 28 | 
            -
                        <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_left: "xs" }) %>
         | 
| 28 | 
            +
                        <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_left: "xs", font_style: object.icon_font_family }) %>
         | 
| 29 29 | 
             
                    </span>
         | 
| 30 30 | 
             
                <% end %>
         | 
| 31 31 | 
             
                <% end %>
         | 
| @@ -99,8 +99,12 @@ const CollapsibleMain = ({ | |
| 99 99 | 
             
              const mainSpacing = globalProps(props, { cursor })
         | 
| 100 100 |  | 
| 101 101 | 
             
              const handleCollapsibleClick = () => {
         | 
| 102 | 
            +
                onClick && onClick();
         | 
| 103 | 
            +
                //To disable default toggling behavior return "true" in the onClick()
         | 
| 104 | 
            +
                const disableToggle = onClick && onClick();
         | 
| 105 | 
            +
                if (disableToggle !== true) {
         | 
| 102 106 | 
             
                toggle();
         | 
| 103 | 
            -
                 | 
| 107 | 
            +
                }
         | 
| 104 108 | 
             
              }
         | 
| 105 109 |  | 
| 106 110 | 
             
              return (
         | 
| @@ -121,30 +121,61 @@ export const toIso = (newDate: Date | string): string => { | |
| 121 121 | 
             
            }
         | 
| 122 122 |  | 
| 123 123 | 
             
            export const fromNow = (newDate: Date | string): string => {
         | 
| 124 | 
            -
              const  | 
| 125 | 
            -
              const  | 
| 124 | 
            +
              const today = new Date()
         | 
| 125 | 
            +
              const formattedDate = formatDate(newDate)
         | 
| 126 | 
            +
             | 
| 127 | 
            +
              const startDate = formattedDate.getTime()
         | 
| 128 | 
            +
              const endDate = today.getTime()
         | 
| 126 129 | 
             
              const elapsedTime = endDate - startDate
         | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
              const  | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
                 | 
| 133 | 
            -
                 | 
| 134 | 
            -
                 | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
               | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 130 | 
            +
             | 
| 131 | 
            +
              // For years/months, don't use elapsedTime due to rounding
         | 
| 132 | 
            +
              const differenceInYears = today.getFullYear() - formattedDate.getFullYear()
         | 
| 133 | 
            +
              const differenceInMonths = () => {
         | 
| 134 | 
            +
                let months = differenceInYears * 12
         | 
| 135 | 
            +
                months -= formattedDate.getMonth()
         | 
| 136 | 
            +
                months += today.getMonth()
         | 
| 137 | 
            +
                return months
         | 
| 138 | 
            +
              }
         | 
| 139 | 
            +
             | 
| 140 | 
            +
              const FORTY_FIVE_SECONDS = 45000
         | 
| 141 | 
            +
              const NINETY_SECONDS = 90000
         | 
| 142 | 
            +
             | 
| 143 | 
            +
              const FORTY_FIVE_MINUTES = 2670000
         | 
| 144 | 
            +
              const NINETY_MINUTES = 5400000
         | 
| 145 | 
            +
             | 
| 146 | 
            +
              const TWENTY_TWO_HOURS = 77400000
         | 
| 147 | 
            +
              const THIRTY_SIX_HOURS = 129600000
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              const TWENTY_SIX_DAYS = 2203200000
         | 
| 150 | 
            +
              const FORTY_FIVE_DAYS = 3888000000
         | 
| 151 | 
            +
             | 
| 152 | 
            +
              const TEN_AND_A_HALF_MONTHS = 27560000000
         | 
| 153 | 
            +
             | 
| 154 | 
            +
              const MILLISECONDS_IN_A_MINUTE = 60000
         | 
| 155 | 
            +
              const MILLISECONDS_IN_A_HOUR = 3600000
         | 
| 156 | 
            +
              const MILLISECONDS_IN_A_DAY = 86400000
         | 
| 157 | 
            +
             | 
| 158 | 
            +
              let elapsedTimeString = differenceInYears === 1 ? `${differenceInYears} year ago` : `${differenceInYears} years ago` // 320 days to 1+ year: "x year(s) ago"
         | 
| 159 | 
            +
             | 
| 160 | 
            +
              // Inspiration: https://momentjs.com/docs/#/displaying/fromnow/
         | 
| 161 | 
            +
              const intervals = [
         | 
| 162 | 
            +
                { min: 0, max: FORTY_FIVE_SECONDS, value: "a few seconds ago" }, // 0-44.99 seconds
         | 
| 163 | 
            +
                { min: FORTY_FIVE_SECONDS, max: NINETY_SECONDS, value: "a minute ago" }, // 45-89.99 seconds
         | 
| 164 | 
            +
                { min: NINETY_SECONDS, max: FORTY_FIVE_MINUTES, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_MINUTE)} minutes ago` }, // 90s-44.49 minutes: "2 minutes ago ... 44 minutes ago"
         | 
| 165 | 
            +
                { min: FORTY_FIVE_MINUTES, max: NINETY_MINUTES, value: "an hour ago" }, // 44.5-89.99 minutes
         | 
| 166 | 
            +
                { min: NINETY_MINUTES, max: TWENTY_TWO_HOURS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_HOUR)} hours ago` }, // 90m-21.49 hours: "2 hours ago ... 21 hours ago"
         | 
| 167 | 
            +
                { min: TWENTY_TWO_HOURS, max: THIRTY_SIX_HOURS, value: "a day ago" }, // 21.5-35.99 hours
         | 
| 168 | 
            +
                { min: THIRTY_SIX_HOURS, max: TWENTY_SIX_DAYS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_DAY)} days ago` }, // 36h-25.49 days: "2 days ago ... 25 days ago"
         | 
| 169 | 
            +
                { min: TWENTY_SIX_DAYS, max: FORTY_FIVE_DAYS, value: "a month ago" }, // 25.5-44.99 days
         | 
| 170 | 
            +
                { min: FORTY_FIVE_DAYS, max: TEN_AND_A_HALF_MONTHS, value: `${differenceInMonths()} months ago` }, // 45 days to 319 days: "2 months ago ... 10 months ago"
         | 
| 171 | 
            +
              ]
         | 
| 172 | 
            +
             | 
| 173 | 
            +
              for (const interval of intervals) {
         | 
| 174 | 
            +
                const { min, max, value } = interval
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                if (elapsedTime >= min && elapsedTime < max) {
         | 
| 177 | 
            +
                  elapsedTimeString = value
         | 
| 178 | 
            +
                  break
         | 
| 148 179 | 
             
                }
         | 
| 149 180 | 
             
              }
         | 
| 150 181 |  | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            <%= pb_rails("table", props: { size: "lg"} ) do %>
         | 
| 2 | 
            +
              <thead>
         | 
| 3 | 
            +
                <tr>
         | 
| 4 | 
            +
                  <%= pb_rails("table/table_header", props: {
         | 
| 5 | 
            +
                    id: "name",
         | 
| 6 | 
            +
                    colspan: 2,
         | 
| 7 | 
            +
                    sort_menu: [
         | 
| 8 | 
            +
                      { item: "Name", link: "?q[sorts]=name+desc", active: false, direction: "desc" },
         | 
| 9 | 
            +
                      { item: "Name", link: "?q[sorts]=name+asc", active: true, direction: "asc" },
         | 
| 10 | 
            +
                    ],
         | 
| 11 | 
            +
                  }) %>
         | 
| 12 | 
            +
                  <%= pb_rails("table/table_header", props: {
         | 
| 13 | 
            +
                    text: "Age",
         | 
| 14 | 
            +
                    id: "age",
         | 
| 15 | 
            +
                    sort_menu: [
         | 
| 16 | 
            +
                      { item: "Age", link: "?q[sorts]=age+desc", active: false, direction: "desc" },
         | 
| 17 | 
            +
                      { item: "Age", link: "?q[sorts]=age+asc", active: false, direction: "asc" },
         | 
| 18 | 
            +
                    ],
         | 
| 19 | 
            +
                  }) %>
         | 
| 20 | 
            +
                  <%= pb_rails("table/table_header", props: {
         | 
| 21 | 
            +
                    text: "Territory",
         | 
| 22 | 
            +
                    id: "territory",
         | 
| 23 | 
            +
                    sort_menu: [
         | 
| 24 | 
            +
                      { item: "Territory", link: "?q[sorts]=territory+desc", active: false, direction: "desc" },
         | 
| 25 | 
            +
                      { item: "Territory", link: "?q[sorts]=territory+asc", active: false, direction: "asc" },
         | 
| 26 | 
            +
                    ],
         | 
| 27 | 
            +
                  }) %>
         | 
| 28 | 
            +
                  <%= pb_rails("table/table_header", props: { text: "Job Title" }) %>
         | 
| 29 | 
            +
                </tr>
         | 
| 30 | 
            +
              </thead>
         | 
| 31 | 
            +
              <tbody>
         | 
| 32 | 
            +
                <tr>
         | 
| 33 | 
            +
                  <td>Name 1</td>
         | 
| 34 | 
            +
                  <td>Name 2</td>
         | 
| 35 | 
            +
                  <td>Value 3</td>
         | 
| 36 | 
            +
                  <td>Value 4</td>
         | 
| 37 | 
            +
                  <td>Value 5</td>
         | 
| 38 | 
            +
                </tr>
         | 
| 39 | 
            +
                <tr>
         | 
| 40 | 
            +
                  <td>Name 1</td>
         | 
| 41 | 
            +
                  <td>Name 2</td>
         | 
| 42 | 
            +
                  <td>Value 3</td>
         | 
| 43 | 
            +
                  <td>Value 4</td>
         | 
| 44 | 
            +
                  <td>Value 5</td>
         | 
| 45 | 
            +
                </tr>
         | 
| 46 | 
            +
                <tr>
         | 
| 47 | 
            +
                  <td>Name 1</td>
         | 
| 48 | 
            +
                  <td>Name 2</td>
         | 
| 49 | 
            +
                  <td>Value 3</td>
         | 
| 50 | 
            +
                  <td>Value 4</td>
         | 
| 51 | 
            +
                  <td>Value 5</td>
         | 
| 52 | 
            +
                </tr>
         | 
| 53 | 
            +
              </tbody>
         | 
| 54 | 
            +
            <% end %>
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            A kit that produces a `<th>` tag. You can also use the `sort_menu` prop to make the header a sortable link, just like <a href="https://playbook.powerapp.cloud/kits/filter#sort-only" target="_blank">our filter kit.</a>
         | 
| @@ -28,7 +28,7 @@ const TableOneAction = (props) => { | |
| 28 28 | 
             
                        <Button
         | 
| 29 29 | 
             
                            onClick={() => alert('button clicked!')}
         | 
| 30 30 | 
             
                            paddingLeft="none"
         | 
| 31 | 
            -
                            text=" | 
| 31 | 
            +
                            text="Tertiary Action"
         | 
| 32 32 | 
             
                            variant="link"
         | 
| 33 33 | 
             
                            {...props}
         | 
| 34 34 | 
             
                        />
         | 
| @@ -49,7 +49,7 @@ const TableOneAction = (props) => { | |
| 49 49 | 
             
                        <Button
         | 
| 50 50 | 
             
                            onClick={() => alert('button clicked!')}
         | 
| 51 51 | 
             
                            paddingLeft="none"
         | 
| 52 | 
            -
                            text=" | 
| 52 | 
            +
                            text="Tertiary Action"
         | 
| 53 53 | 
             
                            variant="link"
         | 
| 54 54 | 
             
                            {...props}
         | 
| 55 55 | 
             
                        />
         | 
| @@ -70,7 +70,7 @@ const TableOneAction = (props) => { | |
| 70 70 | 
             
                        <Button
         | 
| 71 71 | 
             
                            onClick={() => alert('button clicked!')}
         | 
| 72 72 | 
             
                            paddingLeft="none"
         | 
| 73 | 
            -
                            text=" | 
| 73 | 
            +
                            text="Tertiary Action"
         | 
| 74 74 | 
             
                            variant="link"
         | 
| 75 75 | 
             
                            {...props}
         | 
| 76 76 | 
             
                        />
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            $text_align_values: (
         | 
| 3 | 
            +
              start: start,
         | 
| 4 | 
            +
              end: end,
         | 
| 5 | 
            +
              left: left,
         | 
| 6 | 
            +
              right: right,
         | 
| 7 | 
            +
              center: center,
         | 
| 8 | 
            +
              justify: justify,
         | 
| 9 | 
            +
              justify-all: justify-all,
         | 
| 10 | 
            +
              match-parent: match-parent,
         | 
| 11 | 
            +
            );
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            [class^=pb_table] {
         | 
| 14 | 
            +
              thead {
         | 
| 15 | 
            +
                [class^=pb_table_header_kit] {
         | 
| 16 | 
            +
                  @each $align_name, $align_value in $text_align_values {
         | 
| 17 | 
            +
                    &[class*=_align_#{$align_name}] {
         | 
| 18 | 
            +
                      text-align: $align_value;
         | 
| 19 | 
            +
                    }
         | 
| 20 | 
            +
                  }
         | 
| 21 | 
            +
                }
         | 
| 22 | 
            +
              }
         | 
| 23 | 
            +
            }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            [class^=pb_table] {
         | 
| 26 | 
            +
              thead {
         | 
| 27 | 
            +
                [class^=pb_th_active] {
         | 
| 28 | 
            +
                  color: $primary !important;
         | 
| 29 | 
            +
                }
         | 
| 30 | 
            +
              }
         | 
| 31 | 
            +
            }
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            <%= content_tag(:th,
         | 
| 2 | 
            +
                colspan: object.colspan,
         | 
| 3 | 
            +
                aria: object.aria,
         | 
| 4 | 
            +
                class: object.classname,
         | 
| 5 | 
            +
                data: object.data,
         | 
| 6 | 
            +
                id: "pb-th#{object.id}") do %>
         | 
| 7 | 
            +
              <% object.sort_menu.each do |item| %>
         | 
| 8 | 
            +
                <% if item[:active] == true %>
         | 
| 9 | 
            +
                  <%= pb_rails("flex", props:{ align: object.align_content }) do %>
         | 
| 10 | 
            +
                    <%= content.presence || content_tag(:span, item[:item], class: "pb_th_active") %>
         | 
| 11 | 
            +
                    <span class="pb_th_active">
         | 
| 12 | 
            +
                      <%= pb_rails("icon", props: { icon: object.sort_icon(item[:direction]),
         | 
| 13 | 
            +
                                                    fixed_width: true,
         | 
| 14 | 
            +
                                                    classname: "pb_th_active",
         | 
| 15 | 
            +
                                                    padding_left: "xs" }) %>
         | 
| 16 | 
            +
                    </span>
         | 
| 17 | 
            +
                  <% end %>
         | 
| 18 | 
            +
                <% end %>
         | 
| 19 | 
            +
              <% end %>
         | 
| 20 | 
            +
              <% if object.sort_menu.all? { |item| item[:active] == false } %>
         | 
| 21 | 
            +
                <%= pb_rails("flex", props:{ align: object.align_content }) do %>
         | 
| 22 | 
            +
                  <%= content.presence || object.text %>
         | 
| 23 | 
            +
                  <%= pb_rails("icon", props: { icon: "arrow-up-arrow-down",
         | 
| 24 | 
            +
                                                fixed_width: true,
         | 
| 25 | 
            +
                                                padding_left: "xs" }) %>
         | 
| 26 | 
            +
                <% end %>
         | 
| 27 | 
            +
              <% else %>
         | 
| 28 | 
            +
                <%= content.presence || object.text %>
         | 
| 29 | 
            +
              <% end %>
         | 
| 30 | 
            +
              <% if object.sort_menu != [{}] && object.colspan > 1 %>
         | 
| 31 | 
            +
                <%= pb_rails("popover", props: { classname: "pb_filter_sort_menu",
         | 
| 32 | 
            +
                                                close_on_click: "outside",
         | 
| 33 | 
            +
                                                trigger_element_id: "pb-th#{object.id}",
         | 
| 34 | 
            +
                                                tooltip_id: "sort-filter-btn-tooltip#{object.id}",
         | 
| 35 | 
            +
                                                position: object.placement ,
         | 
| 36 | 
            +
                                                padding: 'none'}) do %>
         | 
| 37 | 
            +
                  <%= pb_rails("list") do %>
         | 
| 38 | 
            +
                    <% object.sort_menu.each do |item| %>
         | 
| 39 | 
            +
                      <%= pb_rails("list/item") do %>
         | 
| 40 | 
            +
                        <%= pb_rails("button", props: { variant: "link" ,
         | 
| 41 | 
            +
                                                        classname: "p-0",
         | 
| 42 | 
            +
                                                        text: item[:item],
         | 
| 43 | 
            +
                                                        link: item[:link],
         | 
| 44 | 
            +
                                                        icon: sort_icon(item[:direction]),
         | 
| 45 | 
            +
                                                        icon_right: true }) %>
         | 
| 46 | 
            +
                      <% end %>
         | 
| 47 | 
            +
                    <% end %>
         | 
| 48 | 
            +
                  <% end %>
         | 
| 49 | 
            +
                <% end %>
         | 
| 50 | 
            +
              <% end %>
         | 
| 51 | 
            +
            <% end %>
         | 
| 52 | 
            +
            <% if object.sort_menu != [{}] && object.colspan == 1 %>
         | 
| 53 | 
            +
              <script>
         | 
| 54 | 
            +
                document.addEventListener("DOMContentLoaded", function() {
         | 
| 55 | 
            +
                  var thId = `<%= "#pb-th#{object.id}" %>`
         | 
| 56 | 
            +
                  var firstLink = `<%= next_link %>`
         | 
| 57 | 
            +
                  var thElement = document.querySelector(thId);
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  thElement.addEventListener("click", function() {
         | 
| 60 | 
            +
                    window.location.href = firstLink;
         | 
| 61 | 
            +
                  });
         | 
| 62 | 
            +
                });
         | 
| 63 | 
            +
              </script>
         | 
| 64 | 
            +
            <% end %>
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Playbook
         | 
| 4 | 
            +
              module PbTable
         | 
| 5 | 
            +
                class TableHeader < Playbook::KitBase
         | 
| 6 | 
            +
                  prop :align, type: Playbook::Props::Enum,
         | 
| 7 | 
            +
                               values: %w[start center end stretch baseline none],
         | 
| 8 | 
            +
                               default: "start"
         | 
| 9 | 
            +
                  prop :align_content, type: Playbook::Props::Enum,
         | 
| 10 | 
            +
                                       values: %w[start center end stretch baseline none],
         | 
| 11 | 
            +
                                       default: "center"
         | 
| 12 | 
            +
                  prop :colspan, type: Playbook::Props::Number,
         | 
| 13 | 
            +
                                 default: 1
         | 
| 14 | 
            +
                  prop :placement, type: Playbook::Props::Enum,
         | 
| 15 | 
            +
                                   values: %w[top bottom left right top-start top-end bottom-start bottom-end right-start right-end left-start left-end],
         | 
| 16 | 
            +
                                   default: "bottom-start"
         | 
| 17 | 
            +
                  prop :sort_menu, type: Playbook::Props::HashArray,
         | 
| 18 | 
            +
                                   default: [{}]
         | 
| 19 | 
            +
                  prop :text, type: Playbook::Props::String,
         | 
| 20 | 
            +
                              default: ""
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def classname
         | 
| 23 | 
            +
                    generate_classname("pb_table_header_kit", align_class)
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def align_class
         | 
| 27 | 
            +
                    align.present? ? "align_#{align}" : nil
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def next_link
         | 
| 31 | 
            +
                    return sort_menu[0][:link] if sort_menu.all? { |item| item[:active] == false }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    sort_menu.each_with_index do |item, index|
         | 
| 34 | 
            +
                      if item[:active] == true
         | 
| 35 | 
            +
                        next_index = (index + 1) % sort_menu.length
         | 
| 36 | 
            +
                        sort_menu[next_index][:link]
         | 
| 37 | 
            +
                      end
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def sort_icon(direction)
         | 
| 42 | 
            +
                    case direction
         | 
| 43 | 
            +
                    when "asc"
         | 
| 44 | 
            +
                      "sort-amount-up"
         | 
| 45 | 
            +
                    when "desc"
         | 
| 46 | 
            +
                      "sort-amount-down"
         | 
| 47 | 
            +
                    else
         | 
| 48 | 
            +
                      ""
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -5,7 +5,6 @@ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props' | |
| 5 5 | 
             
            import { globalProps } from '../utilities/globalProps'
         | 
| 6 6 | 
             
            import DateTime from '../pb_kit/dateTime';
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 9 8 | 
             
            import Caption from '../pb_caption/_caption'
         | 
| 10 9 |  | 
| 11 10 | 
             
            type TimestampProps = {
         | 
| @@ -22,6 +21,7 @@ type TimestampProps = { | |
| 22 21 | 
             
              showUser?: boolean,
         | 
| 23 22 | 
             
              hideUpdated?: boolean,
         | 
| 24 23 | 
             
              showTimezone?: boolean,
         | 
| 24 | 
            +
              unstyled?: boolean,
         | 
| 25 25 | 
             
              variant?: "default" | "elapsed" | "updated"
         | 
| 26 26 | 
             
            }
         | 
| 27 27 |  | 
| @@ -39,6 +39,7 @@ const Timestamp = (props: TimestampProps): React.ReactElement => { | |
| 39 39 | 
             
                showUser = false,
         | 
| 40 40 | 
             
                hideUpdated = false,
         | 
| 41 41 | 
             
                showTimezone = false,
         | 
| 42 | 
            +
                unstyled = false,
         | 
| 42 43 | 
             
                variant = 'default',
         | 
| 43 44 | 
             
              } = props
         | 
| 44 45 |  | 
| @@ -85,7 +86,7 @@ const Timestamp = (props: TimestampProps): React.ReactElement => { | |
| 85 86 | 
             
                return `${updatedText} ${userDisplay} ${DateTime.fromNow(timestamp)}`
         | 
| 86 87 | 
             
              }
         | 
| 87 88 |  | 
| 88 | 
            -
              const  | 
| 89 | 
            +
              const timestampText = () => {
         | 
| 89 90 | 
             
                switch (variant) {
         | 
| 90 91 | 
             
                case 'updated':
         | 
| 91 92 | 
             
                  return formatUpdatedString()
         | 
| @@ -103,11 +104,17 @@ const Timestamp = (props: TimestampProps): React.ReactElement => { | |
| 103 104 | 
             
                    className={classes}
         | 
| 104 105 | 
             
                >
         | 
| 105 106 | 
             
                  <div className="pb_timestamp_kit">
         | 
| 106 | 
            -
                     | 
| 107 | 
            -
             | 
| 108 | 
            -
                         | 
| 109 | 
            -
             | 
| 110 | 
            -
                     | 
| 107 | 
            +
                    {unstyled ? (
         | 
| 108 | 
            +
                      <div>
         | 
| 109 | 
            +
                        {timestampText()}
         | 
| 110 | 
            +
                      </div>
         | 
| 111 | 
            +
                    ) : (
         | 
| 112 | 
            +
                      <Caption
         | 
| 113 | 
            +
                          dark={dark}
         | 
| 114 | 
            +
                          size="xs"
         | 
| 115 | 
            +
                          text={timestampText()}
         | 
| 116 | 
            +
                      />
         | 
| 117 | 
            +
                    )}
         | 
| 111 118 | 
             
                  </div>
         | 
| 112 119 | 
             
                </div>
         | 
| 113 120 | 
             
              )
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            <%= pb_rails("caption", props: { size: "xs", text: "Basic unstyled example" }) %>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            <%= pb_rails("timestamp", props: {
         | 
| 4 | 
            +
              timestamp: DateTime.now,
         | 
| 5 | 
            +
              show_date: true,
         | 
| 6 | 
            +
              align: "left",
         | 
| 7 | 
            +
              unstyled: true,
         | 
| 8 | 
            +
            }) %>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            <br />
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            <%= pb_rails("caption", props: { size: "xs", text: "Example with wrapping typography kit" }) %>
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            <%= pb_rails("title", props: { size: 1 }) do %>
         | 
| 15 | 
            +
              <%= pb_rails("timestamp", props: {
         | 
| 16 | 
            +
                timestamp: DateTime.now,
         | 
| 17 | 
            +
                show_date: true,
         | 
| 18 | 
            +
                align: "left",
         | 
| 19 | 
            +
                unstyled: true,
         | 
| 20 | 
            +
              }) %>
         | 
| 21 | 
            +
            <% end %>
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            import React from 'react'
         | 
| 2 | 
            +
            import { Caption, Timestamp, Title } from '../../'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            const TimestampUnstyled = (props) => {
         | 
| 5 | 
            +
              return (
         | 
| 6 | 
            +
                <>
         | 
| 7 | 
            +
                  <Caption size="xs"
         | 
| 8 | 
            +
                      text="Basic unstyled example"
         | 
| 9 | 
            +
                  />
         | 
| 10 | 
            +
                  <Timestamp
         | 
| 11 | 
            +
                      align="left"
         | 
| 12 | 
            +
                      showDate
         | 
| 13 | 
            +
                      timestamp={new Date()}
         | 
| 14 | 
            +
                      unstyled
         | 
| 15 | 
            +
                      {...props}
         | 
| 16 | 
            +
                  />
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  <br />
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  <Caption size="xs"
         | 
| 21 | 
            +
                      text="Example with wrapping typography kit"
         | 
| 22 | 
            +
                  />
         | 
| 23 | 
            +
                  <Title size={1}>
         | 
| 24 | 
            +
                    <Timestamp
         | 
| 25 | 
            +
                        align="left"
         | 
| 26 | 
            +
                        showDate
         | 
| 27 | 
            +
                        timestamp={new Date()}
         | 
| 28 | 
            +
                        unstyled
         | 
| 29 | 
            +
                        {...props}
         | 
| 30 | 
            +
                    />
         | 
| 31 | 
            +
                  </Title>
         | 
| 32 | 
            +
                </>
         | 
| 33 | 
            +
              )
         | 
| 34 | 
            +
            }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            export default TimestampUnstyled
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            For alternative typography styles, you can pass a boolean prop called `unstyled` to the `Timestamp` kit and wrap it in any of our typography kits (`Title`, `Body`, etc.). This will allow the `Timestamp` kit to inherit any of our typography styles.
         | 
| @@ -6,6 +6,7 @@ examples: | |
| 6 6 | 
             
              - timestamp_timezones: Timezones
         | 
| 7 7 | 
             
              - timestamp_updated: Last Updated by
         | 
| 8 8 | 
             
              - timestamp_elapsed: Time Ago
         | 
| 9 | 
            +
              - timestamp_unstyled: Unstyled
         | 
| 9 10 |  | 
| 10 11 | 
             
              react:
         | 
| 11 12 | 
             
              - timestamp_default: Default
         | 
| @@ -13,7 +14,8 @@ examples: | |
| 13 14 | 
             
              - timestamp_timezones: Timezones
         | 
| 14 15 | 
             
              - timestamp_updated: Last Updated by
         | 
| 15 16 | 
             
              - timestamp_elapsed: Time Ago
         | 
| 16 | 
            -
              
         | 
| 17 | 
            +
              - timestamp_unstyled: Unstyled
         | 
| 18 | 
            +
             | 
| 17 19 | 
             
              swift:
         | 
| 18 20 | 
             
              - timestamp_default_swift: Default
         | 
| 19 21 | 
             
              - timestamp_align_swift: Alignments
         | 
| @@ -3,3 +3,4 @@ export { default as TimestampAlign } from './_timestamp_align.jsx' | |
| 3 3 | 
             
            export { default as TimestampTimezones } from './_timestamp_timezones.jsx'
         | 
| 4 4 | 
             
            export { default as TimestampUpdated } from './_timestamp_updated.jsx'
         | 
| 5 5 | 
             
            export { default as TimestampElapsed } from './_timestamp_elapsed.jsx'
         | 
| 6 | 
            +
            export { default as TimestampUnstyled } from './_timestamp_unstyled.jsx'
         | 
| @@ -4,5 +4,9 @@ | |
| 4 4 | 
             
              data: object.data,
         | 
| 5 5 | 
             
              class: object.classname) do %>
         | 
| 6 6 |  | 
| 7 | 
            -
               | 
| 7 | 
            +
              <% if object.unstyled %>
         | 
| 8 | 
            +
                <div><%= object.timestamp_text %></div>
         | 
| 9 | 
            +
              <% else %>
         | 
| 10 | 
            +
                <%= pb_rails("caption", props: { text: object.timestamp_text, size: 'xs', dark: object.dark }) %>
         | 
| 11 | 
            +
              <% end %>
         | 
| 8 12 | 
             
            <% end %>
         |