PageSourceSearch

https://lemonadejs.com/v6/buttongroup.js

js lemonadejs.com collected 2026-09-25 22:11:36 UTC 3,425 bytes, 86 lines download raw bytes

1// components/buttongroup/src/index.ts
2import { component, html } from "lemonadejs";
3var asOption = (raw) => typeof raw === "string" || typeof raw === "number" ? { value: raw, label: String(raw) } : raw;
4var sameValue = (a, b) => {
5  if (a === "" || b === "") {
6    return a === b;
7  }
8  return a == b;
9};
10var asList = (v) => {
11  if (Array.isArray(v)) {
12    return v;
13  }
14  return v === "" || v === null || v === void 0 ? [] : [v];
15};
16var ButtonGroup = component("buttongroup", {
17  bind: null,
18  // selection: single value, array when multiple (any)
19  options: Array,
20  // { value, label, icon, disabled } or strings
21  selectable: "",
22  // '' action buttons | single | multiple
23  variant: "",
24  // '' contained | outlined | text
25  color: "",
26  // green | orange | red | purple
27  size: "",
28  // small | large (default in between)
29  orientation: "",
30  // '' horizontal | vertical
31  disabled: false,
32  // blocks the whole group (native)
33  "aria-label": "",
34  // accessible name for the group
35  onchange: Function,
36  // (selection) on user toggles
37  onclick: Function
38  // (value, event) in plain mode
39}, (props, { bind }) => {
40  const selected = bind(props, "");
41  const isSelected = (value) => !!props.selectable.value && asList(selected.value).some((w) => sameValue(w, value));
42  const press = (item, e) => {
43    if (props.disabled.value || item.disabled === true) {
44      return;
45    }
46    const mode = props.selectable.value;
47    if (!mode) {
48      props.onclick?.(item.value, e);
49    } else if (mode === "multiple") {
50      const current = asList(selected.value);
51      const next = current.some((w) => sameValue(w, item.value)) ? current.filter((w) => !sameValue(w, item.value)) : [...current, item.value];
52      selected.set(next);
53    } else {
54      const current = asList(selected.value);
55      selected.set(current.some((w) => sameValue(w, item.value)) ? null : item.value);
56    }
57  };
58  const hasLabel = (item) => item.label !== void 0 && item.label !== "";
59  const optionName = (item) => item.icon && !hasLabel(item) && String(item.value ?? "") || false;
60  const view = (raw, item) => html`<button type="button"
61        key="${raw}"
62        class="lm-buttongroup-button"
63        data-selected="${() => isSelected(item.value) ? "true" : false}"
64        aria-pressed="${() => props.selectable.value ? String(isSelected(item.value)) : false}"
65        aria-label="${optionName(item)}"
66        disabled="${() => props.disabled.value || item.disabled === true}"
67        onclick="${(e) => press(item, e)}">
68        ${item.icon ? html`<i class="lm-buttongroup-icon material-icons" aria-hidden="true">${item.icon}</i>` : ""}
69        ${hasLabel(item) ? html`<span class="lm-buttongroup-label">${item.label}</span>` : ""}
70    </button>`;
71  return html`<div class="lm-buttongroup" role="group"
72        aria-label="${() => props["aria-label"].value || false}"
73        data-selectable="${() => props.selectable.value || false}"
74        data-variant="${() => props.variant.value || false}"
75        data-color="${() => props.color.value || false}"
76        data-size="${() => props.size.value || false}"
77        data-orientation="${() => props.orientation.value || false}"
78        data-disabled="${() => props.disabled.value ? "true" : false}">
79        ${() => (props.options.value || []).map((raw) => view(raw, asOption(raw)))}
80    </div>`;
81});
82var index_default = ButtonGroup;
83export {
84  ButtonGroup,
85  index_default as default
86};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.