@justeattakeaway/pie-list 0.2.0 → 0.4.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.
- package/README.md +157 -20
- package/custom-elements.json +72 -12
- package/dist/{PieElement-B3g_8vKy.js → PieElement-CGtUo9tK.js} +1 -1
- package/dist/index-BMp2PPeH.js +307 -0
- package/dist/index.js +1 -1
- package/dist/pie-list-item/defs.d.ts +12 -9
- package/dist/pie-list-item/defs.d.ts.map +1 -1
- package/dist/pie-list-item/index.d.ts +24 -5
- package/dist/pie-list-item/index.d.ts.map +1 -1
- package/dist/pie-list-item/index.js +2 -2
- package/dist/pie-list-item/react.js +8 -8
- package/package.json +3 -3
- package/src/pie-list-item/defs.ts +14 -10
- package/src/pie-list-item/index.ts +107 -18
- package/src/pie-list-item/list-item.scss +31 -1
- package/dist/index-KnN5fPmj.js +0 -265
|
@@ -0,0 +1,307 @@
|
|
|
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
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html as n, unsafeCSS as m } from "lit";
|
|
2
|
-
import { P as f } from "./PieElement-
|
|
2
|
+
import { P as f } from "./PieElement-CGtUo9tK.js";
|
|
3
3
|
import { RtlMixin as d, safeCustomElement as p } from "@justeattakeaway/pie-webc-core";
|
|
4
4
|
const c = "*,*:after,*:before{box-sizing:inherit}:host{display:block}:host ::slotted(pie-list-item:not(:last-of-type)){--list-item-size-modifier: 1px;--list-item-border: var(--list-item-size-modifier) solid var(--dt-color-divider-default)}";
|
|
5
5
|
var b = Object.getOwnPropertyDescriptor, u = (s, r, a, l) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
|
-
export declare const
|
|
3
|
-
export type
|
|
2
|
+
export declare const interactionTypes: readonly ["none", "radio", "checkbox", "switch", "link"];
|
|
3
|
+
export type InteractionType = typeof interactionTypes[number];
|
|
4
4
|
export interface ListItemProps {
|
|
5
5
|
/**
|
|
6
6
|
* **Required:** Provides an overview of the content.
|
|
@@ -31,20 +31,23 @@ export interface ListItemProps {
|
|
|
31
31
|
*/
|
|
32
32
|
hasMedia?: boolean;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* How the whole row behaves. A single prop drives the row's role, its accessible naming, whether
|
|
35
|
+
* it forwards clicks, and its interactive (hover/active) states. The item always generates the
|
|
36
|
+
* accessible name and description of whatever it hosts from its own text (`primaryText`,
|
|
37
|
+
* `secondaryText`, `metaText`), so you never set ARIA on the item or its slotted content yourself.
|
|
38
38
|
*
|
|
39
39
|
* - `none` (default) - a static, non-selectable list item (`role="listitem"`).
|
|
40
40
|
* - `radio` - hosts a `pie-radio` (used inside a `pie-radio-group`); the item is `presentation`.
|
|
41
41
|
* - `checkbox` - hosts a `pie-checkbox` (used inside a `pie-checkbox-group`); the item is `presentation`.
|
|
42
42
|
* - `switch` - hosts a `pie-switch`; there is no group, so the item stays `role="listitem"`.
|
|
43
|
+
* - `link` - the whole row is a single navigation link. Slot an empty `<a slot="link" href="...">`;
|
|
44
|
+
* it is stretched over the entire row as the clickable target and named from the item's text.
|
|
43
45
|
*
|
|
44
|
-
* Set this on each
|
|
45
|
-
* them out as a divided list automatically; this prop
|
|
46
|
+
* Set this on each interactive row. When radio/checkbox rows sit inside a `pie-radio-group` /
|
|
47
|
+
* `pie-checkbox-group`, the group lays them out as a divided list automatically; this prop
|
|
48
|
+
* governs the row's own role and behaviour.
|
|
46
49
|
*/
|
|
47
|
-
|
|
50
|
+
interactionType?: typeof interactionTypes[number];
|
|
48
51
|
/**
|
|
49
52
|
* Marks the row as disabled: it takes on the disabled styling and stops forwarding row clicks to
|
|
50
53
|
* its control. Set it alongside the slotted control's own `disabled` (the control still governs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../src/pie-list-item/defs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../src/pie-list-item/defs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAG5E,eAAO,MAAM,gBAAgB,0DAA2D,CAAC;AAEzF,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CAAC,EAAE,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,qBAAqB,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC;AAEzI,eAAO,MAAM,YAAY,EAAE,YAM1B,CAAC"}
|
|
@@ -6,6 +6,7 @@ declare const componentSelector = "pie-list-item";
|
|
|
6
6
|
* @tagname pie-list-item
|
|
7
7
|
* @slot leading - Content shown at the start of the item (for example an icon, avatar, or a slotted radio/checkbox).
|
|
8
8
|
* @slot trailing - Content shown at the end of the item. Mutually exclusive with `metaText`.
|
|
9
|
+
* @slot link - Rendered only when `interactionType="link"`. Slot one empty anchor (e.g. `<a slot="link" href="/x">`) stretched over the whole row as the link target. Must contain no text.
|
|
9
10
|
*/
|
|
10
11
|
export declare class PieListItem extends PieElement implements ListItemProps {
|
|
11
12
|
primaryText: ListItemProps['primaryText'];
|
|
@@ -14,13 +15,18 @@ export declare class PieListItem extends PieElement implements ListItemProps {
|
|
|
14
15
|
isCompact: boolean;
|
|
15
16
|
isBold: boolean;
|
|
16
17
|
hasMedia: boolean;
|
|
17
|
-
|
|
18
|
+
interactionType: "checkbox" | "link" | "none" | "radio" | "switch";
|
|
18
19
|
disabled: boolean;
|
|
19
20
|
private _parentDisabled;
|
|
20
21
|
private _ariaProvider;
|
|
21
22
|
private _abortController;
|
|
22
|
-
private
|
|
23
|
+
private _managedRole;
|
|
24
|
+
private _linkAriaCaptured;
|
|
25
|
+
private _consumerNamedLink;
|
|
26
|
+
private _consumerDescribedLink;
|
|
23
27
|
private get _isSelectable();
|
|
28
|
+
private get _isLinkRow();
|
|
29
|
+
private get _providesAria();
|
|
24
30
|
private get _ownedByGroup();
|
|
25
31
|
private get _isDisabled();
|
|
26
32
|
private get _control();
|
|
@@ -28,9 +34,10 @@ export declare class PieListItem extends PieElement implements ListItemProps {
|
|
|
28
34
|
disconnectedCallback(): void;
|
|
29
35
|
protected updated(): void;
|
|
30
36
|
/**
|
|
31
|
-
* Sets the item's role from `
|
|
32
|
-
* owns those controls directly), otherwise `listitem` (static items and
|
|
33
|
-
* explicitly by the consumer is left untouched
|
|
37
|
+
* Sets the item's role from `interactionType`: `presentation` for radio/checkbox (so the group
|
|
38
|
+
* owns those controls directly), otherwise `listitem` (static items, switches and links). A role
|
|
39
|
+
* set explicitly by the consumer is left untouched, even if it is added or removed dynamically
|
|
40
|
+
* after the element connects.
|
|
34
41
|
*/
|
|
35
42
|
private _applyRole;
|
|
36
43
|
/**
|
|
@@ -47,6 +54,18 @@ export declare class PieListItem extends PieElement implements ListItemProps {
|
|
|
47
54
|
* target. Skips clicks that already landed on the control, to avoid a double toggle.
|
|
48
55
|
*/
|
|
49
56
|
private _handleHostClick;
|
|
57
|
+
/**
|
|
58
|
+
* When the item is a link, names the slotted (empty) anchor from the item's own text: the parent
|
|
59
|
+
* owns the child's aria. The anchor is plain light-DOM, so it cannot reference the shadow-DOM text
|
|
60
|
+
* via `aria-labelledby`; and it is not a PIE control that consumes `ariaContext`, so we set the
|
|
61
|
+
* attributes imperatively. The visible text is `aria-hidden` in the template, so nothing is
|
|
62
|
+
* announced twice.
|
|
63
|
+
*
|
|
64
|
+
* A consumer-provided name/description always wins: we capture (once) whether the anchor already
|
|
65
|
+
* carries `aria-label`/`aria-labelledby` or `aria-description`/`aria-describedby` and, if so,
|
|
66
|
+
* leave that attribute untouched. Otherwise we keep our generated value in sync with the text.
|
|
67
|
+
*/
|
|
68
|
+
private _applyLinkAria;
|
|
50
69
|
_renderSecondaryText(): import('lit-html').TemplateResult<1> | typeof nothing;
|
|
51
70
|
_renderTrailingContent(): import('lit-html').TemplateResult<1>;
|
|
52
71
|
render(): import('lit-html').TemplateResult<1>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pie-list-item/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACa,OAAO,EAC1B,MAAM,KAAK,CAAC;AAWb,OAAO,EAAE,UAAU,EAAE,MAAM,yDAAyD,CAAC;AACrF,OAAO,EAAE,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pie-list-item/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACa,OAAO,EAC1B,MAAM,KAAK,CAAC;AAWb,OAAO,EAAE,UAAU,EAAE,MAAM,yDAAyD,CAAC;AACrF,OAAO,EAAE,KAAK,aAAa,EAAkC,MAAM,QAAQ,CAAC;AAG5E,QAAA,MAAM,iBAAiB,kBAAkB,CAAC;AAE1C;;;;;GAKG;AACH,qBACa,WAAY,SAAQ,UAAW,YAAW,aAAa;IAE5D,WAAW,EAAG,aAAa,CAAC,aAAa,CAAC,CAAC;IAG3C,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAG9C,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAGpC,SAAS,UAA0B;IAGnC,MAAM,UAAuB;IAG7B,QAAQ,UAAyB;IAIjC,eAAe,oDAAgC;IAG/C,QAAQ,UAAyB;IAMrC,OAAO,CAAC,eAAe,CAAS;IAYhC,OAAO,CAAC,aAAa,CAA8E;IAEnG,OAAO,CAAC,gBAAgB,CAAmB;IAI3C,OAAO,CAAC,YAAY,CAAuB;IAI3C,OAAO,CAAC,iBAAiB,CAAS;IAElC,OAAO,CAAC,kBAAkB,CAAS;IAEnC,OAAO,CAAC,sBAAsB,CAAS;IAKvC,OAAO,KAAK,aAAa,GAIxB;IAED,OAAO,KAAK,UAAU,GAErB;IAID,OAAO,KAAK,aAAa,GAExB;IAKD,OAAO,KAAK,aAAa,GAExB;IAKD,OAAO,KAAK,WAAW,GAEtB;IAID,OAAO,KAAK,QAAQ,GAEnB;IAED,iBAAiB;IAOjB,oBAAoB;IAKpB,SAAS,CAAC,OAAO;IAMjB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAUlB;;;;;;;OAOG;IACH,OAAO,KAAK,aAAa,GAMxB;IAED;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAQtB;IAEF;;;;;;;;;;OAUG;IACH,OAAO,CAAC,cAAc;IA8CtB,oBAAoB;IAUpB,sBAAsB;IAStB,MAAM;IA8BN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;KACpC;CACJ"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "lit";
|
|
2
2
|
import "lit/decorators.js";
|
|
3
3
|
import "lit/directives/class-map.js";
|
|
4
|
-
import { P as s } from "../index-
|
|
4
|
+
import { P as s } from "../index-BMp2PPeH.js";
|
|
5
5
|
import "@justeattakeaway/pie-webc-core";
|
|
6
|
-
import "../PieElement-
|
|
6
|
+
import "../PieElement-CGtUo9tK.js";
|
|
7
7
|
export {
|
|
8
8
|
s as PieListItem
|
|
9
9
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as e from "react";
|
|
2
2
|
import { createComponent as t } from "@lit/react";
|
|
3
|
-
import { P as
|
|
4
|
-
import { d as
|
|
5
|
-
const
|
|
3
|
+
import { P as i } from "../index-BMp2PPeH.js";
|
|
4
|
+
import { d as n, i as c } from "../index-BMp2PPeH.js";
|
|
5
|
+
const s = t({
|
|
6
6
|
displayName: "PieListItem",
|
|
7
|
-
elementClass:
|
|
7
|
+
elementClass: i,
|
|
8
8
|
react: e,
|
|
9
9
|
tagName: "pie-list-item",
|
|
10
10
|
events: {}
|
|
11
|
-
}),
|
|
11
|
+
}), o = s;
|
|
12
12
|
export {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
o as PieListItem,
|
|
14
|
+
n as defaultProps,
|
|
15
|
+
c as interactionTypes
|
|
16
16
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justeattakeaway/pie-list",
|
|
3
3
|
"description": "PIE Design System List built using Web Components",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"license": "Apache-2.0",
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@justeattakeaway/pie-components-config": "0.21.3",
|
|
41
|
-
"@justeattakeaway/pie-css": "1.3.
|
|
42
|
-
"@justeattakeaway/pie-monorepo-utils": "0.9.
|
|
41
|
+
"@justeattakeaway/pie-css": "1.3.2",
|
|
42
|
+
"@justeattakeaway/pie-monorepo-utils": "0.9.8"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@justeattakeaway/pie-webc-core": "16.1.0",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// `button` is reserved for future work and is intentionally not yet an accepted value.
|
|
4
|
+
export const interactionTypes = ['none', 'radio', 'checkbox', 'switch', 'link'] as const;
|
|
4
5
|
|
|
5
|
-
export type
|
|
6
|
+
export type InteractionType = typeof interactionTypes[number];
|
|
6
7
|
|
|
7
8
|
export interface ListItemProps {
|
|
8
9
|
/**
|
|
@@ -38,20 +39,23 @@ export interface ListItemProps {
|
|
|
38
39
|
hasMedia?: boolean
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* How the whole row behaves. A single prop drives the row's role, its accessible naming, whether
|
|
43
|
+
* it forwards clicks, and its interactive (hover/active) states. The item always generates the
|
|
44
|
+
* accessible name and description of whatever it hosts from its own text (`primaryText`,
|
|
45
|
+
* `secondaryText`, `metaText`), so you never set ARIA on the item or its slotted content yourself.
|
|
45
46
|
*
|
|
46
47
|
* - `none` (default) - a static, non-selectable list item (`role="listitem"`).
|
|
47
48
|
* - `radio` - hosts a `pie-radio` (used inside a `pie-radio-group`); the item is `presentation`.
|
|
48
49
|
* - `checkbox` - hosts a `pie-checkbox` (used inside a `pie-checkbox-group`); the item is `presentation`.
|
|
49
50
|
* - `switch` - hosts a `pie-switch`; there is no group, so the item stays `role="listitem"`.
|
|
51
|
+
* - `link` - the whole row is a single navigation link. Slot an empty `<a slot="link" href="...">`;
|
|
52
|
+
* it is stretched over the entire row as the clickable target and named from the item's text.
|
|
50
53
|
*
|
|
51
|
-
* Set this on each
|
|
52
|
-
* them out as a divided list automatically; this prop
|
|
54
|
+
* Set this on each interactive row. When radio/checkbox rows sit inside a `pie-radio-group` /
|
|
55
|
+
* `pie-checkbox-group`, the group lays them out as a divided list automatically; this prop
|
|
56
|
+
* governs the row's own role and behaviour.
|
|
53
57
|
*/
|
|
54
|
-
|
|
58
|
+
interactionType?: typeof interactionTypes[number]
|
|
55
59
|
|
|
56
60
|
/**
|
|
57
61
|
* Marks the row as disabled: it takes on the disabled styling and stops forwarding row clicks to
|
|
@@ -68,6 +72,6 @@ export const defaultProps: DefaultProps = {
|
|
|
68
72
|
isCompact: false,
|
|
69
73
|
isBold: false,
|
|
70
74
|
hasMedia: false,
|
|
71
|
-
|
|
75
|
+
interactionType: 'none',
|
|
72
76
|
disabled: false,
|
|
73
77
|
};
|