playbook_ui 15.1.0.pre.alpha.PLAY2468phonenuminputvalidation10803 → 15.1.0.pre.alpha.play252710946
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/pb_button/docs/_button_managed_disabled.html.erb +31 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled.md +7 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.html.erb +21 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.md +7 -0
- data/app/pb_kits/playbook/pb_button/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_button/index.js +99 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +13 -2
- data/app/pb_kits/playbook/pb_form/pb_form_validation.js +8 -40
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +2 -51
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +39 -1
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +2 -0
- data/dist/chunks/{_line_graph-Bkn-wx30.js → _line_graph-DwC5jqYQ.js} +1 -1
- data/dist/chunks/{_typeahead-DkRYiut7.js → _typeahead-4Ud3FHDA.js} +1 -1
- data/dist/chunks/{_weekday_stacked-BUjWQnqn.js → _weekday_stacked-CygSRiZe.js} +1 -1
- data/dist/chunks/pb_form_validation-CleM960_.js +1 -0
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +11 -6
- data/dist/chunks/pb_form_validation-B4uRmBwC.js +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1356285c2892298ab0d74134116ab03ac8559495657fddba5c09715c495b8f8b
|
|
4
|
+
data.tar.gz: e780800f41ea2ca322b7cfb5e15b1e0b8ca1b58ff949e196771987b45a659b79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0930a43f3351acff7849b6eee6c89b565d5454d59a7b81aa4e6b08571d353203c9d47894c4c1cbeb1c3f17d0106fcbe1e7f77a6958cc176ce5f1a2143393aef6'
|
|
7
|
+
data.tar.gz: ae3b1306ae43c73b5a86f949cccd21cead3e2c74b81f59caee59f80b8b53509fe791ef4bc54000580526f29d82f77cf82e11eccf23f69d8173ac8174b675fd2e
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<%= pb_rails("body", props: { text: "Click to disable the Buttons below", id: "toggle-disabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
|
|
2
|
+
<%= pb_rails("body", props: { text: "Click to enable the Buttons below", id: "toggle-enabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
|
|
3
|
+
|
|
4
|
+
<%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
|
|
5
|
+
<%= pb_rails("button", props: { text: "I am a Button", id: "normal_managed_button", data:{pb_button_managed: true}, margin_right: "lg" }) %>
|
|
6
|
+
<%= pb_rails("button", props: { text: "I am an <a> Button", id: "a_tag_managed_button", tag:"a", data:{pb_button_managed: true}, link: "http://google.com"}) %>
|
|
7
|
+
<% end %>
|
|
8
|
+
<script>
|
|
9
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
10
|
+
const disableTrigger = document.querySelector('#toggle-disabled-demo')
|
|
11
|
+
const enableTrigger = document.querySelector('#toggle-enabled-demo')
|
|
12
|
+
|
|
13
|
+
// Find the Buttons you want to 'manage'
|
|
14
|
+
const btn = document.querySelector('#normal_managed_button');
|
|
15
|
+
const link = document.querySelector('#a_tag_managed_button');
|
|
16
|
+
|
|
17
|
+
disableTrigger.addEventListener('click', (e) => {
|
|
18
|
+
// Disable default button
|
|
19
|
+
btn.setAttribute('disabled', true)
|
|
20
|
+
// Disable a tag button
|
|
21
|
+
link.setAttribute('aria-disabled', 'true')
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
enableTrigger.addEventListener('click', (e) => {
|
|
25
|
+
// Enable default button
|
|
26
|
+
btn.removeAttribute('disabled')
|
|
27
|
+
// Enable a tag button
|
|
28
|
+
link.removeAttribute('aria-disabled')
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
If needing to toggle the disabled state of the Button dynamically (for example, within a Turbo or Stimulus context), you can now do so in rails using the `pb-button-managed` data attribute.
|
|
2
|
+
|
|
3
|
+
1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
|
|
4
|
+
|
|
5
|
+
2) To toggle enabled/disabled state via attributes: for buttons set/remove disabled, for links set/remove aria-disabled="true". This will handle disabling the button, preventing clicks as well as all style changes so you don't have to.
|
|
6
|
+
|
|
7
|
+
Click to enable or disable the buttons above and view the code snippet below for details!
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%= pb_rails("body", props: { text: "Click to disable the Button below", id: "toggle-disabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
|
|
2
|
+
<%= pb_rails("body", props: { text: "Click to enable the Button below", id: "toggle-enabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
|
|
3
|
+
<br/>
|
|
4
|
+
<%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
|
|
5
|
+
<%= pb_rails("button", props: { text: "Watch me Change!", id: "managed_button_with_helper", data:{pb_button_managed: true} }) %>
|
|
6
|
+
<% end %>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
10
|
+
const disable = document.querySelector('#toggle-disabled-demo-with-helper')
|
|
11
|
+
const enable = document.querySelector('#toggle-enabled-demo-with-helper')
|
|
12
|
+
|
|
13
|
+
// Find the Button you want to 'manage'
|
|
14
|
+
const demoBtn = document.querySelector('#managed_button_with_helper')
|
|
15
|
+
|
|
16
|
+
// Use the pbButton object created by the kit to call the enable/disable methods
|
|
17
|
+
disable.addEventListener('click', (e) => {demoBtn._pbButton.disable()});
|
|
18
|
+
enable.addEventListener('click', (e) => {demoBtn._pbButton.enable()});
|
|
19
|
+
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
The disabled state for the button can also be toggled via small helpers available through the `pb-button-managed` data attribute.
|
|
2
|
+
|
|
3
|
+
1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
|
|
4
|
+
|
|
5
|
+
2) Toggle state via the provided `_pbButton.disable()` and `_pbButton.enable()` helpers as shown in the code snippet below.
|
|
6
|
+
|
|
7
|
+
Click to enable or disable the buttons above to see this in action!
|
|
@@ -11,6 +11,8 @@ examples:
|
|
|
11
11
|
- button_options: Button Additional Options
|
|
12
12
|
- button_size: Button Size
|
|
13
13
|
- button_form: Button Form Attribute
|
|
14
|
+
- button_managed_disabled: Button Toggle Disabled State
|
|
15
|
+
- button_managed_disabled_helper: Button Toggle Disabled State Helper
|
|
14
16
|
|
|
15
17
|
react:
|
|
16
18
|
- button_default: Button Variants
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import PbEnhancedElement from "../pb_enhanced_element"
|
|
2
|
+
|
|
3
|
+
const BUTTON_SELECTOR = "[data-pb-button-managed]"
|
|
4
|
+
|
|
5
|
+
export default class PbButton extends PbEnhancedElement {
|
|
6
|
+
static get selector() {
|
|
7
|
+
return BUTTON_SELECTOR
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
connect() {
|
|
11
|
+
this._attrManaged = this._attributesPresent()
|
|
12
|
+
this.element._pbButton = this
|
|
13
|
+
|
|
14
|
+
this._onClick = (e) => {
|
|
15
|
+
if (this.isDisabled()) {
|
|
16
|
+
e.preventDefault()
|
|
17
|
+
e.stopImmediatePropagation()
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
this.element.addEventListener("click", this._onClick, true)
|
|
21
|
+
|
|
22
|
+
if (this._attrManaged) this._syncClassesFromAttributes()
|
|
23
|
+
|
|
24
|
+
this._observer = new MutationObserver(() => {
|
|
25
|
+
this._attrManaged = true
|
|
26
|
+
this._syncClassesFromAttributes()
|
|
27
|
+
})
|
|
28
|
+
this._observer.observe(this.element, {
|
|
29
|
+
attributes: true,
|
|
30
|
+
attributeFilter: ["disabled", "aria-disabled"],
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
disconnect() {
|
|
35
|
+
this.element.removeEventListener("click", this._onClick, true)
|
|
36
|
+
this._observer?.disconnect()
|
|
37
|
+
delete this.element._pbButton
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
disable() { this.setDisabled(true) }
|
|
41
|
+
enable() { this.setDisabled(false) }
|
|
42
|
+
|
|
43
|
+
setDisabled(state) {
|
|
44
|
+
if (this._isButton()) {
|
|
45
|
+
state
|
|
46
|
+
? this.element.setAttribute("disabled", "disabled")
|
|
47
|
+
: this.element.removeAttribute("disabled")
|
|
48
|
+
} else {
|
|
49
|
+
state
|
|
50
|
+
? this.element.setAttribute("aria-disabled", "true")
|
|
51
|
+
: this.element.removeAttribute("aria-disabled")
|
|
52
|
+
}
|
|
53
|
+
this._attrManaged = true
|
|
54
|
+
this._applyClassState(state)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
isDisabled() {
|
|
58
|
+
if (this._isButton()) {
|
|
59
|
+
if (this.element.hasAttribute("disabled")) return true
|
|
60
|
+
if (this._attrManaged && !this.element.hasAttribute("disabled")) return false
|
|
61
|
+
} else {
|
|
62
|
+
const aria = this.element.getAttribute("aria-disabled")
|
|
63
|
+
if (aria === "true") return true
|
|
64
|
+
if (this._attrManaged && aria !== "true") return false
|
|
65
|
+
}
|
|
66
|
+
return this.element.classList.contains("pb_button_disabled")
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_isButton() {
|
|
70
|
+
return this.element.tagName === "BUTTON"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_attributesPresent() {
|
|
74
|
+
return this.element.hasAttribute("disabled") || this.element.hasAttribute("aria-disabled")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_syncClassesFromAttributes() {
|
|
78
|
+
const state = this._attrDisabledState()
|
|
79
|
+
const disabled = (state === null) ? false : state
|
|
80
|
+
this._applyClassState(disabled)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_attrDisabledState() {
|
|
84
|
+
if (this._isButton()) {
|
|
85
|
+
return this.element.hasAttribute("disabled") ? true : null
|
|
86
|
+
} else {
|
|
87
|
+
const aria = this.element.getAttribute("aria-disabled")
|
|
88
|
+
if (aria === "true") return true
|
|
89
|
+
if (aria === "false") return false
|
|
90
|
+
return this.element.hasAttribute("aria-disabled") ? false : null
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_applyClassState(disabled) {
|
|
95
|
+
this.element.classList.toggle("pb_button_disabled", !!disabled)
|
|
96
|
+
this.element.classList.toggle("pb_button_enabled", !disabled)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
@@ -21,6 +21,15 @@
|
|
|
21
21
|
]
|
|
22
22
|
%>
|
|
23
23
|
|
|
24
|
+
<%
|
|
25
|
+
example_typeahead_options = [
|
|
26
|
+
{ label: 'Orange', value: '#FFA500' },
|
|
27
|
+
{ label: 'Red', value: '#FF0000' },
|
|
28
|
+
{ label: 'Green', value: '#00FF00' },
|
|
29
|
+
{ label: 'Blue', value: '#0000FF' },
|
|
30
|
+
]
|
|
31
|
+
%>
|
|
32
|
+
|
|
24
33
|
<% treeData = [{
|
|
25
34
|
label: "Power Home Remodeling",
|
|
26
35
|
value: "Power Home Remodeling",
|
|
@@ -88,9 +97,11 @@
|
|
|
88
97
|
}] %>
|
|
89
98
|
|
|
90
99
|
<%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
|
|
91
|
-
<%= form.typeahead :
|
|
100
|
+
<%= form.typeahead :example_typeahead_validation_rails, props: { data: { typeahead_example2: true, user: {} }, label: true, placeholder: "Search for a user", required: true, validation: { message: "Please select a user." } } %>
|
|
101
|
+
<%= form.typeahead :example_typeahead_validation, props: { options: example_typeahead_options, pills: true, label: "Example Typeahead (React Rendered)", placeholder: "Search for a user", required: true, validation: { message: "Please select a color." } } %>
|
|
102
|
+
<%= form.typeahead :example_typeahead_validation_2, props: { options: example_typeahead_options, pills: true, label: "Example Typeahead 2 (React Rendered)", placeholder: "Search for a user", required: true } %>
|
|
92
103
|
<%= form.text_field :example_text_field_validation, props: { label: true, required: true } %>
|
|
93
|
-
<%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field", hidden_inputs: true
|
|
104
|
+
<%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field", hidden_inputs: true } %>
|
|
94
105
|
<%= form.email_field :example_email_field_validation, props: { label: true, required: true } %>
|
|
95
106
|
<%= form.number_field :example_number_field_validation, props: { label: true, required: true } %>
|
|
96
107
|
<%= form.search_field :example_project_number_validation, props: { label: true, required: true, validation: { pattern: "[0-9]{2}-[0-9]{5}", message: "Please enter a valid project number (example: 33-12345)." } } %>
|
|
@@ -2,14 +2,12 @@ import PbEnhancedElement from '../pb_enhanced_element'
|
|
|
2
2
|
import { debounce } from '../utilities/object'
|
|
3
3
|
|
|
4
4
|
// Kit selectors
|
|
5
|
-
const KIT_SELECTOR
|
|
6
|
-
const ERROR_MESSAGE_SELECTOR
|
|
7
|
-
const PHONE_NUMBER_INPUT_SELECTOR = '.pb_phone_number_input'
|
|
5
|
+
const KIT_SELECTOR = '[class^="pb_"][class*="_kit"]'
|
|
6
|
+
const ERROR_MESSAGE_SELECTOR = '.pb_body_kit_negative'
|
|
8
7
|
|
|
9
8
|
// Validation selectors
|
|
10
|
-
const FORM_SELECTOR
|
|
11
|
-
const REQUIRED_FIELDS_SELECTOR
|
|
12
|
-
const PHONE_NUMBER_VALIDATION_ERROR_SELECTOR = '[data-pb-phone-validation-error="true"]'
|
|
9
|
+
const FORM_SELECTOR = 'form[data-pb-form-validation="true"]'
|
|
10
|
+
const REQUIRED_FIELDS_SELECTOR = 'input[required],textarea[required],select[required]'
|
|
13
11
|
|
|
14
12
|
const FIELD_EVENTS = [
|
|
15
13
|
'change',
|
|
@@ -30,14 +28,6 @@ class PbFormValidation extends PbEnhancedElement {
|
|
|
30
28
|
}, 250), false)
|
|
31
29
|
})
|
|
32
30
|
})
|
|
33
|
-
|
|
34
|
-
// Add event listener to check for phone number validation errors
|
|
35
|
-
this.element.addEventListener('submit', (event) => {
|
|
36
|
-
if (this.hasPhoneNumberValidationErrors()) {
|
|
37
|
-
event.preventDefault()
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
31
|
}
|
|
42
32
|
|
|
43
33
|
validateFormField(event) {
|
|
@@ -55,18 +45,10 @@ class PbFormValidation extends PbEnhancedElement {
|
|
|
55
45
|
|
|
56
46
|
showValidationMessage(target) {
|
|
57
47
|
const { parentElement } = target
|
|
58
|
-
const kitElement = parentElement.closest(KIT_SELECTOR)
|
|
59
|
-
|
|
60
|
-
// Skip error message container for Phone Number Input as it handles its own errors
|
|
61
|
-
// as the closest kitElement is "pb_text_input_kit mb_sm" for Phone Number Input,
|
|
62
|
-
// we target the parent element of kitElement to check
|
|
63
|
-
if (kitElement && kitElement.parentElement.matches(PHONE_NUMBER_INPUT_SELECTOR)) {
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
48
|
|
|
67
49
|
// ensure clean error message state
|
|
68
50
|
this.clearError(target)
|
|
69
|
-
|
|
51
|
+
parentElement.closest(KIT_SELECTOR).classList.add('error')
|
|
70
52
|
|
|
71
53
|
// set the error message element
|
|
72
54
|
const errorMessageContainer = this.errorMessageContainer
|
|
@@ -81,23 +63,9 @@ class PbFormValidation extends PbEnhancedElement {
|
|
|
81
63
|
|
|
82
64
|
clearError(target) {
|
|
83
65
|
const { parentElement } = target
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
kitElement.classList.remove('error')
|
|
88
|
-
|
|
89
|
-
// Only remove error message container for non-Phone Number Input kits
|
|
90
|
-
if (!kitElement.matches(PHONE_NUMBER_INPUT_SELECTOR)) {
|
|
91
|
-
const errorMessageContainer = parentElement.querySelector(ERROR_MESSAGE_SELECTOR)
|
|
92
|
-
if (errorMessageContainer) errorMessageContainer.remove()
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Check if there are phone number input errors
|
|
98
|
-
hasPhoneNumberValidationErrors() {
|
|
99
|
-
const phoneNumberErrors = this.element.querySelectorAll(PHONE_NUMBER_VALIDATION_ERROR_SELECTOR)
|
|
100
|
-
return phoneNumberErrors.length > 0
|
|
66
|
+
parentElement.closest(KIT_SELECTOR).classList.remove('error')
|
|
67
|
+
const errorMessageContainer = parentElement.querySelector(ERROR_MESSAGE_SELECTOR)
|
|
68
|
+
if (errorMessageContainer) errorMessageContainer.remove()
|
|
101
69
|
}
|
|
102
70
|
|
|
103
71
|
get errorMessageContainer() {
|
|
@@ -110,35 +110,18 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
110
110
|
|
|
111
111
|
const inputRef = useRef<HTMLInputElement | null>(null)
|
|
112
112
|
const itiRef = useRef<any>(null);
|
|
113
|
-
const wrapperRef = useRef<HTMLDivElement | null>(null); // Add wrapper ref
|
|
114
113
|
const [inputValue, setInputValue] = useState(value)
|
|
115
114
|
const [error, setError] = useState(props.error)
|
|
116
115
|
const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
|
|
117
116
|
const [selectedData, setSelectedData] = useState()
|
|
118
117
|
const [hasTyped, setHasTyped] = useState(false)
|
|
119
118
|
|
|
120
|
-
// Function to update validation state on the wrapper element
|
|
121
|
-
// Only applies when input is required
|
|
122
|
-
const updateValidationState = (hasError: boolean) => {
|
|
123
|
-
if (wrapperRef.current && required) {
|
|
124
|
-
if (hasError) {
|
|
125
|
-
wrapperRef.current.setAttribute('data-pb-phone-validation-error', 'true')
|
|
126
|
-
} else {
|
|
127
|
-
wrapperRef.current.removeAttribute('data-pb-phone-validation-error')
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
119
|
useEffect(() => {
|
|
133
|
-
|
|
134
|
-
if (hasError) {
|
|
120
|
+
if ((error ?? '').length > 0) {
|
|
135
121
|
onValidate(false)
|
|
136
122
|
} else {
|
|
137
123
|
onValidate(true)
|
|
138
124
|
}
|
|
139
|
-
|
|
140
|
-
// Update validation state whenever error changes
|
|
141
|
-
updateValidationState(hasError)
|
|
142
125
|
}, [error, onValidate])
|
|
143
126
|
|
|
144
127
|
/*
|
|
@@ -152,10 +135,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
152
135
|
setInputValue("")
|
|
153
136
|
setError("")
|
|
154
137
|
setHasTyped(false)
|
|
155
|
-
// Only clear validation state if field was required
|
|
156
|
-
if (required) {
|
|
157
|
-
updateValidationState(false)
|
|
158
|
-
}
|
|
159
138
|
},
|
|
160
139
|
inputNode() {
|
|
161
140
|
return inputRef.current
|
|
@@ -185,13 +164,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
185
164
|
|
|
186
165
|
const validateTooShortNumber = (itiInit: any) => {
|
|
187
166
|
if (!itiInit) return
|
|
188
|
-
|
|
189
|
-
// If field is empty, don't show "too short" error
|
|
190
|
-
if (!inputValue || inputValue.trim() === '') {
|
|
191
|
-
setError('')
|
|
192
|
-
return false
|
|
193
|
-
}
|
|
194
|
-
|
|
195
167
|
if (itiInit.getValidationError() === ValidationError.TooShort) {
|
|
196
168
|
return showFormattedError('too short')
|
|
197
169
|
} else {
|
|
@@ -240,26 +212,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
240
212
|
}
|
|
241
213
|
}
|
|
242
214
|
|
|
243
|
-
// Validation for required empty fields
|
|
244
|
-
const validateRequiredField = () => {
|
|
245
|
-
if (required && (!inputValue || inputValue.trim() === '')) {
|
|
246
|
-
setError('Missing phone number')
|
|
247
|
-
return true
|
|
248
|
-
}
|
|
249
|
-
return false
|
|
250
|
-
}
|
|
251
215
|
|
|
252
216
|
const validateErrors = () => {
|
|
253
|
-
// If field is empty, only show required field error if applicable
|
|
254
|
-
if (!inputValue || inputValue.trim() === '') {
|
|
255
|
-
if (validateRequiredField()) return
|
|
256
|
-
// Clear any existing errors if field is empty and not required
|
|
257
|
-
if (!required) {
|
|
258
|
-
setError('')
|
|
259
|
-
}
|
|
260
|
-
return
|
|
261
|
-
}
|
|
262
|
-
|
|
263
217
|
if (!hasTyped && !error) return
|
|
264
218
|
|
|
265
219
|
if (itiRef.current) isValid(itiRef.current.isValidNumber())
|
|
@@ -356,10 +310,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
356
310
|
value: inputValue
|
|
357
311
|
}
|
|
358
312
|
|
|
359
|
-
let wrapperProps: Record<string, unknown> = {
|
|
360
|
-
className: classes,
|
|
361
|
-
ref: wrapperRef // Add ref to wrapper
|
|
362
|
-
}
|
|
313
|
+
let wrapperProps: Record<string, unknown> = { className: classes }
|
|
363
314
|
|
|
364
315
|
if (!isEmpty(aria)) textInputProps = {...textInputProps, ...ariaProps}
|
|
365
316
|
if (!isEmpty(data)) wrapperProps = {...wrapperProps, ...dataProps}
|
|
@@ -53,6 +53,8 @@ type TypeaheadProps = {
|
|
|
53
53
|
pillColor?: "primary" | "neutral" | "success" | "warning" | "error" | "info" | "data_1" | "data_2" | "data_3" | "data_4" | "data_5" | "data_6" | "data_7" | "data_8" | "windows" | "siding" | "roofing" | "doors" | "gutters" | "solar" | "insulation" | "accessories",
|
|
54
54
|
onChange?: any,
|
|
55
55
|
optionsByContext?: Record<string, Array<{ label: string; value?: string }>>
|
|
56
|
+
required?: boolean,
|
|
57
|
+
validation?: { message: string },
|
|
56
58
|
searchContextSelector?: string,
|
|
57
59
|
clearOnContextChange?: boolean,
|
|
58
60
|
preserveSearchInput?: boolean,
|
|
@@ -94,12 +96,16 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
94
96
|
onChange,
|
|
95
97
|
optionsByContext = {},
|
|
96
98
|
searchContextSelector,
|
|
99
|
+
required = false,
|
|
100
|
+
validation,
|
|
97
101
|
clearOnContextChange = false,
|
|
98
102
|
preserveSearchInput = false, // Default to false to maintain backward compatibility
|
|
99
103
|
...props
|
|
100
104
|
}: TypeaheadProps) => {
|
|
101
105
|
// State to manage the input value when preserveSearchInput is true
|
|
102
106
|
const [inputValue, setInputValue] = useState("")
|
|
107
|
+
// State to track if form has been submitted to control validation display for react rendered rails kit
|
|
108
|
+
const [formSubmitted, setFormSubmitted] = useState(false)
|
|
103
109
|
|
|
104
110
|
// If preserveSearchInput is true, we need to control the input value
|
|
105
111
|
const handleInputChange = preserveSearchInput
|
|
@@ -135,6 +141,7 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
135
141
|
|
|
136
142
|
const selectProps = {
|
|
137
143
|
cacheOptions: true,
|
|
144
|
+
required,
|
|
138
145
|
components: {
|
|
139
146
|
Control,
|
|
140
147
|
ClearIndicator,
|
|
@@ -170,6 +177,27 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
170
177
|
|
|
171
178
|
const [contextValue, setContextValue] = useState("")
|
|
172
179
|
|
|
180
|
+
// Add listener for form validation to track when validation should be shown (needed for react rendered rails kit)
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
const handleInvalid = (event: Event) => {
|
|
183
|
+
const target = event.target as HTMLInputElement
|
|
184
|
+
const typeaheadContainer = target.closest('[data-pb-react-component="Typeahead"]')
|
|
185
|
+
|
|
186
|
+
if (typeaheadContainer) {
|
|
187
|
+
// Check if this invalid event is specifically for our typeahead by comparing names so we do not have to require ids
|
|
188
|
+
const invalidInputName = target.name || target.getAttribute('name')
|
|
189
|
+
if (invalidInputName === name) {
|
|
190
|
+
setFormSubmitted(true)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
document.addEventListener('invalid', handleInvalid, true)
|
|
195
|
+
|
|
196
|
+
return () => {
|
|
197
|
+
document.removeEventListener('invalid', handleInvalid, true)
|
|
198
|
+
}
|
|
199
|
+
}, [name])
|
|
200
|
+
|
|
173
201
|
// Add listener for clearing
|
|
174
202
|
useEffect(() => {
|
|
175
203
|
const handleClear = () => {
|
|
@@ -230,6 +258,11 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
230
258
|
}
|
|
231
259
|
}
|
|
232
260
|
|
|
261
|
+
// Reset form submitted state when a selection is made (this is all for react rendered rails kit)
|
|
262
|
+
if (action === 'select-option') {
|
|
263
|
+
setFormSubmitted(false)
|
|
264
|
+
}
|
|
265
|
+
|
|
233
266
|
// If a value is selected and we're preserving input on blur, clear the input
|
|
234
267
|
if (action === 'select-option' && preserveSearchInput) {
|
|
235
268
|
setInputValue('')
|
|
@@ -268,6 +301,11 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
268
301
|
|
|
269
302
|
const inlineClass = selectProps.inline ? 'inline' : null
|
|
270
303
|
|
|
304
|
+
const shouldShowValidationError = required &&
|
|
305
|
+
formSubmitted
|
|
306
|
+
|
|
307
|
+
const errorDisplay = error || (shouldShowValidationError ? validation?.message || "Please fill out this field." : "")
|
|
308
|
+
|
|
271
309
|
return (
|
|
272
310
|
<div
|
|
273
311
|
{...dataProps}
|
|
@@ -276,7 +314,7 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
|
276
314
|
>
|
|
277
315
|
<Tag
|
|
278
316
|
classNamePrefix="typeahead-kit-select"
|
|
279
|
-
error={
|
|
317
|
+
error={errorDisplay}
|
|
280
318
|
isDisabled={disabled}
|
|
281
319
|
onChange={handleOnChange}
|
|
282
320
|
{...selectProps}
|
|
@@ -101,6 +101,8 @@ module Playbook
|
|
|
101
101
|
plusIcon: plus_icon,
|
|
102
102
|
truncate: truncate,
|
|
103
103
|
wrapped: wrapped,
|
|
104
|
+
required: required,
|
|
105
|
+
validation: validation,
|
|
104
106
|
searchContextSelector: search_context_selector,
|
|
105
107
|
optionsByContext: options_by_context,
|
|
106
108
|
clearOnContextChange: clear_on_context_change,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx,Fragment,jsxs}from"react/jsx-runtime";import{useState,useEffect}from"react";import{d as buildAriaProps,e as buildDataProps,f as buildHtmlProps,H as HighchartsReact,g as Highcharts,h as classnames,i as globalProps,j as HighchartsMore,S as SolidGauge,k as buildCss}from"./_typeahead-DkRYiut7.js";import{c as colors,h as highchartsTheme,m as merge,a as highchartsDarkTheme,t as typography}from"./lib-QZuu1ltS.js";const mapColors=array=>{const regex=/(data)\-[1-8]/;const newArray=array.map((item=>regex.test(item)?`${colors[`data_${item[item.length-1]}`]}`:item));return newArray};const BarGraph=({aria:aria={},data:data={},align:align="center",axisTitle:axisTitle,dark:dark=false,chartData:chartData,className:className="pb_bar_graph",colors:colors2,htmlOptions:htmlOptions={},customOptions:customOptions={},axisFormat:axisFormat,id:id,pointStart:pointStart,stacking:stacking,subTitle:subTitle,type:type="column",title:title="Title",xAxisCategories:xAxisCategories,yAxisMin:yAxisMin,yAxisMax:yAxisMax,legend:legend=false,toggleLegendClick:toggleLegendClick=true,height:height,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();const staticOptions={title:{text:title},chart:{height:height,type:type},subtitle:{text:subTitle},yAxis:[{labels:{format:typeof axisFormat==="string"?axisFormat:axisFormat&&axisFormat[0]?axisFormat[0].format:""},min:yAxisMin,max:yAxisMax,opposite:false,title:{text:Array.isArray(axisTitle)?axisTitle.length>0?axisTitle[0].name:null:axisTitle},plotLines:typeof yAxisMin!=="undefined"&&yAxisMin!==null?[]:[{value:0,zIndex:10,color:"#E4E8F0"}]}],xAxis:{categories:xAxisCategories},legend:{enabled:legend,align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},colors:colors2!==void 0&&colors2.length>0?mapColors(colors2):highchartsTheme.colors,plotOptions:{series:{stacking:stacking,pointStart:pointStart,borderWidth:stacking?0:"",events:{},dataLabels:{enabled:false}}},series:chartData,credits:false};if(Array.isArray(axisTitle)&&axisTitle.length>1&&axisTitle[1].name){staticOptions.yAxis.push({labels:{format:typeof axisFormat==="string"?axisFormat:axisFormat[1].format},min:yAxisMin,max:yAxisMax,opposite:true,title:{text:axisTitle[1].name},plotLines:typeof yAxisMin!=="undefined"&&yAxisMin!==null?[]:[{value:0,zIndex:10,color:"#E4E8F0"}]})}if(!toggleLegendClick){staticOptions.plotOptions.series.events={legendItemClick:()=>false}}const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(globalProps(filteredProps),className),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};const alignBlockElement=event=>{const itemToMove=document.querySelector(`#wrapper-circle-chart-${event.target.renderTo.id} .pb-circle-chart-block`);const chartContainer=document.querySelector(`#${event.target.renderTo.id}`);if(itemToMove!==null&&chartContainer!==null){itemToMove.style.height=`${event.target.chartHeight}px`;itemToMove.style.width=`${event.target.chartWidth}px`;if(chartContainer.firstChild!==null){chartContainer.firstChild.before(itemToMove)}}};const CircleChart=({align:align="center",aria:aria={},rounded:rounded=false,borderColor:borderColor=(rounded?null:""),borderWidth:borderWidth=(rounded?20:null),chartData:chartData,children:children,className:className,colors:colors2=[],customOptions:customOptions={},dark:dark=false,data:data={},dataLabelHtml:dataLabelHtml="<div>{point.name}</div>",dataLabels:dataLabels=false,height:height,htmlOptions:htmlOptions={},id:id,innerSize:innerSize="md",legend:legend=false,maxPointSize:maxPointSize=null,minPointSize:minPointSize=null,startAngle:startAngle=null,style:style="pie",title:title,tooltipHtml:tooltipHtml,useHtml:useHtml=false,zMin:zMin=null,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);HighchartsMore(Highcharts);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();Highcharts.setOptions({tooltip:{headerFormat:null,pointFormat:tooltipHtml?tooltipHtml:'<span style="font-weight: bold; color:{point.color};">●</span>{point.name}: <b>{point.y}</b>',useHTML:useHtml}});const innerSizes={sm:"35%",md:"50%",lg:"85%",none:"0%"};const innerSizeFormat=size=>innerSizes[size];const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{const formattedChartData=chartData.map((obj=>{obj.y=obj.value;delete obj.value;return obj}));const staticOptions={title:{text:title},chart:{height:height,type:style,events:{render:event=>alignBlockElement(event),redraw:event=>alignBlockElement(event)}},legend:{align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},plotOptions:{pie:{colors:colors2.length>0?mapColors(colors2):highchartsTheme.colors,dataLabels:{enabled:dataLabels,connectorShape:"straight",connectorWidth:3,format:dataLabelHtml},showInLegend:legend}},series:[{minPointSize:minPointSize,maxPointSize:maxPointSize,innerSize:borderWidth==20?"100%":innerSizeFormat(innerSize),data:formattedChartData,zMin:zMin,startAngle:startAngle,borderWidth:borderWidth,borderColor:borderColor}],credits:false};setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(Fragment,{children:children?jsxs("div",{id:`wrapper-circle-chart-${id}`,children:[jsx(HighchartsReact,{containerProps:{className:classnames("pb_circle_chart",globalProps(filteredProps)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options}),jsx("div",{className:"pb-circle-chart-block",children:children})]}):jsx(HighchartsReact,{containerProps:{className:classnames("pb_circle_chart",globalProps(filteredProps)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})})};const Gauge=({aria:aria={},chartData:chartData,customOptions:customOptions={},dark:dark=false,data:data={},disableAnimation:disableAnimation=false,fullCircle:fullCircle=false,height:height=null,htmlOptions:htmlOptions={},id:id,max:max=100,min:min=0,prefix:prefix="",showLabels:showLabels=false,style:style="solidgauge",suffix:suffix="",title:title="",tooltipHtml:tooltipHtml='<span style="font-weight: bold; color:{point.color};">●</span>{point.name}: <b>{point.y}</b>',colors:colors$1=[],minorTickInterval:minorTickInterval=null,circumference:circumference=(fullCircle?[0,360]:[-100,100]),...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);HighchartsMore(Highcharts);SolidGauge(Highcharts);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();Highcharts.setOptions({tooltip:{pointFormat:tooltipHtml,followPointer:true}});const css=buildCss({pb_gauge_kit:true});const[options,setOptions]=useState({});useEffect((()=>{const formattedChartData=chartData.map((obj=>{obj.y=obj.value;delete obj.value;return obj}));const staticOptions={chart:{events:{load(){setTimeout(this.reflow.bind(this),0)}},type:style,height:height},title:{text:title},yAxis:{min:min,max:max,lineWidth:0,tickWidth:0,minorTickInterval:minorTickInterval,tickAmount:2,tickPositions:[min,max],labels:{y:26,enabled:showLabels}},credits:false,series:[{data:formattedChartData}],pane:{center:["50%","50%"],size:"90%",startAngle:circumference[0],endAngle:circumference[1],background:{borderWidth:20,innerRadius:"90%",outerRadius:"90%",shape:"arc",className:"gauge-pane"}},colors:colors$1!==void 0&&colors$1.length>0?mapColors(colors$1):highchartsTheme.colors,plotOptions:{series:{animation:!disableAnimation},solidgauge:{borderColor:colors$1!==void 0&&colors$1.length===1?mapColors(colors$1).join():highchartsTheme.colors[0],borderWidth:20,radius:90,innerRadius:"90%",dataLabels:{borderWidth:0,color:colors.text_lt_default,enabled:true,format:`<span class="prefix${dark?" dark":""}">${prefix}</span><span class="fix${dark?" dark":""}">{y:,f}</span><span class="suffix${dark?" dark":""}">${suffix}</span>`,style:{fontFamily:typography.font_family_base,fontWeight:typography.regular,fontSize:typography.heading_2},y:-26}}}};setOptions(merge(staticOptions,customOptions));if(document.querySelector(".prefix")){document.querySelectorAll(".prefix").forEach((prefix2=>{prefix2.setAttribute("y","28")}));document.querySelectorAll(".fix").forEach((fix=>fix.setAttribute("y","38")))}}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(css,globalProps(props)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};const LineGraph=({aria:aria={},data:data={},align:align="center",className:className="pb_bar_graph",customOptions:customOptions={},dark:dark=false,gradient:gradient=false,type:type="line",htmlOptions:htmlOptions={},id:id,legend:legend=false,toggleLegendClick:toggleLegendClick=true,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,axisTitle:axisTitle,xAxisCategories:xAxisCategories,yAxisMin:yAxisMin,yAxisMax:yAxisMax,chartData:chartData,pointStart:pointStart,subTitle:subTitle,title:title,height:height,colors:colors2=[],...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();const staticOptions={title:{text:title},chart:{height:height,type:type},subtitle:{text:subTitle},yAxis:{min:yAxisMin,max:yAxisMax,title:{text:axisTitle}},xAxis:{categories:xAxisCategories},legend:{enabled:legend,align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},colors:colors2!==void 0&&colors2.length>0?mapColors(colors2):highchartsTheme.colors,plotOptions:{series:{pointStart:pointStart,events:{},dataLabels:{enabled:false}}},series:chartData,credits:false};if(!toggleLegendClick){staticOptions.plotOptions.series.events={legendItemClick:()=>false}}const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(globalProps(filteredProps),className),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};export{BarGraph as B,CircleChart as C,Gauge as G,LineGraph as L};
|
|
1
|
+
import{jsx,Fragment,jsxs}from"react/jsx-runtime";import{useState,useEffect}from"react";import{d as buildAriaProps,e as buildDataProps,f as buildHtmlProps,H as HighchartsReact,g as Highcharts,h as classnames,i as globalProps,j as HighchartsMore,S as SolidGauge,k as buildCss}from"./_typeahead-4Ud3FHDA.js";import{c as colors,h as highchartsTheme,m as merge,a as highchartsDarkTheme,t as typography}from"./lib-QZuu1ltS.js";const mapColors=array=>{const regex=/(data)\-[1-8]/;const newArray=array.map((item=>regex.test(item)?`${colors[`data_${item[item.length-1]}`]}`:item));return newArray};const BarGraph=({aria:aria={},data:data={},align:align="center",axisTitle:axisTitle,dark:dark=false,chartData:chartData,className:className="pb_bar_graph",colors:colors2,htmlOptions:htmlOptions={},customOptions:customOptions={},axisFormat:axisFormat,id:id,pointStart:pointStart,stacking:stacking,subTitle:subTitle,type:type="column",title:title="Title",xAxisCategories:xAxisCategories,yAxisMin:yAxisMin,yAxisMax:yAxisMax,legend:legend=false,toggleLegendClick:toggleLegendClick=true,height:height,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();const staticOptions={title:{text:title},chart:{height:height,type:type},subtitle:{text:subTitle},yAxis:[{labels:{format:typeof axisFormat==="string"?axisFormat:axisFormat&&axisFormat[0]?axisFormat[0].format:""},min:yAxisMin,max:yAxisMax,opposite:false,title:{text:Array.isArray(axisTitle)?axisTitle.length>0?axisTitle[0].name:null:axisTitle},plotLines:typeof yAxisMin!=="undefined"&&yAxisMin!==null?[]:[{value:0,zIndex:10,color:"#E4E8F0"}]}],xAxis:{categories:xAxisCategories},legend:{enabled:legend,align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},colors:colors2!==void 0&&colors2.length>0?mapColors(colors2):highchartsTheme.colors,plotOptions:{series:{stacking:stacking,pointStart:pointStart,borderWidth:stacking?0:"",events:{},dataLabels:{enabled:false}}},series:chartData,credits:false};if(Array.isArray(axisTitle)&&axisTitle.length>1&&axisTitle[1].name){staticOptions.yAxis.push({labels:{format:typeof axisFormat==="string"?axisFormat:axisFormat[1].format},min:yAxisMin,max:yAxisMax,opposite:true,title:{text:axisTitle[1].name},plotLines:typeof yAxisMin!=="undefined"&&yAxisMin!==null?[]:[{value:0,zIndex:10,color:"#E4E8F0"}]})}if(!toggleLegendClick){staticOptions.plotOptions.series.events={legendItemClick:()=>false}}const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(globalProps(filteredProps),className),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};const alignBlockElement=event=>{const itemToMove=document.querySelector(`#wrapper-circle-chart-${event.target.renderTo.id} .pb-circle-chart-block`);const chartContainer=document.querySelector(`#${event.target.renderTo.id}`);if(itemToMove!==null&&chartContainer!==null){itemToMove.style.height=`${event.target.chartHeight}px`;itemToMove.style.width=`${event.target.chartWidth}px`;if(chartContainer.firstChild!==null){chartContainer.firstChild.before(itemToMove)}}};const CircleChart=({align:align="center",aria:aria={},rounded:rounded=false,borderColor:borderColor=(rounded?null:""),borderWidth:borderWidth=(rounded?20:null),chartData:chartData,children:children,className:className,colors:colors2=[],customOptions:customOptions={},dark:dark=false,data:data={},dataLabelHtml:dataLabelHtml="<div>{point.name}</div>",dataLabels:dataLabels=false,height:height,htmlOptions:htmlOptions={},id:id,innerSize:innerSize="md",legend:legend=false,maxPointSize:maxPointSize=null,minPointSize:minPointSize=null,startAngle:startAngle=null,style:style="pie",title:title,tooltipHtml:tooltipHtml,useHtml:useHtml=false,zMin:zMin=null,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);HighchartsMore(Highcharts);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();Highcharts.setOptions({tooltip:{headerFormat:null,pointFormat:tooltipHtml?tooltipHtml:'<span style="font-weight: bold; color:{point.color};">●</span>{point.name}: <b>{point.y}</b>',useHTML:useHtml}});const innerSizes={sm:"35%",md:"50%",lg:"85%",none:"0%"};const innerSizeFormat=size=>innerSizes[size];const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{const formattedChartData=chartData.map((obj=>{obj.y=obj.value;delete obj.value;return obj}));const staticOptions={title:{text:title},chart:{height:height,type:style,events:{render:event=>alignBlockElement(event),redraw:event=>alignBlockElement(event)}},legend:{align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},plotOptions:{pie:{colors:colors2.length>0?mapColors(colors2):highchartsTheme.colors,dataLabels:{enabled:dataLabels,connectorShape:"straight",connectorWidth:3,format:dataLabelHtml},showInLegend:legend}},series:[{minPointSize:minPointSize,maxPointSize:maxPointSize,innerSize:borderWidth==20?"100%":innerSizeFormat(innerSize),data:formattedChartData,zMin:zMin,startAngle:startAngle,borderWidth:borderWidth,borderColor:borderColor}],credits:false};setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(Fragment,{children:children?jsxs("div",{id:`wrapper-circle-chart-${id}`,children:[jsx(HighchartsReact,{containerProps:{className:classnames("pb_circle_chart",globalProps(filteredProps)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options}),jsx("div",{className:"pb-circle-chart-block",children:children})]}):jsx(HighchartsReact,{containerProps:{className:classnames("pb_circle_chart",globalProps(filteredProps)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})})};const Gauge=({aria:aria={},chartData:chartData,customOptions:customOptions={},dark:dark=false,data:data={},disableAnimation:disableAnimation=false,fullCircle:fullCircle=false,height:height=null,htmlOptions:htmlOptions={},id:id,max:max=100,min:min=0,prefix:prefix="",showLabels:showLabels=false,style:style="solidgauge",suffix:suffix="",title:title="",tooltipHtml:tooltipHtml='<span style="font-weight: bold; color:{point.color};">●</span>{point.name}: <b>{point.y}</b>',colors:colors$1=[],minorTickInterval:minorTickInterval=null,circumference:circumference=(fullCircle?[0,360]:[-100,100]),...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);HighchartsMore(Highcharts);SolidGauge(Highcharts);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();Highcharts.setOptions({tooltip:{pointFormat:tooltipHtml,followPointer:true}});const css=buildCss({pb_gauge_kit:true});const[options,setOptions]=useState({});useEffect((()=>{const formattedChartData=chartData.map((obj=>{obj.y=obj.value;delete obj.value;return obj}));const staticOptions={chart:{events:{load(){setTimeout(this.reflow.bind(this),0)}},type:style,height:height},title:{text:title},yAxis:{min:min,max:max,lineWidth:0,tickWidth:0,minorTickInterval:minorTickInterval,tickAmount:2,tickPositions:[min,max],labels:{y:26,enabled:showLabels}},credits:false,series:[{data:formattedChartData}],pane:{center:["50%","50%"],size:"90%",startAngle:circumference[0],endAngle:circumference[1],background:{borderWidth:20,innerRadius:"90%",outerRadius:"90%",shape:"arc",className:"gauge-pane"}},colors:colors$1!==void 0&&colors$1.length>0?mapColors(colors$1):highchartsTheme.colors,plotOptions:{series:{animation:!disableAnimation},solidgauge:{borderColor:colors$1!==void 0&&colors$1.length===1?mapColors(colors$1).join():highchartsTheme.colors[0],borderWidth:20,radius:90,innerRadius:"90%",dataLabels:{borderWidth:0,color:colors.text_lt_default,enabled:true,format:`<span class="prefix${dark?" dark":""}">${prefix}</span><span class="fix${dark?" dark":""}">{y:,f}</span><span class="suffix${dark?" dark":""}">${suffix}</span>`,style:{fontFamily:typography.font_family_base,fontWeight:typography.regular,fontSize:typography.heading_2},y:-26}}}};setOptions(merge(staticOptions,customOptions));if(document.querySelector(".prefix")){document.querySelectorAll(".prefix").forEach((prefix2=>{prefix2.setAttribute("y","28")}));document.querySelectorAll(".fix").forEach((fix=>fix.setAttribute("y","38")))}}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(css,globalProps(props)),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};const LineGraph=({aria:aria={},data:data={},align:align="center",className:className="pb_bar_graph",customOptions:customOptions={},dark:dark=false,gradient:gradient=false,type:type="line",htmlOptions:htmlOptions={},id:id,legend:legend=false,toggleLegendClick:toggleLegendClick=true,layout:layout="horizontal",verticalAlign:verticalAlign="bottom",x:x=0,y:y=0,axisTitle:axisTitle,xAxisCategories:xAxisCategories,yAxisMin:yAxisMin,yAxisMax:yAxisMax,chartData:chartData,pointStart:pointStart,subTitle:subTitle,title:title,height:height,colors:colors2=[],...props})=>{const ariaProps=buildAriaProps(aria);const dataProps=buildDataProps(data);const htmlProps=buildHtmlProps(htmlOptions);const setupTheme=()=>{dark?Highcharts.setOptions(highchartsDarkTheme):Highcharts.setOptions(highchartsTheme)};setupTheme();const staticOptions={title:{text:title},chart:{height:height,type:type},subtitle:{text:subTitle},yAxis:{min:yAxisMin,max:yAxisMax,title:{text:axisTitle}},xAxis:{categories:xAxisCategories},legend:{enabled:legend,align:align,verticalAlign:verticalAlign,layout:layout,x:x,y:y},colors:colors2!==void 0&&colors2.length>0?mapColors(colors2):highchartsTheme.colors,plotOptions:{series:{pointStart:pointStart,events:{},dataLabels:{enabled:false}}},series:chartData,credits:false};if(!toggleLegendClick){staticOptions.plotOptions.series.events={legendItemClick:()=>false}}const filteredProps={...props};delete filteredProps.verticalAlign;const[options,setOptions]=useState({});useEffect((()=>{setOptions(merge(staticOptions,customOptions))}),[chartData]);return jsx(HighchartsReact,{containerProps:{className:classnames(globalProps(filteredProps),className),id:id,...ariaProps,...dataProps,...htmlProps},highcharts:Highcharts,options:options})};export{BarGraph as B,CircleChart as C,Gauge as G,LineGraph as L};
|