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

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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
  *