@lit-pigeon/editor 0.1.3 → 0.3.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.
@@ -0,0 +1,195 @@
1
+ import { LitElement as b, html as a, css as g } from "lit";
2
+ import { property as h, customElement as u } from "lit/decorators.js";
3
+ import { generateId as p } from "@lit-pigeon/core";
4
+ import { t as i } from "./templates.js";
5
+ var m = Object.defineProperty, f = Object.getOwnPropertyDescriptor, c = (e, t, o, n) => {
6
+ for (var r = n > 1 ? void 0 : n ? f(t, o) : t, s = e.length - 1, d; s >= 0; s--)
7
+ (d = e[s]) && (r = (n ? d(t, o, r) : d(r)) || r);
8
+ return n && r && m(t, o, r), r;
9
+ };
10
+ let l = class extends b {
11
+ constructor() {
12
+ super(...arguments), this.brandKit = null;
13
+ }
14
+ render() {
15
+ const e = this.brandKit;
16
+ return e ? a`
17
+ ${this._renderColors(e)}
18
+ ${this._renderFonts(e)}
19
+ ${this._renderLogos(e)}
20
+ ` : a``;
21
+ }
22
+ _renderColors(e) {
23
+ return a`
24
+ <div class="section">
25
+ <div class="section-head">
26
+ <h4>${i("palette.brand.colors")}</h4>
27
+ <button class="add add-color" type="button" @click=${this._addColor}>${i("palette.brand.add")}</button>
28
+ </div>
29
+ ${e.colors.length === 0 ? a`<div class="empty">${i("palette.brand.no-colors")}</div>` : ""}
30
+ ${e.colors.map(
31
+ (t) => a`<div class="row" data-color-id=${t.id}>
32
+ <button
33
+ class="swatch" type="button" title=${`Apply ${t.name}`} aria-label=${`Apply ${t.name}`}
34
+ style=${`background:${t.value}`} @click=${() => this._applyColor(t)}
35
+ ></button>
36
+ <input
37
+ class="name-input" aria-label=${i("palette.brand.color-name-label")} .value=${t.name}
38
+ @change=${(o) => this._renameColor(t, o.target.value)}
39
+ />
40
+ <input
41
+ type="color" aria-label=${i("palette.brand.color-value-label")} .value=${t.value}
42
+ @input=${(o) => this._recolor(t, o.target.value)}
43
+ />
44
+ <button class="delete" type="button" title=${i("palette.brand.delete-title")} aria-label=${`Delete ${t.name}`} @click=${() => this._deleteColor(t)}>×</button>
45
+ </div>`
46
+ )}
47
+ </div>
48
+ `;
49
+ }
50
+ _renderFonts(e) {
51
+ return a`
52
+ <div class="section">
53
+ <div class="section-head">
54
+ <h4>${i("palette.brand.fonts")}</h4>
55
+ <button class="add add-font" type="button" @click=${this._addFont}>${i("palette.brand.add")}</button>
56
+ </div>
57
+ ${e.fonts.length === 0 ? a`<div class="empty">${i("palette.brand.no-fonts")}</div>` : ""}
58
+ ${e.fonts.map(
59
+ (t) => a`<div class="row" data-font-id=${t.id}>
60
+ <button class="apply" type="button" title=${`Apply ${t.name}`} aria-label=${`Apply font ${t.name}`} @click=${() => this._applyFont(t)}>
61
+ ${t.name}
62
+ </button>
63
+ <button class="delete" type="button" title=${i("palette.brand.delete-title")} aria-label=${`Delete ${t.name}`} @click=${() => this._deleteFont(t)}>×</button>
64
+ </div>`
65
+ )}
66
+ </div>
67
+ `;
68
+ }
69
+ _renderLogos(e) {
70
+ return a`
71
+ <div class="section">
72
+ <div class="section-head">
73
+ <h4>${i("palette.brand.logos")}</h4>
74
+ <button class="add add-logo" type="button" @click=${this._addLogo}>${i("palette.brand.add")}</button>
75
+ </div>
76
+ ${e.logos.length === 0 ? a`<div class="empty">${i("palette.brand.no-logos")}</div>` : ""}
77
+ ${e.logos.map(
78
+ (t) => a`<div class="row" data-logo-id=${t.id}>
79
+ <img class="logo-thumb" src=${t.src} alt=${t.name} />
80
+ <button class="apply" type="button" title=${i("palette.brand.insert-logo-title")} aria-label=${`Insert logo ${t.name}`} @click=${() => this._insertLogo(t)}>
81
+ ${t.name}
82
+ </button>
83
+ <button class="delete" type="button" title=${i("palette.brand.delete-title")} aria-label=${`Delete ${t.name}`} @click=${() => this._deleteLogo(t)}>×</button>
84
+ </div>`
85
+ )}
86
+ </div>
87
+ `;
88
+ }
89
+ /* ---- apply / insert (no kit mutation) ---- */
90
+ _applyColor(e) {
91
+ this._fire("brand-color-apply", { value: e.value });
92
+ }
93
+ _applyFont(e) {
94
+ this._fire("brand-font-apply", { family: e.family });
95
+ }
96
+ _insertLogo(e) {
97
+ this._fire("brand-logo-insert", { logo: e });
98
+ }
99
+ /* ---- mutations: compute new kit, emit brand-kit-edit ---- */
100
+ _emitKit(e) {
101
+ this._fire("brand-kit-edit", { kit: e });
102
+ }
103
+ _clone() {
104
+ const e = this.brandKit;
105
+ return { ...e, colors: [...e.colors], fonts: [...e.fonts], logos: [...e.logos] };
106
+ }
107
+ _addColor() {
108
+ const e = this._clone();
109
+ e.colors = [...e.colors, { id: p(), name: "New color", value: "#000000" }], this._emitKit(e);
110
+ }
111
+ _renameColor(e, t) {
112
+ const o = this._clone();
113
+ o.colors = o.colors.map((n) => n.id === e.id ? { ...n, name: t } : n), this._emitKit(o);
114
+ }
115
+ _recolor(e, t) {
116
+ const o = this._clone();
117
+ o.colors = o.colors.map((n) => n.id === e.id ? { ...n, value: t } : n), this._emitKit(o);
118
+ }
119
+ _deleteColor(e) {
120
+ const t = this._clone();
121
+ t.colors = t.colors.filter((o) => o.id !== e.id), this._emitKit(t);
122
+ }
123
+ _addFont() {
124
+ const e = this._clone();
125
+ e.fonts = [...e.fonts, { id: p(), name: "New font", family: "Arial, Helvetica, sans-serif" }], this._emitKit(e);
126
+ }
127
+ _deleteFont(e) {
128
+ const t = this._clone();
129
+ t.fonts = t.fonts.filter((o) => o.id !== e.id), this._emitKit(t);
130
+ }
131
+ _addLogo() {
132
+ const e = prompt("Logo image URL");
133
+ if (!e) return;
134
+ const t = this._clone();
135
+ t.logos = [...t.logos, { id: p(), name: "Logo", src: e }], this._emitKit(t);
136
+ }
137
+ _deleteLogo(e) {
138
+ const t = this._clone();
139
+ t.logos = t.logos.filter((o) => o.id !== e.id), this._emitKit(t);
140
+ }
141
+ _fire(e, t) {
142
+ this.dispatchEvent(new CustomEvent(e, { detail: t, bubbles: !0, composed: !0 }));
143
+ }
144
+ };
145
+ l.styles = g`
146
+ :host { display: block; }
147
+ .section { padding: 12px; }
148
+ .section:not(:last-child) { border-bottom: 1px solid var(--pigeon-border, #e2e8f0); }
149
+ .section-head {
150
+ display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;
151
+ }
152
+ .section-head h4 {
153
+ margin: 0; font-size: 11px; font-weight: 600; text-transform: uppercase;
154
+ letter-spacing: 0.5px; color: var(--pigeon-text-secondary, #64748b); font-family: var(--pigeon-font);
155
+ }
156
+ .add {
157
+ border: 1px solid var(--pigeon-border, #e2e8f0); background: var(--pigeon-surface, #f8fafc);
158
+ border-radius: var(--pigeon-radius-sm, 6px); cursor: pointer; font-size: 12px;
159
+ line-height: 1; padding: 4px 8px; color: var(--pigeon-text-secondary, #64748b);
160
+ }
161
+ .row {
162
+ display: flex; align-items: center; gap: 8px; padding: 4px 0; font-family: var(--pigeon-font);
163
+ font-size: 13px; color: var(--pigeon-text, #1e293b);
164
+ }
165
+ .swatch {
166
+ width: 20px; height: 20px; border-radius: var(--pigeon-radius-sm, 4px);
167
+ border: 1px solid var(--pigeon-input, #cbd5e1); padding: 0; cursor: pointer; flex-shrink: 0;
168
+ }
169
+ .name { flex: 1; }
170
+ .name-input {
171
+ flex: 1; height: 24px; border: 1px solid var(--pigeon-input, #cbd5e1);
172
+ border-radius: var(--pigeon-radius-sm, 4px); padding: 0 6px; font: inherit; min-width: 0;
173
+ }
174
+ .apply {
175
+ flex: 1; text-align: left; background: none; border: none; cursor: pointer; font: inherit;
176
+ color: var(--pigeon-text, #1e293b); padding: 0; min-width: 0;
177
+ }
178
+ .apply:hover { color: var(--pigeon-primary, #4f46e5); }
179
+ .delete {
180
+ background: none; border: none; cursor: pointer; color: var(--pigeon-text-muted, #94a3b8);
181
+ font-size: 14px; line-height: 1; padding: 2px;
182
+ }
183
+ .delete:hover { color: var(--pigeon-danger, #dc2626); }
184
+ .logo-thumb { width: 28px; height: 28px; object-fit: contain; flex-shrink: 0; }
185
+ .empty { font-size: 12px; color: var(--pigeon-text-muted, #94a3b8); font-family: var(--pigeon-font); }
186
+ `;
187
+ c([
188
+ h({ attribute: !1 })
189
+ ], l.prototype, "brandKit", 2);
190
+ l = c([
191
+ u("pigeon-brand-tab")
192
+ ], l);
193
+ export {
194
+ l as PigeonBrandTab
195
+ };
@@ -0,0 +1,93 @@
1
+ import { LitElement as c, html as l, css as f } from "lit";
2
+ import { property as b, state as g, customElement as u } from "lit/decorators.js";
3
+ import { writeDragTransfer as m } from "./index.js";
4
+ import { t as d } from "./templates.js";
5
+ var v = Object.defineProperty, h = Object.getOwnPropertyDescriptor, p = (e, t, n, o) => {
6
+ for (var r = o > 1 ? void 0 : o ? h(t, n) : t, i = e.length - 1, s; i >= 0; i--)
7
+ (s = e[i]) && (r = (o ? s(t, n, r) : s(r)) || r);
8
+ return o && r && v(t, n, r), r;
9
+ };
10
+ let a = class extends c {
11
+ constructor() {
12
+ super(...arguments), this._entries = [];
13
+ }
14
+ async connectedCallback() {
15
+ super.connectedCallback(), await this.refresh();
16
+ }
17
+ /** Re-load entries from storage. */
18
+ async refresh() {
19
+ if (!this.storage) {
20
+ this._entries = [];
21
+ return;
22
+ }
23
+ try {
24
+ this._entries = await this.storage.list();
25
+ } catch {
26
+ this._entries = [];
27
+ }
28
+ }
29
+ render() {
30
+ return l`
31
+ <div class="section">
32
+ ${this._entries.length === 0 ? l`<div class="empty">${d("palette.saved.empty")}</div>` : this._entries.map(
33
+ (e) => l`<div
34
+ class="row" data-entry-id=${e.id} draggable="true"
35
+ role="button" tabindex="0" aria-label=${`Insert ${e.name}`}
36
+ @dragstart=${(t) => this._onDragStart(t, e)}
37
+ @keydown=${(t) => this._onKeyDown(t, e)}
38
+ >
39
+ <span class="name">${e.name}</span>
40
+ <button class="delete" type="button" title=${d("palette.saved.delete-title")} aria-label=${`Delete ${e.name}`}
41
+ @click=${() => this._onDelete(e)}>×</button>
42
+ </div>`
43
+ )}
44
+ </div>
45
+ `;
46
+ }
47
+ _onKeyDown(e, t) {
48
+ e.key !== "Enter" && e.key !== " " || (e.preventDefault(), this.dispatchEvent(new CustomEvent("library-insert", {
49
+ detail: { node: t.node },
50
+ bubbles: !0,
51
+ composed: !0
52
+ })));
53
+ }
54
+ _onDragStart(e, t) {
55
+ m(e, { type: "library-row", node: t.node }), e.dataTransfer && (e.dataTransfer.effectAllowed = "copy");
56
+ }
57
+ _onDelete(e) {
58
+ this.dispatchEvent(new CustomEvent("library-delete", {
59
+ detail: { id: e.id },
60
+ bubbles: !0,
61
+ composed: !0
62
+ }));
63
+ }
64
+ };
65
+ a.styles = f`
66
+ :host { display: block; }
67
+ .section { padding: 12px; }
68
+ .empty { font-size: 12px; color: var(--pigeon-text-muted, #94a3b8); font-family: var(--pigeon-font); }
69
+ .row {
70
+ display: flex; align-items: center; gap: 8px; padding: 8px 12px; margin-bottom: 6px;
71
+ border: 1px solid var(--pigeon-border, #e2e8f0); border-radius: var(--pigeon-radius, 6px);
72
+ background: var(--pigeon-bg, #ffffff); cursor: grab; font-family: var(--pigeon-font); font-size: 13px;
73
+ }
74
+ .row:hover { border-color: var(--pigeon-primary, #3b82f6); background: var(--pigeon-surface, #f8fafc); }
75
+ .name { flex: 1; color: var(--pigeon-text, #1e293b); }
76
+ .delete {
77
+ background: none; border: none; cursor: pointer; color: var(--pigeon-text-muted, #94a3b8);
78
+ font-size: 14px; line-height: 1; padding: 2px;
79
+ }
80
+ .delete:hover { color: var(--pigeon-danger, #dc2626); }
81
+ `;
82
+ p([
83
+ b({ attribute: !1 })
84
+ ], a.prototype, "storage", 2);
85
+ p([
86
+ g()
87
+ ], a.prototype, "_entries", 2);
88
+ a = p([
89
+ u("pigeon-saved-tab")
90
+ ], a);
91
+ export {
92
+ a as PigeonSavedTab
93
+ };
@@ -0,0 +1,258 @@
1
+ import { LitElement as b, nothing as v, html as d, css as y } from "lit";
2
+ import { property as x, state as u, customElement as k } from "lit/decorators.js";
3
+ import { t as c } from "./templates.js";
4
+ const m = 24;
5
+ class g extends Error {
6
+ constructor(r) {
7
+ super(`Stock request failed: ${r}`), this.status = r, this.name = "StockError";
8
+ }
9
+ }
10
+ function w(e, r) {
11
+ const i = { Authorization: `Client-ID ${e}` }, s = `utm_source=${encodeURIComponent(r)}&utm_medium=referral`, o = (t) => t + (t.includes("?") ? "&" : "?") + s;
12
+ return {
13
+ id: "unsplash",
14
+ label: "Unsplash",
15
+ async search(t, n) {
16
+ const p = `https://api.unsplash.com/search/photos?query=${encodeURIComponent(t)}&page=${n}&per_page=${m}`, f = await fetch(p, { headers: i });
17
+ if (!f.ok) throw new g(f.status);
18
+ const _ = await f.json();
19
+ return { photos: _.results.map((l) => ({
20
+ id: `unsplash:${l.id}`,
21
+ provider: "unsplash",
22
+ thumbUrl: l.urls.small,
23
+ fullUrl: l.urls.regular,
24
+ width: l.width,
25
+ height: l.height,
26
+ alt: l.alt_description ?? l.description ?? "",
27
+ photographerName: l.user.name,
28
+ photographerUrl: o(l.user.links.html),
29
+ providerUrl: o(l.links.html),
30
+ downloadLocation: l.links.download_location
31
+ })), page: n, hasMore: n < _.total_pages };
32
+ },
33
+ async trackDownload(t) {
34
+ if (t.downloadLocation)
35
+ try {
36
+ await fetch(t.downloadLocation, { headers: i });
37
+ } catch {
38
+ }
39
+ }
40
+ };
41
+ }
42
+ function $(e) {
43
+ return {
44
+ id: "pexels",
45
+ label: "Pexels",
46
+ async search(r, i) {
47
+ const s = `https://api.pexels.com/v1/search?query=${encodeURIComponent(r)}&page=${i}&per_page=${m}`, o = await fetch(s, { headers: { Authorization: e } });
48
+ if (!o.ok) throw new g(o.status);
49
+ const t = await o.json();
50
+ return { photos: t.photos.map((p) => ({
51
+ id: `pexels:${p.id}`,
52
+ provider: "pexels",
53
+ thumbUrl: p.src.medium,
54
+ fullUrl: p.src.large,
55
+ width: p.width,
56
+ height: p.height,
57
+ alt: p.alt ?? "",
58
+ photographerName: p.photographer,
59
+ photographerUrl: p.photographer_url,
60
+ providerUrl: p.url
61
+ })), page: i, hasMore: !!t.next_page };
62
+ },
63
+ async trackDownload() {
64
+ }
65
+ };
66
+ }
67
+ function U(e) {
68
+ var s, o;
69
+ if (!e) return [];
70
+ const r = e.appName || "lit-pigeon", i = [];
71
+ return (s = e.unsplash) != null && s.accessKey && i.push(w(e.unsplash.accessKey, r)), (o = e.pexels) != null && o.apiKey && i.push($(e.pexels.apiKey)), i;
72
+ }
73
+ var P = Object.defineProperty, I = Object.getOwnPropertyDescriptor, h = (e, r, i, s) => {
74
+ for (var o = s > 1 ? void 0 : s ? I(r, i) : r, t = e.length - 1, n; t >= 0; t--)
75
+ (n = e[t]) && (o = (s ? n(r, i, o) : n(o)) || o);
76
+ return s && o && P(r, i, o), o;
77
+ };
78
+ const K = 250;
79
+ let a = class extends b {
80
+ constructor() {
81
+ super(...arguments), this.config = {}, this._providers = [], this._providerIndex = 0, this._query = "", this._photos = [], this._page = 1, this._hasMore = !1, this._loading = !1, this._errorKey = "", this._token = 0, this._timer = null;
82
+ }
83
+ willUpdate(e) {
84
+ e.has("config") && (this._providers = U(this.config), this._providerIndex >= this._providers.length && (this._providerIndex = 0));
85
+ }
86
+ get _provider() {
87
+ return this._providers[this._providerIndex];
88
+ }
89
+ render() {
90
+ return d`
91
+ <div class="controls">
92
+ ${this._providers.length > 1 ? d`<div class="provider-switch" role="group">
93
+ ${this._providers.map(
94
+ (e, r) => d`<button
95
+ class="provider-btn ${r === this._providerIndex ? "active" : ""}"
96
+ @click=${() => this._switchProvider(r)}
97
+ >${e.label}</button>`
98
+ )}
99
+ </div>` : v}
100
+ <input
101
+ type="search"
102
+ placeholder=${c("asset.stock.search")}
103
+ aria-label=${c("asset.stock.search")}
104
+ .value=${this._query}
105
+ @input=${this._onInput}
106
+ />
107
+ </div>
108
+ ${this._renderBody()}
109
+ `;
110
+ }
111
+ _renderBody() {
112
+ return this._errorKey ? d`<div class="error">${c(this._errorKey)}</div>` : this._loading && this._photos.length === 0 ? d`<div class="library-spinner">${c("asset.loading")}</div>` : this._query.trim() ? this._photos.length === 0 ? d`<div class="empty-library">${c("asset.stock.empty")}</div>` : d`
113
+ <div class="asset-grid">${this._photos.map((e) => this._renderCard(e))}</div>
114
+ ${this._hasMore ? d`<button class="load-more" @click=${this._loadMore}>${c("asset.stock.load-more")}</button>` : v}
115
+ ` : d`<div class="stock-idle">${c("asset.stock.idle")}</div>`;
116
+ }
117
+ _renderCard(e) {
118
+ var i;
119
+ const r = ((i = this._providers.find((s) => s.id === e.provider)) == null ? void 0 : i.label) ?? e.provider;
120
+ return d`<button class="asset-card" type="button" @click=${() => this._pick(e)}>
121
+ <img class="asset-thumb" src=${e.thumbUrl} alt=${e.alt} loading="lazy" />
122
+ <div class="stock-credit">
123
+ ${c("asset.stock.photo-by")}
124
+ <a href=${e.photographerUrl} target="_blank" rel="noopener"
125
+ @click=${(s) => s.stopPropagation()}>${e.photographerName}</a>
126
+ ${c("asset.stock.on")}
127
+ <a href=${e.providerUrl} target="_blank" rel="noopener"
128
+ @click=${(s) => s.stopPropagation()}>${r}</a>
129
+ </div>
130
+ </button>`;
131
+ }
132
+ _onInput(e) {
133
+ this._query = e.target.value, this._timer && clearTimeout(this._timer), this._timer = setTimeout(() => this._runSearch(1, !1), K);
134
+ }
135
+ async _runSearch(e, r) {
136
+ const i = this._provider, s = this._query.trim();
137
+ if (!i || !s) {
138
+ this._photos = [], this._hasMore = !1, this._errorKey = "";
139
+ return;
140
+ }
141
+ const o = ++this._token;
142
+ this._loading = !0, this._errorKey = "";
143
+ try {
144
+ const t = await i.search(s, e);
145
+ if (o !== this._token) return;
146
+ this._photos = r ? [...this._photos, ...t.photos] : t.photos, this._page = t.page, this._hasMore = t.hasMore;
147
+ } catch (t) {
148
+ if (o !== this._token) return;
149
+ const n = t instanceof g ? t.status : 0;
150
+ this._errorKey = n === 429 || n === 403 ? "asset.stock.rate-limited" : "asset.stock.error", r || (this._photos = []);
151
+ } finally {
152
+ o === this._token && (this._loading = !1);
153
+ }
154
+ }
155
+ _loadMore() {
156
+ this._runSearch(this._page + 1, !0);
157
+ }
158
+ _switchProvider(e) {
159
+ e !== this._providerIndex && (this._providerIndex = e, this._photos = [], this._errorKey = "", this._runSearch(1, !1));
160
+ }
161
+ _pick(e) {
162
+ var r;
163
+ (r = this._provider) == null || r.trackDownload(e), this.dispatchEvent(
164
+ new CustomEvent("stock-select", {
165
+ detail: { url: e.fullUrl },
166
+ bubbles: !0,
167
+ composed: !0
168
+ })
169
+ );
170
+ }
171
+ };
172
+ a.styles = y`
173
+ :host { display: block; }
174
+ .controls { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
175
+ input[type='search'] {
176
+ flex: 1; height: 32px; box-sizing: border-box;
177
+ border: 1px solid var(--pigeon-border, #e2e8f0);
178
+ border-radius: var(--pigeon-radius-sm, 4px);
179
+ padding: 0 10px; font-family: var(--pigeon-font); font-size: 13px;
180
+ color: var(--pigeon-text, #1e293b); background: var(--pigeon-bg, #ffffff); outline: none;
181
+ }
182
+ input[type='search']:focus { border-color: var(--pigeon-border-focus, #3b82f6); }
183
+ .provider-switch { display: flex; gap: 4px; }
184
+ .provider-btn {
185
+ height: 32px; padding: 0 10px; cursor: pointer; font-size: 12px; font-weight: 500;
186
+ font-family: var(--pigeon-font); color: var(--pigeon-text-secondary, #64748b);
187
+ background: var(--pigeon-surface, #f1f5f9);
188
+ border: 1px solid var(--pigeon-border, #e2e8f0); border-radius: var(--pigeon-radius-sm, 4px);
189
+ }
190
+ .provider-btn.active {
191
+ background: var(--pigeon-primary, #3b82f6); color: var(--pigeon-primary-foreground, #fff);
192
+ border-color: var(--pigeon-primary, #3b82f6);
193
+ }
194
+ .asset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
195
+ .asset-card {
196
+ cursor: pointer; border: 1px solid var(--pigeon-border, #e2e8f0);
197
+ border-radius: var(--pigeon-radius-sm, 4px); overflow: hidden; padding: 0;
198
+ background: var(--pigeon-bg, #ffffff); display: flex; flex-direction: column;
199
+ text-align: left; font-family: inherit;
200
+ }
201
+ .asset-card:hover, .asset-card:focus-visible {
202
+ border-color: var(--pigeon-primary, #3b82f6); box-shadow: var(--pigeon-ring-shadow); outline: none;
203
+ }
204
+ .asset-thumb {
205
+ width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
206
+ background: var(--pigeon-surface, #f1f5f9);
207
+ }
208
+ .stock-credit {
209
+ padding: 5px 8px; font-size: 11px; line-height: 1.3;
210
+ color: var(--pigeon-text-secondary, #64748b);
211
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
212
+ }
213
+ .stock-credit a { color: inherit; text-decoration: underline; }
214
+ .stock-idle, .empty-library, .library-spinner {
215
+ padding: 32px 16px; text-align: center; font-size: 13px;
216
+ color: var(--pigeon-text-secondary, #64748b);
217
+ }
218
+ .error { color: var(--pigeon-danger, #ef4444); font-size: 13px; margin: 8px 0; }
219
+ .load-more {
220
+ display: block; margin: 14px auto 0; height: 32px; padding: 0 16px; cursor: pointer;
221
+ font-family: var(--pigeon-font); font-size: 13px; font-weight: 500;
222
+ color: var(--pigeon-text, #1e293b); background: var(--pigeon-surface, #f1f5f9);
223
+ border: 1px solid var(--pigeon-border, #e2e8f0); border-radius: var(--pigeon-radius-sm, 4px);
224
+ }
225
+ `;
226
+ h([
227
+ x({ attribute: !1 })
228
+ ], a.prototype, "config", 2);
229
+ h([
230
+ u()
231
+ ], a.prototype, "_providers", 2);
232
+ h([
233
+ u()
234
+ ], a.prototype, "_providerIndex", 2);
235
+ h([
236
+ u()
237
+ ], a.prototype, "_query", 2);
238
+ h([
239
+ u()
240
+ ], a.prototype, "_photos", 2);
241
+ h([
242
+ u()
243
+ ], a.prototype, "_page", 2);
244
+ h([
245
+ u()
246
+ ], a.prototype, "_hasMore", 2);
247
+ h([
248
+ u()
249
+ ], a.prototype, "_loading", 2);
250
+ h([
251
+ u()
252
+ ], a.prototype, "_errorKey", 2);
253
+ a = h([
254
+ k("pigeon-stock-tab")
255
+ ], a);
256
+ export {
257
+ a as PigeonStockTab
258
+ };