playbook_ui 16.2.0.pre.alpha.play280714580 → 16.2.0.pre.alpha.play284314641
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/_button.scss +3 -2
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +4 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -2
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +2 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -2
- data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -1
- data/app/pb_kits/playbook/pb_icon/icon.rb +168 -19
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_reset_key.jsx +100 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_reset_key.md +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_pagination/_pagination.scss +101 -1
- data/app/pb_kits/playbook/pb_pagination/_pagination.test.jsx +172 -1
- data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +178 -15
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +4 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +2 -0
- data/app/pb_kits/playbook/pb_select/_select.tsx +2 -0
- data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
- data/app/pb_kits/playbook/pb_star_rating/star_rating.html.erb +1 -1
- data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_interactive.tsx +1 -0
- data/app/pb_kits/playbook/pb_table/_table.tsx +21 -24
- data/app/pb_kits/playbook/pb_table/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_table/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_table/table.html.erb +11 -12
- data/app/pb_kits/playbook/pb_table/table.rb +0 -4
- data/app/pb_kits/playbook/pb_table/table.test.js +0 -33
- data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +2 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +2 -2
- data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +43 -21
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_input_options.jsx +68 -0
- data/app/pb_kits/playbook/pb_textarea/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_textarea/docs/index.js +9 -8
- data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +4 -4
- data/app/pb_kits/playbook/pb_textarea/textarea.rb +6 -2
- data/app/pb_kits/playbook/pb_textarea/textarea.test.js +134 -1
- data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +6 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.test.jsx +2 -2
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +1 -1
- data/dist/chunks/{_typeahead-DXIBDeMj.js → _typeahead-COVN8XN7.js} +1 -1
- data/dist/chunks/vendor.js +3 -3
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/forms/builder/checkbox_field.rb +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +6 -7
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props.jsx +0 -152
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props.md +0 -17
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props_rails.html.erb +0 -121
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props_rails.md +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c21c5c359e50742075f58579331eb7acc9ae7a7d992ede03a31fe58d132a6e7
|
|
4
|
+
data.tar.gz: 27012bc375f94c3f2e8ddd5d4cfcf84418bd78260a1dc15aa84db4578f040901
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b563518a788051e655090236d617656a431f12ef0ac68fdde942a900271465f8009b7348584f02ba34fd9a4a7c69fbf0f80d1461636a84025828b27d69ecf33e
|
|
7
|
+
data.tar.gz: d8c12bea96a73908d307b6b860831778e426839f203c6ad401a16637af279c7cdf34d5204847d7133156b99c6f85c1a19419ad04782f974b01f26bec91f4c58b
|
|
@@ -115,9 +115,10 @@ $pb_button_sizes: (
|
|
|
115
115
|
|
|
116
116
|
// Icon-only button (icon prop set, no text) - square with equal padding
|
|
117
117
|
// Rails: uses .pb_button_icon_only class
|
|
118
|
-
// React:
|
|
118
|
+
// React: when pb_button_content is empty (no text). Do not match when content has
|
|
119
|
+
// text + icon (e.g. "Exit Fullscreen" + FA icon) which can include empty spans.
|
|
119
120
|
&.pb_button_icon_only,
|
|
120
|
-
&:has(.pb_button_content
|
|
121
|
+
&:has(.pb_button_content:empty) {
|
|
121
122
|
aspect-ratio: 1;
|
|
122
123
|
min-width: auto;
|
|
123
124
|
width: auto;
|
|
@@ -221,11 +221,14 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
|
|
|
221
221
|
{!hideLabel && (
|
|
222
222
|
<label htmlFor={pickerId}>
|
|
223
223
|
{requiredIndicator ? (
|
|
224
|
-
<Caption className="pb_date_picker_kit_label"
|
|
224
|
+
<Caption className="pb_date_picker_kit_label"
|
|
225
|
+
color="lighter"
|
|
226
|
+
>
|
|
225
227
|
{label} <span style={{ color: `${colors.error}` }}>*</span>
|
|
226
228
|
</Caption>
|
|
227
229
|
) : (
|
|
228
230
|
<Caption className="pb_date_picker_kit_label"
|
|
231
|
+
color="lighter"
|
|
229
232
|
text={label}
|
|
230
233
|
/>
|
|
231
234
|
)}
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
<% if !object.hide_label && object.label %>
|
|
8
8
|
<label for="<%= object.picker_id %>">
|
|
9
9
|
<% if object.required_indicator %>
|
|
10
|
-
<%= pb_rails("caption", props: { dark: object.dark, classname: "pb_date_picker_kit_label" }) do %>
|
|
10
|
+
<%= pb_rails("caption", props: { dark: object.dark, classname: "pb_date_picker_kit_label", color: "lighter" }) do %>
|
|
11
11
|
<%= object.label %><span style="color: #DA0014;"> *</span>
|
|
12
12
|
<% end %>
|
|
13
13
|
<% else %>
|
|
14
|
-
<%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_date_picker_kit_label" }) %>
|
|
14
|
+
<%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_date_picker_kit_label", color: "lighter" }) %>
|
|
15
15
|
<% end %>
|
|
16
16
|
</label>
|
|
17
17
|
<% end %>
|
|
@@ -479,6 +479,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
479
479
|
{requiredIndicator ? (
|
|
480
480
|
<Caption
|
|
481
481
|
className="pb_dropdown_kit_label"
|
|
482
|
+
color="lighter"
|
|
482
483
|
dark={dark}
|
|
483
484
|
marginBottom="xs"
|
|
484
485
|
>
|
|
@@ -487,6 +488,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
487
488
|
) : (
|
|
488
489
|
<Caption
|
|
489
490
|
className="pb_dropdown_kit_label"
|
|
491
|
+
color="lighter"
|
|
490
492
|
dark={dark}
|
|
491
493
|
marginBottom="xs"
|
|
492
494
|
text={label}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<% if object.label.present? %>
|
|
3
3
|
<label for="<%= object.select_id %>" data-dropdown="pb-dropdown-label">
|
|
4
4
|
<% if object.required_indicator %>
|
|
5
|
-
<%= pb_rails("caption", props: { margin_bottom: "xs", classname: "pb_dropdown_kit_label", dark: object.dark }) do %>
|
|
5
|
+
<%= pb_rails("caption", props: { margin_bottom: "xs", classname: "pb_dropdown_kit_label", color: "lighter", dark: object.dark }) do %>
|
|
6
6
|
<%= object.label %><span style="color: #DA0014;"> *</span>
|
|
7
7
|
<% end %>
|
|
8
8
|
<% else %>
|
|
9
|
-
<%= pb_rails("caption", props: { text: object.label, margin_bottom: "xs", classname: "pb_dropdown_kit_label", dark: object.dark }) %>
|
|
9
|
+
<%= pb_rails("caption", props: { text: object.label, margin_bottom: "xs", classname: "pb_dropdown_kit_label", color: "lighter", dark: object.dark }) %>
|
|
10
10
|
<% end %>
|
|
11
11
|
</label>
|
|
12
12
|
<% end %>
|
|
@@ -212,7 +212,7 @@ test('generated label prop', () => {
|
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
const kit = screen.getByTestId(testId)
|
|
215
|
-
const label = kit.querySelector('.
|
|
215
|
+
const label = kit.querySelector('.pb_caption_kit_md_lighter')
|
|
216
216
|
expect(label).toHaveTextContent('Countries')
|
|
217
217
|
})
|
|
218
218
|
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require "open-uri"
|
|
4
4
|
require "json"
|
|
5
|
+
require "digest"
|
|
5
6
|
|
|
6
7
|
module Playbook
|
|
7
8
|
module PbIcon
|
|
8
9
|
class Icon < Playbook::KitBase
|
|
10
|
+
ICON_PATH_DEV_CACHE_TTL_SECONDS = 2
|
|
11
|
+
ICON_PATH_PROD_CACHE_TTL_SECONDS = 60
|
|
12
|
+
|
|
9
13
|
prop :border, type: Playbook::Props::Boolean,
|
|
10
14
|
default: false
|
|
11
15
|
prop :fixed_width, type: Playbook::Props::Boolean,
|
|
@@ -82,30 +86,35 @@ module Playbook
|
|
|
82
86
|
)
|
|
83
87
|
end
|
|
84
88
|
|
|
89
|
+
# Instance-level memoization of alias map lookup result
|
|
85
90
|
def icon_alias_map
|
|
86
|
-
return
|
|
91
|
+
return @icon_alias_map if defined?(@icon_alias_map)
|
|
87
92
|
|
|
88
|
-
|
|
89
|
-
json = File.read(Rails.root.join(base_path))
|
|
90
|
-
JSON.parse(json)["aliases"].freeze
|
|
93
|
+
@icon_alias_map = self.class.icon_alias_map
|
|
91
94
|
end
|
|
92
95
|
|
|
96
|
+
# Instance-level memoization of resolved asset path
|
|
93
97
|
def asset_path
|
|
94
|
-
return
|
|
98
|
+
return @asset_path if defined?(@asset_path)
|
|
99
|
+
|
|
100
|
+
@asset_path =
|
|
101
|
+
if Rails.application.config.respond_to?(:icon_path)
|
|
102
|
+
resolved_icon = resolve_alias(icon)
|
|
103
|
+
path = self.class.icon_path_index[resolved_icon]
|
|
104
|
+
path if path && File.exist?(path)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def is_svg?
|
|
109
|
+
return @is_svg if defined?(@is_svg)
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
resolved_icon = resolve_alias(icon)
|
|
98
|
-
icon_path = Dir.glob(Rails.root.join(base_path, "**", "#{resolved_icon}.svg")).first
|
|
99
|
-
icon_path if icon_path && File.exist?(icon_path)
|
|
111
|
+
@is_svg = (icon || custom_icon.to_s).include?(".svg") || asset_path.present?
|
|
100
112
|
end
|
|
101
113
|
|
|
102
114
|
def render_svg
|
|
103
115
|
doc = Nokogiri::XML(URI.open(asset_path || icon || custom_icon)) # rubocop:disable Security/Open
|
|
104
|
-
svg = doc.at_css
|
|
105
|
-
|
|
106
|
-
unless svg
|
|
107
|
-
return "" # Return an empty string if SVG element is not found
|
|
108
|
-
end
|
|
116
|
+
svg = doc.at_css("svg")
|
|
117
|
+
return "" unless svg
|
|
109
118
|
|
|
110
119
|
svg["class"] = %w[pb_custom_icon svg-inline--fa].concat([object.custom_icon_classname]).join(" ")
|
|
111
120
|
svg["id"] = object.id
|
|
@@ -113,7 +122,9 @@ module Playbook
|
|
|
113
122
|
svg["width"] = "auto"
|
|
114
123
|
svg["tabindex"] = object.tabindex
|
|
115
124
|
fill_color = object.color || "currentColor"
|
|
116
|
-
|
|
125
|
+
|
|
126
|
+
# Safely apply fill to all paths (avoids nil errors + handles multi-path icons)
|
|
127
|
+
doc.css("path").each { |p| p["fill"] = fill_color }
|
|
117
128
|
|
|
118
129
|
if object.data.present?
|
|
119
130
|
object.data.each do |key, value|
|
|
@@ -135,14 +146,152 @@ module Playbook
|
|
|
135
146
|
""
|
|
136
147
|
end
|
|
137
148
|
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
# Class-level caches
|
|
150
|
+
class << self
|
|
151
|
+
@cache_mutex = Mutex.new
|
|
152
|
+
|
|
153
|
+
# Cache aliases.json across the process, but invalidate when the file changes (dev-safe)
|
|
154
|
+
def icon_alias_map
|
|
155
|
+
return @icon_alias_map if alias_cache_fresh?
|
|
156
|
+
|
|
157
|
+
cache_mutex.synchronize do
|
|
158
|
+
return @icon_alias_map if alias_cache_fresh?
|
|
159
|
+
|
|
160
|
+
@icon_alias_map =
|
|
161
|
+
if Rails.application.config.respond_to?(:icon_alias_path)
|
|
162
|
+
base_path = Rails.application.config.icon_alias_path
|
|
163
|
+
full_path = Rails.root.join(base_path)
|
|
164
|
+
@icon_alias_map_mtime = safe_mtime(full_path)
|
|
165
|
+
|
|
166
|
+
json = File.read(full_path)
|
|
167
|
+
parsed = JSON.parse(json)
|
|
168
|
+
parsed.fetch("aliases", {}).freeze
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
@icon_alias_map
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Cache an index of icon_name to file path for all SVGs in the configured directory, with invalidation based on directory mtime
|
|
176
|
+
# Avoids recursive Dir.glob for every icon render
|
|
177
|
+
def icon_path_index
|
|
178
|
+
return @icon_path_index if index_cache_fresh?
|
|
179
|
+
|
|
180
|
+
cache_mutex.synchronize do
|
|
181
|
+
return @icon_path_index if index_cache_fresh?
|
|
182
|
+
|
|
183
|
+
@icon_path_index =
|
|
184
|
+
if Rails.application.config.respond_to?(:icon_path)
|
|
185
|
+
base_path = Rails.application.config.icon_path
|
|
186
|
+
root = Rails.root.join(base_path)
|
|
187
|
+
|
|
188
|
+
# If path doesn't exist, keep behavior aligned (no path resolution)
|
|
189
|
+
if Dir.exist?(root)
|
|
190
|
+
@icon_path_index_cache_key = icon_path_cache_key(root)
|
|
191
|
+
|
|
192
|
+
# One scan builds the map for O(1) lookups
|
|
193
|
+
# Key is the filename (without .svg) to match existing usage
|
|
194
|
+
index = {}
|
|
195
|
+
Dir.glob(File.join(root.to_s, "**", "*.svg")).sort.each do |p|
|
|
196
|
+
name = File.basename(p, ".svg")
|
|
197
|
+
index[name] ||= p
|
|
198
|
+
end
|
|
199
|
+
index.freeze
|
|
200
|
+
else
|
|
201
|
+
@icon_path_index_cache_key = nil
|
|
202
|
+
{}
|
|
203
|
+
end
|
|
204
|
+
else
|
|
205
|
+
{}
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
@icon_path_index_checked_at = monotonic_now
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
@icon_path_index
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
private
|
|
215
|
+
|
|
216
|
+
def cache_mutex
|
|
217
|
+
@cache_mutex ||= Mutex.new
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def alias_cache_fresh?
|
|
221
|
+
return false unless defined?(@icon_alias_map)
|
|
222
|
+
|
|
223
|
+
return true unless Rails.application.config.respond_to?(:icon_alias_path)
|
|
224
|
+
|
|
225
|
+
full_path = Rails.root.join(Rails.application.config.icon_alias_path)
|
|
226
|
+
safe_mtime(full_path) == @icon_alias_map_mtime
|
|
227
|
+
rescue
|
|
228
|
+
false
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def index_cache_fresh?
|
|
232
|
+
return false unless defined?(@icon_path_index)
|
|
233
|
+
|
|
234
|
+
return true unless Rails.application.config.respond_to?(:icon_path)
|
|
235
|
+
|
|
236
|
+
# In development and production, skip re-checks for a short TTL window
|
|
237
|
+
# to avoid repeated tree scans on hot paths.
|
|
238
|
+
return true if Rails.env.development? && within_icon_index_ttl?(ICON_PATH_DEV_CACHE_TTL_SECONDS)
|
|
239
|
+
return true if Rails.env.production? && within_icon_index_ttl?(ICON_PATH_PROD_CACHE_TTL_SECONDS)
|
|
240
|
+
|
|
241
|
+
root = Rails.root.join(Rails.application.config.icon_path)
|
|
242
|
+
fresh = icon_path_cache_key(root) == @icon_path_index_cache_key
|
|
243
|
+
@icon_path_index_checked_at = monotonic_now
|
|
244
|
+
fresh
|
|
245
|
+
rescue
|
|
246
|
+
false
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def within_icon_index_ttl?(ttl_seconds)
|
|
250
|
+
return false unless defined?(@icon_path_index_checked_at)
|
|
251
|
+
|
|
252
|
+
(monotonic_now - @icon_path_index_checked_at) < ttl_seconds
|
|
253
|
+
rescue
|
|
254
|
+
false
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def monotonic_now
|
|
258
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def icon_path_cache_key(root)
|
|
262
|
+
return safe_mtime(root) unless Rails.env.development? || Rails.env.production?
|
|
263
|
+
|
|
264
|
+
digest = Digest::SHA1.new
|
|
265
|
+
root_prefix = "#{root}/"
|
|
266
|
+
|
|
267
|
+
Dir.glob(File.join(root.to_s, "**", "*.svg")).sort.each do |path|
|
|
268
|
+
digest << path.delete_prefix(root_prefix)
|
|
269
|
+
next unless Rails.env.development?
|
|
270
|
+
|
|
271
|
+
# Development tracks file metadata for rapid local edits.
|
|
272
|
+
# Production only needs path-set change detection during periodic checks.
|
|
273
|
+
stat = File.stat(path)
|
|
274
|
+
digest << stat.mtime.to_f.to_s
|
|
275
|
+
digest << stat.size.to_s
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
digest.hexdigest
|
|
279
|
+
rescue
|
|
280
|
+
nil
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def safe_mtime(path)
|
|
284
|
+
File.exist?(path) ? File.mtime(path) : nil
|
|
285
|
+
rescue
|
|
286
|
+
nil
|
|
287
|
+
end
|
|
140
288
|
end
|
|
141
289
|
|
|
142
290
|
private
|
|
143
291
|
|
|
144
292
|
def resolve_alias(icon)
|
|
145
293
|
return icon unless icon_alias_map
|
|
294
|
+
return icon if icon.nil?
|
|
146
295
|
|
|
147
296
|
aliases = icon_alias_map[icon]
|
|
148
297
|
return icon unless aliases
|
|
@@ -155,8 +304,8 @@ module Playbook
|
|
|
155
304
|
end
|
|
156
305
|
|
|
157
306
|
def file_exists?(alias_name)
|
|
158
|
-
|
|
159
|
-
|
|
307
|
+
# Use the cached index (no recursive glob)
|
|
308
|
+
self.class.icon_path_index.key?(alias_name)
|
|
160
309
|
end
|
|
161
310
|
|
|
162
311
|
def svg_size
|
|
@@ -532,6 +532,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>(
|
|
|
532
532
|
{requiredIndicator ? (
|
|
533
533
|
<Caption
|
|
534
534
|
className="pb_multi_level_select_kit_label"
|
|
535
|
+
color="lighter"
|
|
535
536
|
marginBottom="xs"
|
|
536
537
|
>
|
|
537
538
|
{label} <span className="required_indicator">*</span>
|
|
@@ -539,6 +540,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>(
|
|
|
539
540
|
) : (
|
|
540
541
|
<Caption
|
|
541
542
|
className="pb_multi_level_select_kit_label"
|
|
543
|
+
color="lighter"
|
|
542
544
|
marginBottom="xs"
|
|
543
545
|
text={label}
|
|
544
546
|
/>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import MultiLevelSelect from "../_multi_level_select";
|
|
3
|
+
import { Button } from "playbook-ui";
|
|
4
|
+
|
|
5
|
+
const treeData = [
|
|
6
|
+
{
|
|
7
|
+
label: "Power Home Remodeling",
|
|
8
|
+
value: "powerHomeRemodeling",
|
|
9
|
+
id: "100",
|
|
10
|
+
expanded: true,
|
|
11
|
+
children: [
|
|
12
|
+
{
|
|
13
|
+
label: "People",
|
|
14
|
+
value: "people",
|
|
15
|
+
id: "101",
|
|
16
|
+
expanded: true,
|
|
17
|
+
children: [
|
|
18
|
+
{
|
|
19
|
+
label: "Talent Acquisition",
|
|
20
|
+
value: "talentAcquisition",
|
|
21
|
+
id: "102",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: "Business Affairs",
|
|
25
|
+
value: "businessAffairs",
|
|
26
|
+
id: "103",
|
|
27
|
+
children: [
|
|
28
|
+
{
|
|
29
|
+
label: "Initiatives",
|
|
30
|
+
value: "initiatives",
|
|
31
|
+
id: "104",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: "Learning & Development",
|
|
35
|
+
value: "learningAndDevelopment",
|
|
36
|
+
id: "105",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: "People Experience",
|
|
42
|
+
value: "peopleExperience",
|
|
43
|
+
id: "106",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
label: "Contact Center",
|
|
49
|
+
value: "contactCenter",
|
|
50
|
+
id: "107",
|
|
51
|
+
children: [
|
|
52
|
+
{
|
|
53
|
+
label: "Appointment Management",
|
|
54
|
+
value: "appointmentManagement",
|
|
55
|
+
id: "108",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: "Customer Service",
|
|
59
|
+
value: "customerService",
|
|
60
|
+
id: "109",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: "Energy",
|
|
64
|
+
value: "energy",
|
|
65
|
+
id: "110",
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const MultiLevelSelectReactResetKey = (props) => {
|
|
74
|
+
const [resetKey, setResetKey] = useState(0);
|
|
75
|
+
|
|
76
|
+
const handleReset = () => {
|
|
77
|
+
setResetKey((k) => k + 1);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
<MultiLevelSelect
|
|
83
|
+
{...props}
|
|
84
|
+
id="multi-level-select-reset-example"
|
|
85
|
+
key={`multi-level-select-reset-${resetKey}`}
|
|
86
|
+
name="my_array"
|
|
87
|
+
returnAllSelected
|
|
88
|
+
treeData={treeData}
|
|
89
|
+
/>
|
|
90
|
+
<Button
|
|
91
|
+
id="multilevelselect-reset-button"
|
|
92
|
+
marginTop="lg"
|
|
93
|
+
onClick={handleReset}
|
|
94
|
+
text="Reset"
|
|
95
|
+
/>
|
|
96
|
+
</>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default MultiLevelSelectReactResetKey;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
When a parent resets a Multi Level Select (e.g., “Default” or “Clear”), the kit needs a `key` that changes with the selection because React uses the `key` to determine component identity and whether to preserve internal state. If the `key` doesn’t change, React reuses the existing instance and may keep showing the old selection instead of resetting to the new one.
|
|
@@ -39,3 +39,4 @@ examples:
|
|
|
39
39
|
- multi_level_select_disabled_options_parent: Disabled Parent Option (Return All Selected)
|
|
40
40
|
- multi_level_select_single_disabled: Disabled Options (Single Select)
|
|
41
41
|
- multi_level_select_required_indicator: Required Indicator
|
|
42
|
+
- multi_level_select_react_reset_key: Reset with Key (React)
|
|
@@ -17,3 +17,4 @@ export { default as MultiLevelSelectDisabledOptionsDefault } from "./_multi_leve
|
|
|
17
17
|
export { default as MultiLevelSelectLabel } from "./_multi_level_select_label.jsx"
|
|
18
18
|
export { default as MultiLevelSelectSingleDisabled } from "./_multi_level_select_single_disabled.jsx"
|
|
19
19
|
export { default as MultiLevelSelectRequiredIndicator } from "./_multi_level_select_required_indicator.jsx"
|
|
20
|
+
export { default as MultiLevelSelectReactResetKey } from "./_multi_level_select_react_reset_key.jsx"
|
|
@@ -73,8 +73,9 @@ $top_bottom_radius: 0px;
|
|
|
73
73
|
}
|
|
74
74
|
.disabled {
|
|
75
75
|
pointer-events: none;
|
|
76
|
+
cursor: not-allowed;
|
|
76
77
|
opacity: 0.5;
|
|
77
|
-
color:
|
|
78
|
+
color: #B0BDC7; // replace with $text_disabled once added to tokens
|
|
78
79
|
|
|
79
80
|
& > span {
|
|
80
81
|
padding: $pagination_padding;
|
|
@@ -104,4 +105,103 @@ $top_bottom_radius: 0px;
|
|
|
104
105
|
border-right: none;
|
|
105
106
|
margin-left: $space_xxs;
|
|
106
107
|
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.pb_pagination_mobile {
|
|
111
|
+
padding: $space_xxs 0px !important;
|
|
112
|
+
position: relative;
|
|
113
|
+
|
|
114
|
+
.pagination-right {
|
|
115
|
+
border-left: none !important;
|
|
116
|
+
padding: 6px 13px !important;
|
|
117
|
+
flex-shrink: 0;
|
|
118
|
+
|
|
119
|
+
@media (max-width: 435px) {
|
|
120
|
+
padding: 6px 10px !important;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
.pagination-left {
|
|
124
|
+
border-right: none !important;
|
|
125
|
+
padding: 6px 13px !important;
|
|
126
|
+
flex-shrink: 0;
|
|
127
|
+
|
|
128
|
+
@media (max-width: 435px) {
|
|
129
|
+
padding: 6px 10px !important;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
.pagination-dropdown {
|
|
133
|
+
position: static;
|
|
134
|
+
flex: 1;
|
|
135
|
+
margin: 0 $space_xxs;
|
|
136
|
+
min-width: 0;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.pagination-dropdown-trigger {
|
|
141
|
+
padding: 6px 10px 6px 13px !important;
|
|
142
|
+
background-color: $bg_light;
|
|
143
|
+
border-radius: $border_rad_light;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
transition: all 0.2s ease;
|
|
146
|
+
white-space: nowrap;
|
|
147
|
+
overflow: hidden;
|
|
148
|
+
|
|
149
|
+
&:hover {
|
|
150
|
+
background-color: $active_light;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@media (max-width: 435px) {
|
|
154
|
+
padding: 6px 8px 6px 10px !important;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.pagination-dropdown-menu {
|
|
159
|
+
position: absolute;
|
|
160
|
+
left: 0;
|
|
161
|
+
right: 0;
|
|
162
|
+
background-color: $white;
|
|
163
|
+
border: $border_rad_lightest solid $border_light;
|
|
164
|
+
border-radius: $border_rad_light;
|
|
165
|
+
box-shadow: $shadow_deep;
|
|
166
|
+
max-height: 200px;
|
|
167
|
+
overflow-y: auto;
|
|
168
|
+
z-index: 1000;
|
|
169
|
+
|
|
170
|
+
&.below {
|
|
171
|
+
top: 100%;
|
|
172
|
+
margin-top: $space_xs;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
&.above {
|
|
176
|
+
bottom: 100%;
|
|
177
|
+
margin-bottom: $space_xs;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.pagination-dropdown-option {
|
|
182
|
+
padding: $pagination_padding;
|
|
183
|
+
cursor: pointer;
|
|
184
|
+
transition: background-color 0.2s ease;
|
|
185
|
+
|
|
186
|
+
&:hover {
|
|
187
|
+
background-color: $active_light;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&.active {
|
|
191
|
+
background-color: $primary;
|
|
192
|
+
.pb_body_kit {
|
|
193
|
+
color: $white;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&:first-child {
|
|
198
|
+
border-top-left-radius: $border_rad_light;
|
|
199
|
+
border-top-right-radius: $border_rad_light;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
&:last-child {
|
|
203
|
+
border-bottom-left-radius: $border_rad_light;
|
|
204
|
+
border-bottom-right-radius: $border_rad_light;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
107
207
|
}
|