playbook_ui 14.8.0.pre.alpha.PLAY16254545 → 14.8.0.pre.alpha.revert3916revert3893PBNTR667railstypeaheadformintegration4565

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b2b5ad03216b06c9f37e1792a0b208efbfd3d44b79f73696e1a3b006f89228c
4
- data.tar.gz: 282f44cd7aee29b4bc0ca84396be2a914a3786e91c8b308c5e7f284b84d4d74c
3
+ metadata.gz: fbcc7537aa0ece4caf4a922f2b49f40be79668e3cb793727a882184285669f05
4
+ data.tar.gz: 15d4b8d7216b62376bddd4da158f9bbb74b4eb9abbb88b88f7e425af6d0ad8df
5
5
  SHA512:
6
- metadata.gz: 0b14587326a80d3f8a7663ab14df6c51720aae8ad3a3492370dd853a956292a7b80901b2782e6ea04fbdb37b38d7810490234b4396bc9c891158432c208578f4
7
- data.tar.gz: a1f50ae88764cf79258478662bd9cd294b394d8c3cbd3c96580045ba2a5a67c3d924d9ee0170daf134ca9400078c4709c18dff06ea98927392f412343b5d7216
6
+ metadata.gz: 03e07711563ef5c12a4785ad6f01d1168d9360f9a4881ea8c86bd1a878991c611c9cf4e2a27b14c8355469e18c6516fe2fe0fa6426ed8960ee7e7600631648e5
7
+ data.tar.gz: ab58d3db94e12e61aac2e00804a200681452b909cbfb4ac17d57a62a56f6003ea23909551e7ebf5739f6840ded08bcb6f08180a8395536aad982eb2683cd0988
@@ -23,7 +23,7 @@
23
23
  %>
24
24
 
25
25
  <%= pb_form_with(scope: :example, url: "", method: :get) do |form| %>
26
- <%= form.typeahead :example_user, props: { data: { typeahead_example1: true, user: {} }, placeholder: "Search for a user" } %>
26
+ <%= form.typeahead :example_typeahead, props: { data: { typeahead_example1: true, user: {} }, label: true, placeholder: "Search for a user" } %>
27
27
  <%= form.text_field :example_text_field, props: { label: true } %>
28
28
  <%= form.phone_number_field :example_phone_number_field, props: { label: "Example phone field" } %>
29
29
  <%= form.email_field :example_email_field, props: { label: true } %>
@@ -92,7 +92,7 @@
92
92
  const selectedUserData = JSON.parse(selectedUserJSON)
93
93
 
94
94
  // set the input field's value
95
- event.target.querySelector('input[name=example_user]').value = selectedUserData.login
95
+ event.target.querySelector('input[name=example_typeahead]').value = selectedUserData.login
96
96
 
97
97
  // log the selected option's dataset
98
98
  console.log('The selected user data:')
@@ -1,5 +1,5 @@
1
1
  <%= pb_form_with(scope: :example, url: "", method: :get, loading: true) do |form| %>
2
- <%= form.text_field :example_text_field, props: { label: true } %>
2
+ <%= form.text_field :example_text_field_loading, props: { label: true } %>
3
3
 
4
4
  <%= form.actions do |action| %>
5
5
  <%= action.submit %>
@@ -22,23 +22,74 @@
22
22
  %>
23
23
 
24
24
  <%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
25
- <%= form.text_field :example_text_field, props: { label: true, required: true } %>
26
- <%= form.phone_number_field :example_phone_number_field, props: { label: "Example phone field" } %>
27
- <%= form.email_field :example_email_field, props: { label: true, required: true } %>
28
- <%= form.number_field :example_number_field, props: { label: true, required: true } %>
29
- <%= form.search_field :example_project_number, props: { label: true, required: true, validation: { pattern: "[0-9]{2}-[0-9]{5}", message: "Please enter a valid project number (example: 33-12345)." } } %>
30
- <%= form.password_field :example_password_field, props: { label: true, required: true } %>
31
- <%= form.url_field :example_url_field, props: { label: true, required: true } %>
32
- <%= form.text_area :example_text_area, props: { label: true, required: true } %>
33
- <%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options, required: true } %>
34
- <%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
35
- <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
25
+ <%= form.typeahead :example_typeahead_validation, props: { data: { typeahead_example2: true, user: {} }, label: true, placeholder: "Search for a user", required: true, validation: { message: "Please select a user." } } %>
26
+ <%= form.text_field :example_text_field_validation, props: { label: true, required: true } %>
27
+ <%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field" } %>
28
+ <%= form.email_field :example_email_field_validation, props: { label: true, required: true } %>
29
+ <%= form.number_field :example_number_field_validation, props: { label: true, required: true } %>
30
+ <%= 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)." } } %>
31
+ <%= form.password_field :example_password_field_validation, props: { label: true, required: true } %>
32
+ <%= form.url_field :example_url_field_validation, props: { label: true, required: true } %>
33
+ <%= form.text_area :example_text_area_validation, props: { label: true, required: true } %>
34
+ <%= form.dropdown_field :example_dropdown_validation, props: { label: true, options: example_dropdown_options, required: true } %>
35
+ <%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
36
+ <%= form.collection_select :example_collection_select_validation, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
36
37
  <%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
37
38
  <%= form.date_picker :example_date_picker_2, props: { label: true, required: true } %>
38
- <%= form.star_rating_field :example_star_rating, props: { variant: "interactive", label: true, required: true } %>
39
+ <%= form.star_rating_field :example_star_rating_validation, props: { variant: "interactive", label: true, required: true } %>
39
40
 
40
41
  <%= form.actions do |action| %>
41
42
  <%= action.submit %>
42
43
  <%= action.button props: { type: "reset", text: "Cancel", variant: "secondary" } %>
43
44
  <% end %>
44
45
  <% end %>
46
+
47
+ <!-- form.typeahead user results example template -->
48
+ <template data-typeahead-example-result-option>
49
+ <%= pb_rails("user", props: {
50
+ name: tag(:slot, name: "name"),
51
+ orientation: "horizontal",
52
+ align: "left",
53
+ avatar_url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII=",
54
+ avatar: true
55
+ }) %>
56
+ </template>
57
+
58
+ <!-- form.typeahead JS example implementation -->
59
+ <%= javascript_tag defer: "defer" do %>
60
+ document.addEventListener("pb-typeahead-kit-search", function(event) {
61
+ if (!event.target.dataset || !event.target.dataset.typeaheadExample2) return
62
+
63
+ fetch(`https://api.github.com/search/users?q=${encodeURIComponent(event.detail.searchingFor)}`)
64
+ .then(response => response.json())
65
+ .then((result) => {
66
+ const resultOptionTemplate = document.querySelector("[data-typeahead-example-result-option]")
67
+
68
+ event.detail.setResults((result.items || []).map((user) => {
69
+ const wrapper = resultOptionTemplate.content.cloneNode(true)
70
+ wrapper.children[0].dataset.user = JSON.stringify(user)
71
+ wrapper.querySelector('slot[name="name"]').replaceWith(user.login)
72
+ wrapper.querySelector('img').dataset.src = user.avatar_url
73
+ return wrapper
74
+ }))
75
+ })
76
+ })
77
+
78
+
79
+ document.addEventListener("pb-typeahead-kit-result-option-selected", function(event) {
80
+ if (!event.target.dataset.typeaheadExample2) return
81
+
82
+ const selectedUserJSON = event.detail.selected.firstElementChild.dataset.user
83
+ const selectedUserData = JSON.parse(selectedUserJSON)
84
+
85
+ // set the input field's value
86
+ event.target.querySelector('input[name=example_typeahead_validation]').value = selectedUserData.login
87
+
88
+ // log the selected option's dataset
89
+ console.log('The selected user data:')
90
+ console.dir(selectedUserData)
91
+
92
+ // do even more with the data later - TBD
93
+ event.target.dataset.user = selectedUserJSON
94
+ })
95
+ <% end %>
@@ -2,7 +2,6 @@
2
2
  @import "../tokens/border_radius";
3
3
  @import "../tokens/spacing";
4
4
  @import "../tokens/shadows";
5
- @import "../tokens/positioning";
6
5
 
7
6
  [class^=pb_typeahead_kit] {
8
7
  .typeahead-kit-select__option {
@@ -100,7 +99,6 @@
100
99
  .typeahead-kit-select__menu {
101
100
  background-color: $bg_dark;
102
101
  color: $white;
103
- z-index: $z_1;
104
102
  }
105
103
  .typeahead-kit-select__option:hover {
106
104
  background-color: $active_dark;
@@ -184,7 +182,6 @@
184
182
  }
185
183
 
186
184
  .typeahead-kit-select__menu {
187
- z-index: $z_1;
188
185
  .typeahead-kit-select__menu-list {
189
186
  padding: 0;
190
187
  }
@@ -4,11 +4,12 @@ import { debounce } from 'lodash'
4
4
  export default class PbTypeahead extends PbEnhancedElement {
5
5
  _searchInput: HTMLInputElement
6
6
  _resultsElement: HTMLElement
7
- _debouncedSearch: Function
7
+ _debouncedSearch: () => void // changed - diff
8
8
  _resultsLoadingIndicator: HTMLElement
9
9
  _resultOptionTemplate: HTMLElement
10
10
  _resultsOptionCache: Map<string, Array<DocumentFragment>>
11
11
  _searchContext: string
12
+ _validSelection: boolean // changed - new
12
13
 
13
14
  static get selector() {
14
15
  return '[data-pb-typeahead-kit]'
@@ -19,6 +20,7 @@ export default class PbTypeahead extends PbEnhancedElement {
19
20
  this.searchInput.addEventListener('focus', () => this.debouncedSearch())
20
21
  this.searchInput.addEventListener('input', () => this.debouncedSearch())
21
22
  this.resultsElement.addEventListener('click', (event: MouseEvent) => this.optionSelected(event))
23
+ // this.element.closest('form')?.addEventListener('submit', (event) => this.handleFormSubmission(event)) // changed - new
22
24
  }
23
25
 
24
26
  handleKeydown(event: KeyboardEvent) {
@@ -86,12 +88,44 @@ export default class PbTypeahead extends PbEnhancedElement {
86
88
  const resultOption = (event.target as Element).closest('[data-result-option-item]')
87
89
  if (!resultOption) return
88
90
 
91
+ this._validSelection = true // changed - new
92
+ this.removeValidationError() // changed - new
93
+
89
94
  this.resultsCacheClear()
90
95
  this.searchInputClear()
91
96
  this.clearResults()
92
97
 
93
98
  this.element.dispatchEvent(new CustomEvent('pb-typeahead-kit-result-option-selected', { bubbles: true, detail: { selected: resultOption, typeahead: this } }))
94
99
  }
100
+ // changed - new
101
+ removeValidationError() {
102
+ const inputWrapper = this.searchInput.closest('.text_input_wrapper')
103
+ if (inputWrapper) {
104
+ const errorMessage = inputWrapper.querySelector('.pb_body_kit_negative') as HTMLElement
105
+ if (errorMessage) {
106
+ errorMessage.style.display = 'none'
107
+ }
108
+ this.searchInput.classList.remove('error')
109
+ }
110
+ }
111
+ // changed - new
112
+ showValidationError() {
113
+ const inputWrapper = this.searchInput.closest('.text_input_wrapper')
114
+ if (inputWrapper) {
115
+ const errorMessage = inputWrapper.querySelector('.pb_body_kit_negative') as HTMLElement
116
+ if (errorMessage) {
117
+ errorMessage.style.display = 'block'
118
+ }
119
+ this.searchInput.classList.add('error')
120
+ }
121
+ }
122
+ // changed - new
123
+ // handleFormSubmission(event: Event) {
124
+ // if (!this._validSelection) {
125
+ // this.showValidationError()
126
+ // event.preventDefault()
127
+ // }
128
+ // }
95
129
 
96
130
  clearResults() {
97
131
  this.resultsElement.innerHTML = ''
@@ -201,8 +235,263 @@ export default class PbTypeahead extends PbEnhancedElement {
201
235
  }
202
236
 
203
237
  toggleResultsLoadingIndicator(visible: boolean) {
204
- var visibilityProperty = '0'
238
+ let visibilityProperty = '0' // changed - diff
205
239
  if (visible) visibilityProperty = '1'
206
240
  this.resultsLoadingIndicator.style.opacity = visibilityProperty
207
241
  }
208
242
  }
243
+
244
+ // import PbEnhancedElement from '../pb_enhanced_element';
245
+ // import { debounce } from 'lodash';
246
+
247
+ // export default class PbTypeahead extends PbEnhancedElement {
248
+ // _searchInput: HTMLInputElement;
249
+ // _resultsElement: HTMLElement;
250
+ // _debouncedSearch: () => void;
251
+ // _resultsLoadingIndicator: HTMLElement;
252
+ // _resultOptionTemplate: HTMLElement;
253
+ // _resultsOptionCache: Map<string, Array<DocumentFragment>>;
254
+ // _searchContext: string;
255
+ // _validSelection: boolean;
256
+
257
+ // static get selector() {
258
+ // return '[data-pb-typeahead-kit]';
259
+ // }
260
+
261
+ // connect() {
262
+ // this.element.addEventListener('keydown', (event: KeyboardEvent) => this.handleKeydown(event));
263
+ // this.searchInput.addEventListener('focus', () => this.debouncedSearch());
264
+ // this.searchInput.addEventListener('input', () => this.debouncedSearch());
265
+ // this.resultsElement.addEventListener('click', (event: MouseEvent) => this.optionSelected(event));
266
+ // // this.attachFormSubmissionHandler();
267
+ // }
268
+
269
+ // // attachFormSubmissionHandler() {
270
+ // // const formElement = this.element.closest('form');
271
+ // // if (formElement) {
272
+ // // formElement.addEventListener('submit', (event: Event) => {
273
+ // // if (!this._validSelection) {
274
+ // // this.showValidationError();
275
+ // // event.preventDefault();
276
+ // // }
277
+ // // });
278
+ // // }
279
+ // // }
280
+
281
+ // handleKeydown(event: KeyboardEvent) {
282
+ // if (event.key === 'ArrowUp') {
283
+ // event.preventDefault();
284
+ // this.focusPreviousOption();
285
+ // } else if (event.key === 'ArrowDown') {
286
+ // event.preventDefault();
287
+ // this.focusNextOption();
288
+ // }
289
+ // }
290
+
291
+ // search() {
292
+ // if (this.searchTerm.length < parseInt(this.searchTermMinimumLength)) {
293
+ // return this.clearResults();
294
+ // }
295
+
296
+ // this.toggleResultsLoadingIndicator(true);
297
+ // this.showResults();
298
+
299
+ // const searchTerm = this.searchTerm;
300
+ // const searchContext = this.searchContext;
301
+ // const search = {
302
+ // searchingFor: searchTerm,
303
+ // searchingContext: searchContext,
304
+ // setResults: (results: Array<DocumentFragment>) => {
305
+ // this.resultsCacheUpdate(searchTerm, searchContext, results);
306
+ // },
307
+ // };
308
+ // this.element.dispatchEvent(new CustomEvent('pb-typeahead-kit-search', { bubbles: true, detail: search }));
309
+ // }
310
+
311
+ // resultsCacheUpdate(searchTerm: string, searchContext: string, results: Array<DocumentFragment>) {
312
+ // const searchTermAndContext = this.cacheKeyFor(searchTerm, searchContext);
313
+ // if (this.resultsOptionCache.has(searchTermAndContext)) {
314
+ // this.resultsOptionCache.delete(searchTermAndContext);
315
+ // }
316
+ // if (this.resultsOptionCache.size > 32) {
317
+ // this.resultsOptionCache.delete(this.resultsOptionCache.keys().next().value);
318
+ // }
319
+
320
+ // this.resultsOptionCache.set(searchTermAndContext, results);
321
+ // this.showResults();
322
+ // }
323
+
324
+ // resultsCacheClear() {
325
+ // this.resultsOptionCache.clear();
326
+ // }
327
+
328
+ // get debouncedSearch() {
329
+ // return this._debouncedSearch = (
330
+ // this._debouncedSearch ||
331
+ // debounce(this.search, parseInt(this.searchDebounceTimeout)).bind(this)
332
+ // );
333
+ // }
334
+
335
+ // showResults() {
336
+ // if (!this.resultsOptionCache.has(this.searchTermAndContext)) return;
337
+
338
+ // this.toggleResultsLoadingIndicator(false);
339
+ // this.clearResults();
340
+ // for (const result of this.resultsOptionCache.get(this.searchTermAndContext)) {
341
+ // this.resultsElement.appendChild(this.newResultOption(result.cloneNode(true)));
342
+ // }
343
+ // for (const result of this.resultsElement.querySelectorAll('[data-result-option-item]')) {
344
+ // result.addEventListener('mousedown', (event: MouseEvent) => this.optionSelected(event));
345
+ // }
346
+ // }
347
+
348
+ // optionSelected(event: MouseEvent) {
349
+ // const resultOption = (event.target as Element).closest('[data-result-option-item]');
350
+ // if (!resultOption) return;
351
+
352
+ // this._validSelection = true;
353
+ // this.removeValidationError();
354
+
355
+ // this.resultsCacheClear();
356
+ // this.searchInputClear();
357
+ // this.clearResults();
358
+
359
+ // this.element.dispatchEvent(new CustomEvent('pb-typeahead-kit-result-option-selected', {
360
+ // bubbles: true,
361
+ // detail: { selected: resultOption, typeahead: this },
362
+ // }));
363
+ // }
364
+
365
+ // removeValidationError() {
366
+ // const inputWrapper = this.searchInput.closest('.text_input_wrapper');
367
+ // if (inputWrapper) {
368
+ // const errorMessage = inputWrapper.querySelector('.pb_body_kit_negative') as HTMLElement;
369
+ // if (errorMessage) {
370
+ // errorMessage.style.display = 'none';
371
+ // }
372
+ // this.searchInput.classList.remove('error');
373
+ // }
374
+ // }
375
+
376
+ // showValidationError() {
377
+ // const inputWrapper = this.searchInput.closest('.text_input_wrapper');
378
+ // if (inputWrapper) {
379
+ // const errorMessage = inputWrapper.querySelector('.pb_body_kit_negative') as HTMLElement;
380
+ // if (errorMessage) {
381
+ // errorMessage.style.display = 'block';
382
+ // }
383
+ // this.searchInput.classList.add('error');
384
+ // }
385
+ // }
386
+
387
+ // clearResults() {
388
+ // this.resultsElement.innerHTML = '';
389
+ // }
390
+
391
+ // newResultOption(content: DocumentFragment) {
392
+ // const resultOption = (this.resultOptionTemplate as HTMLTemplateElement).content.cloneNode(true) as Element;
393
+ // resultOption.querySelector('slot[name="content"]').replaceWith(content);
394
+ // return resultOption;
395
+ // }
396
+
397
+ // focusPreviousOption() {
398
+ // const currentIndex = this.resultOptionItems.indexOf(this.currentSelectedResultOptionItem);
399
+ // const previousIndex = currentIndex - 1;
400
+ // const previousOptionItem = (
401
+ // this.resultOptionItems[previousIndex] ||
402
+ // this.resultOptionItems[this.resultOptionItems.length - 1]
403
+ // );
404
+ // (previousOptionItem as HTMLElement).focus();
405
+ // }
406
+
407
+ // focusNextOption() {
408
+ // const currentIndex = this.resultOptionItems.indexOf(this.currentSelectedResultOptionItem);
409
+ // const nextIndex = currentIndex + 1;
410
+ // const nextOptionItem = (
411
+ // this.resultOptionItems[nextIndex] ||
412
+ // this.resultOptionItems[0]
413
+ // );
414
+ // (nextOptionItem as HTMLElement).focus();
415
+ // }
416
+
417
+ // get resultOptionItems() {
418
+ // return Array.from(this.resultsElement.querySelectorAll('[data-result-option-item]'));
419
+ // }
420
+
421
+ // get currentSelectedResultOptionItem() {
422
+ // return document.activeElement.closest('[data-result-option-item]');
423
+ // }
424
+
425
+ // get searchInput() {
426
+ // return this._searchInput = (this._searchInput || this.element.querySelector('input[type="search"]'));
427
+ // }
428
+
429
+ // get searchTerm() {
430
+ // return this.searchInput.value;
431
+ // }
432
+
433
+ // get searchContext() {
434
+ // if (this._searchContext) return this._searchContext;
435
+
436
+ // const selector = (this.element as HTMLElement).dataset.searchContextValueSelector;
437
+ // if (selector) return ((
438
+ // this.element.parentNode.querySelector(selector) ||
439
+ // this.element.closest(selector)
440
+ // ) as HTMLInputElement).value;
441
+
442
+ // return null;
443
+ // }
444
+
445
+ // set searchContext(value) {
446
+ // this._searchContext = value;
447
+ // }
448
+
449
+ // get searchTermAndContext() {
450
+ // return this.cacheKeyFor(this.searchTerm, this.searchContext);
451
+ // }
452
+
453
+ // cacheKeyFor(searchTerm: string, searchContext: string) {
454
+ // return [searchTerm, JSON.stringify(searchContext)].join();
455
+ // }
456
+
457
+ // searchInputClear() {
458
+ // this.searchInput.value = '';
459
+ // }
460
+
461
+ // get searchTermMinimumLength() {
462
+ // return (this.element as HTMLElement).dataset.pbTypeaheadKitSearchTermMinimumLength;
463
+ // }
464
+
465
+ // get searchDebounceTimeout() {
466
+ // return (this.element as HTMLElement).dataset.pbTypeaheadKitSearchDebounceTimeout;
467
+ // }
468
+
469
+ // get resultsElement() {
470
+ // return this._resultsElement = (this._resultsElement || this.element.querySelector('[data-pb-typeahead-kit-results]'));
471
+ // }
472
+
473
+ // get resultOptionTemplate() {
474
+ // return this._resultOptionTemplate = (
475
+ // this._resultOptionTemplate ||
476
+ // this.element.querySelector('template[data-pb-typeahead-kit-result-option]')
477
+ // );
478
+ // }
479
+
480
+ // get resultsOptionCache() {
481
+ // return this._resultsOptionCache = (
482
+ // this._resultsOptionCache ||
483
+ // new Map
484
+ // );
485
+ // }
486
+
487
+ // get resultsLoadingIndicator() {
488
+ // return this._resultsLoadingIndicator = (
489
+ // this._resultsLoadingIndicator ||
490
+ // this.element.querySelector('[data-pb-typeahead-kit-loading-indicator]')
491
+ // );
492
+ // }
493
+
494
+ // toggleResultsLoadingIndicator(visible: boolean) {
495
+ // this.resultsLoadingIndicator.style.opacity = visible ? '1' : '0';
496
+ // }
497
+ // }
@@ -17,11 +17,14 @@
17
17
  <%= pb_rails("text_input", props: {
18
18
  type: "search",
19
19
  input_options: object.input_options,
20
- label: object.label,
21
20
  name: object.name,
22
21
  value: object.value,
23
22
  placeholder: object.placeholder,
24
23
  margin_bottom: "none",
24
+ required: object.required,
25
+ validation: object.validation,
26
+ label: object.label,
27
+ id: object.input_options[:id],
25
28
  }) %>
26
29
  <%= pb_rails("list", props: { ordered: false, borderless: false, xpadding: true, role: "status", aria: { live: "polite" }, data: { pb_typeahead_kit_results: true } }) do %>
27
30
  <% end %>
@@ -33,4 +36,4 @@
33
36
  <% end %>
34
37
  </template>
35
38
  <% end %>
36
- <% end %>
39
+ <% end %>
@@ -40,6 +40,10 @@ module Playbook
40
40
  prop :pill_color, type: Playbook::Props::Enum,
41
41
  values: %w[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],
42
42
  default: "primary"
43
+ prop :required, type: Playbook::Props::Boolean,
44
+ default: false
45
+ prop :validation, type: Playbook::Props::HashProp,
46
+ default: {}
43
47
 
44
48
  def classname
45
49
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
@@ -1,4 +1,4 @@
1
- import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useEffect,useMemo,useContext,createElement,useState,useRef,forwardRef,useLayoutEffect,useCallback,useImperativeHandle,Component,Fragment as Fragment$1}from"react";import{q as getDefaultExportFromCjs,w as filter,x as omit,j as getAllIcons,y as get,n as commonjsGlobal,v as colors$1,s as highchartsTheme,z as merge,r as highchartsDarkTheme,A as useCollapsible,B as getAugmentedNamespace,C as createPopper,E as uniqueId,F as typography,G as cloneDeep,H as isString}from"./lib-BC6ESsxG.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";import{TrixEditor}from"react-trix";import Trix from"trix";import require$$0 from"react-is";const initialState={items:[],dragData:{id:"",initialGroup:""},isDragging:"",activeContainer:""};const reducer=(state,action)=>{switch(action.type){case"SET_ITEMS":return Object.assign(Object.assign({},state),{items:action.payload});case"SET_DRAG_DATA":return Object.assign(Object.assign({},state),{dragData:action.payload});case"SET_IS_DRAGGING":return Object.assign(Object.assign({},state),{isDragging:action.payload});case"SET_ACTIVE_CONTAINER":return Object.assign(Object.assign({},state),{activeContainer:action.payload});case"CHANGE_CATEGORY":return Object.assign(Object.assign({},state),{items:state.items.map((item=>item.id===action.payload.itemId?Object.assign(Object.assign({},item),{container:action.payload.container}):item))});case"REORDER_ITEMS":{const{dragId:dragId,targetId:targetId}=action.payload;const newItems=[...state.items];const draggedItem=newItems.find((item=>item.id===dragId));const draggedIndex=newItems.indexOf(draggedItem);const targetIndex=newItems.findIndex((item=>item.id===targetId));newItems.splice(draggedIndex,1);newItems.splice(targetIndex,0,draggedItem);return Object.assign(Object.assign({},state),{items:newItems})}default:return state}};const DragContext=createContext({});const DraggableContext=()=>useContext(DragContext);const DraggableProvider=({children:children,initialItems:initialItems,onReorder:onReorder,onDragStart:onDragStart,onDragEnter:onDragEnter,onDragEnd:onDragEnd,onDrop:onDrop,onDragOver:onDragOver})=>{const[state,dispatch]=useReducer(reducer,initialState);useEffect((()=>{dispatch({type:"SET_ITEMS",payload:initialItems})}),[initialItems]);useEffect((()=>{onReorder(state.items)}),[state.items]);const handleDragStart=(id,container)=>{dispatch({type:"SET_DRAG_DATA",payload:{id:id,initialGroup:container}});dispatch({type:"SET_IS_DRAGGING",payload:id});if(onDragStart)onDragStart(id,container)};const handleDragEnter=(id,container)=>{if(state.dragData.id!==id){dispatch({type:"REORDER_ITEMS",payload:{dragId:state.dragData.id,targetId:id}});dispatch({type:"SET_DRAG_DATA",payload:{id:state.dragData.id,initialGroup:container}})}if(onDragEnter)onDragEnter(id,container)};const handleDragEnd=()=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});if(onDragEnd)onDragEnd()};const changeCategory=(itemId,container)=>{dispatch({type:"CHANGE_CATEGORY",payload:{itemId:itemId,container:container}})};const handleDrop=container=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});changeCategory(state.dragData.id,container);if(onDrop)onDrop(container)};const handleDragOver=(e2,container)=>{e2.preventDefault();dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragOver)onDragOver(e2,container)};const contextValue=useMemo((()=>({items:state.items,dragData:state.dragData,isDragging:state.isDragging,activeContainer:state.activeContainer,handleDragStart:handleDragStart,handleDragEnter:handleDragEnter,handleDragEnd:handleDragEnd,handleDrop:handleDrop,handleDragOver:handleDragOver})),[state]);return jsx$1(DragContext.Provider,Object.assign({value:contextValue},{children:children}),void 0)};var classnames$1={exports:{}};
1
+ import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useEffect,useMemo,useContext,createElement,useState,useRef,forwardRef,useLayoutEffect,useCallback,useImperativeHandle,Component,Fragment as Fragment$1}from"react";import{q as getDefaultExportFromCjs,w as filter,x as omit,j as getAllIcons,y as get,n as commonjsGlobal,v as colors$1,s as highchartsTheme,z as merge,r as highchartsDarkTheme,A as useCollapsible,B as getAugmentedNamespace,C as createPopper,E as uniqueId,F as typography,G as cloneDeep,H as isString}from"./lib-SyD3buPZ.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";import{TrixEditor}from"react-trix";import Trix from"trix";import require$$0 from"react-is";const initialState={items:[],dragData:{id:"",initialGroup:""},isDragging:"",activeContainer:""};const reducer=(state,action)=>{switch(action.type){case"SET_ITEMS":return Object.assign(Object.assign({},state),{items:action.payload});case"SET_DRAG_DATA":return Object.assign(Object.assign({},state),{dragData:action.payload});case"SET_IS_DRAGGING":return Object.assign(Object.assign({},state),{isDragging:action.payload});case"SET_ACTIVE_CONTAINER":return Object.assign(Object.assign({},state),{activeContainer:action.payload});case"CHANGE_CATEGORY":return Object.assign(Object.assign({},state),{items:state.items.map((item=>item.id===action.payload.itemId?Object.assign(Object.assign({},item),{container:action.payload.container}):item))});case"REORDER_ITEMS":{const{dragId:dragId,targetId:targetId}=action.payload;const newItems=[...state.items];const draggedItem=newItems.find((item=>item.id===dragId));const draggedIndex=newItems.indexOf(draggedItem);const targetIndex=newItems.findIndex((item=>item.id===targetId));newItems.splice(draggedIndex,1);newItems.splice(targetIndex,0,draggedItem);return Object.assign(Object.assign({},state),{items:newItems})}default:return state}};const DragContext=createContext({});const DraggableContext=()=>useContext(DragContext);const DraggableProvider=({children:children,initialItems:initialItems,onReorder:onReorder,onDragStart:onDragStart,onDragEnter:onDragEnter,onDragEnd:onDragEnd,onDrop:onDrop,onDragOver:onDragOver})=>{const[state,dispatch]=useReducer(reducer,initialState);useEffect((()=>{dispatch({type:"SET_ITEMS",payload:initialItems})}),[initialItems]);useEffect((()=>{onReorder(state.items)}),[state.items]);const handleDragStart=(id,container)=>{dispatch({type:"SET_DRAG_DATA",payload:{id:id,initialGroup:container}});dispatch({type:"SET_IS_DRAGGING",payload:id});if(onDragStart)onDragStart(id,container)};const handleDragEnter=(id,container)=>{if(state.dragData.id!==id){dispatch({type:"REORDER_ITEMS",payload:{dragId:state.dragData.id,targetId:id}});dispatch({type:"SET_DRAG_DATA",payload:{id:state.dragData.id,initialGroup:container}})}if(onDragEnter)onDragEnter(id,container)};const handleDragEnd=()=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});if(onDragEnd)onDragEnd()};const changeCategory=(itemId,container)=>{dispatch({type:"CHANGE_CATEGORY",payload:{itemId:itemId,container:container}})};const handleDrop=container=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});changeCategory(state.dragData.id,container);if(onDrop)onDrop(container)};const handleDragOver=(e2,container)=>{e2.preventDefault();dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragOver)onDragOver(e2,container)};const contextValue=useMemo((()=>({items:state.items,dragData:state.dragData,isDragging:state.isDragging,activeContainer:state.activeContainer,handleDragStart:handleDragStart,handleDragEnter:handleDragEnter,handleDragEnd:handleDragEnd,handleDrop:handleDrop,handleDragOver:handleDragOver})),[state]);return jsx$1(DragContext.Provider,Object.assign({value:contextValue},{children:children}),void 0)};var classnames$1={exports:{}};
2
2
  /*!
3
3
  Copyright (c) 2018 Jed Watson.
4
4
  Licensed under the MIT License (MIT), see
@@ -1,4 +1,4 @@
1
- import{r as requireLazysizes}from"./lazysizes-B7xYodB-.js";import{jsx,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{useEffect,createContext,useContext,useState,useCallback,createElement,forwardRef,useRef,useImperativeHandle,Fragment as Fragment$1,useReducer,useMemo,useLayoutEffect,isValidElement}from"react";import{h as buildAriaProps,i as buildDataProps,j as buildHtmlProps,k as classnames,l as globalProps,m as buildCss,F as Flex,I as Icon,n as FlexItem,o as Body$1,p as Caption,A as Avatar,q as domSafeProps,r as Title,S as SectionSeparator,s as DialogContext,t as Draggable,u as TextInput,_ as __awaiter,v as __generator,w as __spread,x as PropTypes,y as Card,z as noop$3,E as PbReactPopover,H as CircleIconButton,J as Button,K as HighchartsReact,N as Badge,O as joinPresent,Q as titleize,U as IconCircle,V as Image,W as Checkbox,X as Radio}from"./_typeahead-D0PihN_3.js";import{h as PbTable,j as getAllIcons,D as DateTime$1,a as datePickerHelper,u as useDropdown,o as omitBy,k as isEmpty,m as map,p as partial,l as find$1,n as commonjsGlobal,q as getDefaultExportFromCjs,r as highchartsDarkTheme,s as highchartsTheme,t as noop$4,v as colors,i as PbTextarea}from"./lib-BC6ESsxG.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";var ls_attrchange={exports:{}};(function(module){(function(window2,factory){if(!window2){return}var globalInstall=function(){factory(window2.lazySizes);window2.removeEventListener("lazyunveilread",globalInstall,true)};factory=factory.bind(null,window2,window2.document);if(module.exports){factory(requireLazysizes())}else if(window2.lazySizes){globalInstall()}else{window2.addEventListener("lazyunveilread",globalInstall,true)}})(typeof window!="undefined"?window:0,(function(window2,document2,lazySizes){var addObserver=function(){var connect,disconnect,observer,connected;var lsCfg=lazySizes.cfg;var attributes={"data-bgset":1,"data-include":1,"data-poster":1,"data-bg":1,"data-script":1};var regClassTest="(\\s|^)("+lsCfg.loadedClass;var docElem=document2.documentElement;var setClass=function(target){lazySizes.rAF((function(){lazySizes.rC(target,lsCfg.loadedClass);if(lsCfg.unloadedClass){lazySizes.rC(target,lsCfg.unloadedClass)}lazySizes.aC(target,lsCfg.lazyClass);if(target.style.display=="none"||target.parentNode&&target.parentNode.style.display=="none"){setTimeout((function(){lazySizes.loader.unveil(target)}),0)}}))};var onMutation=function(mutations){var i,len,mutation,target;for(i=0,len=mutations.length;i<len;i++){mutation=mutations[i];target=mutation.target;if(!target.getAttribute(mutation.attributeName)){continue}if(target.localName=="source"&&target.parentNode){target=target.parentNode.querySelector("img")}if(target&&regClassTest.test(target.className)){setClass(target)}}};if(lsCfg.unloadedClass){regClassTest+="|"+lsCfg.unloadedClass}regClassTest+="|"+lsCfg.loadingClass+")(\\s|$)";regClassTest=new RegExp(regClassTest);attributes[lsCfg.srcAttr]=1;attributes[lsCfg.srcsetAttr]=1;if(window2.MutationObserver){observer=new MutationObserver(onMutation);connect=function(){if(!connected){connected=true;observer.observe(docElem,{subtree:true,attributes:true,attributeFilter:Object.keys(attributes)})}};disconnect=function(){if(connected){connected=false;observer.disconnect()}}}else{docElem.addEventListener("DOMAttrModified",function(){var runs;var modifications=[];var callMutations=function(){onMutation(modifications);modifications=[];runs=false};return function(e){if(connected&&attributes[e.attrName]&&e.newValue){modifications.push({target:e.target,attributeName:e.attrName});if(!runs){setTimeout(callMutations);runs=true}}}}(),true);connect=function(){connected=true};disconnect=function(){connected=false}}addEventListener("lazybeforeunveil",disconnect,true);addEventListener("lazybeforeunveil",connect);addEventListener("lazybeforesizes",disconnect,true);addEventListener("lazybeforesizes",connect);connect();removeEventListener("lazybeforeunveil",addObserver)};addEventListener("lazybeforeunveil",addObserver)}))})(ls_attrchange);
1
+ import{r as requireLazysizes}from"./lazysizes-B7xYodB-.js";import{jsx,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{useEffect,createContext,useContext,useState,useCallback,createElement,forwardRef,useRef,useImperativeHandle,Fragment as Fragment$1,useReducer,useMemo,useLayoutEffect,isValidElement}from"react";import{h as buildAriaProps,i as buildDataProps,j as buildHtmlProps,k as classnames,l as globalProps,m as buildCss,F as Flex,I as Icon,n as FlexItem,o as Body$1,p as Caption,A as Avatar,q as domSafeProps,r as Title,S as SectionSeparator,s as DialogContext,t as Draggable,u as TextInput,_ as __awaiter,v as __generator,w as __spread,x as PropTypes,y as Card,z as noop$3,E as PbReactPopover,H as CircleIconButton,J as Button,K as HighchartsReact,N as Badge,O as joinPresent,Q as titleize,U as IconCircle,V as Image,W as Checkbox,X as Radio}from"./_typeahead-IoHUnHeF.js";import{h as PbTable,j as getAllIcons,D as DateTime$1,a as datePickerHelper,u as useDropdown,o as omitBy,k as isEmpty,m as map,p as partial,l as find$1,n as commonjsGlobal,q as getDefaultExportFromCjs,r as highchartsDarkTheme,s as highchartsTheme,t as noop$4,v as colors,i as PbTextarea}from"./lib-SyD3buPZ.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";var ls_attrchange={exports:{}};(function(module){(function(window2,factory){if(!window2){return}var globalInstall=function(){factory(window2.lazySizes);window2.removeEventListener("lazyunveilread",globalInstall,true)};factory=factory.bind(null,window2,window2.document);if(module.exports){factory(requireLazysizes())}else if(window2.lazySizes){globalInstall()}else{window2.addEventListener("lazyunveilread",globalInstall,true)}})(typeof window!="undefined"?window:0,(function(window2,document2,lazySizes){var addObserver=function(){var connect,disconnect,observer,connected;var lsCfg=lazySizes.cfg;var attributes={"data-bgset":1,"data-include":1,"data-poster":1,"data-bg":1,"data-script":1};var regClassTest="(\\s|^)("+lsCfg.loadedClass;var docElem=document2.documentElement;var setClass=function(target){lazySizes.rAF((function(){lazySizes.rC(target,lsCfg.loadedClass);if(lsCfg.unloadedClass){lazySizes.rC(target,lsCfg.unloadedClass)}lazySizes.aC(target,lsCfg.lazyClass);if(target.style.display=="none"||target.parentNode&&target.parentNode.style.display=="none"){setTimeout((function(){lazySizes.loader.unveil(target)}),0)}}))};var onMutation=function(mutations){var i,len,mutation,target;for(i=0,len=mutations.length;i<len;i++){mutation=mutations[i];target=mutation.target;if(!target.getAttribute(mutation.attributeName)){continue}if(target.localName=="source"&&target.parentNode){target=target.parentNode.querySelector("img")}if(target&&regClassTest.test(target.className)){setClass(target)}}};if(lsCfg.unloadedClass){regClassTest+="|"+lsCfg.unloadedClass}regClassTest+="|"+lsCfg.loadingClass+")(\\s|$)";regClassTest=new RegExp(regClassTest);attributes[lsCfg.srcAttr]=1;attributes[lsCfg.srcsetAttr]=1;if(window2.MutationObserver){observer=new MutationObserver(onMutation);connect=function(){if(!connected){connected=true;observer.observe(docElem,{subtree:true,attributes:true,attributeFilter:Object.keys(attributes)})}};disconnect=function(){if(connected){connected=false;observer.disconnect()}}}else{docElem.addEventListener("DOMAttrModified",function(){var runs;var modifications=[];var callMutations=function(){onMutation(modifications);modifications=[];runs=false};return function(e){if(connected&&attributes[e.attrName]&&e.newValue){modifications.push({target:e.target,attributeName:e.attrName});if(!runs){setTimeout(callMutations);runs=true}}}}(),true);connect=function(){connected=true};disconnect=function(){connected=false}}addEventListener("lazybeforeunveil",disconnect,true);addEventListener("lazybeforeunveil",connect);addEventListener("lazybeforesizes",disconnect,true);addEventListener("lazybeforesizes",connect);connect();removeEventListener("lazybeforeunveil",addObserver)};addEventListener("lazybeforeunveil",addObserver)}))})(ls_attrchange);
2
2
  /**
3
3
  * table-core
4
4
  *