playbook_ui 14.12.0.pre.alpha.play1887homeaddressfix5910 → 14.12.0.pre.alpha.playrailsinputmaskissue5933

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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +10 -3
  3. data/app/pb_kits/playbook/pb_advanced_table/Utilities/ActionBarAnimationHelper.ts +26 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +6 -6
  5. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +34 -21
  6. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +7 -11
  7. data/app/pb_kits/playbook/pb_home_address_street/docs/example.yml +0 -2
  8. data/app/pb_kits/playbook/pb_home_address_street/docs/index.js +0 -1
  9. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +2 -13
  10. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.html.erb +1 -1
  11. data/app/pb_kits/playbook/pb_text_input/index.js +52 -83
  12. data/dist/chunks/{_typeahead-CkemExmL.js → _typeahead-qhstadx9.js} +1 -1
  13. data/dist/chunks/_weekday_stacked-CAHsfiaG.js +45 -0
  14. data/dist/chunks/vendor.js +1 -1
  15. data/dist/playbook-doc.js +1 -1
  16. data/dist/playbook-rails-react-bindings.js +1 -1
  17. data/dist/playbook-rails.js +1 -1
  18. data/dist/playbook.css +1 -1
  19. data/lib/playbook/version.rb +1 -1
  20. metadata +5 -8
  21. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.html.erb +0 -11
  22. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.jsx +0 -22
  23. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_rails.md +0 -1
  24. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_react.md +0 -1
  25. data/dist/chunks/_weekday_stacked-C2x2rHKi.js +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f334463a8c895b5718c4265377f2c1a031eb85ab2107c42b20bb126aa1a8db7b
4
- data.tar.gz: 58c22a6fe27363f7dcbd5c189c10c225730fd4cec1676dabe044ecd9be51f4d2
3
+ metadata.gz: 5d0b37aeb1934fcd42145b3b00c5ccdb1d0d202320271ffb3f6cce025a8842c1
4
+ data.tar.gz: d4947bdab12110f001ddb7a4dccd6cb76632f77c5d834aa7ceb4c2ca3f090de9
5
5
  SHA512:
6
- metadata.gz: bafe3f9038a558afdee04a9e66544653dc4f0ae651663d1843c6cfb9d2cd9165822a4c24aeeba845ecf708f155c7d6b69cebcab421f0bd213501544b0e8eb654
7
- data.tar.gz: e18f1d32c6be05479b91f897076a680501a35818b8d9acf4ea5ca44fa29392875d436ac65eff3db9f27fa01516345982be900d4fcfcf5218b1ad8732567a4aa9
6
+ metadata.gz: ed89b4908906b35935f6dc4a95243dbcecc890b73cad32d5e91420d9ccaf762a4ab38fecb391b0c4c72af07d04222066a38b7e8a2c31881da1038457c91861b6
7
+ data.tar.gz: 07a73fd48069b741436c35ed29821d438f1f2114ff1d90eda9626ca2d6632fbf6a0c997eefe8398e0b37b1935fc929c45160e2a959574b7b4f400fd9195e7229
@@ -39,8 +39,15 @@ export const TableHeaderCell = ({
39
39
  sortIcon,
40
40
  table
41
41
  }: TableHeaderCellProps) => {
42
- const { sortControl, responsive, selectableRows, hasAnySubRows, showActionsBar, inlineRowLoading } =
43
- useContext(AdvancedTableContext);
42
+ const {
43
+ sortControl,
44
+ responsive,
45
+ selectableRows,
46
+ hasAnySubRows,
47
+ showActionsBar,
48
+ inlineRowLoading,
49
+ isActionBarVisible,
50
+ } = useContext(AdvancedTableContext);
44
51
 
45
52
  type justifyTypes = "none" | "center" | "start" | "end" | "between" | "around" | "evenly"
46
53
 
@@ -65,7 +72,7 @@ export const TableHeaderCell = ({
65
72
 
66
73
  const cellClassName = classnames(
67
74
  "table-header-cells",
68
- `${showActionsBar && "header-cells-with-actions"}`,
75
+ `${showActionsBar && isActionBarVisible && "header-cells-with-actions"}`,
69
76
  `${isChrome() ? "chrome-styles" : ""}`,
70
77
  `${enableSorting ? "table-header-cells-active" : ""}`,
71
78
  { "pinned-left": responsive === "scroll" && isPinnedLeft },
@@ -0,0 +1,26 @@
1
+ export const showActionBar = (elem: HTMLElement) => {
2
+ elem.style.display = "block";
3
+ const height = elem.scrollHeight + "px";
4
+ elem.style.height = height;
5
+ elem.classList.add("is-visible");
6
+ elem.style.overflow = "hidden";
7
+
8
+ window.setTimeout(() => {
9
+ if (elem.classList.contains("is-visible")) {
10
+ elem.style.height = "";
11
+ elem.style.overflow = "visible";
12
+ }
13
+ }, 300);
14
+ };
15
+
16
+ export const hideActionBar = (elem: HTMLElement) => {
17
+ elem.style.height = elem.scrollHeight + "px";
18
+ elem.offsetHeight;
19
+ window.setTimeout(() => {
20
+ elem.style.height = "0";
21
+ elem.style.overflow = "hidden";
22
+ }, 10);
23
+ window.setTimeout(() => {
24
+ elem.classList.remove("is-visible");
25
+ }, 300);
26
+ };
@@ -31,12 +31,12 @@
31
31
  width: 100%;
32
32
  }
33
33
 
34
- .row-selection-actions-card {
35
- border-bottom-right-radius: 0px !important;
36
- border-bottom-left-radius: 0px !important;
37
- border-bottom-color: transparent;
38
- }
39
-
34
+ .row-selection-actions-card {
35
+ border-bottom-right-radius: 0px !important;
36
+ border-bottom-left-radius: 0px !important;
37
+ border-bottom-color: transparent;
38
+ transition: height 300ms ease;
39
+ }
40
40
  .table-header-cells:first-child {
41
41
  min-width: 180px;
42
42
  }
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useCallback } from "react"
1
+ import React, { useState, useEffect, useCallback, useRef } from "react"
2
2
  import classnames from "classnames"
3
3
 
4
4
  import { GenericObject } from "../types"
@@ -27,6 +27,7 @@ import FlexItem from "../pb_flex/_flex_item"
27
27
  import AdvancedTableContext from "./Context/AdvancedTableContext"
28
28
 
29
29
  import { updateExpandAndCollapseState } from "./Utilities/ExpansionControlHelpers"
30
+ import { showActionBar, hideActionBar } from "./Utilities/ActionBarAnimationHelper"
30
31
 
31
32
  import { CustomCell } from "./Components/CustomCell"
32
33
  import { TableHeader } from "./SubKits/TableHeader"
@@ -295,6 +296,20 @@ const AdvancedTable = (props: AdvancedTableProps) => {
295
296
  const onPageChange = (page: number) => {
296
297
  table.setPageIndex(page - 1)
297
298
  }
299
+ //When to show the actions bar as a whole
300
+ const isActionBarVisible = selectableRows && showActionsBar && selectedRowsLength > 0
301
+
302
+ //Ref and useEffect for animating the actions bar
303
+ const cardRef = useRef(null);
304
+ useEffect(() => {
305
+ if (cardRef.current) {
306
+ if (isActionBarVisible) {
307
+ showActionBar(cardRef.current);
308
+ } else {
309
+ hideActionBar(cardRef.current);
310
+ }
311
+ }
312
+ }, [isActionBarVisible]);
298
313
 
299
314
  return (
300
315
  <div {...ariaProps}
@@ -311,6 +326,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
311
326
  expandedControl,
312
327
  handleExpandOrCollapse,
313
328
  inlineRowLoading,
329
+ isActionBarVisible,
314
330
  loading,
315
331
  responsive,
316
332
  setExpanded,
@@ -333,27 +349,24 @@ const AdvancedTable = (props: AdvancedTableProps) => {
333
349
  total={table.getPageCount()}
334
350
  />
335
351
  }
336
- {
337
- selectableRows && showActionsBar && (
338
- <Card className="row-selection-actions-card"
339
- padding="xs"
352
+ <Card
353
+ borderNone={!isActionBarVisible}
354
+ className={`${isActionBarVisible && "show-action-card row-selection-actions-card"}`}
355
+ htmlOptions={{ ref: cardRef as any }}
356
+ padding={`${isActionBarVisible ? "xs" : "none"}`}
357
+ >
358
+ <Flex alignItems="center"
359
+ justify="between"
360
+ >
361
+ <Caption color="light"
362
+ paddingLeft="xs"
363
+ size="xs"
340
364
  >
341
- <Flex alignItems="center"
342
- justify="between"
343
- >
344
- <Caption color="light"
345
- paddingLeft="xs"
346
- size="xs"
347
- >
348
- {selectedRowsLength} Selected
349
- </Caption>
350
- <FlexItem>
351
- {actions}
352
- </FlexItem>
353
- </Flex>
354
- </Card>
355
- )
356
- }
365
+ {selectedRowsLength} Selected
366
+ </Caption>
367
+ <FlexItem>{actions}</FlexItem>
368
+ </Flex>
369
+ </Card>
357
370
  <Table
358
371
  className={`${loading ? "content-loading" : ""}`}
359
372
  dark={dark}
@@ -18,7 +18,6 @@ type HomeAddressStreetProps = {
18
18
  className?: string,
19
19
  data?: { [key: string]: string },
20
20
  dark?: boolean,
21
- preserveCase?: boolean,
22
21
  emphasis: "street" | "city" | "none",
23
22
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
24
23
  homeId: string,
@@ -44,7 +43,6 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
44
43
  htmlOptions = {},
45
44
  homeId,
46
45
  homeUrl,
47
- preserveCase = false,
48
46
  target,
49
47
  newWindow,
50
48
  houseStyle,
@@ -79,8 +77,6 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
79
77
  return null
80
78
  }
81
79
 
82
- const formatStreetAdr = (address: string): string => preserveCase ? address : titleize(address)
83
-
84
80
  return (
85
81
  <div
86
82
  className={classes(className, dark)}
@@ -95,7 +91,7 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
95
91
  dark={dark}
96
92
  size={4}
97
93
  >
98
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
94
+ {joinPresent([titleize(address), houseStyle], ' · ')}
99
95
  </Title>
100
96
  <Title
101
97
  className="pb_home_address_street_address"
@@ -105,14 +101,14 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
105
101
  {titleize(addressCont)}
106
102
  </Title>
107
103
  <Body color="light">
108
- {`${titleize(city)}, ${state.toUpperCase()} ${zipcode}`}
104
+ {`${titleize(city)}, ${state} ${zipcode}`}
109
105
  </Body>
110
106
  </div>
111
107
  }
112
108
  {emphasis == 'city' &&
113
109
  <div>
114
110
  <Body color="light">
115
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
111
+ {joinPresent([titleize(address), houseStyle], ' · ')}
116
112
  </Body>
117
113
  <Body color="light">{titleize(addressCont)}</Body>
118
114
  <div>
@@ -122,7 +118,7 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
122
118
  size={4}
123
119
  tag="span"
124
120
  >
125
- {`${titleize(city)}, ${state.toUpperCase()}`}
121
+ {`${titleize(city)}, ${state}`}
126
122
  </Title>
127
123
  <Body
128
124
  color="light"
@@ -136,15 +132,15 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
136
132
  {emphasis == 'none' &&
137
133
  <div>
138
134
  <Body dark={dark}>
139
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
135
+ {joinPresent([titleize(address), houseStyle], ' · ')}
140
136
  </Body>
141
- <Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
137
+ <Body dark={dark}>{titleize(addressCont)}</Body>
142
138
  <div>
143
139
  <Body
144
140
  color="light"
145
141
  dark={dark}
146
142
  >
147
- {`${titleize(city)}, ${state.toUpperCase()} ${zipcode}`}
143
+ {`${titleize(city)}, ${state} ${zipcode}`}
148
144
  </Body>
149
145
  </div>
150
146
  </div>
@@ -5,14 +5,12 @@ examples:
5
5
  - home_address_street_emphasis: Emphasis
6
6
  - home_address_street_modified: Modified
7
7
  - home_address_street_link: Link
8
- - home_address_street_formatting: Formatting
9
8
 
10
9
  react:
11
10
  - home_address_street_default: Default
12
11
  - home_address_street_emphasis: Emphasis
13
12
  - home_address_street_modified: Modified
14
13
  - home_address_street_link: Link
15
- - home_address_street_formatting: Formatting
16
14
 
17
15
  swift:
18
16
  - home_address_street_default_swift: Default
@@ -2,4 +2,3 @@ export { default as HomeAddressStreetDefault } from './_home_address_street_defa
2
2
  export { default as HomeAddressStreetEmphasis } from './_home_address_street_emphasis.jsx'
3
3
  export { default as HomeAddressStreetModified } from './_home_address_street_modified.jsx'
4
4
  export { default as HomeAddressStreetLink } from './_home_address_street_link.jsx'
5
- export { default as HomeAddressStreetFormatting } from './_home_address_street_formatting.jsx'
@@ -18,7 +18,6 @@ module Playbook
18
18
  prop :state
19
19
  prop :zipcode
20
20
  prop :territory
21
- prop :preserve_case, default: false
22
21
  prop :dark, type: Playbook::Props::Boolean, default: false
23
22
 
24
23
  def classname
@@ -30,7 +29,7 @@ module Playbook
30
29
  end
31
30
 
32
31
  def city_state
33
- [city&.titleize, state&.upcase].join(", ")
32
+ [city&.titleize, state].join(", ")
34
33
  end
35
34
 
36
35
  def zip
@@ -38,7 +37,7 @@ module Playbook
38
37
  end
39
38
 
40
39
  def address_house_style
41
- [format_street_address, house_style].join(separator)
40
+ [address&.titleize, house_style].join(separator)
42
41
  end
43
42
 
44
43
  def address_house_style2
@@ -49,16 +48,6 @@ module Playbook
49
48
  house_style ? " \u00b7 " : ""
50
49
  end
51
50
 
52
- def format_street_address
53
- preserve_case ? address : custom_titleize(address)
54
- end
55
-
56
- def custom_titleize(str)
57
- return "" if str.nil?
58
-
59
- str.split(" ").map(&:capitalize).join(" ")
60
- end
61
-
62
51
  def city_emphasis_props
63
52
  {
64
53
  address_house_style: address_house_style,
@@ -38,7 +38,7 @@
38
38
  margin_bottom: "md",
39
39
  name: "currency_name",
40
40
  id: "example-currency",
41
- placeholder: "$0.00",
41
+ value: "$99.99",
42
42
  }) %>
43
43
 
44
44
  <style>
@@ -1,102 +1,71 @@
1
- export default class PbTextInput {
2
- static start() {
3
- const inputElements = document.querySelectorAll('[data-pb-input-mask="true"]');
4
-
5
- inputElements.forEach((inputElement) => {
6
- inputElement.addEventListener("input", (event) => {
7
- const maskType = inputElement.getAttribute("mask");
8
- const cursorPosition = inputElement.selectionStart;
9
-
10
- let rawValue = event.target.value;
11
- let formattedValue = rawValue;
12
-
13
- // Apply formatting based on the mask type
14
- switch (maskType) {
15
- case "currency":
16
- formattedValue = formatCurrency(rawValue);
17
- break;
18
- case "ssn":
19
- formattedValue = formatSSN(rawValue);
20
- break;
21
- case "postal_code":
22
- formattedValue = formatPostalCode(rawValue);
23
- break;
24
- case "zip_code":
25
- formattedValue = formatZipCode(rawValue);
26
- break;
27
- }
28
-
29
- // Update the sanitized input field in the same wrapper
30
- const sanitizedInput = inputElement
31
- .closest(".text_input_wrapper")
32
- ?.querySelector('[data="sanitized-pb-input"]');
33
-
34
- if (sanitizedInput) {
35
- switch (maskType) {
36
- case "ssn":
37
- sanitizedInput.value = sanitizeSSN(formattedValue);
38
- break;
39
- case "currency":
40
- sanitizedInput.value = sanitizeCurrency(formattedValue);
41
- break;
42
- default:
43
- sanitizedInput.value = formattedValue;
44
- }
45
- }
46
-
47
- inputElement.value = formattedValue;
48
- setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue);
49
- });
50
- });
1
+ import PbEnhancedElement from "../pb_enhanced_element"
2
+ import { INPUTMASKS } from "./inputMask"
51
3
 
4
+ export default class PbTextInput extends PbEnhancedElement {
5
+ static get selector() {
6
+ return '[data-pb-input-mask="true"]';
52
7
  }
53
- }
54
-
55
- function formatCurrency(value) {
56
- const numericValue = value.replace(/[^0-9]/g, "").slice(0, 15);
57
-
58
- if (!numericValue) return "";
59
-
60
- const dollars = parseFloat((parseInt(numericValue) / 100).toFixed(2));
61
- if (dollars === 0) return "";
62
8
 
63
- return new Intl.NumberFormat("en-US", {
64
- style: "currency",
65
- currency: "USD",
66
- maximumFractionDigits: 2,
67
- }).format(dollars);
68
- }
69
-
70
- function formatSSN(value) {
71
- const cleaned = value.replace(/\D/g, "").slice(0, 9);
72
- return cleaned
73
- .replace(/(\d{5})(?=\d)/, "$1-")
74
- .replace(/(\d{3})(?=\d)/, "$1-");
75
- }
9
+ connect() {
10
+ this.handleInput = this.handleInput.bind(this);
11
+ this.element.addEventListener("input", this.handleInput);
12
+ this.handleInput();
13
+ }
76
14
 
77
- function formatZipCode(value) {
78
- return value.replace(/\D/g, "").slice(0, 5);
79
- }
15
+ disconnect() {
16
+ this.element.removeEventListener("input", this.handleInput);
17
+ }
80
18
 
81
- function formatPostalCode(value) {
82
- const cleaned = value.replace(/\D/g, "").slice(0, 9);
83
- return cleaned.replace(/(\d{5})(?=\d)/, "$1-");
19
+ handleInput() {
20
+ const maskType = this.element.getAttribute("mask");
21
+ const cursorPosition = this.element.selectionStart;
22
+ const rawValue = this.element.value;
23
+ let formattedValue = rawValue;
24
+
25
+ const maskKey = {
26
+ currency: 'currency',
27
+ ssn: 'ssn',
28
+ postal_code: 'postalCode',
29
+ zip_code: 'zipCode',
30
+ }[maskType];
31
+
32
+ if (maskKey && INPUTMASKS[maskKey]) {
33
+ formattedValue = INPUTMASKS[maskKey].format(rawValue);
34
+ }
35
+
36
+ const sanitizedInput = this.element
37
+ .closest(".text_input_wrapper")
38
+ ?.querySelector('[data="sanitized-pb-input"]');
39
+
40
+ if (sanitizedInput) {
41
+ switch (maskType) {
42
+ case "ssn":
43
+ sanitizedInput.value = sanitizeSSN(formattedValue);
44
+ break;
45
+ case "currency":
46
+ sanitizedInput.value = sanitizeCurrency(formattedValue);
47
+ break;
48
+ default:
49
+ sanitizedInput.value = formattedValue;
50
+ }
51
+ }
52
+
53
+ this.element.value = formattedValue;
54
+ setCursorPosition(this.element, cursorPosition, rawValue, formattedValue);
55
+ }
84
56
  }
85
57
 
86
58
  function sanitizeSSN(input) {
87
- return input.replace(/\D/g, "");
59
+ return input.replace(/\D/g, "");
88
60
  }
89
61
 
90
62
  function sanitizeCurrency(input) {
91
- return input.replace(/[$,]/g, "");
63
+ return input.replace(/[$,]/g, "");
92
64
  }
93
65
 
94
- // function to set cursor position
95
66
  function setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue) {
96
67
  const difference = formattedValue.length - rawValue.length;
97
-
98
68
  const newPosition = Math.max(0, cursorPosition + difference);
99
-
100
69
  requestAnimationFrame(() => {
101
70
  inputElement.setSelectionRange(newPosition, newPosition);
102
71
  });