@justeattakeaway/pie-list 0.4.0 → 0.5.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.
@@ -1,307 +0,0 @@
1
- import { unsafeCSS as f, isServer as x, html as p, nothing as b } from "lit";
2
- import { property as c, state as y } from "lit/decorators.js";
3
- import { classMap as k } from "lit/directives/class-map.js";
4
- import { validPropertyValues as _, safeCustomElement as I, ariaContext as T, parentDisabledContext as C } from "@justeattakeaway/pie-webc-core";
5
- import { P as w } from "./PieElement-CGtUo9tK.js";
6
- /**
7
- * @license
8
- * Copyright 2021 Google LLC
9
- * SPDX-License-Identifier: BSD-3-Clause
10
- */
11
- let g = class extends Event {
12
- constructor(t, e, o, s) {
13
- super("context-request", { bubbles: !0, composed: !0 }), this.context = t, this.contextTarget = e, this.callback = o, this.subscribe = s ?? !1;
14
- }
15
- };
16
- /**
17
- * @license
18
- * Copyright 2021 Google LLC
19
- * SPDX-License-Identifier: BSD-3-Clause
20
- */
21
- let v = class {
22
- constructor(t, e, o, s) {
23
- if (this.subscribe = !1, this.provided = !1, this.value = void 0, this.t = (n, r) => {
24
- this.unsubscribe && (this.unsubscribe !== r && (this.provided = !1, this.unsubscribe()), this.subscribe || this.unsubscribe()), this.value = n, this.host.requestUpdate(), this.provided && !this.subscribe || (this.provided = !0, this.callback && this.callback(n, r)), this.unsubscribe = r;
25
- }, this.host = t, e.context !== void 0) {
26
- const n = e;
27
- this.context = n.context, this.callback = n.callback, this.subscribe = n.subscribe ?? !1;
28
- } else this.context = e, this.callback = o, this.subscribe = s ?? !1;
29
- this.host.addController(this);
30
- }
31
- hostConnected() {
32
- this.dispatchRequest();
33
- }
34
- hostDisconnected() {
35
- this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0);
36
- }
37
- dispatchRequest() {
38
- this.host.dispatchEvent(new g(this.context, this.host, this.t, this.subscribe));
39
- }
40
- };
41
- /**
42
- * @license
43
- * Copyright 2021 Google LLC
44
- * SPDX-License-Identifier: BSD-3-Clause
45
- */
46
- class A {
47
- get value() {
48
- return this.o;
49
- }
50
- set value(t) {
51
- this.setValue(t);
52
- }
53
- setValue(t, e = !1) {
54
- const o = e || !Object.is(t, this.o);
55
- this.o = t, o && this.updateObservers();
56
- }
57
- constructor(t) {
58
- this.subscriptions = /* @__PURE__ */ new Map(), this.updateObservers = () => {
59
- for (const [e, { disposer: o }] of this.subscriptions) e(this.o, o);
60
- }, t !== void 0 && (this.value = t);
61
- }
62
- addCallback(t, e, o) {
63
- if (!o) return void t(this.value);
64
- this.subscriptions.has(t) || this.subscriptions.set(t, { disposer: () => {
65
- this.subscriptions.delete(t);
66
- }, consumerHost: e });
67
- const { disposer: s } = this.subscriptions.get(t);
68
- t(this.value, s);
69
- }
70
- clearCallbacks() {
71
- this.subscriptions.clear();
72
- }
73
- }
74
- /**
75
- * @license
76
- * Copyright 2021 Google LLC
77
- * SPDX-License-Identifier: BSD-3-Clause
78
- */
79
- class L extends Event {
80
- constructor(t, e) {
81
- super("context-provider", { bubbles: !0, composed: !0 }), this.context = t, this.contextTarget = e;
82
- }
83
- }
84
- class P extends A {
85
- constructor(t, e, o) {
86
- var s, n;
87
- super(e.context !== void 0 ? e.initialValue : o), this.onContextRequest = (r) => {
88
- if (r.context !== this.context) return;
89
- const h = r.contextTarget ?? r.composedPath()[0];
90
- h !== this.host && (r.stopPropagation(), this.addCallback(r.callback, h, r.subscribe));
91
- }, this.onProviderRequest = (r) => {
92
- if (r.context !== this.context || (r.contextTarget ?? r.composedPath()[0]) === this.host) return;
93
- const h = /* @__PURE__ */ new Set();
94
- for (const [u, { consumerHost: m }] of this.subscriptions) h.has(u) || (h.add(u), m.dispatchEvent(new g(this.context, m, u, !0)));
95
- r.stopPropagation();
96
- }, this.host = t, e.context !== void 0 ? this.context = e.context : this.context = e, this.attachListeners(), (n = (s = this.host).addController) == null || n.call(s, this);
97
- }
98
- attachListeners() {
99
- this.host.addEventListener("context-request", this.onContextRequest), this.host.addEventListener("context-provider", this.onProviderRequest);
100
- }
101
- hostConnected() {
102
- this.host.dispatchEvent(new L(this.context, this.host));
103
- }
104
- }
105
- /**
106
- * @license
107
- * Copyright 2022 Google LLC
108
- * SPDX-License-Identifier: BSD-3-Clause
109
- */
110
- function R({ context: i, subscribe: t }) {
111
- return (e, o) => {
112
- typeof o == "object" ? o.addInitializer((function() {
113
- new v(this, { context: i, callback: (s) => {
114
- e.set.call(this, s);
115
- }, subscribe: t });
116
- })) : e.constructor.addInitializer(((s) => {
117
- new v(s, { context: i, callback: (n) => {
118
- s[o] = n;
119
- }, subscribe: t });
120
- }));
121
- };
122
- }
123
- const S = ["none", "radio", "checkbox", "switch", "link"], d = {
124
- isCompact: !1,
125
- isBold: !1,
126
- hasMedia: !1,
127
- interactionType: "none",
128
- disabled: !1
129
- }, D = "*,*:after,*:before{box-sizing:inherit}:host{--list-item-inline-padding: var(--dt-spacing-d);--list-item-alignment: flex-start;--list-item-border: none;display:block}.c-listItem-container{--list-item-block-padding: var(--dt-spacing-d);--list-item-block-end-padding: calc(var(--list-item-block-padding) - var(--list-item-size-modifier));padding-inline-start:var(--list-item-inline-padding);padding-inline-end:var(--list-item-inline-padding);padding-block-start:var(--list-item-block-padding);padding-block-end:var(--list-item-block-end-padding, var(--list-item-block-padding));display:flex;align-items:var(--list-item-alignment);gap:var(--dt-spacing-c);min-height:56px;border-bottom:var(--list-item-border)}.c-listItem-container:has(.c-listItem-secondaryText){align-items:var(--list-item-alignment);min-height:76px}.c-listItem-container.is-compact{--list-item-block-padding: var(--dt-spacing-c);--list-item-alignment: center;align-items:var(--list-item-alignment);min-height:48px}.c-listItem-container.is-link{position:relative}.c-listItem-container.is-selectable:not(.is-disabled),.c-listItem-container.is-link{--list-item-hover-bg: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--dt-color-hover-01));--list-item-active-bg: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--dt-color-active-01))}@supports (background-color: color-mix(in srgb,black,white)){.c-listItem-container.is-selectable:not(.is-disabled),.c-listItem-container.is-link{--list-item-hover-bg: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), transparent);--list-item-active-bg: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), transparent)}}.c-listItem-container.is-selectable:not(.is-disabled),.c-listItem-container.is-link{cursor:pointer}.c-listItem-container.is-selectable:not(.is-disabled):hover,.c-listItem-container.is-link:hover{background-color:var(--list-item-hover-bg);--interactive-container-tint: var(--list-item-hover-bg)}.c-listItem-container.is-selectable:not(.is-disabled):active,.c-listItem-container.is-link:active{background-color:var(--list-item-active-bg);--interactive-container-tint: var(--list-item-active-bg)}slot[name=link]::slotted(a){position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;border-radius:inherit}slot[name=link]::slotted(a:focus-visible){box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-listItem-container.has-media:has(.c-listItem-primaryText:only-child){--list-item-block-padding: var(--dt-spacing-b)}.c-listItem-text{flex:1}slot[name=trailing]::slotted(*),.c-listItem-metaText{padding-inline-start:var(--dt-spacing-a)}.c-listItem-leading,slot[name=leading],.c-listItem-trailing,slot[name=trailing]{display:contents}.c-listItem-text>*{display:block}.c-listItem-trailing{margin-inline-start:auto}.c-listItem-metaText{display:block;max-width:33.3333333333%}::slotted(.c-pieIcon){--icon-size-override: 24px }.c-listItem-primaryText{font-family:var(--dt-font-body-l-family);font-weight:var(--dt-font-body-l-weight);font-size:calc(var(--dt-font-body-l-size) * 1px);line-height:calc(var(--dt-font-body-l-line-height) * 1px);color:var(--dt-color-content-default)}.c-listItem-container.is-bold .c-listItem-primaryText{font-family:var(--dt-font-body-strong-l-family);font-weight:var(--dt-font-body-strong-l-weight);font-size:calc(var(--dt-font-body-strong-l-size) * 1px);line-height:calc(var(--dt-font-body-strong-l-line-height) * 1px)}.c-listItem-secondaryText,.c-listItem-metaText{font-family:var(--dt-font-body-s-family);font-weight:var(--dt-font-body-s-weight);font-size:calc(var(--dt-font-body-s-size) * 1px);line-height:calc(var(--dt-font-body-s-line-height) * 1px);color:var(--dt-color-content-subdued)}";
130
- var q = Object.defineProperty, z = Object.getOwnPropertyDescriptor, l = (i, t, e, o) => {
131
- for (var s = o > 1 ? void 0 : o ? z(t, e) : t, n = i.length - 1, r; n >= 0; n--)
132
- (r = i[n]) && (s = (o ? r(t, e, s) : r(s)) || s);
133
- return o && s && q(t, e, s), s;
134
- };
135
- const B = "pie-list-item";
136
- let a = class extends w {
137
- constructor() {
138
- super(...arguments), this.isCompact = d.isCompact, this.isBold = d.isBold, this.hasMedia = d.hasMedia, this.interactionType = d.interactionType, this.disabled = d.disabled, this._parentDisabled = !1, this._ariaProvider = x ? void 0 : new P(this, { context: T }), this._managedRole = null, this._linkAriaCaptured = !1, this._consumerNamedLink = !1, this._consumerDescribedLink = !1, this._handleHostClick = (i) => {
139
- if (!this._isSelectable || this._isDisabled) return;
140
- const t = this._control;
141
- !t || i.composedPath().includes(t) || (t.click(), t.focus());
142
- };
143
- }
144
- // A selection row hosts a slotted control (radio/checkbox/switch) and makes the whole row a
145
- // toggle target. `link` is interactive too, but it is a navigation target rather than a
146
- // selection control, so it is deliberately excluded here.
147
- get _isSelectable() {
148
- return this.interactionType === "radio" || this.interactionType === "checkbox" || this.interactionType === "switch";
149
- }
150
- get _isLinkRow() {
151
- return this.interactionType === "link";
152
- }
153
- // True when the item lends its text to a slotted control as that control's accessible
154
- // name/description: selectable rows (radio/checkbox/switch) and link rows (the slotted anchor).
155
- get _providesAria() {
156
- return this._isSelectable || this._isLinkRow;
157
- }
158
- // radio/checkbox are owned by a selection group, which is why the item becomes `presentation`
159
- // (so the group owns the controls directly) and the radio is named on its host. A switch has
160
- // no group, so the item stays a `listitem`.
161
- get _ownedByGroup() {
162
- return this.interactionType === "radio" || this.interactionType === "checkbox";
163
- }
164
- // True when the row should be treated as disabled: either its own `disabled` prop is set, or the
165
- // containing group is disabled (provided via context). Declarative and reactive, so the styling
166
- // and row-click guard react without observing the slotted control.
167
- get _isDisabled() {
168
- return this.disabled || this._parentDisabled;
169
- }
170
- // The interactive control (radio/checkbox/switch) slotted into this item, if any. Used only by
171
- // the client-side row-click handler.
172
- get _control() {
173
- return this.querySelector("pie-radio, pie-checkbox, pie-switch");
174
- }
175
- connectedCallback() {
176
- super.connectedCallback(), this._abortController = new AbortController(), this.addEventListener("click", this._handleHostClick, { signal: this._abortController.signal });
177
- }
178
- disconnectedCallback() {
179
- super.disconnectedCallback(), this._abortController.abort();
180
- }
181
- updated() {
182
- var i;
183
- this._applyRole(), (i = this._ariaProvider) == null || i.setValue(this._providedAria), this._applyLinkAria();
184
- }
185
- /**
186
- * Sets the item's role from `interactionType`: `presentation` for radio/checkbox (so the group
187
- * owns those controls directly), otherwise `listitem` (static items, switches and links). A role
188
- * set explicitly by the consumer is left untouched, even if it is added or removed dynamically
189
- * after the element connects.
190
- */
191
- _applyRole() {
192
- const i = this.getAttribute("role");
193
- if (i !== null && i !== this._managedRole) return;
194
- const t = this._ownedByGroup ? "presentation" : "listitem";
195
- this._managedRole = t, this.setAttribute("role", t);
196
- }
197
- /**
198
- * The accessible name and description this item provides to its slotted control, stitched from
199
- * its text. Only provided in a selectable list. Each control consumes this via `ariaContext`
200
- * and decides how to apply it: `pie-radio` names its host (which carries `role="radio"`),
201
- * while `pie-checkbox` / `pie-switch` name their internal input (their host is role-less, so
202
- * `aria-label` there would be invalid). Context reaches across the shadow boundary that
203
- * `aria-labelledby` cannot.
204
- */
205
- get _providedAria() {
206
- if (!this._providesAria) return;
207
- const i = [this.secondaryText, this.metaText].filter(Boolean).join(". ");
208
- return { label: this.primaryText, description: i || void 0 };
209
- }
210
- /**
211
- * When the item is a link, names the slotted (empty) anchor from the item's own text: the parent
212
- * owns the child's aria. The anchor is plain light-DOM, so it cannot reference the shadow-DOM text
213
- * via `aria-labelledby`; and it is not a PIE control that consumes `ariaContext`, so we set the
214
- * attributes imperatively. The visible text is `aria-hidden` in the template, so nothing is
215
- * announced twice.
216
- *
217
- * A consumer-provided name/description always wins: we capture (once) whether the anchor already
218
- * carries `aria-label`/`aria-labelledby` or `aria-description`/`aria-describedby` and, if so,
219
- * leave that attribute untouched. Otherwise we keep our generated value in sync with the text.
220
- */
221
- _applyLinkAria() {
222
- if (!this._isLinkRow) {
223
- if (this._linkAriaCaptured) {
224
- const e = this.querySelector('a[slot="link"]');
225
- e && (this._consumerNamedLink || e.removeAttribute("aria-label"), this._consumerDescribedLink || e.removeAttribute("aria-description")), this._linkAriaCaptured = !1, this._consumerNamedLink = !1, this._consumerDescribedLink = !1;
226
- }
227
- return;
228
- }
229
- const i = this.querySelector('a[slot="link"]');
230
- if (!i) return;
231
- this._linkAriaCaptured || (this._consumerNamedLink = i.hasAttribute("aria-label") || i.hasAttribute("aria-labelledby"), this._consumerDescribedLink = i.hasAttribute("aria-description") || i.hasAttribute("aria-describedby"), this._linkAriaCaptured = !0);
232
- const t = this._providedAria;
233
- this._consumerNamedLink || (t != null && t.label ? i.setAttribute("aria-label", t.label) : i.removeAttribute("aria-label")), this._consumerDescribedLink || (t != null && t.description ? i.setAttribute("aria-description", t.description) : i.removeAttribute("aria-description"));
234
- }
235
- _renderSecondaryText() {
236
- const { secondaryText: i } = this;
237
- return i ? p`<span class="c-listItem-secondaryText">${i}</span>` : b;
238
- }
239
- // metaText is another form of trailing content. The component can only ever display either slotted trailing content or the metaText string
240
- _renderTrailingContent() {
241
- const { metaText: i } = this;
242
- return i ? p`<span class="c-listItem-metaText c-listItem-trailing" aria-hidden=${this._providesAria ? "true" : b}>${i}</span>` : p`<div class="c-listItem-trailing"><slot name="trailing"></slot></div>`;
243
- }
244
- render() {
245
- const { primaryText: i } = this, t = {
246
- "c-listItem-container": !0,
247
- "is-compact": this.isCompact,
248
- "is-bold": this.isBold,
249
- "has-media": this.hasMedia,
250
- "is-selectable": this._isSelectable,
251
- "is-link": this._isLinkRow,
252
- "is-disabled": this._isDisabled
253
- };
254
- return p`
255
- <div class=${k(t)}>
256
- ${this._isLinkRow ? p`<slot name="link"></slot>` : b}
257
- <div class="c-listItem-leading">
258
- <slot name="leading"></slot>
259
- </div>
260
-
261
- <div class="c-listItem-text" aria-hidden=${this._providesAria ? "true" : b}>
262
- <span class="c-listItem-primaryText">${i}</span>
263
- ${this._renderSecondaryText()}
264
- </div>
265
-
266
- ${this._renderTrailingContent()}
267
- </div>`;
268
- }
269
- };
270
- a.styles = f(D);
271
- l([
272
- c({ type: String })
273
- ], a.prototype, "primaryText", 2);
274
- l([
275
- c({ type: String })
276
- ], a.prototype, "secondaryText", 2);
277
- l([
278
- c({ type: String })
279
- ], a.prototype, "metaText", 2);
280
- l([
281
- c({ type: Boolean })
282
- ], a.prototype, "isCompact", 2);
283
- l([
284
- c({ type: Boolean })
285
- ], a.prototype, "isBold", 2);
286
- l([
287
- c({ type: Boolean })
288
- ], a.prototype, "hasMedia", 2);
289
- l([
290
- c({ type: String }),
291
- _(B, S, d.interactionType)
292
- ], a.prototype, "interactionType", 2);
293
- l([
294
- c({ type: Boolean })
295
- ], a.prototype, "disabled", 2);
296
- l([
297
- R({ context: C, subscribe: !0 }),
298
- y()
299
- ], a.prototype, "_parentDisabled", 2);
300
- a = l([
301
- I("pie-list-item")
302
- ], a);
303
- export {
304
- a as P,
305
- d,
306
- S as i
307
- };