@patternfly/pfe-core 2.4.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +0 -1
  2. package/controllers/activedescendant-controller.d.ts +99 -0
  3. package/controllers/activedescendant-controller.js +230 -0
  4. package/controllers/activedescendant-controller.js.map +1 -0
  5. package/controllers/at-focus-controller.d.ts +56 -0
  6. package/controllers/at-focus-controller.js +168 -0
  7. package/controllers/at-focus-controller.js.map +1 -0
  8. package/controllers/cascade-controller.d.ts +11 -0
  9. package/controllers/cascade-controller.js +10 -3
  10. package/controllers/cascade-controller.js.map +1 -1
  11. package/controllers/combobox-controller.d.ts +117 -0
  12. package/controllers/combobox-controller.js +611 -0
  13. package/controllers/combobox-controller.js.map +1 -0
  14. package/controllers/css-variable-controller.js +1 -1
  15. package/controllers/css-variable-controller.js.map +1 -1
  16. package/controllers/floating-dom-controller.d.ts +10 -3
  17. package/controllers/floating-dom-controller.js +93 -83
  18. package/controllers/floating-dom-controller.js.map +1 -1
  19. package/controllers/internals-controller.d.ts +104 -42
  20. package/controllers/internals-controller.js +354 -36
  21. package/controllers/internals-controller.js.map +1 -1
  22. package/controllers/light-dom-controller.js +2 -2
  23. package/controllers/light-dom-controller.js.map +1 -1
  24. package/controllers/listbox-controller.d.ts +143 -0
  25. package/controllers/listbox-controller.js +443 -0
  26. package/controllers/listbox-controller.js.map +1 -0
  27. package/controllers/logger.d.ts +33 -6
  28. package/controllers/logger.js +58 -13
  29. package/controllers/logger.js.map +1 -1
  30. package/controllers/overflow-controller.d.ts +10 -3
  31. package/controllers/overflow-controller.js +79 -44
  32. package/controllers/overflow-controller.js.map +1 -1
  33. package/controllers/perf-controller.js.map +1 -1
  34. package/controllers/property-observer-controller.d.ts +13 -16
  35. package/controllers/property-observer-controller.js +55 -27
  36. package/controllers/property-observer-controller.js.map +1 -1
  37. package/controllers/roving-tabindex-controller.d.ts +19 -50
  38. package/controllers/roving-tabindex-controller.js +64 -183
  39. package/controllers/roving-tabindex-controller.js.map +1 -1
  40. package/controllers/scroll-spy-controller.d.ts +4 -1
  41. package/controllers/scroll-spy-controller.js +94 -93
  42. package/controllers/scroll-spy-controller.js.map +1 -1
  43. package/controllers/slot-controller.d.ts +26 -19
  44. package/controllers/slot-controller.js +94 -83
  45. package/controllers/slot-controller.js.map +1 -1
  46. package/controllers/style-controller.js +3 -1
  47. package/controllers/style-controller.js.map +1 -1
  48. package/controllers/tabs-aria-controller.d.ts +31 -0
  49. package/controllers/tabs-aria-controller.js +97 -0
  50. package/controllers/tabs-aria-controller.js.map +1 -0
  51. package/controllers/test/combobox-controller.spec.d.ts +1 -0
  52. package/controllers/test/combobox-controller.spec.js +282 -0
  53. package/controllers/test/combobox-controller.spec.js.map +1 -0
  54. package/controllers/timestamp-controller.js +73 -70
  55. package/controllers/timestamp-controller.js.map +1 -1
  56. package/core.d.ts +3 -23
  57. package/core.js +1 -38
  58. package/core.js.map +1 -1
  59. package/custom-elements.json +7302 -2817
  60. package/decorators/bound.d.ts +3 -1
  61. package/decorators/bound.js +3 -1
  62. package/decorators/bound.js.map +1 -1
  63. package/decorators/cascades.d.ts +2 -0
  64. package/decorators/cascades.js +2 -0
  65. package/decorators/cascades.js.map +1 -1
  66. package/decorators/deprecation.d.ts +6 -5
  67. package/decorators/deprecation.js +6 -5
  68. package/decorators/deprecation.js.map +1 -1
  69. package/decorators/initializer.js.map +1 -1
  70. package/decorators/listen.d.ts +8 -0
  71. package/decorators/listen.js +22 -0
  72. package/decorators/listen.js.map +1 -0
  73. package/decorators/observed.d.ts +12 -16
  74. package/decorators/observed.js +39 -44
  75. package/decorators/observed.js.map +1 -1
  76. package/decorators/observes.d.ts +15 -0
  77. package/decorators/observes.js +30 -0
  78. package/decorators/observes.js.map +1 -0
  79. package/decorators/time.d.ts +1 -0
  80. package/decorators/time.js +6 -9
  81. package/decorators/time.js.map +1 -1
  82. package/decorators/trace.d.ts +4 -1
  83. package/decorators/trace.js +4 -1
  84. package/decorators/trace.js.map +1 -1
  85. package/decorators.d.ts +2 -0
  86. package/decorators.js +2 -0
  87. package/decorators.js.map +1 -1
  88. package/functions/arraysAreEquivalent.d.ts +9 -0
  89. package/functions/arraysAreEquivalent.js +28 -0
  90. package/functions/arraysAreEquivalent.js.map +1 -0
  91. package/functions/containsDeep.d.ts +8 -0
  92. package/functions/containsDeep.js +23 -0
  93. package/functions/containsDeep.js.map +1 -0
  94. package/functions/context.d.ts +8 -0
  95. package/functions/context.js +21 -0
  96. package/functions/context.js.map +1 -0
  97. package/functions/debounce.js.map +1 -1
  98. package/functions/isElementInView.d.ts +4 -6
  99. package/functions/isElementInView.js +9 -11
  100. package/functions/isElementInView.js.map +1 -1
  101. package/package.json +10 -4
  102. package/functions/deprecatedCustomEvent.d.ts +0 -5
  103. package/functions/deprecatedCustomEvent.js +0 -12
  104. package/functions/deprecatedCustomEvent.js.map +0 -1
@@ -0,0 +1,282 @@
1
+ var _a;
2
+ import { __decorate } from "tslib";
3
+ import { expect, fixture, nextFrame } from '@open-wc/testing';
4
+ import { sendKeys } from '@web/test-runner-commands';
5
+ import { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js';
6
+ import { customElement } from 'lit/decorators/custom-element.js';
7
+ import { query } from 'lit/decorators/query.js';
8
+ import { ReactiveElement, html, render } from 'lit';
9
+ import { ComboboxController } from '../combobox-controller.js';
10
+ function press(key) {
11
+ return async function () {
12
+ await sendKeys({ press: key });
13
+ };
14
+ }
15
+ class TestCombobox extends ReactiveElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.controller = ComboboxController.of(this, {
19
+ multi: false,
20
+ getItems: () => this.options,
21
+ isItem: item => item instanceof HTMLOptionElement,
22
+ getFallbackLabel: () => 'options',
23
+ getListboxElement: () => this.listbox ?? null,
24
+ getToggleButton: () => this.button ?? null,
25
+ getComboboxInput: () => this.combobox ?? null,
26
+ isExpanded: () => !this.listbox.hidden,
27
+ requestShowListbox: () => void (this.listbox.hidden = false),
28
+ requestHideListbox: () => void (this.listbox.hidden = true),
29
+ setItemActive: (item, active) => item.classList.toggle('active', active),
30
+ setItemSelected: (item, selected) => item.selected = selected,
31
+ });
32
+ }
33
+ /** List of options */
34
+ get options() {
35
+ return [
36
+ ...new Set([
37
+ this.placeholder,
38
+ ...this.querySelectorAll('option'),
39
+ ...this.renderRoot.querySelectorAll('option'),
40
+ ]),
41
+ ].filter(x => !!x);
42
+ }
43
+ get selected() {
44
+ return this.options.filter(x => x.selected);
45
+ }
46
+ get activeOption() {
47
+ return this.options.find(x => x.classList.contains('active'));
48
+ }
49
+ update(changed) {
50
+ render(this.render(), this.renderRoot);
51
+ super.update(changed);
52
+ this.placeholder.inert = !!this.controller.selected.length;
53
+ }
54
+ connectedCallback() {
55
+ super.connectedCallback();
56
+ const root = this.renderRoot.getRootNode();
57
+ root.adoptedStyleSheets = [...root.adoptedStyleSheets ?? [], _a.styles];
58
+ }
59
+ static async test() {
60
+ let element;
61
+ const updateComplete = () => element.updateComplete;
62
+ const { template } = this;
63
+ if (!template) {
64
+ throw new Error(`${this.constructor.name} must implement template`);
65
+ }
66
+ beforeEach(async function () {
67
+ element = await fixture(template);
68
+ });
69
+ describe('Tab', function () {
70
+ beforeEach(press('Tab'));
71
+ beforeEach(updateComplete);
72
+ it('focuses the combobox', async function () {
73
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
74
+ });
75
+ describe('Tab', function () {
76
+ beforeEach(press('Tab'));
77
+ beforeEach(updateComplete);
78
+ beforeEach(nextFrame);
79
+ it('does not focus the toggle button', async function () {
80
+ expect(await a11ySnapshot()).to.not.axContainQuery({ focused: true });
81
+ });
82
+ });
83
+ describe('ArrowDown', function () {
84
+ beforeEach(press('ArrowDown'));
85
+ beforeEach(updateComplete);
86
+ it('expands the listbox', async function () {
87
+ expect(await a11ySnapshot())
88
+ .to.axContainRole('listbox')
89
+ .and
90
+ .to.axContainQuery({ role: 'combobox', expanded: true });
91
+ });
92
+ it('maintains DOM focus on the combobox', async function () {
93
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
94
+ });
95
+ it('sets active state on the placeholder', function () {
96
+ expect(element.activeOption).to.equal(element.placeholder);
97
+ });
98
+ describe('Enter', function () {
99
+ beforeEach(press('Enter'));
100
+ beforeEach(updateComplete);
101
+ it('maintains DOM focus on the combobox', async function () {
102
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
103
+ });
104
+ it('selects nothing', function () {
105
+ expect(element.selected).to.have.length(0);
106
+ });
107
+ });
108
+ describe('ArrowDown', function () {
109
+ beforeEach(press('ArrowDown'));
110
+ beforeEach(updateComplete);
111
+ it('maintains DOM focus on the combobox', async function () {
112
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
113
+ });
114
+ it('sets active state on the 1st option', function () {
115
+ expect(element.activeOption).to.have.text('1');
116
+ });
117
+ describe('Enter', function () {
118
+ beforeEach(press('Enter'));
119
+ beforeEach(updateComplete);
120
+ it('maintains DOM focus on the combobox', async function () {
121
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
122
+ });
123
+ it('selects the first option', function () {
124
+ expect(element.selected).to.have.length(1);
125
+ expect(element.selected.at(0)).to.have.text('1');
126
+ });
127
+ it('collapses the listbox', async function () {
128
+ expect(await a11ySnapshot())
129
+ .to.not.axContainRole('listbox')
130
+ .and
131
+ .to.axContainQuery({ role: 'combobox', expanded: false });
132
+ });
133
+ });
134
+ });
135
+ describe('Escape', function () {
136
+ beforeEach(press('Escape'));
137
+ beforeEach(updateComplete);
138
+ it('collapses the listbox', async function () {
139
+ expect(await a11ySnapshot())
140
+ .to.not.axContainRole('listbox')
141
+ .and
142
+ .to.axContainQuery({ role: 'combobox', expanded: false });
143
+ });
144
+ it('maintains DOM focus on the combobox', async function () {
145
+ expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');
146
+ });
147
+ });
148
+ });
149
+ });
150
+ }
151
+ ;
152
+ }
153
+ _a = TestCombobox;
154
+ TestCombobox.styles = new CSSStyleSheet();
155
+ (() => {
156
+ _a.styles.replaceSync(/* css */ `
157
+ option {
158
+ &.active {
159
+ outline: 1px solid black;
160
+ }
161
+ &[selected] {
162
+ background: lightblue;
163
+ }
164
+ }
165
+ `);
166
+ })();
167
+ __decorate([
168
+ query('#listbox')
169
+ ], TestCombobox.prototype, "listbox", void 0);
170
+ __decorate([
171
+ query('#button')
172
+ ], TestCombobox.prototype, "button", void 0);
173
+ __decorate([
174
+ query('#combobox')
175
+ ], TestCombobox.prototype, "combobox", void 0);
176
+ __decorate([
177
+ query('#placeholder')
178
+ ], TestCombobox.prototype, "placeholder", void 0);
179
+ let XComboboxCrossRoot = class XComboboxCrossRoot extends TestCombobox {
180
+ /** List of options */
181
+ get options() {
182
+ return [
183
+ ...new Set([
184
+ this.placeholder,
185
+ ...this.querySelectorAll('option'),
186
+ ]),
187
+ ].filter(x => !!x);
188
+ }
189
+ render() {
190
+ return html `
191
+ <div id="toggle">
192
+ <input id="combobox">
193
+ <button id="button">Show Options</button>
194
+ </div>
195
+ <div id="listbox">
196
+ <option id="placeholder" aria-disabled="true">Select an Option</option>
197
+ ${this.controller.renderItemsToShadowRoot()}
198
+ <div ?hidden=${!ComboboxController.supportsCrossRootActiveDescendant}>
199
+ <slot></slot>
200
+ </div>
201
+ </div>
202
+ `;
203
+ }
204
+ };
205
+ XComboboxCrossRoot.template = html `
206
+ <x-combobox-cross-root>
207
+ <option>1</option>
208
+ <option>2</option>
209
+ <option>3</option>
210
+ <option>4</option>
211
+ <option>5</option>
212
+ <option>6</option>
213
+ <option>7</option>
214
+ <option>8</option>
215
+ <option>9</option>
216
+ <option>10</option>
217
+ </x-combobox-cross-root>
218
+ `;
219
+ XComboboxCrossRoot = __decorate([
220
+ customElement('x-combobox-cross-root')
221
+ ], XComboboxCrossRoot);
222
+ let XComboboxLight = class XComboboxLight extends TestCombobox {
223
+ createRenderRoot() {
224
+ return this;
225
+ }
226
+ render() {
227
+ return html `
228
+ <input id="combobox">
229
+ <button id="button">Show Options</button>
230
+ <div id="listbox">
231
+ <option id="placeholder" aria-disabled="true">Select an Option</option>
232
+ <option>1</option>
233
+ <option>2</option>
234
+ <option>3</option>
235
+ <option>4</option>
236
+ <option>5</option>
237
+ <option>6</option>
238
+ <option>7</option>
239
+ <option>8</option>
240
+ <option>9</option>
241
+ <option>10</option>
242
+ </div>`;
243
+ }
244
+ };
245
+ XComboboxLight.template = html `
246
+ <x-combobox-light></x-combobox-light>
247
+ `;
248
+ XComboboxLight = __decorate([
249
+ customElement('x-combobox-light')
250
+ ], XComboboxLight);
251
+ let XComboboxShadow = class XComboboxShadow extends TestCombobox {
252
+ render() {
253
+ return html `
254
+ <input id="combobox">
255
+ <button id="button">Show Options</button>
256
+ <div id="listbox">
257
+ <option id="placeholder" aria-disabled="true">Select an Option</option>
258
+ <option>1</option>
259
+ <option>2</option>
260
+ <option>3</option>
261
+ <option>4</option>
262
+ <option>5</option>
263
+ <option>6</option>
264
+ <option>7</option>
265
+ <option>8</option>
266
+ <option>9</option>
267
+ <option>10</option>
268
+ </div>`;
269
+ }
270
+ };
271
+ XComboboxShadow.template = html `
272
+ <x-combobox-shadow></x-combobox-shadow>
273
+ `;
274
+ XComboboxShadow = __decorate([
275
+ customElement('x-combobox-shadow')
276
+ ], XComboboxShadow);
277
+ describe('ComboboxController', function () {
278
+ describe('Cross-root ARIA', XComboboxCrossRoot.test.bind(XComboboxCrossRoot));
279
+ describe('Light-DOM only', XComboboxLight.test.bind(XComboboxLight));
280
+ describe('Shadow-DOM only', XComboboxShadow.test.bind(XComboboxShadow));
281
+ });
282
+ //# sourceMappingURL=combobox-controller.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-controller.spec.js","sourceRoot":"","sources":["combobox-controller.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, nextFrame } from '@open-wc/testing';\nimport { sendKeys } from '@web/test-runner-commands';\nimport { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js';\n\nimport { customElement } from 'lit/decorators/custom-element.js';\nimport { query } from 'lit/decorators/query.js';\nimport { ReactiveElement, html, render, type PropertyValues, type TemplateResult } from 'lit';\n\nimport { ComboboxController } from '../combobox-controller.js';\n\nfunction press(key: string) {\n return async function() {\n await sendKeys({ press: key });\n };\n}\n\nabstract class TestCombobox extends ReactiveElement {\n declare static template: TemplateResult;\n\n static styles = new CSSStyleSheet();\n\n static {\n this.styles.replaceSync(/* css */`\n option {\n &.active {\n outline: 1px solid black;\n }\n &[selected] {\n background: lightblue;\n }\n }\n `);\n }\n\n controller = ComboboxController.of(this, {\n multi: false,\n getItems: () => this.options,\n isItem: item => item instanceof HTMLOptionElement,\n getFallbackLabel: () => 'options',\n getListboxElement: () => this.listbox ?? null,\n getToggleButton: () => this.button ?? null,\n getComboboxInput: () => this.combobox ?? null,\n isExpanded: () => !this.listbox.hidden,\n requestShowListbox: () => void (this.listbox.hidden = false),\n requestHideListbox: () => void (this.listbox.hidden = true),\n setItemActive: (item, active) => item.classList.toggle('active', active),\n setItemSelected: (item, selected) => item.selected = selected,\n });\n\n @query('#listbox') listbox!: HTMLElement;\n @query('#button') button!: HTMLButtonElement;\n @query('#combobox') combobox!: HTMLInputElement;\n @query('#placeholder') placeholder!: HTMLOptionElement;\n\n /** List of options */\n get options(): HTMLOptionElement[] {\n return [\n ...new Set([\n this.placeholder,\n ...this.querySelectorAll('option'),\n ...this.renderRoot.querySelectorAll('option'),\n ]),\n ].filter(x => !!x);\n }\n\n get selected() {\n return this.options.filter(x => x.selected);\n }\n\n get activeOption() {\n return this.options.find(x => x.classList.contains('active'));\n }\n\n abstract render(): TemplateResult;\n\n override update(changed: PropertyValues<this>) {\n render(this.render(), this.renderRoot);\n super.update(changed);\n this.placeholder.inert = !!this.controller.selected.length;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n const root = this.renderRoot.getRootNode() as Document | ShadowRoot;\n root.adoptedStyleSheets = [...root.adoptedStyleSheets ?? [], TestCombobox.styles];\n }\n\n static async test() {\n let element: TestCombobox;\n\n const updateComplete = () => element.updateComplete;\n\n const { template } = this;\n\n if (!template) {\n throw new Error(`${this.constructor.name} must implement template`);\n }\n\n beforeEach(async function() {\n element = await fixture<TestCombobox>(template);\n });\n\n describe('Tab', function() {\n beforeEach(press('Tab'));\n beforeEach(updateComplete);\n\n it('focuses the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n\n describe('Tab', function() {\n beforeEach(press('Tab'));\n beforeEach(updateComplete);\n beforeEach(nextFrame);\n\n it('does not focus the toggle button', async function() {\n expect(await a11ySnapshot()).to.not.axContainQuery({ focused: true });\n });\n });\n\n describe('ArrowDown', function() {\n beforeEach(press('ArrowDown'));\n beforeEach(updateComplete);\n\n it('expands the listbox', async function() {\n expect(await a11ySnapshot())\n .to.axContainRole('listbox')\n .and\n .to.axContainQuery({ role: 'combobox', expanded: true });\n });\n\n it('maintains DOM focus on the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n\n it('sets active state on the placeholder', function() {\n expect(element.activeOption).to.equal(element.placeholder);\n });\n\n describe('Enter', function() {\n beforeEach(press('Enter'));\n beforeEach(updateComplete);\n\n it('maintains DOM focus on the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n\n it('selects nothing', function() {\n expect(element.selected).to.have.length(0);\n });\n });\n\n describe('ArrowDown', function() {\n beforeEach(press('ArrowDown'));\n beforeEach(updateComplete);\n\n it('maintains DOM focus on the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n\n it('sets active state on the 1st option', function() {\n expect(element.activeOption).to.have.text('1');\n });\n\n describe('Enter', function() {\n beforeEach(press('Enter'));\n beforeEach(updateComplete);\n\n it('maintains DOM focus on the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n\n it('selects the first option', function() {\n expect(element.selected).to.have.length(1);\n expect(element.selected.at(0)).to.have.text('1');\n });\n\n it('collapses the listbox', async function() {\n expect(await a11ySnapshot())\n .to.not.axContainRole('listbox')\n .and\n .to.axContainQuery({ role: 'combobox', expanded: false });\n });\n });\n });\n\n describe('Escape', function() {\n beforeEach(press('Escape'));\n beforeEach(updateComplete);\n\n it('collapses the listbox', async function() {\n expect(await a11ySnapshot())\n .to.not.axContainRole('listbox')\n .and\n .to.axContainQuery({ role: 'combobox', expanded: false });\n });\n\n it('maintains DOM focus on the combobox', async function() {\n expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox');\n });\n });\n });\n });\n };\n}\n\n@customElement('x-combobox-cross-root')\nclass XComboboxCrossRoot extends TestCombobox {\n static template = html`\n <x-combobox-cross-root>\n <option>1</option>\n <option>2</option>\n <option>3</option>\n <option>4</option>\n <option>5</option>\n <option>6</option>\n <option>7</option>\n <option>8</option>\n <option>9</option>\n <option>10</option>\n </x-combobox-cross-root>\n `;\n\n\n /** List of options */\n override get options(): HTMLOptionElement[] {\n return [\n ...new Set([\n this.placeholder,\n ...this.querySelectorAll('option'),\n ]),\n ].filter(x => !!x);\n }\n\n render() {\n return html`\n <div id=\"toggle\">\n <input id=\"combobox\">\n <button id=\"button\">Show Options</button>\n </div>\n <div id=\"listbox\">\n <option id=\"placeholder\" aria-disabled=\"true\">Select an Option</option>\n ${this.controller.renderItemsToShadowRoot()}\n <div ?hidden=${!ComboboxController.supportsCrossRootActiveDescendant}>\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n\n@customElement('x-combobox-light')\nclass XComboboxLight extends TestCombobox {\n static template = html`\n <x-combobox-light></x-combobox-light>\n `;\n\n protected createRenderRoot(): HTMLElement | DocumentFragment {\n return this;\n }\n\n render() {\n return html`\n <input id=\"combobox\">\n <button id=\"button\">Show Options</button>\n <div id=\"listbox\">\n <option id=\"placeholder\" aria-disabled=\"true\">Select an Option</option>\n <option>1</option>\n <option>2</option>\n <option>3</option>\n <option>4</option>\n <option>5</option>\n <option>6</option>\n <option>7</option>\n <option>8</option>\n <option>9</option>\n <option>10</option>\n </div>`;\n }\n}\n\n@customElement('x-combobox-shadow')\nclass XComboboxShadow extends TestCombobox {\n static template = html`\n <x-combobox-shadow></x-combobox-shadow>\n `;\n\n render() {\n return html`\n <input id=\"combobox\">\n <button id=\"button\">Show Options</button>\n <div id=\"listbox\">\n <option id=\"placeholder\" aria-disabled=\"true\">Select an Option</option>\n <option>1</option>\n <option>2</option>\n <option>3</option>\n <option>4</option>\n <option>5</option>\n <option>6</option>\n <option>7</option>\n <option>8</option>\n <option>9</option>\n <option>10</option>\n </div>`;\n }\n}\n\ndescribe('ComboboxController', function() {\n describe('Cross-root ARIA', XComboboxCrossRoot.test.bind(XComboboxCrossRoot));\n describe('Light-DOM only', XComboboxLight.test.bind(XComboboxLight));\n describe('Shadow-DOM only', XComboboxShadow.test.bind(XComboboxShadow));\n});\n"]}
@@ -1,3 +1,5 @@
1
+ var _TimestampController_instances, _a, _TimestampController_isTimestampOptionKey, _TimestampController_date, _TimestampController_options, _TimestampController_host, _TimestampController_getTimeRelative;
2
+ import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
1
3
  const defaults = {
2
4
  dateFormat: undefined,
3
5
  timeFormat: undefined,
@@ -9,100 +11,101 @@ const defaults = {
9
11
  hour12: false,
10
12
  };
11
13
  export class TimestampController {
12
- static #isTimestampOptionKey(prop) {
13
- return prop in defaults;
14
- }
15
- #date = new Date();
16
- #options = {};
17
- #host;
18
14
  get localeString() {
19
- return this.#date.toLocaleString(this.#options.locale);
15
+ return __classPrivateFieldGet(this, _TimestampController_date, "f").toLocaleString(__classPrivateFieldGet(this, _TimestampController_options, "f").locale);
20
16
  }
21
17
  get date() {
22
- return this.#date;
18
+ return __classPrivateFieldGet(this, _TimestampController_date, "f");
23
19
  }
24
20
  set date(string) {
25
- this.#date = new Date(string);
21
+ __classPrivateFieldSet(this, _TimestampController_date, new Date(string), "f");
26
22
  }
27
23
  get isoString() {
28
- return this.#date.toISOString();
24
+ return __classPrivateFieldGet(this, _TimestampController_date, "f").toISOString();
29
25
  }
30
26
  get time() {
31
- if (this.#options.relative) {
32
- return this.#getTimeRelative();
27
+ if (__classPrivateFieldGet(this, _TimestampController_options, "f").relative) {
28
+ return __classPrivateFieldGet(this, _TimestampController_instances, "m", _TimestampController_getTimeRelative).call(this);
33
29
  }
34
30
  else {
35
- let { displaySuffix, locale } = this.#options;
36
- if (this.#options.utc) {
37
- displaySuffix ||= 'UTC';
31
+ let { displaySuffix } = __classPrivateFieldGet(this, _TimestampController_options, "f");
32
+ const { locale } = __classPrivateFieldGet(this, _TimestampController_options, "f");
33
+ if (__classPrivateFieldGet(this, _TimestampController_options, "f").utc) {
34
+ displaySuffix || (displaySuffix = 'UTC');
38
35
  }
39
- const localeString = this.#date.toLocaleString(locale, this.#options.customFormat ?? {
40
- hour12: this.#options.hour12,
41
- timeStyle: this.#options.timeFormat,
42
- dateStyle: this.#options.dateFormat,
43
- ...this.#options.utc && { timeZone: 'UTC' },
36
+ const localeString = __classPrivateFieldGet(this, _TimestampController_date, "f").toLocaleString(locale, __classPrivateFieldGet(this, _TimestampController_options, "f").customFormat ?? {
37
+ hour12: __classPrivateFieldGet(this, _TimestampController_options, "f").hour12,
38
+ timeStyle: __classPrivateFieldGet(this, _TimestampController_options, "f").timeFormat,
39
+ dateStyle: __classPrivateFieldGet(this, _TimestampController_options, "f").dateFormat,
40
+ ...__classPrivateFieldGet(this, _TimestampController_options, "f").utc && { timeZone: 'UTC' },
44
41
  });
45
42
  return `${localeString} ${displaySuffix ?? ''}`.trim();
46
43
  }
47
44
  }
48
45
  constructor(host, options) {
49
- this.#host = host;
46
+ _TimestampController_instances.add(this);
47
+ _TimestampController_date.set(this, new Date());
48
+ _TimestampController_options.set(this, {});
49
+ _TimestampController_host.set(this, void 0);
50
+ __classPrivateFieldSet(this, _TimestampController_host, host, "f");
50
51
  host.addController(this);
51
- for (const [name, value] of Object.entries(this.#options)) {
52
+ for (const [name, value] of Object.entries(__classPrivateFieldGet(this, _TimestampController_options, "f"))) {
52
53
  // @ts-expect-error: seems typescript compiler isn't up to the task here
53
- this.#options[name] = options?.[name] ?? value;
54
- }
55
- }
56
- /**
57
- * Based off of Github Relative Time
58
- * https://github.com/github/time-elements/blob/master/src/relative-time.js
59
- */
60
- #getTimeRelative() {
61
- const date = this.#date;
62
- const { locale } = this.#options;
63
- const rtf = new Intl.RelativeTimeFormat(locale, { localeMatcher: 'best fit', numeric: 'auto', style: 'long' });
64
- const ms = date.getTime() - Date.now();
65
- const tense = ms > 0 ? 1 : -1;
66
- let qty = 0;
67
- let units;
68
- const s = Math.round(Math.abs(ms) / 1000);
69
- const min = Math.round(s / 60);
70
- const h = Math.round(min / 60);
71
- const d = Math.round(h / 24);
72
- const m = Math.round(d / 30);
73
- const y = Math.round(m / 12);
74
- if (m >= 12) {
75
- qty = y;
76
- units = 'year';
77
- }
78
- else if (d >= 30) {
79
- qty = m;
80
- units = 'month';
81
- }
82
- else if (h >= 24) {
83
- qty = d;
84
- units = 'day';
85
- }
86
- else if (min >= 45) {
87
- qty = h;
88
- units = 'hour';
89
- }
90
- else if (s >= 45) {
91
- qty = min;
92
- units = 'minute';
93
- }
94
- else if (s >= 10) {
95
- qty = s;
96
- units = 'second';
54
+ __classPrivateFieldGet(this, _TimestampController_options, "f")[name] = options?.[name] ?? value;
97
55
  }
98
- return typeof (units) !== 'undefined' ? rtf.format(tense * qty, units) : 'just now';
99
56
  }
100
57
  set(prop, value) {
101
- if (TimestampController.#isTimestampOptionKey(prop)) {
58
+ if (__classPrivateFieldGet(_a, _a, "m", _TimestampController_isTimestampOptionKey).call(_a, prop)) {
102
59
  // @ts-expect-error: seems typescript compiler isn't up to the task here
103
- this.#options[prop] = value;
104
- this.#host.requestUpdate();
60
+ __classPrivateFieldGet(this, _TimestampController_options, "f")[prop] = value;
61
+ __classPrivateFieldGet(this, _TimestampController_host, "f").requestUpdate();
105
62
  }
106
63
  }
107
64
  }
65
+ _a = TimestampController, _TimestampController_date = new WeakMap(), _TimestampController_options = new WeakMap(), _TimestampController_host = new WeakMap(), _TimestampController_instances = new WeakSet(), _TimestampController_isTimestampOptionKey = function _TimestampController_isTimestampOptionKey(prop) {
66
+ return prop in defaults;
67
+ }, _TimestampController_getTimeRelative = function _TimestampController_getTimeRelative() {
68
+ const date = __classPrivateFieldGet(this, _TimestampController_date, "f");
69
+ const { locale } = __classPrivateFieldGet(this, _TimestampController_options, "f");
70
+ const rtf = new Intl.RelativeTimeFormat(locale, {
71
+ localeMatcher: 'best fit',
72
+ numeric: 'auto',
73
+ style: 'long',
74
+ });
75
+ const ms = date.getTime() - Date.now();
76
+ const tense = ms > 0 ? 1 : -1;
77
+ let qty = 0;
78
+ let units;
79
+ const s = Math.round(Math.abs(ms) / 1000);
80
+ const min = Math.round(s / 60);
81
+ const h = Math.round(min / 60);
82
+ const d = Math.round(h / 24);
83
+ const m = Math.round(d / 30);
84
+ const y = Math.round(m / 12);
85
+ if (m >= 12) {
86
+ qty = y;
87
+ units = 'year';
88
+ }
89
+ else if (d >= 30) {
90
+ qty = m;
91
+ units = 'month';
92
+ }
93
+ else if (h >= 24) {
94
+ qty = d;
95
+ units = 'day';
96
+ }
97
+ else if (min >= 45) {
98
+ qty = h;
99
+ units = 'hour';
100
+ }
101
+ else if (s >= 45) {
102
+ qty = min;
103
+ units = 'minute';
104
+ }
105
+ else if (s >= 10) {
106
+ qty = s;
107
+ units = 'second';
108
+ }
109
+ return typeof (units) !== 'undefined' ? rtf.format(tense * qty, units) : 'just now';
110
+ };
108
111
  //# sourceMappingURL=timestamp-controller.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timestamp-controller.js","sourceRoot":"","sources":["timestamp-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport type DateTimeFormat = 'full' | 'long' | 'medium' | 'short';\n\nexport interface TimestampOptions {\n dateFormat?: DateTimeFormat;\n timeFormat?: DateTimeFormat;\n customFormat?: Intl.DateTimeFormatOptions;\n displaySuffix: string;\n locale: Intl.LocalesArgument;\n relative: boolean;\n utc: boolean;\n hour12: boolean;\n}\n\nconst defaults = {\n dateFormat: undefined,\n timeFormat: undefined,\n customFormat: undefined,\n displaySuffix: '',\n locale: undefined,\n relative: false,\n utc: false,\n hour12: false,\n} as const;\n\nexport class TimestampController implements ReactiveController {\n static #isTimestampOptionKey(prop: PropertyKey): prop is keyof TimestampOptions {\n return prop in defaults;\n }\n\n #date = new Date();\n\n #options: TimestampOptions = {} as TimestampOptions;\n\n #host: ReactiveControllerHost;\n\n get localeString() {\n return this.#date.toLocaleString(this.#options.locale);\n }\n\n get date() {\n return this.#date;\n }\n\n set date(string) {\n this.#date = new Date(string);\n }\n\n get isoString() {\n return this.#date.toISOString();\n }\n\n get time() {\n if (this.#options.relative) {\n return this.#getTimeRelative();\n } else {\n let { displaySuffix, locale } = this.#options;\n if (this.#options.utc) {\n displaySuffix ||= 'UTC';\n }\n const localeString = this.#date.toLocaleString(locale, this.#options.customFormat ?? {\n hour12: this.#options.hour12,\n timeStyle: this.#options.timeFormat,\n dateStyle: this.#options.dateFormat,\n ...this.#options.utc && { timeZone: 'UTC' },\n });\n\n return `${localeString} ${displaySuffix ?? ''}`.trim();\n }\n }\n\n constructor(host: ReactiveControllerHost, options?: Partial<TimestampOptions>) {\n this.#host = host;\n host.addController(this);\n for (const [name, value] of Object.entries(this.#options)) {\n // @ts-expect-error: seems typescript compiler isn't up to the task here\n this.#options[name] = options?.[name] ?? value;\n }\n }\n\n hostConnected?(): void\n\n /**\n * Based off of Github Relative Time\n * https://github.com/github/time-elements/blob/master/src/relative-time.js\n */\n #getTimeRelative() {\n const date = this.#date;\n const { locale } = this.#options;\n const rtf = new Intl.RelativeTimeFormat(locale as string, { localeMatcher: 'best fit', numeric: 'auto', style: 'long' });\n const ms: number = date.getTime() - Date.now();\n const tense = ms > 0 ? 1 : -1;\n let qty = 0;\n let units: Intl.RelativeTimeFormatUnit | undefined;\n const s = Math.round(Math.abs(ms) / 1000);\n const min = Math.round(s / 60);\n const h = Math.round(min / 60);\n const d = Math.round(h / 24);\n const m = Math.round(d / 30);\n const y = Math.round(m / 12);\n if (m >= 12) {\n qty = y;\n units = 'year';\n } else if (d >= 30) {\n qty = m;\n units = 'month';\n } else if (h >= 24) {\n qty = d;\n units = 'day';\n } else if (min >= 45) {\n qty = h;\n units = 'hour';\n } else if (s >= 45) {\n qty = min;\n units = 'minute';\n } else if (s >= 10) {\n qty = s;\n units = 'second';\n }\n\n return typeof (units) !== 'undefined' ? rtf.format(tense * qty, units) : 'just now';\n }\n\n set(prop: PropertyKey, value: unknown) {\n if (TimestampController.#isTimestampOptionKey(prop)) {\n // @ts-expect-error: seems typescript compiler isn't up to the task here\n this.#options[prop] = value;\n this.#host.requestUpdate();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"timestamp-controller.js","sourceRoot":"","sources":["timestamp-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport type DateTimeFormat = 'full' | 'long' | 'medium' | 'short';\n\nexport interface TimestampOptions {\n dateFormat?: DateTimeFormat;\n timeFormat?: DateTimeFormat;\n customFormat?: Intl.DateTimeFormatOptions;\n displaySuffix: string;\n locale: Intl.LocalesArgument;\n relative: boolean;\n utc: boolean;\n hour12: boolean;\n}\n\nconst defaults = {\n dateFormat: undefined,\n timeFormat: undefined,\n customFormat: undefined,\n displaySuffix: '',\n locale: undefined,\n relative: false,\n utc: false,\n hour12: false,\n} as const;\n\nexport class TimestampController implements ReactiveController {\n static #isTimestampOptionKey(prop: PropertyKey): prop is keyof TimestampOptions {\n return prop in defaults;\n }\n\n #date = new Date();\n\n #options: TimestampOptions = {} as TimestampOptions;\n\n #host: ReactiveControllerHost;\n\n get localeString(): string {\n return this.#date.toLocaleString(this.#options.locale);\n }\n\n get date(): Date {\n return this.#date;\n }\n\n set date(string) {\n this.#date = new Date(string);\n }\n\n get isoString(): string {\n return this.#date.toISOString();\n }\n\n get time(): string {\n if (this.#options.relative) {\n return this.#getTimeRelative();\n } else {\n let { displaySuffix } = this.#options;\n const { locale } = this.#options;\n if (this.#options.utc) {\n displaySuffix ||= 'UTC';\n }\n const localeString = this.#date.toLocaleString(locale, this.#options.customFormat ?? {\n hour12: this.#options.hour12,\n timeStyle: this.#options.timeFormat,\n dateStyle: this.#options.dateFormat,\n ...this.#options.utc && { timeZone: 'UTC' },\n });\n\n return `${localeString} ${displaySuffix ?? ''}`.trim();\n }\n }\n\n constructor(host: ReactiveControllerHost, options?: Partial<TimestampOptions>) {\n this.#host = host;\n host.addController(this);\n for (const [name, value] of Object.entries(this.#options)) {\n // @ts-expect-error: seems typescript compiler isn't up to the task here\n this.#options[name] = options?.[name] ?? value;\n }\n }\n\n hostConnected?(): void;\n\n /**\n * Based off of Github Relative Time\n * https://github.com/github/time-elements/blob/master/src/relative-time.js\n */\n #getTimeRelative() {\n const date = this.#date;\n const { locale } = this.#options;\n const rtf = new Intl.RelativeTimeFormat(locale as string, {\n localeMatcher: 'best fit',\n numeric: 'auto',\n style: 'long',\n });\n const ms: number = date.getTime() - Date.now();\n const tense = ms > 0 ? 1 : -1;\n let qty = 0;\n let units: Intl.RelativeTimeFormatUnit | undefined;\n const s = Math.round(Math.abs(ms) / 1000);\n const min = Math.round(s / 60);\n const h = Math.round(min / 60);\n const d = Math.round(h / 24);\n const m = Math.round(d / 30);\n const y = Math.round(m / 12);\n if (m >= 12) {\n qty = y;\n units = 'year';\n } else if (d >= 30) {\n qty = m;\n units = 'month';\n } else if (h >= 24) {\n qty = d;\n units = 'day';\n } else if (min >= 45) {\n qty = h;\n units = 'hour';\n } else if (s >= 45) {\n qty = min;\n units = 'minute';\n } else if (s >= 10) {\n qty = s;\n units = 'second';\n }\n\n return typeof (units) !== 'undefined' ? rtf.format(tense * qty, units) : 'just now';\n }\n\n set(prop: PropertyKey, value: unknown): void {\n if (TimestampController.#isTimestampOptionKey(prop)) {\n // @ts-expect-error: seems typescript compiler isn't up to the task here\n this.#options[prop] = value;\n this.#host.requestUpdate();\n }\n }\n}\n"]}
package/core.d.ts CHANGED
@@ -1,20 +1,7 @@
1
1
  import type { ComplexAttributeConverter } from 'lit';
2
- /** PatternFly Elements global config object */
3
- export interface PfeConfig {
4
- /** Set to false to disable client-side page load performance tracking */
5
- trackPerformance?: boolean;
6
- /** Set to false to disable various debug logs */
7
- log?: boolean;
8
- /** Set to false to disable automatically removing `unresolved` attr from body */
9
- autoReveal?: boolean;
10
- }
11
- declare const noPref: unique symbol;
12
- /**
13
- * A boolean value that indicates if the performance should be tracked.
14
- * For use in a JS file or script tag; can also be added in the constructor of a component during development.
15
- * @example trackPerformance(true);
16
- */
17
- export declare function trackPerformance(preference?: boolean | typeof noPref): boolean | undefined;
2
+ export type RequireProps<T, Ps extends keyof T> = T & {
3
+ [P in Ps]-?: T[P];
4
+ };
18
5
  /**
19
6
  * A LitElement property converter which represents a list of numbers as a comma separated string
20
7
  * @see https://lit.dev/docs/components/properties/#conversion-converter
@@ -32,10 +19,3 @@ export declare const StringListConverter: ComplexAttributeConverter<string[] | n
32
19
  export declare class ComposedEvent extends Event {
33
20
  constructor(type: string, init?: EventInit);
34
21
  }
35
- declare global {
36
- interface Window {
37
- /** Global configuration settings for PatternFly Elements */
38
- PfeConfig: PfeConfig;
39
- }
40
- }
41
- export {};
package/core.js CHANGED
@@ -1,19 +1,3 @@
1
- const noPref = Symbol();
2
- /** Retrieve an HTML metadata item */
3
- function getMeta(name) {
4
- return document.head.querySelector(`meta[name="${name}"]`)?.content;
5
- }
6
- /**
7
- * A boolean value that indicates if the performance should be tracked.
8
- * For use in a JS file or script tag; can also be added in the constructor of a component during development.
9
- * @example trackPerformance(true);
10
- */
11
- export function trackPerformance(preference = noPref) {
12
- if (preference !== noPref) {
13
- window.PfeConfig.trackPerformance = !!preference;
14
- }
15
- return window.PfeConfig.trackPerformance;
16
- }
17
1
  function makeConverter(f) {
18
2
  return {
19
3
  fromAttribute(value) {
@@ -48,29 +32,8 @@ export class ComposedEvent extends Event {
48
32
  super(type, {
49
33
  bubbles: true,
50
34
  composed: true,
51
- ...init
35
+ ...init,
52
36
  });
53
37
  }
54
38
  }
55
- const bodyNoAutoReveal = document.body.hasAttribute('no-auto-reveal');
56
- /** Global patternfly elements config */
57
- window.PfeConfig = Object.assign(window.PfeConfig ?? {}, {
58
- trackPerformance: window.PfeConfig?.trackPerformance ?? getMeta('pf-track-performance') === 'true',
59
- // if the body tag has `no-auto-reveal` attribute, reveal immediately
60
- // if `<meta name="pf-auto-reveal">` exists, and it's `content` is 'true',
61
- // then auto-reveal the body
62
- autoReveal: window.PfeConfig?.autoReveal ?? (bodyNoAutoReveal ? !bodyNoAutoReveal
63
- : getMeta('pf-auto-reveal') === 'true'),
64
- get log() {
65
- return !!localStorage.pfeLog;
66
- },
67
- set log(v) {
68
- if (v) {
69
- localStorage.setItem('pfeLog', `${true}`);
70
- }
71
- else {
72
- localStorage.removeItem('pfeLog');
73
- }
74
- },
75
- });
76
39
  //# sourceMappingURL=core.js.map
package/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["core.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,qCAAqC;AACrC,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAkB,cAAc,IAAI,IAAI,CAAC,EAAE,OAAO,CAAC;AACvF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,aAAsC,MAAM;IAC3E,IAAI,UAAU,KAAK,MAAM,EAAE;QACzB,MAAM,CAAC,SAAS,CAAC,gBAAgB,GAAG,CAAC,CAAC,UAAU,CAAC;KAClD;IACD,OAAO,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAI,CAAmC;IAC3D,OAAO;QACL,aAAa,CAAC,KAAa;YACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC7B,OAAO,IAAI,CAAC;aACb;iBAAM;gBACL,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aAChC;QACH,CAAC;QACD,WAAW,CAAC,KAAU;YACpB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAE/B;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,IAAY,EAAE,IAAgB;QACxC,KAAK,CAAC,IAAI,EAAE;YACV,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,GAAG,IAAI;SACR,CAAC,CAAC;IACL,CAAC;CACF;AAWD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAEtE,wCAAwC;AACxC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE;IACvD,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,gBAAgB,IAAI,OAAO,CAAC,sBAAsB,CAAC,KAAK,MAAM;IAClG,qEAAqE;IACrE,0EAA0E;IAC1E,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,IAAI,CACxC,gBAAgB,CAAC,CAAC,CAAC,CAAC,gBAAgB;QACtC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,MAAM,CACvC;IACD,IAAI,GAAG;QACL,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;IAC/B,CAAC;IACD,IAAI,GAAG,CAAC,CAAU;QAChB,IAAI,CAAC,EAAE;YACL,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;SAC3C;aAAM;YACL,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;SACnC;IACH,CAAC;CACF,CAAC,CAAC","sourcesContent":["import type { ComplexAttributeConverter } from 'lit';\n\n/** PatternFly Elements global config object */\nexport interface PfeConfig {\n /** Set to false to disable client-side page load performance tracking */\n trackPerformance?: boolean;\n /** Set to false to disable various debug logs */\n log?: boolean;\n /** Set to false to disable automatically removing `unresolved` attr from body */\n autoReveal?: boolean;\n}\n\nconst noPref = Symbol();\n\n/** Retrieve an HTML metadata item */\nfunction getMeta(name: string): string | undefined {\n return document.head.querySelector<HTMLMetaElement>(`meta[name=\"${name}\"]`)?.content;\n}\n\n/**\n * A boolean value that indicates if the performance should be tracked.\n * For use in a JS file or script tag; can also be added in the constructor of a component during development.\n * @example trackPerformance(true);\n */\nexport function trackPerformance(preference: boolean | typeof noPref = noPref) {\n if (preference !== noPref) {\n window.PfeConfig.trackPerformance = !!preference;\n }\n return window.PfeConfig.trackPerformance;\n}\n\nfunction makeConverter<T>(f: (x: string, type?: unknown) => T): ComplexAttributeConverter<null | T[]> {\n return {\n fromAttribute(value: string) {\n if (typeof value !== 'string') {\n return null;\n } else {\n return value.split(',').map(f);\n }\n },\n toAttribute(value: T[]) {\n return value.join(',');\n },\n };\n}\n\n/**\n * A LitElement property converter which represents a list of numbers as a comma separated string\n * @see https://lit.dev/docs/components/properties/#conversion-converter\n */\nexport const NumberListConverter =\n makeConverter(x => parseInt(x?.trim(), 10));\n\n/**\n * A LitElement property converter which represents a list of strings as a comma separated string\n * @see https://lit.dev/docs/components/properties/#conversion-converter\n */\nexport const StringListConverter =\n makeConverter(x => x.trim());\n\n/**\n * A composed, bubbling event for UI interactions\n * e.g. when an accordion panel opens.\n */\nexport class ComposedEvent extends Event {\n constructor(type: string, init?: EventInit) {\n super(type, {\n bubbles: true,\n composed: true,\n ...init\n });\n }\n}\n\n// 👇 SIDE EFFECTS 👇\n\ndeclare global {\n interface Window {\n /** Global configuration settings for PatternFly Elements */\n PfeConfig: PfeConfig;\n }\n}\n\nconst bodyNoAutoReveal = document.body.hasAttribute('no-auto-reveal');\n\n/** Global patternfly elements config */\nwindow.PfeConfig = Object.assign(window.PfeConfig ?? {}, {\n trackPerformance: window.PfeConfig?.trackPerformance ?? getMeta('pf-track-performance') === 'true',\n // if the body tag has `no-auto-reveal` attribute, reveal immediately\n // if `<meta name=\"pf-auto-reveal\">` exists, and it's `content` is 'true',\n // then auto-reveal the body\n autoReveal: window.PfeConfig?.autoReveal ?? (\n bodyNoAutoReveal ? !bodyNoAutoReveal\n : getMeta('pf-auto-reveal') === 'true'\n ),\n get log() {\n return !!localStorage.pfeLog;\n },\n set log(v: boolean) {\n if (v) {\n localStorage.setItem('pfeLog', `${true}`);\n } else {\n localStorage.removeItem('pfeLog');\n }\n },\n});\n"]}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["core.ts"],"names":[],"mappings":"AAMA,SAAS,aAAa,CACpB,CAAmC;IAEnC,OAAO;QACL,aAAa,CAAC,KAAa;YACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC;YACd,CAAC;iBAAM,CAAC;gBACN,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QACD,WAAW,CAAC,KAAU;YACpB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAE/B;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,IAAY,EAAE,IAAgB;QACxC,KAAK,CAAC,IAAI,EAAE;YACV,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,GAAG,IAAI;SACR,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import type { ComplexAttributeConverter } from 'lit';\n\nexport type RequireProps<T, Ps extends keyof T> = T & {\n [P in Ps]-?: T[P];\n};\n\nfunction makeConverter<T>(\n f: (x: string, type?: unknown) => T,\n): ComplexAttributeConverter<null | T[]> {\n return {\n fromAttribute(value: string) {\n if (typeof value !== 'string') {\n return null;\n } else {\n return value.split(',').map(f);\n }\n },\n toAttribute(value: T[]) {\n return value.join(',');\n },\n };\n}\n\n/**\n * A LitElement property converter which represents a list of numbers as a comma separated string\n * @see https://lit.dev/docs/components/properties/#conversion-converter\n */\nexport const NumberListConverter: ComplexAttributeConverter<number[] | null, unknown> =\n makeConverter(x => parseInt(x?.trim(), 10));\n\n/**\n * A LitElement property converter which represents a list of strings as a comma separated string\n * @see https://lit.dev/docs/components/properties/#conversion-converter\n */\nexport const StringListConverter: ComplexAttributeConverter<string[] | null, unknown> =\n makeConverter(x => x.trim());\n\n/**\n * A composed, bubbling event for UI interactions\n * e.g. when an accordion panel opens.\n */\nexport class ComposedEvent extends Event {\n constructor(type: string, init?: EventInit) {\n super(type, {\n bubbles: true,\n composed: true,\n ...init,\n });\n }\n}\n\n"]}