playbook_ui 14.8.0.pre.alpha.PLAY1615movenegativetoleftofcurrencysign4543 → 14.8.0.pre.alpha.pbntr661createstickyleftprop4612

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1129b60a8057cb4a47a1cd2a7fbfe1ab4a6566d84a3ee8413f494694d17d13b
4
- data.tar.gz: 1488209f50dca59f1e932ff6b53183e1772718e0d5664e1d7b05e49c0d2994df
3
+ metadata.gz: 447188fd32d5d83aeaf14c246e24bbb2ded7d4ef68ec21db96a48fc115a50d49
4
+ data.tar.gz: 4c1d2183a6df9ebefcb605e8aaeb52c097cdc1726c672a234237aa194b67c475
5
5
  SHA512:
6
- metadata.gz: 1e0e520ba271f69218c9f0b812bfac695491c19105b34a4df62d3ba7cfaa209f29a8bcab3dd08900910d2aca5920d1eb72b2d44d9eefb84a60b3538554d8b378
7
- data.tar.gz: c7ebb609bf8a7f21fb85cb161e0ddd39b798193e493cdef6bfd3d8feb821f8f837a5c6caeb37167d4ca33678fabbdf211dc704d89603fdcbf1d58116bfd4c8e9
6
+ metadata.gz: 99ea4d44f89369d8d928c441c86ebac5261bd849fda00bdb2490b209fb906232be43c480d49101c24f56c2fcacd23f662025e1dba331dd9472275e5d67040df5
7
+ data.tar.gz: b5e4d90132d0d728c6fb9c023b9ceeaf8ac64a017cdac314b5d85c774917a806540eb97dab62d7690112cbff97a395e794c271fb7375d4a3c50e6e13afe1abbc
@@ -6,12 +6,12 @@
6
6
  ) do %>
7
7
  <%= content.presence || object.input %>
8
8
  <% if object.indeterminate %>
9
- <span class="pb_checkbox_indeterminate">
9
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_indeterminate">
10
10
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon", fixed_width: true}) %>
11
11
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon hidden", fixed_width: true}) %>
12
12
  </span>
13
13
  <% else %>
14
- <span class="pb_checkbox_checkmark">
14
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
15
15
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
16
16
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
17
17
  </span>
@@ -18,10 +18,6 @@ module Playbook
18
18
  prop :form_spacing, type: Playbook::Props::Boolean,
19
19
  default: false
20
20
 
21
- def checked_html
22
- checked ? "checked='true'" : nil
23
- end
24
-
25
21
  def classname
26
22
  generate_classname("pb_checkbox_kit", checked_class) + indeterminate_class + error_class
27
23
  end
@@ -1,7 +1,84 @@
1
- <%= pb_rails("checkbox" , props: {
2
- text: "Select ",
3
- value: "checkbox-value",
4
- name: "main",
5
- indeterminate: true,
6
- id: "test-indeterminate-js"
7
- }) %>
1
+ <% checkboxes = [
2
+ { name: 'Coffee', id: 'coffee', checked: false },
3
+ { name: 'Ice Cream', id: 'ice-cream', checked: false },
4
+ { name: 'Chocolate', id: 'chocolate', checked: true }
5
+ ] %>
6
+
7
+ <%= pb_rails("table", props: { container: false, size: "md" }) do %>
8
+ <thead>
9
+ <tr>
10
+ <th>
11
+ <%= pb_rails("checkbox", props: {
12
+ checked: true,
13
+ text: "Uncheck All",
14
+ value: "checkbox-value",
15
+ name: "main-checkbox",
16
+ indeterminate: true,
17
+ id: "indeterminate-checkbox"
18
+ }) %>
19
+ </th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <% checkboxes.each do |checkbox| %>
25
+ <tr>
26
+ <td>
27
+ <%= pb_rails("checkbox", props: {
28
+ checked: checkbox[:checked],
29
+ text: checkbox[:name],
30
+ value: checkbox[:id],
31
+ name: "#{checkbox[:id]}-indeterminate-checkbox",
32
+ id: "#{checkbox[:id]}-indeterminate-checkbox",
33
+ }) %>
34
+ </td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ <% end %>
39
+
40
+ <script>
41
+ document.addEventListener('DOMContentLoaded', function() {
42
+ const mainCheckboxWrapper = document.getElementById('indeterminate-checkbox');
43
+ const mainCheckbox = document.getElementsByName("main-checkbox")[0];
44
+ const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="indeterminate-checkbox"]');
45
+
46
+ const updateMainCheckbox = () => {
47
+ // Count the number of checked child checkboxes
48
+ const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
49
+ // Determine if the main checkbox should be in an indeterminate state
50
+ const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
51
+
52
+ // Set the main checkbox states
53
+ mainCheckbox.indeterminate = indeterminate;
54
+ mainCheckbox.checked = checkedCount > 0;
55
+
56
+ // Determine the main checkbox label based on the number of checked checkboxes
57
+ const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
58
+
59
+ // Determine the icon class to add and remove based on the number of checked checkboxes
60
+ const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
61
+ const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
62
+
63
+ // Update main checkbox label
64
+ mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
65
+
66
+ // Add and remove the icon class to the main checkbox wrapper
67
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
68
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
69
+
70
+ // Toggle the visibility of the checkbox icon based on the indeterminate state
71
+ mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
72
+ mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
73
+ };
74
+
75
+ mainCheckbox.addEventListener('change', function() {
76
+ childCheckboxes.forEach(cb => cb.checked = this.checked);
77
+ updateMainCheckbox();
78
+ });
79
+
80
+ childCheckboxes.forEach(cb => {
81
+ cb.addEventListener('change', updateMainCheckbox);
82
+ });
83
+ });
84
+ </script>
@@ -101,11 +101,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
101
101
  return decimalPart ? `${formattedWhole}.${decimalPart}` : formattedWhole;
102
102
  }
103
103
 
104
- const swapNegative = size === "sm" && symbol !== ""
105
- const handleNegative = amount.startsWith("-") && swapNegative ? "-" : ""
106
- const getAbsoluteAmount = (amountString: string) => amountString.replace(/^-/,'')
107
- const getAbbrOrFormatAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount)
108
- const getAmount = swapNegative ? getAbsoluteAmount(getAbbrOrFormatAmount) : getAbbrOrFormatAmount
104
+ const getAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount)
109
105
  const getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null
110
106
  const getDecimalValue = abbreviate ? '' : getMatchingDecimalValue
111
107
 
@@ -122,7 +118,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
122
118
  <div className={`pb_currency_wrapper${variantClass || emphasizedClass}`}>
123
119
  {unstyled ? (
124
120
  <>
125
- <div>{handleNegative}{symbol}</div>
121
+ <div>{symbol}</div>
126
122
  <div>{getAmount}</div>
127
123
  <div>
128
124
  {getAbbreviation}
@@ -136,7 +132,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
136
132
  color="light"
137
133
  dark={dark}
138
134
  >
139
- {handleNegative}{symbol}
135
+ {symbol}
140
136
  </Body>
141
137
 
142
138
  <Title
@@ -3,12 +3,12 @@
3
3
 
4
4
  <div class=<%= "pb_currency_wrapper#{object.variant_class || object.emphasized_class}" %>>
5
5
  <% if object.unstyled %>
6
- <div><%= object.negative_sign %><%= object.symbol %></div>
6
+ <div><%= object.symbol %></div>
7
7
  <div><%= object.title_props[:text] %></div>
8
8
  <div><%= object.body_props[:text] %></div>
9
9
  <% else %>
10
10
  <%= pb_rails("body", props: object.currency_wrapper_props) do %>
11
- <%= object.negative_sign %><%= object.symbol %>
11
+ <%= object.symbol %>
12
12
  <% end %>
13
13
  <%= pb_rails("title", props: object.title_props) %>
14
14
  <%= pb_rails("body", props: object.body_props) %>
@@ -68,20 +68,12 @@ module Playbook
68
68
  def title_props
69
69
  {
70
70
  size: size_value,
71
- text: swap_negative ? absolute_amount(abbr_or_format_amount) : abbr_or_format_amount,
71
+ text: abbreviate ? abbreviated_value : formatted_amount,
72
72
  classname: "pb_currency_value",
73
73
  dark: dark,
74
74
  }
75
75
  end
76
76
 
77
- def abbr_or_format_amount
78
- abbreviate ? abbreviated_value : formatted_amount
79
- end
80
-
81
- def negative_sign
82
- amount.starts_with?("-") && swap_negative ? "-" : ""
83
- end
84
-
85
77
  def body_props
86
78
  {
87
79
  text: units_element,
@@ -167,14 +159,6 @@ module Playbook
167
159
  whole_value
168
160
  end
169
161
  end
170
-
171
- def absolute_amount(amount_string)
172
- amount_string.sub(/^-/, "")
173
- end
174
-
175
- def swap_negative
176
- size == "sm" && symbol != ""
177
- end
178
162
  end
179
163
  end
180
164
  end
@@ -53,6 +53,7 @@
53
53
  }
54
54
 
55
55
  .pb_dropdown_container {
56
+ position: absolute;
56
57
  background-color: $white;
57
58
  overflow: hidden;
58
59
  box-shadow: $shadow_deep;
@@ -3,7 +3,6 @@
3
3
  class: object.classname,
4
4
  data: object.data,
5
5
  id: object.id,
6
- style: object.container_style,
7
6
  **combined_html_options) do %>
8
7
  <%= pb_rails("list", props: {ordered: false, borderless: false}) do %>
9
8
  <% if content.present? %>
@@ -7,10 +7,6 @@ module Playbook
7
7
  generate_classname("pb_dropdown_container", "close", separator: " ")
8
8
  end
9
9
 
10
- def container_style
11
- "position: absolute"
12
- end
13
-
14
10
  def data
15
11
  Hash(prop(:data)).merge(dropdown_container: true)
16
12
  end
@@ -4,11 +4,11 @@ import { buildAriaProps, buildDataProps, buildHtmlProps } from '../utilities/pro
4
4
  import { globalProps, GlobalProps } from '../utilities/globalProps'
5
5
  import PbTable from '.'
6
6
  import {
7
- TableHead,
8
- TableHeader,
9
- TableBody,
10
- TableRow,
11
- TableCell,
7
+ TableHead,
8
+ TableHeader,
9
+ TableBody,
10
+ TableRow,
11
+ TableCell,
12
12
  } from "./subcomponents";
13
13
 
14
14
  type TableProps = {
@@ -28,6 +28,7 @@ type TableProps = {
28
28
  singleLine?: boolean,
29
29
  size?: "sm" | "md" | "lg",
30
30
  sticky?: boolean,
31
+ stickyLeftcolumn?: string[],
31
32
  striped?: boolean,
32
33
  tag?: "table" | "div",
33
34
  verticalBorder?: boolean,
@@ -51,6 +52,7 @@ const Table = (props: TableProps): React.ReactElement => {
51
52
  singleLine = false,
52
53
  size = 'sm',
53
54
  sticky = false,
55
+ stickyLeftcolumn = [],
54
56
  striped = false,
55
57
  tag = 'table',
56
58
  verticalBorder = false,
@@ -76,6 +78,7 @@ const Table = (props: TableProps): React.ReactElement => {
76
78
  'single-line': singleLine,
77
79
  'no-hover': disableHover,
78
80
  'sticky-header': sticky,
81
+ 'sticky-left-column': stickyLeftcolumn,
79
82
  'striped': striped,
80
83
  [outerPaddingCss]: outerPadding !== '',
81
84
  },
@@ -85,6 +88,56 @@ const Table = (props: TableProps): React.ReactElement => {
85
88
  className
86
89
  )
87
90
 
91
+ useEffect(() => {
92
+ const handleStickyColumns = () => {
93
+ let accumulatedWidth = 0;
94
+
95
+ stickyLeftcolumn.forEach((colId, index) => {
96
+ const isLastColumn = index === stickyLeftcolumn.length - 1;
97
+ const header = document.querySelector(`th[id="${colId}"]`);
98
+ const cells = document.querySelectorAll(`td[id="${colId}"]`);
99
+
100
+ if (header) {
101
+ header.classList.add('sticky');
102
+ (header as HTMLElement).style.left = `${accumulatedWidth}px`;
103
+
104
+ if (!isLastColumn) {
105
+ header.classList.add('with-border');
106
+ header.classList.remove('sticky-shadow');
107
+ } else {
108
+ header.classList.remove('with-border');
109
+ header.classList.add('sticky-shadow');
110
+ }
111
+
112
+ accumulatedWidth += (header as HTMLElement).offsetWidth;
113
+ }
114
+
115
+ cells.forEach((cell) => {
116
+ cell.classList.add('sticky');
117
+ (cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;
118
+
119
+ if (!isLastColumn) {
120
+ cell.classList.add('with-border');
121
+ cell.classList.remove('sticky-shadow');
122
+ } else {
123
+ cell.classList.remove('with-border');
124
+ cell.classList.add('sticky-shadow');
125
+ }
126
+ });
127
+ });
128
+ };
129
+
130
+ setTimeout(() => {
131
+ handleStickyColumns();
132
+ }, 10);
133
+
134
+ window.addEventListener('resize', handleStickyColumns);
135
+
136
+ return () => {
137
+ window.removeEventListener('resize', handleStickyColumns);
138
+ };
139
+ }, [stickyLeftcolumn]);
140
+
88
141
  useEffect(() => {
89
142
  const instance = new PbTable()
90
143
  instance.connect()
@@ -92,26 +145,52 @@ const Table = (props: TableProps): React.ReactElement => {
92
145
 
93
146
  return (
94
147
  <>
95
- {isTableTag ? (
96
- <table
97
- {...ariaProps}
98
- {...dataProps}
99
- {...htmlProps}
100
- className={classNames}
101
- id={id}
102
- >
103
- {children}
104
- </table>
105
- ) : (
106
- <div
107
- {...ariaProps}
108
- {...dataProps}
109
- {...htmlProps}
110
- className={classNames}
111
- id={id}
112
- >
113
- {children}
148
+ {responsive === 'scroll' ? (
149
+ <div className='table-responsive-scroll'>
150
+ {isTableTag ? (
151
+ <table
152
+ {...ariaProps}
153
+ {...dataProps}
154
+ {...htmlProps}
155
+ className={classNames}
156
+ id={id}
157
+ >
158
+ {children}
159
+ </table>
160
+ ) : (
161
+ <div
162
+ {...ariaProps}
163
+ {...dataProps}
164
+ {...htmlProps}
165
+ className={classNames}
166
+ id={id}
167
+ >
168
+ {children}
169
+ </div>
170
+ )}
114
171
  </div>
172
+ ) : (
173
+ isTableTag ? (
174
+ <table
175
+ {...ariaProps}
176
+ {...dataProps}
177
+ {...htmlProps}
178
+ className={classNames}
179
+ id={id}
180
+ >
181
+ {children}
182
+ </table>
183
+ ) : (
184
+ <div
185
+ {...ariaProps}
186
+ {...dataProps}
187
+ {...htmlProps}
188
+ className={classNames}
189
+ id={id}
190
+ >
191
+ {children}
192
+ </div>
193
+ )
115
194
  )}
116
195
  </>
117
196
  )
@@ -0,0 +1,87 @@
1
+ import React from 'react'
2
+ import Table from '../_table'
3
+
4
+ const TableStickyLeftColumns = () => {
5
+ return (
6
+ <Table
7
+ responsive="scroll"
8
+ size="md"
9
+ stickyLeftcolumn={["1", "2", "3"]}
10
+ >
11
+ <thead>
12
+ <tr>
13
+ <th id="1">{'Column 1'}</th>
14
+ <th id="2">{'Column 2'}</th>
15
+ <th id="3">{'Column 3'}</th>
16
+ <th>{'Column 4'}</th>
17
+ <th>{'Column 5'}</th>
18
+ <th>{'Column 6'}</th>
19
+ <th>{'Column 7'}</th>
20
+ <th>{'Column 8'}</th>
21
+ <th>{'Column 9'}</th>
22
+ <th>{'Column 10'}</th>
23
+ <th>{'Column 11'}</th>
24
+ <th>{'Column 12'}</th>
25
+ <th>{'Column 13'}</th>
26
+ <th>{'Column 14'}</th>
27
+ <th>{'Column 15'}</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td id="1">{'Value 1'}</td>
33
+ <td id="2">{'Value 2'}</td>
34
+ <td id="3">{'Value 3'}</td>
35
+ <td>{'Value 4'}</td>
36
+ <td>{'Value 5'}</td>
37
+ <td>{'Value 6'}</td>
38
+ <td>{'Value 7'}</td>
39
+ <td>{'Value 8'}</td>
40
+ <td>{'Value 9'}</td>
41
+ <td>{'Value 10'}</td>
42
+ <td>{'Value 11'}</td>
43
+ <td>{'Value 12'}</td>
44
+ <td>{'Value 13'}</td>
45
+ <td>{'Value 14'}</td>
46
+ <td>{'Value 15'}</td>
47
+ </tr>
48
+ <tr>
49
+ <td id="1">{'Value 1'}</td>
50
+ <td id="2">{'Value 2'}</td>
51
+ <td id="3">{'Value 3'}</td>
52
+ <td>{'Value 4'}</td>
53
+ <td>{'Value 5'}</td>
54
+ <td>{'Value 6'}</td>
55
+ <td>{'Value 7'}</td>
56
+ <td>{'Value 8'}</td>
57
+ <td>{'Value 9'}</td>
58
+ <td>{'Value 10'}</td>
59
+ <td>{'Value 11'}</td>
60
+ <td>{'Value 12'}</td>
61
+ <td>{'Value 13'}</td>
62
+ <td>{'Value 14'}</td>
63
+ <td>{'Value 15'}</td>
64
+ </tr>
65
+ <tr>
66
+ <td id="1">{'Value 1'}</td>
67
+ <td id="2">{'Value 2'}</td>
68
+ <td id="3">{'Value 3'}</td>
69
+ <td>{'Value 4'}</td>
70
+ <td>{'Value 5'}</td>
71
+ <td>{'Value 6'}</td>
72
+ <td>{'Value 7'}</td>
73
+ <td>{'Value 8'}</td>
74
+ <td>{'Value 9'}</td>
75
+ <td>{'Value 10'}</td>
76
+ <td>{'Value 11'}</td>
77
+ <td>{'Value 12'}</td>
78
+ <td>{'Value 13'}</td>
79
+ <td>{'Value 14'}</td>
80
+ <td>{'Value 15'}</td>
81
+ </tr>
82
+ </tbody>
83
+ </Table>
84
+ )
85
+ }
86
+
87
+ export default TableStickyLeftColumns
@@ -0,0 +1,2 @@
1
+ The `stickyLeftColumn` prop expects an array of the column ids you want to be sticky. Make sure to add the corresponding id to the `<th>` and `<td>`.
2
+ If you are using the sub-component variant, then you will pass the id to `<Table.Header>` and `<Table.Cell>`
@@ -33,6 +33,7 @@ examples:
33
33
  - table_md: Medium
34
34
  - table_lg: Large
35
35
  - table_sticky: Sticky Header
36
+ - table_sticky_left_columns: Sticky Left Column
36
37
  - table_alignment_row: Row Alignment
37
38
  - table_alignment_column: Cell Alignment
38
39
  - table_alignment_shift_row: Row Shift
@@ -25,3 +25,4 @@ export { default as TableDiv } from './_table_div.jsx'
25
25
  export { default as TableWithSubcomponents } from './_table_with_subcomponents.jsx'
26
26
  export { default as TableWithSubcomponentsAsDivs } from './_table_with_subcomponents_as_divs.jsx'
27
27
  export { default as TableOuterPadding } from './_table_outer_padding.jsx'
28
+ export { default as TableStickyLeftColumns } from './_table_sticky_left_columns.jsx'
@@ -20,3 +20,5 @@
20
20
  @import "table_header";
21
21
  @import "striped";
22
22
  @import "outer_padding";
23
+ @import "sticky_columns";
24
+ @import "scroll";
@@ -0,0 +1,4 @@
1
+ .table-responsive-scroll {
2
+ display: block;
3
+ overflow-x: auto;
4
+ }
@@ -0,0 +1,18 @@
1
+ @import "../../tokens/colors";
2
+
3
+ [class^="pb_table"] {
4
+ .sticky {
5
+ position: sticky !important;
6
+ left: 0;
7
+ z-index: 1;
8
+ background-color: white;
9
+ }
10
+
11
+ .with-border {
12
+ border-right: 1px solid $border_light !important;
13
+ }
14
+
15
+ .sticky-shadow {
16
+ box-shadow: 4px 0 10px rgba(60, 106, 172, 0.16) !important;
17
+ }
18
+ }
@@ -2,6 +2,7 @@
2
2
  @import "../tokens/border_radius";
3
3
  @import "../tokens/spacing";
4
4
  @import "../tokens/shadows";
5
+ @import "../tokens/positioning";
5
6
 
6
7
  [class^=pb_typeahead_kit] {
7
8
  .typeahead-kit-select__option {
@@ -99,6 +100,7 @@
99
100
  .typeahead-kit-select__menu {
100
101
  background-color: $bg_dark;
101
102
  color: $white;
103
+ z-index: $z_1;
102
104
  }
103
105
  .typeahead-kit-select__option:hover {
104
106
  background-color: $active_dark;
@@ -182,6 +184,7 @@
182
184
  }
183
185
 
184
186
  .typeahead-kit-select__menu {
187
+ z-index: $z_1;
185
188
  .typeahead-kit-select__menu-list {
186
189
  padding: 0;
187
190
  }