@openelement/ui 0.41.0-alpha.1

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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -0
  3. package/package.json +142 -0
  4. package/src/daisy-classes.d.ts +7 -0
  5. package/src/daisy-classes.js +770 -0
  6. package/src/index.d.ts +57 -0
  7. package/src/index.js +62 -0
  8. package/src/manifest.d.ts +8 -0
  9. package/src/manifest.js +255 -0
  10. package/src/open-badge.d.ts +15 -0
  11. package/src/open-badge.js +88 -0
  12. package/src/open-brand-mark.d.ts +14 -0
  13. package/src/open-brand-mark.js +107 -0
  14. package/src/open-button.d.ts +38 -0
  15. package/src/open-button.js +219 -0
  16. package/src/open-callout.d.ts +26 -0
  17. package/src/open-callout.js +99 -0
  18. package/src/open-card.d.ts +33 -0
  19. package/src/open-card.js +107 -0
  20. package/src/open-code-block.d.ts +44 -0
  21. package/src/open-code-block.js +267 -0
  22. package/src/open-dialog.d.ts +47 -0
  23. package/src/open-dialog.js +235 -0
  24. package/src/open-dropdown.d.ts +25 -0
  25. package/src/open-dropdown.js +45 -0
  26. package/src/open-hero-ping.d.ts +27 -0
  27. package/src/open-hero-ping.js +136 -0
  28. package/src/open-input.d.ts +51 -0
  29. package/src/open-input.js +233 -0
  30. package/src/open-lab-panel.d.ts +16 -0
  31. package/src/open-lab-panel.js +151 -0
  32. package/src/open-lab-stage.d.ts +15 -0
  33. package/src/open-lab-stage.js +622 -0
  34. package/src/open-layout.d.ts +111 -0
  35. package/src/open-layout.js +1377 -0
  36. package/src/open-modal.d.ts +25 -0
  37. package/src/open-modal.js +48 -0
  38. package/src/open-props-tokens.d.ts +7 -0
  39. package/src/open-props-tokens.js +474 -0
  40. package/src/open-standards-visual.d.ts +20 -0
  41. package/src/open-standards-visual.js +425 -0
  42. package/src/open-step-card.d.ts +34 -0
  43. package/src/open-step-card.js +117 -0
  44. package/src/open-tabs.d.ts +27 -0
  45. package/src/open-tabs.js +56 -0
  46. package/src/open-theme-toggle.d.ts +38 -0
  47. package/src/open-theme-toggle.js +223 -0
@@ -0,0 +1,56 @@
1
+ /** @jsxImportSource @openelement/core */ /**
2
+ * @openelement/ui - open-tabs
3
+ *
4
+ * DaisyUI-style tabs using DsdElement + Signals.
5
+ * Reads light DOM children with `slot="tab"` and `slot="panel"`
6
+ * to render tab buttons and panel content.
7
+ *
8
+ * Usage:
9
+ * ```html
10
+ * <open-tabs>
11
+ * <span slot="tab">Tab 1</span>
12
+ * <span slot="tab">Tab 2</span>
13
+ * <div slot="panel">Panel 1 content</div>
14
+ * <div slot="panel">Panel 2 content</div>
15
+ * </open-tabs>
16
+ * ```
17
+ *
18
+ * @slot tab - Tab button labels (multiple)
19
+ * @slot panel - Tab panel content (multiple, one per tab)
20
+ */ import { OpenElement } from '@openelement/element';
21
+ import { signal } from '@openelement/signal';
22
+ import { daisyClassSheet } from './daisy-classes.js';
23
+ export const tagName = 'open-tabs';
24
+ export class OpenTabs extends OpenElement {
25
+ static styles = [
26
+ daisyClassSheet
27
+ ];
28
+ #active = signal(0);
29
+ #select(idx) {
30
+ this.#active.value = idx;
31
+ this.update();
32
+ }
33
+ render() {
34
+ const tabs = this.querySelectorAll('[slot="tab"]');
35
+ const panels = this.querySelectorAll('[slot="panel"]');
36
+ const active = this.#active.value;
37
+ return <div>
38
+ <div class='tabs'>
39
+ {Array.from(tabs).map((tab, i)=><button type='button' class={`tab ${i === active ? 'tab-active' : ''}`} onClick={()=>this.#select(i)}>
40
+ {tab.textContent}
41
+ </button>)}
42
+ </div>
43
+ <div>
44
+ {Array.from(panels).map((panel, i)=><div style={{
45
+ display: i === active ? 'block' : 'none'
46
+ }}>{panel.innerHTML}</div>)}
47
+ </div>
48
+ </div>;
49
+ }
50
+ }
51
+ export default OpenTabs;
52
+ // Guard: idempotent across SSR paths
53
+ if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {
54
+ customElements.define(tagName, OpenTabs);
55
+ }
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy91aS9zcmMvb3Blbi10YWJzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQGpzeEltcG9ydFNvdXJjZSBAb3BlbmVsZW1lbnQvY29yZSAqL1xuLyoqXG4gKiBAb3BlbmVsZW1lbnQvdWkgLSBvcGVuLXRhYnNcbiAqXG4gKiBEYWlzeVVJLXN0eWxlIHRhYnMgdXNpbmcgRHNkRWxlbWVudCArIFNpZ25hbHMuXG4gKiBSZWFkcyBsaWdodCBET00gY2hpbGRyZW4gd2l0aCBgc2xvdD1cInRhYlwiYCBhbmQgYHNsb3Q9XCJwYW5lbFwiYFxuICogdG8gcmVuZGVyIHRhYiBidXR0b25zIGFuZCBwYW5lbCBjb250ZW50LlxuICpcbiAqIFVzYWdlOlxuICogYGBgaHRtbFxuICogPG9wZW4tdGFicz5cbiAqICAgPHNwYW4gc2xvdD1cInRhYlwiPlRhYiAxPC9zcGFuPlxuICogICA8c3BhbiBzbG90PVwidGFiXCI+VGFiIDI8L3NwYW4+XG4gKiAgIDxkaXYgc2xvdD1cInBhbmVsXCI+UGFuZWwgMSBjb250ZW50PC9kaXY+XG4gKiAgIDxkaXYgc2xvdD1cInBhbmVsXCI+UGFuZWwgMiBjb250ZW50PC9kaXY+XG4gKiA8L29wZW4tdGFicz5cbiAqIGBgYFxuICpcbiAqIEBzbG90IHRhYiAtIFRhYiBidXR0b24gbGFiZWxzIChtdWx0aXBsZSlcbiAqIEBzbG90IHBhbmVsIC0gVGFiIHBhbmVsIGNvbnRlbnQgKG11bHRpcGxlLCBvbmUgcGVyIHRhYilcbiAqL1xuXG5pbXBvcnQgeyBPcGVuRWxlbWVudCwgdHlwZSBWTm9kZSB9IGZyb20gJ0BvcGVuZWxlbWVudC9lbGVtZW50JztcbmltcG9ydCB7IHNpZ25hbCB9IGZyb20gJ0BvcGVuZWxlbWVudC9zaWduYWwnO1xuaW1wb3J0IHsgZGFpc3lDbGFzc1NoZWV0IH0gZnJvbSAnLi9kYWlzeS1jbGFzc2VzLmpzJztcblxuZXhwb3J0IGNvbnN0IHRhZ05hbWUgPSAnb3Blbi10YWJzJztcblxuZXhwb3J0IGNsYXNzIE9wZW5UYWJzIGV4dGVuZHMgT3BlbkVsZW1lbnQge1xuICBzdGF0aWMgb3ZlcnJpZGUgc3R5bGVzID0gW2RhaXN5Q2xhc3NTaGVldF07XG4gICNhY3RpdmUgPSBzaWduYWwoMCk7XG5cbiAgI3NlbGVjdChpZHg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuI2FjdGl2ZS52YWx1ZSA9IGlkeDtcbiAgICB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgb3ZlcnJpZGUgcmVuZGVyKCk6IFZOb2RlIHtcbiAgICBjb25zdCB0YWJzID0gdGhpcy5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50PignW3Nsb3Q9XCJ0YWJcIl0nKTtcbiAgICBjb25zdCBwYW5lbHMgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCdbc2xvdD1cInBhbmVsXCJdJyk7XG4gICAgY29uc3QgYWN0aXZlID0gdGhpcy4jYWN0aXZlLnZhbHVlO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9J3RhYnMnPlxuICAgICAgICAgIHtBcnJheS5mcm9tKHRhYnMpLm1hcCgodGFiLCBpKSA9PiAoXG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIHR5cGU9J2J1dHRvbidcbiAgICAgICAgICAgICAgY2xhc3M9e2B0YWIgJHtpID09PSBhY3RpdmUgPyAndGFiLWFjdGl2ZScgOiAnJ31gfVxuICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiB0aGlzLiNzZWxlY3QoaSl9XG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt0YWIudGV4dENvbnRlbnR9XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICApKX1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXY+XG4gICAgICAgICAge0FycmF5LmZyb20ocGFuZWxzKS5tYXAoKHBhbmVsLCBpKSA9PiAoXG4gICAgICAgICAgICA8ZGl2IHN0eWxlPXt7IGRpc3BsYXk6IGkgPT09IGFjdGl2ZSA/ICdibG9jaycgOiAnbm9uZScgfX0+e3BhbmVsLmlubmVySFRNTH08L2Rpdj5cbiAgICAgICAgICApKX1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE9wZW5UYWJzO1xuXG4vLyBHdWFyZDogaWRlbXBvdGVudCBhY3Jvc3MgU1NSIHBhdGhzXG5pZiAodHlwZW9mIGN1c3RvbUVsZW1lbnRzICE9PSAndW5kZWZpbmVkJyAmJiAhY3VzdG9tRWxlbWVudHMuZ2V0KHRhZ05hbWUpKSB7XG4gIGN1c3RvbUVsZW1lbnRzLmRlZmluZSh0YWdOYW1lLCBPcGVuVGFicyk7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdUNBQXVDLEdBQ3ZDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBbUJDLEdBRUQsU0FBUyxXQUFXLFFBQW9CLHVCQUF1QjtBQUMvRCxTQUFTLE1BQU0sUUFBUSxzQkFBc0I7QUFDN0MsU0FBUyxlQUFlLFFBQVEscUJBQXFCO0FBRXJELE9BQU8sTUFBTSxVQUFVLFlBQVk7QUFFbkMsT0FBTyxNQUFNLGlCQUFpQjtFQUM1QixPQUFnQixTQUFTO0lBQUM7R0FBZ0IsQ0FBQztFQUMzQyxDQUFBLE1BQU8sR0FBRyxPQUFPLEdBQUc7RUFFcEIsQ0FBQSxNQUFPLENBQUMsR0FBVztJQUNqQixJQUFJLENBQUMsQ0FBQSxNQUFPLENBQUMsS0FBSyxHQUFHO0lBQ3JCLElBQUksQ0FBQyxNQUFNO0VBQ2I7RUFFUyxTQUFnQjtJQUN2QixNQUFNLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFjO0lBQ2hELE1BQU0sU0FBUyxJQUFJLENBQUMsZ0JBQWdCLENBQWM7SUFDbEQsTUFBTSxTQUFTLElBQUksQ0FBQyxDQUFBLE1BQU8sQ0FBQyxLQUFLO0lBRWpDLFFBQ0csSUFBSTtRQUNILENBQUMsSUFBSSxNQUFNLE9BQU87VUFDaEIsQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEtBQUssS0FDekIsT0FDQyxLQUFLLFNBQ0wsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLFNBQVMsZUFBZSxJQUFJLEVBQ2hELFNBQVMsSUFBTSxJQUFJLENBQUMsQ0FBQSxNQUFPLENBQUMsSUFDN0I7Y0FDQyxDQUFDLElBQUksV0FBVyxDQUFDO1lBQ25CLEVBQUUsU0FDRDtRQUNMLEVBQUUsSUFBSTtRQUNOLENBQUMsSUFBSTtVQUNILENBQUMsTUFBTSxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxPQUFPLEtBQzdCLElBQUksT0FBTztRQUFFLFNBQVMsTUFBTSxTQUFTLFVBQVU7TUFBTyxJQUFJLE1BQU0sU0FBUyxHQUFHLE1BQzVFO1FBQ0wsRUFBRSxJQUFJO01BQ1IsRUFBRTtFQUVOO0FBQ0Y7QUFFQSxlQUFlLFNBQVM7QUFFeEIscUNBQXFDO0FBQ3JDLElBQUksT0FBTyxtQkFBbUIsZUFBZSxDQUFDLGVBQWUsR0FBRyxDQUFDLFVBQVU7RUFDekUsZUFBZSxNQUFNLENBQUMsU0FBUztBQUNqQyJ9
@@ -0,0 +1,38 @@
1
+ /** @jsxImportSource @openelement/core */ /**
2
+ * @openelement/ui - open-theme-toggle
3
+ *
4
+ * Theme toggle Reactive DSD component for Dark/Light mode switching.
5
+ * Swiss International Style: Pure B&W, minimal.
6
+ *
7
+ * v0.21.0: Uses DsdElement + html templates + Signals.
8
+ * v0.24.1: Migrated from html`` template to JSX (ADR-0057).
9
+ *
10
+ * @csspart toggle -The button element
11
+ * @csspart icon-sun -The sun SVG icon
12
+ * @csspart icon-moon -The moon SVG icon
13
+ *
14
+ * Usage:
15
+ * ```html
16
+ * <open-theme-toggle theme="light"></open-theme-toggle>
17
+ * ```
18
+ */ import { OpenElement } from '@openelement/element';
19
+ import { type StyleSheetLike } from '@openelement/core/style-sheet';
20
+ export declare const tagName: 'open-theme-toggle';
21
+ declare const sheet: StyleSheetLike;
22
+ export declare class OpenThemeToggle extends OpenElement {
23
+ static override styles: [];
24
+ static delegatesFocus: boolean;
25
+ static override observedAttributes: [string];
26
+ private _theme: any;
27
+ private _initDone: any;
28
+ override connectedCallback(): void;
29
+ private _initTheme: any;
30
+ private _persistTheme: any;
31
+ protected override onDsdHydrated(): void;
32
+ protected override onCsrRendered(): void;
33
+ override render(): ReturnType<typeof OpenElement.prototype.render>;
34
+ private _handleToggle: any;
35
+ private _dispatchThemeChange: any;
36
+ override attributeChangedCallback(name: string, old: string | null, val: string | null): void;
37
+ }
38
+ export default OpenThemeToggle;
@@ -0,0 +1,223 @@
1
+ /** @jsxImportSource @openelement/core */ /**
2
+ * @openelement/ui - open-theme-toggle
3
+ *
4
+ * Theme toggle Reactive DSD component for Dark/Light mode switching.
5
+ * Swiss International Style: Pure B&W, minimal.
6
+ *
7
+ * v0.21.0: Uses DsdElement + html templates + Signals.
8
+ * v0.24.1: Migrated from html`` template to JSX (ADR-0057).
9
+ *
10
+ * @csspart toggle -The button element
11
+ * @csspart icon-sun -The sun SVG icon
12
+ * @csspart icon-moon -The moon SVG icon
13
+ *
14
+ * Usage:
15
+ * ```html
16
+ * <open-theme-toggle theme="light"></open-theme-toggle>
17
+ * ```
18
+ */ import { OpenElement } from '@openelement/element';
19
+ import { StyleSheet } from '@openelement/core/style-sheet';
20
+ import { signal } from '@openelement/signal';
21
+ export const tagName = 'open-theme-toggle';
22
+ const sheet = new StyleSheet();
23
+ sheet.replaceSync(`
24
+ :host {
25
+ display: inline-block;
26
+ }
27
+
28
+ .theme-toggle {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ width: 38px; height: 38px; padding: 0;
33
+ border: var(--border-size-1) solid color-mix(in srgb, var(--border) 72%, var(--brand));
34
+ border-radius: var(--radius-round);
35
+ background: color-mix(in srgb, var(--bg-elevated) 76%, transparent);
36
+ color: var(--text-muted);
37
+ box-shadow: inset 0 1px 0 color-mix(in srgb, var(--gray-0) 70%, transparent);
38
+ cursor: pointer;
39
+ transition: all var(--ease-2) var(--duration-2);
40
+ }
41
+ .theme-toggle:hover {
42
+ color: var(--text-primary);
43
+ border-color: var(--brand-light);
44
+ background: color-mix(in srgb, var(--brand-pale) 42%, var(--bg-elevated));
45
+ }
46
+
47
+ .theme-toggle svg {
48
+ width: 16px;
49
+ height: 16px;
50
+ }
51
+
52
+ .theme-toggle .icon-sun {
53
+ display: block;
54
+ }
55
+
56
+ .theme-toggle .icon-moon {
57
+ display: none;
58
+ }
59
+
60
+ .theme-toggle[data-theme="light"] .icon-sun {
61
+ display: none;
62
+ }
63
+
64
+ .theme-toggle[data-theme="light"] .icon-moon {
65
+ display: block;
66
+ }
67
+ `);
68
+ export class OpenThemeToggle extends OpenElement {
69
+ // ponytail: Safari does not recompute adoptedStyleSheets when
70
+ // :host([data-theme]) changes. The token sheets (openPropsTokenSheet,
71
+ // daisyClassSheet) are already injected as page-level <style> by
72
+ // vite.config.ts — CSS custom properties cascade from :root naturally.
73
+ // Only adopt the component-specific sheet.
74
+ static styles = [
75
+ sheet
76
+ ];
77
+ static delegatesFocus = true;
78
+ static observedAttributes = [
79
+ 'theme'
80
+ ];
81
+ _theme = signal('dark');
82
+ _initDone = false;
83
+ connectedCallback() {
84
+ super.connectedCallback();
85
+ requestAnimationFrame(()=>this._initTheme());
86
+ }
87
+ /**
88
+ * v0.23.0: Theme initialization lives in _initTheme(), called from
89
+ * both onDsdHydrated() and onCsrRendered() so that the priority
90
+ * chain works regardless of hydration path.
91
+ *
92
+ * Priority: theme attribute > document.documentElement.dataset.theme
93
+ * > localStorage > prefers-color-scheme > default 'dark'.
94
+ */ _initTheme() {
95
+ if (this._initDone) return;
96
+ this._initDone = true;
97
+ const themeAttr = this.getAttribute('theme');
98
+ if (themeAttr === 'light') {
99
+ this._theme.value = 'light';
100
+ } else if (themeAttr === 'dark') {
101
+ this._theme.value = 'dark';
102
+ } else {
103
+ const docTheme = document.documentElement?.dataset?.theme;
104
+ if (docTheme === 'light') {
105
+ this._theme.value = 'light';
106
+ } else if (docTheme === 'dark') {
107
+ this._theme.value = 'dark';
108
+ } else {
109
+ let resolved = false;
110
+ try {
111
+ const saved = localStorage.getItem('open-theme');
112
+ if (saved === 'light') {
113
+ this._theme.value = 'light';
114
+ resolved = true;
115
+ } else if (saved === 'dark') {
116
+ this._theme.value = 'dark';
117
+ resolved = true;
118
+ }
119
+ } catch {}
120
+ if (!resolved && globalThis.matchMedia) {
121
+ this._theme.value = globalThis.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
122
+ }
123
+ }
124
+ }
125
+ this.setAttribute('data-theme', this._theme.value);
126
+ document.documentElement.setAttribute('data-theme', this._theme.value);
127
+ if (document.documentElement.style) {
128
+ document.documentElement.style.colorScheme = this._theme.value;
129
+ }
130
+ // Propagate to parent open-layout
131
+ try {
132
+ const root = this.getRootNode();
133
+ if (root instanceof ShadowRoot && root.host) {
134
+ root.host.setAttribute('data-theme', this._theme.value);
135
+ }
136
+ } catch {}
137
+ this._dispatchThemeChange(this._theme.value);
138
+ this._persistTheme(this._theme.value);
139
+ }
140
+ _persistTheme(theme) {
141
+ try {
142
+ localStorage.setItem('open-theme', theme);
143
+ } catch {}
144
+ }
145
+ onDsdHydrated() {
146
+ super.onDsdHydrated();
147
+ requestAnimationFrame(()=>this._initTheme());
148
+ }
149
+ onCsrRendered() {
150
+ super.onCsrRendered();
151
+ }
152
+ render() {
153
+ // Zero signal.value reads in render (ADR-0062).
154
+ // effect binding that updates the attribute when theme changes.
155
+ // CSS selectors ([data-theme="light"]) handle icon visibility.
156
+ return <button type='button' className='theme-toggle' part='toggle' data-theme={this._theme} aria-label='Toggle theme' onClick={()=>this._handleToggle()}>
157
+ <svg className='icon-sun' part='icon-sun' viewBox='0 0 16 16' fill='none' stroke='currentColor' stroke-width='1.2' stroke-linecap='round'>
158
+ <circle cx='8' cy='8' r='3'/>
159
+ <line x1='8' y1='1' x2='8' y2='3'/>
160
+ <line x1='8' y1='13' x2='8' y2='15'/>
161
+ <line x1='1' y1='8' x2='3' y2='8'/>
162
+ <line x1='13' y1='8' x2='15' y2='8'/>
163
+ <line x1='3.05' y1='3.05' x2='4.46' y2='4.46'/>
164
+ <line x1='11.54' y1='11.54' x2='12.95' y2='12.95'/>
165
+ <line x1='3.05' y1='12.95' x2='4.46' y2='11.54'/>
166
+ <line x1='11.54' y1='4.46' x2='12.95' y2='3.05'/>
167
+ </svg>
168
+ <svg className='icon-moon' part='icon-moon' viewBox='0 0 16 16' fill='none' stroke='currentColor' stroke-width='1.2' stroke-linecap='round'>
169
+ <path d='M13.5 9.14A5.5 5.5 0 0 1 6.86 2.5 5.5 5.5 0 1 0 13.5 9.14Z'/>
170
+ </svg>
171
+ </button>;
172
+ }
173
+ _handleToggle() {
174
+ const theme = this._theme.value === 'light' ? 'dark' : 'light';
175
+ this._theme.value = theme;
176
+ document.documentElement.setAttribute('data-theme', theme);
177
+ if (document.documentElement.style) {
178
+ document.documentElement.style.colorScheme = theme;
179
+ }
180
+ // Propagate data-theme to parent <open-layout> so :host([data-theme="dark"]) matches
181
+ try {
182
+ const root = this.getRootNode();
183
+ if (root instanceof ShadowRoot && root.host) {
184
+ root.host.setAttribute('data-theme', theme);
185
+ }
186
+ } catch (e) {
187
+ console.debug('[open-theme-toggle] getRootNode unavailable:', e);
188
+ }
189
+ this._dispatchThemeChange(theme);
190
+ try {
191
+ localStorage.setItem('open-theme', theme);
192
+ } catch (e) {
193
+ console.debug('[open-theme-toggle] localStorage.setItem unavailable:', e);
194
+ }
195
+ // data-theme attribute is managed by signal prop binding (data-theme={this._theme})
196
+ }
197
+ _dispatchThemeChange(theme) {
198
+ try {
199
+ if (typeof CustomEvent !== 'undefined' && typeof globalThis.dispatchEvent === 'function') {
200
+ globalThis.dispatchEvent(new CustomEvent('open:theme-change', {
201
+ detail: {
202
+ theme
203
+ }
204
+ }));
205
+ }
206
+ } catch (e) {
207
+ console.debug('[open-theme-toggle] theme event dispatch unavailable:', e);
208
+ }
209
+ }
210
+ attributeChangedCallback(name, old, val) {
211
+ if (old === val) return;
212
+ if (name === 'theme' && val) {
213
+ this._theme.value = val === 'light' ? 'light' : 'dark';
214
+ this.setAttribute('data-theme', this._theme.value);
215
+ }
216
+ }
217
+ }
218
+ export default OpenThemeToggle;
219
+ // Guard: idempotent across SSR paths
220
+ if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {
221
+ customElements.define(tagName, OpenThemeToggle);
222
+ }
223
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy91aS9zcmMvb3Blbi10aGVtZS10b2dnbGUudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4SW1wb3J0U291cmNlIEBvcGVuZWxlbWVudC9jb3JlICovXG4vKipcbiAqIEBvcGVuZWxlbWVudC91aSAtIG9wZW4tdGhlbWUtdG9nZ2xlXG4gKlxuICogVGhlbWUgdG9nZ2xlIFJlYWN0aXZlIERTRCBjb21wb25lbnQgZm9yIERhcmsvTGlnaHQgbW9kZSBzd2l0Y2hpbmcuXG4gKiBTd2lzcyBJbnRlcm5hdGlvbmFsIFN0eWxlOiBQdXJlIEImVywgbWluaW1hbC5cbiAqXG4gKiB2MC4yMS4wOiBVc2VzIERzZEVsZW1lbnQgKyBodG1sIHRlbXBsYXRlcyArIFNpZ25hbHMuXG4gKiB2MC4yNC4xOiBNaWdyYXRlZCBmcm9tIGh0bWxgYCB0ZW1wbGF0ZSB0byBKU1ggKEFEUi0wMDU3KS5cbiAqXG4gKiBAY3NzcGFydCB0b2dnbGUgLVRoZSBidXR0b24gZWxlbWVudFxuICogQGNzc3BhcnQgaWNvbi1zdW4gLVRoZSBzdW4gU1ZHIGljb25cbiAqIEBjc3NwYXJ0IGljb24tbW9vbiAtVGhlIG1vb24gU1ZHIGljb25cbiAqXG4gKiBVc2FnZTpcbiAqIGBgYGh0bWxcbiAqIDxvcGVuLXRoZW1lLXRvZ2dsZSB0aGVtZT1cImxpZ2h0XCI+PC9vcGVuLXRoZW1lLXRvZ2dsZT5cbiAqIGBgYFxuICovXG5cbmltcG9ydCB7IE9wZW5FbGVtZW50IH0gZnJvbSAnQG9wZW5lbGVtZW50L2VsZW1lbnQnO1xuaW1wb3J0IHsgU3R5bGVTaGVldCwgdHlwZSBTdHlsZVNoZWV0TGlrZSB9IGZyb20gJ0BvcGVuZWxlbWVudC9jb3JlL3N0eWxlLXNoZWV0JztcbmltcG9ydCB7IHNpZ25hbCB9IGZyb20gJ0BvcGVuZWxlbWVudC9zaWduYWwnO1xuZXhwb3J0IGNvbnN0IHRhZ05hbWUgPSAnb3Blbi10aGVtZS10b2dnbGUnO1xuXG5jb25zdCBzaGVldDogU3R5bGVTaGVldExpa2UgPSBuZXcgU3R5bGVTaGVldCgpO1xuc2hlZXQucmVwbGFjZVN5bmMoYFxuICA6aG9zdCB7XG4gICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICB9XG5cbiAgLnRoZW1lLXRvZ2dsZSB7XG4gICAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICB3aWR0aDogMzhweDsgaGVpZ2h0OiAzOHB4OyBwYWRkaW5nOiAwO1xuICAgIGJvcmRlcjogdmFyKC0tYm9yZGVyLXNpemUtMSkgc29saWQgY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWJvcmRlcikgNzIlLCB2YXIoLS1icmFuZCkpO1xuICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLXJhZGl1cy1yb3VuZCk7XG4gICAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWJnLWVsZXZhdGVkKSA3NiUsIHRyYW5zcGFyZW50KTtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7XG4gICAgYm94LXNoYWRvdzogaW5zZXQgMCAxcHggMCBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tZ3JheS0wKSA3MCUsIHRyYW5zcGFyZW50KTtcbiAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgdHJhbnNpdGlvbjogYWxsIHZhcigtLWVhc2UtMikgdmFyKC0tZHVyYXRpb24tMik7XG4gIH1cbiAgLnRoZW1lLXRvZ2dsZTpob3ZlciB7XG4gICAgY29sb3I6IHZhcigtLXRleHQtcHJpbWFyeSk7XG4gICAgYm9yZGVyLWNvbG9yOiB2YXIoLS1icmFuZC1saWdodCk7XG4gICAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWJyYW5kLXBhbGUpIDQyJSwgdmFyKC0tYmctZWxldmF0ZWQpKTtcbiAgfVxuXG4gIC50aGVtZS10b2dnbGUgc3ZnIHtcbiAgICB3aWR0aDogMTZweDtcbiAgICBoZWlnaHQ6IDE2cHg7XG4gIH1cblxuICAudGhlbWUtdG9nZ2xlIC5pY29uLXN1biB7XG4gICAgZGlzcGxheTogYmxvY2s7XG4gIH1cblxuICAudGhlbWUtdG9nZ2xlIC5pY29uLW1vb24ge1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gIH1cblxuICAudGhlbWUtdG9nZ2xlW2RhdGEtdGhlbWU9XCJsaWdodFwiXSAuaWNvbi1zdW4ge1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gIH1cblxuICAudGhlbWUtdG9nZ2xlW2RhdGEtdGhlbWU9XCJsaWdodFwiXSAuaWNvbi1tb29uIHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgfVxuYCk7XG5cbmV4cG9ydCBjbGFzcyBPcGVuVGhlbWVUb2dnbGUgZXh0ZW5kcyBPcGVuRWxlbWVudCB7XG4gIC8vIHBvbnl0YWlsOiBTYWZhcmkgZG9lcyBub3QgcmVjb21wdXRlIGFkb3B0ZWRTdHlsZVNoZWV0cyB3aGVuXG4gIC8vIDpob3N0KFtkYXRhLXRoZW1lXSkgY2hhbmdlcy4gVGhlIHRva2VuIHNoZWV0cyAob3BlblByb3BzVG9rZW5TaGVldCxcbiAgLy8gZGFpc3lDbGFzc1NoZWV0KSBhcmUgYWxyZWFkeSBpbmplY3RlZCBhcyBwYWdlLWxldmVsIDxzdHlsZT4gYnlcbiAgLy8gdml0ZS5jb25maWcudHMg4oCUIENTUyBjdXN0b20gcHJvcGVydGllcyBjYXNjYWRlIGZyb20gOnJvb3QgbmF0dXJhbGx5LlxuICAvLyBPbmx5IGFkb3B0IHRoZSBjb21wb25lbnQtc3BlY2lmaWMgc2hlZXQuXG4gIHN0YXRpYyBvdmVycmlkZSBzdHlsZXMgPSBbc2hlZXRdO1xuICBzdGF0aWMgb3ZlcnJpZGUgZGVsZWdhdGVzRm9jdXMgPSB0cnVlO1xuICBzdGF0aWMgb3ZlcnJpZGUgb2JzZXJ2ZWRBdHRyaWJ1dGVzID0gWyd0aGVtZSddO1xuXG4gIHByaXZhdGUgX3RoZW1lID0gc2lnbmFsPCdkYXJrJyB8ICdsaWdodCc+KCdkYXJrJyk7XG4gIHByaXZhdGUgX2luaXREb25lID0gZmFsc2U7XG5cbiAgb3ZlcnJpZGUgY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgc3VwZXIuY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy5faW5pdFRoZW1lKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIHYwLjIzLjA6IFRoZW1lIGluaXRpYWxpemF0aW9uIGxpdmVzIGluIF9pbml0VGhlbWUoKSwgY2FsbGVkIGZyb21cbiAgICogYm90aCBvbkRzZEh5ZHJhdGVkKCkgYW5kIG9uQ3NyUmVuZGVyZWQoKSBzbyB0aGF0IHRoZSBwcmlvcml0eVxuICAgKiBjaGFpbiB3b3JrcyByZWdhcmRsZXNzIG9mIGh5ZHJhdGlvbiBwYXRoLlxuICAgKlxuICAgKiBQcmlvcml0eTogdGhlbWUgYXR0cmlidXRlID4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmRhdGFzZXQudGhlbWVcbiAgICogPiBsb2NhbFN0b3JhZ2UgPiBwcmVmZXJzLWNvbG9yLXNjaGVtZSA+IGRlZmF1bHQgJ2RhcmsnLlxuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdFRoZW1lKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9pbml0RG9uZSkgcmV0dXJuO1xuICAgIHRoaXMuX2luaXREb25lID0gdHJ1ZTtcbiAgICBjb25zdCB0aGVtZUF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZSgndGhlbWUnKTtcbiAgICBpZiAodGhlbWVBdHRyID09PSAnbGlnaHQnKSB7XG4gICAgICB0aGlzLl90aGVtZS52YWx1ZSA9ICdsaWdodCc7XG4gICAgfSBlbHNlIGlmICh0aGVtZUF0dHIgPT09ICdkYXJrJykge1xuICAgICAgdGhpcy5fdGhlbWUudmFsdWUgPSAnZGFyayc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGRvY1RoZW1lID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Py5kYXRhc2V0Py50aGVtZTtcbiAgICAgIGlmIChkb2NUaGVtZSA9PT0gJ2xpZ2h0Jykge1xuICAgICAgICB0aGlzLl90aGVtZS52YWx1ZSA9ICdsaWdodCc7XG4gICAgICB9IGVsc2UgaWYgKGRvY1RoZW1lID09PSAnZGFyaycpIHtcbiAgICAgICAgdGhpcy5fdGhlbWUudmFsdWUgPSAnZGFyayc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcmVzb2x2ZWQgPSBmYWxzZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzYXZlZCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdvcGVuLXRoZW1lJyk7XG4gICAgICAgICAgaWYgKHNhdmVkID09PSAnbGlnaHQnKSB7XG4gICAgICAgICAgICB0aGlzLl90aGVtZS52YWx1ZSA9ICdsaWdodCc7XG4gICAgICAgICAgICByZXNvbHZlZCA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIGlmIChzYXZlZCA9PT0gJ2RhcmsnKSB7XG4gICAgICAgICAgICB0aGlzLl90aGVtZS52YWx1ZSA9ICdkYXJrJztcbiAgICAgICAgICAgIHJlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggeyAvKiBsb2NhbFN0b3JhZ2UgYmxvY2tlZCAqLyB9XG4gICAgICAgIGlmICghcmVzb2x2ZWQgJiYgZ2xvYmFsVGhpcy5tYXRjaE1lZGlhKSB7XG4gICAgICAgICAgdGhpcy5fdGhlbWUudmFsdWUgPSBnbG9iYWxUaGlzLm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpJykubWF0Y2hlc1xuICAgICAgICAgICAgPyAnbGlnaHQnXG4gICAgICAgICAgICA6ICdkYXJrJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdkYXRhLXRoZW1lJywgdGhpcy5fdGhlbWUudmFsdWUpO1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtdGhlbWUnLCB0aGlzLl90aGVtZS52YWx1ZSk7XG4gICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZSkge1xuICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmNvbG9yU2NoZW1lID0gdGhpcy5fdGhlbWUudmFsdWU7XG4gICAgfVxuICAgIC8vIFByb3BhZ2F0ZSB0byBwYXJlbnQgb3Blbi1sYXlvdXRcbiAgICB0cnkge1xuICAgICAgY29uc3Qgcm9vdCA9IHRoaXMuZ2V0Um9vdE5vZGUoKTtcbiAgICAgIGlmIChyb290IGluc3RhbmNlb2YgU2hhZG93Um9vdCAmJiByb290Lmhvc3QpIHtcbiAgICAgICAgcm9vdC5ob3N0LnNldEF0dHJpYnV0ZSgnZGF0YS10aGVtZScsIHRoaXMuX3RoZW1lLnZhbHVlKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHsgLyogbm90IGluIHNoYWRvdyBET00gKi8gfVxuICAgIHRoaXMuX2Rpc3BhdGNoVGhlbWVDaGFuZ2UodGhpcy5fdGhlbWUudmFsdWUpO1xuICAgIHRoaXMuX3BlcnNpc3RUaGVtZSh0aGlzLl90aGVtZS52YWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIF9wZXJzaXN0VGhlbWUodGhlbWU6ICdkYXJrJyB8ICdsaWdodCcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ29wZW4tdGhlbWUnLCB0aGVtZSk7XG4gICAgfSBjYXRjaCB7IC8qIGJsb2NrZWQgKi8gfVxuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIG9uRHNkSHlkcmF0ZWQoKTogdm9pZCB7XG4gICAgc3VwZXIub25Ec2RIeWRyYXRlZCgpO1xuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLl9pbml0VGhlbWUoKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25Dc3JSZW5kZXJlZCgpOiB2b2lkIHtcbiAgICBzdXBlci5vbkNzclJlbmRlcmVkKCk7XG4gIH1cblxuICBvdmVycmlkZSByZW5kZXIoKTogUmV0dXJuVHlwZTx0eXBlb2YgT3BlbkVsZW1lbnQucHJvdG90eXBlLnJlbmRlcj4ge1xuICAgIC8vIFplcm8gc2lnbmFsLnZhbHVlIHJlYWRzIGluIHJlbmRlciAoQURSLTAwNjIpLlxuICAgIC8vIGVmZmVjdCBiaW5kaW5nIHRoYXQgdXBkYXRlcyB0aGUgYXR0cmlidXRlIHdoZW4gdGhlbWUgY2hhbmdlcy5cbiAgICAvLyBDU1Mgc2VsZWN0b3JzIChbZGF0YS10aGVtZT1cImxpZ2h0XCJdKSBoYW5kbGUgaWNvbiB2aXNpYmlsaXR5LlxuICAgIHJldHVybiAoXG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9J2J1dHRvbidcbiAgICAgICAgY2xhc3NOYW1lPSd0aGVtZS10b2dnbGUnXG4gICAgICAgIHBhcnQ9J3RvZ2dsZSdcbiAgICAgICAgZGF0YS10aGVtZT17dGhpcy5fdGhlbWV9XG4gICAgICAgIGFyaWEtbGFiZWw9J1RvZ2dsZSB0aGVtZSdcbiAgICAgICAgb25DbGljaz17KCkgPT4gdGhpcy5faGFuZGxlVG9nZ2xlKCl9XG4gICAgICA+XG4gICAgICAgIDxzdmdcbiAgICAgICAgICBjbGFzc05hbWU9J2ljb24tc3VuJ1xuICAgICAgICAgIHBhcnQ9J2ljb24tc3VuJ1xuICAgICAgICAgIHZpZXdCb3g9JzAgMCAxNiAxNidcbiAgICAgICAgICBmaWxsPSdub25lJ1xuICAgICAgICAgIHN0cm9rZT0nY3VycmVudENvbG9yJ1xuICAgICAgICAgIHN0cm9rZS13aWR0aD0nMS4yJ1xuICAgICAgICAgIHN0cm9rZS1saW5lY2FwPSdyb3VuZCdcbiAgICAgICAgPlxuICAgICAgICAgIDxjaXJjbGUgY3g9JzgnIGN5PSc4JyByPSczJyAvPlxuICAgICAgICAgIDxsaW5lIHgxPSc4JyB5MT0nMScgeDI9JzgnIHkyPSczJyAvPlxuICAgICAgICAgIDxsaW5lIHgxPSc4JyB5MT0nMTMnIHgyPSc4JyB5Mj0nMTUnIC8+XG4gICAgICAgICAgPGxpbmUgeDE9JzEnIHkxPSc4JyB4Mj0nMycgeTI9JzgnIC8+XG4gICAgICAgICAgPGxpbmUgeDE9JzEzJyB5MT0nOCcgeDI9JzE1JyB5Mj0nOCcgLz5cbiAgICAgICAgICA8bGluZSB4MT0nMy4wNScgeTE9JzMuMDUnIHgyPSc0LjQ2JyB5Mj0nNC40NicgLz5cbiAgICAgICAgICA8bGluZSB4MT0nMTEuNTQnIHkxPScxMS41NCcgeDI9JzEyLjk1JyB5Mj0nMTIuOTUnIC8+XG4gICAgICAgICAgPGxpbmUgeDE9JzMuMDUnIHkxPScxMi45NScgeDI9JzQuNDYnIHkyPScxMS41NCcgLz5cbiAgICAgICAgICA8bGluZSB4MT0nMTEuNTQnIHkxPSc0LjQ2JyB4Mj0nMTIuOTUnIHkyPSczLjA1JyAvPlxuICAgICAgICA8L3N2Zz5cbiAgICAgICAgPHN2Z1xuICAgICAgICAgIGNsYXNzTmFtZT0naWNvbi1tb29uJ1xuICAgICAgICAgIHBhcnQ9J2ljb24tbW9vbidcbiAgICAgICAgICB2aWV3Qm94PScwIDAgMTYgMTYnXG4gICAgICAgICAgZmlsbD0nbm9uZSdcbiAgICAgICAgICBzdHJva2U9J2N1cnJlbnRDb2xvcidcbiAgICAgICAgICBzdHJva2Utd2lkdGg9JzEuMidcbiAgICAgICAgICBzdHJva2UtbGluZWNhcD0ncm91bmQnXG4gICAgICAgID5cbiAgICAgICAgICA8cGF0aCBkPSdNMTMuNSA5LjE0QTUuNSA1LjUgMCAwIDEgNi44NiAyLjUgNS41IDUuNSAwIDEgMCAxMy41IDkuMTRaJyAvPlxuICAgICAgICA8L3N2Zz5cbiAgICAgIDwvYnV0dG9uPlxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIF9oYW5kbGVUb2dnbGUoKTogdm9pZCB7XG4gICAgY29uc3QgdGhlbWUgPSB0aGlzLl90aGVtZS52YWx1ZSA9PT0gJ2xpZ2h0JyA/ICdkYXJrJyA6ICdsaWdodCc7XG4gICAgdGhpcy5fdGhlbWUudmFsdWUgPSB0aGVtZTtcblxuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtdGhlbWUnLCB0aGVtZSk7XG4gICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZSkge1xuICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmNvbG9yU2NoZW1lID0gdGhlbWU7XG4gICAgfVxuXG4gICAgLy8gUHJvcGFnYXRlIGRhdGEtdGhlbWUgdG8gcGFyZW50IDxvcGVuLWxheW91dD4gc28gOmhvc3QoW2RhdGEtdGhlbWU9XCJkYXJrXCJdKSBtYXRjaGVzXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJvb3QgPSB0aGlzLmdldFJvb3ROb2RlKCk7XG4gICAgICBpZiAocm9vdCBpbnN0YW5jZW9mIFNoYWRvd1Jvb3QgJiYgcm9vdC5ob3N0KSB7XG4gICAgICAgIHJvb3QuaG9zdC5zZXRBdHRyaWJ1dGUoJ2RhdGEtdGhlbWUnLCB0aGVtZSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5kZWJ1ZygnW29wZW4tdGhlbWUtdG9nZ2xlXSBnZXRSb290Tm9kZSB1bmF2YWlsYWJsZTonLCBlKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaXNwYXRjaFRoZW1lQ2hhbmdlKHRoZW1lKTtcblxuICAgIHRyeSB7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnb3Blbi10aGVtZScsIHRoZW1lKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdbb3Blbi10aGVtZS10b2dnbGVdIGxvY2FsU3RvcmFnZS5zZXRJdGVtIHVuYXZhaWxhYmxlOicsIGUpO1xuICAgIH1cbiAgICAvLyBkYXRhLXRoZW1lIGF0dHJpYnV0ZSBpcyBtYW5hZ2VkIGJ5IHNpZ25hbCBwcm9wIGJpbmRpbmcgKGRhdGEtdGhlbWU9e3RoaXMuX3RoZW1lfSlcbiAgfVxuXG4gIHByaXZhdGUgX2Rpc3BhdGNoVGhlbWVDaGFuZ2UodGhlbWU6ICdkYXJrJyB8ICdsaWdodCcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBDdXN0b21FdmVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGdsb2JhbFRoaXMuZGlzcGF0Y2hFdmVudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBnbG9iYWxUaGlzLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KCdvcGVuOnRoZW1lLWNoYW5nZScsIHsgZGV0YWlsOiB7IHRoZW1lIH0gfSkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ1tvcGVuLXRoZW1lLXRvZ2dsZV0gdGhlbWUgZXZlbnQgZGlzcGF0Y2ggdW5hdmFpbGFibGU6JywgZSk7XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWU6IHN0cmluZywgb2xkOiBzdHJpbmcgfCBudWxsLCB2YWw6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAob2xkID09PSB2YWwpIHJldHVybjtcbiAgICBpZiAobmFtZSA9PT0gJ3RoZW1lJyAmJiB2YWwpIHtcbiAgICAgIHRoaXMuX3RoZW1lLnZhbHVlID0gdmFsID09PSAnbGlnaHQnID8gJ2xpZ2h0JyA6ICdkYXJrJztcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdkYXRhLXRoZW1lJywgdGhpcy5fdGhlbWUudmFsdWUpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBPcGVuVGhlbWVUb2dnbGU7XG5cbi8vIEd1YXJkOiBpZGVtcG90ZW50IGFjcm9zcyBTU1IgcGF0aHNcbmlmICh0eXBlb2YgY3VzdG9tRWxlbWVudHMgIT09ICd1bmRlZmluZWQnICYmICFjdXN0b21FbGVtZW50cy5nZXQodGFnTmFtZSkpIHtcbiAgY3VzdG9tRWxlbWVudHMuZGVmaW5lKHRhZ05hbWUsIE9wZW5UaGVtZVRvZ2dsZSk7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdUNBQXVDLEdBQ3ZDOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCQyxHQUVELFNBQVMsV0FBVyxRQUFRLHVCQUF1QjtBQUNuRCxTQUFTLFVBQVUsUUFBNkIsZ0NBQWdDO0FBQ2hGLFNBQVMsTUFBTSxRQUFRLHNCQUFzQjtBQUM3QyxPQUFPLE1BQU0sVUFBVSxvQkFB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